@hyperframes/studio 0.8.143 → 0.8.145
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-BXSuksFh.js → hyperframes-player-DZ5JrMDg.js} +3 -3
- package/dist/assets/{index-FgyO_5Kv.js → index-BOs6C0aZ.js} +1 -1
- package/dist/assets/{index-BgOVCqjo.js → index-BqFRhNZa.js} +1 -1
- package/dist/assets/{index-J7jpL4pj.js → index-D8W0a0Z9.js} +149 -149
- package/dist/{chunk-TFLU2MGI.js → chunk-6JY3MTIX.js} +108 -2
- package/dist/chunk-6JY3MTIX.js.map +1 -0
- package/dist/{chunk-H2DUOXTF.js → chunk-NZPJUZKT.js} +100 -4
- package/dist/chunk-NZPJUZKT.js.map +1 -0
- package/dist/{chunk-UYWON5AX.js → chunk-TP6D3U37.js} +7 -100
- package/dist/chunk-TP6D3U37.js.map +1 -0
- package/dist/{chunk-LOVBLSMR.js → chunk-Y2OHHNM2.js} +35 -19
- package/dist/chunk-Y2OHHNM2.js.map +1 -0
- package/dist/{domEditingLayers-KBTPQKGA.js → domEditingLayers-PTP2ICGM.js} +3 -3
- package/dist/index.d.ts +8 -5
- package/dist/index.html +1 -1
- package/dist/index.js +545 -495
- package/dist/index.js.map +1 -1
- package/dist/player.js +3 -3
- package/dist/ui.d.ts +4 -5
- package/dist/ui.js +1 -1
- package/package.json +8 -8
- package/src/components/StudioLeftPanels.tsx +2 -2
- package/src/components/editor/DomEditSelectionChrome.test.tsx +103 -0
- package/src/components/editor/DomEditSelectionChrome.tsx +42 -16
- package/src/components/editor/LayersPanel.test.ts +4 -4
- package/src/components/editor/LayersPanel.tsx +2 -2
- package/src/components/editor/TopologyLens.test.tsx +5 -4
- package/src/components/editor/anchoredResizeCommitFeedsOffset.test.ts +36 -0
- package/src/components/editor/domEditOverlayGestures.ts +1 -0
- package/src/components/editor/domEditOverlayStartGesture.ts +5 -0
- package/src/components/editor/domEditResizeLocal.test.ts +81 -1
- package/src/components/editor/domEditResizeLocal.ts +27 -3
- package/src/components/editor/domEditingLayers.ts +4 -1
- package/src/components/editor/domEditingTextFields.test.ts +18 -0
- package/src/components/editor/manualEditsDom.ts +12 -12
- package/src/components/editor/previewGestureStarts.ts +14 -5
- package/src/components/editor/resizeDraft.ts +13 -4
- package/src/components/editor/useDomEditOverlayGestures.ts +5 -3
- package/src/components/renders/GpuEncodingToggle.tsx +28 -0
- package/src/components/renders/RenderQueue.test.tsx +20 -2
- package/src/components/renders/RenderQueue.tsx +13 -1
- package/src/components/renders/RenderQueuePanel.tsx +2 -1
- package/src/components/renders/renderSettings.ts +5 -2
- package/src/components/renders/useRenderQueue.ts +3 -0
- package/src/components/renders/useRenderQueueComposition.test.tsx +12 -0
- package/src/components/ui/Menu.test.tsx +67 -5
- package/src/components/ui/Menu.tsx +21 -4
- package/src/components/ui/Popover.tsx +11 -5
- package/src/hooks/gsapResizeIntercept.test.ts +46 -11
- package/src/hooks/gsapResizeIntercept.ts +25 -20
- package/src/hooks/useConsoleErrorCapture.test.tsx +21 -2
- package/src/hooks/useConsoleErrorCapture.ts +3 -2
- package/src/hooks/useThumbnailStripSize.test.tsx +123 -0
- package/src/hooks/useThumbnailStripSize.ts +19 -8
- package/src/index.ts +1 -0
- package/src/player/components/CompositionThumbnail.test.ts +3 -0
- package/src/player/components/ImageThumbnail.test.tsx +4 -1
- package/src/player/components/Player.test.ts +44 -0
- package/src/player/components/Player.tsx +11 -0
- package/src/player/components/VideoThumbnail.test.tsx +13 -2
- package/src/player/hooks/timelineSyncHydration.ts +2 -1
- package/src/player/lib/playbackTypes.ts +1 -0
- package/src/player/sceneSwap.test.ts +27 -1
- package/src/player/sceneSwap.ts +16 -2
- package/src/utils/authoredSource.test.ts +25 -0
- package/src/utils/authoredSource.ts +3 -5
- package/src/utils/rounding.ts +7 -0
- package/dist/chunk-H2DUOXTF.js.map +0 -1
- package/dist/chunk-LOVBLSMR.js.map +0 -1
- package/dist/chunk-TFLU2MGI.js.map +0 -1
- package/dist/chunk-UYWON5AX.js.map +0 -1
- /package/dist/{domEditingLayers-KBTPQKGA.js.map → domEditingLayers-PTP2ICGM.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/editor/domEditingLayers.ts","../src/components/editor/probeSourceElement.ts","../src/components/editor/domEditingGroups.ts","../src/components/editor/domEditingElement.ts","../src/components/editor/domEditingRootLayer.ts","../src/components/editor/domEditLayerWalkCache.ts"],"sourcesContent":["import { PREVIEW_ONLY_ATTRS } from \"@hyperframes/core/studio-preview-mark\";\nimport { knownSourceAnswer, probeSourceElement, type ProbeTarget } from \"./probeSourceElement\";\nimport { isAudibleVideoNode } from \"../../player/lib/timelineElementHelpers\";\nimport type { PatchOperation } from \"../../utils/sourcePatcher\";\nimport {\n resolveEditingAffordances,\n resolveEditingSections,\n type EditableElementFacts,\n} from \"@hyperframes/core/editing\";\nimport { groupScopedLayerRoots, resolveGroupCapture } from \"./domEditingGroups\";\nimport type {\n DomEditCapabilities,\n DomEditContextOptions,\n DomEditLayerItem,\n DomEditSelection,\n DomEditTextField,\n} from \"./domEditingTypes\";\nimport {\n buildElementLabel,\n buildStableSelector,\n findClosestByAttribute,\n getCuratedComputedStyles,\n getDataAttributes,\n getInlineStyles,\n getSelectorIndex,\n getSourceFileForElement,\n isEditableTextLeaf,\n isHtmlElement,\n} from \"./domEditingDom\";\nimport {\n findElementForSelection,\n getSelectionCandidate,\n isDomLayerElement,\n} from \"./domEditingElement\";\nimport { isCompositionRootLayer } from \"./domEditingRootLayer\";\nimport { withSelectorIndexPass } from \"../../utils/sourceScopedSelectorIndex\";\nimport { type DomEditLayerWalkCache, readDomEditLayerWalkEntry } from \"./domEditLayerWalkCache\";\n\nfunction sameTagChildIndex(el: HTMLElement): number {\n let index = 0;\n let sibling = el.previousElementSibling;\n while (sibling) {\n if (sibling.tagName === el.tagName) index += 1;\n sibling = sibling.previousElementSibling;\n }\n return index;\n}\n\nfunction getTextFieldLabel(\n _tagName: string,\n index: number,\n total: number,\n source: \"self\" | \"child\",\n): string {\n if (source === \"self\" || total === 1) return \"Content\";\n return `Text ${index + 1}`;\n}\n\nconst NOT_COPIED_ATTRS = new Set<string>([\"style\", ...PREVIEW_ONLY_ATTRS]);\n\nfunction buildTextField(\n el: HTMLElement,\n index: number,\n total: number,\n source: \"self\" | \"child\",\n sourceChildIndex?: number,\n): DomEditTextField {\n const tagName = el.tagName.toLowerCase();\n const key = el.getAttribute(\"data-hf-text-key\") ?? `${source}:${index}:${tagName}`;\n return {\n key,\n label: getTextFieldLabel(tagName, index, total, source),\n value: el.textContent ?? \"\",\n tagName,\n attributes: Array.from(el.attributes)\n .filter((attribute) => !NOT_COPIED_ATTRS.has(attribute.name))\n .map((attribute) => ({\n name: attribute.name,\n value: attribute.value,\n })),\n inlineStyles: getInlineStyles(el),\n computedStyles: getCuratedComputedStyles(el),\n source,\n ...(sourceChildIndex == null ? {} : { sourceChildIndex }),\n };\n}\n\n// fallow-ignore-next-line complexity\nexport function collectDomEditTextFields(el: HTMLElement): DomEditTextField[] {\n const childElements = Array.from(el.children).filter(isHtmlElement).filter(isEditableTextLeaf);\n\n if (childElements.length > 0) {\n const hasMixedContent = Array.from(el.childNodes).some(\n (node) => node.nodeType === 3 && node.textContent?.trim(),\n );\n\n if (hasMixedContent) {\n const fields: DomEditTextField[] = [];\n let childIdx = 0;\n for (const node of el.childNodes) {\n if (node.nodeType === 3) {\n const text = node.textContent ?? \"\";\n if (!text.trim()) continue;\n fields.push({\n key: `text-node:${childIdx}`,\n label: `Text ${childIdx + 1}`,\n value: text,\n tagName: \"#text\",\n attributes: [],\n inlineStyles: {},\n computedStyles: {},\n source: \"text-node\",\n });\n childIdx++;\n } else if (isHtmlElement(node) && isEditableTextLeaf(node)) {\n fields.push(\n buildTextField(node, childIdx, childElements.length, \"child\", sameTagChildIndex(node)),\n );\n childIdx++;\n }\n }\n return fields;\n }\n\n return childElements.map((child, index) =>\n buildTextField(child, index, childElements.length, \"child\", sameTagChildIndex(child)),\n );\n }\n\n if (isEditableTextLeaf(el)) {\n return [buildTextField(el, 0, 1, \"self\")];\n }\n\n return [];\n}\n\nfunction escapeHtmlText(value: string): string {\n return value.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\");\n}\n\nfunction serializeTextFieldStyle(field: DomEditTextField): string {\n const entries = Object.entries(field.inlineStyles).filter(([, value]) => Boolean(value));\n if (entries.length === 0) return \"\";\n return entries.map(([key, value]) => `${key}: ${value}`).join(\"; \");\n}\n\nexport function serializeDomEditTextFields(fields: DomEditTextField[]): string {\n return fields\n .filter((field) => field.source === \"child\" || field.source === \"text-node\")\n .map((field) => {\n if (field.source === \"text-node\") {\n return escapeHtmlText(field.value);\n }\n const attrs = [\n ...field.attributes.filter((attribute) => attribute.name !== \"data-hf-text-key\"),\n { name: \"data-hf-text-key\", value: field.key },\n ]\n .map((attribute) => ` ${attribute.name}=\"${attribute.value.replace(/\"/g, \""\")}\"`)\n .join(\"\");\n const style = serializeTextFieldStyle(field);\n const styleAttr = style ? ` style=\"${style.replace(/\"/g, \""\")}\"` : \"\";\n return `<${field.tagName}${attrs}${styleAttr}>${escapeHtmlText(field.value)}</${field.tagName}>`;\n })\n .join(\"\");\n}\n\nexport function buildDefaultDomEditTextField(base?: Partial<DomEditTextField>): DomEditTextField {\n return {\n key: `child:new:${Date.now()}`,\n label: \"Text\",\n value: \"New text\",\n tagName: \"span\",\n attributes: [],\n inlineStyles: {\n \"font-family\": base?.computedStyles?.[\"font-family\"] ?? \"inherit\",\n \"font-size\": base?.computedStyles?.[\"font-size\"] ?? \"16px\",\n \"font-weight\": base?.computedStyles?.[\"font-weight\"] ?? \"400\",\n color: base?.computedStyles?.color ?? \"inherit\",\n },\n computedStyles: {},\n source: \"child\",\n };\n}\n\nexport interface DomEditChildLocator {\n childSelector: string;\n childIndex: number;\n}\n\nexport function buildTextFieldChildLocator(\n fields: DomEditTextField[],\n fieldKey: string,\n): DomEditChildLocator | null {\n const field = fields.find((candidate) => candidate.key === fieldKey);\n if (!field || field.source !== \"child\") return null;\n // sourceChildIndex is only absent for a synthetic field that was never read\n // back from the live DOM (e.g. one built by buildDefaultDomEditTextField).\n // Guessing its position by counting same-tag \"child\" fields elsewhere in\n // the array is unreliable and can silently locate the wrong element — fail\n // closed instead so the caller falls back to the unsupported-structure path.\n if (field.sourceChildIndex == null) return null;\n\n return {\n childSelector: `:scope > ${field.tagName}`,\n childIndex: field.sourceChildIndex,\n };\n}\n\nfunction capabilityFacts(geometry: {\n hasStableTarget: boolean;\n tag: string;\n inlineStyles: Record<string, string>;\n computedStyles: Record<string, string>;\n isCompositionHost: boolean;\n isCompositionRoot: boolean;\n isInsideLockedComposition: boolean;\n isMasterView: boolean;\n existsInSource: boolean;\n}): EditableElementFacts {\n return {\n ...geometry,\n hasEditableText: false,\n hasTimingStart: false,\n animationCount: 0,\n };\n}\n\n/**\n * Build core EditableElementFacts from a fully-resolved DomEditSelection.\n * `animationCount` is supplied by the caller because live GSAP tweens arrive on\n * a separate channel (the PropertyPanel `gsapAnimations` prop), not on the\n * selection — `selection.gsapAnimations` is never populated.\n */\nexport function domEditSelectionToFacts(\n selection: DomEditSelection,\n animationCount = selection.gsapAnimations?.length ?? 0,\n): EditableElementFacts {\n return {\n hasStableTarget: Boolean(selection.selector || selection.hfId),\n tag: selection.tagName,\n inlineStyles: selection.inlineStyles,\n computedStyles: selection.computedStyles,\n isCompositionHost: selection.isCompositionHost,\n isCompositionRoot: false,\n isInsideLockedComposition: selection.isInsideLockedComposition,\n isMasterView: false,\n existsInSource: true,\n hasEditableText: selection.textFields.length > 0,\n hasTimingStart: selection.dataAttributes.start != null,\n animationCount,\n hasAudio: isAudibleVideoNode(selection.element),\n };\n}\n\n/**\n * Resolve DOM edit capabilities for a given element.\n * Thin wrapper over core resolveEditingAffordances — kept for backward\n * compatibility (tests and the barrel import this signature directly).\n */\nexport function resolveDomEditCapabilities(args: {\n selector?: string;\n hfId?: string;\n tagName?: string;\n inlineStyles: Record<string, string>;\n computedStyles: Record<string, string>;\n isCompositionHost: boolean;\n isCompositionRoot?: boolean;\n isInsideLockedComposition: boolean;\n isMasterView: boolean;\n existsInSource?: boolean;\n}): DomEditCapabilities {\n return resolveEditingAffordances(\n capabilityFacts({\n hasStableTarget: Boolean(args.selector || args.hfId),\n tag: (args.tagName ?? \"div\").toLowerCase(),\n inlineStyles: args.inlineStyles,\n computedStyles: args.computedStyles,\n isCompositionHost: args.isCompositionHost,\n isCompositionRoot: args.isCompositionRoot ?? false,\n isInsideLockedComposition: args.isInsideLockedComposition ?? false,\n isMasterView: args.isMasterView,\n existsInSource: args.existsInSource ?? true,\n }),\n ).capabilities;\n}\n\n// fallow-ignore-next-line complexity\nexport async function resolveDomEditSelection(\n startEl: HTMLElement | null,\n options: DomEditContextOptions & {\n projectId?: string | null;\n skipSourceProbe?: boolean;\n exactTarget?: boolean;\n previous?: DomEditSelection | null;\n },\n): Promise<DomEditSelection | null> {\n if (!startEl) return null;\n const doc = startEl.ownerDocument;\n\n let capture = options.exactTarget\n ? ({ kind: \"unit\", element: startEl } as const)\n : resolveGroupCapture(startEl, options.activeGroupElement ?? null);\n if (capture.kind === \"out-of-scope\") {\n // Drill-in is non-sticky: clicking/hovering OUTSIDE the drilled-into group\n // exits it and resolves the target normally, rather than selecting nothing\n // (which felt like \"can't select anything\" once you'd drilled in).\n capture = resolveGroupCapture(startEl, null);\n }\n let current: HTMLElement | null =\n capture.kind === \"unit\" ? capture.element : getSelectionCandidate(startEl, options);\n while (current && current !== doc.body && current !== doc.documentElement) {\n const selector = buildStableSelector(current);\n const hfId = readHfId(current);\n if (!selector && !hfId) {\n current = current.parentElement;\n continue;\n }\n\n const { sourceFile, compositionPath } = getSourceFileForElement(\n current,\n options.activeCompositionPath,\n );\n const selectorIndex = selector\n ? getSelectorIndex(doc, current, selector, sourceFile, options.activeCompositionPath)\n : undefined;\n const compositionSrc =\n current.getAttribute(\"data-composition-src\") ??\n current.getAttribute(\"data-composition-file\") ??\n undefined;\n const inlineStyles = getInlineStyles(current);\n const computedStyles = getCuratedComputedStyles(current);\n const isCompositionRoot =\n (current.hasAttribute(\"data-composition-id\") && !compositionSrc) ||\n isCompositionRootLayer(current, doc, computedStyles);\n const textFields = collectDomEditTextFields(current);\n const isInsideLocked = Boolean(findClosestByAttribute(current, [\"data-timeline-locked\"]));\n const probeTarget: ProbeTarget = {};\n if (current.id) probeTarget.id = current.id;\n if (hfId) probeTarget.hfId = hfId;\n if (selector) probeTarget.selector = selector;\n if (selectorIndex != null) probeTarget.selectorIndex = selectorIndex;\n let existsInSource = knownSourceAnswer(options.previous, current, sourceFile, probeTarget);\n const probe = existsInSource === undefined && !options.skipSourceProbe;\n if (probe && options.projectId && (current.id || selector || hfId)) {\n existsInSource = await probeSourceElement(options.projectId, sourceFile, probeTarget);\n }\n const capabilities = resolveEditingAffordances(\n capabilityFacts({\n hasStableTarget: Boolean(selector || hfId),\n tag: current.tagName.toLowerCase(),\n inlineStyles,\n computedStyles,\n isCompositionHost: Boolean(compositionSrc),\n isCompositionRoot,\n isInsideLockedComposition: isInsideLocked,\n isMasterView: options.isMasterView,\n existsInSource: existsInSource ?? true,\n }),\n ).capabilities;\n const rect = current.getBoundingClientRect();\n\n return {\n element: current,\n id: current.id || undefined,\n hfId,\n selector,\n selectorIndex,\n sourceFile,\n compositionPath,\n compositionSrc,\n isCompositionHost: Boolean(compositionSrc),\n isInsideLockedComposition: isInsideLocked,\n label: buildElementLabel(current),\n tagName: current.tagName.toLowerCase(),\n boundingBox: {\n x: rect.left,\n y: rect.top,\n width: rect.width,\n height: rect.height,\n },\n textContent: current.textContent?.trim() || null,\n dataAttributes: getDataAttributes(current),\n inlineStyles,\n computedStyles,\n textFields,\n capabilities,\n existsInSource,\n };\n }\n\n return null;\n}\n\nexport async function refreshDomEditSelection(\n selection: DomEditSelection,\n activeCompositionPath: string | null,\n): Promise<DomEditSelection | null> {\n const doc = selection.element.ownerDocument;\n const nextElement = findElementForSelection(doc, selection, activeCompositionPath);\n return nextElement\n ? resolveDomEditSelection(nextElement, {\n activeCompositionPath,\n isMasterView: !activeCompositionPath || activeCompositionPath === \"index.html\",\n })\n : null;\n}\n\n// ─── Layer items ─────────────────────────────────────────────────────────────\n\nexport function getDomEditLayerKey(\n target: Pick<DomEditSelection, \"id\" | \"selector\" | \"selectorIndex\" | \"sourceFile\">,\n): string {\n const selectorIndex = target.selectorIndex ?? 0;\n return `${target.sourceFile}:${target.id ?? target.selector ?? \"layer\"}:${selectorIndex}`;\n}\n\nexport function countDomEditChildLayers(\n root: HTMLElement | null | undefined,\n options: DomEditContextOptions,\n maxCount = 99,\n): number {\n if (!root) return 0;\n\n let count = 0;\n const visit = (el: HTMLElement) => {\n for (const child of Array.from(el.children)) {\n if (!isHtmlElement(child)) continue;\n if (isDomLayerElement(child)) {\n count += 1;\n if (count >= maxCount) return;\n }\n visit(child);\n if (count >= maxCount) return;\n }\n };\n\n visit(root);\n return count;\n}\n\n// Every editable element under `root`, in document order. `maxItems` is a\n// caller's rendering budget, not a property of the document: hit-testing\n// callers (marquee, off-canvas indicators) must see all of it, and sharing a\n// truncated list left everything past the cut unselectable however far you drag.\nexport function collectDomEditLayerItems(\n root: HTMLElement | null | undefined,\n options: DomEditContextOptions,\n maxItems = Number.POSITIVE_INFINITY,\n cache?: DomEditLayerWalkCache,\n): DomEditLayerItem[] {\n if (!root) return [];\n cache?.beginWalk(options.activeCompositionPath);\n\n const items: DomEditLayerItem[] = [];\n // fallow-ignore-next-line complexity\n const visit = (el: HTMLElement, depth: number) => {\n if (items.length >= maxItems) return;\n\n const entry = readDomEditLayerWalkEntry(el, options.activeCompositionPath, cache);\n if (entry) {\n const { target } = entry;\n items.push({\n key: getDomEditLayerKey(target),\n element: el,\n label: entry.label,\n tagName: el.tagName.toLowerCase(),\n depth,\n childCount: entry.childCount,\n id: target.id ?? undefined,\n hfId: target.hfId ?? undefined,\n selector: target.selector ?? undefined,\n selectorIndex: target.selectorIndex,\n sourceFile: target.sourceFile,\n });\n }\n\n const nextDepth = entry ? depth + 1 : depth;\n for (const child of Array.from(el.children)) {\n if (!isHtmlElement(child)) continue;\n visit(child, nextDepth);\n if (items.length >= maxItems) return;\n }\n };\n\n // Every item resolves its selector's occurrence index, and unshared that is a\n // whole-document query per element — quadratic once a composition repeats a\n // card or tile class. The walk is one synchronous read of a document it does\n // not mutate, so one index per selector serves the whole of it. The pass lives\n // here rather than in each caller because this function owns the loop.\n withSelectorIndexPass(root.ownerDocument, () => {\n // Drilled into a group → show only its members; otherwise the whole tree.\n for (const el of groupScopedLayerRoots(root, options.activeGroupElement ?? null)) visit(el, 0);\n });\n return items;\n}\n\nexport function liveLayerElement(\n layer: DomEditLayerItem,\n doc: Document | null | undefined,\n activeCompositionPath: string | null,\n): HTMLElement {\n if (layer.element.isConnected || !doc) return layer.element;\n return findElementForSelection(doc, layer, activeCompositionPath) ?? layer.element;\n}\n\n// ─── Patch operations ────────────────────────────────────────────────────────\n\nexport function buildDomEditStylePatchOperation(\n property: string,\n value: string | null,\n childLocator?: DomEditChildLocator,\n): PatchOperation {\n return {\n type: \"inline-style\",\n property,\n value,\n ...childLocator,\n };\n}\n\nexport function buildDomEditTextPatchOperation(\n value: string,\n childLocator?: DomEditChildLocator,\n): PatchOperation {\n return { type: \"text-content\", property: \"text\", value, ...childLocator };\n}\n\n/** Replace an element's contents with markup, for a change no per-child operation\n * can express (a text layer added, removed or reordered). Sanitized at both ends. */\nexport function buildDomEditRichTextPatchOperation(value: string): PatchOperation {\n return { type: \"rich-text\", property: \"\", value };\n}\n\n// ─── Non-editable reason ─────────────────────────────────────────────────────\n\nfunction hasSupportedDirectEdit(capabilities: DomEditCapabilities): boolean {\n return (\n capabilities.canEditStyles ||\n capabilities.canMove ||\n capabilities.canResize ||\n capabilities.canApplyManualOffset ||\n capabilities.canApplyManualSize ||\n capabilities.canApplyManualRotation\n );\n}\n\nexport function getDomEditNonEditableReason(\n element: HTMLElement,\n selection: DomEditSelection | null,\n): string | null {\n if (!selection) {\n return \"No stable source target\";\n }\n\n if (selection.element !== element) {\n return selection.isCompositionHost\n ? \"Nested composition boundary\"\n : `Selection resolves to ${selection.label}`;\n }\n\n if (!hasSupportedDirectEdit(selection.capabilities)) {\n return selection.capabilities.reasonIfDisabled ?? \"No supported direct edits\";\n }\n\n return null;\n}\n\nexport function getDomEditTargetKey(\n selection: Pick<DomEditSelection, \"id\" | \"hfId\" | \"selector\" | \"selectorIndex\" | \"sourceFile\">,\n): string {\n return [\n selection.sourceFile || \"index.html\",\n selection.hfId ?? \"\",\n selection.id ?? \"\",\n selection.selector ?? \"\",\n selection.selectorIndex ?? \"\",\n ].join(\"|\");\n}\n\nexport function isTextEditableSelection(selection: DomEditSelection): boolean {\n return resolveEditingSections(domEditSelectionToFacts(selection)).text;\n}\n\n// buildElementAgentPrompt is in domEditingAgentPrompt.ts\n\nexport function readHfId(element: Element): string | undefined {\n return element.getAttribute(\"data-hf-id\")?.trim() || undefined;\n}\n\nexport function buildDomEditPatchTarget(\n selection: Pick<DomEditSelection, \"id\" | \"hfId\" | \"selector\" | \"selectorIndex\">,\n): { id?: string | null; hfId?: string; selector?: string; selectorIndex?: number } {\n return {\n id: selection.id,\n hfId: selection.hfId,\n selector: selection.selector,\n selectorIndex: selection.selectorIndex,\n };\n}\n","import { buildProjectApiPath } from \"../../utils/projectRouting\";\nimport { studioApiFetch } from \"../../utils/studioApiFetch\";\nimport type { DomEditSelection } from \"./domEditingTypes\";\n\nexport type ProbeTarget = { id?: string; hfId?: string; selector?: string; selectorIndex?: number };\n\nexport function knownSourceAnswer(\n previous: DomEditSelection | null | undefined,\n element: HTMLElement,\n sourceFile: string,\n target: ProbeTarget,\n): boolean | undefined {\n if (!previous || previous.element !== element || previous.sourceFile !== sourceFile) return;\n const same =\n previous.id === target.id &&\n previous.hfId === target.hfId &&\n previous.selector === target.selector &&\n previous.selectorIndex === target.selectorIndex;\n return same ? previous.existsInSource : undefined;\n}\n\ninterface PendingProbe {\n target: ProbeTarget;\n resolve: (exists: boolean) => void;\n}\n\nconst pending = new Map<string, PendingProbe[]>();\n\nasync function sendBatch(projectId: string, sourceFile: string, probes: PendingProbe[]) {\n let exists: boolean[] = [];\n try {\n const response = await studioApiFetch(\n buildProjectApiPath(\n projectId,\n `/file-mutations/probe-elements/${encodeURIComponent(sourceFile)}`,\n ),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ targets: probes.map((probe) => probe.target) }),\n },\n );\n if (response.ok) {\n const data = await response.json();\n if (Array.isArray(data?.exists)) exists = data.exists;\n }\n } catch {}\n probes.forEach((probe, index) => probe.resolve(exists[index] !== false));\n}\n\nexport function probeSourceElement(\n projectId: string,\n sourceFile: string,\n target: ProbeTarget,\n): Promise<boolean> {\n return new Promise((resolve) => {\n const key = `${projectId}\\0${sourceFile}`;\n let probes = pending.get(key);\n if (!probes) {\n const batch: PendingProbe[] = [];\n probes = batch;\n pending.set(key, batch);\n setTimeout(() => {\n pending.delete(key);\n void sendBatch(projectId, sourceFile, batch);\n }, 0);\n }\n probes.push({ target, resolve });\n });\n}\n","import { isHtmlElement } from \"./domEditingDom\";\n\n// `data-hf-group` selection semantics: a group wrapper is selected as one unit\n// until the user drills into it; once drilled in, clicks resolve to its children\n// (or to the next nested group inside it). One level of drill-in at a time keeps\n// nested groups navigable.\n\nexport type GroupCapture =\n | { kind: \"unit\"; element: HTMLElement } // select this group wrapper as one unit\n | { kind: \"child\" } // resolve the clicked element normally\n | { kind: \"out-of-scope\" }; // clicked outside the drilled-into group → select nothing\n\n// Layer-tree roots: the drilled-into group's element children, else the doc root.\nexport function groupScopedLayerRoots(\n root: HTMLElement,\n activeGroupElement: HTMLElement | null,\n): HTMLElement[] {\n const els = activeGroupElement?.isConnected ? Array.from(activeGroupElement.children) : [root];\n return els.filter(isHtmlElement);\n}\n\nexport function resolveGroupCapture(\n startEl: HTMLElement,\n activeGroupElement: HTMLElement | null,\n): GroupCapture {\n const groups: HTMLElement[] = [];\n for (let n: HTMLElement | null = startEl; n; n = n.parentElement) {\n if (n.hasAttribute(\"data-hf-group\")) groups.push(n);\n }\n const result = ((): GroupCapture => {\n if (!activeGroupElement) {\n const outermost = groups[groups.length - 1];\n return outermost ? { kind: \"unit\", element: outermost } : { kind: \"child\" };\n }\n const idx = groups.indexOf(activeGroupElement);\n if (idx === -1) return { kind: \"out-of-scope\" };\n const nestedInside = groups[idx - 1];\n return nestedInside ? { kind: \"unit\", element: nestedInside } : { kind: \"child\" };\n })();\n return result;\n}\n","/**\n * Element visibility, visual scoring, layer patch targets, element finders,\n * and the `findElementForSelection` / `findElementForTimelineElement` lookups.\n */\nimport type {\n DomEditContextOptions,\n DomEditSelection,\n DomEditViewport,\n TimelineElementDomTarget,\n TimelineElementDomTargetOptions,\n} from \"./domEditingTypes\";\nimport {\n buildStableSelector,\n escapeCssString,\n getSelectorIndex,\n getSourceFileForElement,\n isHtmlElement,\n isElementVisibleThroughAncestors,\n normalizeTimelineCompositionSource,\n querySelectorAllSafely,\n} from \"./domEditingDom\";\n\n// ─── Visibility ──────────────────────────────────────────────────────────────\n\nexport function isElementComputedVisible(\n el: HTMLElement,\n memo?: Map<HTMLElement, boolean>,\n): boolean {\n return isElementVisibleThroughAncestors(el, memo);\n}\n\nconst VISUAL_LEAF_TAGS = new Set([\"img\", \"video\", \"canvas\", \"svg\", \"audio\"]);\n\n// fallow-ignore-next-line complexity\nfunction hasVisualPresence(el: HTMLElement): boolean {\n const win = el.ownerDocument.defaultView;\n if (!win) return false;\n const cs = win.getComputedStyle(el);\n if (cs.backgroundImage !== \"none\") return true;\n if (\n cs.backgroundColor &&\n cs.backgroundColor !== \"transparent\" &&\n cs.backgroundColor !== \"rgba(0, 0, 0, 0)\"\n )\n return true;\n if (cs.borderWidth && parseFloat(cs.borderWidth) > 0 && cs.borderStyle !== \"none\") return true;\n if (cs.boxShadow && cs.boxShadow !== \"none\") return true;\n return false;\n}\n\nfunction isEmptyVisualContainer(el: HTMLElement): boolean {\n const tag = el.tagName.toLowerCase();\n if (VISUAL_LEAF_TAGS.has(tag)) return false;\n if (hasVisualPresence(el)) return false;\n\n const { children } = el;\n if (children.length === 0) {\n return (el.textContent ?? \"\").trim().length === 0;\n }\n\n for (let i = 0; i < children.length; i += 1) {\n const child = children[i];\n if (!isHtmlElement(child)) continue;\n if (VISUAL_LEAF_TAGS.has(child.tagName.toLowerCase())) return false;\n if (isElementComputedVisible(child)) return false;\n }\n\n return true;\n}\n\nfunction hasRenderedBox(el: HTMLElement): boolean {\n const rect = el.getBoundingClientRect();\n if (rect.width <= 1 || rect.height <= 1) return false;\n if (!isElementComputedVisible(el)) return false;\n if (isEmptyVisualContainer(el)) return false;\n return true;\n}\n\n// ─── Visual scoring ──────────────────────────────────────────────────────────\n\n// ─── Layer patch target ──────────────────────────────────────────────────────\n\nconst DOM_LAYER_IGNORED_TAGS = new Set([\n \"base\",\n \"br\",\n \"canvas\",\n \"link\",\n \"meta\",\n \"script\",\n \"source\",\n \"style\",\n \"template\",\n \"track\",\n \"wbr\",\n]);\n\n/**\n * Is the element rendered at all? The half of `getDomLayerPatchTarget` that a\n * plain style write can flip, and the only half that reads computed style.\n * Exported so a caller memoizing a layer walk can give it its own (short)\n * cache lifetime — see `domEditLayerWalkCache`.\n */\nexport function isInspectableLayerElement(el: HTMLElement): boolean {\n const tagName = el.tagName.toLowerCase();\n if (DOM_LAYER_IGNORED_TAGS.has(tagName)) return false;\n\n const computed = el.ownerDocument.defaultView?.getComputedStyle(el);\n if (computed?.display === \"none\" || computed?.visibility === \"hidden\") return false;\n\n return true;\n}\n\n/**\n * How the element is ADDRESSED — its selector, that selector's occurrence index\n * within the source file, and the file itself. Independent of whether the\n * element currently renders, so it survives every style write and moves only\n * when an identity attribute changes or the document's population of elements\n * sharing the selector does.\n */\n/**\n * The selector an element is addressed by, or undefined when it cannot be a\n * layer at all. Sole owner of that rule: `isDomLayerElement` answers the same\n * question without paying for the occurrence index, and a second copy of the\n * conditions would go stale the first time one of them changed.\n */\nfunction resolveLayerSelector(el: HTMLElement): string | undefined {\n if (el.hasAttribute(\"data-composition-id\")) return undefined;\n return buildStableSelector(el);\n}\n\nexport function resolveDomLayerIdentity(\n el: HTMLElement,\n activeCompositionPath: string | null,\n): Pick<DomEditSelection, \"id\" | \"hfId\" | \"selector\" | \"selectorIndex\" | \"sourceFile\"> | null {\n const selector = resolveLayerSelector(el);\n if (!selector) return null;\n\n const { sourceFile } = getSourceFileForElement(el, activeCompositionPath);\n return {\n id: el.id || undefined,\n hfId: el.getAttribute(\"data-hf-id\") || undefined,\n selector,\n selectorIndex: getSelectorIndex(\n el.ownerDocument,\n el,\n selector,\n sourceFile,\n activeCompositionPath,\n ),\n sourceFile,\n };\n}\n\nexport function getDomLayerPatchTarget(\n el: HTMLElement,\n activeCompositionPath: string | null,\n): Pick<DomEditSelection, \"id\" | \"hfId\" | \"selector\" | \"selectorIndex\" | \"sourceFile\"> | null {\n return isInspectableLayerElement(el) ? resolveDomLayerIdentity(el, activeCompositionPath) : null;\n}\n\n/**\n * Is `el` a layer at all? Exactly the condition under which\n * `getDomLayerPatchTarget` returns non-null, for callers that want the yes/no\n * and throw the target away.\n *\n * Worth its own function because the target carries the selector's OCCURRENCE\n * INDEX, and resolving that is a whole-document query — which the yes/no does\n * not depend on. Counting an element's layer children asked for one per child.\n */\nexport function isDomLayerElement(el: HTMLElement): boolean {\n return isInspectableLayerElement(el) && resolveLayerSelector(el) !== undefined;\n}\n\n// ─── Clip ancestor / selection candidate ─────────────────────────────────────\n\nfunction getPreferredClipAncestor(startEl: HTMLElement): HTMLElement | null {\n let current: HTMLElement | null = startEl;\n while (current) {\n if (current.classList.contains(\"clip\")) {\n const isCompositionHost =\n current.hasAttribute(\"data-composition-src\") ||\n current.hasAttribute(\"data-composition-file\");\n if (!isCompositionHost || current === startEl) return current;\n }\n current = current.parentElement;\n }\n return null;\n}\n\nexport function getSelectionCandidate(\n startEl: HTMLElement,\n options: DomEditContextOptions,\n): HTMLElement {\n if (options.preferClipAncestor) {\n const clipAncestor = getPreferredClipAncestor(startEl);\n if (clipAncestor) {\n return clipAncestor;\n }\n }\n\n return startEl;\n}\n\n// ─── Visual target resolution ─────────────────────────────────────────────────\n\nexport function resolveVisualDomEditSelectionTarget(\n elementsFromPoint: Iterable<Element | null | undefined>,\n options: Pick<DomEditContextOptions, \"activeCompositionPath\">,\n): HTMLElement | null {\n const candidates = resolveAllVisualDomEditTargets(elementsFromPoint, options);\n return candidates[0] ?? null;\n}\n\n/**\n * Returns all independently-selectable elements at the given point, in paint\n * order (topmost first). Used for click-cycling through stacked layers.\n *\n * Each entry in the returned array is an independent \"layer\" — an element\n * that is not an ancestor of an earlier entry. This gives one result per\n * z-stacked element rather than one per DOM node.\n */\nexport function resolveAllVisualDomEditTargets(\n elementsFromPoint: Iterable<Element | null | undefined>,\n options: Pick<DomEditContextOptions, \"activeCompositionPath\">,\n): HTMLElement[] {\n const raw: HTMLElement[] = [];\n\n for (const entry of elementsFromPoint) {\n if (!isHtmlElement(entry)) continue;\n if (hasRenderedBox(entry) && getDomLayerPatchTarget(entry, options.activeCompositionPath)) {\n raw.push(entry);\n }\n }\n\n if (raw.length === 0) return [];\n\n // First pass: for each contiguous ancestor-descendant run, keep only the\n // deepest (most specific) element, matching the original single-pick logic.\n const layers: HTMLElement[] = [];\n let best = raw[0];\n for (let i = 1; i < raw.length; i++) {\n const el = raw[i];\n if (best.contains(el)) {\n best = el; // go deeper in this subtree\n } else {\n layers.push(best);\n best = el;\n }\n }\n layers.push(best);\n\n return layers;\n}\n\n// ─── Raster detection ────────────────────────────────────────────────────────\n\nfunction hasRasterBackground(selection: Pick<DomEditSelection, \"computedStyles\">): boolean {\n const backgroundImage = selection.computedStyles[\"background-image\"]?.trim();\n return Boolean(backgroundImage && backgroundImage !== \"none\");\n}\n\nexport function isLargeRasterDomEditSelection(\n selection: Pick<DomEditSelection, \"boundingBox\" | \"computedStyles\" | \"tagName\">,\n viewport?: DomEditViewport | null,\n): boolean {\n const tagName = selection.tagName.toLowerCase();\n const isRasterLike = tagName === \"img\" || hasRasterBackground(selection);\n if (!isRasterLike) return false;\n\n const { width, height } = selection.boundingBox;\n if (width <= 1 || height <= 1) return false;\n if (!viewport || viewport.width <= 1 || viewport.height <= 1) {\n return width >= 960 && height >= 540;\n }\n\n const areaRatio = (width * height) / (viewport.width * viewport.height);\n const widthRatio = width / viewport.width;\n const heightRatio = height / viewport.height;\n return areaRatio >= 0.4 || (widthRatio >= 0.7 && heightRatio >= 0.5);\n}\n\n// ─── Element finders ──────────────────────────────────────────────────────────\n\ntype FindElementSelection = Pick<DomEditSelection, \"id\" | \"hfId\" | \"selector\" | \"selectorIndex\"> & {\n sourceFile?: string;\n};\n\nexport function findElementForSelection(\n doc: Document,\n selection: FindElementSelection,\n activeCompositionPath: string | null = null,\n): HTMLElement | null {\n const sourceMatches = (candidate: Element): candidate is HTMLElement =>\n isHtmlElement(candidate) &&\n (!selection.sourceFile ||\n getSourceFileForElement(candidate, activeCompositionPath).sourceFile ===\n selection.sourceFile);\n const findAll = (selector: string): HTMLElement[] =>\n querySelectorAllSafely(doc, selector).filter(sourceMatches);\n\n if (selection.hfId) {\n const byHfId = findAll(`[data-hf-id=\"${escapeCssString(selection.hfId)}\"]`)[0];\n if (byHfId) return byHfId;\n }\n\n if (selection.id) {\n // Flattened sub-compositions can repeat authored ids. getElementById returns\n // only the first document match, so filter every id match by source first.\n const byId = findAll(`[id=\"${escapeCssString(selection.id)}\"]`)[0];\n if (byId) return byId;\n }\n\n if (!selection.selector) return null;\n return findAll(selection.selector)[selection.selectorIndex ?? 0] ?? null;\n}\n\n// The selected node while mounted, else its copy in the selection's own file (ids repeat across files), else any copy.\nexport function findPreviewNode(\n doc: Document | null | undefined,\n el: DomEditSelection,\n): Element | null {\n if (!doc) return null;\n if (el.element?.isConnected && el.element.ownerDocument === doc) return el.element;\n return (\n findElementForSelection(doc, el) ??\n findElementForSelection(doc, { ...el, sourceFile: undefined })\n );\n}\n\n// fallow-ignore-next-line complexity\nexport function findElementForTimelineElement(\n doc: Document,\n element: TimelineElementDomTarget,\n options: TimelineElementDomTargetOptions,\n): HTMLElement | null {\n const elementId = typeof element.id === \"string\" ? element.id : \"\";\n const compositionSource =\n normalizeTimelineCompositionSource(element.compositionSrc) ??\n options.compIdToSrc?.get(elementId);\n const sourceFile =\n compositionSource ??\n normalizeTimelineCompositionSource(element.sourceFile) ??\n options.activeCompositionPath ??\n \"index.html\";\n const escapedElementId = escapeCssString(elementId);\n const escapedCompositionSource = compositionSource ? escapeCssString(compositionSource) : null;\n const selector =\n element.selector ??\n (compositionSource\n ? `[data-composition-src=\"${escapedCompositionSource}\"],[data-composition-file=\"${escapedCompositionSource}\"],[data-composition-id=\"${escapedElementId}\"]`\n : escapedElementId\n ? `[data-composition-id=\"${escapedElementId}\"]`\n : undefined);\n\n if (selector || element.domId) {\n const targetElement = findElementForSelection(\n doc,\n {\n id: element.domId ?? undefined,\n selector,\n selectorIndex: element.selectorIndex,\n sourceFile,\n },\n options.activeCompositionPath,\n );\n if (targetElement) return targetElement;\n }\n\n const hasExplicitDomTarget = Boolean(element.domId || element.selector || compositionSource);\n if (options.isMasterView || hasExplicitDomTarget || !options.activeCompositionPath) {\n return null;\n }\n\n const root = doc.querySelector(\"[data-composition-id]\");\n if (!isHtmlElement(root)) return null;\n return getSourceFileForElement(root, options.activeCompositionPath).sourceFile === sourceFile\n ? root\n : null;\n}\n\n// ─── Layer children ───────────────────────────────────────────────────────────\n\n/** `el`'s direct children that are layers. No longer takes the context options:\n * layer-ness does not depend on the active composition path. */\nexport function getDirectLayerChildren(el: HTMLElement): HTMLElement[] {\n return Array.from(el.children).filter(\n (child): child is HTMLElement => isHtmlElement(child) && isDomLayerElement(child),\n );\n}\n","import { parsePx } from \"./domEditingDom\";\n\nconst COMPOSITION_ROOT_LAYER_EPSILON_PX = 1;\n\nfunction readPositiveDimension(value: string | null): number | null {\n if (!value) return null;\n const parsed = Number.parseFloat(value);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : null;\n}\n\nfunction approximatelyEqual(a: number, b: number) {\n return Math.abs(a - b) <= COMPOSITION_ROOT_LAYER_EPSILON_PX;\n}\n\nfunction getCompositionRootBounds(doc: Document) {\n const root =\n doc.querySelector<HTMLElement>(\"[data-composition-id]\") ?? doc.documentElement ?? null;\n const rootWidth = readPositiveDimension(root?.getAttribute(\"data-width\") ?? null);\n const rootHeight = readPositiveDimension(root?.getAttribute(\"data-height\") ?? null);\n if (!root || !rootWidth || !rootHeight) return null;\n return { rect: root.getBoundingClientRect(), width: rootWidth, height: rootHeight };\n}\n\nfunction getRenderedLayerSize(element: HTMLElement, computedStyles: Record<string, string>) {\n const rect = element.getBoundingClientRect();\n const width = rect.width || parsePx(computedStyles.width);\n const height = rect.height || parsePx(computedStyles.height);\n return width && height ? { width, height } : null;\n}\n\nfunction matchesCompositionRootBounds(\n elementRect: DOMRect,\n elementSize: { width: number; height: number },\n rootBounds: { rect: DOMRect; width: number; height: number },\n) {\n return (\n approximatelyEqual(elementRect.left, rootBounds.rect.left) &&\n approximatelyEqual(elementRect.top, rootBounds.rect.top) &&\n approximatelyEqual(elementSize.width, rootBounds.width) &&\n approximatelyEqual(elementSize.height, rootBounds.height)\n );\n}\n\nfunction isExplicitFullBleedLayer(computedStyles: Record<string, string>) {\n return computedStyles.position === \"absolute\" || computedStyles.position === \"fixed\";\n}\n\nexport function isCompositionRootLayer(\n element: HTMLElement,\n doc: Document,\n computedStyles: Record<string, string>,\n) {\n if (element.parentElement !== doc.body) return false;\n if (element.hasAttribute(\"data-hf-allow-root-edit\")) return false;\n if (isExplicitFullBleedLayer(computedStyles)) return false;\n\n const rootBounds = getCompositionRootBounds(doc);\n const elementSize = getRenderedLayerSize(element, computedStyles);\n return Boolean(\n rootBounds &&\n elementSize &&\n matchesCompositionRootBounds(element.getBoundingClientRect(), elementSize, rootBounds),\n );\n}\n","/**\n * Incremental memory for `collectDomEditLayerItems`.\n *\n * The layer walk is re-run from scratch every time a MutationObserver says the\n * preview changed, and the observer's loudest source is inline `style` — which\n * is exactly what animation writes. So a paused-looking editor re-derived every\n * element's patch target, label and child count several times a second, and each\n * derivation costs two `getComputedStyle` reads (its own plus one per direct\n * child), two ancestor walks for the source file, and a `textContent` read whose\n * cost is the element's whole subtree.\n *\n * None of that depends on the traversal — only on the element. So the traversal\n * stays live (it is pointer-chasing, and `depth` genuinely is positional) and the\n * per-element half is memoized, with the mutation records deciding what to drop.\n *\n * WHAT MAKES A CACHED ENTRY WRONG, and how each is caught:\n *\n * - the element's own attributes (`style` -> computed display, `class`/`id`/\n * `data-hf-group` -> selector and label) -> attribute record on it\n * - an ancestor's `visibility`, the ONLY inherited input to the\n * display/visibility gate (`display:none` on an ancestor does not change a\n * descendant's own computed `display`) -> attribute record on the\n * ancestor, whose subtree is\n * dropped only when the\n * style declares visibility\n * - a direct child appearing or disappearing from the layer list, which moves\n * the parent's `childCount` -> the parent is dropped\n * alongside every element\n * - descendant text, which moves an ancestor's label -> characterData record,\n * ancestors dropped\n * - selector occurrence indices, which shift for EVERY element sharing a\n * selector when one element's identity changes -> whole cache dropped\n * - nodes added or removed, which shift indices, order, labels and counts at\n * once and cannot be attributed to one element -> whole cache dropped\n * - a different active composition path, or a new composition-id -> source-file\n * map, both of which re-scope every source file -> checked per walk\n *\n * The bias is deliberate and matches the duration cache in the runtime: a\n * redundant recomputation is a missed optimisation, a missed one is a wrong\n * layer tree.\n */\n\nimport { buildElementLabel, getCompositionSourceMapRevision, isHtmlElement } from \"./domEditingDom\";\nimport {\n getDirectLayerChildren,\n isInspectableLayerElement,\n resolveDomLayerIdentity,\n} from \"./domEditingElement\";\nimport type { DomEditSelection } from \"./domEditingTypes\";\n\n/** How an element is addressed. Survives style writes; see `readIdentity`. */\nexport type DomEditLayerIdentity = Pick<\n DomEditSelection,\n \"id\" | \"hfId\" | \"selector\" | \"selectorIndex\" | \"sourceFile\"\n>;\n\n/** Whether the element renders, and how many of its direct children are layers.\n * Both are computed style reads, and both a style write can flip. Filled\n * lazily: `childCount` is only asked for once an element is known to be one. */\ninterface PresenceMemo {\n inspectable?: boolean;\n childCount?: number;\n}\n\ninterface IdentityMemo {\n identity?: DomEditLayerIdentity | null;\n label?: string;\n}\n\n/**\n * Attributes that decide an element's SELECTOR, and therefore the occurrence\n * index of every other element sharing that selector. One of these changing\n * renumbers elements the record does not mention, so the only sound response is\n * to drop everything. `class` is here because `buildStableSelector` falls back\n * to the preferred class.\n */\nconst SELECTOR_IDENTITY_ATTRIBUTES = new Set([\n \"id\",\n \"class\",\n \"data-hf-group\",\n \"data-composition-id\",\n \"data-composition-file\",\n \"data-composition-src\",\n \"data-hf-original-composition-id\",\n]);\n\n/**\n * The observer configuration the cache's invalidation is written against.\n * Exported so the refresh loop and the tests cannot drift from it.\n *\n * No `attributeFilter`: an unlisted attribute is one the cache would never learn\n * about, and serving a stale entry is worse than the extra records.\n */\nexport const DOM_EDIT_LAYER_OBSERVER_INIT: MutationObserverInit = {\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n};\n\n/**\n * The inline `visibility` each element last presented. Deliberately NOT cleared\n * by `invalidateAll`: it records what the DOM said, not a value derived from it.\n */\nconst lastInlineVisibility = new WeakMap<HTMLElement, string>();\n\n/**\n * Did this style write move the element's inline `visibility`?\n *\n * `visibility` is inherited, so changing it changes the layer-list membership of\n * the element's whole subtree, and only then is the subtree worth dropping.\n *\n * The comparison is on the PARSED value, remembered per element. Testing the\n * attribute TEXT for \"visibility\" looks equivalent and is not: the standard\n * GSAP fade (`autoAlpha`) writes `visibility: visible` once and leaves it in the\n * attribute for the rest of the clip, so a text test stays true for every\n * transform tick afterwards. That is a whole-subtree walk per animation frame,\n * in the observer callback rather than behind the rebuild throttle, on exactly\n * the elements a composition animates most.\n *\n * An element seen for the first time reports changed, which costs one drop and\n * is the safe answer: its entries were derived before this write.\n */\nfunction inlineVisibilityChanged(el: HTMLElement): boolean {\n const next = el.style.visibility;\n if (lastInlineVisibility.get(el) === next) return false;\n lastInlineVisibility.set(el, next);\n return true;\n}\n\nexport interface DomEditLayerWalkCache {\n /**\n * Start a walk. Drops everything when the scoping inputs the entries were\n * built under no longer hold. Call once per `collectDomEditLayerItems`.\n */\n beginWalk(activeCompositionPath: string | null): void;\n /**\n * Does `el` render? Cheap to invalidate and invalidated often: any attribute\n * write on the element, on its parent, or a `visibility` write on an ancestor\n * drops it, because all three can flip the answer.\n */\n readInspectable(el: HTMLElement, compute: () => boolean): boolean;\n /** How many of `el`'s direct children are layers. Same lifetime as\n * `readInspectable`: it is a sum over their answers. */\n readChildCount(el: HTMLElement, compute: () => number): number;\n /**\n * `el`'s selector, occurrence index and source file. A SEPARATE, much longer\n * lifetime than presence: a style write cannot renumber a selector, so this\n * survives one, and it is the only part of the walk that queries the\n * document. That split is what makes an ordinary animation frame cost no\n * document queries at all.\n */\n readIdentity(\n el: HTMLElement,\n compute: () => DomEditLayerIdentity | null,\n ): DomEditLayerIdentity | null;\n /** `el`'s display label. Shares the identity lifetime, plus descendant text. */\n readLabel(el: HTMLElement, compute: () => string): string;\n /** Apply mutation records. Safe to call with an empty array. */\n ingest(records: MutationRecord[]): void;\n /** Forget every entry — the fallback for anything not attributable. */\n invalidateAll(): void;\n}\n\nexport function createDomEditLayerWalkCache(): DomEditLayerWalkCache {\n let presence = new WeakMap<HTMLElement, PresenceMemo>();\n let identities = new WeakMap<HTMLElement, IdentityMemo>();\n let scope: string | null = null;\n\n const invalidateAll = () => {\n presence = new WeakMap();\n identities = new WeakMap();\n };\n\n const drop = (el: HTMLElement | null) => {\n if (el) presence.delete(el);\n };\n\n const dropSubtree = (el: HTMLElement) => {\n for (const descendant of el.querySelectorAll(\"*\")) {\n if (isHtmlElement(descendant)) presence.delete(descendant);\n }\n };\n\n const ingestOne = (record: MutationRecord): boolean => {\n // Structural change: order, occurrence indices, labels and child counts all\n // move at once, and the record names the parent rather than everything\n // affected. This is the documented full-rebuild fallback.\n if (record.type === \"childList\") return false;\n\n if (record.type === \"characterData\") {\n // `buildElementLabel` falls back to `textContent`, so edited text changes\n // the label of every ancestor that contains it.\n for (\n let ancestor = record.target.parentElement;\n ancestor;\n ancestor = ancestor.parentElement\n ) {\n identities.delete(ancestor);\n }\n return true;\n }\n\n const target = record.target;\n if (!isHtmlElement(target)) return true;\n if (record.attributeName && SELECTOR_IDENTITY_ATTRIBUTES.has(record.attributeName))\n return false;\n\n drop(target);\n // The parent counts its layer children, and this element may have just\n // joined or left that count.\n drop(target.parentElement);\n if (record.attributeName === \"style\" && inlineVisibilityChanged(target)) dropSubtree(target);\n return true;\n };\n\n return {\n beginWalk(activeCompositionPath) {\n const nextScope = `${activeCompositionPath ?? \"\"}|${getCompositionSourceMapRevision()}`;\n if (nextScope === scope) return;\n scope = nextScope;\n invalidateAll();\n },\n readInspectable(el, compute) {\n const memo = presence.get(el) ?? {};\n if (memo.inspectable === undefined) {\n memo.inspectable = compute();\n presence.set(el, memo);\n }\n return memo.inspectable;\n },\n readChildCount(el, compute) {\n const memo = presence.get(el) ?? {};\n if (memo.childCount === undefined) {\n memo.childCount = compute();\n presence.set(el, memo);\n }\n return memo.childCount;\n },\n readIdentity(el, compute) {\n const memo = identities.get(el) ?? {};\n if (memo.identity === undefined) {\n memo.identity = compute();\n identities.set(el, memo);\n }\n return memo.identity;\n },\n readLabel(el, compute) {\n const memo = identities.get(el) ?? {};\n if (memo.label === undefined) {\n memo.label = compute();\n identities.set(el, memo);\n }\n return memo.label;\n },\n ingest(records) {\n for (const record of records) {\n if (!ingestOne(record)) {\n invalidateAll();\n return;\n }\n }\n },\n invalidateAll,\n };\n}\n\n/** One element's contribution to a layer walk. `depth` is absent on purpose: it\n * belongs to the traversal, not to the element. */\nexport interface DomEditLayerWalkEntry {\n target: DomEditLayerIdentity;\n label: string;\n childCount: number;\n}\n\n/**\n * Everything `collectDomEditLayerItems` needs about ONE element, served from\n * `cache` where it is still valid. Null when the element is not a layer.\n *\n * The four reads go through the cache separately rather than as one record\n * because they do not go stale together: a style write flips whether an element\n * renders without touching how it is addressed. Without a cache this is exactly\n * the original per-element derivation, which is what every other caller of the\n * walk still gets.\n *\n * Lives here rather than in the walk so the two halves of the memoization —\n * what is stored and what is read — sit in one file.\n */\nexport function readDomEditLayerWalkEntry(\n el: HTMLElement,\n activeCompositionPath: string | null,\n cache?: DomEditLayerWalkCache,\n): DomEditLayerWalkEntry | null {\n const inspectable = cache\n ? cache.readInspectable(el, () => isInspectableLayerElement(el))\n : isInspectableLayerElement(el);\n if (!inspectable) return null;\n\n const identity = () => resolveDomLayerIdentity(el, activeCompositionPath);\n const target = cache ? cache.readIdentity(el, identity) : identity();\n if (!target) return null;\n\n const label = () => buildElementLabel(el);\n const childCount = () => getDirectLayerChildren(el).length;\n return {\n target,\n label: cache ? cache.readLabel(el, label) : label(),\n childCount: cache ? cache.readChildCount(el, childCount) : childCount(),\n };\n}\n\n/**\n * Apply the records the observer has taken in but not yet delivered.\n *\n * Records arrive in a microtask, so an edit made earlier in THIS task would\n * otherwise be read back against entries that predate it. Taking them suppresses\n * the observer's own callback for them, which is equivalent here: that callback\n * only ingests and marks a rebuild owed, and a caller draining is rebuilding\n * regardless. A caller with no observer yet has nothing pending.\n */\nexport function drainPendingLayerMutations(\n observer: MutationObserver | null,\n cache: DomEditLayerWalkCache,\n): void {\n if (!observer) return;\n cache.ingest(observer.takeRecords());\n}\n"],"mappings":"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","names":[]}
|
|
@@ -271,7 +271,17 @@ function HyperframesLoader({
|
|
|
271
271
|
// src/components/ui/Menu.tsx
|
|
272
272
|
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu";
|
|
273
273
|
import { Menu as BaseMenu } from "@base-ui/react/menu";
|
|
274
|
+
import { useRef } from "react";
|
|
274
275
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
276
|
+
var CONTENTS = { display: "contents" };
|
|
277
|
+
function useInlinePortal(container) {
|
|
278
|
+
const host = useRef(null);
|
|
279
|
+
if (container !== null) return { host: null, portal: { container } };
|
|
280
|
+
return {
|
|
281
|
+
host: /* @__PURE__ */ jsx6("span", { ref: host, style: CONTENTS }),
|
|
282
|
+
portal: { container: host, style: CONTENTS }
|
|
283
|
+
};
|
|
284
|
+
}
|
|
275
285
|
var SIDE_OFFSET = 6;
|
|
276
286
|
var VIEWPORT_MARGIN = 8;
|
|
277
287
|
function floatingMotion(openDuration) {
|
|
@@ -315,9 +325,11 @@ function Menu({
|
|
|
315
325
|
"data-preview-state": previewState,
|
|
316
326
|
...root
|
|
317
327
|
}) {
|
|
328
|
+
const inline = useInlinePortal(container);
|
|
318
329
|
return /* @__PURE__ */ jsxs4(BaseMenu.Root, { ...root, children: [
|
|
319
330
|
/* @__PURE__ */ jsx6(BaseMenu.Trigger, { render: trigger }),
|
|
320
|
-
|
|
331
|
+
inline.host,
|
|
332
|
+
/* @__PURE__ */ jsx6(BaseMenu.Portal, { ...inline.portal, children: /* @__PURE__ */ jsx6(
|
|
321
333
|
BaseMenu.Positioner,
|
|
322
334
|
{
|
|
323
335
|
side,
|
|
@@ -347,9 +359,11 @@ function ContextMenu({
|
|
|
347
359
|
"data-preview-state": previewState,
|
|
348
360
|
...root
|
|
349
361
|
}) {
|
|
362
|
+
const inline = useInlinePortal(container);
|
|
350
363
|
return /* @__PURE__ */ jsxs4(BaseContextMenu.Root, { ...root, children: [
|
|
351
364
|
/* @__PURE__ */ jsx6(BaseContextMenu.Trigger, { render: trigger }),
|
|
352
|
-
|
|
365
|
+
inline.host,
|
|
366
|
+
/* @__PURE__ */ jsx6(BaseContextMenu.Portal, { ...inline.portal, children: /* @__PURE__ */ jsx6(BaseContextMenu.Positioner, { collisionPadding: VIEWPORT_MARGIN, className: POPUP_LAYER, children: /* @__PURE__ */ jsx6(
|
|
353
367
|
BaseContextMenu.Popup,
|
|
354
368
|
{
|
|
355
369
|
"aria-label": ariaLabel,
|
|
@@ -401,7 +415,7 @@ function MenuSeparator({ className, ...props }) {
|
|
|
401
415
|
|
|
402
416
|
// src/components/ui/Tooltip.tsx
|
|
403
417
|
import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
|
|
404
|
-
import { cloneElement, useId as useId2, useRef, useState } from "react";
|
|
418
|
+
import { cloneElement, useId as useId2, useRef as useRef2, useState } from "react";
|
|
405
419
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
406
420
|
var SIDE_OFFSET2 = 6;
|
|
407
421
|
var VIEWPORT_MARGIN2 = 8;
|
|
@@ -413,7 +427,7 @@ function Tooltip({
|
|
|
413
427
|
disabled = false
|
|
414
428
|
}) {
|
|
415
429
|
const [open, setOpen] = useState(false);
|
|
416
|
-
const boxRef =
|
|
430
|
+
const boxRef = useRef2(null);
|
|
417
431
|
const tooltipId = useId2();
|
|
418
432
|
return /* @__PURE__ */ jsxs5(BaseTooltip.Root, { open, onOpenChange: setOpen, disabled, children: [
|
|
419
433
|
/* @__PURE__ */ jsx7(BaseTooltip.Trigger, { delay, render: /* @__PURE__ */ jsx7("span", { ref: boxRef, className: "contents" }), children: cloneElement(children, {
|
|
@@ -470,9 +484,11 @@ function Popover({
|
|
|
470
484
|
"data-preview-state": previewState,
|
|
471
485
|
...root
|
|
472
486
|
}) {
|
|
487
|
+
const inline = useInlinePortal(container);
|
|
473
488
|
return /* @__PURE__ */ jsxs6(BasePopover.Root, { ...root, children: [
|
|
474
489
|
/* @__PURE__ */ jsx8(BasePopover.Trigger, { render: trigger }),
|
|
475
|
-
|
|
490
|
+
inline.host,
|
|
491
|
+
/* @__PURE__ */ jsx8(BasePopover.Portal, { ...inline.portal, children: /* @__PURE__ */ jsx8(
|
|
476
492
|
BasePopover.Positioner,
|
|
477
493
|
{
|
|
478
494
|
side,
|
|
@@ -501,7 +517,7 @@ function Popover({
|
|
|
501
517
|
|
|
502
518
|
// src/components/ui/Input.tsx
|
|
503
519
|
import { Input as BaseInput } from "@base-ui/react/input";
|
|
504
|
-
import { useEffect, useRef as
|
|
520
|
+
import { useEffect, useRef as useRef3, useState as useState2 } from "react";
|
|
505
521
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
506
522
|
var fieldBase = cn(
|
|
507
523
|
"flex min-w-0 items-center gap-1.5 h-ctl px-2 rounded-md",
|
|
@@ -532,9 +548,9 @@ function Input({
|
|
|
532
548
|
...props
|
|
533
549
|
}) {
|
|
534
550
|
const [draft, setDraft] = useState2(value);
|
|
535
|
-
const valueRef =
|
|
551
|
+
const valueRef = useRef3(value);
|
|
536
552
|
valueRef.current = value;
|
|
537
|
-
const dirtyRef =
|
|
553
|
+
const dirtyRef = useRef3(false);
|
|
538
554
|
useEffect(() => {
|
|
539
555
|
if (!dirtyRef.current) setDraft(value);
|
|
540
556
|
}, [value]);
|
|
@@ -585,7 +601,7 @@ function Input({
|
|
|
585
601
|
|
|
586
602
|
// src/components/ui/NumberField.tsx
|
|
587
603
|
import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
|
|
588
|
-
import { useEffect as useEffect2, useRef as
|
|
604
|
+
import { useEffect as useEffect2, useRef as useRef4, useState as useState3 } from "react";
|
|
589
605
|
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
590
606
|
function NumberField({
|
|
591
607
|
label,
|
|
@@ -602,9 +618,9 @@ function NumberField({
|
|
|
602
618
|
}) {
|
|
603
619
|
const [draft, setDraft] = useState3(value);
|
|
604
620
|
const [invalid, setInvalid] = useState3(false);
|
|
605
|
-
const inputRef =
|
|
606
|
-
const committedRef =
|
|
607
|
-
const valueRef =
|
|
621
|
+
const inputRef = useRef4(null);
|
|
622
|
+
const committedRef = useRef4(value);
|
|
623
|
+
const valueRef = useRef4(value);
|
|
608
624
|
valueRef.current = value;
|
|
609
625
|
useEffect2(() => {
|
|
610
626
|
committedRef.current = value;
|
|
@@ -756,7 +772,7 @@ function Select({
|
|
|
756
772
|
|
|
757
773
|
// src/components/ui/Slider.tsx
|
|
758
774
|
import { Slider as BaseSlider } from "@base-ui/react/slider";
|
|
759
|
-
import { useEffect as useEffect3, useRef as
|
|
775
|
+
import { useEffect as useEffect3, useRef as useRef5, useState as useState4 } from "react";
|
|
760
776
|
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
761
777
|
var first = (next) => Array.isArray(next) ? next[0] : next;
|
|
762
778
|
function Slider({
|
|
@@ -773,11 +789,11 @@ function Slider({
|
|
|
773
789
|
"data-preview-state": previewState
|
|
774
790
|
}) {
|
|
775
791
|
const [draft, setDraft] = useState4(value);
|
|
776
|
-
const draggingRef =
|
|
777
|
-
const abortedRef =
|
|
778
|
-
const dragStartRef =
|
|
779
|
-
const committedRef =
|
|
780
|
-
const valueRef =
|
|
792
|
+
const draggingRef = useRef5(false);
|
|
793
|
+
const abortedRef = useRef5(false);
|
|
794
|
+
const dragStartRef = useRef5(value);
|
|
795
|
+
const committedRef = useRef5(value);
|
|
796
|
+
const valueRef = useRef5(value);
|
|
781
797
|
valueRef.current = value;
|
|
782
798
|
useEffect3(() => {
|
|
783
799
|
if (draggingRef.current) return;
|
|
@@ -951,4 +967,4 @@ export {
|
|
|
951
967
|
Slider,
|
|
952
968
|
Toggle
|
|
953
969
|
};
|
|
954
|
-
//# sourceMappingURL=chunk-
|
|
970
|
+
//# sourceMappingURL=chunk-Y2OHHNM2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/cn.ts","../src/components/ui/Button.tsx","../src/components/ui/IconButton.tsx","../src/components/ui/Tabs.tsx","../src/components/ui/HyperframesMark.tsx","../src/components/ui/HyperframesLoader.tsx","../src/components/ui/Menu.tsx","../src/components/ui/Tooltip.tsx","../src/components/ui/Popover.tsx","../src/components/ui/Input.tsx","../src/components/ui/NumberField.tsx","../src/components/ui/Select.tsx","../src/components/ui/Slider.tsx","../src/components/ui/Toggle.tsx"],"sourcesContent":["/**\n * Studio's tailwind-merge config: teaches it the two scales `theme.css`\n * invents (`text-step-*`, `ctl`/`ctl-sm`/`ctl-lg`) so overrides replace, not stack.\n */\n\nimport type { CnFunction } from \"cn\";\nimport { createCn } from \"cn/config\";\n\n/** `text-step-11`, `text-step-9`, … — the type scale from `theme.css`. */\nconst isTypeStep = (value: string) => /^step-\\d+$/.test(value);\n\n/** `ctl`, `ctl-sm`, `ctl-lg` — the control heights from `theme.css`. */\nconst isControlSize = (value: string) => /^ctl(-sm|-lg)?$/.test(value);\n\nexport const cn: CnFunction = createCn({\n extend: {\n classGroups: {\n \"font-size\": [{ text: [isTypeStep] }],\n h: [{ h: [isControlSize] }],\n w: [{ w: [isControlSize] }],\n size: [{ size: [isControlSize] }],\n \"min-h\": [{ \"min-h\": [isControlSize] }],\n \"min-w\": [{ \"min-w\": [isControlSize] }],\n },\n },\n});\n","/**\n * Button — a native `<button>` wearing Studio's tokens.\n *\n * Everything visual comes from `theme.css`: the three control heights, the\n * radius scale, the semantic colours, the motion durations. No value is decided\n * here, so a button cannot drift from the rest of the system.\n *\n * Two conventions: classes merge through `cn`, so a caller's `className`\n * always wins within its group; and every interactive look is written twice,\n * once as the real state and once as `data-[preview-state=…]` (CSS-only, for\n * screenshots). `Button.test.tsx` asserts the two stay in sync.\n */\n\nimport { forwardRef, type ButtonHTMLAttributes, type ReactNode } from \"react\";\nimport { cn } from \"./cn\";\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"danger\" | \"ghost\";\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\n/** Forces one interactive look for a gallery shot. CSS-only; see the header. */\nexport type PreviewState = \"hover\" | \"active\" | \"focus\";\n\nexport interface ButtonBaseProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n \"data-preview-state\"?: PreviewState;\n}\n\ninterface ButtonProps extends ButtonBaseProps {\n loading?: boolean;\n icon?: ReactNode;\n}\n\n/**\n * Shared by Button and IconButton. `disabled:` keeps pointer events alive so a\n * wrapping Tooltip can still explain why the control is disabled.\n */\nexport const buttonBase = cn(\n \"inline-flex items-center justify-center select-none cursor-pointer whitespace-nowrap\",\n \"transition-[background-color,border-color,color,filter,transform] ease-out-quint duration-press\",\n \"disabled:opacity-40 disabled:cursor-not-allowed\",\n \"outline-hidden\",\n \"focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-accent\",\n \"data-[preview-state=focus]:outline-solid data-[preview-state=focus]:outline-2 data-[preview-state=focus]:outline-offset-1 data-[preview-state=focus]:outline-accent\",\n);\n\n/**\n * One entry per variant. The `data-[preview-state=…]` half of each string\n * repeats the `hover:` and `active:` half exactly; the test pairs them.\n */\nexport const buttonVariants: Record<ButtonVariant, string> = {\n primary: cn(\n \"bg-accent text-on-accent font-semibold\",\n \"enabled:hover:bg-accent-hover data-[preview-state=hover]:bg-accent-hover\",\n \"enabled:active:scale-[0.98] data-[preview-state=active]:scale-[0.98]\",\n ),\n secondary: cn(\n \"bg-transparent text-text-1 font-medium border border-border-strong\",\n \"enabled:hover:bg-hover enabled:hover:text-text-0 data-[preview-state=hover]:bg-hover data-[preview-state=hover]:text-text-0\",\n \"enabled:active:scale-[0.98] data-[preview-state=active]:scale-[0.98]\",\n ),\n danger: cn(\n \"bg-danger text-on-danger font-medium\",\n \"enabled:hover:brightness-95 data-[preview-state=hover]:brightness-95\",\n \"enabled:active:scale-[0.98] data-[preview-state=active]:scale-[0.98]\",\n ),\n ghost: cn(\n \"bg-transparent text-text-2 font-medium\",\n \"enabled:hover:bg-hover enabled:hover:text-text-0 data-[preview-state=hover]:bg-hover data-[preview-state=hover]:text-text-0\",\n \"enabled:active:scale-[0.98] data-[preview-state=active]:scale-[0.98]\",\n ),\n};\n\n/**\n * The three control heights, 24 / 28 / 32 px, from `--spacing-ctl-*`.\n * Exported so the Capture download `<a href>` can wear the same recipe as a Button.\n */\nexport const buttonSizes: Record<ButtonSize, string> = {\n sm: \"h-ctl-sm px-2 gap-1 rounded-sm text-step-11\",\n md: \"h-ctl px-3 gap-1.5 rounded-md text-step-12\",\n lg: \"h-ctl-lg px-4 gap-2 rounded-md text-step-13\",\n};\n\nfunction Spinner() {\n return (\n <svg className=\"animate-spin size-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n );\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n { variant = \"secondary\", size = \"md\", loading, icon, children, className, disabled, ...props },\n ref,\n ) => {\n const isDisabled = disabled || loading;\n let leading: ReactNode = null;\n if (loading) leading = <Spinner />;\n else if (icon) leading = <span className=\"shrink-0\">{icon}</span>;\n return (\n <button\n ref={ref}\n disabled={isDisabled}\n // `aria-disabled` as well as `disabled`: assistive tech announces the\n // state even where the native attribute is filtered out of the tree.\n aria-disabled={isDisabled || undefined}\n className={cn(buttonBase, buttonVariants[variant], buttonSizes[size], className)}\n {...props}\n >\n {leading}\n {children}\n </button>\n );\n },\n);\nButton.displayName = \"Button\";\n","/**\n * IconButton — Button's square sibling; shares its base/variant classes so\n * the two never drift. `aria-label` is required for screen readers.\n */\n\nimport { forwardRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { buttonBase, buttonVariants, type ButtonBaseProps, type ButtonSize } from \"./Button\";\nimport { cn } from \"./cn\";\n\ninterface IconButtonProps extends ButtonBaseProps {\n icon: ReactNode;\n \"aria-label\": string;\n}\n\n/** Square boxes on the same 24 / 28 / 32 px control heights as Button. */\nconst iconSizeStyles: Record<ButtonSize, string> = {\n sm: \"size-ctl-sm rounded-sm\",\n md: \"size-ctl rounded-md\",\n lg: \"size-ctl-lg rounded-md\",\n};\n\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n ({ icon, size = \"md\", variant = \"ghost\", className, disabled, ...props }, ref) => {\n return (\n <button\n ref={ref}\n disabled={disabled}\n aria-disabled={disabled || undefined}\n className={cn(buttonBase, buttonVariants[variant], iconSizeStyles[size], className)}\n {...props}\n >\n {icon}\n </button>\n );\n },\n);\nIconButton.displayName = \"IconButton\";\n","/**\n * Tabs — Base UI's tabs wearing Studio's tokens; replaces six hand-rolled\n * strips with one implementation (roving tabindex, arrow/Home/End, `aria-controls`).\n */\n\nimport { Tabs as BaseTabs } from \"@base-ui/react/tabs\";\nimport type { ComponentPropsWithoutRef, ElementType } from \"react\";\nimport { cn } from \"./cn\";\nimport type { PreviewState } from \"./Button\";\n\n/**\n * Base UI lets `className` be a function of the part's state. Studio's parts\n * merge a string with `cn`, so the string form is the one they accept.\n */\ntype StyledProps<T extends ElementType> = Omit<ComponentPropsWithoutRef<T>, \"className\"> & {\n className?: string;\n};\n\n/**\n * Groups a tab list with its panels. Uncontrolled by default; pass `value` and\n * `onValueChange` for a strip whose selection lives in a store.\n */\nexport function Tabs(props: ComponentPropsWithoutRef<typeof BaseTabs.Root>) {\n return <BaseTabs.Root {...props} />;\n}\n\n/** The strip. Give it an `aria-label`: a tablist with no name is unlabelled. */\nexport function TabsList({ className, ...props }: StyledProps<typeof BaseTabs.List>) {\n return (\n <BaseTabs.List\n // Arrow keys move selection, matching today's sidebar strip.\n activateOnFocus\n className={cn(\"inline-flex items-center gap-0.5 rounded-lg bg-surface-alt p-1\", className)}\n {...props}\n />\n );\n}\n\ninterface TabProps extends StyledProps<typeof BaseTabs.Tab> {\n value: string;\n \"data-preview-state\"?: PreviewState;\n}\n\n/**\n * aria-selected drives the selected look (Base UI sets it) so assistive tech\n * and sighted users match. data-preview-state is for gallery shots only.\n */\nexport function Tab({ value, className, ...props }: TabProps) {\n return (\n <BaseTabs.Tab\n value={value}\n data-tab-id={value}\n className={cn(\n \"inline-flex h-ctl-sm cursor-pointer select-none items-center justify-center rounded-sm px-2.5\",\n \"text-step-11 font-semibold whitespace-nowrap text-text-3\",\n \"transition-[background-color,color] ease-out-quint duration-hover\",\n \"hover:text-text-1 data-[preview-state=hover]:text-text-1\",\n \"aria-selected:bg-hover aria-selected:text-text-0\",\n \"outline-hidden focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-accent\",\n \"data-[preview-state=focus]:outline-solid data-[preview-state=focus]:outline-2 data-[preview-state=focus]:outline-offset-1 data-[preview-state=focus]:outline-accent\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** The panel for one tab. Base UI wires `aria-labelledby` back to its tab. */\nexport function TabPanel({ className, ...props }: StyledProps<typeof BaseTabs.Panel>) {\n return <BaseTabs.Panel className={cn(\"outline-hidden\", className)} {...props} />;\n}\n","import { useId, type SVGProps } from \"react\";\n\nexport function HyperframesMark({ viewBox = \"0 0 100 100\", ...props }: SVGProps<SVGSVGElement>) {\n const gradientId = useId();\n const leftGradient = `${gradientId}-left`;\n const rightGradient = `${gradientId}-right`;\n return (\n <svg\n viewBox={viewBox}\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n {...props}\n >\n <g transform=\"translate(50 50)\" opacity=\".92\">\n <g transform=\"translate(-50 -50)\">\n <path\n d=\"M10.1851 57.8021L33.1145 73.8313C36.2202 75.9978 41.5173 73.5433 42.4816 69.4984L51.7611 30.4271C52.7253 26.3822 48.5802 23.9277 44.4602 26.0942L13.917 42.1235C6.96677 45.7676 4.97564 54.1579 10.1851 57.8021Z\"\n fill={`url(#${leftGradient})`}\n />\n <path\n d=\"M87.5129 57.5141L56.9696 73.5433C52.8371 75.7098 48.7046 73.2553 49.6688 69.2104L58.9483 30.1391C59.9125 26.0942 65.2097 23.6397 68.3154 25.8062L91.2447 41.8354C96.4668 45.4796 94.4631 53.8699 87.5129 57.5141Z\"\n fill={`url(#${rightGradient})`}\n />\n </g>\n </g>\n <defs>\n <linearGradient\n id={leftGradient}\n x1=\"48.5676\"\n y1=\"25\"\n x2=\"44.7804\"\n y2=\"71.9384\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop stopColor=\"#06E3FA\" />\n <stop offset=\"1\" stopColor=\"#4FDB5E\" />\n </linearGradient>\n <linearGradient\n id={rightGradient}\n x1=\"54.8282\"\n y1=\"73.8392\"\n x2=\"72.0989\"\n y2=\"32.8932\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop stopColor=\"#06E3FA\" />\n <stop offset=\"1\" stopColor=\"#4FDB5E\" />\n </linearGradient>\n </defs>\n </svg>\n );\n}\n","import { HyperframesMark } from \"./HyperframesMark\";\n\nexport interface HyperframesLoaderProps {\n /** Status text shown below the mark. */\n title: string;\n /** Optional secondary detail line. */\n detail?: string;\n /** Optional monospace third line for IDs, counts, or percentages. */\n mono?: string;\n /** Pixel size of the mark itself; status text scales independently. */\n size?: number;\n /** Optional normalized progress value from 0 to 1. */\n progress?: number;\n}\n\nexport function HyperframesLoader({\n title,\n detail,\n mono,\n size = 64,\n progress,\n}: HyperframesLoaderProps) {\n const boundedProgress =\n typeof progress === \"number\" && Number.isFinite(progress)\n ? Math.min(1, Math.max(0, progress))\n : undefined;\n const markFrameSize = Math.round(size * 1.16);\n\n return (\n <div className=\"hf-loader\" role=\"status\" draggable={false}>\n <div\n className=\"hf-loader-mark-frame\"\n style={{ width: markFrameSize, height: markFrameSize }}\n draggable={false}\n >\n <HyperframesMark className=\"hf-loader-mark\" width={size} height={size} />\n </div>\n <div className=\"hf-loader-title\">{title}</div>\n {detail && <div className=\"hf-loader-detail\">{detail}</div>}\n {boundedProgress !== undefined && (\n <div\n className=\"hf-loader-progress\"\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(boundedProgress * 100)}\n >\n <div\n className=\"hf-loader-progress__fill\"\n style={{ transform: `scaleX(${boundedProgress})` }}\n />\n </div>\n )}\n {mono && <div className=\"hf-loader-mono\">{mono}</div>}\n </div>\n );\n}\n\n// fallow-ignore-next-line unused-export\nexport function StatusFrame(props: HyperframesLoaderProps) {\n return (\n <div className=\"hf-frame\">\n <HyperframesLoader {...props} />\n </div>\n );\n}\n","/**\n * Menu and ContextMenu on Base UI. Dismissal is plain Base UI (capture-phase listeners survive the overlay's\n * `stopPropagation`); `trigger` is rendered, not wrapped; `container` exists for shadow roots.\n */\n\nimport { ContextMenu as BaseContextMenu } from \"@base-ui/react/context-menu\";\nimport { Menu as BaseMenu } from \"@base-ui/react/menu\";\nimport { useRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ElementType, ReactElement, ReactNode } from \"react\";\nimport { cn } from \"./cn\";\n\n/**\n * Base UI lets `className` be a function of the part's state. Studio's parts\n * merge a string with `cn`, so the string form is the one they accept.\n */\ntype StyledProps<T extends ElementType> = Omit<ComponentPropsWithoutRef<T>, \"className\"> & {\n className?: string;\n};\n\n/** Forces the settled open look for a gallery shot; CSS-only, open state stays controlled. */\nexport type PopupPreviewState = \"open\";\n\n/** Where the portal puts the popup. `null` keeps it inline, next to its trigger. */\nexport type PortalContainer = ComponentPropsWithoutRef<typeof BaseMenu.Portal>[\"container\"];\n\nconst CONTENTS = { display: \"contents\" } as const;\n\n/** Base UI reads a `null` container as \"not resolved yet\" and renders nothing, so give `null` a host by the trigger. */\nexport function useInlinePortal(container: PortalContainer) {\n const host = useRef<HTMLSpanElement>(null);\n if (container !== null) return { host: null, portal: { container } };\n return {\n host: <span ref={host} style={CONTENTS} />,\n portal: { container: host, style: CONTENTS },\n };\n}\n\n/** Matches Tooltip's gap from its trigger, and its viewport margin. */\nconst SIDE_OFFSET = 6;\nconst VIEWPORT_MARGIN = 8;\n\n/**\n * Enter and exit shared by menus, popovers, dropdowns, and tooltips.\n * The open duration class differs; the shape does not.\n * `data-starting-style`/`data-ending-style` are Base UI's transition attributes.\n */\nexport function floatingMotion(openDuration: \"duration-open\" | \"duration-tooltip\") {\n return cn(\n \"origin-[var(--transform-origin)] outline-hidden\",\n \"transition-[opacity,transform] ease-out-quint\",\n openDuration,\n \"data-[ending-style]:duration-close data-[ending-style]:ease-in\",\n \"data-[starting-style]:[opacity:var(--popup-enter-opacity)]\",\n \"data-[starting-style]:[scale:var(--popup-enter-scale)]\",\n \"data-[ending-style]:opacity-0\",\n );\n}\n\n/**\n * Chrome shared by every floating panel (`Popover` too); callers add their own shadow token.\n */\nexport const popupSurface = cn(\n \"rounded-lg border border-border-input bg-surface\",\n floatingMotion(\"duration-open\"),\n \"data-[preview-state=open]:opacity-100 data-[preview-state=open]:scale-100\",\n);\n\n/** Every floating list, menu, popover and tooltip sits on this layer, above panel chrome and modals. */\nexport const POPUP_LAYER = \"z-200\";\n\nconst menuPopup = cn(popupSurface, \"min-w-36 p-1 shadow-menu\");\n\n/** One row. `data-highlighted` is set by keyboard and pointer alike, so the seen row is the Enter row. */\nconst itemBase = cn(\n \"flex cursor-default select-none items-center justify-between gap-6 rounded-sm px-2 py-1.5\",\n \"text-step-11 whitespace-nowrap text-text-1\",\n \"outline-hidden transition-colors ease-out-quint duration-hover\",\n \"data-[highlighted]:bg-hover data-[highlighted]:text-text-0\",\n \"data-[preview-state=hover]:bg-hover data-[preview-state=hover]:text-text-0\",\n \"data-[disabled]:pointer-events-none data-[disabled]:opacity-40\",\n);\n\nconst itemDanger = cn(\n \"text-danger-ink data-[highlighted]:bg-danger/15 data-[highlighted]:text-danger-ink\",\n);\n\nexport type MenuItemTone = \"default\" | \"danger\";\n\ninterface PositionedProps {\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n sideOffset?: number;\n /** Portal target. Pass the shadow root when the trigger lives in one; `null` keeps it inline. */\n container?: PortalContainer;\n /** Names the popup for assistive tech. A menu with no name is unlabelled. */\n \"aria-label\"?: string;\n className?: string;\n \"data-preview-state\"?: PopupPreviewState;\n}\n\ninterface MenuProps\n extends PositionedProps, Omit<ComponentPropsWithoutRef<typeof BaseMenu.Root>, \"children\"> {\n /** A single element. It becomes the trigger; no wrapper is added around it. */\n trigger: ReactElement;\n /** The items: `MenuItem`, `MenuRadioGroup`, `MenuSeparator`. */\n children: ReactNode;\n}\n\n/**\n * A menu opened by its trigger. Uncontrolled by default; pass `open` and\n * `onOpenChange` for a menu whose state lives in a store.\n */\nexport function Menu({\n trigger,\n children,\n side = \"bottom\",\n align = \"start\",\n sideOffset = SIDE_OFFSET,\n container,\n className,\n \"aria-label\": ariaLabel,\n \"data-preview-state\": previewState,\n ...root\n}: MenuProps) {\n const inline = useInlinePortal(container);\n return (\n <BaseMenu.Root {...root}>\n <BaseMenu.Trigger render={trigger} />\n {inline.host}\n <BaseMenu.Portal {...inline.portal}>\n <BaseMenu.Positioner\n side={side}\n align={align}\n sideOffset={sideOffset}\n collisionPadding={VIEWPORT_MARGIN}\n className={POPUP_LAYER}\n >\n <BaseMenu.Popup\n aria-label={ariaLabel}\n data-preview-state={previewState}\n className={cn(menuPopup, className)}\n >\n {children}\n </BaseMenu.Popup>\n </BaseMenu.Positioner>\n </BaseMenu.Portal>\n </BaseMenu.Root>\n );\n}\n\ninterface ContextMenuProps\n extends PositionedProps, Omit<ComponentPropsWithoutRef<typeof BaseContextMenu.Root>, \"children\"> {\n /**\n * The right-clickable area, as the caller's own element. Its children are\n * kept: the trigger renders that element rather than wrapping it.\n */\n trigger: ReactElement;\n children: ReactNode;\n}\n\n/** Opened by right click or long press at the pointer, so `side` and `align` are not offered. */\nexport function ContextMenu({\n trigger,\n children,\n container,\n className,\n \"aria-label\": ariaLabel,\n \"data-preview-state\": previewState,\n ...root\n}: Omit<ContextMenuProps, \"side\" | \"align\" | \"sideOffset\">) {\n const inline = useInlinePortal(container);\n return (\n <BaseContextMenu.Root {...root}>\n <BaseContextMenu.Trigger render={trigger} />\n {inline.host}\n <BaseContextMenu.Portal {...inline.portal}>\n <BaseContextMenu.Positioner collisionPadding={VIEWPORT_MARGIN} className={POPUP_LAYER}>\n <BaseContextMenu.Popup\n aria-label={ariaLabel}\n data-preview-state={previewState}\n className={cn(menuPopup, className)}\n >\n {children}\n </BaseContextMenu.Popup>\n </BaseContextMenu.Positioner>\n </BaseContextMenu.Portal>\n </BaseContextMenu.Root>\n );\n}\n\n/** Keyboard shortcut hint, mono and tabular; exported for hints that are not a plain string. */\nexport function MenuShortcut({ className, ...props }: StyledProps<\"span\">) {\n return (\n <span\n className={cn(\"shrink-0 font-mono text-step-10 tabular-nums text-text-4\", className)}\n aria-hidden=\"true\"\n {...props}\n />\n );\n}\n\ninterface MenuItemProps extends StyledProps<typeof BaseMenu.Item> {\n /** Rendered as a dim mono hint on the trailing edge. Decorative. */\n shortcut?: string;\n /** `danger` for a destructive action (Delete, Remove). */\n tone?: MenuItemTone;\n \"data-preview-state\"?: \"hover\";\n}\n\n/** One action. `disabled` items are skipped by the arrow keys, not just dimmed. */\nexport function MenuItem({ shortcut, tone, className, children, ...props }: MenuItemProps) {\n return (\n <BaseMenu.Item className={cn(itemBase, tone === \"danger\" && itemDanger, className)} {...props}>\n <span className=\"truncate\">{children}</span>\n {shortcut ? <MenuShortcut>{shortcut}</MenuShortcut> : null}\n </BaseMenu.Item>\n );\n}\n\n/** Single-choice group; selection is `aria-checked` on each item, which the dot indicator draws from. */\nexport function MenuRadioGroup(props: ComponentPropsWithoutRef<typeof BaseMenu.RadioGroup>) {\n return <BaseMenu.RadioGroup {...props} />;\n}\n\ninterface MenuRadioItemProps extends StyledProps<typeof BaseMenu.RadioItem> {\n \"data-preview-state\"?: \"hover\";\n}\n\n/** One choice in a `MenuRadioGroup`. The dot renders only while it is checked. */\nexport function MenuRadioItem({ className, children, ...props }: MenuRadioItemProps) {\n return (\n <BaseMenu.RadioItem className={cn(itemBase, className)} {...props}>\n <span className=\"truncate\">{children}</span>\n {/* Fixed box so a checked and an unchecked row keep the same width. */}\n <span className=\"flex size-3 shrink-0 items-center justify-center\">\n <BaseMenu.RadioItemIndicator className=\"size-1.5 rounded-full bg-accent\" />\n </span>\n </BaseMenu.RadioItem>\n );\n}\n\n/** An on/off row; the tick renders only while `checked`. */\nexport function MenuCheckboxItem({\n className,\n children,\n ...props\n}: StyledProps<typeof BaseMenu.CheckboxItem>) {\n return (\n <BaseMenu.CheckboxItem className={cn(itemBase, className)} {...props}>\n <span className=\"truncate\">{children}</span>\n <span className=\"flex size-3 shrink-0 items-center justify-center text-accent-ink\">\n <BaseMenu.CheckboxItemIndicator>✓</BaseMenu.CheckboxItemIndicator>\n </span>\n </BaseMenu.CheckboxItem>\n );\n}\n\n/** A hairline between two groups of items. */\nexport function MenuSeparator({ className, ...props }: StyledProps<typeof BaseMenu.Separator>) {\n return <BaseMenu.Separator className={cn(\"my-1 h-px bg-hairline\", className)} {...props} />;\n}\n","/**\n * Tooltip: Base UI's tooltip in Studio tokens. The trigger is a box-less\n * `display: contents` wrapper so a disabled control still gets hover.\n */\n\nimport { Tooltip as BaseTooltip } from \"@base-ui/react/tooltip\";\nimport { cloneElement, useId, useRef, useState, type ReactElement } from \"react\";\nimport { cn } from \"./cn\";\nimport { floatingMotion, POPUP_LAYER } from \"./Menu\";\n\ninterface TooltipProps {\n label: string;\n /** A single element, wrapped in a box-less span so a disabled one still gets hover. */\n children: ReactElement<{ \"aria-describedby\"?: string }>;\n /** Hover delay in ms. */\n delay?: number;\n disabled?: boolean;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n}\n\n/** Matches the old bubble's gap from its trigger, and its viewport margin. */\nconst SIDE_OFFSET = 6;\nconst VIEWPORT_MARGIN = 8;\n\nexport function Tooltip({\n label,\n children,\n delay = 400,\n side = \"top\",\n disabled = false,\n}: TooltipProps) {\n const [open, setOpen] = useState(false);\n const boxRef = useRef<HTMLSpanElement>(null);\n const tooltipId = useId();\n\n return (\n <BaseTooltip.Root open={open} onOpenChange={setOpen} disabled={disabled}>\n <BaseTooltip.Trigger delay={delay} render={<span ref={boxRef} className=\"contents\" />}>\n {cloneElement(children, {\n \"aria-describedby\": open && !disabled ? tooltipId : children.props[\"aria-describedby\"],\n })}\n </BaseTooltip.Trigger>\n <BaseTooltip.Portal>\n <BaseTooltip.Positioner\n anchor={() => boxRef.current?.firstElementChild ?? null}\n side={side}\n sideOffset={SIDE_OFFSET}\n collisionPadding={VIEWPORT_MARGIN}\n className={POPUP_LAYER}\n >\n <BaseTooltip.Popup\n id={tooltipId}\n role=\"tooltip\"\n className={cn(\n \"pointer-events-none rounded-md border border-border-input bg-surface px-2 py-1 text-step-10 font-medium text-text-1 whitespace-nowrap shadow-menu\",\n floatingMotion(\"duration-tooltip\"),\n )}\n >\n {label}\n </BaseTooltip.Popup>\n </BaseTooltip.Positioner>\n </BaseTooltip.Portal>\n </BaseTooltip.Root>\n );\n}\n","/**\n * Popover: `Menu`'s floating chrome (`popupSurface`) without item semantics, so arrow keys\n * stay with whatever is focused inside (rename inputs, forms). Only the shadow differs.\n */\n\nimport { Popover as BasePopover } from \"@base-ui/react/popover\";\nimport type { ComponentPropsWithoutRef, ReactElement, ReactNode } from \"react\";\nimport { cn } from \"./cn\";\nimport {\n POPUP_LAYER,\n popupSurface,\n useInlinePortal,\n type PopupPreviewState,\n type PortalContainer,\n} from \"./Menu\";\n\n/** Matches Menu's gap from its trigger, and its viewport margin. */\nconst SIDE_OFFSET = 6;\nconst VIEWPORT_MARGIN = 8;\n\n/** The arrow's 14x8 box overlaps the popup's border by 1px, so its fill hides the border where it meets the popup. */\nconst ARROW_PX = 7;\nconst ARROW_CORNER_CLEARANCE = 10;\nconst arrowPlace = cn(\n \"data-[side=bottom]:-top-[7px] data-[side=top]:-bottom-[7px] data-[side=top]:rotate-180\",\n \"data-[side=left]:-right-[10px] data-[side=left]:rotate-90\",\n \"data-[side=right]:-left-[10px] data-[side=right]:-rotate-90\",\n);\n\ninterface PopoverProps extends Omit<ComponentPropsWithoutRef<typeof BasePopover.Root>, \"children\"> {\n /** A single element. It becomes the trigger; no wrapper is added around it. */\n trigger: ReactElement;\n /** Arbitrary content. The popover owns none of its keys. */\n children: ReactNode;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n sideOffset?: number;\n /** Points the popup at its trigger. Off by default; the default gap from the trigger grows by the arrow's height. */\n arrow?: boolean;\n /** Portal target. Pass the shadow root when the trigger lives in one; `null` keeps it inline. */\n container?: PortalContainer;\n /** Names the popup for assistive tech. */\n \"aria-label\"?: string;\n /**\n * What to focus on open. Defaults to Base UI's behaviour (the first tabbable\n * element), which is what a rename field wants.\n */\n initialFocus?: ComponentPropsWithoutRef<typeof BasePopover.Popup>[\"initialFocus\"];\n className?: string;\n \"data-preview-state\"?: PopupPreviewState;\n}\n\nexport function Popover({\n trigger,\n children,\n side = \"bottom\",\n align = \"center\",\n arrow = false,\n sideOffset = arrow ? SIDE_OFFSET + ARROW_PX : SIDE_OFFSET,\n container,\n className,\n initialFocus,\n \"aria-label\": ariaLabel,\n \"data-preview-state\": previewState,\n ...root\n}: PopoverProps) {\n const inline = useInlinePortal(container);\n return (\n <BasePopover.Root {...root}>\n <BasePopover.Trigger render={trigger} />\n {inline.host}\n <BasePopover.Portal {...inline.portal}>\n <BasePopover.Positioner\n side={side}\n align={align}\n sideOffset={sideOffset}\n collisionPadding={VIEWPORT_MARGIN}\n arrowPadding={ARROW_CORNER_CLEARANCE}\n className={POPUP_LAYER}\n >\n <BasePopover.Popup\n aria-label={ariaLabel}\n initialFocus={initialFocus}\n data-preview-state={previewState}\n className={cn(popupSurface, \"p-3 text-step-11 text-text-1 shadow-popover\", className)}\n >\n {arrow && (\n <BasePopover.Arrow className={arrowPlace}>\n <svg width=\"14\" height=\"8\" viewBox=\"0 0 14 8\" aria-hidden=\"true\" className=\"block\">\n <path d=\"M0 8 L7 1 L14 8\" className=\"fill-surface stroke-border-input\" />\n </svg>\n </BasePopover.Arrow>\n )}\n {children}\n </BasePopover.Popup>\n </BasePopover.Positioner>\n </BasePopover.Portal>\n </BasePopover.Root>\n );\n}\n","/**\n * Input: a boxed text field. Typing edits a local draft; Enter and blur commit it,\n * Escape abandons it. `onTrack` fires once per commit, never per keystroke.\n */\n\nimport { Input as BaseInput } from \"@base-ui/react/input\";\nimport { useEffect, useRef, useState, type ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"./cn\";\nimport type { PreviewState } from \"./Button\";\n\n/**\n * Shared field look (also used by NumberField and Select). Each interactive state is written\n * twice, real and `data-[preview-state=...]`; `valueControls.test.tsx` asserts the lists match.\n */\nexport const fieldBase = cn(\n \"flex min-w-0 items-center gap-1.5 h-ctl px-2 rounded-md\",\n \"bg-input border border-border-input text-step-11 font-medium text-text-1\",\n \"transition-[border-color,background-color] ease-standard duration-focus\",\n \"hover:border-border-strong data-[preview-state=hover]:border-border-strong\",\n \"outline-hidden\",\n \"focus-within:outline-solid focus-within:outline-2 focus-within:outline-offset-1 focus-within:outline-accent\",\n \"data-[preview-state=focus]:outline-solid data-[preview-state=focus]:outline-2 data-[preview-state=focus]:outline-offset-1 data-[preview-state=focus]:outline-accent\",\n // `aria-invalid` is not one of Tailwind's built-in aria variants, so the\n // arbitrary form is the one that compiles. The token gate would have caught\n // the bare `aria-invalid:` spelling as a class that resolves to nothing.\n \"aria-[invalid]:border-danger-ink\",\n \"has-[:disabled]:opacity-40 has-[:disabled]:cursor-not-allowed\",\n);\n\n/** The text itself, inside the box. The box owns the border and the ring. */\nexport const fieldText = cn(\n \"min-w-0 w-full bg-transparent text-inherit outline-hidden\",\n \"placeholder:text-text-5 disabled:cursor-not-allowed\",\n);\n\nexport interface InputProps extends Omit<\n ComponentPropsWithoutRef<\"input\">,\n \"value\" | \"onChange\" | \"className\"\n> {\n /** The committed value. A draft lives inside until Enter or blur. */\n value: string;\n /** Called with the draft on Enter and on blur, only when it really changed. */\n onCommit: (next: string) => void;\n /** Called once per committed change, for design-input telemetry. */\n onTrack?: () => void;\n /** Marks the field invalid: red boundary and `aria-invalid`. */\n invalid?: boolean;\n className?: string;\n \"data-preview-state\"?: PreviewState;\n}\n\nexport function Input({\n value,\n onCommit,\n onTrack,\n invalid,\n disabled,\n className,\n \"data-preview-state\": previewState,\n ...props\n}: InputProps) {\n const [draft, setDraft] = useState(value);\n const valueRef = useRef(value);\n valueRef.current = value;\n const dirtyRef = useRef(false);\n\n // An external write (a seek, an undo, another panel) is authoritative, but it\n // must not eat what the user is halfway through typing.\n useEffect(() => {\n if (!dirtyRef.current) setDraft(value);\n }, [value]);\n\n const commit = (next: string) => {\n dirtyRef.current = false;\n if (next === valueRef.current) return;\n onCommit(next);\n onTrack?.();\n };\n\n return (\n <div\n className={cn(fieldBase, className)}\n aria-invalid={invalid || undefined}\n data-preview-state={previewState}\n >\n <BaseInput\n value={draft}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n className={fieldText}\n onValueChange={(next) => {\n dirtyRef.current = true;\n setDraft(next);\n }}\n onBlur={() => commit(draft)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n commit(draft);\n return;\n }\n if (event.key === \"Escape\") {\n // Abandon the draft rather than leave it for the blur commit.\n event.preventDefault();\n event.stopPropagation();\n dirtyRef.current = false;\n setDraft(valueRef.current);\n event.currentTarget.blur();\n }\n }}\n {...props}\n />\n </div>\n );\n}\n","/**\n * NumberField: the inspector's metric control. Commits only on blur, Enter, or a settled step (KTD11),\n * never per keystroke. The unit is a sibling of the input; unparseable text shows a red boundary and commits nothing.\n */\n\nimport { NumberField as BaseNumberField } from \"@base-ui/react/number-field\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { cn } from \"./cn\";\nimport { fieldBase, fieldText } from \"./Input\";\nimport type { PreviewState } from \"./Button\";\n\nexport interface NumberFieldProps {\n /** Accessible name. The inspector's row label is the usual one. */\n label: string;\n /** The committed value. */\n value: number;\n /** Called when a commit boundary produces a value different from `value`. */\n onCommit: (next: number) => void;\n /** Called once per committed change, for design-input telemetry. */\n onTrack?: () => void;\n /** Rendered beside the number: \"px\", \"%\", \"deg\". Never part of the text. */\n unit?: string;\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n className?: string;\n \"data-preview-state\"?: PreviewState;\n}\n\nexport function NumberField({\n label,\n value,\n onCommit,\n onTrack,\n unit,\n min,\n max,\n step,\n disabled,\n className,\n \"data-preview-state\": previewState,\n}: NumberFieldProps) {\n const [draft, setDraft] = useState<number | null>(value);\n const [invalid, setInvalid] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n // What was last handed to `onCommit`, which is not the same as `value`: a\n // blur can fire both Base UI's commit and ours in one turn, before the parent\n // has re-rendered with the new prop, and the second must be a no-op.\n const committedRef = useRef(value);\n const valueRef = useRef(value);\n valueRef.current = value;\n\n useEffect(() => {\n committedRef.current = value;\n setDraft(value);\n setInvalid(false);\n }, [value]);\n\n const commit = (next: number | null) => {\n if (next === null || !Number.isFinite(next)) {\n setInvalid(true);\n return;\n }\n setInvalid(false);\n if (next === committedRef.current) return;\n committedRef.current = next;\n onCommit(next);\n onTrack?.();\n };\n\n /** Enter commits what is on screen, which Base UI has not parsed for us yet. */\n const commitFromText = () => {\n const text = inputRef.current?.value.trim() ?? \"\";\n commit(text === \"\" ? null : Number(text));\n };\n\n return (\n <BaseNumberField.Root\n value={draft}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onValueChange={(next) => {\n setDraft(next);\n if (next !== null) setInvalid(false);\n }}\n onValueCommitted={(next) => commit(next)}\n >\n <BaseNumberField.Group\n className={cn(fieldBase, className)}\n aria-invalid={invalid || undefined}\n data-preview-state={previewState}\n >\n <BaseNumberField.Input\n ref={inputRef}\n aria-label={label}\n aria-invalid={invalid || undefined}\n className={cn(fieldText, \"tabular-nums\")}\n onKeyDown={(event) => {\n if (event.key !== \"Enter\") return;\n event.preventDefault();\n commitFromText();\n }}\n onBlur={() => {\n // Base UI's own blur handler returns without committing when the\n // text does not parse. That is the only case left for us: a valid\n // blur has already arrived through `onValueCommitted`.\n const text = inputRef.current?.value.trim() ?? \"\";\n if (text === \"\" || !Number.isFinite(Number(text))) setInvalid(true);\n }}\n />\n {unit && (\n <span className=\"shrink-0 select-none text-step-10 text-text-4\" aria-hidden=\"true\">\n {unit}\n </span>\n )}\n </BaseNumberField.Group>\n </BaseNumberField.Root>\n );\n}\n","/**\n * Select: Base UI select in Input's box. The trigger keeps `role=\"combobox\"`, which both hotkey selector\n * lists match. Options are data, not children, so typeahead and the value display can read labels.\n */\n\nimport { Select as BaseSelect } from \"@base-ui/react/select\";\nimport { cn } from \"./cn\";\nimport { fieldBase } from \"./Input\";\nimport { floatingMotion, POPUP_LAYER } from \"./Menu\";\nimport type { PreviewState } from \"./Button\";\n\nexport interface SelectOption {\n label: string;\n value: string;\n /** Offered but not choosable; the label stays visible so the reason stays visible too. */\n disabled?: boolean;\n}\n\nexport interface SelectProps {\n /** Accessible name for the trigger. */\n label: string;\n value: string;\n options: SelectOption[];\n /** Called when a different option is chosen. */\n onCommit: (next: string) => void;\n /** Called once per committed change, for design-input telemetry. */\n onTrack?: () => void;\n disabled?: boolean;\n className?: string;\n \"data-preview-state\"?: PreviewState;\n}\n\nexport function Select({\n label,\n value,\n options,\n onCommit,\n onTrack,\n disabled,\n className,\n \"data-preview-state\": previewState,\n}: SelectProps) {\n return (\n <BaseSelect.Root\n value={value}\n disabled={disabled}\n items={options}\n onValueChange={(next) => {\n const chosen = String(next);\n if (chosen === value) return;\n onCommit(chosen);\n onTrack?.();\n }}\n >\n <BaseSelect.Trigger\n aria-label={label}\n className={cn(\n fieldBase,\n \"w-full cursor-pointer justify-between text-left\",\n \"data-[popup-open]:border-border-strong\",\n className,\n )}\n data-preview-state={previewState}\n >\n <BaseSelect.Value className=\"truncate\" />\n <BaseSelect.Icon className=\"shrink-0 text-text-4\" aria-hidden=\"true\">\n <svg width=\"8\" height=\"5\" viewBox=\"0 0 8 5\" fill=\"none\">\n <path\n d=\"M1 1L4 4L7 1\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </BaseSelect.Icon>\n </BaseSelect.Trigger>\n\n <BaseSelect.Portal>\n <BaseSelect.Positioner sideOffset={4} alignItemWithTrigger={false} className={POPUP_LAYER}>\n <BaseSelect.Popup\n className={cn(\n \"min-w-[var(--anchor-width)] rounded-md border border-border bg-surface py-1 shadow-menu\",\n floatingMotion(\"duration-open\"),\n )}\n >\n <BaseSelect.List>\n {options.map((option) => (\n <BaseSelect.Item\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n className={cn(\n \"flex h-ctl-sm cursor-pointer select-none items-center gap-2 px-2.5\",\n \"text-step-11 text-text-2 outline-hidden\",\n \"data-[highlighted]:bg-hover data-[highlighted]:text-text-0\",\n \"data-[selected]:text-text-0\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-40\",\n )}\n >\n <BaseSelect.ItemText className=\"truncate\">{option.label}</BaseSelect.ItemText>\n </BaseSelect.Item>\n ))}\n </BaseSelect.List>\n </BaseSelect.Popup>\n </BaseSelect.Positioner>\n </BaseSelect.Portal>\n </BaseSelect.Root>\n );\n}\n","/**\n * Slider: `onPreview` fires while the thumb moves and writes nothing durable; `onCommit` (with `onTrack`, once)\n * fires at a boundary. Right-click or Escape aborts a drag via `eventDetails.cancel()` and restores the start value.\n */\n\nimport { Slider as BaseSlider } from \"@base-ui/react/slider\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { cn } from \"./cn\";\nimport type { PreviewState } from \"./Button\";\n\nexport interface SliderProps {\n /** Accessible name for the thumb. The inspector's row label is the usual one. */\n label: string;\n /** The committed value. */\n value: number;\n min: number;\n max: number;\n step?: number;\n /** Every intermediate value while dragging or stepping. Not a commit. */\n onPreview?: (next: number) => void;\n /** Called at a commit boundary when the value really changed. */\n onCommit: (next: number) => void;\n /** Called once per commit boundary, for design-input telemetry. */\n onTrack?: () => void;\n disabled?: boolean;\n className?: string;\n \"data-preview-state\"?: PreviewState;\n}\n\nconst first = (next: number | number[]): number => (Array.isArray(next) ? next[0] : next);\n\nexport function Slider({\n label,\n value,\n min,\n max,\n step,\n onPreview,\n onCommit,\n onTrack,\n disabled,\n className,\n \"data-preview-state\": previewState,\n}: SliderProps) {\n const [draft, setDraft] = useState(value);\n const draggingRef = useRef(false);\n const abortedRef = useRef(false);\n // The committed value the current gesture started from, so an abort has\n // something to put back.\n const dragStartRef = useRef(value);\n // What was last handed to `onCommit`. A gesture's own commit lands before the\n // parent re-renders, so deduping against the `value` prop would double-fire.\n const committedRef = useRef(value);\n const valueRef = useRef(value);\n valueRef.current = value;\n\n // An external write wins, except mid-drag: the echo is a frame behind, and\n // applying it would snap the thumb backwards under the pointer.\n useEffect(() => {\n if (draggingRef.current) return;\n committedRef.current = value;\n setDraft(value);\n }, [value]);\n\n const commit = (next: number) => {\n if (next === committedRef.current) return;\n committedRef.current = next;\n onCommit(next);\n };\n\n const abort = () => {\n if (!draggingRef.current) return;\n abortedRef.current = true;\n const start = dragStartRef.current;\n setDraft(start);\n onPreview?.(start);\n commit(start);\n };\n\n return (\n <BaseSlider.Root\n value={draft}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onValueChange={(next, details) => {\n if (abortedRef.current) {\n // The pointer is still down after a right-click abort. Base UI would\n // otherwise keep applying moves to a gesture the user cancelled.\n details.cancel();\n return;\n }\n const n = first(next);\n setDraft(n);\n onPreview?.(n);\n }}\n onValueCommitted={(next) => {\n draggingRef.current = false;\n if (abortedRef.current) {\n abortedRef.current = false;\n return;\n }\n commit(first(next));\n onTrack?.();\n }}\n className={cn(\"flex min-w-0 items-center\", className)}\n data-preview-state={previewState}\n >\n <BaseSlider.Control\n // A stable hook for the drag tests and for the screenshot script. Base\n // UI's own marker on this part only exists before hydration.\n data-slider-control=\"true\"\n // h-6 is the 24x24 WCAG 2.2 (2.5.8) target: the visible track stays\n // 2px, only the pointer box grows.\n className=\"flex h-6 w-full min-w-0 touch-none select-none items-center\"\n onPointerDown={() => {\n draggingRef.current = true;\n abortedRef.current = false;\n dragStartRef.current = valueRef.current;\n }}\n onContextMenu={(event) => {\n if (!draggingRef.current) return;\n event.preventDefault();\n abort();\n }}\n onKeyDown={(event) => {\n if (event.key !== \"Escape\" || !draggingRef.current) return;\n event.preventDefault();\n abort();\n }}\n >\n <BaseSlider.Track className=\"h-0.5 w-full rounded-full bg-hover\">\n <BaseSlider.Indicator className=\"rounded-full bg-text-5\" />\n <BaseSlider.Thumb\n aria-label={label}\n className={cn(\n // The ring separates the thumb from the track behind it. A drop\n // shadow would need a raw colour literal, which R5 does not allow\n // outside the token file, and no shadow token fits a 10px dot.\n \"size-2.5 rounded-full bg-text-0 ring-2 ring-bg-1\",\n \"cursor-grab active:cursor-grabbing data-[preview-state=active]:cursor-grabbing\",\n \"hover:scale-110 data-[preview-state=hover]:scale-110\",\n \"transition-transform ease-standard duration-hover\",\n \"has-[:focus-visible]:outline-solid has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-accent\",\n \"data-[preview-state=focus]:outline-solid data-[preview-state=focus]:outline-2 data-[preview-state=focus]:outline-offset-2 data-[preview-state=focus]:outline-accent\",\n )}\n />\n </BaseSlider.Track>\n </BaseSlider.Control>\n </BaseSlider.Root>\n );\n}\n","/**\n * Toggle: a switch, not a checkbox (immediate effect). `role=\"switch\"` needed an entry in\n * `typingTarget.ts` so Space is not leaked to the global playback shortcut.\n */\n\nimport { Switch } from \"@base-ui/react/switch\";\nimport { cn } from \"./cn\";\nimport type { PreviewState } from \"./Button\";\n\nexport interface ToggleProps {\n /** Accessible name. */\n label: string;\n checked: boolean;\n /** Called on every flip. */\n onCommit: (next: boolean) => void;\n /** Called once per flip, for design-input telemetry. */\n onTrack?: () => void;\n disabled?: boolean;\n className?: string;\n \"data-preview-state\"?: PreviewState;\n}\n\nexport function Toggle({\n label,\n checked,\n onCommit,\n onTrack,\n disabled,\n className,\n \"data-preview-state\": previewState,\n}: ToggleProps) {\n return (\n <Switch.Root\n aria-label={label}\n checked={checked}\n disabled={disabled}\n onCheckedChange={(next) => {\n onCommit(next);\n onTrack?.();\n }}\n data-preview-state={previewState}\n className={cn(\n \"relative inline-flex h-4 w-7 shrink-0 cursor-pointer items-center rounded-full p-0.5\",\n \"border border-border-input bg-input\",\n \"transition-[background-color,border-color] ease-standard duration-press\",\n \"hover:border-border-strong data-[preview-state=hover]:border-border-strong\",\n \"data-[checked]:border-accent data-[checked]:bg-accent\",\n \"outline-hidden focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-accent\",\n \"data-[preview-state=focus]:outline-solid data-[preview-state=focus]:outline-2 data-[preview-state=focus]:outline-offset-1 data-[preview-state=focus]:outline-accent\",\n \"disabled:cursor-not-allowed disabled:opacity-40\",\n className,\n )}\n >\n <Switch.Thumb\n className={cn(\n \"size-3 rounded-full bg-text-3\",\n \"transition-[transform,background-color] ease-standard duration-press\",\n \"data-[checked]:translate-x-3 data-[checked]:bg-bg-0\",\n )}\n />\n </Switch.Root>\n );\n}\n"],"mappings":";AAMA,SAAS,gBAAgB;AAGzB,IAAM,aAAa,CAAC,UAAkB,aAAa,KAAK,KAAK;AAG7D,IAAM,gBAAgB,CAAC,UAAkB,kBAAkB,KAAK,KAAK;AAE9D,IAAM,KAAiB,SAAS;AAAA,EACrC,QAAQ;AAAA,IACN,aAAa;AAAA,MACX,aAAa,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;AAAA,MACpC,GAAG,CAAC,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC;AAAA,MAC1B,GAAG,CAAC,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC;AAAA,MAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC;AAAA,MAChC,SAAS,CAAC,EAAE,SAAS,CAAC,aAAa,EAAE,CAAC;AAAA,MACtC,SAAS,CAAC,EAAE,SAAS,CAAC,aAAa,EAAE,CAAC;AAAA,IACxC;AAAA,EACF;AACF,CAAC;;;ACZD,SAAS,kBAA6D;AAwElE,SACE,KADF;AAhDG,IAAM,aAAa;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,IAAM,iBAAgD;AAAA,EAC3D,SAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAMO,IAAM,cAA0C;AAAA,EACrD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,SAAS,UAAU;AACjB,SACE,qBAAC,SAAI,WAAU,yBAAwB,SAAQ,aAAY,MAAK,QAAO,eAAY,QACjF;AAAA,wBAAC,YAAO,WAAU,cAAa,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,QAAO,gBAAe,aAAY,KAAI;AAAA,IAC5F;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,MAAK;AAAA,QACL,GAAE;AAAA;AAAA,IACJ;AAAA,KACF;AAEJ;AAEO,IAAM,SAAS;AAAA,EACpB,CACE,EAAE,UAAU,aAAa,OAAO,MAAM,SAAS,MAAM,UAAU,WAAW,UAAU,GAAG,MAAM,GAC7F,QACG;AACH,UAAM,aAAa,YAAY;AAC/B,QAAI,UAAqB;AACzB,QAAI,QAAS,WAAU,oBAAC,WAAQ;AAAA,aACvB,KAAM,WAAU,oBAAC,UAAK,WAAU,YAAY,gBAAK;AAC1D,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,UAAU;AAAA,QAGV,iBAAe,cAAc;AAAA,QAC7B,WAAW,GAAG,YAAY,eAAe,OAAO,GAAG,YAAY,IAAI,GAAG,SAAS;AAAA,QAC9E,GAAG;AAAA,QAEH;AAAA;AAAA,UACA;AAAA;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AACA,OAAO,cAAc;;;ACpHrB,SAAS,cAAAA,mBAAkB;AAoBrB,gBAAAC,YAAA;AATN,IAAM,iBAA6C;AAAA,EACjD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEO,IAAM,aAAaC;AAAA,EACxB,CAAC,EAAE,MAAM,OAAO,MAAM,UAAU,SAAS,WAAW,UAAU,GAAG,MAAM,GAAG,QAAQ;AAChF,WACE,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,iBAAe,YAAY;AAAA,QAC3B,WAAW,GAAG,YAAY,eAAe,OAAO,GAAG,eAAe,IAAI,GAAG,SAAS;AAAA,QACjF,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;;;AChCzB,SAAS,QAAQ,gBAAgB;AAkBxB,gBAAAE,YAAA;AADF,SAAS,KAAK,OAAuD;AAC1E,SAAO,gBAAAA,KAAC,SAAS,MAAT,EAAe,GAAG,OAAO;AACnC;AAGO,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAsC;AACnF,SACE,gBAAAA;AAAA,IAAC,SAAS;AAAA,IAAT;AAAA,MAEC,iBAAe;AAAA,MACf,WAAW,GAAG,kEAAkE,SAAS;AAAA,MACxF,GAAG;AAAA;AAAA,EACN;AAEJ;AAWO,SAAS,IAAI,EAAE,OAAO,WAAW,GAAG,MAAM,GAAa;AAC5D,SACE,gBAAAA;AAAA,IAAC,SAAS;AAAA,IAAT;AAAA,MACC;AAAA,MACA,eAAa;AAAA,MACb,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAGO,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAuC;AACpF,SAAO,gBAAAA,KAAC,SAAS,OAAT,EAAe,WAAW,GAAG,kBAAkB,SAAS,GAAI,GAAG,OAAO;AAChF;;;ACtEA,SAAS,aAA4B;AAe7B,SACE,OAAAC,MADF,QAAAC,aAAA;AAbD,SAAS,gBAAgB,EAAE,UAAU,eAAe,GAAG,MAAM,GAA4B;AAC9F,QAAM,aAAa,MAAM;AACzB,QAAM,eAAe,GAAG,UAAU;AAClC,QAAM,gBAAgB,GAAG,UAAU;AACnC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAK;AAAA,MACL,OAAM;AAAA,MACN,eAAY;AAAA,MACX,GAAG;AAAA,MAEJ;AAAA,wBAAAD,KAAC,OAAE,WAAU,oBAAmB,SAAQ,OACtC,0BAAAC,MAAC,OAAE,WAAU,sBACX;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,GAAE;AAAA,cACF,MAAM,QAAQ,YAAY;AAAA;AAAA,UAC5B;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,GAAE;AAAA,cACF,MAAM,QAAQ,aAAa;AAAA;AAAA,UAC7B;AAAA,WACF,GACF;AAAA,QACA,gBAAAC,MAAC,UACC;AAAA,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,IAAI;AAAA,cACJ,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,eAAc;AAAA,cAEd;AAAA,gCAAAD,KAAC,UAAK,WAAU,WAAU;AAAA,gBAC1B,gBAAAA,KAAC,UAAK,QAAO,KAAI,WAAU,WAAU;AAAA;AAAA;AAAA,UACvC;AAAA,UACA,gBAAAC;AAAA,YAAC;AAAA;AAAA,cACC,IAAI;AAAA,cACJ,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,eAAc;AAAA,cAEd;AAAA,gCAAAD,KAAC,UAAK,WAAU,WAAU;AAAA,gBAC1B,gBAAAA,KAAC,UAAK,QAAO,KAAI,WAAU,WAAU;AAAA;AAAA;AAAA,UACvC;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACvBI,SAMI,OAAAE,MANJ,QAAAC,aAAA;AAdG,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AACF,GAA2B;AACzB,QAAM,kBACJ,OAAO,aAAa,YAAY,OAAO,SAAS,QAAQ,IACpD,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC,IACjC;AACN,QAAM,gBAAgB,KAAK,MAAM,OAAO,IAAI;AAE5C,SACE,gBAAAA,MAAC,SAAI,WAAU,aAAY,MAAK,UAAS,WAAW,OAClD;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,OAAO,eAAe,QAAQ,cAAc;AAAA,QACrD,WAAW;AAAA,QAEX,0BAAAA,KAAC,mBAAgB,WAAU,kBAAiB,OAAO,MAAM,QAAQ,MAAM;AAAA;AAAA,IACzE;AAAA,IACA,gBAAAA,KAAC,SAAI,WAAU,mBAAmB,iBAAM;AAAA,IACvC,UAAU,gBAAAA,KAAC,SAAI,WAAU,oBAAoB,kBAAO;AAAA,IACpD,oBAAoB,UACnB,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,MAAK;AAAA,QACL,iBAAe;AAAA,QACf,iBAAe;AAAA,QACf,iBAAe,KAAK,MAAM,kBAAkB,GAAG;AAAA,QAE/C,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,WAAW,UAAU,eAAe,IAAI;AAAA;AAAA,QACnD;AAAA;AAAA,IACF;AAAA,IAED,QAAQ,gBAAAA,KAAC,SAAI,WAAU,kBAAkB,gBAAK;AAAA,KACjD;AAEJ;;;ACnDA,SAAS,eAAe,uBAAuB;AAC/C,SAAS,QAAQ,gBAAgB;AACjC,SAAS,cAAc;AAyBb,gBAAAE,MA8FN,QAAAC,aA9FM;AAPV,IAAM,WAAW,EAAE,SAAS,WAAW;AAGhC,SAAS,gBAAgB,WAA4B;AAC1D,QAAM,OAAO,OAAwB,IAAI;AACzC,MAAI,cAAc,KAAM,QAAO,EAAE,MAAM,MAAM,QAAQ,EAAE,UAAU,EAAE;AACnE,SAAO;AAAA,IACL,MAAM,gBAAAD,KAAC,UAAK,KAAK,MAAM,OAAO,UAAU;AAAA,IACxC,QAAQ,EAAE,WAAW,MAAM,OAAO,SAAS;AAAA,EAC7C;AACF;AAGA,IAAM,cAAc;AACpB,IAAM,kBAAkB;AAOjB,SAAS,eAAe,cAAoD;AACjF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKO,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA,eAAe,eAAe;AAAA,EAC9B;AACF;AAGO,IAAM,cAAc;AAE3B,IAAM,YAAY,GAAG,cAAc,0BAA0B;AAG7D,IAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,aAAa;AAAA,EACjB;AACF;AA4BO,SAAS,KAAK;AAAA,EACnB;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,sBAAsB;AAAA,EACtB,GAAG;AACL,GAAc;AACZ,QAAM,SAAS,gBAAgB,SAAS;AACxC,SACE,gBAAAC,MAAC,SAAS,MAAT,EAAe,GAAG,MACjB;AAAA,oBAAAD,KAAC,SAAS,SAAT,EAAiB,QAAQ,SAAS;AAAA,IAClC,OAAO;AAAA,IACR,gBAAAA,KAAC,SAAS,QAAT,EAAiB,GAAG,OAAO,QAC1B,0BAAAA;AAAA,MAAC,SAAS;AAAA,MAAT;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,kBAAkB;AAAA,QAClB,WAAW;AAAA,QAEX,0BAAAA;AAAA,UAAC,SAAS;AAAA,UAAT;AAAA,YACC,cAAY;AAAA,YACZ,sBAAoB;AAAA,YACpB,WAAW,GAAG,WAAW,SAAS;AAAA,YAEjC;AAAA;AAAA,QACH;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;AAaO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,sBAAsB;AAAA,EACtB,GAAG;AACL,GAA4D;AAC1D,QAAM,SAAS,gBAAgB,SAAS;AACxC,SACE,gBAAAC,MAAC,gBAAgB,MAAhB,EAAsB,GAAG,MACxB;AAAA,oBAAAD,KAAC,gBAAgB,SAAhB,EAAwB,QAAQ,SAAS;AAAA,IACzC,OAAO;AAAA,IACR,gBAAAA,KAAC,gBAAgB,QAAhB,EAAwB,GAAG,OAAO,QACjC,0BAAAA,KAAC,gBAAgB,YAAhB,EAA2B,kBAAkB,iBAAiB,WAAW,aACxE,0BAAAA;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,cAAY;AAAA,QACZ,sBAAoB;AAAA,QACpB,WAAW,GAAG,WAAW,SAAS;AAAA,QAEjC;AAAA;AAAA,IACH,GACF,GACF;AAAA,KACF;AAEJ;AAGO,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAwB;AACzE,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,4DAA4D,SAAS;AAAA,MACnF,eAAY;AAAA,MACX,GAAG;AAAA;AAAA,EACN;AAEJ;AAWO,SAAS,SAAS,EAAE,UAAU,MAAM,WAAW,UAAU,GAAG,MAAM,GAAkB;AACzF,SACE,gBAAAC,MAAC,SAAS,MAAT,EAAc,WAAW,GAAG,UAAU,SAAS,YAAY,YAAY,SAAS,GAAI,GAAG,OACtF;AAAA,oBAAAD,KAAC,UAAK,WAAU,YAAY,UAAS;AAAA,IACpC,WAAW,gBAAAA,KAAC,gBAAc,oBAAS,IAAkB;AAAA,KACxD;AAEJ;AAGO,SAAS,eAAe,OAA6D;AAC1F,SAAO,gBAAAA,KAAC,SAAS,YAAT,EAAqB,GAAG,OAAO;AACzC;AAOO,SAAS,cAAc,EAAE,WAAW,UAAU,GAAG,MAAM,GAAuB;AACnF,SACE,gBAAAC,MAAC,SAAS,WAAT,EAAmB,WAAW,GAAG,UAAU,SAAS,GAAI,GAAG,OAC1D;AAAA,oBAAAD,KAAC,UAAK,WAAU,YAAY,UAAS;AAAA,IAErC,gBAAAA,KAAC,UAAK,WAAU,oDACd,0BAAAA,KAAC,SAAS,oBAAT,EAA4B,WAAU,mCAAkC,GAC3E;AAAA,KACF;AAEJ;AAGO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA8C;AAC5C,SACE,gBAAAC,MAAC,SAAS,cAAT,EAAsB,WAAW,GAAG,UAAU,SAAS,GAAI,GAAG,OAC7D;AAAA,oBAAAD,KAAC,UAAK,WAAU,YAAY,UAAS;AAAA,IACrC,gBAAAA,KAAC,UAAK,WAAU,oEACd,0BAAAA,KAAC,SAAS,uBAAT,EAA+B,oBAAC,GACnC;AAAA,KACF;AAEJ;AAGO,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAA2C;AAC7F,SAAO,gBAAAA,KAAC,SAAS,WAAT,EAAmB,WAAW,GAAG,yBAAyB,SAAS,GAAI,GAAG,OAAO;AAC3F;;;AC/PA,SAAS,WAAW,mBAAmB;AACvC,SAAS,cAAc,SAAAE,QAAO,UAAAC,SAAQ,gBAAmC;AA8BrE,SAC6C,OAAAC,MAD7C,QAAAC,aAAA;AAfJ,IAAMC,eAAc;AACpB,IAAMC,mBAAkB;AAEjB,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AACb,GAAiB;AACf,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,SAASC,QAAwB,IAAI;AAC3C,QAAM,YAAYC,OAAM;AAExB,SACE,gBAAAJ,MAAC,YAAY,MAAZ,EAAiB,MAAY,cAAc,SAAS,UACnD;AAAA,oBAAAD,KAAC,YAAY,SAAZ,EAAoB,OAAc,QAAQ,gBAAAA,KAAC,UAAK,KAAK,QAAQ,WAAU,YAAW,GAChF,uBAAa,UAAU;AAAA,MACtB,oBAAoB,QAAQ,CAAC,WAAW,YAAY,SAAS,MAAM,kBAAkB;AAAA,IACvF,CAAC,GACH;AAAA,IACA,gBAAAA,KAAC,YAAY,QAAZ,EACC,0BAAAA;AAAA,MAAC,YAAY;AAAA,MAAZ;AAAA,QACC,QAAQ,MAAM,OAAO,SAAS,qBAAqB;AAAA,QACnD;AAAA,QACA,YAAYE;AAAA,QACZ,kBAAkBC;AAAA,QAClB,WAAW;AAAA,QAEX,0BAAAH;AAAA,UAAC,YAAY;AAAA,UAAZ;AAAA,YACC,IAAI;AAAA,YACJ,MAAK;AAAA,YACL,WAAW;AAAA,cACT;AAAA,cACA,eAAe,kBAAkB;AAAA,YACnC;AAAA,YAEC;AAAA;AAAA,QACH;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;;;AC3DA,SAAS,WAAW,mBAAmB;AAgEjC,gBAAAM,MAWI,QAAAC,aAXJ;AApDN,IAAMC,eAAc;AACpB,IAAMC,mBAAkB;AAGxB,IAAM,WAAW;AACjB,IAAM,yBAAyB;AAC/B,IAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AACF;AAyBO,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,aAAa,QAAQD,eAAc,WAAWA;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,sBAAsB;AAAA,EACtB,GAAG;AACL,GAAiB;AACf,QAAM,SAAS,gBAAgB,SAAS;AACxC,SACE,gBAAAD,MAAC,YAAY,MAAZ,EAAkB,GAAG,MACpB;AAAA,oBAAAD,KAAC,YAAY,SAAZ,EAAoB,QAAQ,SAAS;AAAA,IACrC,OAAO;AAAA,IACR,gBAAAA,KAAC,YAAY,QAAZ,EAAoB,GAAG,OAAO,QAC7B,0BAAAA;AAAA,MAAC,YAAY;AAAA,MAAZ;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,kBAAkBG;AAAA,QAClB,cAAc;AAAA,QACd,WAAW;AAAA,QAEX,0BAAAF;AAAA,UAAC,YAAY;AAAA,UAAZ;AAAA,YACC,cAAY;AAAA,YACZ;AAAA,YACA,sBAAoB;AAAA,YACpB,WAAW,GAAG,cAAc,+CAA+C,SAAS;AAAA,YAEnF;AAAA,uBACC,gBAAAD,KAAC,YAAY,OAAZ,EAAkB,WAAW,YAC5B,0BAAAA,KAAC,SAAI,OAAM,MAAK,QAAO,KAAI,SAAQ,YAAW,eAAY,QAAO,WAAU,SACzE,0BAAAA,KAAC,UAAK,GAAE,mBAAkB,WAAU,oCAAmC,GACzE,GACF;AAAA,cAED;AAAA;AAAA;AAAA,QACH;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;;;AC9FA,SAAS,SAAS,iBAAiB;AACnC,SAAS,WAAW,UAAAI,SAAQ,YAAAC,iBAA+C;AA+ErE,gBAAAC,YAAA;AAvEC,IAAM,YAAY;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAIA;AAAA,EACA;AACF;AAGO,IAAM,YAAY;AAAA,EACvB;AAAA,EACA;AACF;AAkBO,SAAS,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AAAA,EACtB,GAAG;AACL,GAAe;AACb,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,KAAK;AACxC,QAAM,WAAWC,QAAO,KAAK;AAC7B,WAAS,UAAU;AACnB,QAAM,WAAWA,QAAO,KAAK;AAI7B,YAAU,MAAM;AACd,QAAI,CAAC,SAAS,QAAS,UAAS,KAAK;AAAA,EACvC,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,SAAS,CAAC,SAAiB;AAC/B,aAAS,UAAU;AACnB,QAAI,SAAS,SAAS,QAAS;AAC/B,aAAS,IAAI;AACb,cAAU;AAAA,EACZ;AAEA,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,WAAW,SAAS;AAAA,MAClC,gBAAc,WAAW;AAAA,MACzB,sBAAoB;AAAA,MAEpB,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP;AAAA,UACA,gBAAc,WAAW;AAAA,UACzB,WAAW;AAAA,UACX,eAAe,CAAC,SAAS;AACvB,qBAAS,UAAU;AACnB,qBAAS,IAAI;AAAA,UACf;AAAA,UACA,QAAQ,MAAM,OAAO,KAAK;AAAA,UAC1B,WAAW,CAAC,UAAU;AACpB,gBAAI,MAAM,QAAQ,SAAS;AACzB,oBAAM,eAAe;AACrB,qBAAO,KAAK;AACZ;AAAA,YACF;AACA,gBAAI,MAAM,QAAQ,UAAU;AAE1B,oBAAM,eAAe;AACrB,oBAAM,gBAAgB;AACtB,uBAAS,UAAU;AACnB,uBAAS,SAAS,OAAO;AACzB,oBAAM,cAAc,KAAK;AAAA,YAC3B;AAAA,UACF;AAAA,UACC,GAAG;AAAA;AAAA,MACN;AAAA;AAAA,EACF;AAEJ;;;AC7GA,SAAS,eAAe,uBAAuB;AAC/C,SAAS,aAAAG,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAoFtC,SAKE,OAAAC,OALF,QAAAC,aAAA;AA5DC,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AACxB,GAAqB;AACnB,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAwB,KAAK;AACvD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,WAAWC,QAAyB,IAAI;AAI9C,QAAM,eAAeA,QAAO,KAAK;AACjC,QAAM,WAAWA,QAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,EAAAC,WAAU,MAAM;AACd,iBAAa,UAAU;AACvB,aAAS,KAAK;AACd,eAAW,KAAK;AAAA,EAClB,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,SAAS,CAAC,SAAwB;AACtC,QAAI,SAAS,QAAQ,CAAC,OAAO,SAAS,IAAI,GAAG;AAC3C,iBAAW,IAAI;AACf;AAAA,IACF;AACA,eAAW,KAAK;AAChB,QAAI,SAAS,aAAa,QAAS;AACnC,iBAAa,UAAU;AACvB,aAAS,IAAI;AACb,cAAU;AAAA,EACZ;AAGA,QAAM,iBAAiB,MAAM;AAC3B,UAAM,OAAO,SAAS,SAAS,MAAM,KAAK,KAAK;AAC/C,WAAO,SAAS,KAAK,OAAO,OAAO,IAAI,CAAC;AAAA,EAC1C;AAEA,SACE,gBAAAJ;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe,CAAC,SAAS;AACvB,iBAAS,IAAI;AACb,YAAI,SAAS,KAAM,YAAW,KAAK;AAAA,MACrC;AAAA,MACA,kBAAkB,CAAC,SAAS,OAAO,IAAI;AAAA,MAEvC,0BAAAC;AAAA,QAAC,gBAAgB;AAAA,QAAhB;AAAA,UACC,WAAW,GAAG,WAAW,SAAS;AAAA,UAClC,gBAAc,WAAW;AAAA,UACzB,sBAAoB;AAAA,UAEpB;AAAA,4BAAAD;AAAA,cAAC,gBAAgB;AAAA,cAAhB;AAAA,gBACC,KAAK;AAAA,gBACL,cAAY;AAAA,gBACZ,gBAAc,WAAW;AAAA,gBACzB,WAAW,GAAG,WAAW,cAAc;AAAA,gBACvC,WAAW,CAAC,UAAU;AACpB,sBAAI,MAAM,QAAQ,QAAS;AAC3B,wBAAM,eAAe;AACrB,iCAAe;AAAA,gBACjB;AAAA,gBACA,QAAQ,MAAM;AAIZ,wBAAM,OAAO,SAAS,SAAS,MAAM,KAAK,KAAK;AAC/C,sBAAI,SAAS,MAAM,CAAC,OAAO,SAAS,OAAO,IAAI,CAAC,EAAG,YAAW,IAAI;AAAA,gBACpE;AAAA;AAAA,YACF;AAAA,YACC,QACC,gBAAAA,MAAC,UAAK,WAAU,iDAAgD,eAAY,QACzE,gBACH;AAAA;AAAA;AAAA,MAEJ;AAAA;AAAA,EACF;AAEJ;;;ACpHA,SAAS,UAAU,kBAAkB;AAiD/B,SAUE,OAAAK,OAVF,QAAAC,aAAA;AAtBC,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AACxB,GAAgB;AACd,SACE,gBAAAA;AAAA,IAAC,WAAW;AAAA,IAAX;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,eAAe,CAAC,SAAS;AACvB,cAAM,SAAS,OAAO,IAAI;AAC1B,YAAI,WAAW,MAAO;AACtB,iBAAS,MAAM;AACf,kBAAU;AAAA,MACZ;AAAA,MAEA;AAAA,wBAAAA;AAAA,UAAC,WAAW;AAAA,UAAX;AAAA,YACC,cAAY;AAAA,YACZ,WAAW;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,YACA,sBAAoB;AAAA,YAEpB;AAAA,8BAAAD,MAAC,WAAW,OAAX,EAAiB,WAAU,YAAW;AAAA,cACvC,gBAAAA,MAAC,WAAW,MAAX,EAAgB,WAAU,wBAAuB,eAAY,QAC5D,0BAAAA,MAAC,SAAI,OAAM,KAAI,QAAO,KAAI,SAAQ,WAAU,MAAK,QAC/C,0BAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA;AAAA,cACjB,GACF,GACF;AAAA;AAAA;AAAA,QACF;AAAA,QAEA,gBAAAA,MAAC,WAAW,QAAX,EACC,0BAAAA,MAAC,WAAW,YAAX,EAAsB,YAAY,GAAG,sBAAsB,OAAO,WAAW,aAC5E,0BAAAA;AAAA,UAAC,WAAW;AAAA,UAAX;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,eAAe,eAAe;AAAA,YAChC;AAAA,YAEA,0BAAAA,MAAC,WAAW,MAAX,EACE,kBAAQ,IAAI,CAAC,WACZ,gBAAAA;AAAA,cAAC,WAAW;AAAA,cAAX;AAAA,gBAEC,OAAO,OAAO;AAAA,gBACd,UAAU,OAAO;AAAA,gBACjB,WAAW;AAAA,kBACT;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA,gBAEA,0BAAAA,MAAC,WAAW,UAAX,EAAoB,WAAU,YAAY,iBAAO,OAAM;AAAA;AAAA,cAXnD,OAAO;AAAA,YAYd,CACD,GACH;AAAA;AAAA,QACF,GACF,GACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACxGA,SAAS,UAAU,kBAAkB;AACrC,SAAS,aAAAE,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AA8HpC,SACE,OAAAC,OADF,QAAAC,aAAA;AAvGR,IAAM,QAAQ,CAAC,SAAqC,MAAM,QAAQ,IAAI,IAAI,KAAK,CAAC,IAAI;AAE7E,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AACxB,GAAgB;AACd,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,KAAK;AACxC,QAAM,cAAcC,QAAO,KAAK;AAChC,QAAM,aAAaA,QAAO,KAAK;AAG/B,QAAM,eAAeA,QAAO,KAAK;AAGjC,QAAM,eAAeA,QAAO,KAAK;AACjC,QAAM,WAAWA,QAAO,KAAK;AAC7B,WAAS,UAAU;AAInB,EAAAC,WAAU,MAAM;AACd,QAAI,YAAY,QAAS;AACzB,iBAAa,UAAU;AACvB,aAAS,KAAK;AAAA,EAChB,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,SAAS,CAAC,SAAiB;AAC/B,QAAI,SAAS,aAAa,QAAS;AACnC,iBAAa,UAAU;AACvB,aAAS,IAAI;AAAA,EACf;AAEA,QAAM,QAAQ,MAAM;AAClB,QAAI,CAAC,YAAY,QAAS;AAC1B,eAAW,UAAU;AACrB,UAAM,QAAQ,aAAa;AAC3B,aAAS,KAAK;AACd,gBAAY,KAAK;AACjB,WAAO,KAAK;AAAA,EACd;AAEA,SACE,gBAAAJ;AAAA,IAAC,WAAW;AAAA,IAAX;AAAA,MACC,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe,CAAC,MAAM,YAAY;AAChC,YAAI,WAAW,SAAS;AAGtB,kBAAQ,OAAO;AACf;AAAA,QACF;AACA,cAAM,IAAI,MAAM,IAAI;AACpB,iBAAS,CAAC;AACV,oBAAY,CAAC;AAAA,MACf;AAAA,MACA,kBAAkB,CAAC,SAAS;AAC1B,oBAAY,UAAU;AACtB,YAAI,WAAW,SAAS;AACtB,qBAAW,UAAU;AACrB;AAAA,QACF;AACA,eAAO,MAAM,IAAI,CAAC;AAClB,kBAAU;AAAA,MACZ;AAAA,MACA,WAAW,GAAG,6BAA6B,SAAS;AAAA,MACpD,sBAAoB;AAAA,MAEpB,0BAAAA;AAAA,QAAC,WAAW;AAAA,QAAX;AAAA,UAGC,uBAAoB;AAAA,UAGpB,WAAU;AAAA,UACV,eAAe,MAAM;AACnB,wBAAY,UAAU;AACtB,uBAAW,UAAU;AACrB,yBAAa,UAAU,SAAS;AAAA,UAClC;AAAA,UACA,eAAe,CAAC,UAAU;AACxB,gBAAI,CAAC,YAAY,QAAS;AAC1B,kBAAM,eAAe;AACrB,kBAAM;AAAA,UACR;AAAA,UACA,WAAW,CAAC,UAAU;AACpB,gBAAI,MAAM,QAAQ,YAAY,CAAC,YAAY,QAAS;AACpD,kBAAM,eAAe;AACrB,kBAAM;AAAA,UACR;AAAA,UAEA,0BAAAC,MAAC,WAAW,OAAX,EAAiB,WAAU,sCAC1B;AAAA,4BAAAD,MAAC,WAAW,WAAX,EAAqB,WAAU,0BAAyB;AAAA,YACzD,gBAAAA;AAAA,cAAC,WAAW;AAAA,cAAX;AAAA,gBACC,cAAY;AAAA,gBACZ,WAAW;AAAA;AAAA;AAAA;AAAA,kBAIT;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA;AAAA,YACF;AAAA,aACF;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;;;ACnJA,SAAS,cAAc;AAgDjB,gBAAAK,aAAA;AA/BC,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AACxB,GAAgB;AACd,SACE,gBAAAA;AAAA,IAAC,OAAO;AAAA,IAAP;AAAA,MACC,cAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA,iBAAiB,CAAC,SAAS;AACzB,iBAAS,IAAI;AACb,kBAAU;AAAA,MACZ;AAAA,MACA,sBAAoB;AAAA,MACpB,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEA,0BAAAA;AAAA,QAAC,OAAO;AAAA,QAAP;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;","names":["forwardRef","jsx","forwardRef","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","useId","useRef","jsx","jsxs","SIDE_OFFSET","VIEWPORT_MARGIN","useRef","useId","jsx","jsxs","SIDE_OFFSET","VIEWPORT_MARGIN","useRef","useState","jsx","useState","useRef","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","jsx","jsxs","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","jsx"]}
|
|
@@ -19,8 +19,8 @@ import {
|
|
|
19
19
|
resolveDomEditCapabilities,
|
|
20
20
|
resolveDomEditSelection,
|
|
21
21
|
serializeDomEditTextFields
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-TP6D3U37.js";
|
|
23
|
+
import "./chunk-6JY3MTIX.js";
|
|
24
24
|
import "./chunk-PZ5AY32C.js";
|
|
25
25
|
export {
|
|
26
26
|
buildDefaultDomEditTextField,
|
|
@@ -44,4 +44,4 @@ export {
|
|
|
44
44
|
resolveDomEditSelection,
|
|
45
45
|
serializeDomEditTextFields
|
|
46
46
|
};
|
|
47
|
-
//# sourceMappingURL=domEditingLayers-
|
|
47
|
+
//# sourceMappingURL=domEditingLayers-PTP2ICGM.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -2692,6 +2692,7 @@ interface StartRenderOptions {
|
|
|
2692
2692
|
format?: "mp4" | "webm" | "mov";
|
|
2693
2693
|
/** `"auto"` (default) renders at the composition's authored dimensions. */
|
|
2694
2694
|
resolution?: ResolutionPreset | "auto";
|
|
2695
|
+
gpu?: boolean;
|
|
2695
2696
|
/**
|
|
2696
2697
|
* Render a specific composition file. Omit it to render the composition the
|
|
2697
2698
|
* user currently has open — only the sidebar's per-composition Render button
|
|
@@ -2728,7 +2729,7 @@ interface CompositionDimensions {
|
|
|
2728
2729
|
width: number;
|
|
2729
2730
|
height: number;
|
|
2730
2731
|
}
|
|
2731
|
-
type StartRenderHandler = (format: "mp4" | "webm" | "mov", quality: "draft" | "standard" | "high", resolution: ResolutionPreset | "auto", fps: 24 | 30 | 60) => void | Promise<void>;
|
|
2732
|
+
type StartRenderHandler = (format: "mp4" | "webm" | "mov", quality: "draft" | "standard" | "high", resolution: ResolutionPreset | "auto", fps: 24 | 30 | 60, gpu?: boolean) => void | Promise<void>;
|
|
2732
2733
|
interface RenderQueueProps {
|
|
2733
2734
|
jobs: RenderJob[];
|
|
2734
2735
|
projectId: string;
|
|
@@ -2764,9 +2765,10 @@ interface PersistedRenderSettings {
|
|
|
2764
2765
|
format: "mp4" | "webm" | "mov";
|
|
2765
2766
|
quality: "draft" | "standard" | "high";
|
|
2766
2767
|
fps: 24 | 30 | 60;
|
|
2768
|
+
gpu: boolean;
|
|
2767
2769
|
}
|
|
2768
2770
|
declare function getPersistedRenderSettings(): PersistedRenderSettings;
|
|
2769
|
-
declare function persistRenderSettings(format: PersistedRenderSettings["format"], quality: PersistedRenderSettings["quality"], fps: PersistedRenderSettings["fps"]): void;
|
|
2771
|
+
declare function persistRenderSettings(format: PersistedRenderSettings["format"], quality: PersistedRenderSettings["quality"], fps: PersistedRenderSettings["fps"], gpu?: boolean): void;
|
|
2770
2772
|
|
|
2771
2773
|
interface PickedElement {
|
|
2772
2774
|
id: string | null;
|
|
@@ -3590,6 +3592,7 @@ declare function useDomEditSession({ projectId, activeCompPath, compIdToSrc, cap
|
|
|
3590
3592
|
/** The one source for which preview is on screen: the host's iframe, then each reload promoted in its place. */
|
|
3591
3593
|
declare function useLivePreviewIframe(host: HTMLIFrameElement | null): HTMLIFrameElement | null;
|
|
3592
3594
|
|
|
3595
|
+
declare function announcePreviewDocumentLoaded(iframe: HTMLIFrameElement): void;
|
|
3593
3596
|
type PreviewPromotion = {
|
|
3594
3597
|
retired: HTMLIFrameElement | null;
|
|
3595
3598
|
live: HTMLIFrameElement;
|
|
@@ -3842,8 +3845,8 @@ interface StudioPlaybackValue {
|
|
|
3842
3845
|
refreshPreviewDocumentVersion: () => void;
|
|
3843
3846
|
}
|
|
3844
3847
|
|
|
3845
|
-
/** Studio state the panel reads; passed by hosts outside Studio's providers. Keep previewIframeRef stable
|
|
3846
|
-
*
|
|
3848
|
+
/** Studio state the panel reads; passed by hosts outside Studio's providers. Keep previewIframeRef stable;
|
|
3849
|
+
* a host with its own player calls announcePreviewDocumentLoaded on each new page, or bumps refreshKey. */
|
|
3847
3850
|
type LayersPanelHost = Pick<StudioShellValue, "previewIframeRef" | "activeCompPath" | "showToast"> & Pick<StudioPlaybackValue, "timelineElements" | "isPlaying"> & Partial<Pick<StudioPlaybackValue, "refreshKey" | "compositionLoading">>;
|
|
3848
3851
|
declare const LayersPanel: react.NamedExoticComponent<{
|
|
3849
3852
|
host?: LayersPanelHost;
|
|
@@ -4312,4 +4315,4 @@ declare function buildStudioTools(depsRef: {
|
|
|
4312
4315
|
readonly current: StudioAgentToolsDeps;
|
|
4313
4316
|
}): ModelContextTool[];
|
|
4314
4317
|
|
|
4315
|
-
export { type AgentModalAnchorPoint, type AgentPromptElementInfo, AskAgentModal, type AskAgentModalProps, AudioMeterStrip, type AudioMeterStripProps, AudioWaveform, type AudioWaveformProps, type BlockedTimelineEditIntent, type CanEditTimelineElement, ColorField, CompositionBreadcrumb, type CompositionDimensions, type CompositionLevel, CompositionThumbnail, ConnectedDomEditOverlay, type ConnectedDomEditOverlayProps, DEFAULT_SHORTCUT_SECTIONS, Dock, type DockController, type DomEditCapabilities, type DomEditCommitDeclineReason, type DomEditCommitOutcome, type DomEditGroupPathOffsetCommit, DomEditOverlay, type DomEditOverlayProps, DomEditProvider, type DomEditSelection, type DomEditZOrder, type DomGeometryCommits, type EditHistoryHandle, EditorShell, type EditorShellProps, type ExternalFileChangeBlockedState, type ExternalFileChangeCoordinatorHandle, ExternalFileConflictBanner, type FadeEdge, type FadeHandleBox, type FadeHandleClipBox, type FfmpegStatus, FileTree, GradientField, GridOverlay, ImageThumbnail, type ImageThumbnailProps, LayersPanel, type LayersPanelHost, type LinkShortcutCallbacks, type MarqueeGestures, type MarqueeGesturesDeps, MarqueeOverlay, type MarqueeOverlayProps, type Rect$1 as MarqueeRect, type ModelContextTool, NLEPreview, type PanelId, type PatchOperation, type PersistedRenderSettings, type PickedElement, PlayerControls, type PlayerHandle, type PlayerHandleElement, type PlayerHandleListener, type PlayerHandleTimeListener, type DomEditCompositionRect as PreviewCompositionRect, PreviewGuides, PreviewOverlayProvider, type PreviewOverlayProviderProps, type PreviewPromotion, PreviewReadOnlyProvider, type PreviewSnapPreferences, PropertyPanel, type RenderJob, RenderQueue, type RenderQueueProps, type ResolutionPreset, SNAP_THRESHOLD_PX, type ShortcutHint, type ShortcutSection, ShortcutsButton, type ShortcutsButtonProps, type SnapContext, type SnapEdge, type SnapGuide, SnapGuideOverlay, type SnapGuideOverlayProps, type SnapGuidesState, type Rect as SnapRect, type SnapResult, type SnapTarget, SnapToolbar, SourceEditor, type SpacingGuide, type StartRenderOptions, type StudioAgentToolsDeps, StudioApp, StudioFileConflictError, type StudioLookSnapshot, type StudioPendingEditsDrainResult, TRACK_H, type ThumbnailPriority, type ThumbnailStill, Timeline, TimelineClipMenu, type TimelineClipMenuItem, type TimelineClipRenderContext, type TimelineEditCallbacks, type TimelineEditOutcome, type TimelineEditPermission, TimelineEditPopover, TimelineEditProvider, type TimelineElement, TimelineEmptyStatePart, TimelineFrame, TimelineGapMenu, TimelineHistoryButtons, type TimelineHistoryButtonsProps, TimelineKeyframeMenu, TimelineLanes, TimelineOverlays, TimelinePane, type TimelinePaneProps, TimelinePlayhead, TimelineProvider, TimelineRazorGuide, TimelineRuler, TimelineShortcutHint, type TimelineTheme, type TimelineTimeRange$1 as TimelineTimeRange, TimelineToolbar, type TimelineToolbarProps, type TimelineTrackPadding, type TimelineZIndexReorderCommit, type ToolResult, type UseClipboardOptions, type UseDomEditSessionParams, type UseDomGeometryCommitOptions, type UseDomStyleCommitOptions, type UseEditHistoryActionsOptions, type UsePersistentEditHistoryOptions, type UsePreviewPersistenceParams, type UseProjectFileWriterOptions, type UseRenderClipContentOptions, type UseThumbnailStillOptions, type UseTimelineEditingOptions, VideoThumbnail, type ZOrderAction, applyPatch, buildCompositionSnapTarget, buildGridSnapEdges, buildPickerAgentContextPreview, buildPickerAgentPrompt, buildStudioTools, cancelNewestStudioWaitingPress, collectSnapContext, collectStudioLookScene, currentTimelineRange, dispatchLinkShortcut, displayTrackOrder, extractSnapTargets, fadeHandleBoxes, findElementBlock, flushStudioPendingEdits, formatTime, getPersistedRenderSettings, liveTime, mergeStyleIntoTag, openAudioGainDialog, parseStyleString, persistRenderSettings, resolveDomEditSelection, resolveEquidistanceGuides, resolveGuideLineRect, resolveIframe, resolveSnapAdjustment, resolveSourceFile, revertNewestStudioPendingEdit, snapEngagedForTravel, useAudioGainDialogStore, useAudioMetersVisible, useClipboard, useCompositionStack, useDockLayoutStore, useDomEditSelectionContext, useDomEditSession, useDomEditZOrder, useDomGeometryCommit, useDomStyleCommit, useEditHistoryActions, useElementPicker, useLivePreviewIframe, useMarqueeGestures, usePersistentEditHistory, usePlayerHandle, usePlayerStore, usePreviewCompositionRect, usePreviewGuidesStore, usePreviewIframeStore, usePreviewOverlayContext, usePreviewPersistence, useProjectFileWriter, useRenderClipContent, useRenderQueue, useThumbnailStill, useTimelineContext, useTimelineEditing, useTimelinePlayer, zoomTimelineToRange };
|
|
4318
|
+
export { type AgentModalAnchorPoint, type AgentPromptElementInfo, AskAgentModal, type AskAgentModalProps, AudioMeterStrip, type AudioMeterStripProps, AudioWaveform, type AudioWaveformProps, type BlockedTimelineEditIntent, type CanEditTimelineElement, ColorField, CompositionBreadcrumb, type CompositionDimensions, type CompositionLevel, CompositionThumbnail, ConnectedDomEditOverlay, type ConnectedDomEditOverlayProps, DEFAULT_SHORTCUT_SECTIONS, Dock, type DockController, type DomEditCapabilities, type DomEditCommitDeclineReason, type DomEditCommitOutcome, type DomEditGroupPathOffsetCommit, DomEditOverlay, type DomEditOverlayProps, DomEditProvider, type DomEditSelection, type DomEditZOrder, type DomGeometryCommits, type EditHistoryHandle, EditorShell, type EditorShellProps, type ExternalFileChangeBlockedState, type ExternalFileChangeCoordinatorHandle, ExternalFileConflictBanner, type FadeEdge, type FadeHandleBox, type FadeHandleClipBox, type FfmpegStatus, FileTree, GradientField, GridOverlay, ImageThumbnail, type ImageThumbnailProps, LayersPanel, type LayersPanelHost, type LinkShortcutCallbacks, type MarqueeGestures, type MarqueeGesturesDeps, MarqueeOverlay, type MarqueeOverlayProps, type Rect$1 as MarqueeRect, type ModelContextTool, NLEPreview, type PanelId, type PatchOperation, type PersistedRenderSettings, type PickedElement, PlayerControls, type PlayerHandle, type PlayerHandleElement, type PlayerHandleListener, type PlayerHandleTimeListener, type DomEditCompositionRect as PreviewCompositionRect, PreviewGuides, PreviewOverlayProvider, type PreviewOverlayProviderProps, type PreviewPromotion, PreviewReadOnlyProvider, type PreviewSnapPreferences, PropertyPanel, type RenderJob, RenderQueue, type RenderQueueProps, type ResolutionPreset, SNAP_THRESHOLD_PX, type ShortcutHint, type ShortcutSection, ShortcutsButton, type ShortcutsButtonProps, type SnapContext, type SnapEdge, type SnapGuide, SnapGuideOverlay, type SnapGuideOverlayProps, type SnapGuidesState, type Rect as SnapRect, type SnapResult, type SnapTarget, SnapToolbar, SourceEditor, type SpacingGuide, type StartRenderOptions, type StudioAgentToolsDeps, StudioApp, StudioFileConflictError, type StudioLookSnapshot, type StudioPendingEditsDrainResult, TRACK_H, type ThumbnailPriority, type ThumbnailStill, Timeline, TimelineClipMenu, type TimelineClipMenuItem, type TimelineClipRenderContext, type TimelineEditCallbacks, type TimelineEditOutcome, type TimelineEditPermission, TimelineEditPopover, TimelineEditProvider, type TimelineElement, TimelineEmptyStatePart, TimelineFrame, TimelineGapMenu, TimelineHistoryButtons, type TimelineHistoryButtonsProps, TimelineKeyframeMenu, TimelineLanes, TimelineOverlays, TimelinePane, type TimelinePaneProps, TimelinePlayhead, TimelineProvider, TimelineRazorGuide, TimelineRuler, TimelineShortcutHint, type TimelineTheme, type TimelineTimeRange$1 as TimelineTimeRange, TimelineToolbar, type TimelineToolbarProps, type TimelineTrackPadding, type TimelineZIndexReorderCommit, type ToolResult, type UseClipboardOptions, type UseDomEditSessionParams, type UseDomGeometryCommitOptions, type UseDomStyleCommitOptions, type UseEditHistoryActionsOptions, type UsePersistentEditHistoryOptions, type UsePreviewPersistenceParams, type UseProjectFileWriterOptions, type UseRenderClipContentOptions, type UseThumbnailStillOptions, type UseTimelineEditingOptions, VideoThumbnail, type ZOrderAction, announcePreviewDocumentLoaded, applyPatch, buildCompositionSnapTarget, buildGridSnapEdges, buildPickerAgentContextPreview, buildPickerAgentPrompt, buildStudioTools, cancelNewestStudioWaitingPress, collectSnapContext, collectStudioLookScene, currentTimelineRange, dispatchLinkShortcut, displayTrackOrder, extractSnapTargets, fadeHandleBoxes, findElementBlock, flushStudioPendingEdits, formatTime, getPersistedRenderSettings, liveTime, mergeStyleIntoTag, openAudioGainDialog, parseStyleString, persistRenderSettings, resolveDomEditSelection, resolveEquidistanceGuides, resolveGuideLineRect, resolveIframe, resolveSnapAdjustment, resolveSourceFile, revertNewestStudioPendingEdit, snapEngagedForTravel, useAudioGainDialogStore, useAudioMetersVisible, useClipboard, useCompositionStack, useDockLayoutStore, useDomEditSelectionContext, useDomEditSession, useDomEditZOrder, useDomGeometryCommit, useDomStyleCommit, useEditHistoryActions, useElementPicker, useLivePreviewIframe, useMarqueeGestures, usePersistentEditHistory, usePlayerHandle, usePlayerStore, usePreviewCompositionRect, usePreviewGuidesStore, usePreviewIframeStore, usePreviewOverlayContext, usePreviewPersistence, useProjectFileWriter, useRenderClipContent, useRenderQueue, useThumbnailStill, useTimelineContext, useTimelineEditing, useTimelinePlayer, zoomTimelineToRange };
|
package/dist/index.html
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
document.documentElement.dataset.theme = "paper";
|
|
15
15
|
}
|
|
16
16
|
</script>
|
|
17
|
-
<script type="module" crossorigin src="/assets/index-
|
|
17
|
+
<script type="module" crossorigin src="/assets/index-D8W0a0Z9.js"></script>
|
|
18
18
|
<link rel="stylesheet" crossorigin href="/assets/index-CVd4O6eH.css">
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|