@hyperframes/studio 0.8.145 → 0.8.146
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{hyperframes-player-DZ5JrMDg.js → hyperframes-player-tkxyWf5H.js} +3 -3
- package/dist/assets/{index-BqFRhNZa.js → index-BrdqOkqP.js} +1 -1
- package/dist/assets/{index-D8W0a0Z9.js → index-Cg48BxAo.js} +135 -135
- package/dist/assets/{index-BOs6C0aZ.js → index-Dllxg4aU.js} +1 -1
- package/dist/{chunk-EEXSYY5F.js → chunk-C5BDT7NG.js} +0 -1
- package/dist/{chunk-TP6D3U37.js → chunk-HZDCMUG4.js} +1 -2
- package/dist/{chunk-PZ5AY32C.js → chunk-MLKGABMK.js} +0 -1
- package/dist/{chunk-NZPJUZKT.js → chunk-PHGBG7OG.js} +3 -4
- package/dist/{chunk-Y2OHHNM2.js → chunk-PVFBY7KR.js} +0 -1
- package/dist/{chunk-6JY3MTIX.js → chunk-T43DM7Q6.js} +2 -3
- package/dist/{domEditingLayers-PTP2ICGM.js → domEditingLayers-SMVA3FEW.js} +3 -4
- package/dist/index.css +0 -1
- package/dist/index.html +1 -1
- package/dist/index.js +106 -107
- package/dist/player.js +4 -5
- package/dist/styles/tailwind-preset.js +1 -2
- package/dist/ui.js +3 -4
- package/package.json +8 -8
- package/src/captions/components/CaptionOverlay.tsx +1 -1
- package/src/captions/hooks/useCaptionSync.ts +1 -1
- package/src/components/LinkedSelectionToggle.tsx +2 -2
- package/src/components/LintModal.tsx +1 -5
- package/src/components/MediaPreview.tsx +2 -2
- package/src/components/ProjectUnreachableBanner.tsx +1 -1
- package/src/components/StudioRightPanels.tsx +1 -1
- package/src/components/TimelineToolbar.test.tsx +2 -2
- package/src/components/TimelineToolbar.tsx +6 -6
- package/src/components/editor/AnimationCard.tsx +3 -3
- package/src/components/editor/AnimationCardParts.tsx +1 -1
- package/src/components/editor/BlockParamsPanel.tsx +3 -3
- package/src/components/editor/ComputedTweenNotice.tsx +2 -2
- package/src/components/editor/FileTree.tsx +1 -1
- package/src/components/editor/GsapAnimationList.tsx +1 -1
- package/src/components/editor/GsapAnimationSection.tsx +2 -2
- package/src/components/editor/OffCanvasIndicators.tsx +1 -1
- package/src/components/editor/PromotableControl.tsx +1 -1
- package/src/components/editor/PropertyPanel.tsx +2 -2
- package/src/components/editor/SnapToolbar.tsx +2 -2
- package/src/components/editor/Transform3DCube.tsx +1 -1
- package/src/components/editor/gsapAnimationConstants.ts +2 -2
- package/src/components/editor/gsapAnimationHelpers.test.ts +1 -1
- package/src/components/editor/gsapAnimationHelpers.ts +1 -1
- package/src/components/editor/propertyPanelColorGradingControls.tsx +1 -1
- package/src/components/editor/propertyPanelFill.tsx +1 -1
- package/src/components/editor/propertyPanelFlatMotionSection.tsx +3 -3
- package/src/components/editor/propertyPanelFlatPrimitives.tsx +2 -2
- package/src/components/editor/propertyPanelFlatSelectRow.tsx +1 -1
- package/src/components/editor/propertyPanelFlatTextSection.tsx +1 -1
- package/src/components/editor/propertyPanelFont.tsx +3 -3
- package/src/components/editor/propertyPanelFxBandRuler.tsx +2 -2
- package/src/components/editor/propertyPanelFxNodeOpenBody.tsx +2 -2
- package/src/components/editor/propertyPanelTimingSection.tsx +1 -1
- package/src/components/editor/propertyPanelTransformCommit.ts +3 -3
- package/src/components/editor/useColorGradingController.ts +1 -1
- package/src/components/panels/SlideshowSubPanels.tsx +2 -2
- package/src/components/panels/VariablesBindElement.tsx +1 -1
- package/src/components/panels/VariablesPanel.tsx +3 -3
- package/src/components/renders/RenderQueue.tsx +2 -2
- package/src/components/renders/useRenderQueue.ts +3 -3
- package/src/components/sidebar/AssetCard.tsx +2 -2
- package/src/components/sidebar/AudioRow.tsx +1 -1
- package/src/components/sidebar/BlocksTab.tsx +2 -2
- package/src/components/sidebar/CompositionsTab.tsx +2 -2
- package/src/components/sidebar/PromptPreviewModal.tsx +1 -1
- package/src/hooks/timelineAudioGroupCreate.ts +1 -1
- package/src/hooks/timelineEditingHelpers.ts +1 -1
- package/src/hooks/useBlockHandlers.ts +1 -1
- package/src/hooks/useDomEditSession.ts +1 -1
- package/src/hooks/useEditorSave.ts +1 -1
- package/src/hooks/useFrameCapture.ts +1 -1
- package/src/hooks/useGestureCommit.ts +4 -4
- package/src/hooks/useGsapScriptCommits.ts +1 -1
- package/src/player/components/AudioGainDialog.test.tsx +1 -1
- package/src/player/components/AudioGainDialog.tsx +2 -1
- package/src/player/components/EditModal.tsx +2 -2
- package/src/player/components/KeyframeDiamondContextMenu.tsx +1 -1
- package/src/player/components/OutOfSyncBadge.tsx +1 -1
- package/src/player/components/Player.tsx +1 -1
- package/src/player/components/ShortcutsPanel.tsx +2 -2
- package/src/player/components/Timeline.virtualization.test.tsx +1 -1
- package/src/player/components/TimelineAutomationLaneSlot.tsx +1 -1
- package/src/player/components/TimelineClip.tsx +1 -1
- package/src/player/components/TimelineFxButton.tsx +2 -2
- package/src/player/components/TimelineTrackHeader.test.tsx +3 -3
- package/src/player/components/timelineClipDragCommit.ts +2 -2
- package/src/player/components/trackHeaderLabelRows.tsx +1 -1
- package/src/player/lib/playbackAdapter.ts +1 -1
- package/src/utils/hmrStableContext.ts +1 -1
- package/src/utils/razorSplitTransaction.ts +0 -2
- package/src/utils/sdkCutover.linkedTiming.test.ts +1 -1
- package/dist/chunk-6JY3MTIX.js.map +0 -1
- package/dist/chunk-EEXSYY5F.js.map +0 -1
- package/dist/chunk-NZPJUZKT.js.map +0 -1
- package/dist/chunk-PZ5AY32C.js.map +0 -1
- package/dist/chunk-TP6D3U37.js.map +0 -1
- package/dist/chunk-Y2OHHNM2.js.map +0 -1
- package/dist/domEditingLayers-PTP2ICGM.js.map +0 -1
- package/dist/index.css.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/player.js.map +0 -1
- package/dist/styles/tailwind-preset.js.map +0 -1
- package/dist/ui.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/sourceScopedSelectorIndex.ts","../src/components/editor/domEditingDom.ts","../src/components/editor/domEditingTypes.ts","../src/player/lib/timelineText.ts","../src/utils/rounding.ts","../src/components/editor/colorValue.ts","../src/player/lib/playbackAdapter.ts","../src/player/lib/timelineElementHelpers.ts","../src/player/lib/storedVolume.ts","../src/utils/projectRouting.ts","../src/components/editor/manualEditingAvailability.ts","../src/utils/sdkCutoverPolicy.ts","../src/utils/studioApiFetch.ts"],"sourcesContent":["/**\n * Occurrence index for a selector within its source document.\n *\n * The preview flattens multiple composition files into one DOM, so a raw\n * `querySelectorAll` index is not a stable source-file identity. Callers supply\n * their existing source resolver; this helper alone owns occurrence scoping.\n */\n\n/** Every element matching one selector, mapped to the source file it belongs to\n * and its occurrence index within that file. One document query fills it. */\ntype SelectorOccurrences = Map<Element, { scope: string; index: number }>;\n\ninterface SelectorIndexPass {\n doc: Document;\n bySelector: Map<string, SelectorOccurrences>;\n}\n\nlet activePass: SelectorIndexPass | null = null;\n\n/**\n * Share one occurrence index per selector across every\n * `getSourceScopedSelectorIndex` call made synchronously inside `run`.\n *\n * Unshared, each call runs its own whole-document `querySelectorAll(selector)`\n * and resolves the source file of every match. A rebuild that walks n elements\n * sharing a selector therefore does n whole-document queries and n² resolver\n * calls — a composition of repeated cards or tiles is exactly that shape. One\n * index per selector makes the same pass linear.\n *\n * Correctness rests on the pass being ONE synchronous walk of a document that\n * does not change under it: nothing invalidates the index, so `run` must not\n * mutate `doc`, and every call inside it must resolve source files the same way\n * (the resolver may be a fresh closure per call, as long as it answers the\n * same). Outside a pass the index is per-call, exactly as before.\n */\nexport function withSelectorIndexPass<T>(doc: Document, run: () => T): T {\n const previous = activePass;\n activePass = { doc, bySelector: new Map() };\n try {\n return run();\n } finally {\n activePass = previous;\n }\n}\n\nfunction buildOccurrences(\n doc: Document,\n selector: string,\n resolveSourceFile: (candidate: Element) => string | undefined,\n): SelectorOccurrences {\n const occurrences: SelectorOccurrences = new Map();\n const counts = new Map<string, number>();\n for (const candidate of doc.querySelectorAll(selector)) {\n const scope = resolveSourceFile(candidate) ?? \"index.html\";\n const index = counts.get(scope) ?? 0;\n counts.set(scope, index + 1);\n occurrences.set(candidate, { scope, index });\n }\n return occurrences;\n}\n\nexport function getSourceScopedSelectorIndex(\n doc: Document,\n el: Element,\n selector: string | undefined,\n sourceFile: string | undefined,\n resolveSourceFile: (candidate: Element) => string | undefined,\n): number | undefined {\n if (!selector || selector.startsWith(\"#\") || selector.startsWith(\"[data-composition-id=\")) {\n return undefined;\n }\n\n try {\n const pass = activePass?.doc === doc ? activePass : null;\n let occurrences = pass?.bySelector.get(selector);\n if (!occurrences) {\n occurrences = buildOccurrences(doc, selector, resolveSourceFile);\n pass?.bySelector.set(selector, occurrences);\n }\n // An element outside the requested scope is not in that scope's occurrence\n // run at all, which is the `indexOf` miss the filtered form returned before.\n const hit = occurrences.get(el);\n return hit && hit.scope === (sourceFile ?? \"index.html\") ? hit.index : undefined;\n } catch {\n return undefined;\n }\n}\n","/**\n * Low-level DOM primitives: type guards, style getters, CSS escaping,\n * selector utilities, and composition source resolution.\n * No imports from other domEditing* modules — safe to import from anywhere.\n */\nimport { COLOR_GRADING_SOURCE_HIDDEN_ATTR } from \"@hyperframes/core/color-grading\";\nimport { getSourceScopedSelectorIndex } from \"../../utils/sourceScopedSelectorIndex\";\nimport { CURATED_STYLE_PROPERTIES } from \"./domEditingTypes\";\n\n// ─── Type guard ───────────────────────────────────────────────────────────────\n\nexport function isHtmlElement(value: unknown): value is HTMLElement {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"nodeType\" in value &&\n typeof (value as { nodeType?: unknown }).nodeType === \"number\" &&\n (value as { nodeType: number }).nodeType === 1\n );\n}\n\n// ─── Style parsing ────────────────────────────────────────────────────────────\n\n// Single source of truth lives in @hyperframes/core/editing so the studio\n// callers and the core resolver can't drift. Re-exported here to keep this\n// module's public surface (6 studio callers import parsePx from it).\nexport { parsePx } from \"@hyperframes/core/editing\";\n\nexport function isTextBearingTag(tagName: string): boolean {\n return [\"div\", \"span\", \"p\", \"strong\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"].includes(tagName);\n}\n\nexport function isEditableTextLeaf(el: HTMLElement): boolean {\n return isTextBearingTag(el.tagName.toLowerCase()) && el.children.length === 0;\n}\n\n/** Does this node render AT ALL, ignoring what it inherits? Sole owner of the\n * rule; the walk below only decides which nodes to ask it about. */\nfunction elementRendersItself(win: Window, el: HTMLElement): boolean {\n const computed = win.getComputedStyle(el);\n if (computed.display === \"none\" || computed.visibility === \"hidden\") return false;\n const opacity = Number.parseFloat(computed.opacity);\n return !(\n Number.isFinite(opacity) &&\n opacity <= 0.01 &&\n !el.hasAttribute(COLOR_GRADING_SOURCE_HIDDEN_ATTR)\n );\n}\n\n/**\n * Does `el` render, given everything above it?\n *\n * `memo` is for a caller asking this about MANY elements in one synchronous\n * pass. Answers are a function of the node and its ancestors, and siblings\n * share almost all of their chain, so memoizing per node turns a walk per\n * element into one style read per node in the tree. It is only ever valid for\n * the length of one pass — the DOM cannot change under a pass, and every read\n * here is a read — so the caller creates it and drops it, and nothing survives\n * to be invalidated. Omitted, every call walks the chain itself.\n *\n * The ANSWER is what it always was. Which nodes get a style read is not: this\n * resolves top-down and stops at the first node that is out, where the previous\n * version resolved bottom-up and stopped at the first one that is out going the\n * other way. Same boolean for every input, a different (and, for a subtree\n * hidden near the root, smaller) set of reads.\n */\nexport function isElementVisibleThroughAncestors(\n el: HTMLElement,\n memo?: Map<HTMLElement, boolean>,\n): boolean {\n const win = el.ownerDocument.defaultView;\n if (!win) return true;\n // Up to the first node already answered for, then back down: a node's answer\n // needs its ancestors' first, and the topmost unanswered node is where the\n // chain of unknowns starts.\n const pending: HTMLElement[] = [];\n let inherited = true;\n for (let node: HTMLElement | null = el; node; node = node.parentElement) {\n const answered = memo?.get(node);\n if (answered !== undefined) {\n inherited = answered;\n break;\n }\n pending.push(node);\n }\n for (let i = pending.length - 1; i >= 0; i -= 1) {\n const node = pending[i]!;\n // Once an ancestor is out, its descendants are out with it, and asking the\n // platform about them would be a style read for an answer already known.\n inherited = inherited && elementRendersItself(win, node);\n memo?.set(node, inherited);\n }\n return inherited;\n}\n\n// ─── Style accessors ──────────────────────────────────────────────────────────\n\nexport function getCuratedComputedStyles(el: HTMLElement): Record<string, string> {\n const styles: Record<string, string> = {};\n const computed = el.ownerDocument.defaultView?.getComputedStyle(el);\n if (!computed) return styles;\n\n for (const prop of CURATED_STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(prop);\n if (value) styles[prop] = value;\n }\n\n return styles;\n}\n\nexport function getInlineStyles(el: HTMLElement): Record<string, string> {\n const styles: Record<string, string> = {};\n for (const property of CURATED_STYLE_PROPERTIES) {\n const value = el.style.getPropertyValue(property);\n if (value) styles[property] = value;\n }\n return styles;\n}\n\nexport function getDataAttributes(el: HTMLElement): Record<string, string> {\n const attrs: Record<string, string> = {};\n for (const attr of el.attributes) {\n if (attr.name.startsWith(\"data-\")) {\n attrs[attr.name.slice(5)] = attr.value;\n }\n }\n return attrs;\n}\n\n// ─── DOM traversal ────────────────────────────────────────────────────────────\n\nexport function findClosestByAttribute(\n el: HTMLElement,\n attributeNames: string[],\n): HTMLElement | null {\n let current: HTMLElement | null = el;\n while (current) {\n const candidate = current;\n if (attributeNames.some((attribute) => candidate.hasAttribute(attribute))) {\n return candidate;\n }\n current = current.parentElement;\n }\n return null;\n}\n// ─── Composition source resolution ───────────────────────────────────────────\n\n// The runtime INLINES subcompositions and strips the source-file linkage from the\n// mounted root (it keeps `data-composition-id` but drops `data-composition-src`/\n// `-file`), so a subcomp element's DOM ancestors no longer say which file it came\n// from. This project-global map (composition-id → source file, built once from\n// index.html's clips — see NLEContext/EditorShell) recovers it. The studio loads one project at a\n// time, so module scope is the right lifetime; it's empty until set, in which case\n// resolution falls back to the historical attribute-only behavior.\nlet compositionSourceMap: Map<string, string> = new Map();\n// Bumped on every replacement so a consumer that memoizes a resolved source file\n// can tell that the map it resolved against is gone. The map is module state\n// with no DOM footprint, so nothing else can observe the change.\nlet compositionSourceMapRevision = 0;\n\nexport function setCompositionSourceMap(map: Map<string, string>): void {\n compositionSourceMap = map;\n compositionSourceMapRevision += 1;\n}\n\nexport function getCompositionSourceMapRevision(): number {\n return compositionSourceMapRevision;\n}\n\nfunction sourceFromCompositionId(ownerRoot: HTMLElement | null): string | undefined {\n if (!ownerRoot || compositionSourceMap.size === 0) return undefined;\n // The runtime may rename the mounted id to a runtime-unique one, preserving the\n // authored id on `data-hf-original-composition-id` — prefer that, then the current id.\n const authored = ownerRoot.getAttribute(\"data-hf-original-composition-id\");\n const current = ownerRoot.getAttribute(\"data-composition-id\");\n return (\n (authored ? compositionSourceMap.get(authored) : undefined) ??\n (current ? compositionSourceMap.get(current) : undefined)\n );\n}\n\nexport function getSourceFileForElement(\n el: HTMLElement,\n activeCompositionPath: string | null,\n): { sourceFile: string; compositionPath: string } {\n const sourceHost = findClosestByAttribute(el, [\"data-composition-file\", \"data-composition-src\"]);\n const ownerRoot = findClosestByAttribute(el, [\"data-composition-id\"]);\n const sourceFile =\n sourceHost?.getAttribute(\"data-composition-file\") ??\n sourceHost?.getAttribute(\"data-composition-src\") ??\n ownerRoot?.getAttribute(\"data-composition-file\") ??\n ownerRoot?.getAttribute(\"data-composition-src\") ??\n sourceFromCompositionId(ownerRoot) ??\n activeCompositionPath ??\n \"index.html\";\n\n return {\n sourceFile,\n compositionPath: sourceFile,\n };\n}\n\nexport function normalizeTimelineCompositionSource(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n if (!trimmed) return undefined;\n if (!/^([a-z][a-z0-9+.-]*:|\\/)/i.test(trimmed)) return trimmed;\n\n let pathname = trimmed;\n try {\n pathname = new URL(trimmed, \"http://studio.local\").pathname;\n } catch {\n pathname = trimmed;\n }\n\n for (const marker of [\"/preview/comp/\", \"/preview/\"]) {\n const markerIndex = pathname.indexOf(marker);\n if (markerIndex < 0) continue;\n const sourcePath = pathname.slice(markerIndex + marker.length).replace(/^\\/+/, \"\");\n return sourcePath || trimmed;\n }\n\n return trimmed;\n}\n\n// ─── CSS escaping ─────────────────────────────────────────────────────────────\n\nfunction escapeCssIdentifier(value: string): string {\n const css = globalThis.CSS as { escape?: (input: string) => string } | undefined;\n if (typeof css?.escape === \"function\") return css.escape(value);\n\n if (value === \"-\") return \"\\\\-\";\n\n let escaped = \"\";\n for (let index = 0; index < value.length; index += 1) {\n const char = value[index] ?? \"\";\n const code = char.charCodeAt(0);\n if (code === 0) {\n escaped += \"�\";\n continue;\n }\n\n const isDigit = code >= 48 && code <= 57;\n const isUpperAlpha = code >= 65 && code <= 90;\n const isLowerAlpha = code >= 97 && code <= 122;\n const isControl = (code >= 1 && code <= 31) || code === 127;\n const isLeadingDigit = index === 0 && isDigit;\n const isSecondDigitAfterDash = index === 1 && value.startsWith(\"-\") && isDigit;\n if (isControl || isLeadingDigit || isSecondDigitAfterDash) {\n escaped += `\\\\${code.toString(16)} `;\n continue;\n }\n if (isUpperAlpha || isLowerAlpha || isDigit || char === \"-\" || char === \"_\" || code >= 128) {\n escaped += char;\n continue;\n }\n escaped += `\\\\${char}`;\n }\n return escaped;\n}\n\nexport function escapeCssString(value: string): string {\n return value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, \"\\\\a \")\n .replace(/\\r/g, \"\\\\d \")\n .replace(/\\f/g, \"\\\\c \");\n}\n\nexport function querySelectorAllSafely(doc: Document, selector: string): Element[] {\n try {\n return Array.from(doc.querySelectorAll(selector));\n } catch {\n return [];\n }\n}\n\nfunction humanizeIdentifier(value: string): string {\n return (\n value\n .replace(/\\.html$/i, \"\")\n .replace(/^compositions\\//i, \"\")\n .split(\"/\")\n .at(-1)\n ?.replace(/[-_]+/g, \" \")\n .replace(/\\b\\w/g, (char) => char.toUpperCase()) ?? value\n );\n}\n\n// ─── CSS selector building ────────────────────────────────────────────────────\n\nexport function buildStableSelector(el: HTMLElement): string | undefined {\n if (el.id) return `#${escapeCssIdentifier(el.id)}`;\n\n const compositionId = el.getAttribute(\"data-composition-id\");\n if (compositionId) return `[data-composition-id=\"${escapeCssString(compositionId)}\"]`;\n\n // Group wrappers carry no id/class; their data-hf-group value is the unique,\n // stable handle the source mutations write — use it so the wrapper is\n // selectable, patchable (move/scale), and addressable for ungroup.\n const group = el.getAttribute(\"data-hf-group\");\n if (group) return `[data-hf-group=\"${escapeCssString(group)}\"]`;\n\n return getPreferredClassSelector(el);\n}\n\nfunction getPreferredClassSelector(el: HTMLElement): string | undefined {\n const classes = Array.from(el.classList)\n .map((value) => value.trim())\n .filter(Boolean);\n if (classes.length === 0) return undefined;\n const preferred =\n classes.find((value) => value !== \"clip\" && !value.startsWith(\"__hf-\")) ?? classes[0];\n return preferred ? `.${escapeCssIdentifier(preferred)}` : undefined;\n}\n\n// fallow-ignore-next-line complexity\nexport function buildElementLabel(el: HTMLElement): string {\n const compositionId =\n el.getAttribute(\"data-hf-original-composition-id\") ?? el.getAttribute(\"data-composition-id\");\n if (compositionId && compositionId !== \"main\") {\n return humanizeIdentifier(compositionId);\n }\n\n const compositionSrc =\n el.getAttribute(\"data-composition-src\") ?? el.getAttribute(\"data-composition-file\");\n if (compositionSrc) {\n return humanizeIdentifier(compositionSrc);\n }\n\n const group = el.getAttribute(\"data-hf-group\");\n if (group) return group;\n\n if (el.id) return humanizeIdentifier(el.id);\n\n const preferredClass = getPreferredClassSelector(el);\n if (preferredClass) {\n return humanizeIdentifier(preferredClass.replace(/^\\./, \"\"));\n }\n\n const text = (el.textContent ?? \"\").trim().replace(/\\s+/g, \" \");\n if (text) return text.length > 40 ? `${text.slice(0, 39)}…` : text;\n return el.tagName.toLowerCase();\n}\n\nexport function getSelectorIndex(\n doc: Document,\n el: HTMLElement,\n selector: string | undefined,\n sourceFile: string,\n activeCompositionPath: string | null,\n): number | undefined {\n if (!selector?.startsWith(\".\")) return undefined;\n\n return getSourceScopedSelectorIndex(doc, el, selector, sourceFile, (candidate) =>\n isHtmlElement(candidate)\n ? getSourceFileForElement(candidate, activeCompositionPath).sourceFile\n : undefined,\n );\n}\n","import type { PatchTarget } from \"../../utils/sourcePatcher\";\nimport type { GsapAnimation } from \"@hyperframes/parsers/gsap-parser\";\n\nexport const CURATED_STYLE_PROPERTIES = [\n \"position\",\n \"display\",\n \"top\",\n \"left\",\n \"right\",\n \"bottom\",\n \"inset\",\n \"width\",\n \"height\",\n \"gap\",\n \"justify-content\",\n \"align-items\",\n \"flex-direction\",\n \"font-size\",\n \"font-style\",\n \"font-weight\",\n \"font-family\",\n \"line-height\",\n \"letter-spacing\",\n \"text-align\",\n \"text-transform\",\n \"color\",\n \"background-color\",\n \"background-image\",\n \"opacity\",\n \"mix-blend-mode\",\n \"border-radius\",\n \"border-width\",\n \"border-style\",\n \"border-color\",\n \"border-top-width\",\n \"border-top-style\",\n \"border-top-color\",\n \"outline-color\",\n \"overflow\",\n \"clip-path\",\n \"box-shadow\",\n \"filter\",\n \"backdrop-filter\",\n \"z-index\",\n \"transform\",\n \"object-fit\",\n \"object-position\",\n] as const;\n\nexport interface DomEditCapabilities {\n canSelect: boolean;\n canEditStyles: boolean;\n /** Can take a non-destructive `clip-path: inset()` crop — broader than\n * canEditStyles (a sub-composition host is croppable from the parent view). */\n canCrop: boolean;\n /** Directly editable authored left/top style fields. Canvas drag uses manual edits instead. */\n canMove: boolean;\n /** Directly editable authored width/height style fields. Canvas resize uses manual edits instead. */\n canResize: boolean;\n canApplyManualOffset: boolean;\n canApplyManualSize: boolean;\n canApplyManualRotation: boolean;\n reasonIfDisabled?: string;\n commitCheckPending?: boolean;\n}\n\nexport interface DomEditTextField {\n key: string;\n label: string;\n value: string;\n tagName: string;\n attributes: Array<{ name: string; value: string }>;\n inlineStyles: Record<string, string>;\n computedStyles: Record<string, string>;\n source: \"self\" | \"child\" | \"text-node\";\n sourceChildIndex?: number;\n}\n\nexport interface DomEditSelection extends PatchTarget {\n element: HTMLElement;\n label: string;\n tagName: string;\n sourceFile: string;\n compositionPath: string;\n compositionSrc?: string;\n isCompositionHost: boolean;\n isInsideLockedComposition: boolean;\n boundingBox: { x: number; y: number; width: number; height: number };\n textContent: string | null;\n dataAttributes: Record<string, string>;\n inlineStyles: Record<string, string>;\n computedStyles: Record<string, string>;\n textFields: DomEditTextField[];\n capabilities: DomEditCapabilities;\n existsInSource?: boolean;\n gsapAnimations?: GsapAnimation[];\n}\n\nexport interface DomEditLayerItem {\n key: string;\n element: HTMLElement;\n label: string;\n tagName: string;\n depth: number;\n childCount: number;\n id?: string;\n hfId?: string;\n selector?: string;\n selectorIndex?: number;\n sourceFile: string;\n}\n\nexport interface DomEditContextOptions {\n activeCompositionPath: string | null;\n isMasterView: boolean;\n preferClipAncestor?: boolean;\n /** The group wrapper the user has drilled into (null = top level). Selection\n * resolution treats groups as a unit unless drilled into one. */\n activeGroupElement?: HTMLElement | null;\n}\n\nexport interface DomEditViewport {\n width: number;\n height: number;\n}\n\nexport interface TimelineElementDomTarget {\n id?: string;\n domId?: string;\n selector?: string;\n selectorIndex?: number;\n sourceFile?: string;\n compositionSrc?: string;\n}\n\nexport interface TimelineElementDomTargetOptions {\n activeCompositionPath: string | null;\n compIdToSrc?: ReadonlyMap<string, string>;\n isMasterView: boolean;\n}\n","import { isHtmlElement } from \"@hyperframes/core/runtime/dom-realm\";\nimport { parseCssColor } from \"../../components/editor/colorValue\";\nimport type { TimelineText } from \"../store/timelineElement\";\nimport {\n getCuratedComputedStyles,\n isEditableTextLeaf,\n isTextBearingTag,\n} from \"../../components/editor/domEditingDom\";\n\n/** A layer that paints only text and a flat colour (a text tag whose children are all text leaves,\n * no background image): its words and look. Anything painted beyond that keeps its picture. */\nexport function readTimelineText(el: Element): TimelineText | undefined {\n if (!isHtmlElement(el) || !isTextBearingTag(el.localName)) return undefined;\n const children = Array.from(el.children);\n if (!children.every((child) => isHtmlElement(child) && isEditableTextLeaf(child)))\n return undefined;\n const value = el.textContent?.replace(/\\s+/g, \" \").trim();\n if (!value) return undefined;\n const style = getCuratedComputedStyles(el);\n if ((style[\"background-image\"] ?? \"none\") !== \"none\") return undefined;\n const background = style[\"background-color\"];\n return {\n value,\n fontFamily: style[\"font-family\"],\n fontWeight: style[\"font-weight\"],\n color: style.color,\n background: background && parseCssColor(background)?.alpha === 1 ? background : undefined,\n };\n}\n\nexport function sameTimelineText(a?: TimelineText, b?: TimelineText): boolean {\n if (!a || !b) return a === b;\n return (\n a.value === b.value &&\n a.fontFamily === b.fontFamily &&\n a.fontWeight === b.fontWeight &&\n a.color === b.color &&\n a.background === b.background\n );\n}\n","/** Round to 3 decimal places (millisecond precision for GSAP values). */\nexport function roundTo3(val: number): number {\n return Math.round(val * 1000) / 1000;\n}\n\n/** Whole CSS px: GSAP parses a -50% translate against the integer offsetWidth/Height. */\nexport function roundToLayoutPx(val: number): number {\n return Math.round(val);\n}\n\nexport function roundToLayoutSize(size: { width: number; height: number }) {\n return {\n width: roundToLayoutPx(Math.max(1, size.width)),\n height: roundToLayoutPx(Math.max(1, size.height)),\n };\n}\n\n/** Round to 2 decimal places (centisecond precision for timeline values). */\nexport function roundToCenti(val: number): number {\n return Math.round(val * 100) / 100;\n}\n","import { roundToCenti } from \"../../utils/rounding\";\n\nexport interface ParsedColor {\n red: number;\n green: number;\n blue: number;\n alpha: number;\n}\n\nexport interface HsvColor {\n hue: number;\n saturation: number;\n value: number;\n}\n\nfunction clampChannel(value: number): number {\n return Math.max(0, Math.min(255, Math.round(value)));\n}\n\nfunction clampAlpha(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nfunction toHex(value: number): string {\n return clampChannel(value).toString(16).padStart(2, \"0\");\n}\n\nfunction formatAlpha(value: number): string {\n return `${roundToCenti(clampAlpha(value))}`;\n}\n\nfunction parseComponent(value: string, scale: number): number {\n return value.endsWith(\"%\") ? (Number(value.slice(0, -1)) * scale) / 100 : Number(value);\n}\n\nconst NUMBER = String.raw`(?:\\d+(?:\\.\\d+)?|\\.\\d+)`;\nconst COMMA_RGB = new RegExp(\n String.raw`^rgba?\\(\\s*(${NUMBER})\\s*,\\s*(${NUMBER})\\s*,\\s*(${NUMBER})(?:\\s*,\\s*(${NUMBER}))?\\s*\\)$`,\n);\nconst SPACE_RGB = new RegExp(\n String.raw`^rgba?\\(\\s*(${NUMBER}%?)\\s+(${NUMBER}%?)\\s+(${NUMBER}%?)(?:\\s*\\/\\s*(${NUMBER}%?))?\\s*\\)$`,\n);\n\nfunction parseSerializedColor(value: string): ParsedColor | null {\n const trimmed = value.trim().toLowerCase();\n if (!trimmed) return null;\n if (trimmed === \"transparent\") {\n return { red: 0, green: 0, blue: 0, alpha: 0 };\n }\n\n const hex = trimmed.match(/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/);\n if (hex) {\n const digits = hex[1].length <= 4 ? [...hex[1]].map((digit) => digit + digit).join(\"\") : hex[1];\n return {\n red: Number.parseInt(digits.slice(0, 2), 16),\n green: Number.parseInt(digits.slice(2, 4), 16),\n blue: Number.parseInt(digits.slice(4, 6), 16),\n alpha: digits.length === 8 ? Number.parseInt(digits.slice(6, 8), 16) / 255 : 1,\n };\n }\n\n const rgba = trimmed.match(COMMA_RGB) ?? trimmed.match(SPACE_RGB);\n if (rgba) {\n return {\n red: clampChannel(parseComponent(rgba[1], 255)),\n green: clampChannel(parseComponent(rgba[2], 255)),\n blue: clampChannel(parseComponent(rgba[3], 255)),\n alpha: clampAlpha(rgba[4] != null ? parseComponent(rgba[4], 1) : 1),\n };\n }\n\n return null;\n}\n\nlet colorContext: CanvasRenderingContext2D | null = null;\n\nfunction canResolveInBrowser(value: string): boolean {\n return (\n typeof document !== \"undefined\" &&\n typeof CSS !== \"undefined\" &&\n CSS.supports(\"color\", value) &&\n !/\\bcurrentcolor\\b|\\bvar\\s*\\(|\\blight-dark\\s*\\(/i.test(value)\n );\n}\n\nfunction parseBrowserColor(value: string): ParsedColor | null {\n try {\n if (!canResolveInBrowser(value)) return null;\n colorContext ??= document.createElement(\"canvas\").getContext(\"2d\");\n if (!colorContext) return null;\n return (\n parseCanvasColor(\n colorContext,\n `color(from ${value} srgb r g b / alpha)`,\n parseSrgbSerialization,\n ) ?? parseCanvasColor(colorContext, value, parseSerializedColor)\n );\n } catch {\n return null;\n }\n}\n\nfunction parseCanvasColor(\n context: CanvasRenderingContext2D,\n value: string,\n parse: (serialized: string) => ParsedColor | null,\n): ParsedColor | null {\n const serialized = readCanvasColor(context, value);\n return serialized === null ? null : parse(serialized);\n}\n\nfunction readCanvasColor(context: CanvasRenderingContext2D, value: string): string | null {\n context.fillStyle = \"transparent\";\n context.fillStyle = value;\n const first = context.fillStyle;\n context.fillStyle = \"white\";\n context.fillStyle = value;\n return typeof first === \"string\" && first === context.fillStyle ? first : null;\n}\n\nfunction parseSrgbSerialization(serialized: string): ParsedColor | null {\n const match = serialized.match(/^color\\(srgb ([^ ]+) ([^ ]+) ([^ /)]+)(?: \\/ ([^)]+))?\\)$/);\n if (!match) return null;\n const channels = match.slice(1, 4).map(Number);\n const alpha = match[4] === undefined ? 1 : Number(match[4]);\n if (!channels.every(Number.isFinite) || !Number.isFinite(alpha)) return null;\n return {\n red: clampChannel(channels[0] * 255),\n green: clampChannel(channels[1] * 255),\n blue: clampChannel(channels[2] * 255),\n alpha: clampAlpha(alpha),\n };\n}\n\nexport function parseCssColor(value: string): ParsedColor | null {\n return parseSerializedColor(value) ?? parseBrowserColor(value.trim());\n}\n\nexport function resolvePickerColor(\n value: string | undefined,\n element: Element | null,\n fallback: string,\n): string {\n const view = element?.ownerDocument.defaultView;\n const parsed =\n (value ? parseCssColor(value) : null) ??\n (element && view ? parseCssColor(view.getComputedStyle(element).color) : null);\n return parsed ? toHexColor(parsed) : fallback;\n}\n\nexport function toColorPickerValue(value: string): string {\n const parsed = parseCssColor(value);\n if (!parsed) return \"#000000\";\n return toHexColor(parsed);\n}\n\nexport function toHexColor(color: Pick<ParsedColor, \"red\" | \"green\" | \"blue\">): string {\n return `#${toHex(color.red)}${toHex(color.green)}${toHex(color.blue)}`;\n}\n\nexport function formatCssColor(color: ParsedColor): string {\n const red = clampChannel(color.red);\n const green = clampChannel(color.green);\n const blue = clampChannel(color.blue);\n const alpha = clampAlpha(color.alpha);\n\n if (alpha >= 1) {\n return `rgb(${red}, ${green}, ${blue})`;\n }\n\n return `rgba(${red}, ${green}, ${blue}, ${formatAlpha(alpha)})`;\n}\n\nexport function rgbToHsv(color: Pick<ParsedColor, \"red\" | \"green\" | \"blue\">): HsvColor {\n const red = clampChannel(color.red) / 255;\n const green = clampChannel(color.green) / 255;\n const blue = clampChannel(color.blue) / 255;\n const max = Math.max(red, green, blue);\n const min = Math.min(red, green, blue);\n const delta = max - min;\n\n let hue = 0;\n if (delta !== 0) {\n if (max === red) {\n hue = 60 * (((green - blue) / delta) % 6);\n } else if (max === green) {\n hue = 60 * ((blue - red) / delta + 2);\n } else {\n hue = 60 * ((red - green) / delta + 4);\n }\n }\n\n if (hue < 0) hue += 360;\n\n return {\n hue,\n saturation: max === 0 ? 0 : delta / max,\n value: max,\n };\n}\n\nexport function hsvToRgb(color: HsvColor): Pick<ParsedColor, \"red\" | \"green\" | \"blue\"> {\n const hue = (((color.hue % 360) + 360) % 360) / 60;\n const saturation = Math.max(0, Math.min(1, color.saturation));\n const value = Math.max(0, Math.min(1, color.value));\n const chroma = value * saturation;\n const x = chroma * (1 - Math.abs((hue % 2) - 1));\n const m = value - chroma;\n\n let red = 0;\n let green = 0;\n let blue = 0;\n\n if (hue >= 0 && hue < 1) {\n red = chroma;\n green = x;\n } else if (hue >= 1 && hue < 2) {\n red = x;\n green = chroma;\n } else if (hue >= 2 && hue < 3) {\n green = chroma;\n blue = x;\n } else if (hue >= 3 && hue < 4) {\n green = x;\n blue = chroma;\n } else if (hue >= 4 && hue < 5) {\n red = x;\n blue = chroma;\n } else {\n red = chroma;\n blue = x;\n }\n\n return {\n red: clampChannel((red + m) * 255),\n green: clampChannel((green + m) * 255),\n blue: clampChannel((blue + m) * 255),\n };\n}\n\nexport function mergeColorWithExistingAlpha(nextHex: string, previousValue: string): string {\n const hex = nextHex.trim();\n const match = hex.match(/^#([0-9a-f]{6})$/i);\n if (!match) return previousValue;\n\n const previous = parseCssColor(previousValue);\n const red = Number.parseInt(match[1].slice(0, 2), 16);\n const green = Number.parseInt(match[1].slice(2, 4), 16);\n const blue = Number.parseInt(match[1].slice(4, 6), 16);\n const alpha = previous?.alpha ?? 1;\n\n return formatCssColor({ red, green, blue, alpha });\n}\n","/**\n * Playback adapter utilities: factory for the static-seek adapter used when a\n * composition exposes only a `renderSeek` / `seek` API (no native play/pause\n * support), plus a thin wrapper that normalises GSAP-style `TimelineLike`\n * objects to the `PlaybackAdapter` interface.\n */\n\nimport type {\n PlaybackAdapter,\n RuntimePlaybackAdapter,\n StaticSeekPlaybackClock,\n TimelineLike,\n} from \"./playbackTypes\";\n\n// ---------------------------------------------------------------------------\n// Pure numeric helpers\n// ---------------------------------------------------------------------------\n\nexport function isFinitePositive(value: number): boolean {\n return Number.isFinite(value) && value > 0;\n}\n\nfunction clampTime(time: number, duration: number): number {\n const safeDuration = Math.max(0, Number.isFinite(duration) ? duration : 0);\n const safeTime = Math.max(0, Number.isFinite(time) ? time : 0);\n return safeDuration > 0 ? Math.min(safeTime, safeDuration) : safeTime;\n}\n\nexport function getAdapterDuration(adapter: PlaybackAdapter | null | undefined): number {\n if (!adapter) return 0;\n try {\n const duration = Number(adapter.getDuration());\n return isFinitePositive(duration) ? duration : 0;\n } catch {\n return 0;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Clock factory\n// ---------------------------------------------------------------------------\n\nexport function getDefaultStaticSeekPlaybackClock(win: Window): StaticSeekPlaybackClock {\n return {\n now: () => win.performance.now(),\n requestAnimationFrame: (callback) => win.requestAnimationFrame(callback),\n cancelAnimationFrame: (handle) => win.cancelAnimationFrame(handle),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Static-seek adapter\n// ---------------------------------------------------------------------------\n\n/**\n * Wraps a render-only player (exposes `renderSeek`/`seek` but no native\n * play/pause) and drives playback via `requestAnimationFrame`.\n */\nexport function createStaticSeekPlaybackAdapter(\n player: Pick<RuntimePlaybackAdapter, \"getTime\"> &\n Partial<Pick<RuntimePlaybackAdapter, \"renderSeek\" | \"seek\">>,\n duration: number,\n clock: StaticSeekPlaybackClock,\n getPlaybackRate: () => number = () => 1,\n): PlaybackAdapter {\n const safeDuration = Math.max(0, Number.isFinite(duration) ? duration : 0);\n let currentTime = clampTime(Number(player.getTime?.() ?? 0), safeDuration);\n let playing = false;\n let rafId = 0;\n let playStartTime = currentTime;\n let playStartNow = clock.now();\n\n const renderSeek = (time: number) => {\n currentTime = clampTime(time, safeDuration);\n if (typeof player.renderSeek === \"function\") {\n player.renderSeek(currentTime);\n return;\n }\n player.seek?.(currentTime);\n };\n\n const stopTicker = () => {\n if (rafId) {\n clock.cancelAnimationFrame(rafId);\n rafId = 0;\n }\n };\n\n const tick: FrameRequestCallback = (now) => {\n if (!playing) return;\n const playbackRate = Math.max(0.1, Number(getPlaybackRate()) || 1);\n const elapsed = ((now - playStartNow) / 1000) * playbackRate;\n renderSeek(playStartTime + elapsed);\n if (currentTime >= safeDuration) {\n playing = false;\n rafId = 0;\n return;\n }\n rafId = clock.requestAnimationFrame(tick);\n };\n\n return {\n play: () => {\n if (playing || safeDuration <= 0) return;\n if (currentTime >= safeDuration) renderSeek(0);\n playing = true;\n playStartTime = currentTime;\n playStartNow = clock.now();\n stopTicker();\n rafId = clock.requestAnimationFrame(tick);\n },\n pause: () => {\n playing = false;\n stopTicker();\n },\n seek: (time, options) => {\n renderSeek(time);\n if (options?.keepPlaying) {\n if (playing) {\n playStartTime = currentTime;\n playStartNow = clock.now();\n }\n return;\n }\n // Default seek aligns with wrapTimeline: stop the RAF ticker so the\n // adapter's `playing` flag matches the public seek contract instead of\n // silently driving renderSeek in the background.\n playing = false;\n stopTicker();\n },\n getTime: () => currentTime,\n getDuration: () => safeDuration,\n isPlaying: () => playing,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Static-seek fallback cache\n// ---------------------------------------------------------------------------\n\nexport type StaticSeekCacheEntry = {\n player: RuntimePlaybackAdapter | PlaybackAdapter;\n duration: number;\n adapter: PlaybackAdapter;\n};\n\ntype StaticSeekCacheRef = { current: StaticSeekCacheEntry | null };\ntype WarnedRef = { current: boolean };\n\n/**\n * Pause and drop the cached static-seek adapter. Must be called whenever\n * adapter selection switches to a native adapter — a cached static-seek\n * adapter that was mid-play keeps its private rAF loop seeking the player\n * forever otherwise, fighting the native transport. Also re-arms the\n * downgrade warning so a later re-downgrade is surfaced again.\n */\nexport function releaseStaticSeekCache(cache: StaticSeekCacheRef, warned: WarnedRef): void {\n cache.current?.adapter.pause();\n cache.current = null;\n warned.current = false;\n}\n\n/**\n * Resolve (with caching) the seek-driven fallback adapter. Warns once per\n * downgrade streak: seek-driven playback never starts media elements or\n * WebAudio, so without the warning the downgrade silently loses audio.\n */\nexport function resolveStaticSeekFallback(opts: {\n cache: StaticSeekCacheRef;\n warned: WarnedRef;\n bestAdapter: RuntimePlaybackAdapter | PlaybackAdapter;\n effectiveDuration: number;\n docDuration: number;\n clock: StaticSeekPlaybackClock;\n getPlaybackRate: () => number;\n}): PlaybackAdapter {\n const { cache, warned, bestAdapter, effectiveDuration, docDuration } = opts;\n const cached = cache.current;\n if (cached?.player === bestAdapter && cached.duration === effectiveDuration) {\n return cached.adapter;\n }\n cached?.adapter.pause();\n if (!warned.current) {\n warned.current = true;\n console.warn(\n `[useTimelinePlayer] Selected adapter duration (${getAdapterDuration(bestAdapter)}s) does not cover the document duration (${docDuration}s); falling back to seek-driven playback, which never starts media elements or WebAudio. Audio will not play in preview — extend the GSAP timeline to cover the declared data-duration.`,\n );\n }\n const adapter = createStaticSeekPlaybackAdapter(\n bestAdapter,\n effectiveDuration,\n opts.clock,\n opts.getPlaybackRate,\n );\n cache.current = { player: bestAdapter, duration: effectiveDuration, adapter };\n return adapter;\n}\n\n// ---------------------------------------------------------------------------\n// GSAP timeline wrapper\n// ---------------------------------------------------------------------------\n\nexport function wrapTimeline(tl: TimelineLike): PlaybackAdapter {\n return {\n play: () => tl.play(),\n pause: () => tl.pause(),\n seek: (t, options) => {\n const shouldPause = !options?.keepPlaying;\n if (shouldPause) tl.pause();\n tl.seek(t);\n if (shouldPause) tl.pause();\n },\n getTime: () => tl.time(),\n getDuration: () => tl.duration(),\n isPlaying: () => tl.isActive(),\n };\n}\n","/**\n * Low-level helpers for building and identifying TimelineElement objects.\n *\n * Covers: duration reading, media-element metadata extraction, selector/key/\n * identity builders, and DOM node lookup. These are\n * intentionally dependency-free (no store, no hooks) so they can be used in\n * both the React hook and test environments.\n */\n\nimport type { TimelineElement } from \"../store/playerStore\";\nimport { readTimelineText } from \"./timelineText\";\nimport type { ClipManifestClip } from \"./playbackTypes\";\nimport { isFinitePositive } from \"./playbackAdapter\";\nimport { getSourceScopedSelectorIndex } from \"../../utils/sourceScopedSelectorIndex\";\nimport { HF_AUDIO_GROUP_TAG } from \"@hyperframes/core/audio-groups\";\nimport { readElementFades } from \"@hyperframes/core/audio-fade\";\nimport { isHtmlElement, isImageElement, isMediaElement } from \"@hyperframes/core/runtime/dom-realm\";\nimport { elementVolume } from \"./storedVolume\";\nimport {\n type AttrReader,\n clampPlaybackRate,\n readMediaOffsetSeconds,\n} from \"@hyperframes/parsers/media-duration\";\n\n// ---------------------------------------------------------------------------\n// Layer-reveal lift transparency\n// ---------------------------------------------------------------------------\n\n/**\n * Attributes carrying the pre-lift state of a Layers-panel selection reveal\n * (useLayerRevealOverride): while a layer is selected it PAINTS on top via a\n * temporary inline z-index, but the lift is a purely visual, ephemeral studio\n * affordance — every z reader must keep reporting the element's TRUE z\n * (stored here) so menus, badges, the lane mirror, and the panel sort never\n * reason on the lifted value. A z-reorder commit removes the attributes (the\n * commit is the new truth).\n */\nexport const LAYER_REVEAL_PRIOR_Z_ATTR = \"data-hf-reveal-prior-z\";\nexport const LAYER_REVEAL_PRIOR_POSITION_ATTR = \"data-hf-reveal-prior-pos\";\n\n/** The lifted element's true (pre-lift) z, or null when no lift is active. */\nexport function readLayerRevealPriorZ(el: Element): number | null {\n const raw = el.getAttribute(LAYER_REVEAL_PRIOR_Z_ATTR);\n if (raw == null) return null;\n const n = Number.parseInt(raw, 10);\n return Number.isFinite(n) ? n : null;\n}\n\n// ---------------------------------------------------------------------------\n// Duration attribute helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Read a host element's effective CSS stacking order for the timeline's reverse\n * z→lane mapping. Prefers the inline `style.zIndex` (what the canvas context\n * menu and LayersPanel z-edits write via handleDomZIndexReorderCommit), falls\n * back to computed style; \"auto\" / empty / unparseable ⇒ 0. Works with a\n * detached parse Document (no defaultView) as well as a live iframe. Mirrors\n * canvasContextMenuZOrder.parseZIndex semantics so the two directions agree.\n * Reveal-lift transparent: an active lift reports the stored TRUE z.\n */\nexport function readTimelineElementZIndex(el: Element): number {\n const prior = readLayerRevealPriorZ(el);\n if (prior != null) return prior;\n const html = el as HTMLElement;\n const parseZ = (value: string | null | undefined): number | null => {\n if (value == null || value === \"\" || value === \"auto\") return null;\n const n = Number.parseInt(value, 10);\n return Number.isFinite(n) ? n : null;\n };\n const fromInline = parseZ(html.style?.zIndex);\n if (fromInline != null) return fromInline;\n const view = el.ownerDocument?.defaultView;\n if (view?.getComputedStyle) {\n const fromComputed = parseZ(view.getComputedStyle(html).zIndex);\n if (fromComputed != null) return fromComputed;\n }\n return 0;\n}\n\nfunction readDurationAttribute(el: Element | null | undefined): number {\n if (!el) return 0;\n const duration =\n Number.parseFloat(el.getAttribute(\"data-duration\") ?? \"\") ||\n Number.parseFloat(el.getAttribute(\"data-hf-authored-duration\") ?? \"\");\n return isFinitePositive(duration) ? duration : 0;\n}\n\nexport function isTimelineIgnoredElement(el: Element): boolean {\n // An `<hf-audio-group>` is a mixer bus with no timing of its own, drawn as a group row, never a clip.\n if (el.tagName.toLowerCase() === HF_AUDIO_GROUP_TAG) return true;\n return Boolean(\n el.closest(\n [\n \"[data-hyperframes-ignore]\",\n \"[data-hyperframes-picker-ignore]\",\n \"[data-hf-ignore]\",\n \"[data-hf-color-grading-canvas]\",\n ].join(\",\"),\n ),\n );\n}\n\n/**\n * Furthest clip end (start + RAW `data-duration`) over every non-root clip in the\n * document. Reads the authored attribute, NOT any runtime-computed value — so it\n * is immune to the runtime's clamp that truncates a clip's live duration to the\n * composition length. This is the source of truth for content-driven duration:\n * computing it from the store instead would feed the truncated value back in and\n * make the composition length ratchet down (research HANDOFF-3 §6.1 feedback loop).\n */\nexport function furthestClipEndFromDocument(doc: Document | null | undefined): number {\n if (!doc) return 0;\n const root = doc.querySelector(\"[data-composition-id]\");\n let maxEnd = 0;\n for (const node of Array.from(doc.querySelectorAll(\"[data-start]\"))) {\n if (node === root || isTimelineIgnoredElement(node)) continue;\n const start = Number.parseFloat(node.getAttribute(\"data-start\") ?? \"\");\n const duration = readDurationAttribute(node);\n if (!Number.isFinite(start) || start < 0 || duration <= 0) continue;\n maxEnd = Math.max(maxEnd, start + duration);\n }\n return maxEnd;\n}\n\nexport function readTimelineDurationFromDocument(doc: Document | null | undefined): number {\n if (!doc) return 0;\n const rootDuration = readDurationAttribute(doc.querySelector(\"[data-composition-id]\"));\n if (rootDuration > 0) return rootDuration;\n return furthestClipEndFromDocument(doc);\n}\n\n// ---------------------------------------------------------------------------\n// DOM element type guards\n// ---------------------------------------------------------------------------\n\nfunction isCompositionHost(el: Element): boolean {\n return (\n el.hasAttribute(\"data-composition-id\") ||\n el.hasAttribute(\"data-composition-src\") ||\n el.hasAttribute(\"data-composition-file\")\n );\n}\n\nexport function resolveMediaElement(el: Element): HTMLMediaElement | HTMLImageElement | null {\n if (isMediaElement(el) || isImageElement(el)) return el;\n // A composition's media belongs to its own timeline, not the clip's: its length would cap a trim.\n if (isCompositionHost(el)) return null;\n const candidate = el.querySelector(\"video, audio, img\");\n return isMediaElement(candidate) || isImageElement(candidate) ? candidate : null;\n}\n\n/** The in-point as playback reads it, and the attribute holding it; empty when neither is authored. */\nexport function readPlaybackStartAttributes(\n getAttr: AttrReader,\n): Pick<TimelineElement, \"playbackStart\" | \"playbackStartAttr\"> {\n const playbackStartAttr =\n getAttr(\"data-playback-start\") != null\n ? \"playback-start\"\n : getAttr(\"data-media-start\") != null\n ? \"media-start\"\n : undefined;\n return playbackStartAttr\n ? { playbackStart: readMediaOffsetSeconds(getAttr), playbackStartAttr }\n : {};\n}\n\nexport function playbackStartAttributeForElement(\n element: Pick<TimelineElement, \"kind\" | \"playbackStartAttr\">,\n): \"data-media-start\" | \"data-playback-start\" {\n return element.playbackStartAttr === \"playback-start\" || element.kind === \"composition\"\n ? \"data-playback-start\"\n : \"data-media-start\";\n}\n\nfunction applyPlaybackMetadataFromElement(entry: TimelineElement, el: Element): void {\n Object.assign(\n entry,\n readPlaybackStartAttributes((n) => el.getAttribute(n)),\n );\n\n const authoredPlaybackRate = Number.parseFloat(el.getAttribute(\"data-playback-rate\") ?? \"\");\n if (Number.isFinite(authoredPlaybackRate) && authoredPlaybackRate > 0) {\n entry.playbackRate = clampPlaybackRate(authoredPlaybackRate);\n }\n}\n\n/** Sets or clears an optional field, so a re-parse after the attribute is removed drops it. */\nfunction setOptional<K extends keyof TimelineElement>(\n entry: TimelineElement,\n key: K,\n value: TimelineElement[K] | undefined,\n): void {\n if (value === undefined) delete entry[key];\n else entry[key] = value;\n}\n\n/** The compiler's rule (timingCompiler): explicit data-has-audio wins; otherwise an unmuted <video> is audible. */\nexport function isVideoAudible(opts: {\n tag: string;\n hasAudioAttr: string | null | undefined;\n muted: boolean;\n}): boolean {\n if (opts.hasAudioAttr === \"true\") return true;\n if (opts.hasAudioAttr === \"false\" || opts.hasAudioAttr === \"\") return false;\n return opts.tag.toLowerCase() === \"video\" && !opts.muted;\n}\n\nexport function isAudibleVideoNode(el: Element): boolean {\n if (el.tagName.toLowerCase() !== \"video\" || el.hasAttribute(\"muted\")) return false;\n return isVideoAudible({\n tag: \"video\",\n hasAudioAttr: el.getAttribute(\"data-has-audio\"),\n muted: false,\n });\n}\n\n/** What the mixer gets: the compiler's `data-has-audio` rule, muted and volume. */\nfunction applyAudioMetadataFromElement(entry: TimelineElement, el: Element): void {\n const media = resolveMediaElement(el) ?? el;\n const muted = el.hasAttribute(\"muted\") || media.hasAttribute(\"muted\");\n const sound = isVideoAudible({\n tag: el.tagName,\n hasAudioAttr: el.getAttribute(\"data-has-audio\"),\n muted,\n });\n setOptional(entry, \"hasAudio\", sound ? true : undefined);\n setOptional(entry, \"muted\", muted ? true : undefined);\n setOptional(entry, \"volume\", elementVolume(el, media));\n}\n\nfunction applyFadeMetadataFromElement(entry: TimelineElement, el: Element): void {\n const fades = readElementFades(el);\n setOptional(entry, \"fadeIn\", fades.fadeIn > 0 ? fades.fadeIn : undefined);\n setOptional(entry, \"fadeOut\", fades.fadeOut > 0 ? fades.fadeOut : undefined);\n}\n\nexport function applyMediaMetadataFromElement(entry: TimelineElement, el: Element): void {\n setOptional(entry, \"text\", readTimelineText(el));\n applyPlaybackMetadataFromElement(entry, el);\n applyAudioMetadataFromElement(entry, el);\n applyFadeMetadataFromElement(entry, el);\n\n const mediaEl = resolveMediaElement(el);\n if (!mediaEl) return;\n\n entry.tag = mediaEl.tagName.toLowerCase();\n const src = mediaEl.getAttribute(\"src\");\n if (src) entry.src = src;\n\n if (!isMediaElement(mediaEl)) return;\n\n const sourceDurationAttr =\n el.getAttribute(\"data-source-duration\") ?? mediaEl.getAttribute(\"data-source-duration\");\n const sourceDuration = sourceDurationAttr ? parseFloat(sourceDurationAttr) : mediaEl.duration;\n if (Number.isFinite(sourceDuration) && sourceDuration > 0) {\n entry.sourceDuration = sourceDuration;\n }\n\n const playbackRate = mediaEl.defaultPlaybackRate;\n if (entry.playbackRate == null && Number.isFinite(playbackRate) && playbackRate > 0) {\n entry.playbackRate = clampPlaybackRate(playbackRate);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Label helpers\n// ---------------------------------------------------------------------------\n\nexport function getTimelineElementDisplayLabel(input: {\n id?: string | null;\n label?: string | null;\n tag?: string | null;\n}): string {\n const label = input.label?.trim();\n if (label) return label;\n const id = input.id?.trim();\n if (id) return id;\n const tag = input.tag?.trim().toLowerCase();\n return tag ? `${tag} clip` : \"Timeline clip\";\n}\n\n// ---------------------------------------------------------------------------\n// Selector / identity / key builders\n// ---------------------------------------------------------------------------\n\nexport function getTimelineElementSelector(el: Element): string | undefined {\n if (isHtmlElement(el) && el.id) return `#${CSS.escape(el.id)}`;\n const compId = el.getAttribute(\"data-composition-id\");\n if (compId) return `[data-composition-id=\"${CSS.escape(compId)}\"]`;\n if (isHtmlElement(el)) {\n const classes = el.className.split(/\\s+/).filter(Boolean);\n const firstClass = classes.find((className) => className !== \"clip\") ?? classes[0];\n if (firstClass) return `.${CSS.escape(firstClass)}`;\n }\n return undefined;\n}\n\nexport function getTimelineElementSourceFile(el: Element): string | undefined {\n const ownerRoot = el.parentElement?.closest(\"[data-composition-id]\");\n return (\n ownerRoot?.getAttribute(\"data-composition-file\") ??\n ownerRoot?.getAttribute(\"data-composition-src\") ??\n undefined\n );\n}\n\nexport function getTimelineElementSelectorIndex(\n doc: Document,\n el: Element,\n selector: string | undefined,\n): number | undefined {\n return getSourceScopedSelectorIndex(\n doc,\n el,\n selector,\n getTimelineElementSourceFile(el),\n getTimelineElementSourceFile,\n );\n}\n\nexport function buildTimelineElementKey(params: {\n id: string;\n fallbackIndex: number;\n domId?: string;\n selector?: string;\n selectorIndex?: number;\n sourceFile?: string;\n}): string {\n const scope = params.sourceFile ?? \"index.html\";\n if (params.domId) return `${scope}#${params.domId}`;\n if (params.selector) return `${scope}:${params.selector}:${params.selectorIndex ?? 0}`;\n return `${scope}:${params.id}:${params.fallbackIndex}`;\n}\n\n/**\n * Inverse of {@link buildTimelineElementKey} for the `sourceFile#domId` form.\n * A key with no `#` is a bare dom id and carries no source file of its own, so\n * the caller supplies the scope it wants to look that id up in.\n */\nexport function splitTimelineElementKey(key: string): {\n sourceFile: string | null;\n domId: string;\n} {\n const hashIndex = key.lastIndexOf(\"#\");\n if (hashIndex < 0) return { sourceFile: null, domId: key };\n return { sourceFile: key.slice(0, hashIndex), domId: key.slice(hashIndex + 1) };\n}\n\nexport function buildTimelineElementIdentity(params: {\n preferredId?: string | null;\n label: string;\n fallbackIndex: number;\n domId?: string;\n selector?: string;\n selectorIndex?: number;\n sourceFile?: string;\n}): { id: string; key: string } {\n const id =\n params.preferredId?.trim() ||\n buildTimelineElementKey({\n id: params.label,\n fallbackIndex: params.fallbackIndex,\n domId: params.domId,\n selector: params.selector,\n selectorIndex: params.selectorIndex,\n sourceFile: params.sourceFile,\n });\n const key = buildTimelineElementKey({\n id,\n fallbackIndex: params.fallbackIndex,\n domId: params.domId,\n selector: params.selector,\n selectorIndex: params.selectorIndex,\n sourceFile: params.sourceFile,\n });\n return { id, key };\n}\n\nexport function getTimelineElementIdentity(element: { key?: string | null; id: string }): string {\n return element.key ?? element.id;\n}\n\n/**\n * The id space the RUNTIME matches on — a bare DOM id, never a store key.\n *\n * Studio addresses rows by `buildTimelineElementKey`'s composite\n * `<sourceFile>#<domId>`, but everything audio in `@hyperframes/core` keys off\n * the live document: `resolveAudioGroups` collects `member.id`,\n * `resolveCarveSourceIds` goes through `getElementById`. Anything crossing into\n * that space — a group membership list, a carve source — has to be\n * converted here first; a composite key silently matches nothing.\n *\n * `null` for a row with no DOM id at all (selector-addressed elements): such an\n * element cannot be grouped, because `resolveAudioGroups` skips\n * members without an `id` and would build a group that is half there.\n */\nexport function runtimeAudioId(element: { domId?: string | null }): string | null {\n return element.domId || null;\n}\n\n/**\n * Timeline store key for a z-reorder entry built OUTSIDE the timeline\n * expansion (canvas context menu / LayersPanel), so the reorder commit can\n * update the store's zIndex synchronously. Matches buildTimelineElementKey's\n * stable branches (`sourceFile#domId`, else the selector-based key). Undefined\n * when the element has neither a DOM id nor a selector — the timeline's\n * fallback branch needs its own fallbackIndex, which these callers don't have,\n * so such an entry simply skips the synchronous store update.\n */\nexport function deriveTimelineStoreKey(params: {\n domId?: string;\n selector?: string;\n selectorIndex?: number;\n sourceFile?: string;\n}): string | undefined {\n if (!params.domId && !params.selector) return undefined;\n return buildTimelineElementKey({ id: \"\", fallbackIndex: 0, ...params });\n}\n\n/**\n * {@link deriveTimelineStoreKey} for a caller that already has a DOM id in\n * hand (e.g. one it just minted), so the undefined branch never applies.\n */\nexport function deriveTimelineStoreKeyForDomId(domId: string, sourceFile?: string): string {\n return deriveTimelineStoreKey({ domId, sourceFile })!;\n}\n\n// ---------------------------------------------------------------------------\n// DOM node querying\n// ---------------------------------------------------------------------------\n\nfunction getTimelineDomNodes(doc: Document): Element[] {\n const rootComp = doc.querySelector(\"[data-composition-id]\");\n return Array.from(doc.querySelectorAll(\"[data-start]\")).filter(\n (node) => node !== rootComp && !isTimelineIgnoredElement(node),\n );\n}\n\nfunction numbersNearlyEqual(a: number, b: number): boolean {\n return Math.abs(a - b) < 0.001;\n}\n\nconst MANIFEST_CLIP_ATTRS: ReadonlyArray<[string, (clip: ClipManifestClip) => number]> = [\n [\"data-start\", (clip) => clip.start],\n [\"data-duration\", (clip) => clip.duration],\n [\"data-track-index\", (clip) => clip.track],\n];\n\nfunction nodeMatchesClipTag(node: Element, clip: ClipManifestClip): boolean {\n return !clip.tagName || node.tagName.toLowerCase() === clip.tagName.toLowerCase();\n}\n\nfunction nodeMatchesManifestClip(node: Element, clip: ClipManifestClip): boolean {\n if (!nodeMatchesClipTag(node, clip)) return false;\n // An attribute only constrains the match when it parses to a finite number:\n // missing or garbled reads as \"unknown\", not \"mismatch\".\n return MANIFEST_CLIP_ATTRS.every(([attr, expected]) => {\n const actual = Number.parseFloat(node.getAttribute(attr) ?? \"\");\n return !Number.isFinite(actual) || numbersNearlyEqual(actual, expected(clip));\n });\n}\n\n/** Whether `node` sits in the composition the clip was read from, the chain the runtime records outermost first\n * (`resolveNearestCompositionContext` in core's runtime/timeline.ts). A clip without that scope accepts any node. */\nfunction nodeInClipScope(node: Element, clip: ClipManifestClip): boolean {\n const scope = clip.compositionAncestors;\n if (!scope) return true;\n const ids: string[] = [];\n for (let cursor = node.parentElement; cursor; cursor = cursor.parentElement) {\n const id = cursor.getAttribute(\"data-composition-id\");\n if (id) ids.unshift(id);\n }\n return ids.length === scope.length && ids.every((id, index) => id === scope[index]);\n}\n\n/** The first match in the clip's composition across `selectors`; a lone match stands only when none is in scope, as a\n * healed host can stale the clip's chain for a pass. An id can repeat in a sub-composition earlier in the document. */\nfunction findInClipScope(\n doc: Document,\n clip: ClipManifestClip,\n selectors: string[],\n): Element | null {\n let lone: Element | null = null;\n for (const selector of selectors) {\n const nodes = Array.from(doc.querySelectorAll(selector));\n const scoped = nodes.find((node) => nodeInClipScope(node, clip));\n if (scoped) return scoped;\n if (nodes.length === 1) lone ??= nodes[0];\n }\n return lone;\n}\n\nexport type PreviewTarget = Pick<TimelineElement, \"hfId\" | \"domId\" | \"id\" | \"sourceFile\">;\n\n/** Finds a row's preview element by `data-hf-id`, then id, preferring one in the row's own file: both repeat across\n * files. Indexes the document once, so a pass over every row costs one scan. */\nexport function previewElementFinder(\n doc: Document,\n selector = \"[data-hf-id], [id]\",\n): (target: PreviewTarget) => Element | null {\n const byKey = new Map<string, Element[]>();\n const add = (key: string, node: Element) => {\n const nodes = byKey.get(key);\n if (nodes) nodes.push(node);\n else byKey.set(key, [node]);\n };\n for (const node of doc.querySelectorAll(selector)) {\n const hfId = node.getAttribute(\"data-hf-id\");\n const id = node.getAttribute(\"id\");\n if (hfId) add(`hf:${hfId}`, node);\n if (id) add(`id:${id}`, node);\n }\n return (target) => {\n const matches = [\n ...((target.hfId && byKey.get(`hf:${target.hfId}`)) || []),\n ...(byKey.get(`id:${target.domId ?? target.id}`) ?? []),\n ];\n return (\n matches.find((node) => getTimelineElementSourceFile(node) === target.sourceFile) ??\n matches[0] ??\n null\n );\n };\n}\n\nexport function findClipElementById(doc: Document, clip: ClipManifestClip): Element | null {\n if (!clip.id) return null;\n const first = doc.getElementById(clip.id);\n if (!first || nodeInClipScope(first, clip)) return first;\n return findInClipScope(doc, clip, [`[id=\"${CSS.escape(clip.id)}\"]`]);\n}\n\nfunction findTimelineDomNode(doc: Document, clip: ClipManifestClip): Element | null {\n if (!clip.id) return null;\n const first = doc.getElementById(clip.id);\n if (first && nodeInClipScope(first, clip)) return first;\n const id = CSS.escape(clip.id);\n const byOtherKeys = [`[data-hf-id=\"${id}\"]`, `[data-composition-id=\"${id}\"]`, `.${id}`];\n return findInClipScope(doc, clip, first ? [`[id=\"${id}\"]`, ...byOtherKeys] : byOtherKeys);\n}\n\nexport function findTimelineDomNodeForClip(\n doc: Document,\n clip: ClipManifestClip,\n fallbackIndex: number,\n usedNodes = new Set<Element>(),\n getCandidates = () => getTimelineDomNodes(doc),\n): Element | null {\n const byIdentity = findTimelineDomNode(doc, clip);\n if (byIdentity && !usedNodes.has(byIdentity) && nodeMatchesClipTag(byIdentity, clip))\n return byIdentity;\n\n const candidates = getCandidates().filter((node) => !usedNodes.has(node));\n const exact = candidates.find((node) => nodeMatchesManifestClip(node, clip));\n if (exact) return exact;\n\n const positional = candidates[fallbackIndex];\n return positional && nodeMatchesClipTag(positional, clip) ? positional : null;\n}\n\n/** One synchronous hydration pass: snapshot only on a miss, never across reloads. */\nexport function createTimelineDomNodeResolver(doc: Document) {\n let candidates: Element[] | undefined;\n const usedNodes = new Set<Element>();\n const getCandidates = () => (candidates ??= getTimelineDomNodes(doc));\n return (clip: ClipManifestClip, index: number): Element | null => {\n const node = findTimelineDomNodeForClip(doc, clip, index, usedNodes, getCandidates);\n if (node) usedNodes.add(node);\n return node;\n };\n}\n","export function parseStoredVolume(text: string | null): number | undefined {\n const volume = Number.parseFloat(text ?? \"\");\n return Number.isFinite(volume) ? volume : undefined;\n}\n\nexport const elementVolume = (el: Element, media: Element) =>\n parseStoredVolume(el.getAttribute(\"data-volume\") ?? media.getAttribute(\"data-volume\"));\n","const PROJECT_HASH_PREFIX = \"#project/\";\n\nexport interface ProjectHashRoute {\n projectId: string;\n params: URLSearchParams;\n}\n\nconst WINDOWS_DRIVE_PREFIX = /^[a-z]:/i;\n\n/** Project names are single path segments, including when received from a hash or server. */\nexport function isValidProjectId(value: string): boolean {\n return (\n value.length > 0 &&\n value !== \".\" &&\n value !== \"..\" &&\n !WINDOWS_DRIVE_PREFIX.test(value) &&\n !value.includes(\"/\") &&\n !value.includes(\"\\\\\") &&\n !Array.from(value).some((char) => char.charCodeAt(0) < 32)\n );\n}\n\nfunction decodeHashProjectId(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n\nfunction normalizeHashParams(\n params?: URLSearchParams | Record<string, string | null | undefined>,\n): URLSearchParams {\n if (!params) return new URLSearchParams();\n if (params instanceof URLSearchParams) return params;\n\n const next = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (!key || value == null || value === \"\") continue;\n next.set(key, value);\n }\n return next;\n}\n\nexport function encodeProjectId(projectId: string): string {\n if (!isValidProjectId(projectId)) throw new Error(\"Invalid project ID\");\n return encodeURIComponent(projectId);\n}\n\nexport function buildProjectHash(\n projectId: string,\n params?: URLSearchParams | Record<string, string | null | undefined>,\n): string {\n const search = normalizeHashParams(params).toString();\n return `${PROJECT_HASH_PREFIX}${encodeProjectId(projectId)}${search ? `?${search}` : \"\"}`;\n}\n\nexport function parseProjectHashRoute(hash: string): ProjectHashRoute | null {\n if (!hash.startsWith(PROJECT_HASH_PREFIX)) return null;\n\n const route = hash.slice(PROJECT_HASH_PREFIX.length);\n const queryIndex = route.indexOf(\"?\");\n const encodedProjectId = queryIndex >= 0 ? route.slice(0, queryIndex) : route;\n if (!encodedProjectId || encodedProjectId.includes(\"/\")) return null;\n\n const projectId = decodeHashProjectId(encodedProjectId);\n if (!isValidProjectId(projectId)) return null;\n\n const rawParams = queryIndex >= 0 ? route.slice(queryIndex + 1) : \"\";\n return {\n projectId,\n params: new URLSearchParams(rawParams),\n };\n}\n\nexport function parseProjectIdFromHash(hash: string): string | null {\n return parseProjectHashRoute(hash)?.projectId ?? null;\n}\n\nexport function buildProjectApiPath(projectId: string, suffix = \"\"): string {\n const normalizedSuffix = suffix && !suffix.startsWith(\"/\") ? `/${suffix}` : suffix;\n return `/api/projects/${encodeProjectId(projectId)}${normalizedSuffix}`;\n}\n","export type StudioFeatureFlagEnv = Record<string, boolean | string | undefined>;\n\nconst TRUTHY_ENV_VALUES = new Set([\"1\", \"true\", \"yes\", \"on\", \"enabled\"]);\nconst FALSY_ENV_VALUES = new Set([\"0\", \"false\", \"no\", \"off\", \"disabled\"]);\n\nexport function resolveStudioBooleanEnvFlag(\n env: StudioFeatureFlagEnv,\n names: string[],\n fallback: boolean,\n): boolean {\n for (const name of names) {\n const value = env[name];\n if (typeof value === \"boolean\") return value;\n if (typeof value !== \"string\") continue;\n\n const normalized = value.trim().toLowerCase();\n if (!normalized) continue;\n if (TRUTHY_ENV_VALUES.has(normalized)) return true;\n if (FALSY_ENV_VALUES.has(normalized)) return false;\n }\n\n return fallback;\n}\n\n// `import.meta.env` is a Vite-only extension. In non-Vite ESM hosts\n// (Next.js / Turbopack, Node, jest in some configs) it's undefined,\n// and downstream `env[name]` reads would crash. Fall back to `{}` so\n// every flag resolves to its declared default outside Vite. Direct\n// property access keeps Vite's compile-time transform happy.\n//\n// When the studio is served as a pre-built SPA by the embedded Hono server,\n// `import.meta.env` values were baked at build time. The server injects\n// `window.__HF_STUDIO_ENV__` with any `VITE_STUDIO_*` env vars from the\n// user's shell, so runtime overrides take precedence over baked defaults.\nconst runtimeEnv =\n typeof window !== \"undefined\"\n ? ((window as Window & { __HF_STUDIO_ENV__?: StudioFeatureFlagEnv }).__HF_STUDIO_ENV__ ?? {})\n : {};\nconst env = { ...(import.meta.env ?? {}), ...runtimeEnv } as StudioFeatureFlagEnv;\n\n// Stage 7 SDK cutover — routes Studio edits through SDK dispatch instead of the\n// server patch/mutation routes. Default TRUE as of the flip release (spec:\n// 2026-09-17-studio-sdk-cutover-flip-design.md). Kill switch:\n// VITE_STUDIO_SDK_CUTOVER_ENABLED=false (works at runtime via __HF_STUDIO_ENV__).\nexport const STUDIO_SDK_CUTOVER_ENABLED = resolveStudioBooleanEnvFlag(\n env,\n [\"VITE_STUDIO_SDK_CUTOVER_ENABLED\"],\n true,\n);\n\n/**\n * Per-family selection. Unset = every family (the master alone enables all).\n * Set `VITE_STUDIO_SDK_CUTOVER_FAMILIES=dom,timing` to RESTRICT to a subset.\n */\nexport const STUDIO_SDK_CUTOVER_FAMILIES = resolveEnabledSdkFamilies(\n env,\n STUDIO_SDK_CUTOVER_ENABLED,\n);\n\n// Resolver-parity tripwire (telemetry-only, decoupled from cutover).\n// Runs the SDK resolver alongside any edit and emits sdk_resolver_shadow on\n// divergence. Default true; disable via VITE_STUDIO_SDK_RESOLVER_SHADOW_ENABLED=false.\n// Soak gate: retire once zero element_not_found divergences over a clean window.\nexport const STUDIO_SDK_RESOLVER_SHADOW_ENABLED = resolveStudioBooleanEnvFlag(\n env,\n [\"VITE_STUDIO_SDK_RESOLVER_SHADOW_ENABLED\"],\n true,\n);\n\n// Studio inspector redesign (\"Ledger, flat\" — design_handoff_studio_inspector):\n// flat identity header/footer/groups. Default true as of v0.7.59+ bug-fix pass\n// (right-aligned values, Stroke select-only, promote-badge overlap, Layout/\n// Style section gating); disable via VITE_STUDIO_FLAT_INSPECTOR_ENABLED=false\n// to fall back to the legacy panel.\nexport const STUDIO_FLAT_INSPECTOR_ENABLED = resolveStudioBooleanEnvFlag(\n env,\n [\"VITE_STUDIO_ENABLE_FLAT_INSPECTOR\", \"VITE_STUDIO_FLAT_INSPECTOR_ENABLED\"],\n true,\n);\n\n// A host whose mounted API authenticates with same-origin cookies sets this; studioApiFetch then sends them, and its\n// requests share the preview media's sockets again.\nexport const STUDIO_API_SAME_ORIGIN_CREDENTIALS = resolveStudioBooleanEnvFlag(\n env,\n [\"VITE_STUDIO_API_SAME_ORIGIN_CREDENTIALS\"],\n false,\n);\n\nimport { resolveEnabledSdkFamilies } from \"../../utils/sdkCutoverPolicy\";\n","export const STUDIO_SDK_OPERATION_FAMILIES = [\n \"dom\",\n \"timing\",\n \"gsap-animation\",\n \"gsap-keyframe\",\n \"lifecycle\",\n] as const;\n\nexport type StudioSdkOperationFamily = (typeof STUDIO_SDK_OPERATION_FAMILIES)[number];\n\ninterface StudioSdkFamilyStatus {\n owner: string;\n deadline: string;\n parityEvidence: string;\n graduated: boolean;\n}\n\nconst STUDIO_SDK_FAMILY_STATUS = {\n dom: {\n owner: \"studio-foundations\",\n deadline: \"2026-09-30\",\n parityEvidence: \"sdkCutoverParity.test.ts\",\n graduated: false,\n },\n timing: {\n owner: \"studio-foundations\",\n deadline: \"2026-10-15\",\n parityEvidence: \"sdkCutover.test.ts timing corpus\",\n graduated: false,\n },\n \"gsap-animation\": {\n owner: \"studio-foundations\",\n deadline: \"2026-10-31\",\n parityEvidence: \"sdkCutover.test.ts GSAP animation corpus\",\n graduated: false,\n },\n \"gsap-keyframe\": {\n owner: \"studio-foundations\",\n deadline: \"2026-11-15\",\n parityEvidence: \"sdkCutover.test.ts GSAP keyframe corpus\",\n graduated: false,\n },\n lifecycle: {\n owner: \"studio-foundations\",\n deadline: \"2026-11-30\",\n parityEvidence: \"sdkCutover.test.ts lifecycle corpus\",\n graduated: false,\n },\n} as const satisfies Record<StudioSdkOperationFamily, StudioSdkFamilyStatus>;\n\nexport function resolveEnabledSdkFamilies(\n env: Record<string, boolean | string | undefined>,\n masterEnabled: boolean,\n): ReadonlySet<StudioSdkOperationFamily> {\n if (!masterEnabled) return new Set();\n const raw = env[\"VITE_STUDIO_SDK_CUTOVER_FAMILIES\"];\n // Unset/blank = every family. The list exists to RESTRICT (kill switch per family).\n if (typeof raw !== \"string\" || raw.trim() === \"\") return new Set(STUDIO_SDK_OPERATION_FAMILIES);\n const requested = raw\n .split(\",\")\n .map((family) => family.trim())\n .filter(Boolean);\n const known = new Set<string>(STUDIO_SDK_OPERATION_FAMILIES);\n const unknown = requested.filter((family) => !known.has(family));\n if (unknown.length > 0) {\n throw new Error(`Unknown Studio SDK cutover families: ${unknown.join(\", \")}`);\n }\n return new Set(requested as StudioSdkOperationFamily[]);\n}\n\nexport function isSdkFamilyEnabled(\n masterEnabled: boolean,\n configured: ReadonlySet<StudioSdkOperationFamily> | undefined,\n family: StudioSdkOperationFamily,\n): boolean {\n // `undefined` preserves compatibility for isolated tests/embedders that mock\n // only the historical master flag. Production always supplies an explicit set.\n return masterEnabled && (configured?.has(family) ?? true);\n}\n\nexport function renderStudioSdkCutoverReport(): string {\n const rows = STUDIO_SDK_OPERATION_FAMILIES.map((family) => {\n const status = STUDIO_SDK_FAMILY_STATUS[family];\n return `| ${family} | ${status.owner} | ${status.deadline} | ${status.parityEvidence} | ${status.graduated ? \"yes\" : \"no\"} |`;\n });\n return [\n \"# Studio SDK cutover report\",\n \"\",\n \"Default: SDK persist ON for every family. Kill switches:\",\n \" `VITE_STUDIO_SDK_CUTOVER_ENABLED=false` (all families → server path)\",\n \" `VITE_STUDIO_SDK_CUTOVER_FAMILIES=dom,timing` (only listed families → SDK; rest → server)\",\n \"\",\n \"A family graduates only after zero unexplained resolver/serialization divergences over its agreed corpus and soak window.\",\n \"\",\n \"| Family | Owner | Deadline | Parity evidence | Graduated |\",\n \"| --- | --- | --- | --- | --- |\",\n ...rows,\n \"\",\n ].join(\"\\n\");\n}\n","import { STUDIO_API_SAME_ORIGIN_CREDENTIALS } from \"../components/editor/manualEditingAvailability\";\n\nconst LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\"]);\n\nfunction studioApiCredentials(): RequestCredentials {\n if (STUDIO_API_SAME_ORIGIN_CREDENTIALS) return \"same-origin\";\n const host = globalThis.location?.hostname;\n return !host || LOOPBACK_HOSTS.has(host) ? \"omit\" : \"same-origin\";\n}\n\nexport function studioApiFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n return globalThis.fetch(input, { ...init, credentials: studioApiCredentials() });\n}\n"],"mappings":"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","names":["isHtmlElement","isHtmlElement","isHtmlElement","isHtmlElement","env","env"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ui/HyperframesLogo.tsx"],"sourcesContent":["export function HyperframesLogo() {\n // Full logo from logo-dark.svg (263×79): heygen label + gradient mark + hyperframes wordmark.\n // The wordmark paths take the text colour, so the logo reads in both themes.\n const height = 28;\n const width = Math.round(height * (263 / 79));\n return (\n <svg\n width={width}\n height={height}\n viewBox=\"0 0 263 79\"\n fill=\"none\"\n className=\"text-text-0\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-label=\"Hyperframes\"\n >\n <defs>\n <linearGradient\n id=\"hf-g0\"\n x1=\"225.869\"\n y1=\"0\"\n x2=\"222.845\"\n y2=\"37.482\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop stopColor=\"var(--color-brand-gradient-from)\" />\n <stop offset=\"1\" stopColor=\"var(--color-brand-gradient-to)\" />\n </linearGradient>\n <linearGradient\n id=\"hf-g1\"\n x1=\"230.87\"\n y1=\"39\"\n x2=\"244.661\"\n y2=\"6.303\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop stopColor=\"var(--color-brand-gradient-from)\" />\n <stop offset=\"1\" stopColor=\"var(--color-brand-gradient-to)\" />\n </linearGradient>\n </defs>\n {/* heygen label */}\n <path\n d=\"M0 16.6738H4.96V23.3838H11.53V16.6738H16.49V35.4538H11.53V27.6738H4.96V35.4538H0V16.6738Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M17.8899 28.0137C17.8899 23.4237 21.2399 20.0237 25.7999 20.0237C30.0099 20.0237 32.9399 23.0837 32.9399 27.5637C32.9399 28.2037 32.8599 28.8237 32.8299 29.3337H22.6099C23.0399 31.1337 24.6199 32.1237 27.1399 32.1237C28.7199 32.1237 30.2199 31.7237 31.2999 31.0237V34.6737C30.1699 35.3937 28.2999 35.8537 26.3599 35.8537C21.2599 35.8537 17.8799 32.6037 17.8799 28.0237L17.8899 28.0137ZM28.5699 26.1937C28.4899 24.5337 27.3899 23.5637 25.7499 23.5637C24.1099 23.5637 22.9599 24.5337 22.6099 26.1937H28.5699Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M37.85 33.8638L32 20.4238H37.29L40.46 28.1538L43.6 20.4238H48.48L40.33 39.5738H35.26L37.86 33.8638H37.85Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M48.1797 26.1138C48.1797 20.4238 52.7097 16.2438 58.9397 16.2438C61.2997 16.2438 63.5297 16.8038 64.8197 17.7238V21.9338C63.5597 20.9138 61.6797 20.2938 59.7497 20.2938C55.7797 20.2938 53.2597 22.6238 53.2597 26.1438C53.2597 29.6638 55.5697 31.8838 58.8897 31.8838C59.6397 31.8838 60.4997 31.7538 61.1997 31.5038V27.8838H57.4697V24.2338H65.5197V33.7038C63.6697 35.0938 61.1997 35.8738 58.5997 35.8738C52.5397 35.8738 48.1897 31.7438 48.1897 26.1138H48.1797Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M66.6604 28.0137C66.6604 23.4237 70.0104 20.0237 74.5704 20.0237C78.7804 20.0237 81.7104 23.0837 81.7104 27.5637C81.7104 28.2037 81.6304 28.8237 81.6004 29.3337H71.3804C71.8104 31.1337 73.3904 32.1237 75.9104 32.1237C77.4904 32.1237 78.9904 31.7237 80.0704 31.0237V34.6737C78.9404 35.3937 77.0704 35.8537 75.1304 35.8537C70.0304 35.8537 66.6504 32.6037 66.6504 28.0237L66.6604 28.0137ZM77.3404 26.1937C77.2604 24.5337 76.1604 23.5637 74.5204 23.5637C72.8804 23.5637 71.7304 24.5337 71.3804 26.1937H77.3404Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M82.9688 20.4238H87.8488V22.4138C88.7588 20.9638 90.3488 20.1038 92.3288 20.1038C95.4988 20.1038 97.3988 22.3338 97.3988 25.8138V35.4438H92.5188V26.8638C92.5188 25.0438 91.8188 24.1838 90.4788 24.1838C88.9488 24.1838 87.8488 25.3638 87.8488 27.2638V35.4438H82.9688V20.4238Z\"\n fill=\"currentColor\"\n />\n {/* gradient icon mark */}\n <path\n d=\"M195.219 26.1937L213.529 38.9937C216.009 40.7237 220.239 38.7637 221.009 35.5337L228.419 4.33374C229.189 1.10374 225.879 -0.856262 222.589 0.873738L198.199 13.6737C192.649 16.5837 191.059 23.2837 195.219 26.1937Z\"\n fill=\"url(#hf-g0)\"\n />\n <path\n d=\"M256.97 25.9638L232.58 38.7638C229.28 40.4938 225.98 38.5338 226.75 35.3038L234.16 4.10376C234.93 0.873757 239.16 -1.08624 241.64 0.643757L259.95 13.4438C264.12 16.3538 262.52 23.0538 256.97 25.9638Z\"\n fill=\"url(#hf-g1)\"\n />\n {/* hyperframes wordmark */}\n <path\n d=\"M0 71.9996V42.7256H7.7367V53.1806H17.9826V42.7256H25.7193V71.9996H17.9826V59.8718H7.7367V71.9996H0Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M31.9606 78.4405L36.0171 69.5329L26.9004 48.5811H35.1389L40.0737 60.6252L44.9666 48.5811H52.5779L39.8646 78.4405H31.9606Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M53.3711 78.4404V48.5809H60.9823V52.052C62.446 49.501 65.0807 48.0791 68.3008 48.0791C74.3647 48.0791 78.9649 53.3066 78.9649 60.2487C78.9649 67.2745 74.3229 72.4602 68.259 72.4602C65.0807 72.4602 62.446 71.1637 60.9823 68.78V78.4404H53.3711ZM66.1262 66.1872C69.2627 66.1872 71.3119 63.7616 71.3119 60.2905C71.3119 56.8195 69.2627 54.4357 66.1262 54.4357C62.7388 54.4357 60.9823 57.2795 60.9823 59.7051V60.9178C60.9823 63.3434 62.7388 66.1872 66.1262 66.1872Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M93.4397 72.6269C85.4939 72.6269 80.2246 67.5667 80.2246 60.4155C80.2246 53.2643 85.4521 47.9531 92.5615 47.9531C99.1273 47.9531 103.686 52.7206 103.686 59.7045C103.686 60.7082 103.56 61.6701 103.518 62.4647H87.5849C88.2541 65.2666 90.7214 66.8139 94.6525 66.8139C97.1199 66.8139 99.4618 66.1866 101.135 65.0993V70.7868C99.3782 71.916 96.4508 72.6269 93.4397 72.6269ZM87.5849 57.5717H96.869C96.7435 54.9789 95.0289 53.4734 92.4779 53.4734C89.9687 53.4734 88.1286 54.9789 87.5849 57.5717Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M105.645 72V48.5808H113.214V52.9719C114.218 50.0445 116.183 48.2881 118.692 48.2881C119.361 48.2881 119.989 48.4135 120.407 48.6645V55.8993C119.822 55.5648 119.111 55.4393 118.274 55.4393C115.138 55.4393 113.256 57.6558 113.256 61.2941V72H105.645Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M122.643 71.9996V42.7256H139.371V49.124H130.379V54.477H138.911V60.5827H130.379V71.9996H122.643Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M141.258 72V48.5808H148.827V52.9719C149.831 50.0445 151.796 48.2881 154.306 48.2881C154.975 48.2881 155.602 48.4135 156.02 48.6645V55.8993C155.435 55.5648 154.724 55.4393 153.887 55.4393C150.751 55.4393 148.869 57.6558 148.869 61.2941V72H141.258Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M167.26 72.4602C161.154 72.4602 156.596 67.2745 156.596 60.3324C156.596 53.3066 161.196 48.0791 167.302 48.0791C170.438 48.0791 173.031 49.4173 174.536 51.8429V48.5809H182.148V72.0001H174.536V68.4873C173.031 71.0801 170.438 72.4602 167.26 72.4602ZM169.393 66.1872C172.78 66.1872 174.536 63.3434 174.536 60.876V59.6632C174.536 57.2377 172.78 54.4357 169.393 54.4357C166.298 54.4357 164.207 56.7777 164.207 60.2905C164.207 63.7616 166.298 66.1872 169.393 66.1872Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M184.998 72.0001V48.5809H192.609V51.6756C193.989 49.4173 196.373 48.0791 199.426 48.0791C202.521 48.0791 204.779 49.5428 206.075 52.052C207.497 49.5846 210.132 48.0791 213.352 48.0791C218.245 48.0791 221.214 51.592 221.214 57.0286V72.0001H213.603V58.5341C213.603 55.774 212.557 54.4357 210.634 54.4357C208.459 54.4357 206.912 56.234 206.912 59.0778V72.0001H199.3V58.5341C199.3 55.774 198.255 54.4357 196.373 54.4357C194.157 54.4357 192.609 56.234 192.609 59.0778V72.0001H184.998Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M236.338 72.6269C228.392 72.6269 223.123 67.5667 223.123 60.4155C223.123 53.2643 228.351 47.9531 235.46 47.9531C242.026 47.9531 246.584 52.7206 246.584 59.7045C246.584 60.7082 246.459 61.6701 246.417 62.4647H230.483C231.152 65.2666 233.62 66.8139 237.551 66.8139C240.018 66.8139 242.36 66.1866 244.033 65.0993V70.7868C242.277 71.916 239.349 72.6269 236.338 72.6269ZM230.483 57.5717H239.767C239.642 54.9789 237.927 53.4734 235.376 53.4734C232.867 53.4734 231.027 54.9789 230.483 57.5717Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M252.115 72.502C250.192 72.502 248.268 72.0838 246.93 71.3728V65.6853C247.808 66.3126 248.937 66.689 250.066 66.689C251.739 66.689 252.784 65.8526 252.784 64.5562C252.784 63.8452 252.492 63.0925 251.655 62.0888L249.899 59.956C248.728 58.4923 248.226 56.9031 248.226 55.2721C248.226 51.0065 251.864 48.0791 256.883 48.0791C258.723 48.0791 260.438 48.4555 261.65 49.0828V54.7703C260.898 54.2266 259.768 53.8503 258.723 53.8503C257.092 53.8503 256.046 54.6867 256.046 55.8994C256.046 56.6522 256.423 57.405 257.259 58.4086L258.974 60.4996C260.187 62.047 260.73 63.5943 260.73 65.2671C260.73 69.5746 257.05 72.502 252.115 72.502Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n"],"mappings":"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","names":[]}
|