/** * Variables tab section for compositions OTHER than the active one. A variable * promoted into a sub-comp lives in that frame's file, not the active session — * this surfaces every such file's declarations grouped by path, with per-file * management (edit declaration / remove). Live-preview override for these is a * follow-up (values are per-composition-scope), so no preview control is shown. */ import { useCallback, useState, type MutableRefObject } from "react"; import type { Composition, CompositionVariable } from "@hyperframes/sdk"; import { useEditVariablesInFile, useProjectCompositionVariables, type CompositionVariableGroup, type RecordEditFn, } from "../../hooks/useProjectCompositionVariables"; import { DeclarationForm, draftFromDeclaration, mergeDeclarationEdit, } from "./VariablesDeclarationForm"; import { RowAction } from "./VariablesRowAction"; function CompositionSection({ group, editingKey, onToggleEdit, onSave, onRemove, }: { group: CompositionVariableGroup; editingKey: string | null; onToggleEdit: (key: string | null) => void; onSave: (path: string, decl: CompositionVariable) => void; onRemove: (path: string, id: string) => void; }) { return (

{group.path}

{group.variables.map((decl) => { const key = `${group.path}::${decl.id}`; const editing = editingKey === key; return (
{decl.label} {decl.type} onToggleEdit(editing ? null : key)} /> onRemove(group.path, decl.id)} />
{decl.description &&

{decl.description}

} {editing && ( onSave(group.path, mergeDeclarationEdit(decl, edited))} onCancel={() => onToggleEdit(null)} /> )}
); })}
); } export function VariablesOtherCompositions({ fileTree, excludePath, refreshKey, readProjectFile, writeProjectFile, recordEdit, reloadPreview, domEditSaveTimestampRef, }: { fileTree: string[]; excludePath: string; refreshKey: unknown; readProjectFile: (path: string) => Promise; writeProjectFile: (path: string, content: string) => Promise; recordEdit: RecordEditFn; reloadPreview: () => void; domEditSaveTimestampRef: MutableRefObject; }) { const [selfRefresh, setSelfRefresh] = useState(0); const groups = useProjectCompositionVariables( fileTree, excludePath, readProjectFile, `${refreshKey}:${selfRefresh}`, ); const editInFile = useEditVariablesInFile({ readProjectFile, writeProjectFile, recordEdit, reloadPreview, domEditSaveTimestampRef, }); const [editingKey, setEditingKey] = useState(null); const onSave = useCallback( (path: string, decl: CompositionVariable) => { setEditingKey(null); void editInFile(path, `Update variable "${decl.id}"`, (s: Composition) => s.updateVariableDeclaration(decl.id, decl), ).then(() => setSelfRefresh((r) => r + 1)); }, [editInFile], ); const onRemove = useCallback( (path: string, id: string) => { void editInFile(path, `Remove variable "${id}"`, (s: Composition) => s.removeVariableDeclaration(id), ).then(() => setSelfRefresh((r) => r + 1)); }, [editInFile], ); if (groups.length === 0) return null; return (

Other compositions

{groups.map((group) => ( ))}
); }