/** * Art-historical movement lineage (predecessor β†’ successor). * Defaults match museum essays; live data comes from GET /api/movement-links. * Multiple parents are allowed (e.g. Post-Impressionism feeding several modern paths). */ export type MovementLineageEdge = readonly [parent: string, child: string]; export const FALLBACK_MOVEMENT_LINEAGE: ReadonlyArray = [ // Classical & medieval ['Ancient Greek & Roman', 'Byzantine'], ['Byzantine', 'Gothic'], // Renaissance chain ['Gothic', 'Early Renaissance'], ['Early Renaissance', 'High Renaissance'], ['Northern Renaissance', 'Early Renaissance'], ['High Renaissance', 'Mannerism'], ['Mannerism', 'Baroque'], // 17th–19th century ['Baroque', 'Rococo'], ['Rococo', 'Neoclassicism'], ['Neoclassicism', 'Romanticism'], ['Romanticism', 'Realism'], ['Romanticism', 'Impressionism'], ['Realism', 'Impressionism'], // Modern origins ['Impressionism', 'Post-Impressionism'], ['Post-Impressionism', 'Symbolism'], ['Post-Impressionism', 'Fauvism'], ['Post-Impressionism', 'Expressionism'], ['Post-Impressionism', 'Cubism'], ['Symbolism', 'Art Nouveau'], ['Fauvism', 'Cubism'], ['Cubism', 'Futurism'], ['Cubism', 'Suprematism'], ['Cubism', 'Constructivism'], ['Expressionism', 'Abstract Expressionism'], // Avant-garde 20th century ['Dada', 'Surrealism'], ['Surrealism', 'Abstract Expressionism'], ['Abstract Expressionism', 'Pop Art'], ]; let activeLineage: ReadonlyArray = FALLBACK_MOVEMENT_LINEAGE; /** Active edges for timeline / tree layout (API-backed when loaded). */ export function getMovementLineage(): ReadonlyArray { return activeLineage; } /** Apply curator DB rows; empty list keeps the static fallback. */ export function setMovementLineageFromApi( items: ReadonlyArray<{ source_name: string; target_name: string }> ): void { if (!items.length) { activeLineage = FALLBACK_MOVEMENT_LINEAGE; return; } activeLineage = items.map((row) => [row.source_name, row.target_name] as const); } /** @deprecated Use getMovementLineage() β€” alias for older imports. */ export const MOVEMENT_LINEAGE = FALLBACK_MOVEMENT_LINEAGE; export function lineageParentsByName(childName: string): string[] { return getMovementLineage() .filter(([, child]) => child === childName) .map(([parent]) => parent); } export function lineageChildrenByName(parentName: string): string[] { return getMovementLineage() .filter(([parent]) => parent === parentName) .map(([, child]) => child); }