@pixerate/editor-react 0.13.0 → 0.15.0
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/README.md +5 -4
- package/dist/canvas/index.cjs +329 -84
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +82 -4
- package/dist/canvas/index.d.ts +82 -4
- package/dist/canvas/index.js +266 -18
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-4ZC2WCUO.js +196 -0
- package/dist/chunk-4ZC2WCUO.js.map +1 -0
- package/dist/{chunk-TL27COKM.js → chunk-LPFZMZ3L.js} +45 -2
- package/dist/chunk-LPFZMZ3L.js.map +1 -0
- package/dist/{chunk-MHTAR3RS.js → chunk-QVQYYHJ5.js} +87 -29
- package/dist/chunk-QVQYYHJ5.js.map +1 -0
- package/dist/commands/index.cjs +232 -0
- package/dist/commands/index.cjs.map +1 -0
- package/dist/commands/index.d.cts +69 -0
- package/dist/commands/index.d.ts +69 -0
- package/dist/commands/index.js +13 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/image-editor/index.cjs +41 -0
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +2 -0
- package/dist/image-editor/index.d.ts +2 -0
- package/dist/image-editor/index.js +1 -1
- package/dist/index.cjs +624 -268
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -9
- package/dist/index.d.ts +57 -9
- package/dist/index.js +147 -71
- package/dist/index.js.map +1 -1
- package/dist/spreadsheet/index.cjs +79 -22
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +2 -3
- package/dist/spreadsheet/index.d.ts +2 -3
- package/dist/spreadsheet/index.js +1 -1
- package/package.json +10 -2
- package/dist/chunk-MHTAR3RS.js.map +0 -1
- package/dist/chunk-TL27COKM.js.map +0 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/hooks/usePromptEditor.ts","../src/hooks/useEditor.ts","../src/hooks/useNavigationGuard.ts","../src/hooks/useDismissGuard.ts","../src/hooks/useHistory.ts","../src/hooks/useHistoryShortcuts.ts","../src/hooks/useFileImport.ts","../src/hooks/useAgentToolProvider.ts","../src/components/EditorContent.tsx","../src/components/BubbleMenu.tsx","../src/components/TemplateRenderer.tsx","../src/components/VariableForm.tsx","../src/hooks/useOutline.ts","../src/components/OutlinePanel.tsx","../src/spreadsheet/useSpreadsheetEditor.ts","../src/spreadsheet/SpreadsheetEditor.tsx","../src/spreadsheet/SpreadsheetContextMenu.tsx","../src/spreadsheet/SpreadsheetGroupRow.tsx","../src/spreadsheet/useSpreadsheetTableInteractions.ts","../src/spreadsheet/FormulaHints.tsx","../src/slots.tsx","../src/image-editor/useImageEditor.ts","../src/image-editor/ImageEditor.tsx","../src/review/useReview.ts","../src/review/CommentsPanel.tsx","../src/review/ReviewToolbar.tsx","../src/review/CommentButton.tsx"],"sourcesContent":["export * from \"./hooks/usePromptEditor\";\nexport * from \"./hooks/useEditor\";\nexport * from \"./hooks/useNavigationGuard\";\nexport * from \"./hooks/useDismissGuard\";\nexport * from \"./hooks/useHistory\";\nexport * from \"./hooks/useHistoryShortcuts\";\nexport * from \"./hooks/useFileImport\";\nexport * from \"./hooks/useAgentToolProvider\";\nexport * from \"./components/EditorContent\";\nexport * from \"./components/BubbleMenu\";\nexport * from \"./components/TemplateRenderer\";\nexport * from \"./components/VariableForm\";\nexport * from \"./hooks/useOutline\";\nexport * from \"./components/OutlinePanel\";\n\n// Re-export core types for easy consumer access\nexport {\n DirtyTracker,\n createDirtyTracker,\n defaultIsEqual,\n HistoryManager,\n createHistoryManager,\n} from \"@pixerate/editor\";\nexport type {\n Template,\n TemplateVersion,\n Token,\n TokenType,\n ColorGradient,\n RichTextPresetOptions,\n DirtyTrackerOptions,\n Command,\n HistoryState,\n HistoryManagerOptions,\n} from \"@pixerate/editor\";\nexport type {\n PromptValues,\n PromptDiagnostic,\n VariableFormField,\n} from \"@pixerate/editor\";\n\nexport * from \"./spreadsheet\";\nexport * from \"./slots\";\nexport * from \"./image-editor\";\nexport * from \"./review\";\n","import { useMemo, useEffect, useRef } from \"react\";\nimport { useEditor } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport { Slice } from \"@tiptap/pm/model\";\nimport {\n Template,\n ColorGradient,\n GradientText,\n TemplateSuggestions,\n LoadingNode,\n plainTextToTipTapHtml,\n plainTextToSlice,\n getEditorText,\n tokenizePrompt,\n FileImport,\n type FileImportOptions,\n} from \"@pixerate/editor\";\n\nexport interface UsePromptEditorProps {\n /**\n * The editor content as plain text. Changes from the parent (e.g. clearing\n * after submit) are applied to the editor; echoes of the editor's own\n * updates via `onContentChange` are ignored.\n */\n content: string;\n /** Callback fired when the editor content changes (returns plain text) */\n onContentChange: (text: string) => void;\n /** List of available templates to be suggested and highlighted */\n templates?: Template[];\n /** Custom gradient color map for templates */\n templateColorMap?: Map<string, ColorGradient>;\n /** Whether the editor is editable */\n isEditing?: boolean;\n /** Placeholder text for the editor */\n placeholder?: string;\n /** Additional CSS classes for the editor container */\n className?: string;\n /** Callback fired when the Escape key is pressed */\n onEscape?: () => void;\n /** Custom keydown handler. Return true to prevent default behavior */\n onKeyDown?: (event: KeyboardEvent) => boolean;\n /** Callback fired when text selection changes */\n onSelectionChange?: (selection: { from: number; to: number } | null) => void;\n /** Callback fired when a slash command (e.g., /template) matches */\n onSlashCommandMatch?: (\n match: RegExpMatchArray,\n from: number,\n to: number,\n coords: { top: number; left: number },\n ) => void;\n /** Callback to dismiss/clear the active slash command */\n clearSlashCommand?: () => void;\n /** Whether a slash command menu is currently active */\n slashCommandActive?: boolean;\n /**\n * Callback fired the first time each milestone is reached while the editor\n * is mounted: `used_variable` ({variable}) and `used_magic` (__instruction__).\n */\n onMilestone?: (milestone: string) => void;\n /** DOM element ID of the container, used for positioning popovers */\n containerId?: string;\n /** Variable names originating from structured JSON output steps */\n jsonVariables?: string[];\n /** Animation speed for gradient decorations */\n speed?: number;\n /**\n * Import text from .md, .html, .txt and .rtf files dropped onto the editor\n * (opt-in). Content is always inserted as plain text. Pasting keeps the\n * plain-text paste handler, so pasted files are not imported.\n */\n fileImport?: Omit<FileImportOptions, \"asPlainText\"> | boolean;\n}\n\nconst DEFAULT_TEMPLATES: Template[] = [];\nconst DEFAULT_COLOR_MAP = new Map<string, ColorGradient>([\n [\"default\", { from: \"#f43f5e\", to: \"#8b5cf6\" }],\n]);\nconst DEFAULT_CLASS_NAME =\n \"w-full border border-input rounded-md p-3 font-mono text-sm leading-relaxed focus:outline-none focus:ring-2 focus:ring-primary whitespace-pre-wrap break-words\";\n\nconst normalizeNewlines = (text: string) => text.replace(/\\r\\n?/g, \"\\n\");\n\nexport function usePromptEditor({\n content,\n onContentChange,\n templates = DEFAULT_TEMPLATES,\n templateColorMap: userColorMap,\n isEditing = true,\n placeholder = \"Write a prompt, use {{template}}, {variable}, or /command...\",\n className,\n onEscape,\n onKeyDown,\n onSelectionChange,\n onSlashCommandMatch,\n clearSlashCommand,\n slashCommandActive = false,\n onMilestone,\n containerId = \"editor-container\",\n jsonVariables,\n speed = 2,\n fileImport,\n}: UsePromptEditorProps) {\n const fileImportRef = useRef(fileImport);\n fileImportRef.current = fileImport;\n const fileImportEnabled = !!fileImport;\n\n const slashCommandActiveRef = useRef(slashCommandActive);\n slashCommandActiveRef.current = slashCommandActive;\n\n const clearSlashCommandRef = useRef(clearSlashCommand);\n clearSlashCommandRef.current = clearSlashCommand;\n\n const onEscapeRef = useRef(onEscape);\n onEscapeRef.current = onEscape;\n\n const onKeyDownRef = useRef(onKeyDown);\n onKeyDownRef.current = onKeyDown;\n\n const onSelectionChangeRef = useRef(onSelectionChange);\n onSelectionChangeRef.current = onSelectionChange;\n\n const onSlashCommandMatchRef = useRef(onSlashCommandMatch);\n onSlashCommandMatchRef.current = onSlashCommandMatch;\n\n const onContentChangeRef = useRef(onContentChange);\n onContentChangeRef.current = onContentChange;\n\n const onMilestoneRef = useRef(onMilestone);\n onMilestoneRef.current = onMilestone;\n\n const containerIdRef = useRef(containerId);\n containerIdRef.current = containerId;\n\n const templateKey = useMemo(() => {\n return (templates || [])\n .map((t) => `${t.id || t.name}:${(t as any).latestVersion || \"\"}`)\n .sort()\n .join(\",\");\n }, [templates]);\n\n // Key the color map by value so an inline `new Map(...)` does not recreate\n // the editor on every render.\n const colorMapKey = userColorMap\n ? JSON.stringify(Array.from(userColorMap.entries()))\n : \"\";\n const resolvedColorMap = useMemo(() => {\n if (userColorMap) return userColorMap;\n const map = new Map<string, ColorGradient>();\n templates.forEach((t) => {\n map.set(t.name, { from: \"#f43f5e\", to: \"#8b5cf6\" });\n });\n return map.size > 0 ? map : DEFAULT_COLOR_MAP;\n }, [colorMapKey, templateKey]);\n\n const jsonVariablesKey = (jsonVariables || []).join(\"\\u0000\");\n\n const reachedMilestonesRef = useRef(new Set<string>());\n\n const StarterKitExt =\n (StarterKit as any)?.configure\n ? StarterKit\n : (StarterKit as any)?.default?.configure\n ? (StarterKit as any)?.default\n : StarterKit;\n\n const PlaceholderExt =\n (Placeholder as any)?.configure\n ? Placeholder\n : (Placeholder as any)?.default?.configure\n ? (Placeholder as any)?.default\n : Placeholder;\n\n const editor = useEditor(\n {\n immediatelyRender: false,\n enablePasteRules: false,\n enableInputRules: false,\n editable: isEditing,\n extensions: [\n StarterKitExt.configure({\n heading: false,\n codeBlock: false,\n }),\n PlaceholderExt.configure({ placeholder }),\n GradientText.configure({\n templateColorMap: resolvedColorMap,\n speed,\n jsonVariables,\n }),\n TemplateSuggestions.configure({\n templates,\n }),\n LoadingNode,\n ...(fileImportEnabled\n ? [\n FileImport.configure({\n ...(typeof fileImportRef.current === \"object\" ? fileImportRef.current : {}),\n // Prompt editors only ever receive plain text.\n asPlainText: true,\n }),\n ]\n : []),\n ],\n content: plainTextToTipTapHtml(content),\n onUpdate: ({ editor: ed }) => {\n const plainText = getEditorText(ed);\n onContentChangeRef.current?.(plainText);\n\n if (onMilestoneRef.current) {\n const reached = reachedMilestonesRef.current;\n for (const token of tokenizePrompt(plainText)) {\n const milestone =\n token.type === \"variable\"\n ? \"used_variable\"\n : token.type === \"instruction\"\n ? \"used_magic\"\n : null;\n if (milestone && !reached.has(milestone)) {\n reached.add(milestone);\n onMilestoneRef.current(milestone);\n }\n }\n }\n\n const { state, view } = ed;\n const { selection } = state;\n const { $from, from, to } = selection;\n\n onSelectionChangeRef.current?.({ from, to });\n\n if (onSlashCommandMatchRef.current && clearSlashCommandRef.current) {\n const textBeforeCursor = $from?.parent?.textBetween\n ? $from.parent.textBetween(0, $from.parentOffset)\n : \"\";\n const slashMatch = textBeforeCursor.match(\n /(?:^|\\s)\\/([a-zA-Z0-9_-]*)$/,\n );\n\n if (slashMatch) {\n const coords = view.coordsAtPos($from.pos);\n const containerEl =\n document.getElementById(containerIdRef.current) ||\n document.getElementById(\"editor-container\") ||\n (view.dom.closest?.(\".relative\") as HTMLElement | null);\n const containerCoords = containerEl?.getBoundingClientRect();\n\n if (containerCoords) {\n onSlashCommandMatchRef.current(\n slashMatch,\n $from.pos -\n slashMatch[0].length +\n (slashMatch[0].startsWith(\" \") ? 1 : 0),\n $from.pos,\n {\n top: coords.bottom - containerCoords.top + 5,\n left: coords.left - containerCoords.left,\n },\n );\n }\n } else {\n clearSlashCommandRef.current();\n }\n }\n },\n onSelectionUpdate: ({ editor: ed }) => {\n const { from, to } = ed.state.selection;\n onSelectionChangeRef.current?.({ from, to });\n },\n editorProps: {\n attributes: {\n class: className || DEFAULT_CLASS_NAME,\n role: \"textbox\",\n \"aria-label\": \"Prompt editor\",\n },\n handleKeyDown(view, event) {\n if (slashCommandActiveRef.current) {\n if (\n event.key === \"ArrowUp\" ||\n event.key === \"ArrowDown\" ||\n event.key === \"Enter\"\n ) {\n event.preventDefault();\n return true;\n }\n if (event.key === \"Escape\") {\n clearSlashCommandRef.current?.();\n event.preventDefault();\n event.stopPropagation();\n return true;\n }\n }\n if (onKeyDownRef.current && onKeyDownRef.current(event as KeyboardEvent)) {\n return true;\n }\n if (event.key === \"Escape\" && onEscapeRef.current) {\n onEscapeRef.current();\n return true;\n }\n return false;\n },\n handlePaste: (view, event) => {\n // Paste as plain text even when the clipboard also carries HTML.\n const text = event.clipboardData?.getData(\"text/plain\");\n if (!text) return false;\n event.preventDefault();\n const schema = view.state.schema;\n if (!schema) return false;\n view.dispatch(\n view.state.tr.replaceSelection(plainTextToSlice(text, schema)),\n );\n return true;\n },\n clipboardTextParser: (text, context, _plain, view) => {\n const schema =\n (context as any)?.doc?.type?.schema ||\n (context as any)?.schema ||\n view?.state?.schema;\n\n if (!schema) return Slice.empty;\n return plainTextToSlice(text, schema);\n },\n },\n },\n // Only options baked into extensions recreate the editor; editable state,\n // placeholder, class names and content are applied to the live instance.\n [resolvedColorMap, templateKey, speed, jsonVariablesKey, fileImportEnabled],\n );\n\n useEffect(() => {\n if (editor && !editor.isDestroyed) {\n editor.setEditable(isEditing);\n }\n }, [editor, isEditing]);\n\n // Apply content changes made by the parent (e.g. clearing after submit).\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n if (normalizeNewlines(content) === getEditorText(editor)) return;\n const { from, to } = editor.state.selection;\n editor.commands.setContent(plainTextToTipTapHtml(content), false);\n const max = editor.state.doc.content.size;\n editor.commands.setTextSelection({\n from: Math.min(from, max),\n to: Math.min(to, max),\n });\n }, [editor, content]);\n\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n editor.setOptions({\n editorProps: {\n ...editor.options.editorProps,\n attributes: {\n ...(editor.options.editorProps.attributes as Record<string, string>),\n class: className || DEFAULT_CLASS_NAME,\n },\n },\n });\n }, [editor, className]);\n\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n const placeholderExt = editor.extensionManager.extensions.find(\n (ext) => ext.name === \"placeholder\",\n );\n if (!placeholderExt || placeholderExt.options.placeholder === placeholder) {\n return;\n }\n placeholderExt.options.placeholder = placeholder;\n // Re-run decorations so the new placeholder renders.\n editor.view.dispatch(editor.state.tr);\n }, [editor, placeholder]);\n\n return editor;\n}\n","import { useEditor as useTipTapEditor, UseEditorOptions } from \"@tiptap/react\";\nimport {\n createRichTextPreset,\n RichTextPresetOptions,\n type FileImportOptions,\n type RichClipboardOptions,\n} from \"@pixerate/editor\";\n\nexport interface UseRichEditorProps extends UseEditorOptions {\n richTextOptions?: RichTextPresetOptions;\n /**\n * Import .md, .html, .txt and .rtf files dropped or pasted into the editor\n * at the drop position (opt-in; same as `richTextOptions.fileImport`).\n */\n fileImport?: FileImportOptions | boolean;\n /**\n * Copy/paste lossless ProseMirror slices between editors via the\n * `application/x.pixerate.document+json` clipboard type (opt-in; same as\n * `richTextOptions.richClipboard`).\n */\n richClipboard?: RichClipboardOptions | boolean;\n}\n\n/**\n * Hook to initialize a TipTap rich-text editor instance with pre-configured extensions.\n */\nexport function useEditor(options: UseRichEditorProps = {}) {\n const {\n richTextOptions,\n fileImport,\n richClipboard,\n extensions = [],\n ...editorOptions\n } = options;\n\n const preset = createRichTextPreset({\n ...(fileImport !== undefined ? { fileImport } : {}),\n ...(richClipboard !== undefined ? { richClipboard } : {}),\n ...richTextOptions,\n });\n const combinedExtensions = [...preset, ...extensions];\n\n return useTipTapEditor({\n extensions: combinedExtensions,\n ...editorOptions,\n });\n}\n","import { useState, useEffect, useCallback, useRef } from \"react\";\n\nexport interface UseNavigationGuardOptions {\n /** Whether the current form or editor has unsaved changes */\n isDirty: boolean;\n /** Whether guarding is enabled (defaults to true) */\n enabled?: boolean;\n /** Custom navigation function (e.g. router.push from next/navigation or react-router) */\n onNavigate?: (url: string) => void;\n /** Optional callback fired when an internal navigation attempt is intercepted */\n onBlocked?: (url: string) => void;\n}\n\nexport interface UseNavigationGuardReturn {\n /** Whether the unsaved changes confirmation dialog should be displayed */\n showConfirm: boolean;\n /** Setter to manually control the dialog visibility */\n setShowConfirm: (show: boolean) => void;\n /** The target URL that the user attempted to navigate to */\n pendingUrl: string | null;\n /** Proceeds with the blocked navigation and closes the dialog */\n confirmLeave: () => void;\n /** Cancels the navigation attempt and keeps the user on the current page */\n cancelLeave: () => void;\n}\n\n/**\n * Hook to guard against navigation when there are unsaved changes.\n * Intercepts both external unloads (tab closing/refreshing) and internal link clicks.\n */\nexport function useNavigationGuard({\n isDirty,\n enabled = true,\n onNavigate,\n onBlocked,\n}: UseNavigationGuardOptions): UseNavigationGuardReturn {\n const [showConfirm, setShowConfirm] = useState(false);\n const [pendingUrl, setPendingUrl] = useState<string | null>(null);\n\n const onNavigateRef = useRef(onNavigate);\n onNavigateRef.current = onNavigate;\n\n const onBlockedRef = useRef(onBlocked);\n onBlockedRef.current = onBlocked;\n\n // 1. Intercept external navigation / tab close (beforeunload)\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!enabled || !isDirty) return;\n\n const handleBeforeUnload = (e: BeforeUnloadEvent) => {\n e.preventDefault();\n e.returnValue = \"\";\n };\n\n window.addEventListener(\"beforeunload\", handleBeforeUnload);\n return () => {\n window.removeEventListener(\"beforeunload\", handleBeforeUnload);\n };\n }, [enabled, isDirty]);\n\n // 2. Intercept internal anchor link clicks\n useEffect(() => {\n if (typeof document === \"undefined\" || typeof window === \"undefined\")\n return;\n if (!enabled || !isDirty) return;\n\n const handleClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n const anchor = target?.closest?.(\"a\");\n\n if (!anchor) return;\n if (anchor.target === \"_blank\") return;\n\n // Only guard internal origins\n const isInternal = anchor.host === window.location.host;\n if (!isInternal) return;\n\n // Ignore navigation to the exact same path & query\n if (\n anchor.pathname === window.location.pathname &&\n anchor.search === window.location.search\n ) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n\n const href = anchor.href;\n setPendingUrl(href);\n setShowConfirm(true);\n onBlockedRef.current?.(href);\n };\n\n document.addEventListener(\"click\", handleClick, { capture: true });\n return () => {\n document.removeEventListener(\"click\", handleClick, { capture: true });\n };\n }, [enabled, isDirty]);\n\n const confirmLeave = useCallback(() => {\n setShowConfirm(false);\n if (pendingUrl) {\n if (onNavigateRef.current) {\n onNavigateRef.current(pendingUrl);\n } else if (typeof window !== \"undefined\") {\n window.location.href = pendingUrl;\n }\n }\n }, [pendingUrl]);\n\n const cancelLeave = useCallback(() => {\n setShowConfirm(false);\n setPendingUrl(null);\n }, []);\n\n return {\n showConfirm,\n setShowConfirm,\n pendingUrl,\n confirmLeave,\n cancelLeave,\n };\n}\n","import { useState, useCallback, useRef } from \"react\";\n\nexport interface UseDismissGuardOptions {\n /** Whether there are unsaved changes */\n isDirty: boolean;\n /** Whether the dismissal guard is enabled (defaults to true) */\n enabled?: boolean;\n /** Callback fired when dismissal is confirmed or when clean dismissal occurs */\n onDismiss?: () => void;\n}\n\nexport interface UseDismissGuardReturn {\n /** Whether the discard confirmation modal should be shown */\n showConfirm: boolean;\n /** Manually update confirmation modal visibility */\n setShowConfirm: (show: boolean) => void;\n /** Request dismissal - checks isDirty and shows confirm or executes onDismiss */\n requestDismiss: () => void;\n /** Confirm discarding changes and dismiss */\n confirmDismiss: () => void;\n /** Cancel discarding and resume editing */\n cancelDismiss: () => void;\n /** Helper keydown handler intercepting Escape key */\n handleKeyDown: (event: React.KeyboardEvent | KeyboardEvent) => boolean;\n}\n\n/**\n * Hook to guard against closing or exiting an editor/dialog with uncommitted changes.\n */\nexport function useDismissGuard({\n isDirty,\n enabled = true,\n onDismiss,\n}: UseDismissGuardOptions): UseDismissGuardReturn {\n const [showConfirm, setShowConfirm] = useState(false);\n\n const onDismissRef = useRef(onDismiss);\n onDismissRef.current = onDismiss;\n\n const requestDismiss = useCallback(() => {\n if (enabled && isDirty) {\n setShowConfirm(true);\n } else {\n onDismissRef.current?.();\n }\n }, [enabled, isDirty]);\n\n const confirmDismiss = useCallback(() => {\n setShowConfirm(false);\n onDismissRef.current?.();\n }, []);\n\n const cancelDismiss = useCallback(() => {\n setShowConfirm(false);\n }, []);\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent | KeyboardEvent) => {\n if (event.key === \"Escape\") {\n if (event.defaultPrevented) return false;\n event.preventDefault();\n requestDismiss();\n return true;\n }\n return false;\n },\n [requestDismiss],\n );\n\n return {\n showConfirm,\n setShowConfirm,\n requestDismiss,\n confirmDismiss,\n cancelDismiss,\n handleKeyDown,\n };\n}\n","import { useSyncExternalStore, useRef, useCallback } from \"react\";\nimport {\n HistoryManager,\n HistoryState,\n Command,\n createHistoryManager,\n HistoryManagerOptions,\n} from \"@pixerate/editor\";\n\nexport interface UseHistoryResult extends HistoryState {\n manager: HistoryManager;\n undo: () => boolean;\n redo: () => boolean;\n clear: () => void;\n execute: (command: Command) => void;\n executeMerged: (command: Command, options?: { windowMs?: number }) => void;\n batch: (name: string, fn: () => void) => void;\n}\n\n/**\n * React hook that subscribes to a HistoryManager instance.\n * Accepts an existing HistoryManager or config options to create an instance\n * (options are read on first render only).\n */\nexport function useHistory(\n managerOrOptions?: HistoryManager | HistoryManagerOptions,\n): UseHistoryResult {\n // Options are read once, so passing an inline options object does not\n // create a new manager (and wipe history) on every render.\n const ownManagerRef = useRef<HistoryManager | null>(null);\n let manager: HistoryManager;\n if (managerOrOptions instanceof HistoryManager) {\n manager = managerOrOptions;\n } else {\n ownManagerRef.current ??= createHistoryManager(managerOrOptions);\n manager = ownManagerRef.current;\n }\n\n const state = useSyncExternalStore(\n useCallback(\n (onStoreChange) => manager.subscribe(onStoreChange),\n [manager],\n ),\n () => manager.getState(),\n () => manager.getState(),\n );\n\n const undo = useCallback(() => manager.undo(), [manager]);\n const redo = useCallback(() => manager.redo(), [manager]);\n const clear = useCallback(() => manager.clear(), [manager]);\n const execute = useCallback(\n (cmd: Command) => manager.execute(cmd),\n [manager],\n );\n const executeMerged = useCallback(\n (cmd: Command, opts?: { windowMs?: number }) =>\n manager.executeMerged(cmd, opts),\n [manager],\n );\n const batch = useCallback(\n (name: string, fn: () => void) => manager.batch(name, fn),\n [manager],\n );\n\n return {\n ...state,\n manager,\n undo,\n redo,\n clear,\n execute,\n executeMerged,\n batch,\n };\n}\n","import { useEffect } from \"react\";\nimport { HistoryManager } from \"@pixerate/editor\";\n\nexport interface HistoryShortcutsOptions {\n /**\n * Whether the keyboard shortcuts are enabled. Defaults to true.\n */\n enabled?: boolean;\n /**\n * Target element or window to listen on. Defaults to window.\n */\n target?: Window | HTMLElement | null;\n /**\n * When true (default), shortcuts will not trigger if an <input>, <textarea>,\n * or [contenteditable] element is currently active / focused.\n */\n ignoreEditableElements?: boolean;\n}\n\n/**\n * Attaches keyboard listeners for Undo (Mod+Z) and Redo (Mod+Shift+Z / Mod+Y).\n * Automatically guards against active text inputs and contenteditable editors.\n */\nexport function useHistoryShortcuts(\n manager: HistoryManager,\n options: HistoryShortcutsOptions = {},\n): void {\n const {\n enabled = true,\n target,\n ignoreEditableElements = true,\n } = options;\n\n useEffect(() => {\n if (!enabled) return;\n\n const eventTarget = target ?? (typeof window !== \"undefined\" ? window : null);\n if (!eventTarget) return;\n\n const handleKeyDown = (event: Event) => {\n const e = event as KeyboardEvent;\n const isMac =\n typeof navigator !== \"undefined\" &&\n /Mac|iPod|iPhone|iPad/.test(navigator.platform || navigator.userAgent);\n const modifier = isMac ? e.metaKey : e.ctrlKey;\n\n if (!modifier) return;\n\n if (ignoreEditableElements && typeof document !== \"undefined\") {\n const targetEl = (e.target || document.activeElement) as HTMLElement | null;\n if (targetEl && targetEl.tagName) {\n const tagName = targetEl.tagName.toLowerCase();\n const isInput = tagName === \"input\" || tagName === \"textarea\";\n const isContentEditable =\n targetEl.isContentEditable ||\n targetEl.getAttribute?.(\"contenteditable\") === \"true\";\n if (isInput || isContentEditable) {\n return;\n }\n }\n }\n\n const key = e.key.toLowerCase();\n\n // Undo: Mod+Z (without Shift)\n if (key === \"z\" && !e.shiftKey) {\n if (manager.getState().canUndo) {\n e.preventDefault();\n manager.undo();\n }\n return;\n }\n\n // Redo: Mod+Shift+Z or (on non-Mac) Mod+Y\n const isRedoKey =\n (key === \"z\" && e.shiftKey) || (!isMac && key === \"y\" && !e.shiftKey);\n\n if (isRedoKey) {\n if (manager.getState().canRedo) {\n e.preventDefault();\n manager.redo();\n }\n }\n };\n\n eventTarget.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n eventTarget.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [manager, enabled, target, ignoreEditableElements]);\n}\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n FileImportController,\n type FileImportControllerOptions,\n type FileImportState,\n} from \"@pixerate/editor\";\n\nexport interface UseFileImportResult extends FileImportState {\n /** Value for `<input type=\"file\" accept={…}>`. */\n accept: string;\n /** Opens the browser file picker and imports the chosen files at the selection. */\n openFilePicker: FileImportController[\"openFilePicker\"];\n /** Imports files (e.g. from your own `<input>` or drop zone) at `at` or the selection. */\n importFiles: FileImportController[\"importFiles\"];\n}\n\n/**\n * Imports markdown, HTML, plain-text and RTF files (or anything registered\n * with `registerImportAdapter` for the `document` target) into an editor.\n * Pair it with `useEditor({ fileImport: true })` to also accept dropped files.\n */\nexport function useFileImport(\n editor: Editor | null | undefined,\n options: FileImportControllerOptions = {},\n): UseFileImportResult {\n const editorRef = useRef(editor);\n editorRef.current = editor;\n\n const controller = useMemo(\n () =>\n new FileImportController(() => {\n const current = editorRef.current;\n return current && !current.isDestroyed ? current : null;\n }, options),\n [],\n );\n\n useEffect(() => {\n controller.setOptions(options);\n });\n\n const state = useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n\n return {\n ...state,\n accept: controller.accept,\n openFilePicker: controller.openFilePicker,\n importFiles: controller.importFiles,\n };\n}\n","import { useEffect } from \"react\";\nimport type { AgentToolProvider, ToolRegistry } from \"@pixerate/editor/agent\";\n\n/**\n * Registers a tool provider with a `ToolRegistry` while the component is\n * mounted and unregisters it on unmount (the registry then announces the\n * change through `onListChanged`).\n *\n * Memoize the provider (e.g. `useMemo(() => createRichTextToolProvider(editor,\n * { id }), [editor])`): a new provider object re-registers it. Pass `null`\n * while it isn't ready.\n */\nexport function useAgentToolProvider(\n registry: ToolRegistry | null | undefined,\n provider: AgentToolProvider | null | undefined,\n): void {\n useEffect(() => {\n if (!registry || !provider) return;\n return registry.register(provider);\n }, [registry, provider]);\n}\n","import React from \"react\";\nimport {\n EditorContent as TipTapEditorContent,\n EditorContentProps as TipTapEditorContentProps,\n} from \"@tiptap/react\";\n\nexport interface EditorContentProps extends TipTapEditorContentProps {\n className?: string;\n}\n\nexport const EditorContent: React.FC<EditorContentProps> = ({\n className,\n editor,\n ...props\n}) => {\n return (\n <div className={className}>\n <TipTapEditorContent editor={editor} {...props} />\n </div>\n );\n};\n","import React, { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n BubbleMenuPlugin,\n type BubbleMenuPluginProps,\n} from \"@tiptap/extension-bubble-menu\";\nimport type { Editor } from \"@tiptap/core\";\n\nexport interface BubbleMenuProps {\n editor: Editor | null;\n className?: string;\n children: React.ReactNode;\n tippyOptions?: BubbleMenuPluginProps[\"tippyOptions\"];\n shouldShow?: BubbleMenuPluginProps[\"shouldShow\"];\n pluginKey?: BubbleMenuPluginProps[\"pluginKey\"];\n updateDelay?: BubbleMenuPluginProps[\"updateDelay\"];\n}\n\nexport const BubbleMenu: React.FC<BubbleMenuProps> = ({\n editor,\n className = \"flex items-center gap-1 bg-popover text-popover-foreground border shadow-md rounded-md p-1\",\n children,\n tippyOptions = { duration: 100 },\n shouldShow = null,\n pluginKey = \"bubbleMenu\",\n updateDelay,\n}) => {\n const menuEl = useRef<HTMLDivElement | null>(null);\n const [mounted, setMounted] = useState(false);\n\n if (!menuEl.current && typeof document !== \"undefined\") {\n menuEl.current = document.createElement(\"div\");\n }\n\n useEffect(() => {\n if (!editor || !menuEl.current || editor.isDestroyed) {\n return;\n }\n\n const element = menuEl.current;\n element.className = className;\n\n const plugin = BubbleMenuPlugin({\n editor,\n element,\n pluginKey,\n tippyOptions,\n shouldShow,\n updateDelay,\n });\n\n editor.registerPlugin(plugin);\n setMounted(true);\n\n return () => {\n setMounted(false);\n editor.unregisterPlugin(pluginKey);\n if (element.parentNode) {\n element.parentNode.removeChild(element);\n }\n };\n }, [editor, className, pluginKey]);\n\n if (!editor || !menuEl.current || !mounted) {\n return null;\n }\n\n return createPortal(children, menuEl.current);\n};\n","import React, { useMemo } from \"react\";\nimport {\n evaluatePromptTokens,\n resolveTemplates,\n Template,\n ColorGradient,\n PromptValues,\n} from \"@pixerate/editor\";\n\nexport interface TemplateRendererProps {\n /** Raw prompt or text string to render */\n content: string;\n /** Available templates for recursive resolution and custom coloring */\n templates?: Template[];\n /** Custom gradient color map for templates */\n templateColorMap?: Map<string, ColorGradient>;\n /** Whether to resolve nested templates recursively before displaying */\n resolve?: boolean;\n /** Template version bindings used when `resolve` is set */\n bindings?: Record<string, string>;\n /**\n * Variable values. When set, variables show their value (or default),\n * sections whose condition fails are hidden, and section tags are dropped.\n */\n values?: PromptValues;\n /** Custom class name for the wrapper */\n className?: string;\n /** Click callback for template badges */\n onTemplateClick?: (templateName: string) => void;\n /** Click callback for variable badges */\n onVariableClick?: (variableName: string) => void;\n}\n\nconst CONDITIONAL_PREFIX = { if: \"?\", unless: \"!\", end: \"/\" } as const;\n\nexport const TemplateRenderer: React.FC<TemplateRendererProps> = ({\n content,\n templates = [],\n templateColorMap,\n resolve = false,\n bindings,\n values,\n className = \"font-mono text-sm leading-relaxed whitespace-pre-wrap break-words\",\n onTemplateClick,\n onVariableClick,\n}) => {\n const displayText = useMemo(() => {\n if (!resolve || templates.length === 0) return content;\n return resolveTemplates(content, templates, { bindings });\n }, [content, templates, resolve, bindings]);\n\n const tokens = useMemo(() => {\n return evaluatePromptTokens(displayText, values);\n }, [displayText, values]);\n\n return (\n <div className={className}>\n {tokens.map((token, index) => {\n if (token.type === \"template\") {\n const colors = templateColorMap?.get(token.value) || {\n from: \"#f43f5e\",\n to: \"#8b5cf6\",\n };\n const style = {\n \"--color-from\": colors.from,\n \"--color-to\": colors.to,\n } as React.CSSProperties;\n\n return (\n <span\n key={index}\n style={style}\n onClick={() => onTemplateClick?.(token.value)}\n className=\"inline-flex items-center px-1.5 py-0.5 mx-0.5 text-xs font-semibold rounded-md border border-[var(--color-to)]/40 bg-gradient-to-r from-[var(--color-from)]/15 to-[var(--color-to)]/15 text-[var(--color-to)] hover:brightness-110 cursor-pointer transition-all\"\n title={`Template: ${token.value}`}\n >\n {`{{${token.value}}}`}\n </span>\n );\n }\n\n if (token.type === \"variable\") {\n const details = [\n `Variable: ${token.value}`,\n token.description,\n token.defaultValue !== undefined\n ? `Default: ${token.defaultValue || \"(empty)\"}`\n : undefined,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n\n if (token.resolvedValue !== undefined) {\n return (\n <span\n key={index}\n onClick={() => onVariableClick?.(token.value)}\n data-variable={token.value}\n data-value-source={token.valueSource}\n className={\n token.valueSource === \"value\"\n ? \"inline px-1 mx-0.5 rounded-md bg-emerald-400/15 text-emerald-700 dark:text-emerald-300 border-b border-emerald-400/60 cursor-pointer\"\n : \"inline px-1 mx-0.5 rounded-md bg-violet-400/10 text-violet-600 dark:text-violet-300 italic border-b border-dashed border-violet-400/60 cursor-pointer\"\n }\n title={details}\n >\n {token.resolvedValue}\n </span>\n );\n }\n\n return (\n <span\n key={index}\n onClick={() => onVariableClick?.(token.value)}\n data-variable={token.value}\n className=\"inline-flex items-center px-1.5 py-0.5 mx-0.5 text-xs font-medium rounded-md border border-violet-400/40 bg-violet-400/15 text-violet-600 dark:text-violet-300 hover:brightness-110 cursor-pointer transition-all\"\n title={details}\n >\n {`{${token.value}`}\n {token.defaultValue !== undefined && (\n <span className=\"opacity-60\">{`|${token.defaultValue}`}</span>\n )}\n {\"}\"}\n </span>\n );\n }\n\n if (token.type === \"conditional\" && token.conditional) {\n return (\n <span\n key={index}\n data-conditional={token.conditional}\n className=\"inline-flex items-center px-1 py-0.5 mx-0.5 text-xs font-medium rounded-md border border-amber-400/40 bg-amber-400/15 text-amber-700 dark:text-amber-300\"\n title={\n token.conditional === \"end\"\n ? `End of section: ${token.value}`\n : token.conditional === \"if\"\n ? `Shown when \"${token.value}\" has a value`\n : `Shown when \"${token.value}\" is empty`\n }\n >\n {`{${CONDITIONAL_PREFIX[token.conditional]}${token.value}}`}\n </span>\n );\n }\n\n if (token.type === \"instruction\") {\n return (\n <span\n key={index}\n className=\"inline-flex items-center px-1.5 py-0.5 mx-0.5 text-xs italic font-medium rounded-md border border-rose-400/40 bg-rose-400/15 text-rose-600 dark:text-rose-300\"\n title={`Instruction: ${token.value}`}\n >\n {`__${token.value}__`}\n </span>\n );\n }\n\n return <span key={index}>{token.value}</span>;\n })}\n </div>\n );\n};\n","import React, { useId, useMemo, useState } from \"react\";\nimport {\n compactVariableValues,\n getVariableFormFields,\n PromptValues,\n Template,\n VariableFormField,\n} from \"@pixerate/editor\";\n\nexport interface VariableFormProps {\n /** Prompt whose variables become form fields */\n content: string;\n /** Templates searched recursively for further variables */\n templates?: Template[];\n /** Template version bindings */\n bindings?: Record<string, string>;\n /** Entered text per variable (controlled). Omit to let the form keep its own state. */\n values?: Record<string, string>;\n /** Initial entered text when uncontrolled */\n defaultValues?: Record<string, string>;\n /**\n * Called on every edit with the values to resolve with (blank fields\n * dropped so defaults apply) and the raw entered text.\n */\n onChange?: (values: PromptValues, entered: Record<string, string>) => void;\n /** Custom class name for the wrapper */\n className?: string;\n}\n\n/**\n * Renders one input per prompt variable: labelled with its description,\n * using its default as the placeholder. Variables only used by `{?name}`\n * conditions render as checkboxes.\n */\nexport const VariableForm: React.FC<VariableFormProps> = ({\n content,\n templates,\n bindings,\n values,\n defaultValues,\n onChange,\n className = \"flex flex-col gap-3 text-sm\",\n}) => {\n const idPrefix = useId();\n const [internal, setInternal] = useState<Record<string, string>>(\n () => defaultValues ?? {},\n );\n const entered = values ?? internal;\n\n const fields = useMemo<VariableFormField[]>(\n () => getVariableFormFields(content, { templates, bindings }),\n [content, templates, bindings],\n );\n\n const update = (name: string, value: string) => {\n const next = { ...entered, [name]: value };\n if (values === undefined) setInternal(next);\n onChange?.(compactVariableValues(next), next);\n };\n\n if (fields.length === 0) return null;\n\n return (\n <form className={className} onSubmit={(event) => event.preventDefault()}>\n {fields.map((field) => {\n const id = `${idPrefix}-${field.name}`;\n if (field.conditionOnly) {\n return (\n <label\n key={field.name}\n htmlFor={id}\n className=\"flex items-center gap-2\"\n data-variable-field={field.name}\n >\n <input\n id={id}\n name={field.name}\n type=\"checkbox\"\n checked={(entered[field.name] ?? \"\") !== \"\"}\n onChange={(event) =>\n update(field.name, event.target.checked ? \"true\" : \"\")\n }\n />\n <span>{field.label}</span>\n </label>\n );\n }\n return (\n <label\n key={field.name}\n htmlFor={id}\n className=\"flex flex-col gap-1\"\n data-variable-field={field.name}\n >\n <span className=\"font-medium\">\n {field.label}\n {field.required && (\n <span className=\"text-rose-500\" aria-hidden=\"true\">\n {\" *\"}\n </span>\n )}\n </span>\n <input\n id={id}\n name={field.name}\n type=\"text\"\n value={entered[field.name] ?? \"\"}\n placeholder={field.placeholder}\n aria-required={field.required || undefined}\n onChange={(event) => update(field.name, event.target.value)}\n className=\"px-2 py-1 rounded-md border border-violet-400/40 bg-transparent\"\n />\n </label>\n );\n })}\n </form>\n );\n};\n","import { useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { createOutlineStore, type OutlineSnapshot } from \"@pixerate/editor\";\n\nexport type { OutlineHeading, OutlineSnapshot, OutlineTreeItem } from \"@pixerate/editor\";\n\n/**\n * Subscribes to an editor's heading outline. Returns the headings (flat and\n * nested) and the id of the heading whose section contains the selection.\n * Re-renders only when the outline or the active heading changes.\n *\n * Install the `Outline` extension (`richTextOptions: { outline: true }`) for\n * stable heading ids; without it, headings are still listed.\n */\nexport function useOutline(editor: Editor | null | undefined): OutlineSnapshot {\n // The store only listens to the editor while subscribed, so it needs no\n // explicit cleanup (and survives StrictMode's double effects).\n const store = useMemo(() => createOutlineStore(editor), [editor]);\n return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n}\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { navigateToHeading, type OutlineHeading } from \"@pixerate/editor\";\nimport { useOutline } from \"../hooks/useOutline\";\n\nexport interface OutlinePanelProps {\n editor: Editor | null;\n /** Heading shown above the list. Pass `null` to hide it. */\n title?: React.ReactNode;\n /** Content shown when the document has no headings. */\n emptyState?: React.ReactNode;\n /** Deepest heading level listed. Defaults to 6. */\n maxLevel?: number;\n /** Whether clicking an entry focuses the editor. Defaults to `true`. */\n focusOnNavigate?: boolean;\n /** Custom class name for the wrapper. */\n className?: string;\n /** Class name for each entry button. */\n itemClassName?: string;\n /** Class name added to the entry of the section containing the selection. */\n activeItemClassName?: string;\n /** Called after navigating to a heading. */\n onNavigate?: (heading: OutlineHeading) => void;\n}\n\n/**\n * Navigation sidebar listing the document's headings (Word's Navigation pane).\n * Clicking an entry moves the caret to that heading; the entry for the\n * section containing the selection is highlighted.\n */\nexport const OutlinePanel: React.FC<OutlinePanelProps> = ({\n editor,\n title = \"Outline\",\n emptyState = \"Add headings to see the outline.\",\n maxLevel = 6,\n focusOnNavigate = true,\n className = \"flex flex-col gap-1 text-sm\",\n itemClassName = \"w-full truncate rounded px-2 py-1 text-left hover:bg-black/5\",\n activeItemClassName = \"font-semibold bg-black/5\",\n onNavigate,\n}) => {\n const { headings, activeId } = useOutline(editor);\n const visible = headings.filter((h) => h.level <= maxLevel);\n\n return (\n <nav className={className} aria-label=\"Document outline\" data-outline-panel=\"\">\n {title != null && <div className=\"pixerate-outline-title\">{title}</div>}\n {visible.length === 0 ? (\n <div className=\"pixerate-outline-empty\">{emptyState}</div>\n ) : (\n <ul role=\"list\" style={{ listStyle: \"none\", margin: 0, padding: 0 }}>\n {visible.map((heading) => {\n const active = heading.id === activeId;\n return (\n <li key={heading.id} data-level={heading.level}>\n <button\n type=\"button\"\n className={active ? `${itemClassName} ${activeItemClassName}` : itemClassName}\n style={{ paddingLeft: `${0.5 + heading.depth * 0.75}rem` }}\n aria-current={active ? \"location\" : undefined}\n data-heading-id={heading.id}\n onClick={() => {\n if (!editor) return;\n if (navigateToHeading(editor, heading, { focus: focusOnNavigate })) {\n onNavigate?.(heading);\n }\n }}\n >\n {heading.text || \"Untitled\"}\n </button>\n </li>\n );\n })}\n </ul>\n )}\n </nav>\n );\n};\n","import { useState, useRef, useCallback, useMemo } from 'react';\nimport {\n SpreadsheetController,\n bindSpreadsheetTableActions,\n type SpreadsheetControllerOptions,\n type SpreadsheetDocument,\n type CellCoordinate,\n type CellRange,\n type SpreadsheetColumn,\n type SpreadsheetRow,\n type SpreadsheetDataSource\n} from '@pixerate/editor/spreadsheet';\n\nexport function useSpreadsheetEditor(options: SpreadsheetControllerOptions = {}) {\n // Callbacks are read through a ref so they are never stale.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const settersRef = useRef<{\n setDoc?: (doc: SpreadsheetDocument) => void;\n setActiveCell?: (cell: CellCoordinate | null) => void;\n setSelectedRange?: (range: CellRange | null) => void;\n }>({});\n\n // Create the controller first so the initial state reflects its document\n // (including default rows and columns when no document is passed).\n const [controller] = useState(\n () =>\n new SpreadsheetController({\n ...options,\n onDocumentChange: (updated) => {\n settersRef.current.setDoc?.({ ...updated });\n optionsRef.current.onDocumentChange?.(updated);\n },\n onSelectionChange: (active, range) => {\n settersRef.current.setActiveCell?.(active);\n settersRef.current.setSelectedRange?.(range);\n optionsRef.current.onSelectionChange?.(active, range);\n },\n onCellCommit: (rowId, colId, raw, value) => {\n optionsRef.current.onCellCommit?.(rowId, colId, raw, value);\n },\n }),\n );\n\n const [doc, setDoc] = useState<SpreadsheetDocument>(() => ({ ...controller.document }));\n const [activeCell, setActiveCell] = useState<CellCoordinate | null>(controller.activeCell);\n const [selectedRange, setSelectedRange] = useState<CellRange | null>(controller.selectedRange);\n const [editingCell, setEditingCell] = useState<CellCoordinate | null>(null);\n const [draftValue, setDraftValue] = useState<string>('');\n settersRef.current = { setDoc, setActiveCell, setSelectedRange };\n\n const setCellValue = useCallback((rowId: string, colId: string, raw: string) => {\n controller.setCellValue(rowId, colId, raw);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const selectCell = useCallback((row: number, col: number, extendSelection = false) => {\n controller.selectCell(row, col, extendSelection);\n setActiveCell(controller.activeCell);\n setSelectedRange(controller.selectedRange);\n }, [controller]);\n\n const selectRange = useCallback((range: CellRange) => {\n controller.selectRange(range);\n setSelectedRange(controller.selectedRange);\n }, [controller]);\n\n const startEditing = useCallback((row?: number, col?: number, initialVal?: string) => {\n controller.startEditing(row, col, initialVal);\n setActiveCell(controller.activeCell);\n setEditingCell(controller.editingCell);\n setDraftValue(controller.draftValue);\n }, [controller]);\n\n const commitEditing = useCallback((val?: string) => {\n controller.commitEditing(val);\n setEditingCell(null);\n setDraftValue('');\n setDoc({ ...controller.document });\n }, [controller]);\n\n const cancelEditing = useCallback(() => {\n controller.cancelEditing();\n setEditingCell(null);\n setDraftValue('');\n }, [controller]);\n\n const moveCursor = useCallback((dir: 'up' | 'down' | 'left' | 'right', extend = false) => {\n controller.moveCursor(dir, extend);\n setActiveCell(controller.activeCell);\n setSelectedRange(controller.selectedRange);\n }, [controller]);\n\n const insertColumn = useCallback((index: number, config?: Partial<SpreadsheetColumn>) => {\n controller.insertColumn(index, config);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const deleteColumn = useCallback((colId: string) => {\n controller.deleteColumn(colId);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const insertRow = useCallback((index: number, config?: Partial<SpreadsheetRow>) => {\n controller.insertRow(index, config);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const deleteRow = useCallback((rowId: string) => {\n controller.deleteRow(rowId);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const setColumnWidth = useCallback((colId: string, width: number) => {\n controller.setColumnWidth(colId, width);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const autoFitColumnWidth = useCallback((colId: string, customWidth?: number) => {\n controller.autoFitColumnWidth(colId, customWidth);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const registerDataSource = useCallback((ds: SpreadsheetDataSource) => {\n controller.registerDataSource(ds);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const setPrimaryDataSource = useCallback((id: string | undefined) => {\n controller.setPrimaryDataSource(id);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const recalculateAll = useCallback(() => {\n controller.recalculateAll();\n setDoc({ ...controller.document });\n }, [controller]);\n\n const undo = useCallback(() => {\n controller.undo();\n setDoc({ ...controller.document });\n }, [controller]);\n\n const redo = useCallback(() => {\n controller.redo();\n setDoc({ ...controller.document });\n }, [controller]);\n\n // Table operations (sort, filters, freeze, hide, merge, autofill, categories,\n // transpose, CSV, clipboard). The controller reports their changes through\n // onDocumentChange / onSelectionChange, which update the state above.\n const tableActions = useMemo(() => bindSpreadsheetTableActions(controller), [controller]);\n // What to render: visible rows (with group headers) and columns, frozen\n // offsets and merged-cell spans. Recomputed whenever the document changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const viewModel = useMemo(() => controller.getViewModel(), [controller, doc]);\n\n return {\n document: doc,\n activeCell,\n selectedRange,\n editingCell,\n draftValue,\n setDraftValue,\n controller,\n getCell: (rowId: string, colId: string) => controller.getCell(rowId, colId),\n setCellValue,\n selectCell,\n selectRange,\n startEditing,\n commitEditing,\n cancelEditing,\n moveCursor,\n insertColumn,\n deleteColumn,\n insertRow,\n deleteRow,\n setColumnWidth,\n autoFitColumnWidth,\n loadDocument: (document: SpreadsheetDocument) => {\n controller.loadDocument(document);\n setDoc({ ...controller.document });\n setActiveCell(null);\n setSelectedRange(null);\n setEditingCell(null);\n setDraftValue('');\n },\n syncWithDataSource: () => {\n controller.syncWithDataSource();\n controller.recalculateAll();\n setDoc({ ...controller.document });\n },\n registerDataSource,\n setPrimaryDataSource,\n recalculateAll,\n exportToTsv: (range?: CellRange | null) => controller.exportToTsv(range),\n importFromTsv: (data: string) => {\n controller.importFromTsv(data);\n setDoc({ ...controller.document });\n },\n ...tableActions,\n viewModel,\n undo,\n redo\n };\n}\n","import React, { useRef, useState, useMemo, useEffect, useCallback } from 'react';\nimport {\n indexToColName,\n getSpreadsheetMenuItems,\n normalizeRange,\n rangeContains,\n type SpreadsheetColumn,\n type SpreadsheetRow,\n type CellData,\n type SpreadsheetMenuItem,\n type SpreadsheetViewColumn,\n type SpreadsheetViewRow\n} from '@pixerate/editor/spreadsheet';\nimport { useSpreadsheetEditor } from './useSpreadsheetEditor';\nimport { SpreadsheetContextMenu } from './SpreadsheetContextMenu';\nimport { SpreadsheetGroupRow } from './SpreadsheetGroupRow';\nimport { useFillHandle, useSpreadsheetClipboard } from './useSpreadsheetTableInteractions';\n\n// Sizes of the sticky header row and row-number column, for frozen-pane offsets.\nconst COLUMN_HEADER_HEIGHT = 28;\nconst ROW_HEADER_WIDTH = 48;\n\n/** Sticky positioning for cells in frozen rows and/or columns. */\nfunction frozenCellStyle(\n viewRow: Extract<SpreadsheetViewRow, { kind: 'row' }>,\n viewCol: SpreadsheetViewColumn\n): React.CSSProperties | undefined {\n if (!viewRow.frozen && !viewCol.frozen) return undefined;\n return {\n position: 'sticky',\n ...(viewRow.frozen ? { top: COLUMN_HEADER_HEIGHT + viewRow.stickyTop } : {}),\n ...(viewCol.frozen ? { left: ROW_HEADER_WIDTH + viewCol.stickyLeft } : {}),\n zIndex: viewRow.frozen && viewCol.frozen ? 14 : viewRow.frozen ? 12 : 11,\n background: 'var(--background, #fff)'\n };\n}\nimport { FormulaHints } from './FormulaHints';\n\nexport interface SpreadsheetEditorProps {\n state?: ReturnType<typeof useSpreadsheetEditor>;\n readOnly?: boolean;\n customCellRenderer?: (props: { row: SpreadsheetRow; col: SpreadsheetColumn; cell: CellData }) => React.ReactNode;\n onAddColumnClick?: () => void;\n onColumnHeaderClick?: (col: SpreadsheetColumn) => void;\n onColumnResize?: (colId: string, width: number) => void;\n}\n\nexport const SpreadsheetEditor: React.FC<SpreadsheetEditorProps> = ({\n state: externalState,\n readOnly = false,\n customCellRenderer,\n onAddColumnClick,\n onColumnHeaderClick,\n onColumnResize\n}) => {\n const defaultState = useSpreadsheetEditor();\n const state = externalState || defaultState;\n const gridRef = useRef<HTMLDivElement>(null);\n const formulaBarRef = useRef<HTMLInputElement>(null);\n const cellInputRef = useRef<HTMLInputElement>(null);\n\n const [resizingColId, setResizingColId] = useState<string | null>(null);\n const [hoveredColId, setHoveredColId] = useState<string | null>(null);\n const [resizeStartX, setResizeStartX] = useState(0);\n const [resizeStartWidth, setResizeStartWidth] = useState(0);\n\n // Table operations: render model, clipboard, fill handle and context menu.\n const view = state.viewModel;\n const { copyShortcutFallback } = useSpreadsheetClipboard(gridRef, state, readOnly);\n const { fillTarget, startFill, extendFill } = useFillHandle(state);\n const [menu, setMenu] = useState<{ x: number; y: number; items: SpreadsheetMenuItem[] } | null>(null);\n const filter = state.document.table?.filter;\n const filteredColIds = useMemo(\n () => new Set(filter?.enabled ? filter.rules.map((r) => r.colId) : []),\n [filter]\n );\n\n const handleCellContextMenu = useCallback((rIdx: number, cIdx: number, e: React.MouseEvent) => {\n if (readOnly) return;\n e.preventDefault();\n if (state.editingCell) state.commitEditing();\n if (!state.selectedRange || !rangeContains(state.selectedRange, rIdx, cIdx)) {\n state.selectCell(rIdx, cIdx);\n }\n setMenu({ x: e.clientX, y: e.clientY, items: getSpreadsheetMenuItems(state.controller, { row: rIdx, col: cIdx }) });\n }, [readOnly, state]);\n\n const activeRawValue = useMemo(() => {\n if (!state.activeCell) return '';\n const row = state.document.rows[state.activeCell.row];\n const col = state.document.columns[state.activeCell.col];\n if (!row || !col) return '';\n return state.getCell(row.id, col.id).raw;\n }, [state.activeCell, state.document]);\n\n const coordLabel = useMemo(() => {\n if (!state.activeCell) return '--';\n const colName = indexToColName(state.activeCell.col);\n return `${colName}${state.activeCell.row + 1}`;\n }, [state.activeCell]);\n\n // Text typed in the formula bar while no cell editor is open.\n const [formulaDraft, setFormulaDraft] = useState<string | null>(null);\n const activeColumn = state.activeCell ? state.document.columns[state.activeCell.col] : undefined;\n const formulaBarReadOnly = readOnly || !state.activeCell || !!activeColumn?.readOnly;\n\n useEffect(() => {\n setFormulaDraft(null);\n }, [state.activeCell?.row, state.activeCell?.col]);\n\n const commitFormulaBar = () => {\n if (state.editingCell) {\n state.commitEditing();\n return;\n }\n if (formulaDraft === null || !state.activeCell) return;\n const row = state.document.rows[state.activeCell.row];\n const col = state.document.columns[state.activeCell.col];\n if (row && col && !formulaBarReadOnly && formulaDraft !== activeRawValue) {\n state.setCellValue(row.id, col.id, formulaDraft);\n }\n setFormulaDraft(null);\n };\n\n const handleCellClick = useCallback((rIdx: number, cIdx: number, e: React.MouseEvent) => {\n if (state.editingCell && (state.editingCell.row !== rIdx || state.editingCell.col !== cIdx)) {\n state.commitEditing();\n }\n state.selectCell(rIdx, cIdx, e.shiftKey);\n }, [state]);\n\n const handleCellDblClick = useCallback((rIdx: number, cIdx: number) => {\n if (readOnly) return;\n const col = state.document.columns[cIdx];\n if (col?.readOnly) return;\n state.startEditing(rIdx, cIdx);\n }, [readOnly, state]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (state.editingCell) {\n if (e.key === 'Enter') {\n e.preventDefault();\n state.commitEditing();\n state.moveCursor('down');\n } else if (e.key === 'Escape') {\n e.preventDefault();\n state.cancelEditing();\n } else if (e.key === 'Tab') {\n e.preventDefault();\n state.commitEditing();\n state.moveCursor(e.shiftKey ? 'left' : 'right');\n }\n return;\n }\n\n if (!state.activeCell) return;\n\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n state.moveCursor('up', e.shiftKey);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n state.moveCursor('down', e.shiftKey);\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n state.moveCursor('left', e.shiftKey);\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n state.moveCursor('right', e.shiftKey);\n } else if (e.key === 'Tab') {\n e.preventDefault();\n state.moveCursor(e.shiftKey ? 'left' : 'right');\n } else if (e.key === 'Enter') {\n e.preventDefault();\n const col = state.document.columns[state.activeCell.col];\n if (!readOnly && !col?.readOnly) {\n state.startEditing();\n }\n } else if (e.key === 'Backspace' || e.key === 'Delete') {\n if (readOnly) return;\n const row = state.document.rows[state.activeCell.row];\n const col = state.document.columns[state.activeCell.col];\n if (row && col && !col.readOnly) {\n e.preventDefault();\n state.setCellValue(row.id, col.id, '');\n }\n } else if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'z') {\n // With Shift held, e.key is 'Z'.\n e.preventDefault();\n if (e.shiftKey) {\n state.redo();\n } else {\n state.undo();\n }\n } else if (e.ctrlKey && !e.metaKey && e.key.toLowerCase() === 'y') {\n e.preventDefault();\n state.redo();\n } else if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'c') {\n // Copy the selection, not the whole sheet. The browser's copy event\n // writes TSV, HTML and the internal format; the fallback writes TSV.\n copyShortcutFallback();\n } else if (!readOnly && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n const col = state.document.columns[state.activeCell.col];\n if (!col?.readOnly) {\n state.startEditing(state.activeCell.row, state.activeCell.col, e.key);\n }\n }\n }, [readOnly, state, copyShortcutFallback]);\n // The resize effect reads these through refs: re-running it on every width\n // update would reset the in-progress drag (and skip onColumnResize).\n const stateRef = useRef(state);\n stateRef.current = state;\n const onColumnResizeRef = useRef(onColumnResize);\n onColumnResizeRef.current = onColumnResize;\n\n useEffect(() => {\n if (!resizingColId) return;\n\n if (typeof document !== 'undefined') {\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n }\n\n let rafId: number | null = null;\n let pendingWidth = resizeStartWidth;\n let hasDragged = false;\n\n const handleMouseMove = (e: MouseEvent) => {\n const delta = e.clientX - resizeStartX;\n if (Math.abs(delta) > 2) {\n hasDragged = true;\n }\n pendingWidth = Math.max(30, resizeStartWidth + delta);\n\n if (rafId === null) {\n rafId = requestAnimationFrame(() => {\n rafId = null;\n stateRef.current.setColumnWidth(resizingColId, pendingWidth);\n });\n }\n };\n\n const handleMouseUp = () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n if (hasDragged) {\n stateRef.current.setColumnWidth(resizingColId, pendingWidth);\n onColumnResizeRef.current?.(resizingColId, pendingWidth);\n }\n setResizingColId(null);\n if (typeof document !== 'undefined') {\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n }\n };\n\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n return () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n if (typeof document !== 'undefined') {\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n }\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n }, [resizingColId, resizeStartX, resizeStartWidth]);\n\n const measureElementContentWidth = useCallback((el: HTMLElement, container: HTMLElement): number => {\n if (typeof document === 'undefined') return 0;\n\n let maxW = el.scrollWidth || 0;\n const firstChild = el.firstElementChild as HTMLElement | null;\n if (firstChild && firstChild.scrollWidth > maxW) {\n maxW = firstChild.scrollWidth;\n }\n\n const truncated = el.querySelectorAll<HTMLElement>('.truncate, [title], span, div');\n truncated.forEach((node) => {\n if (node.scrollWidth > maxW) {\n maxW = node.scrollWidth;\n }\n });\n\n try {\n const clone = (firstChild ? firstChild.cloneNode(true) : el.cloneNode(true)) as HTMLElement;\n clone.style.cssText = `\n position: absolute !important;\n visibility: hidden !important;\n width: max-content !important;\n min-width: max-content !important;\n max-width: none !important;\n overflow: visible !important;\n white-space: nowrap !important;\n pointer-events: none !important;\n top: -9999px !important;\n left: -9999px !important;\n `;\n\n const allNodes = clone.querySelectorAll<HTMLElement>('*');\n allNodes.forEach((node) => {\n node.style.maxWidth = 'none';\n node.style.overflow = 'visible';\n node.style.textOverflow = 'clip';\n node.style.whiteSpace = 'nowrap';\n if (\n node.classList.contains('truncate') ||\n node.classList.contains('min-w-0') ||\n node.classList.contains('w-full') ||\n node.classList.contains('max-w-0') ||\n node.classList.contains('flex-1')\n ) {\n node.style.width = 'max-content';\n node.style.minWidth = 'max-content';\n }\n });\n\n container.appendChild(clone);\n const rect = clone.getBoundingClientRect();\n container.removeChild(clone);\n\n if (rect.width > maxW) {\n maxW = rect.width;\n }\n } catch {\n // Ignore cloning/measuring errors\n }\n\n return maxW;\n }, []);\n\n const autoFitColumn = useCallback((colId: string, colIndex: number) => {\n const col = state.document.columns.find((c) => c.id === colId);\n if (!col) return;\n\n let calculatedWidth = 0;\n\n if (gridRef.current && typeof document !== 'undefined') {\n const table = gridRef.current.querySelector('table');\n if (table) {\n // Look cells up by column index: hidden columns and merges shift DOM positions.\n const th = table.querySelector(`thead th[data-col=\"${colIndex}\"]`) as HTMLElement | null;\n if (th) {\n const headerInner = (th.firstElementChild as HTMLElement) || th;\n const headerW = measureElementContentWidth(headerInner, gridRef.current);\n calculatedWidth = Math.max(calculatedWidth, headerW + 28);\n }\n\n const rows = table.querySelectorAll('tbody tr');\n const sampleLimit = Math.min(rows.length, 150);\n for (let r = 0; r < sampleLimit; r++) {\n const tr = rows[r];\n const td = tr.querySelector(`td[data-col=\"${colIndex}\"][colspan=\"1\"]`) as HTMLElement | null;\n if (td) {\n const cellW = measureElementContentWidth(td, gridRef.current);\n calculatedWidth = Math.max(calculatedWidth, cellW + 20);\n }\n }\n }\n }\n\n if (calculatedWidth > 0) {\n const finalWidth = Math.min(600, Math.max(50, Math.ceil(calculatedWidth)));\n state.setColumnWidth(colId, finalWidth);\n } else {\n state.autoFitColumnWidth?.(colId);\n }\n\n const updatedCol = state.document.columns.find((c) => c.id === colId);\n if (updatedCol && onColumnResize) {\n onColumnResize(updatedCol.id, updatedCol.width || 130);\n }\n }, [state, measureElementContentWidth, onColumnResize]);\n\n const handleResizeDblClick = useCallback((colId: string, colIndex: number, e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n autoFitColumn(colId, colIndex);\n }, [autoFitColumn]);\n\n const handleHeaderDblClick = useCallback((colId: string, colIndex: number, e: React.MouseEvent) => {\n const target = e.currentTarget as HTMLElement | null;\n if (target) {\n const rect = target.getBoundingClientRect();\n if (rect.right - e.clientX <= 12) {\n e.preventDefault();\n e.stopPropagation();\n autoFitColumn(colId, colIndex);\n }\n }\n }, [autoFitColumn]);\n\n const isCellSelected = (rIdx: number, cIdx: number) => {\n if (!state.selectedRange) return false;\n const minR = Math.min(state.selectedRange.startRow, state.selectedRange.endRow);\n const maxR = Math.max(state.selectedRange.startRow, state.selectedRange.endRow);\n const minC = Math.min(state.selectedRange.startCol, state.selectedRange.endCol);\n const maxC = Math.max(state.selectedRange.startCol, state.selectedRange.endCol);\n return rIdx >= minR && rIdx <= maxR && cIdx >= minC && cIdx <= maxC;\n };\n\n const isActiveCell = (rIdx: number, cIdx: number) => {\n return state.activeCell?.row === rIdx && state.activeCell?.col === cIdx;\n };\n\n return (\n <div\n ref={gridRef}\n className=\"flex flex-col h-full w-full overflow-hidden border border-border bg-background select-none outline-none text-foreground font-sans text-xs\"\n tabIndex={0}\n onKeyDown={handleKeyDown}\n role=\"grid\"\n aria-label=\"Spreadsheet\"\n >\n {/* Formula Bar */}\n <div className=\"flex items-center gap-2 border-b border-border bg-muted/20 px-3 py-1.5 text-xs font-mono\">\n <div className=\"flex h-6 min-w-[3rem] items-center justify-center rounded border border-border bg-background px-1.5 font-semibold text-foreground\">\n {coordLabel}\n </div>\n <div className=\"flex items-center text-muted-foreground select-none\">\n <span className=\"italic font-serif font-bold text-sm text-primary\">fx</span>\n </div>\n <input\n ref={formulaBarRef}\n type=\"text\"\n className=\"flex-1 bg-transparent px-2 py-0.5 outline-none font-sans text-xs text-foreground placeholder:text-muted-foreground/60 focus:bg-background focus:ring-1 focus:ring-primary rounded\"\n placeholder=\"Enter a value or formula (e.g. =SUM(A1:A5))\"\n aria-label=\"Formula bar\"\n readOnly={formulaBarReadOnly}\n value={state.editingCell ? state.draftValue : formulaDraft ?? activeRawValue}\n onFocus={() => {\n if (!state.editingCell) setFormulaDraft(activeRawValue);\n }}\n onChange={(e) => {\n if (state.editingCell) {\n state.setDraftValue(e.target.value);\n } else if (state.activeCell) {\n setFormulaDraft(e.target.value);\n }\n }}\n onBlur={() => commitFormulaBar()}\n onKeyDown={(e) => {\n // Keys typed here must not reach the grid's navigation handler.\n e.stopPropagation();\n if (e.key === 'Enter') {\n e.preventDefault();\n commitFormulaBar();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setFormulaDraft(null);\n if (state.editingCell) state.cancelEditing();\n }\n }}\n />\n {!formulaBarReadOnly && (\n <FormulaHints\n inputRef={formulaBarRef}\n value={state.editingCell ? state.draftValue : formulaDraft ?? activeRawValue}\n onAccept={(next) => (state.editingCell ? state.setDraftValue(next) : setFormulaDraft(next))}\n />\n )}\n </div>\n\n {/* Main Grid */}\n <div className=\"relative flex-1 overflow-auto\">\n <table className=\"border-collapse table-fixed w-max min-w-full\">\n <thead>\n <tr className=\"h-7 bg-muted/60 sticky top-0 z-20 border-b border-border shadow-xs\">\n <th className=\"w-12 min-w-[3rem] sticky left-0 z-30 bg-muted/90 border-r border-border text-center text-[10px] text-muted-foreground font-medium\">\n #\n </th>\n {view.columns.map(({ column: col, index: cIdx, frozen, stickyLeft }) => (\n <th\n key={col.id}\n data-col={cIdx}\n className={`relative border-r border-border px-2 text-left font-medium text-muted-foreground hover:bg-muted/90 transition-colors group overflow-hidden max-w-0 ${\n onColumnHeaderClick ? 'cursor-pointer' : 'cursor-default'\n }`}\n style={{\n width: col.width || 130,\n minWidth: col.width || 130,\n maxWidth: col.width || 130,\n overflow: 'hidden',\n ...(frozen ? { position: 'sticky', left: ROW_HEADER_WIDTH + stickyLeft, zIndex: 25, background: 'var(--muted, #f4f4f5)' } : {})\n }}\n onClick={() => onColumnHeaderClick?.(col)}\n onDoubleClick={(e) => handleHeaderDblClick(col.id, cIdx, e)}\n >\n <div className=\"flex items-center justify-between gap-1 min-w-0 overflow-hidden truncate\">\n <span className=\"truncate font-semibold text-foreground text-xs min-w-0\">{col.title}</span>\n {filteredColIds.has(col.id) && (\n <span className=\"text-[10px] text-primary shrink-0\" title=\"Filtered\" data-filtered=\"true\">⏷</span>\n )}\n <span className=\"text-[10px] text-muted-foreground/70 font-mono font-normal shrink-0\">({col.key})</span>\n </div>\n {/* Column Resize Handle */}\n <div\n className=\"col-resize-handle\"\n style={{ position: 'absolute', top: 0, bottom: 0, width: 12, right: -6, cursor: 'col-resize', zIndex: 20, display: 'flex', justifyContent: 'center', touchAction: 'none' }}\n onMouseEnter={() => setHoveredColId(col.id)}\n onMouseLeave={() => setHoveredColId((cur) => cur === col.id ? null : cur)}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setResizingColId(col.id);\n setResizeStartX(e.clientX);\n setResizeStartWidth(col.width || 130);\n }}\n onDoubleClick={(e) => handleResizeDblClick(col.id, cIdx, e)}\n role=\"separator\"\n aria-orientation=\"vertical\"\n >\n <div\n className=\"col-resize-handle-line\"\n style={{\n width: 2,\n height: '100%',\n pointerEvents: 'none',\n transition: 'background-color 150ms ease',\n backgroundColor: resizingColId === col.id ? 'var(--primary, #6366f1)' : hoveredColId === col.id ? 'color-mix(in srgb, var(--primary, #6366f1) 75%, transparent)' : 'transparent'\n }}\n />\n </div>\n </th>\n ))}\n {onAddColumnClick && (\n <th\n className=\"w-10 min-w-[2.5rem] px-1 text-center bg-muted/40 hover:bg-muted cursor-pointer transition-colors\"\n onClick={onAddColumnClick}\n title=\"Add Column\"\n >\n <span className=\"text-xs font-bold text-muted-foreground\">+</span>\n </th>\n )}\n </tr>\n </thead>\n <tbody>\n {view.rows.map((viewRow) => {\n if (viewRow.kind === 'group') {\n return (\n <SpreadsheetGroupRow\n key={`group:${viewRow.group.key}`}\n group={viewRow.group}\n columns={view.columns}\n groupColId={state.document.table?.grouping?.colId ?? ''}\n onToggle={state.toggleGroupCollapsed}\n trailingCell={!!onAddColumnClick}\n />\n );\n }\n const displayRowIndex = viewRow.index;\n const selection = state.selectedRange ? normalizeRange(state.selectedRange) : null;\n return (\n <tr\n key={viewRow.row.id}\n data-row={displayRowIndex}\n className={`border-b border-border hover:bg-muted/10 transition-colors ${viewRow.section !== 'body' ? 'bg-muted/30 font-semibold' : ''}`}\n style={{ height: viewRow.row.height || 32 }}\n >\n <td\n className=\"w-12 min-w-[3rem] sticky left-0 z-10 bg-muted/50 border-r border-border text-center text-[10px] text-muted-foreground font-mono select-none\"\n style={viewRow.frozen ? { top: COLUMN_HEADER_HEIGHT + viewRow.stickyTop, zIndex: 15 } : undefined}\n >\n {displayRowIndex + 1}\n </td>\n {view.columns.map((viewCol) => {\n // A merged cell renders its top-left cell, spanning the merge.\n const span = view.getCellSpan(displayRowIndex, viewCol.index);\n if (!span) return null;\n const rIdx = span.source.row;\n const cIdx = span.source.col;\n const row = state.document.rows[rIdx];\n const col = state.document.columns[cIdx];\n const cell = state.getCell(row.id, col.id);\n const selected = isCellSelected(rIdx, cIdx);\n const active = isActiveCell(rIdx, cIdx);\n const isEditing = state.editingCell?.row === rIdx && state.editingCell?.col === cIdx;\n\n const inFillPreview = !!fillTarget && !selected && rangeContains(fillTarget, displayRowIndex, viewCol.index);\n const showFillHandle =\n !readOnly &&\n !isEditing &&\n !!selection &&\n (span.merge\n ? rangeContains(span.merge, selection.endRow, selection.endCol)\n : selection.endRow === rIdx && selection.endCol === cIdx);\n\n return (\n <td\n key={viewCol.column.id}\n data-row={rIdx}\n data-col={cIdx}\n rowSpan={span.rowSpan}\n colSpan={span.colSpan}\n className={`relative border-r border-border px-2 py-1 truncate max-w-0 text-foreground transition-colors ${\n selected ? 'bg-primary/10' : ''\n } ${active ? 'ring-2 ring-primary ring-inset z-10' : ''} ${viewCol.header ? 'font-semibold' : ''}`}\n style={{\n maxWidth: 0,\n overflow: 'hidden',\n ...frozenCellStyle(viewRow, viewCol),\n ...(inFillPreview ? { outline: '1px dashed var(--primary, #6366f1)', outlineOffset: -1 } : {})\n }}\n onClick={(e) => handleCellClick(rIdx, cIdx, e)}\n onDoubleClick={() => handleCellDblClick(rIdx, cIdx)}\n onContextMenu={(e) => handleCellContextMenu(rIdx, cIdx, e)}\n onMouseOver={() => extendFill(displayRowIndex, viewCol.index)}\n >\n {isEditing ? (\n <>\n <input\n ref={cellInputRef}\n type=\"text\"\n className=\"absolute inset-0 w-full h-full px-2 py-1 bg-background text-foreground outline-none font-sans text-xs border-2 border-primary z-20\"\n value={state.draftValue}\n onChange={(e) => state.setDraftValue(e.target.value)}\n onBlur={() => state.commitEditing()}\n autoFocus\n />\n <FormulaHints inputRef={cellInputRef} value={state.draftValue} onAccept={state.setDraftValue} />\n </>\n ) : customCellRenderer ? (\n customCellRenderer({ row, col, cell })\n ) : (\n <span\n className={`truncate block max-w-full ${cell.error ? 'text-destructive font-semibold' : ''}`}\n title={cell.error ? cell.errorMessage ?? cell.error : undefined}\n >\n {cell.error || (cell.value ?? '')}\n </span>\n )}\n {showFillHandle && (\n <div\n className=\"spreadsheet-fill-handle\"\n aria-label=\"Fill handle\"\n onMouseDown={startFill}\n onClick={(e) => e.stopPropagation()}\n style={{ position: 'absolute', right: 0, bottom: 0, width: 7, height: 7, background: 'var(--primary, #6366f1)', cursor: 'crosshair', zIndex: 25 }}\n />\n )}\n </td>\n );\n })}\n {onAddColumnClick && <td className=\"w-10 min-w-[2.5rem] bg-muted/10 border-r border-border\" />}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n {menu && (\n <SpreadsheetContextMenu\n items={menu.items}\n x={menu.x}\n y={menu.y}\n onClose={() => {\n setMenu(null);\n gridRef.current?.focus();\n }}\n />\n )}\n <style>{`\n .col-resize-handle:hover .col-resize-handle-line {\n background-color: var(--primary, #6366f1);\n opacity: 0.75;\n }\n .col-resize-handle.active .col-resize-handle-line {\n background-color: var(--primary, #6366f1);\n opacity: 1;\n }\n table.table-fixed th {\n overflow: hidden;\n }\n table.table-fixed td {\n max-width: 0;\n overflow: hidden;\n }\n `}</style>\n </div>\n );\n};\n","import React, { useEffect, useRef } from 'react';\nimport type { SpreadsheetMenuItem } from '@pixerate/editor/spreadsheet';\n\nexport interface SpreadsheetContextMenuProps {\n items: SpreadsheetMenuItem[];\n x: number;\n y: number;\n onClose: () => void;\n}\n\n/** The table context menu (sort, filter, freeze, hide, merge, categories, transpose). */\nexport const SpreadsheetContextMenu: React.FC<SpreadsheetContextMenuProps> = ({ items, x, y, onClose }) => {\n const menuRef = useRef<HTMLDivElement>(null);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n\n useEffect(() => {\n const handlePointer = (e: MouseEvent) => {\n if (!menuRef.current?.contains(e.target as Node)) onCloseRef.current();\n };\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onCloseRef.current();\n };\n window.addEventListener('mousedown', handlePointer);\n window.addEventListener('keydown', handleKey);\n return () => {\n window.removeEventListener('mousedown', handlePointer);\n window.removeEventListener('keydown', handleKey);\n };\n }, []);\n\n return (\n <div\n ref={menuRef}\n role=\"menu\"\n aria-label=\"Table actions\"\n className=\"fixed z-50 min-w-[14rem] rounded-md border border-border bg-popover py-1 text-xs text-popover-foreground shadow-lg\"\n style={{ left: x, top: y, background: 'var(--popover, var(--background, #fff))' }}\n onContextMenu={(e) => e.preventDefault()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n {items.map((item) => (\n <React.Fragment key={item.id}>\n {item.separatorBefore && <div role=\"separator\" className=\"my-1 h-px bg-border\" />}\n <button\n type=\"button\"\n role=\"menuitem\"\n data-action={item.id}\n disabled={item.disabled}\n className=\"block w-full px-3 py-1 text-left hover:bg-muted disabled:cursor-default disabled:opacity-40 disabled:hover:bg-transparent\"\n onClick={() => {\n onClose();\n item.run();\n }}\n >\n {item.label}\n </button>\n </React.Fragment>\n ))}\n </div>\n );\n};\n","import React from 'react';\nimport type { SpreadsheetRowGroup, SpreadsheetViewColumn } from '@pixerate/editor/spreadsheet';\n\nexport interface SpreadsheetGroupRowProps {\n group: SpreadsheetRowGroup;\n columns: SpreadsheetViewColumn[];\n /** Column the rows are grouped by: shows the group label and toggle. */\n groupColId: string;\n onToggle: (key: string) => void;\n /** Render a trailing cell for the \"add column\" column. */\n trailingCell?: boolean;\n}\n\nconst formatSummary = (value: number | null) => (value === null ? '–' : String(value));\n\n/** A category header row: collapse toggle, label, row count and per-column summaries. */\nexport const SpreadsheetGroupRow: React.FC<SpreadsheetGroupRowProps> = ({\n group,\n columns,\n groupColId,\n onToggle,\n trailingCell\n}) => {\n // The label goes in the grouping column, or the first column when that one is hidden.\n const labelColId = columns.some((c) => c.column.id === groupColId) ? groupColId : columns[0]?.column.id;\n return (\n <tr className=\"border-b border-border bg-muted/40 font-semibold\" data-group-key={group.key} style={{ height: 28 }}>\n <td className=\"w-12 min-w-[3rem] sticky left-0 z-10 bg-muted/60 border-r border-border text-center\">\n <button\n type=\"button\"\n aria-label={`${group.collapsed ? 'Expand' : 'Collapse'} group ${group.label}`}\n aria-expanded={!group.collapsed}\n className=\"h-5 w-5 rounded text-[10px] text-muted-foreground hover:bg-muted\"\n onClick={(e) => {\n e.stopPropagation();\n onToggle(group.key);\n }}\n >\n {group.collapsed ? '▸' : '▾'}\n </button>\n </td>\n {columns.map(({ column }) => {\n const summary = group.summaries[column.id];\n return (\n <td key={column.id} className=\"border-r border-border px-2 py-1 truncate max-w-0 text-foreground\" style={{ maxWidth: 0, overflow: 'hidden' }}>\n {column.id === labelColId ? (\n <span className=\"truncate\">\n {group.label} <span className=\"font-normal text-muted-foreground\">({group.rowIndices.length})</span>\n </span>\n ) : summary !== undefined ? (\n <span className=\"truncate\" data-summary={column.id}>{formatSummary(summary)}</span>\n ) : null}\n </td>\n );\n })}\n {trailingCell && <td className=\"w-10 min-w-[2.5rem] bg-muted/10 border-r border-border\" />}\n </tr>\n );\n};\n","import { useCallback, useEffect, useRef, useState, type RefObject } from 'react';\nimport {\n computeFillTarget,\n normalizeRange,\n type CellRange\n} from '@pixerate/editor/spreadsheet';\nimport type { useSpreadsheetEditor } from './useSpreadsheetEditor';\n\ntype SpreadsheetState = ReturnType<typeof useSpreadsheetEditor>;\n\n/** True when focus is in the grid itself, not in a text input (cell editor, formula bar). */\nfunction gridHasFocus(grid: HTMLElement | null): boolean {\n if (!grid || typeof document === 'undefined') return false;\n const active = document.activeElement;\n if (!active || !grid.contains(active)) return false;\n return !(active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement);\n}\n\n/**\n * Copy and paste for the grid. Copy writes TSV, an HTML table and the\n * lossless `application/x.pixerate.spreadsheet+json` format; paste prefers\n * that format, then HTML, then TSV.\n *\n * The listeners are on `document`: with no text selection the browser fires\n * `copy`/`paste` at `<body>`, not at the focused grid. Text inputs inside the\n * grid keep native copy/paste.\n */\nexport function useSpreadsheetClipboard(\n gridRef: RefObject<HTMLElement | null>,\n state: SpreadsheetState,\n readOnly: boolean\n) {\n const stateRef = useRef(state);\n stateRef.current = state;\n const readOnlyRef = useRef(readOnly);\n readOnlyRef.current = readOnly;\n // Set when a copy event wrote the selection, so the keyboard fallback is skipped.\n const copiedRef = useRef(false);\n\n useEffect(() => {\n if (typeof document === 'undefined') return;\n const handleCopy = (e: ClipboardEvent) => {\n const s = stateRef.current;\n if (!gridHasFocus(gridRef.current) || s.editingCell || !e.clipboardData || !s.selectedRange) return;\n for (const [type, data] of Object.entries(s.copyToClipboardData(s.selectedRange))) {\n e.clipboardData.setData(type, data);\n }\n copiedRef.current = true;\n e.preventDefault();\n };\n const handlePaste = (e: ClipboardEvent) => {\n const s = stateRef.current;\n if (readOnlyRef.current || !gridHasFocus(gridRef.current) || s.editingCell || !e.clipboardData) return;\n if (s.pasteClipboardData(e.clipboardData)) e.preventDefault();\n };\n document.addEventListener('copy', handleCopy);\n document.addEventListener('paste', handlePaste);\n return () => {\n document.removeEventListener('copy', handleCopy);\n document.removeEventListener('paste', handlePaste);\n };\n }, [gridRef]);\n\n /**\n * Call on Mod+C (without preventing default). The browser normally follows\n * with a `copy` event; where it doesn't (no selection in some browsers),\n * the selection is written as plain TSV instead.\n */\n const copyShortcutFallback = useCallback(() => {\n copiedRef.current = false;\n setTimeout(() => {\n if (copiedRef.current) return;\n const s = stateRef.current;\n navigator.clipboard?.writeText(s.exportToTsv(s.selectedRange));\n }, 0);\n }, []);\n\n return { copyShortcutFallback };\n}\n\n/**\n * Fill handle dragging: press on the handle, move over cells, release to\n * autofill from the selection into the dragged range (one undo step).\n */\nexport function useFillHandle(state: SpreadsheetState) {\n const [drag, setDrag] = useState<{ source: CellRange; target: CellRange | null } | null>(null);\n const dragRef = useRef(drag);\n dragRef.current = drag;\n const stateRef = useRef(state);\n stateRef.current = state;\n const dragging = drag !== null;\n\n useEffect(() => {\n if (!dragging) return;\n const handleMouseUp = () => {\n const current = dragRef.current;\n setDrag(null);\n if (current?.target) stateRef.current.autofill(current.source, current.target);\n };\n window.addEventListener('mouseup', handleMouseUp);\n return () => window.removeEventListener('mouseup', handleMouseUp);\n }, [dragging]);\n\n const startFill = useCallback((e: { preventDefault(): void; stopPropagation(): void }) => {\n e.preventDefault();\n e.stopPropagation();\n const range = stateRef.current.selectedRange;\n if (range) setDrag({ source: normalizeRange(range), target: null });\n }, []);\n\n const extendFill = useCallback((row: number, col: number) => {\n const current = dragRef.current;\n if (!current) return;\n setDrag({ source: current.source, target: computeFillTarget(current.source, { row, col }) });\n }, []);\n\n return { fillTarget: drag?.target ?? null, isFilling: dragging, startFill, extendFill };\n}\n","import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { applyFormulaSuggestion, getFormulaHints } from '@pixerate/editor/spreadsheet';\n\nexport interface FormulaHintsProps {\n /** The input being edited (a cell editor or the formula bar). */\n inputRef: React.RefObject<HTMLInputElement | null>;\n /** The input's current value. */\n value: string;\n /** Called with the new value when a suggestion is accepted. */\n onAccept: (value: string) => void;\n /** Maximum number of function suggestions (default 8). */\n limit?: number;\n}\n\n/**\n * Formula autocomplete for an input: while the value starts with `=`, lists\n * functions matching the name at the caret (name, signature, description) and,\n * inside a call, shows the signature with the current argument highlighted.\n *\n * Keys are handled on the input itself, before the grid sees them: ArrowUp /\n * ArrowDown move the selection, Tab accepts it, Escape closes the list.\n * Enter is left alone so it still commits the cell.\n */\nexport const FormulaHints: React.FC<FormulaHintsProps> = ({ inputRef, value, onAccept, limit = 8 }) => {\n const [caret, setCaret] = useState<number | null>(null);\n const [focused, setFocused] = useState(false);\n const [selected, setSelected] = useState(0);\n const [dismissed, setDismissed] = useState(false);\n const [position, setPosition] = useState<{ top: number; left: number; width: number } | null>(null);\n const pendingCaret = useRef<number | null>(null);\n\n const hints = useMemo(\n () => getFormulaHints(value, caret ?? value.length, { limit }),\n [value, caret, limit],\n );\n const suggestions = dismissed ? [] : hints.suggestions;\n const selectedIndex = Math.max(0, Math.min(selected, suggestions.length - 1));\n const visible = focused && value.trimStart().startsWith('=') && (suggestions.length > 0 || !!hints.activeCall);\n\n // The key listener reads the latest state through a ref.\n const latest = useRef({ suggestions, selected: selectedIndex, value, caret, onAccept });\n latest.current = { suggestions, selected: selectedIndex, value, caret, onAccept };\n\n const accept = (index: number) => {\n const { suggestions: list, value: current, caret: at, onAccept: commit } = latest.current;\n const suggestion = list[index];\n if (!suggestion) return;\n const next = applyFormulaSuggestion(current, at ?? current.length, suggestion.name);\n pendingCaret.current = next.caret;\n commit(next.value);\n };\n\n useEffect(() => {\n const input = inputRef.current;\n if (!input) return;\n const syncCaret = () => setCaret(input.selectionStart ?? input.value.length);\n const onInput = () => {\n setDismissed(false);\n setSelected(0);\n syncCaret();\n };\n const onFocus = () => {\n setFocused(true);\n syncCaret();\n };\n const onBlur = () => setFocused(false);\n // A native listener on the input runs before React's delegated handlers,\n // so stopping propagation keeps these keys away from the grid.\n const onKeyDown = (e: KeyboardEvent) => {\n const { suggestions: list } = latest.current;\n if (list.length === 0) return;\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n e.stopPropagation();\n const step = e.key === 'ArrowDown' ? 1 : -1;\n setSelected((i) => (i + step + list.length) % list.length);\n } else if (e.key === 'Tab' && !e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n accept(latest.current.selected);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n setDismissed(true);\n }\n };\n\n input.addEventListener('input', onInput);\n input.addEventListener('keyup', syncCaret);\n input.addEventListener('click', syncCaret);\n input.addEventListener('select', syncCaret);\n input.addEventListener('focus', onFocus);\n input.addEventListener('blur', onBlur);\n input.addEventListener('keydown', onKeyDown);\n // Inputs focused on mount (autoFocus) fired `focus` before this effect ran.\n if (typeof document !== 'undefined' && document.activeElement === input) onFocus();\n return () => {\n input.removeEventListener('input', onInput);\n input.removeEventListener('keyup', syncCaret);\n input.removeEventListener('click', syncCaret);\n input.removeEventListener('select', syncCaret);\n input.removeEventListener('focus', onFocus);\n input.removeEventListener('blur', onBlur);\n input.removeEventListener('keydown', onKeyDown);\n };\n }, [inputRef]);\n\n // After accepting, put the caret inside the inserted parenthesis.\n useLayoutEffect(() => {\n const input = inputRef.current;\n const at = pendingCaret.current;\n if (!input || at === null || input.value !== value) return;\n pendingCaret.current = null;\n input.setSelectionRange(at, at);\n setCaret(at);\n setSelected(0);\n }, [value, inputRef]);\n\n useLayoutEffect(() => {\n const input = inputRef.current;\n if (!visible || !input) return;\n const rect = input.getBoundingClientRect();\n setPosition({ top: rect.bottom + 2, left: rect.left, width: rect.width });\n }, [visible, value, inputRef]);\n\n if (!visible) return null;\n\n const { activeCall } = hints;\n return (\n <div\n data-formula-hints=\"\"\n className=\"rounded-md border border-border bg-popover text-popover-foreground shadow-md text-xs font-sans overflow-hidden\"\n style={{\n position: 'fixed',\n top: position?.top ?? 0,\n left: position?.left ?? 0,\n minWidth: Math.max(260, position?.width ?? 0),\n maxWidth: 440,\n zIndex: 50,\n visibility: position ? 'visible' : 'hidden'\n }}\n onMouseDown={(e) => e.preventDefault()}\n >\n {activeCall && (\n <div data-formula-signature=\"\" className=\"px-2 py-1.5 border-b border-border bg-muted/30\">\n <div className=\"font-mono\">\n {activeCall.parts.map((part, i) => (\n <span\n key={i}\n data-active={part.active ? '' : undefined}\n className={part.active ? 'font-bold text-primary underline' : ''}\n >\n {part.text}\n </span>\n ))}\n </div>\n <div className=\"mt-0.5 text-muted-foreground\">\n {activeCall.argument ? (\n <>\n <span className=\"font-semibold\">{activeCall.argument.name}</span>: {activeCall.argument.description}\n </>\n ) : (\n activeCall.description\n )}\n </div>\n </div>\n )}\n {suggestions.length > 0 && (\n <ul role=\"listbox\" aria-label=\"Formula suggestions\" className=\"max-h-64 overflow-auto py-1 m-0 list-none p-0\">\n {suggestions.map((s, i) => (\n <li\n key={s.name}\n role=\"option\"\n aria-selected={i === selectedIndex}\n className={`cursor-pointer px-2 py-1 ${i === selectedIndex ? 'bg-primary/10' : 'hover:bg-muted/50'}`}\n onMouseEnter={() => setSelected(i)}\n onMouseDown={(e) => {\n // Keep focus in the input so the edit isn't committed by blur.\n e.preventDefault();\n accept(i);\n }}\n >\n <div className=\"font-mono font-semibold text-foreground\">{s.signature}</div>\n <div className=\"text-muted-foreground truncate\">{s.description}</div>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n","import React, { createContext, useContext, useMemo } from 'react';\nimport type {\n\tButtonSlotProps,\n\tEditorSlotsMap,\n\tNodeHeaderSlotProps,\n\tTooltipSlotProps\n} from '@pixerate/editor';\n\nconst defaultSlots: EditorSlotsMap = {\n\tButton: (props: ButtonSlotProps) => (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={`pixerate-btn ${props.className || ''}`}\n\t\t\tonClick={props.onClick}\n\t\t\tdisabled={props.disabled}\n\t\t>\n\t\t\t{props.children}\n\t\t</button>\n\t),\n\tTooltip: (props: TooltipSlotProps) => (\n\t\t<div className={`pixerate-tooltip-container ${props.className || ''}`} title={String(props.content)}>\n\t\t\t{props.children}\n\t\t</div>\n\t),\n\tNodeHeader: (props: NodeHeaderSlotProps) => (\n\t\t<div className={`pixerate-node-header flex items-center justify-between ${props.className || ''}`}>\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t{props.icon}\n\t\t\t\t<span className=\"font-semibold\">{props.title}</span>\n\t\t\t</div>\n\t\t\t{props.onClose && (\n\t\t\t\t<button type=\"button\" onClick={props.onClose} className=\"opacity-70 hover:opacity-100\">\n\t\t\t\t\t×\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t)\n};\n\nconst EditorSlotsContext = createContext<EditorSlotsMap>(defaultSlots);\n\nexport interface EditorSlotsProviderProps {\n\tslots?: Partial<EditorSlotsMap>;\n\tchildren: React.ReactNode;\n}\n\n/**\n * Context provider allowing consumers to inject custom design system components into the editor.\n */\nexport function EditorSlotsProvider({ slots, children }: EditorSlotsProviderProps) {\n\tconst mergedSlots = useMemo(() => ({ ...defaultSlots, ...slots }), [slots]);\n\n\treturn (\n\t\t<EditorSlotsContext.Provider value={mergedSlots}>\n\t\t\t{children}\n\t\t</EditorSlotsContext.Provider>\n\t);\n}\n\n/**\n * Hook to access injected design system slots.\n */\nexport function useEditorSlots(): EditorSlotsMap {\n\treturn useContext(EditorSlotsContext);\n}\n","import { useRef, useState, useEffect, useCallback, useMemo } from 'react';\nimport {\n ImageEditorController,\n type ImageEditorOptions,\n type ImageEditorState,\n type ImageEditorTool,\n type CropBox,\n type AspectRatio,\n type ImageAdjustments,\n type DepthMaskOptions,\n type Annotation,\n type CreateAnnotationPayload,\n type ExportOptions,\n type SerializedImageEditorState,\n type ImagePoint,\n} from '@pixerate/editor/image-editor';\n\nexport interface UseImageEditorReturn {\n controller: ImageEditorController;\n state: ImageEditorState;\n canUndo: boolean;\n canRedo: boolean;\n setTool: (tool: ImageEditorTool) => void;\n setCrop: (crop: CropBox | null, addToHistory?: boolean) => void;\n applyCropPreset: (ratio: AspectRatio) => void;\n resetCrop: () => void;\n rotate: (degrees: number) => void;\n setRotation: (degrees: number) => void;\n flipHorizontal: () => void;\n flipVertical: () => void;\n setAdjustments: (partial: Partial<ImageAdjustments>, commitToHistory?: boolean) => void;\n resetAdjustments: () => void;\n setDepthMask: (partial: Partial<DepthMaskOptions>) => void;\n resetDepthMask: () => void;\n addAnnotation: (annotation: CreateAnnotationPayload) => string;\n updateAnnotation: (id: string, partial: Partial<Annotation>, commitToHistory?: boolean) => void;\n removeAnnotation: (id: string) => void;\n clearAnnotations: () => void;\n selectAnnotation: (id: string | null) => void;\n undo: () => boolean;\n redo: () => boolean;\n reset: () => void;\n zoomIn: (factor?: number) => void;\n zoomOut: (factor?: number) => void;\n resetZoom: () => void;\n setZoom: (zoom: number) => void;\n setPan: (pan: ImagePoint) => void;\n setComparing: (comparing: boolean) => void;\n loadImage: (src: string | HTMLImageElement) => Promise<void>;\n toDataURL: (options?: ExportOptions) => Promise<string>;\n toBlob: (options?: ExportOptions) => Promise<Blob>;\n toJSON: () => SerializedImageEditorState;\n loadJSON: (data: SerializedImageEditorState) => void;\n renderMask: (options?: { useAnnotations?: boolean; useCrop?: boolean }) => Promise<HTMLCanvasElement>;\n toMaskDataURL: (options?: { useAnnotations?: boolean; useCrop?: boolean }) => Promise<string>;\n toSourceDataURL: (options?: Pick<ExportOptions, 'format' | 'quality'>) => Promise<string>;\n applyInpaintedImage: (newDataUrl: string) => Promise<void>;\n applyBackgroundRemovedImage: (newDataUrl: string) => Promise<void>;\n}\n\nexport function useImageEditor(options: ImageEditorOptions = {}): UseImageEditorReturn {\n const controllerRef = useRef<ImageEditorController | null>(null);\n\n if (!controllerRef.current) {\n controllerRef.current = new ImageEditorController(options);\n }\n\n const controller = controllerRef.current;\n const [state, setState] = useState<ImageEditorState>(() => controller.getState());\n const [historyTicks, setHistoryTicks] = useState(0);\n\n useEffect(() => {\n const unsub = controller.subscribe((next) => {\n setState(next);\n setHistoryTicks((t) => t + 1);\n });\n return unsub;\n }, [controller]);\n\n // The constructor loads the initial image. Reload only when the `image`\n // option itself changes, not whenever the controller's source differs from\n // it (AI edits replace the source with a data URL and must not be reverted).\n const loadedImageRef = useRef(options.image);\n useEffect(() => {\n if (options.image === loadedImageRef.current) return;\n loadedImageRef.current = options.image;\n if (options.image) {\n controller.loadImage(options.image);\n }\n }, [options.image, controller]);\n\n const setTool = useCallback((tool: ImageEditorTool) => controller.setTool(tool), [controller]);\n const setCrop = useCallback(\n (crop: CropBox | null, addToHistory = true) => controller.setCrop(crop, addToHistory),\n [controller]\n );\n const applyCropPreset = useCallback((ratio: AspectRatio) => controller.applyCropPreset(ratio), [controller]);\n const resetCrop = useCallback(() => controller.resetCrop(), [controller]);\n const rotate = useCallback((deg: number) => controller.rotate(deg), [controller]);\n const setRotation = useCallback((deg: number) => controller.setRotation(deg), [controller]);\n const flipHorizontal = useCallback(() => controller.flipHorizontal(), [controller]);\n const flipVertical = useCallback(() => controller.flipVertical(), [controller]);\n const setAdjustments = useCallback(\n (partial: Partial<ImageAdjustments>, commitToHistory = true) =>\n controller.setAdjustments(partial, commitToHistory),\n [controller]\n );\n const resetAdjustments = useCallback(() => controller.resetAdjustments(), [controller]);\n const setDepthMask = useCallback((partial: Partial<DepthMaskOptions>) => controller.setDepthMask(partial), [controller]);\n const resetDepthMask = useCallback(() => controller.resetDepthMask(), [controller]);\n const addAnnotation = useCallback((ann: CreateAnnotationPayload) => controller.addAnnotation(ann), [controller]);\n const updateAnnotation = useCallback(\n (id: string, partial: Partial<Annotation>, commitToHistory = true) =>\n controller.updateAnnotation(id, partial, commitToHistory),\n [controller]\n );\n const removeAnnotation = useCallback((id: string) => controller.removeAnnotation(id), [controller]);\n const clearAnnotations = useCallback(() => controller.clearAnnotations(), [controller]);\n const selectAnnotation = useCallback((id: string | null) => controller.selectAnnotation(id), [controller]);\n const undo = useCallback(() => controller.undo(), [controller]);\n const redo = useCallback(() => controller.redo(), [controller]);\n const reset = useCallback(() => controller.reset(), [controller]);\n const zoomIn = useCallback((factor?: number) => controller.zoomIn(factor), [controller]);\n const zoomOut = useCallback((factor?: number) => controller.zoomOut(factor), [controller]);\n const resetZoom = useCallback(() => controller.resetZoom(), [controller]);\n const setZoom = useCallback((zoom: number) => controller.setZoom(zoom), [controller]);\n const setPan = useCallback((pan: ImagePoint) => controller.setPan(pan), [controller]);\n const setComparing = useCallback((comp: boolean) => controller.setComparing(comp), [controller]);\n const loadImage = useCallback((src: string | HTMLImageElement) => controller.loadImage(src), [controller]);\n const toDataURL = useCallback((opts?: ExportOptions) => controller.toDataURL(opts), [controller]);\n const toBlob = useCallback((opts?: ExportOptions) => controller.toBlob(opts), [controller]);\n const toJSON = useCallback(() => controller.toJSON(), [controller]);\n const loadJSON = useCallback((data: SerializedImageEditorState) => controller.loadJSON(data), [controller]);\n const renderMask = useCallback(\n (opts?: { useAnnotations?: boolean; useCrop?: boolean }) => controller.renderMask(opts),\n [controller]\n );\n const toMaskDataURL = useCallback(\n (opts?: { useAnnotations?: boolean; useCrop?: boolean }) => controller.toMaskDataURL(opts),\n [controller]\n );\n const toSourceDataURL = useCallback(\n (opts?: Pick<ExportOptions, 'format' | 'quality'>) => controller.toSourceDataURL(opts),\n [controller]\n );\n const applyInpaintedImage = useCallback(\n (newDataUrl: string) => controller.applyInpaintedImage(newDataUrl),\n [controller]\n );\n const applyBackgroundRemovedImage = useCallback(\n (newDataUrl: string) => controller.applyBackgroundRemovedImage(newDataUrl),\n [controller]\n );\n\n return useMemo(\n () => ({\n controller,\n state,\n canUndo: controller.canUndo,\n canRedo: controller.canRedo,\n setTool,\n setCrop,\n applyCropPreset,\n resetCrop,\n rotate,\n setRotation,\n flipHorizontal,\n flipVertical,\n setAdjustments,\n resetAdjustments,\n setDepthMask,\n resetDepthMask,\n addAnnotation,\n updateAnnotation,\n removeAnnotation,\n clearAnnotations,\n selectAnnotation,\n undo,\n redo,\n reset,\n zoomIn,\n zoomOut,\n resetZoom,\n setZoom,\n setPan,\n setComparing,\n loadImage,\n toDataURL,\n toBlob,\n toJSON,\n loadJSON,\n renderMask,\n toMaskDataURL,\n toSourceDataURL,\n applyInpaintedImage,\n applyBackgroundRemovedImage,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [controller, state, historyTicks]\n );\n}\n","import React, { useRef, useEffect, useState, useCallback } from 'react';\nimport type {\n Annotation,\n CropBox,\n CropHandle,\n ExportOptions,\n ImageEditorTool,\n ImagePoint,\n InpaintHook,\n RemoveBackgroundHook,\n ImageEditorAIHooks,\n} from '@pixerate/editor/image-editor';\nimport {\n canvasToImagePoint,\n hitTestCrop,\n getCropCursor,\n calculateCropDrag,\n hitTestAnnotation,\n} from '@pixerate/editor/image-editor';\nimport { useImageEditor, type UseImageEditorReturn } from './useImageEditor';\n\nexport interface ImageEditorProps {\n editor?: UseImageEditorReturn;\n src?: string;\n className?: string;\n style?: React.CSSProperties;\n onSave?: (dataUrl: string) => void;\n exportOptions?: ExportOptions;\n onInpaint?: InpaintHook;\n onRemoveBackground?: RemoveBackgroundHook;\n aiHooks?: ImageEditorAIHooks;\n}\n\ntype TabType = 'crop' | 'adjust' | 'annotate' | 'depth' | 'ai';\n\nexport const ImageEditor: React.FC<ImageEditorProps> = ({\n editor: externalEditor,\n src,\n className = '',\n style,\n onSave,\n exportOptions,\n onInpaint,\n onRemoveBackground,\n aiHooks,\n}) => {\n const internalEditor = useImageEditor({ image: src });\n const editor = externalEditor || internalEditor;\n const { state, controller } = editor;\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const [activeTab, setActiveTab] = useState<TabType>('crop');\n const [activeCropRatio, setActiveCropRatio] = useState<number | null>(null);\n\n // AI Tools state\n const [inpaintPrompt, setInpaintPrompt] = useState('');\n const [inpaintMaskMode, setInpaintMaskMode] = useState<'annotations' | 'crop'>('annotations');\n const [isRemovingBg, setIsRemovingBg] = useState(false);\n const [isInpainting, setIsInpainting] = useState(false);\n const [aiError, setAiError] = useState<string | null>(null);\n const [aiSuccess, setAiSuccess] = useState<string | null>(null);\n\n const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;\n const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;\n\n const handleRemoveBackground = async () => {\n if (!effectiveOnRemoveBg) {\n setAiError('No background removal hook is configured.');\n return;\n }\n setAiError(null);\n setAiSuccess(null);\n setIsRemovingBg(true);\n try {\n // AI hooks work on the untransformed source image (natural pixels); crop, rotation,\n // adjustments and annotations stay non-destructive and are re-applied on top.\n const imageDataUrl = await editor.toSourceDataURL();\n const result = await effectiveOnRemoveBg({ imageDataUrl });\n if (typeof result === 'string') {\n await editor.applyBackgroundRemovedImage(result);\n setAiSuccess('Background removed successfully!');\n } else {\n setAiSuccess('Background removal complete.');\n }\n } catch (err: any) {\n setAiError(err?.message || 'Failed to remove background.');\n } finally {\n setIsRemovingBg(false);\n }\n };\n\n const handleInpaint = async () => {\n if (!effectiveOnInpaint) {\n setAiError('No inpainting hook is configured.');\n return;\n }\n if (!inpaintPrompt.trim()) {\n setAiError('Please enter an inpainting prompt.');\n return;\n }\n setAiError(null);\n setAiSuccess(null);\n setIsInpainting(true);\n try {\n // Source image and mask share natural image space so they line up exactly.\n const imageDataUrl = await editor.toSourceDataURL();\n const maskDataUrl = await editor.toMaskDataURL({\n useAnnotations: inpaintMaskMode === 'annotations',\n useCrop: inpaintMaskMode === 'crop',\n });\n const result = await effectiveOnInpaint({\n prompt: inpaintPrompt.trim(),\n imageDataUrl,\n maskDataUrl,\n cropBox: inpaintMaskMode === 'crop' ? editor.state.crop : null,\n });\n if (typeof result === 'string') {\n await editor.applyInpaintedImage(result);\n setAiSuccess('Inpainting applied successfully!');\n } else {\n setAiSuccess('Inpainting complete.');\n }\n } catch (err: any) {\n setAiError(err?.message || 'Failed to apply inpainting.');\n } finally {\n setIsInpainting(false);\n }\n };\n\n // Annotation drafting state\n const [activeColor, setActiveColor] = useState('#ef4444');\n const [strokeWidth, setStrokeWidth] = useState(3);\n const [fontSize, setFontSize] = useState(24);\n const [textInput, setTextInput] = useState('');\n\n // Live draft and drag references\n const draftAnnotationRef = useRef<Annotation | null>(null);\n const draftCropRef = useRef<CropBox | null>(null);\n const cropDragInfoRef = useRef<{\n handle: CropHandle | 'new';\n startCanvasPt: ImagePoint;\n startImgPt: ImagePoint;\n startCrop: CropBox;\n } | null>(null);\n const annotationDragInfoRef = useRef<{\n annId: string;\n startImgPt: ImagePoint;\n initialAnn: Annotation;\n } | null>(null);\n const isDrawingRef = useRef(false);\n const currentPathRef = useRef<ImagePoint[]>([]);\n const dragStartPointRef = useRef<ImagePoint | null>(null);\n\n // Canvas viewport sizing and re-render\n const renderCanvas = useCallback(\n async (draftAnnotation?: Annotation | null, draftCrop?: CropBox | null) => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const vpWidth = container.clientWidth || 800;\n const vpHeight = container.clientHeight || 500;\n\n await controller.render(canvas, {\n viewportWidth: vpWidth,\n viewportHeight: vpHeight,\n showCropOverlay: activeTab === 'crop',\n showSelectionOverlay: true,\n interactive: true,\n draftAnnotation: draftAnnotation !== undefined ? draftAnnotation : draftAnnotationRef.current,\n draftCrop: draftCrop !== undefined ? draftCrop : draftCropRef.current,\n });\n },\n [controller, activeTab]\n );\n\n useEffect(() => {\n const raf =\n typeof requestAnimationFrame !== 'undefined'\n ? requestAnimationFrame\n : (cb: () => void) => setTimeout(cb, 0) as unknown as number;\n const caf =\n typeof cancelAnimationFrame !== 'undefined'\n ? cancelAnimationFrame\n : (id: number) => clearTimeout(id);\n\n const animId = raf(() => {\n renderCanvas();\n });\n return () => caf(animId);\n }, [renderCanvas, state]);\n\n // Synchronize initial tool with activeTab\n useEffect(() => {\n if (activeTab === 'crop' && editor.state.activeTool !== 'crop') {\n editor.setTool('crop');\n }\n }, [activeTab, editor]);\n\n // Container resize observer to safely adapt viewport without feedback loops\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(() => {\n renderCanvas();\n });\n observer.observe(container);\n return () => observer.disconnect();\n } else {\n const handleResize = () => renderCanvas();\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }\n }, [renderCanvas]);\n\n // Convert mouse event coordinates to internal canvas pixel space\n const getCanvasEventPoint = (e: React.MouseEvent<HTMLCanvasElement>): ImagePoint => {\n const canvas = canvasRef.current;\n if (!canvas) return { x: 0, y: 0 };\n const rect = canvas.getBoundingClientRect();\n const scaleX = rect.width > 0 ? canvas.width / rect.width : 1;\n const scaleY = rect.height > 0 ? canvas.height / rect.height : 1;\n return {\n x: (e.clientX - rect.left) * scaleX,\n y: (e.clientY - rect.top) * scaleY,\n };\n };\n\n // Pointer event handlers for drawing and annotations\n const handleMouseDown = (e: React.MouseEvent<HTMLCanvasElement>) => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const canvasPt = getCanvasEventPoint(e);\n\n if (activeTab === 'crop') {\n const activeCrop = draftCropRef.current || state.crop || {\n x: 0,\n y: 0,\n width: state.imageDimensions.width,\n height: state.imageDimensions.height,\n };\n const handle = hitTestCrop(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);\n const startImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, true);\n\n if (handle) {\n cropDragInfoRef.current = {\n handle,\n startCanvasPt: canvasPt,\n startImgPt,\n startCrop: activeCrop,\n };\n } else {\n // Clicked outside crop box: start new crop selection\n cropDragInfoRef.current = {\n handle: 'new',\n startCanvasPt: canvasPt,\n startImgPt,\n startCrop: { x: startImgPt.x, y: startImgPt.y, width: 0, height: 0 },\n };\n }\n return;\n }\n\n if (activeTab === 'annotate') {\n const imgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n dragStartPointRef.current = imgPt;\n\n if (state.activeTool === 'select') {\n for (let i = state.annotations.length - 1; i >= 0; i--) {\n const ann = state.annotations[i];\n if (hitTestAnnotation(imgPt, ann)) {\n editor.selectAnnotation(ann.id);\n annotationDragInfoRef.current = {\n annId: ann.id,\n startImgPt: imgPt,\n initialAnn: { ...ann },\n };\n return;\n }\n }\n editor.selectAnnotation(null);\n return;\n }\n\n if (state.activeTool === 'pen') {\n isDrawingRef.current = true;\n currentPathRef.current = [imgPt];\n const draft: Annotation = {\n id: 'draft',\n type: 'pen',\n x: 0,\n y: 0,\n points: [imgPt],\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n }\n }\n };\n\n const handleMouseMove = (e: React.MouseEvent<HTMLCanvasElement>) => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const canvasPt = getCanvasEventPoint(e);\n\n if (activeTab === 'crop') {\n const drag = cropDragInfoRef.current;\n if (drag) {\n const currentImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, true);\n let newCrop: CropBox;\n\n if (drag.handle === 'new') {\n const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));\n const minY = Math.max(0, Math.min(drag.startImgPt.y, currentImgPt.y));\n const maxX = Math.min(state.imageDimensions.width, Math.max(drag.startImgPt.x, currentImgPt.x));\n const maxY = Math.min(state.imageDimensions.height, Math.max(drag.startImgPt.y, currentImgPt.y));\n newCrop = {\n x: Math.round(minX),\n y: Math.round(minY),\n width: Math.round(Math.max(20, maxX - minX)),\n height: Math.round(Math.max(20, maxY - minY)),\n };\n } else {\n newCrop = calculateCropDrag(\n drag.startCrop,\n drag.handle,\n drag.startImgPt,\n currentImgPt,\n state.imageDimensions.width,\n state.imageDimensions.height,\n activeCropRatio,\n state.transform\n );\n }\n\n draftCropRef.current = newCrop;\n renderCanvas(null, newCrop);\n } else {\n const activeCrop = draftCropRef.current || state.crop || {\n x: 0,\n y: 0,\n width: state.imageDimensions.width,\n height: state.imageDimensions.height,\n };\n const handle = hitTestCrop(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);\n canvas.style.cursor = getCropCursor(handle, state.transform);\n }\n return;\n }\n\n if (activeTab === 'annotate') {\n // If moving selected annotation\n if (annotationDragInfoRef.current) {\n const drag = annotationDragInfoRef.current;\n const currentImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n const dx = currentImgPt.x - drag.startImgPt.x;\n const dy = currentImgPt.y - drag.startImgPt.y;\n editor.updateAnnotation(drag.annId, {\n x: Math.round(drag.initialAnn.x + dx),\n y: Math.round(drag.initialAnn.y + dy),\n });\n return;\n }\n\n const startPt = dragStartPointRef.current;\n if (!startPt) {\n // Update cursor for hover on select tool\n if (state.activeTool === 'select') {\n const imgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n let hovered = false;\n for (let i = state.annotations.length - 1; i >= 0; i--) {\n if (hitTestAnnotation(imgPt, state.annotations[i])) {\n hovered = true;\n break;\n }\n }\n canvas.style.cursor = hovered ? 'move' : 'default';\n } else {\n canvas.style.cursor = 'crosshair';\n }\n return;\n }\n\n const currentImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n\n if (state.activeTool === 'pen' && isDrawingRef.current) {\n currentPathRef.current.push(currentImgPt);\n const draft: Annotation = {\n id: 'draft',\n type: 'pen',\n x: 0,\n y: 0,\n points: [...currentPathRef.current],\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n } else if (state.activeTool === 'rect') {\n const w = currentImgPt.x - startPt.x;\n const h = currentImgPt.y - startPt.y;\n const draft: Annotation = {\n id: 'draft',\n type: 'rect',\n x: Math.min(startPt.x, currentImgPt.x),\n y: Math.min(startPt.y, currentImgPt.y),\n width: Math.abs(w),\n height: Math.abs(h),\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n } else if (state.activeTool === 'circle') {\n const rx = Math.abs(currentImgPt.x - startPt.x) / 2;\n const ry = Math.abs(currentImgPt.y - startPt.y) / 2;\n const draft: Annotation = {\n id: 'draft',\n type: 'circle',\n x: Math.min(startPt.x, currentImgPt.x) + rx,\n y: Math.min(startPt.y, currentImgPt.y) + ry,\n radiusX: rx,\n radiusY: ry,\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n } else if (state.activeTool === 'arrow') {\n const draft: Annotation = {\n id: 'draft',\n type: 'arrow',\n x: startPt.x,\n y: startPt.y,\n endX: currentImgPt.x,\n endY: currentImgPt.y,\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n } else if (state.activeTool === 'line') {\n const draft: Annotation = {\n id: 'draft',\n type: 'line',\n x: startPt.x,\n y: startPt.y,\n endX: currentImgPt.x,\n endY: currentImgPt.y,\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n }\n }\n };\n\n const handleMouseUp = (e: React.MouseEvent<HTMLCanvasElement>) => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const canvasPt = getCanvasEventPoint(e);\n\n if (activeTab === 'crop') {\n if (cropDragInfoRef.current) {\n if (\n draftCropRef.current &&\n draftCropRef.current.width >= 20 &&\n draftCropRef.current.height >= 20\n ) {\n editor.setCrop(draftCropRef.current, true);\n }\n cropDragInfoRef.current = null;\n draftCropRef.current = null;\n renderCanvas();\n }\n return;\n }\n\n if (activeTab === 'annotate') {\n if (annotationDragInfoRef.current) {\n annotationDragInfoRef.current = null;\n return;\n }\n\n const startPt = dragStartPointRef.current;\n if (startPt) {\n const currentImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n\n if (state.activeTool === 'pen' && isDrawingRef.current) {\n if (currentPathRef.current.length > 1) {\n editor.addAnnotation({\n type: 'pen',\n x: 0,\n y: 0,\n points: [...currentPathRef.current],\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n isDrawingRef.current = false;\n currentPathRef.current = [];\n } else if (state.activeTool === 'rect') {\n const w = Math.abs(currentImgPt.x - startPt.x);\n const h = Math.abs(currentImgPt.y - startPt.y);\n if (w > 4 && h > 4) {\n editor.addAnnotation({\n type: 'rect',\n x: Math.min(startPt.x, currentImgPt.x),\n y: Math.min(startPt.y, currentImgPt.y),\n width: w,\n height: h,\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n } else if (state.activeTool === 'circle') {\n const rx = Math.abs(currentImgPt.x - startPt.x) / 2;\n const ry = Math.abs(currentImgPt.y - startPt.y) / 2;\n if (rx > 4 && ry > 4) {\n editor.addAnnotation({\n type: 'circle',\n x: Math.min(startPt.x, currentImgPt.x) + rx,\n y: Math.min(startPt.y, currentImgPt.y) + ry,\n radiusX: rx,\n radiusY: ry,\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n } else if (state.activeTool === 'arrow') {\n if (Math.hypot(currentImgPt.x - startPt.x, currentImgPt.y - startPt.y) > 4) {\n editor.addAnnotation({\n type: 'arrow',\n x: startPt.x,\n y: startPt.y,\n endX: currentImgPt.x,\n endY: currentImgPt.y,\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n } else if (state.activeTool === 'line') {\n if (Math.hypot(currentImgPt.x - startPt.x, currentImgPt.y - startPt.y) > 4) {\n editor.addAnnotation({\n type: 'line',\n x: startPt.x,\n y: startPt.y,\n endX: currentImgPt.x,\n endY: currentImgPt.y,\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n }\n\n draftAnnotationRef.current = null;\n dragStartPointRef.current = null;\n renderCanvas();\n }\n }\n };\n\n const handleAddText = () => {\n if (!textInput.trim()) return;\n editor.addAnnotation({\n type: 'text',\n x: 50,\n y: 50,\n text: textInput.trim(),\n fontSize,\n color: activeColor,\n });\n setTextInput('');\n };\n\n const handleExport = async () => {\n const dataUrl = await editor.toDataURL(exportOptions);\n if (onSave) {\n onSave(dataUrl);\n } else {\n // Default download trigger\n const link = document.createElement('a');\n link.download = `edited-image-${Date.now()}.png`;\n link.href = dataUrl;\n link.click();\n }\n };\n\n return (\n <div\n className={`flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`}\n style={style}\n >\n {/* Top Action Header */}\n <div className=\"flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3\">\n {/* Navigation Tabs */}\n <div className=\"flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs\">\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('crop');\n editor.setTool('crop');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors ${\n activeTab === 'crop' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n Transform & Crop\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('adjust');\n editor.setTool('select');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors ${\n activeTab === 'adjust' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n Adjustments\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('annotate');\n editor.setTool('pen');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors ${\n activeTab === 'annotate' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n Annotations\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('depth');\n editor.setTool('select');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors ${\n activeTab === 'depth' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n Depth Mask\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('ai');\n editor.setTool('select');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors flex items-center gap-1.5 ${\n activeTab === 'ai' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83\" />\n </svg>\n AI Tools\n </button>\n </div>\n\n {/* Global Action Tools (Undo/Redo, Zoom, Compare, Save) */}\n <div className=\"flex items-center gap-2 text-xs\">\n <button\n type=\"button\"\n disabled={!editor.canUndo}\n onClick={() => editor.undo()}\n className=\"p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-slate-800\"\n title=\"Undo\"\n >\n ↩\n </button>\n <button\n type=\"button\"\n disabled={!editor.canRedo}\n onClick={() => editor.redo()}\n className=\"p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-slate-800\"\n title=\"Redo\"\n >\n ↪\n </button>\n <button\n type=\"button\"\n onClick={() => editor.reset()}\n className=\"px-2 py-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-400 hover:text-slate-200 hover:bg-slate-800\"\n >\n Reset\n </button>\n\n <div className=\"h-4 w-px bg-slate-800 mx-1\" />\n\n {/* Zoom */}\n <button\n type=\"button\"\n onClick={() => editor.zoomOut()}\n className=\"p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 hover:bg-slate-800\"\n title=\"Zoom Out\"\n >\n -\n </button>\n <span className=\"font-mono text-slate-400 w-10 text-center\">{Math.round(state.zoom * 100)}%</span>\n <button\n type=\"button\"\n onClick={() => editor.zoomIn()}\n className=\"p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 hover:bg-slate-800\"\n title=\"Zoom In\"\n >\n +\n </button>\n\n <div className=\"h-4 w-px bg-slate-800 mx-1\" />\n\n {/* Live Compare */}\n <button\n type=\"button\"\n onMouseDown={() => editor.setComparing(true)}\n onMouseUp={() => editor.setComparing(false)}\n onMouseLeave={() => editor.setComparing(false)}\n className=\"px-2.5 py-1.5 rounded-lg border border-slate-800 bg-slate-900 text-amber-400 hover:bg-slate-800 select-none active:bg-amber-950/40\"\n >\n Hold Compare\n </button>\n\n {/* Save / Export */}\n <button\n type=\"button\"\n onClick={handleExport}\n className=\"px-4 py-1.5 rounded-lg bg-emerald-600 hover:bg-emerald-500 text-white font-medium shadow-md shadow-emerald-900/30 transition-colors\"\n >\n Export Image\n </button>\n </div>\n </div>\n\n {/* Main Viewport + Sidebar Layout */}\n <div className=\"flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]\">\n {/* Canvas Area */}\n <div\n ref={containerRef}\n className=\"relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none\"\n >\n <canvas\n ref={canvasRef}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n className=\"absolute inset-0 w-full h-full block\"\n />\n </div>\n\n {/* Tab Controls Sidebar */}\n <div className=\"w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]\">\n {/* TAB 1: CROP & TRANSFORM */}\n {activeTab === 'crop' && (\n <div className=\"flex flex-col gap-4 text-xs\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Aspect Ratio Presets\n </span>\n <div className=\"grid grid-cols-3 gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(null);\n editor.applyCropPreset(null);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === null && state.crop\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n Freeform\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(1);\n editor.applyCropPreset(1);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === 1\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n 1:1 Square\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(4 / 3);\n editor.applyCropPreset(4 / 3);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === 4 / 3\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n 4:3 Standard\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(16 / 9);\n editor.applyCropPreset(16 / 9);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === 16 / 9\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n 16:9 Wide\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(3 / 2);\n editor.applyCropPreset(3 / 2);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === 3 / 2\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n 3:2 Photo\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(null);\n editor.resetCrop();\n }}\n className=\"px-2.5 py-2 rounded-lg bg-rose-950/40 hover:bg-rose-900/60 text-rose-300 border border-rose-800/40 font-medium\"\n >\n Clear Crop\n </button>\n </div>\n\n <div className=\"h-px bg-slate-800 my-1\" />\n\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Orientation & Flips\n </span>\n <div className=\"grid grid-cols-2 gap-2\">\n <button\n type=\"button\"\n onClick={() => editor.rotate(-90)}\n className=\"px-3 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 border border-slate-700\"\n >\n Rotate -90°\n </button>\n <button\n type=\"button\"\n onClick={() => editor.rotate(90)}\n className=\"px-3 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 border border-slate-700\"\n >\n Rotate +90°\n </button>\n <button\n type=\"button\"\n onClick={() => editor.flipHorizontal()}\n className={`px-3 py-2 rounded-lg border transition-colors ${\n state.transform.flipH\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-200 hover:bg-slate-700'\n }`}\n >\n Flip Horizontal\n </button>\n <button\n type=\"button\"\n onClick={() => editor.flipVertical()}\n className={`px-3 py-2 rounded-lg border transition-colors ${\n state.transform.flipV\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-200 hover:bg-slate-700'\n }`}\n >\n Flip Vertical\n </button>\n </div>\n </div>\n )}\n\n {/* TAB 2: ADJUSTMENTS */}\n {activeTab === 'adjust' && (\n <div className=\"flex flex-col gap-3 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Color Adjustments\n </span>\n <button\n type=\"button\"\n onClick={() => editor.resetAdjustments()}\n className=\"text-[10px] text-rose-400 hover:underline\"\n >\n Reset Sliders\n </button>\n </div>\n\n {/* Brightness */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Brightness</span>\n <span className=\"font-mono\">{state.adjustments.brightness}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.brightness}\n onChange={(e) => editor.setAdjustments({ brightness: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Contrast */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Contrast</span>\n <span className=\"font-mono\">{state.adjustments.contrast}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.contrast}\n onChange={(e) => editor.setAdjustments({ contrast: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Saturation */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Saturation</span>\n <span className=\"font-mono\">{state.adjustments.saturation}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.saturation}\n onChange={(e) => editor.setAdjustments({ saturation: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Exposure */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Exposure</span>\n <span className=\"font-mono\">{state.adjustments.exposure}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.exposure}\n onChange={(e) => editor.setAdjustments({ exposure: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Temperature / Warmth */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Warmth / Temperature</span>\n <span className=\"font-mono\">{state.adjustments.temperature}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.temperature}\n onChange={(e) => editor.setAdjustments({ temperature: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Blur */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Blur</span>\n <span className=\"font-mono\">{state.adjustments.blur}px</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"30\"\n value={state.adjustments.blur}\n onChange={(e) => editor.setAdjustments({ blur: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Opacity */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Opacity</span>\n <span className=\"font-mono\">{Math.round(state.adjustments.opacity * 100)}%</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n value={state.adjustments.opacity}\n onChange={(e) => editor.setAdjustments({ opacity: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n </div>\n )}\n\n {/* TAB 3: ANNOTATIONS */}\n {activeTab === 'annotate' && (\n <div className=\"flex flex-col gap-3 text-xs\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Draw & Annotate\n </span>\n\n {/* Tool Picker */}\n <div className=\"grid grid-cols-3 gap-1.5\">\n {(['pen', 'rect', 'circle', 'arrow', 'line'] as ImageEditorTool[]).map((t) => (\n <button\n key={t}\n type=\"button\"\n onClick={() => editor.setTool(t)}\n className={`py-1.5 px-2 rounded-lg font-medium capitalize border transition-colors ${\n state.activeTool === t\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-300 hover:bg-slate-700'\n }`}\n >\n {t}\n </button>\n ))}\n </div>\n\n {/* Color & Size */}\n <div className=\"flex items-center gap-2 mt-2\">\n <label className=\"text-slate-400\">Color:</label>\n <input\n type=\"color\"\n value={activeColor}\n onChange={(e) => setActiveColor(e.target.value)}\n className=\"w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent\"\n />\n <div className=\"flex-1 ml-2\">\n <div className=\"flex justify-between text-slate-400 mb-0.5\">\n <span>Width:</span>\n <span className=\"font-mono\">{strokeWidth}px</span>\n </div>\n <input\n type=\"range\"\n min=\"1\"\n max=\"20\"\n value={strokeWidth}\n onChange={(e) => setStrokeWidth(Number(e.target.value))}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n </div>\n\n <div className=\"h-px bg-slate-800 my-1\" />\n\n {/* Text Tool */}\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">Add Text</span>\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n placeholder=\"Type watermark or label...\"\n value={textInput}\n onChange={(e) => setTextInput(e.target.value)}\n onKeyDown={(e) => e.key === 'Enter' && handleAddText()}\n className=\"flex-1 bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1.5 text-xs text-slate-100 placeholder-slate-500 focus:outline-none focus:border-indigo-500\"\n />\n <button\n type=\"button\"\n onClick={handleAddText}\n className=\"px-3 py-1.5 rounded-lg bg-indigo-600 hover:bg-indigo-500 text-white font-medium shadow\"\n >\n Add\n </button>\n </div>\n <div className=\"flex items-center justify-between text-slate-400\">\n <span>Font Size:</span>\n <span className=\"font-mono\">{fontSize}px</span>\n </div>\n <input\n type=\"range\"\n min=\"12\"\n max=\"72\"\n value={fontSize}\n onChange={(e) => setFontSize(Number(e.target.value))}\n className=\"w-full accent-indigo-500\"\n />\n\n {/* Layers & Selected Annotation */}\n <div className=\"h-px bg-slate-800 my-1\" />\n <div className=\"flex items-center justify-between\">\n <span className=\"text-slate-400\">Layers ({state.annotations.length})</span>\n {state.selectedAnnotationId && (\n <button\n type=\"button\"\n onClick={() => editor.removeAnnotation(state.selectedAnnotationId!)}\n className=\"text-rose-400 hover:underline text-[11px]\"\n >\n Delete Selected\n </button>\n )}\n {state.annotations.length > 0 && (\n <button\n type=\"button\"\n onClick={() => editor.clearAnnotations()}\n className=\"text-slate-400 hover:text-slate-200 text-[11px]\"\n >\n Clear All\n </button>\n )}\n </div>\n </div>\n )}\n\n {/* TAB 4: GLEAMFORGE DEPTH MASKING */}\n {activeTab === 'depth' && (\n <div className=\"flex flex-col gap-3 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Depth Masking\n </span>\n <button\n type=\"button\"\n onClick={() => editor.resetDepthMask()}\n className=\"text-[10px] text-rose-400 hover:underline\"\n >\n Reset Mask\n </button>\n </div>\n\n <label className=\"flex items-center gap-2 cursor-pointer text-slate-300\">\n <input\n type=\"checkbox\"\n checked={state.depthMask.enabled}\n onChange={(e) => editor.setDepthMask({ enabled: e.target.checked })}\n className=\"rounded accent-indigo-500\"\n />\n <span>Enable Depth / Alpha Mask</span>\n </label>\n\n {state.depthMask.enabled && (\n <>\n <div>\n <label className=\"text-slate-400 block mb-1\">Mask Image URL:</label>\n <input\n type=\"text\"\n placeholder=\"https://.../depthmap.png\"\n value={state.depthMask.maskSource || ''}\n onChange={(e) => editor.setDepthMask({ maskSource: e.target.value || null })}\n className=\"w-full bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1.5 text-xs text-slate-100 placeholder-slate-500\"\n />\n </div>\n\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={() => editor.setDepthMask({ mode: 'threshold' })}\n className={`flex-1 py-1.5 rounded-lg border text-xs font-medium ${\n state.depthMask.mode === 'threshold'\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-300'\n }`}\n >\n Threshold Mode\n </button>\n <button\n type=\"button\"\n onClick={() => editor.setDepthMask({ mode: 'brightness' })}\n className={`flex-1 py-1.5 rounded-lg border text-xs font-medium ${\n state.depthMask.mode === 'brightness'\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-300'\n }`}\n >\n Brightness Mode\n </button>\n </div>\n\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Depth Start (Lower):</span>\n <span className=\"font-mono\">{state.depthMask.depthRange[0]}</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"255\"\n value={state.depthMask.depthRange[0]}\n onChange={(e) =>\n editor.setDepthMask({\n depthRange: [Number(e.target.value), state.depthMask.depthRange[1]],\n })\n }\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Depth Stop (Upper):</span>\n <span className=\"font-mono\">{state.depthMask.depthRange[1]}</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"255\"\n value={state.depthMask.depthRange[1]}\n onChange={(e) =>\n editor.setDepthMask({\n depthRange: [state.depthMask.depthRange[0], Number(e.target.value)],\n })\n }\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Softness:</span>\n <span className=\"font-mono\">{state.depthMask.softness}</span>\n </div>\n <input\n type=\"range\"\n min=\"1\"\n max=\"50\"\n value={state.depthMask.softness}\n onChange={(e) => editor.setDepthMask({ softness: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n <label className=\"flex items-center gap-2 cursor-pointer text-slate-300 mt-1\">\n <input\n type=\"checkbox\"\n checked={state.depthMask.invert}\n onChange={(e) => editor.setDepthMask({ invert: e.target.checked })}\n className=\"rounded accent-indigo-500\"\n />\n <span>Invert Mask</span>\n </label>\n </>\n )}\n </div>\n )}\n\n {/* TAB 5: AI TOOLS / INPAINTING & BACKGROUND REMOVAL */}\n {activeTab === 'ai' && (\n <div className=\"flex flex-col gap-4 text-xs\">\n {/* Background Removal Section */}\n <div className=\"p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5\">\n <svg className=\"w-3.5 h-3.5 text-indigo-400\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z\" />\n </svg>\n Background Removal\n </span>\n {isRemovingBg && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse\">\n Removing...\n </span>\n )}\n </div>\n\n <p className=\"text-slate-400 text-[11px] leading-relaxed\">\n Isolate foreground subject with AI alpha transparency segmentation.\n </p>\n\n <button\n type=\"button\"\n onClick={handleRemoveBackground}\n disabled={isRemovingBg || isInpainting}\n className=\"mt-1 px-3 py-2 rounded-lg bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2\"\n >\n {isRemovingBg ? (\n <>\n <div className=\"w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin\" />\n Removing Background...\n </>\n ) : (\n <>\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83\" />\n </svg>\n Remove Background\n </>\n )}\n </button>\n </div>\n\n {/* AI Inpainting / Generative Fill Section */}\n <div className=\"p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5\">\n <svg className=\"w-3.5 h-3.5 text-purple-400\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z\" />\n <path d=\"m14 7 3 3\" />\n </svg>\n Generative Inpainting\n </span>\n {isInpainting && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse\">\n Inpainting...\n </span>\n )}\n </div>\n\n <p className=\"text-slate-400 text-[11px] leading-relaxed\">\n Replace, modify, or fill selected regions using prompt-guided generative inpainting.\n </p>\n\n <div className=\"flex flex-col gap-1\">\n <label htmlFor=\"ai-inpaint-prompt-react\" className=\"text-slate-300 text-[11px] font-medium\">Prompt</label>\n <textarea\n id=\"ai-inpaint-prompt-react\"\n value={inpaintPrompt}\n onChange={(e) => setInpaintPrompt(e.target.value)}\n placeholder=\"e.g. replace sunglasses with steampunk goggles, remove person in background...\"\n rows={3}\n className=\"w-full bg-slate-900 border border-slate-700 rounded-lg p-2 text-xs text-slate-100 placeholder-slate-500 focus:outline-none focus:border-indigo-500 resize-none\"\n />\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-slate-300 text-[11px] font-medium\">Target Mask Region</span>\n <div className=\"grid grid-cols-2 gap-1.5\">\n <button\n type=\"button\"\n onClick={() => setInpaintMaskMode('annotations')}\n className={`px-2 py-1.5 rounded border text-[11px] font-medium text-left transition-colors ${\n inpaintMaskMode === 'annotations'\n ? 'bg-purple-600/30 border-purple-500 text-purple-200'\n : 'bg-slate-900 border-slate-700 text-slate-400 hover:text-slate-200'\n }`}\n >\n Drawn Shapes ({state.annotations.length})\n </button>\n <button\n type=\"button\"\n onClick={() => setInpaintMaskMode('crop')}\n className={`px-2 py-1.5 rounded border text-[11px] font-medium text-left transition-colors ${\n inpaintMaskMode === 'crop'\n ? 'bg-purple-600/30 border-purple-500 text-purple-200'\n : 'bg-slate-900 border-slate-700 text-slate-400 hover:text-slate-200'\n }`}\n >\n Crop Box ({state.crop ? 'Selected' : 'Full'})\n </button>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={handleInpaint}\n disabled={isInpainting || isRemovingBg || !inpaintPrompt.trim()}\n className=\"mt-1 px-3 py-2 rounded-lg bg-purple-600 hover:bg-purple-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2\"\n >\n {isInpainting ? (\n <>\n <div className=\"w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin\" />\n Generating Inpaint...\n </>\n ) : (\n <>\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83\" />\n </svg>\n Apply Inpainting\n </>\n )}\n </button>\n </div>\n\n {aiError && (\n <div className=\"p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]\">\n {aiError}\n </div>\n )}\n\n {aiSuccess && (\n <div className=\"p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]\">\n {aiSuccess}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n};\n","import { useCallback, useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n getCommentStore,\n getTrackChangesStore,\n type CommentStore,\n type CommentStoreSnapshot,\n type TrackChangesSnapshot,\n type TrackedChange,\n} from \"@pixerate/editor\";\n\nconst EMPTY_COMMENTS: CommentStoreSnapshot = Object.freeze({\n threads: [],\n activeThreadId: null,\n}) as CommentStoreSnapshot;\n\nconst EMPTY_TRACK_CHANGES: TrackChangesSnapshot = Object.freeze({\n enabled: false,\n author: { id: \"anonymous\", name: \"Anonymous\" },\n changes: [],\n currentChangeId: null,\n}) as TrackChangesSnapshot;\n\nconst noopUnsubscribe = () => {};\n\nfunction isCommentStore(value: unknown): value is CommentStore {\n return (\n !!value &&\n typeof (value as CommentStore).getSnapshot === \"function\" &&\n typeof (value as CommentStore).createThread === \"function\"\n );\n}\n\nexport interface UseCommentsResult extends CommentStoreSnapshot {\n store: CommentStore | null;\n}\n\n/**\n * Subscribes to a comment store: pass the store itself, or an editor using\n * the `Comments` extension (`null` while the editor is being created).\n */\nexport function useComments(\n source: Editor | CommentStore | null | undefined,\n): UseCommentsResult {\n const store = isCommentStore(source) ? source : getCommentStore(source as Editor | null);\n const subscribe = useCallback(\n (onChange: () => void) => (store ? store.subscribe(() => onChange()) : noopUnsubscribe),\n [store],\n );\n const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n return useMemo(() => ({ ...snapshot, store }), [snapshot, store]);\n}\n\nexport interface UseTrackChangesResult extends TrackChangesSnapshot {\n currentChange: TrackedChange | null;\n setEnabled: (enabled: boolean) => void;\n toggle: () => void;\n accept: (id: string) => void;\n reject: (id: string) => void;\n acceptAll: () => void;\n rejectAll: () => void;\n next: () => void;\n previous: () => void;\n}\n\n/**\n * Subscribes to the tracked-change state of an editor using the\n * `TrackChanges` extension and exposes its commands.\n */\nexport function useTrackChanges(editor: Editor | null | undefined): UseTrackChangesResult {\n const store = getTrackChangesStore(editor ?? null);\n const subscribe = useCallback(\n (onChange: () => void) => (store ? store.subscribe(() => onChange()) : noopUnsubscribe),\n [store],\n );\n const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return useMemo(() => {\n const run = (fn: (e: Editor) => void) => () => {\n if (editor && !editor.isDestroyed) fn(editor);\n };\n return {\n ...snapshot,\n currentChange:\n snapshot.changes.find((c) => c.id === snapshot.currentChangeId) ?? null,\n setEnabled: (enabled: boolean) => run((e) => e.commands.setTrackChanges(enabled))(),\n toggle: run((e) => e.commands.toggleTrackChanges()),\n accept: (id: string) => run((e) => e.commands.acceptChange(id))(),\n reject: (id: string) => run((e) => e.commands.rejectChange(id))(),\n acceptAll: run((e) => e.commands.acceptAllChanges()),\n rejectAll: run((e) => e.commands.rejectAllChanges()),\n next: run((e) => e.chain().focus().selectNextChange().run()),\n previous: run((e) => e.chain().focus().selectPreviousChange().run()),\n };\n }, [snapshot, editor]);\n}\n","import React, { useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n formatReviewTime,\n getCommentAuthor,\n type CommentStore,\n type CommentThread,\n type ReviewAuthor,\n} from \"@pixerate/editor\";\nimport { useComments } from \"./useReview\";\n\nexport interface CommentsPanelProps {\n editor: Editor | null;\n /** Defaults to the store of the editor's `Comments` extension. */\n store?: CommentStore;\n /** Author of replies. Defaults to the `Comments` extension's author. */\n author?: ReviewAuthor;\n /** Initially show resolved threads. */\n showResolved?: boolean;\n className?: string;\n formatTime?: (timestamp: number) => string;\n emptyMessage?: string;\n}\n\nconst buttonClass =\n \"rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50\";\nconst primaryButtonClass =\n \"rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50\";\nconst textareaClass =\n \"w-full resize-y rounded-md border border-input bg-background p-2 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary\";\n\n/**\n * Lists comment threads with reply, resolve and delete actions. Clicking a\n * thread selects its text in the editor. Threads with an empty body are\n * drafts (e.g. created by `CommentButton`) and show a compose box.\n */\nexport const CommentsPanel: React.FC<CommentsPanelProps> = ({\n editor,\n store: storeProp,\n author: authorProp,\n showResolved: showResolvedInitial = false,\n className = \"flex flex-col gap-2 text-sm text-foreground\",\n formatTime = (t) => formatReviewTime(t),\n emptyMessage = \"No comments yet. Select text and add a comment.\",\n}) => {\n const { threads, activeThreadId, store } = useComments(storeProp ?? editor);\n const [showResolved, setShowResolved] = useState(showResolvedInitial);\n const author = authorProp ?? getCommentAuthor(editor) ?? { id: \"anonymous\", name: \"Anonymous\" };\n\n const visible = threads.filter((t) => showResolved || !t.resolved);\n const resolvedCount = threads.filter((t) => t.resolved).length;\n\n return (\n <aside className={className} aria-label=\"Comments\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n {threads.length - resolvedCount} open\n {resolvedCount > 0 ? ` · ${resolvedCount} resolved` : \"\"}\n </span>\n {resolvedCount > 0 && (\n <button\n type=\"button\"\n className={buttonClass}\n aria-pressed={showResolved}\n onClick={() => setShowResolved((v) => !v)}\n >\n {showResolved ? \"Hide resolved\" : \"Show resolved\"}\n </button>\n )}\n </div>\n {visible.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">{emptyMessage}</p>\n ) : (\n <ul className=\"flex flex-col gap-2\" role=\"list\">\n {visible.map((thread) => (\n <CommentThreadCard\n key={thread.id}\n thread={thread}\n active={thread.id === activeThreadId}\n editor={editor}\n store={store}\n author={author}\n formatTime={formatTime}\n />\n ))}\n </ul>\n )}\n </aside>\n );\n};\n\ninterface CommentThreadCardProps {\n thread: CommentThread;\n active: boolean;\n editor: Editor | null;\n store: CommentStore | null;\n author: ReviewAuthor;\n formatTime: (timestamp: number) => string;\n}\n\nconst CommentThreadCard: React.FC<CommentThreadCardProps> = ({\n thread,\n active,\n editor,\n store,\n author,\n formatTime,\n}) => {\n const [draft, setDraft] = useState(\"\");\n const isDraft = thread.body === \"\";\n const quote = thread.anchor?.quote ?? thread.lastQuote ?? \"\";\n const live = editor && !editor.isDestroyed ? editor : null;\n\n const focus = () => {\n if (!active) {\n if (live && !thread.orphaned) live.commands.focusComment(thread.id);\n else store?.setActiveThread(thread.id);\n }\n };\n const remove = () => {\n if (live) live.commands.deleteComment(thread.id);\n else store?.deleteThread(thread.id);\n };\n const setResolved = (resolved: boolean) => {\n if (live) live.commands.resolveComment(thread.id, resolved);\n else store?.resolveThread(thread.id, resolved, author);\n };\n const submit = () => {\n const body = draft.trim();\n if (!body || !store) return;\n if (isDraft) store.editComment(thread.id, body);\n else store.addReply(thread.id, { body, author });\n setDraft(\"\");\n };\n const stop = (e: React.SyntheticEvent) => e.stopPropagation();\n\n return (\n <li\n className={`flex flex-col gap-2 rounded-md border bg-background p-3 cursor-pointer ${\n active ? \"border-primary ring-1 ring-primary\" : \"border-border\"\n } ${thread.resolved ? \"opacity-70\" : \"\"}`}\n data-thread-id={thread.id}\n data-active={active || undefined}\n aria-current={active || undefined}\n tabIndex={0}\n onClick={focus}\n onKeyDown={(e) => {\n if (e.target === e.currentTarget && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n focus();\n }\n }}\n >\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"font-medium\">{thread.author.name}</span>\n <span className=\"text-xs text-muted-foreground\">{formatTime(thread.createdAt)}</span>\n </div>\n {quote && (\n <blockquote className=\"border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2\">\n {quote}\n </blockquote>\n )}\n {thread.orphaned && (\n <span className=\"text-xs text-destructive\">The commented text was deleted.</span>\n )}\n {thread.resolved && <span className=\"text-xs text-muted-foreground\">Resolved</span>}\n {!isDraft && <p className=\"whitespace-pre-wrap break-words\">{thread.body}</p>}\n {thread.replies.length > 0 && (\n <ul className=\"flex flex-col gap-2 border-l border-border pl-3\" role=\"list\">\n {thread.replies.map((reply) => (\n <li key={reply.id} className=\"flex flex-col gap-0.5\" data-reply-id={reply.id}>\n <span className=\"text-xs\">\n <span className=\"font-medium\">{reply.author.name}</span>{\" \"}\n <span className=\"text-muted-foreground\">{formatTime(reply.createdAt)}</span>\n </span>\n <p className=\"whitespace-pre-wrap break-words\">{reply.body}</p>\n </li>\n ))}\n </ul>\n )}\n {(active || isDraft) && !thread.resolved && (\n <div className=\"flex flex-col gap-1\" onClick={stop}>\n <textarea\n className={textareaClass}\n rows={2}\n value={draft}\n aria-label={isDraft ? \"Comment\" : \"Reply\"}\n placeholder={isDraft ? \"Add a comment…\" : \"Reply…\"}\n autoFocus={isDraft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n }}\n />\n <div className=\"flex justify-end gap-1\">\n {isDraft && (\n <button type=\"button\" className={buttonClass} onClick={remove}>\n Cancel\n </button>\n )}\n <button\n type=\"button\"\n className={primaryButtonClass}\n disabled={!draft.trim()}\n onClick={submit}\n >\n {isDraft ? \"Comment\" : \"Reply\"}\n </button>\n </div>\n </div>\n )}\n {!isDraft && (\n <div className=\"flex justify-end gap-1\" onClick={stop}>\n <button type=\"button\" className={buttonClass} onClick={() => setResolved(!thread.resolved)}>\n {thread.resolved ? \"Reopen\" : \"Resolve\"}\n </button>\n <button\n type=\"button\"\n className={`${buttonClass} hover:text-destructive`}\n onClick={remove}\n >\n Delete\n </button>\n </div>\n )}\n </li>\n );\n};\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { useTrackChanges } from \"./useReview\";\n\nexport interface ReviewToolbarProps {\n editor: Editor | null;\n className?: string;\n}\n\nconst buttonClass =\n \"rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent\";\n\n/**\n * Toolbar for tracked changes: toggle tracking, step through changes, and\n * accept or reject the current change or all changes.\n */\nexport const ReviewToolbar: React.FC<ReviewToolbarProps> = ({\n editor,\n className = \"flex flex-wrap items-center gap-1 rounded-md border border-border bg-background p-1 text-sm\",\n}) => {\n const review = useTrackChanges(editor);\n const count = review.changes.length;\n const current = review.currentChange;\n const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;\n\n return (\n <div className={className} role=\"toolbar\" aria-label=\"Review\">\n <button\n type=\"button\"\n className={`${buttonClass} ${review.enabled ? \"bg-primary/10 text-primary\" : \"\"}`}\n aria-pressed={review.enabled}\n disabled={!editor}\n onClick={review.toggle}\n >\n {review.enabled ? \"Tracking on\" : \"Track changes\"}\n </button>\n <span className=\"mx-1 h-4 w-px bg-border\" aria-hidden=\"true\" />\n <button\n type=\"button\"\n className={buttonClass}\n aria-label=\"Previous change\"\n disabled={count === 0}\n onClick={review.previous}\n >\n ‹\n </button>\n <span className=\"min-w-[4rem] text-center text-xs text-muted-foreground\" aria-live=\"polite\">\n {count === 0 ? \"No changes\" : current ? `${index} of ${count}` : `${count} changes`}\n </span>\n <button\n type=\"button\"\n className={buttonClass}\n aria-label=\"Next change\"\n disabled={count === 0}\n onClick={review.next}\n >\n ›\n </button>\n <span className=\"mx-1 h-4 w-px bg-border\" aria-hidden=\"true\" />\n <button\n type=\"button\"\n className={buttonClass}\n disabled={!current}\n onClick={() => current && review.accept(current.id)}\n >\n Accept\n </button>\n <button\n type=\"button\"\n className={buttonClass}\n disabled={!current}\n onClick={() => current && review.reject(current.id)}\n >\n Reject\n </button>\n <button type=\"button\" className={buttonClass} disabled={count === 0} onClick={review.acceptAll}>\n Accept all\n </button>\n <button type=\"button\" className={buttonClass} disabled={count === 0} onClick={review.rejectAll}>\n Reject all\n </button>\n </div>\n );\n};\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\n\nexport interface CommentButtonProps {\n editor: Editor | null;\n className?: string;\n children?: React.ReactNode;\n}\n\n/**\n * Adds a draft comment on the selection; drop it into a `BubbleMenu`. The\n * draft is completed in `CommentsPanel`.\n */\nexport const CommentButton: React.FC<CommentButtonProps> = ({\n editor,\n className = \"rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted\",\n children = \"Comment\",\n}) => (\n <button\n type=\"button\"\n className={className}\n disabled={!editor}\n onClick={() => editor?.chain().focus().addComment().run()}\n >\n {children}\n </button>\n);\n"],"mappings":"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","names":["useEditor","import_react","StarterKit","Placeholder","import_react","import_editor","useEditor","useTipTapEditor","import_react","import_react","import_react","import_editor","import_react","import_react","import_editor","import_react","import_react","TipTapEditorContent","import_react","import_react","import_editor","import_jsx_runtime","import_react","import_editor","import_jsx_runtime","import_react","import_editor","import_editor","import_jsx_runtime","import_editor","import_react","document","import_react","import_spreadsheet","import_react","import_jsx_runtime","React","import_jsx_runtime","import_react","import_spreadsheet","import_react","import_spreadsheet","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_image_editor","import_jsx_runtime","currentImgPt","import_react","import_editor","import_react","import_editor","import_jsx_runtime","import_jsx_runtime","buttonClass","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/hooks/usePromptEditor.ts","../src/hooks/useEditor.ts","../src/hooks/useNavigationGuard.ts","../src/hooks/useDismissGuard.ts","../src/hooks/useHistory.ts","../src/hooks/useHistoryDirty.ts","../src/hooks/useHistoryShortcuts.ts","../src/hooks/useFileImport.ts","../src/hooks/useAgentToolProvider.ts","../src/components/EditorContent.tsx","../src/components/BubbleMenu.tsx","../src/components/TemplateRenderer.tsx","../src/components/VariableForm.tsx","../src/hooks/useOutline.ts","../src/components/OutlinePanel.tsx","../src/spreadsheet/useSpreadsheetEditor.ts","../src/spreadsheet/SpreadsheetEditor.tsx","../src/spreadsheet/SpreadsheetContextMenu.tsx","../src/spreadsheet/SpreadsheetGroupRow.tsx","../src/spreadsheet/useSpreadsheetTableInteractions.ts","../src/spreadsheet/FormulaHints.tsx","../src/slots.tsx","../src/image-editor/useImageEditor.ts","../src/image-editor/ImageEditor.tsx","../src/review/useReview.ts","../src/review/CommentsPanel.tsx","../src/review/ReviewToolbar.tsx","../src/review/CommentButton.tsx","../src/commands/useCommandPalette.ts","../src/commands/CommandPalette.tsx","../src/commands/useCommandShortcuts.ts"],"sourcesContent":["export * from \"./hooks/usePromptEditor\";\nexport * from \"./hooks/useEditor\";\nexport * from \"./hooks/useNavigationGuard\";\nexport * from \"./hooks/useDismissGuard\";\nexport * from \"./hooks/useHistory\";\nexport * from \"./hooks/useHistoryDirty\";\nexport * from \"./hooks/useHistoryShortcuts\";\nexport * from \"./hooks/useFileImport\";\nexport * from \"./hooks/useAgentToolProvider\";\nexport * from \"./components/EditorContent\";\nexport * from \"./components/BubbleMenu\";\nexport * from \"./components/TemplateRenderer\";\nexport * from \"./components/VariableForm\";\nexport * from \"./hooks/useOutline\";\nexport * from \"./components/OutlinePanel\";\n\n// Re-export core types for easy consumer access\nexport {\n DirtyTracker,\n createDirtyTracker,\n defaultIsEqual,\n HistoryManager,\n createHistoryManager,\n bindDirtyToHistory,\n withoutDirty,\n} from \"@pixerate/editor\";\nexport type {\n Template,\n TemplateVersion,\n Token,\n TokenType,\n ColorGradient,\n RichTextPresetOptions,\n DirtyTrackerOptions,\n Command,\n HistoryState,\n HistoryManagerOptions,\n HistoryEntry,\n HistoryMark,\n MergedExecutionOptions,\n HistoryDirtyBinding,\n BindDirtyToHistoryOptions,\n} from \"@pixerate/editor\";\nexport type {\n PromptValues,\n PromptDiagnostic,\n VariableFormField,\n} from \"@pixerate/editor\";\n\nexport * from \"./spreadsheet\";\nexport * from \"./slots\";\nexport * from \"./image-editor\";\nexport * from \"./review\";\nexport * from \"./commands\";\n","import { useMemo, useEffect, useRef } from \"react\";\nimport { useEditor } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport { Slice } from \"@tiptap/pm/model\";\nimport {\n Template,\n ColorGradient,\n GradientText,\n TemplateSuggestions,\n LoadingNode,\n plainTextToTipTapHtml,\n plainTextToSlice,\n getEditorText,\n tokenizePrompt,\n FileImport,\n type FileImportOptions,\n} from \"@pixerate/editor\";\n\nexport interface UsePromptEditorProps {\n /**\n * The editor content as plain text. Changes from the parent (e.g. clearing\n * after submit) are applied to the editor; echoes of the editor's own\n * updates via `onContentChange` are ignored.\n */\n content: string;\n /** Callback fired when the editor content changes (returns plain text) */\n onContentChange: (text: string) => void;\n /** List of available templates to be suggested and highlighted */\n templates?: Template[];\n /** Custom gradient color map for templates */\n templateColorMap?: Map<string, ColorGradient>;\n /** Whether the editor is editable */\n isEditing?: boolean;\n /** Placeholder text for the editor */\n placeholder?: string;\n /** Additional CSS classes for the editor container */\n className?: string;\n /** Callback fired when the Escape key is pressed */\n onEscape?: () => void;\n /** Custom keydown handler. Return true to prevent default behavior */\n onKeyDown?: (event: KeyboardEvent) => boolean;\n /** Callback fired when text selection changes */\n onSelectionChange?: (selection: { from: number; to: number } | null) => void;\n /** Callback fired when a slash command (e.g., /template) matches */\n onSlashCommandMatch?: (\n match: RegExpMatchArray,\n from: number,\n to: number,\n coords: { top: number; left: number },\n ) => void;\n /** Callback to dismiss/clear the active slash command */\n clearSlashCommand?: () => void;\n /** Whether a slash command menu is currently active */\n slashCommandActive?: boolean;\n /**\n * Callback fired the first time each milestone is reached while the editor\n * is mounted: `used_variable` ({variable}) and `used_magic` (__instruction__).\n */\n onMilestone?: (milestone: string) => void;\n /** DOM element ID of the container, used for positioning popovers */\n containerId?: string;\n /** Variable names originating from structured JSON output steps */\n jsonVariables?: string[];\n /** Animation speed for gradient decorations */\n speed?: number;\n /**\n * Import text from .md, .html, .txt and .rtf files dropped onto the editor\n * (opt-in). Content is always inserted as plain text. Pasting keeps the\n * plain-text paste handler, so pasted files are not imported.\n */\n fileImport?: Omit<FileImportOptions, \"asPlainText\"> | boolean;\n}\n\nconst DEFAULT_TEMPLATES: Template[] = [];\nconst DEFAULT_COLOR_MAP = new Map<string, ColorGradient>([\n [\"default\", { from: \"#f43f5e\", to: \"#8b5cf6\" }],\n]);\nconst DEFAULT_CLASS_NAME =\n \"w-full border border-input rounded-md p-3 font-mono text-sm leading-relaxed focus:outline-none focus:ring-2 focus:ring-primary whitespace-pre-wrap break-words\";\n\nconst normalizeNewlines = (text: string) => text.replace(/\\r\\n?/g, \"\\n\");\n\nexport function usePromptEditor({\n content,\n onContentChange,\n templates = DEFAULT_TEMPLATES,\n templateColorMap: userColorMap,\n isEditing = true,\n placeholder = \"Write a prompt, use {{template}}, {variable}, or /command...\",\n className,\n onEscape,\n onKeyDown,\n onSelectionChange,\n onSlashCommandMatch,\n clearSlashCommand,\n slashCommandActive = false,\n onMilestone,\n containerId = \"editor-container\",\n jsonVariables,\n speed = 2,\n fileImport,\n}: UsePromptEditorProps) {\n const fileImportRef = useRef(fileImport);\n fileImportRef.current = fileImport;\n const fileImportEnabled = !!fileImport;\n\n const slashCommandActiveRef = useRef(slashCommandActive);\n slashCommandActiveRef.current = slashCommandActive;\n\n const clearSlashCommandRef = useRef(clearSlashCommand);\n clearSlashCommandRef.current = clearSlashCommand;\n\n const onEscapeRef = useRef(onEscape);\n onEscapeRef.current = onEscape;\n\n const onKeyDownRef = useRef(onKeyDown);\n onKeyDownRef.current = onKeyDown;\n\n const onSelectionChangeRef = useRef(onSelectionChange);\n onSelectionChangeRef.current = onSelectionChange;\n\n const onSlashCommandMatchRef = useRef(onSlashCommandMatch);\n onSlashCommandMatchRef.current = onSlashCommandMatch;\n\n const onContentChangeRef = useRef(onContentChange);\n onContentChangeRef.current = onContentChange;\n\n const onMilestoneRef = useRef(onMilestone);\n onMilestoneRef.current = onMilestone;\n\n const containerIdRef = useRef(containerId);\n containerIdRef.current = containerId;\n\n const templateKey = useMemo(() => {\n return (templates || [])\n .map((t) => `${t.id || t.name}:${(t as any).latestVersion || \"\"}`)\n .sort()\n .join(\",\");\n }, [templates]);\n\n // Key the color map by value so an inline `new Map(...)` does not recreate\n // the editor on every render.\n const colorMapKey = userColorMap\n ? JSON.stringify(Array.from(userColorMap.entries()))\n : \"\";\n const resolvedColorMap = useMemo(() => {\n if (userColorMap) return userColorMap;\n const map = new Map<string, ColorGradient>();\n templates.forEach((t) => {\n map.set(t.name, { from: \"#f43f5e\", to: \"#8b5cf6\" });\n });\n return map.size > 0 ? map : DEFAULT_COLOR_MAP;\n }, [colorMapKey, templateKey]);\n\n const jsonVariablesKey = (jsonVariables || []).join(\"\\u0000\");\n\n const reachedMilestonesRef = useRef(new Set<string>());\n\n const StarterKitExt =\n (StarterKit as any)?.configure\n ? StarterKit\n : (StarterKit as any)?.default?.configure\n ? (StarterKit as any)?.default\n : StarterKit;\n\n const PlaceholderExt =\n (Placeholder as any)?.configure\n ? Placeholder\n : (Placeholder as any)?.default?.configure\n ? (Placeholder as any)?.default\n : Placeholder;\n\n const editor = useEditor(\n {\n immediatelyRender: false,\n enablePasteRules: false,\n enableInputRules: false,\n editable: isEditing,\n extensions: [\n StarterKitExt.configure({\n heading: false,\n codeBlock: false,\n }),\n PlaceholderExt.configure({ placeholder }),\n GradientText.configure({\n templateColorMap: resolvedColorMap,\n speed,\n jsonVariables,\n }),\n TemplateSuggestions.configure({\n templates,\n }),\n LoadingNode,\n ...(fileImportEnabled\n ? [\n FileImport.configure({\n ...(typeof fileImportRef.current === \"object\" ? fileImportRef.current : {}),\n // Prompt editors only ever receive plain text.\n asPlainText: true,\n }),\n ]\n : []),\n ],\n content: plainTextToTipTapHtml(content),\n onUpdate: ({ editor: ed }) => {\n const plainText = getEditorText(ed);\n onContentChangeRef.current?.(plainText);\n\n if (onMilestoneRef.current) {\n const reached = reachedMilestonesRef.current;\n for (const token of tokenizePrompt(plainText)) {\n const milestone =\n token.type === \"variable\"\n ? \"used_variable\"\n : token.type === \"instruction\"\n ? \"used_magic\"\n : null;\n if (milestone && !reached.has(milestone)) {\n reached.add(milestone);\n onMilestoneRef.current(milestone);\n }\n }\n }\n\n const { state, view } = ed;\n const { selection } = state;\n const { $from, from, to } = selection;\n\n onSelectionChangeRef.current?.({ from, to });\n\n if (onSlashCommandMatchRef.current && clearSlashCommandRef.current) {\n const textBeforeCursor = $from?.parent?.textBetween\n ? $from.parent.textBetween(0, $from.parentOffset)\n : \"\";\n const slashMatch = textBeforeCursor.match(\n /(?:^|\\s)\\/([a-zA-Z0-9_-]*)$/,\n );\n\n if (slashMatch) {\n const coords = view.coordsAtPos($from.pos);\n const containerEl =\n document.getElementById(containerIdRef.current) ||\n document.getElementById(\"editor-container\") ||\n (view.dom.closest?.(\".relative\") as HTMLElement | null);\n const containerCoords = containerEl?.getBoundingClientRect();\n\n if (containerCoords) {\n onSlashCommandMatchRef.current(\n slashMatch,\n $from.pos -\n slashMatch[0].length +\n (slashMatch[0].startsWith(\" \") ? 1 : 0),\n $from.pos,\n {\n top: coords.bottom - containerCoords.top + 5,\n left: coords.left - containerCoords.left,\n },\n );\n }\n } else {\n clearSlashCommandRef.current();\n }\n }\n },\n onSelectionUpdate: ({ editor: ed }) => {\n const { from, to } = ed.state.selection;\n onSelectionChangeRef.current?.({ from, to });\n },\n editorProps: {\n attributes: {\n class: className || DEFAULT_CLASS_NAME,\n role: \"textbox\",\n \"aria-label\": \"Prompt editor\",\n },\n handleKeyDown(view, event) {\n if (slashCommandActiveRef.current) {\n if (\n event.key === \"ArrowUp\" ||\n event.key === \"ArrowDown\" ||\n event.key === \"Enter\"\n ) {\n event.preventDefault();\n return true;\n }\n if (event.key === \"Escape\") {\n clearSlashCommandRef.current?.();\n event.preventDefault();\n event.stopPropagation();\n return true;\n }\n }\n if (onKeyDownRef.current && onKeyDownRef.current(event as KeyboardEvent)) {\n return true;\n }\n if (event.key === \"Escape\" && onEscapeRef.current) {\n onEscapeRef.current();\n return true;\n }\n return false;\n },\n handlePaste: (view, event) => {\n // Paste as plain text even when the clipboard also carries HTML.\n const text = event.clipboardData?.getData(\"text/plain\");\n if (!text) return false;\n event.preventDefault();\n const schema = view.state.schema;\n if (!schema) return false;\n view.dispatch(\n view.state.tr.replaceSelection(plainTextToSlice(text, schema)),\n );\n return true;\n },\n clipboardTextParser: (text, context, _plain, view) => {\n const schema =\n (context as any)?.doc?.type?.schema ||\n (context as any)?.schema ||\n view?.state?.schema;\n\n if (!schema) return Slice.empty;\n return plainTextToSlice(text, schema);\n },\n },\n },\n // Only options baked into extensions recreate the editor; editable state,\n // placeholder, class names and content are applied to the live instance.\n [resolvedColorMap, templateKey, speed, jsonVariablesKey, fileImportEnabled],\n );\n\n useEffect(() => {\n if (editor && !editor.isDestroyed) {\n editor.setEditable(isEditing);\n }\n }, [editor, isEditing]);\n\n // Apply content changes made by the parent (e.g. clearing after submit).\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n if (normalizeNewlines(content) === getEditorText(editor)) return;\n const { from, to } = editor.state.selection;\n editor.commands.setContent(plainTextToTipTapHtml(content), false);\n const max = editor.state.doc.content.size;\n editor.commands.setTextSelection({\n from: Math.min(from, max),\n to: Math.min(to, max),\n });\n }, [editor, content]);\n\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n editor.setOptions({\n editorProps: {\n ...editor.options.editorProps,\n attributes: {\n ...(editor.options.editorProps.attributes as Record<string, string>),\n class: className || DEFAULT_CLASS_NAME,\n },\n },\n });\n }, [editor, className]);\n\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n const placeholderExt = editor.extensionManager.extensions.find(\n (ext) => ext.name === \"placeholder\",\n );\n if (!placeholderExt || placeholderExt.options.placeholder === placeholder) {\n return;\n }\n placeholderExt.options.placeholder = placeholder;\n // Re-run decorations so the new placeholder renders.\n editor.view.dispatch(editor.state.tr);\n }, [editor, placeholder]);\n\n return editor;\n}\n","import { useEditor as useTipTapEditor, UseEditorOptions } from \"@tiptap/react\";\nimport {\n createRichTextPreset,\n RichTextPresetOptions,\n type FileImportOptions,\n type RichClipboardOptions,\n} from \"@pixerate/editor\";\n\nexport interface UseRichEditorProps extends UseEditorOptions {\n richTextOptions?: RichTextPresetOptions;\n /**\n * Import .md, .html, .txt and .rtf files dropped or pasted into the editor\n * at the drop position (opt-in; same as `richTextOptions.fileImport`).\n */\n fileImport?: FileImportOptions | boolean;\n /**\n * Copy/paste lossless ProseMirror slices between editors via the\n * `application/x.pixerate.document+json` clipboard type (opt-in; same as\n * `richTextOptions.richClipboard`).\n */\n richClipboard?: RichClipboardOptions | boolean;\n}\n\n/**\n * Hook to initialize a TipTap rich-text editor instance with pre-configured extensions.\n */\nexport function useEditor(options: UseRichEditorProps = {}) {\n const {\n richTextOptions,\n fileImport,\n richClipboard,\n extensions = [],\n ...editorOptions\n } = options;\n\n const preset = createRichTextPreset({\n ...(fileImport !== undefined ? { fileImport } : {}),\n ...(richClipboard !== undefined ? { richClipboard } : {}),\n ...richTextOptions,\n });\n const combinedExtensions = [...preset, ...extensions];\n\n return useTipTapEditor({\n extensions: combinedExtensions,\n ...editorOptions,\n });\n}\n","import { useState, useEffect, useCallback, useRef } from \"react\";\n\nexport interface UseNavigationGuardOptions {\n /** Whether the current form or editor has unsaved changes */\n isDirty: boolean;\n /** Whether guarding is enabled (defaults to true) */\n enabled?: boolean;\n /** Custom navigation function (e.g. router.push from next/navigation or react-router) */\n onNavigate?: (url: string) => void;\n /** Optional callback fired when an internal navigation attempt is intercepted */\n onBlocked?: (url: string) => void;\n}\n\nexport interface UseNavigationGuardReturn {\n /** Whether the unsaved changes confirmation dialog should be displayed */\n showConfirm: boolean;\n /** Setter to manually control the dialog visibility */\n setShowConfirm: (show: boolean) => void;\n /** The target URL that the user attempted to navigate to */\n pendingUrl: string | null;\n /** Proceeds with the blocked navigation and closes the dialog */\n confirmLeave: () => void;\n /** Cancels the navigation attempt and keeps the user on the current page */\n cancelLeave: () => void;\n}\n\n/**\n * Hook to guard against navigation when there are unsaved changes.\n * Intercepts both external unloads (tab closing/refreshing) and internal link clicks.\n */\nexport function useNavigationGuard({\n isDirty,\n enabled = true,\n onNavigate,\n onBlocked,\n}: UseNavigationGuardOptions): UseNavigationGuardReturn {\n const [showConfirm, setShowConfirm] = useState(false);\n const [pendingUrl, setPendingUrl] = useState<string | null>(null);\n\n const onNavigateRef = useRef(onNavigate);\n onNavigateRef.current = onNavigate;\n\n const onBlockedRef = useRef(onBlocked);\n onBlockedRef.current = onBlocked;\n\n // 1. Intercept external navigation / tab close (beforeunload)\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!enabled || !isDirty) return;\n\n const handleBeforeUnload = (e: BeforeUnloadEvent) => {\n e.preventDefault();\n e.returnValue = \"\";\n };\n\n window.addEventListener(\"beforeunload\", handleBeforeUnload);\n return () => {\n window.removeEventListener(\"beforeunload\", handleBeforeUnload);\n };\n }, [enabled, isDirty]);\n\n // 2. Intercept internal anchor link clicks\n useEffect(() => {\n if (typeof document === \"undefined\" || typeof window === \"undefined\")\n return;\n if (!enabled || !isDirty) return;\n\n const handleClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n const anchor = target?.closest?.(\"a\");\n\n if (!anchor) return;\n if (anchor.target === \"_blank\") return;\n\n // Only guard internal origins\n const isInternal = anchor.host === window.location.host;\n if (!isInternal) return;\n\n // Ignore navigation to the exact same path & query\n if (\n anchor.pathname === window.location.pathname &&\n anchor.search === window.location.search\n ) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n\n const href = anchor.href;\n setPendingUrl(href);\n setShowConfirm(true);\n onBlockedRef.current?.(href);\n };\n\n document.addEventListener(\"click\", handleClick, { capture: true });\n return () => {\n document.removeEventListener(\"click\", handleClick, { capture: true });\n };\n }, [enabled, isDirty]);\n\n const confirmLeave = useCallback(() => {\n setShowConfirm(false);\n if (pendingUrl) {\n if (onNavigateRef.current) {\n onNavigateRef.current(pendingUrl);\n } else if (typeof window !== \"undefined\") {\n window.location.href = pendingUrl;\n }\n }\n }, [pendingUrl]);\n\n const cancelLeave = useCallback(() => {\n setShowConfirm(false);\n setPendingUrl(null);\n }, []);\n\n return {\n showConfirm,\n setShowConfirm,\n pendingUrl,\n confirmLeave,\n cancelLeave,\n };\n}\n","import { useState, useCallback, useRef } from \"react\";\n\nexport interface UseDismissGuardOptions {\n /** Whether there are unsaved changes */\n isDirty: boolean;\n /** Whether the dismissal guard is enabled (defaults to true) */\n enabled?: boolean;\n /** Callback fired when dismissal is confirmed or when clean dismissal occurs */\n onDismiss?: () => void;\n}\n\nexport interface UseDismissGuardReturn {\n /** Whether the discard confirmation modal should be shown */\n showConfirm: boolean;\n /** Manually update confirmation modal visibility */\n setShowConfirm: (show: boolean) => void;\n /** Request dismissal - checks isDirty and shows confirm or executes onDismiss */\n requestDismiss: () => void;\n /** Confirm discarding changes and dismiss */\n confirmDismiss: () => void;\n /** Cancel discarding and resume editing */\n cancelDismiss: () => void;\n /** Helper keydown handler intercepting Escape key */\n handleKeyDown: (event: React.KeyboardEvent | KeyboardEvent) => boolean;\n}\n\n/**\n * Hook to guard against closing or exiting an editor/dialog with uncommitted changes.\n */\nexport function useDismissGuard({\n isDirty,\n enabled = true,\n onDismiss,\n}: UseDismissGuardOptions): UseDismissGuardReturn {\n const [showConfirm, setShowConfirm] = useState(false);\n\n const onDismissRef = useRef(onDismiss);\n onDismissRef.current = onDismiss;\n\n const requestDismiss = useCallback(() => {\n if (enabled && isDirty) {\n setShowConfirm(true);\n } else {\n onDismissRef.current?.();\n }\n }, [enabled, isDirty]);\n\n const confirmDismiss = useCallback(() => {\n setShowConfirm(false);\n onDismissRef.current?.();\n }, []);\n\n const cancelDismiss = useCallback(() => {\n setShowConfirm(false);\n }, []);\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent | KeyboardEvent) => {\n if (event.key === \"Escape\") {\n if (event.defaultPrevented) return false;\n event.preventDefault();\n requestDismiss();\n return true;\n }\n return false;\n },\n [requestDismiss],\n );\n\n return {\n showConfirm,\n setShowConfirm,\n requestDismiss,\n confirmDismiss,\n cancelDismiss,\n handleKeyDown,\n };\n}\n","import { useSyncExternalStore, useRef, useCallback, useMemo } from \"react\";\nimport {\n HistoryManager,\n HistoryState,\n HistoryEntry,\n HistoryMark,\n Command,\n MergedExecutionOptions,\n createHistoryManager,\n HistoryManagerOptions,\n} from \"@pixerate/editor\";\n\nexport interface UseHistoryResult extends HistoryState {\n manager: HistoryManager;\n /** History panel rows (undo steps, then redo steps). */\n entries: HistoryEntry[];\n undo: () => boolean;\n redo: () => boolean;\n clear: () => void;\n execute: (command: Command) => void;\n executeMerged: (command: Command, options?: MergedExecutionOptions) => void;\n batch: (name: string, fn: () => void) => void;\n /** Undoes / redoes until the entry at `index` is current (`-1` = before all). */\n goTo: (index: number) => number;\n /** Captures the current point, e.g. when a drag starts. */\n mark: () => HistoryMark;\n /** Takes back every step since `mark` without leaving redo (Escape-cancel). */\n revertTo: (mark: HistoryMark) => number;\n /** Joins every merged execute into one step until `endGesture`. */\n beginGesture: (key: string) => void;\n endGesture: () => void;\n}\n\n/**\n * React hook that subscribes to a HistoryManager instance.\n * Accepts an existing HistoryManager or config options to create an instance\n * (options are read on first render only).\n */\nexport function useHistory(\n managerOrOptions?: HistoryManager | HistoryManagerOptions,\n): UseHistoryResult {\n // Options are read once, so passing an inline options object does not\n // create a new manager (and wipe history) on every render.\n const ownManagerRef = useRef<HistoryManager | null>(null);\n let manager: HistoryManager;\n if (managerOrOptions instanceof HistoryManager) {\n manager = managerOrOptions;\n } else {\n ownManagerRef.current ??= createHistoryManager(managerOrOptions);\n manager = ownManagerRef.current;\n }\n\n const state = useSyncExternalStore(\n useCallback(\n (onStoreChange) => manager.subscribe(onStoreChange),\n [manager],\n ),\n () => manager.getState(),\n () => manager.getState(),\n );\n\n // getEntries() is cached per history change, so `state` is a valid dependency.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const entries = useMemo(() => manager.getEntries(), [manager, state]);\n\n const undo = useCallback(() => manager.undo(), [manager]);\n const redo = useCallback(() => manager.redo(), [manager]);\n const clear = useCallback(() => manager.clear(), [manager]);\n const execute = useCallback(\n (cmd: Command) => manager.execute(cmd),\n [manager],\n );\n const executeMerged = useCallback(\n (cmd: Command, opts?: MergedExecutionOptions) =>\n manager.executeMerged(cmd, opts),\n [manager],\n );\n const batch = useCallback(\n (name: string, fn: () => void) => manager.batch(name, fn),\n [manager],\n );\n const goTo = useCallback((index: number) => manager.goTo(index), [manager]);\n const mark = useCallback(() => manager.mark(), [manager]);\n const revertTo = useCallback(\n (m: HistoryMark) => manager.revertTo(m),\n [manager],\n );\n const beginGesture = useCallback(\n (key: string) => manager.beginGesture(key),\n [manager],\n );\n const endGesture = useCallback(() => manager.endGesture(), [manager]);\n\n return {\n ...state,\n manager,\n entries,\n undo,\n redo,\n clear,\n execute,\n executeMerged,\n batch,\n goTo,\n mark,\n revertTo,\n beginGesture,\n endGesture,\n };\n}\n","import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport {\n DirtyTracker,\n bindDirtyToHistory,\n type DirtyTrackerOptions,\n type HistoryDirtyBinding,\n type HistoryManager,\n} from \"@pixerate/editor\";\n\nexport interface UseHistoryDirtyOptions<T> extends DirtyTrackerOptions<T> {\n /** The history whose changes re-check the document. */\n history: HistoryManager;\n /** Reads the current document value (the latest function is always used). */\n getValue: () => T;\n /** Existing tracker to drive (read on first render only). */\n tracker?: DirtyTracker<T>;\n}\n\nexport interface UseHistoryDirtyResult<T> {\n /** Whether the document differs from the saved state. Feed it to `useNavigationGuard`. */\n isDirty: boolean;\n /** Marks the current document as saved. */\n markClean: () => void;\n /** Runs a load / restore without marking the document dirty (re-entrant). */\n suppress: <R>(fn: () => R) => R;\n /** Re-checks after a change made outside the history. */\n refresh: () => boolean;\n tracker: DirtyTracker<T>;\n}\n\n/**\n * Dirty-vs-saved tracking bound to a HistoryManager: undoing back to the saved\n * state makes the document clean again, selection/viewport changes can be\n * ignored with `normalize`, and programmatic loads can be wrapped in `suppress`.\n * Options other than `getValue` and `history` are read on first render only.\n */\nexport function useHistoryDirty<T>(\n options: UseHistoryDirtyOptions<T>,\n): UseHistoryDirtyResult<T> {\n const getValueRef = useRef(options.getValue);\n getValueRef.current = options.getValue;\n\n const [tracker] = useState(\n () =>\n options.tracker ??\n new DirtyTracker<T>(options.getValue(), {\n isEqual: options.isEqual,\n normalize: options.normalize,\n }),\n );\n\n const bindingRef = useRef<HistoryDirtyBinding<T> | null>(null);\n useEffect(() => {\n const binding = bindDirtyToHistory<T>({\n history: options.history,\n getValue: () => getValueRef.current(),\n tracker,\n });\n bindingRef.current = binding;\n return () => {\n binding.destroy();\n if (bindingRef.current === binding) bindingRef.current = null;\n };\n }, [options.history, tracker]);\n\n const isDirty = useSyncExternalStore(\n useCallback((onChange) => tracker.subscribe(onChange), [tracker]),\n () => tracker.dirty,\n () => tracker.dirty,\n );\n\n const markClean = useCallback(\n () => tracker.markClean(getValueRef.current()),\n [tracker],\n );\n const suppress = useCallback(\n <R,>(fn: () => R): R =>\n bindingRef.current ? bindingRef.current.suppress(fn) : tracker.suppress(fn),\n [tracker],\n );\n const refresh = useCallback(\n () => tracker.update(getValueRef.current()),\n [tracker],\n );\n\n return { isDirty, markClean, suppress, refresh, tracker };\n}\n","import { useEffect } from \"react\";\nimport type { HistoryManager } from \"@pixerate/editor/history\";\nimport { matchHistoryShortcut } from \"@pixerate/editor/commands\";\n\nexport interface HistoryShortcutsOptions {\n /**\n * Whether the keyboard shortcuts are enabled. Defaults to true.\n */\n enabled?: boolean;\n /**\n * Target element or window to listen on. Defaults to window.\n */\n target?: Window | HTMLElement | null;\n /**\n * When true (default), shortcuts will not trigger if an <input>, <textarea>,\n * or [contenteditable] element is currently active / focused.\n */\n ignoreEditableElements?: boolean;\n}\n\n/**\n * Attaches keyboard listeners for Undo (Mod+Z) and Redo (Mod+Shift+Z / Mod+Y).\n * Automatically guards against active text inputs and contenteditable editors.\n */\nexport function useHistoryShortcuts(\n manager: HistoryManager,\n options: HistoryShortcutsOptions = {},\n): void {\n const {\n enabled = true,\n target,\n ignoreEditableElements = true,\n } = options;\n\n useEffect(() => {\n if (!enabled) return;\n\n const eventTarget = target ?? (typeof window !== \"undefined\" ? window : null);\n if (!eventTarget) return;\n\n const handleKeyDown = (event: Event) => {\n const e = event as KeyboardEvent;\n // Default bindings from the command system: Mod+Z, Mod+Shift+Z and (off macOS) Mod+Y,\n // matched by `event.code` with `Mod` = ⌘ on macOS and Ctrl elsewhere.\n const action = matchHistoryShortcut(e, { allowInEditable: !ignoreEditableElements });\n if (action === \"undo\" && manager.getState().canUndo) {\n e.preventDefault();\n manager.undo();\n } else if (action === \"redo\" && manager.getState().canRedo) {\n e.preventDefault();\n manager.redo();\n }\n };\n\n eventTarget.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n eventTarget.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [manager, enabled, target, ignoreEditableElements]);\n}\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n FileImportController,\n type FileImportControllerOptions,\n type FileImportState,\n} from \"@pixerate/editor\";\n\nexport interface UseFileImportResult extends FileImportState {\n /** Value for `<input type=\"file\" accept={…}>`. */\n accept: string;\n /** Opens the browser file picker and imports the chosen files at the selection. */\n openFilePicker: FileImportController[\"openFilePicker\"];\n /** Imports files (e.g. from your own `<input>` or drop zone) at `at` or the selection. */\n importFiles: FileImportController[\"importFiles\"];\n}\n\n/**\n * Imports markdown, HTML, plain-text and RTF files (or anything registered\n * with `registerImportAdapter` for the `document` target) into an editor.\n * Pair it with `useEditor({ fileImport: true })` to also accept dropped files.\n */\nexport function useFileImport(\n editor: Editor | null | undefined,\n options: FileImportControllerOptions = {},\n): UseFileImportResult {\n const editorRef = useRef(editor);\n editorRef.current = editor;\n\n const controller = useMemo(\n () =>\n new FileImportController(() => {\n const current = editorRef.current;\n return current && !current.isDestroyed ? current : null;\n }, options),\n [],\n );\n\n useEffect(() => {\n controller.setOptions(options);\n });\n\n const state = useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n\n return {\n ...state,\n accept: controller.accept,\n openFilePicker: controller.openFilePicker,\n importFiles: controller.importFiles,\n };\n}\n","import { useEffect } from \"react\";\nimport type { AgentToolProvider, ToolRegistry } from \"@pixerate/editor/agent\";\n\n/**\n * Registers a tool provider with a `ToolRegistry` while the component is\n * mounted and unregisters it on unmount (the registry then announces the\n * change through `onListChanged`).\n *\n * Memoize the provider (e.g. `useMemo(() => createRichTextToolProvider(editor,\n * { id }), [editor])`): a new provider object re-registers it. Pass `null`\n * while it isn't ready.\n */\nexport function useAgentToolProvider(\n registry: ToolRegistry | null | undefined,\n provider: AgentToolProvider | null | undefined,\n): void {\n useEffect(() => {\n if (!registry || !provider) return;\n return registry.register(provider);\n }, [registry, provider]);\n}\n","import React from \"react\";\nimport {\n EditorContent as TipTapEditorContent,\n EditorContentProps as TipTapEditorContentProps,\n} from \"@tiptap/react\";\n\nexport interface EditorContentProps extends TipTapEditorContentProps {\n className?: string;\n}\n\nexport const EditorContent: React.FC<EditorContentProps> = ({\n className,\n editor,\n ...props\n}) => {\n return (\n <div className={className}>\n <TipTapEditorContent editor={editor} {...props} />\n </div>\n );\n};\n","import React, { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n BubbleMenuPlugin,\n type BubbleMenuPluginProps,\n} from \"@tiptap/extension-bubble-menu\";\nimport type { Editor } from \"@tiptap/core\";\n\nexport interface BubbleMenuProps {\n editor: Editor | null;\n className?: string;\n children: React.ReactNode;\n tippyOptions?: BubbleMenuPluginProps[\"tippyOptions\"];\n shouldShow?: BubbleMenuPluginProps[\"shouldShow\"];\n pluginKey?: BubbleMenuPluginProps[\"pluginKey\"];\n updateDelay?: BubbleMenuPluginProps[\"updateDelay\"];\n}\n\nexport const BubbleMenu: React.FC<BubbleMenuProps> = ({\n editor,\n className = \"flex items-center gap-1 bg-popover text-popover-foreground border shadow-md rounded-md p-1\",\n children,\n tippyOptions = { duration: 100 },\n shouldShow = null,\n pluginKey = \"bubbleMenu\",\n updateDelay,\n}) => {\n const menuEl = useRef<HTMLDivElement | null>(null);\n const [mounted, setMounted] = useState(false);\n\n if (!menuEl.current && typeof document !== \"undefined\") {\n menuEl.current = document.createElement(\"div\");\n }\n\n useEffect(() => {\n if (!editor || !menuEl.current || editor.isDestroyed) {\n return;\n }\n\n const element = menuEl.current;\n element.className = className;\n\n const plugin = BubbleMenuPlugin({\n editor,\n element,\n pluginKey,\n tippyOptions,\n shouldShow,\n updateDelay,\n });\n\n editor.registerPlugin(plugin);\n setMounted(true);\n\n return () => {\n setMounted(false);\n editor.unregisterPlugin(pluginKey);\n if (element.parentNode) {\n element.parentNode.removeChild(element);\n }\n };\n }, [editor, className, pluginKey]);\n\n if (!editor || !menuEl.current || !mounted) {\n return null;\n }\n\n return createPortal(children, menuEl.current);\n};\n","import React, { useMemo } from \"react\";\nimport {\n evaluatePromptTokens,\n resolveTemplates,\n Template,\n ColorGradient,\n PromptValues,\n} from \"@pixerate/editor\";\n\nexport interface TemplateRendererProps {\n /** Raw prompt or text string to render */\n content: string;\n /** Available templates for recursive resolution and custom coloring */\n templates?: Template[];\n /** Custom gradient color map for templates */\n templateColorMap?: Map<string, ColorGradient>;\n /** Whether to resolve nested templates recursively before displaying */\n resolve?: boolean;\n /** Template version bindings used when `resolve` is set */\n bindings?: Record<string, string>;\n /**\n * Variable values. When set, variables show their value (or default),\n * sections whose condition fails are hidden, and section tags are dropped.\n */\n values?: PromptValues;\n /** Custom class name for the wrapper */\n className?: string;\n /** Click callback for template badges */\n onTemplateClick?: (templateName: string) => void;\n /** Click callback for variable badges */\n onVariableClick?: (variableName: string) => void;\n}\n\nconst CONDITIONAL_PREFIX = { if: \"?\", unless: \"!\", end: \"/\" } as const;\n\nexport const TemplateRenderer: React.FC<TemplateRendererProps> = ({\n content,\n templates = [],\n templateColorMap,\n resolve = false,\n bindings,\n values,\n className = \"font-mono text-sm leading-relaxed whitespace-pre-wrap break-words\",\n onTemplateClick,\n onVariableClick,\n}) => {\n const displayText = useMemo(() => {\n if (!resolve || templates.length === 0) return content;\n return resolveTemplates(content, templates, { bindings });\n }, [content, templates, resolve, bindings]);\n\n const tokens = useMemo(() => {\n return evaluatePromptTokens(displayText, values);\n }, [displayText, values]);\n\n return (\n <div className={className}>\n {tokens.map((token, index) => {\n if (token.type === \"template\") {\n const colors = templateColorMap?.get(token.value) || {\n from: \"#f43f5e\",\n to: \"#8b5cf6\",\n };\n const style = {\n \"--color-from\": colors.from,\n \"--color-to\": colors.to,\n } as React.CSSProperties;\n\n return (\n <span\n key={index}\n style={style}\n onClick={() => onTemplateClick?.(token.value)}\n className=\"inline-flex items-center px-1.5 py-0.5 mx-0.5 text-xs font-semibold rounded-md border border-[var(--color-to)]/40 bg-gradient-to-r from-[var(--color-from)]/15 to-[var(--color-to)]/15 text-[var(--color-to)] hover:brightness-110 cursor-pointer transition-all\"\n title={`Template: ${token.value}`}\n >\n {`{{${token.value}}}`}\n </span>\n );\n }\n\n if (token.type === \"variable\") {\n const details = [\n `Variable: ${token.value}`,\n token.description,\n token.defaultValue !== undefined\n ? `Default: ${token.defaultValue || \"(empty)\"}`\n : undefined,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n\n if (token.resolvedValue !== undefined) {\n return (\n <span\n key={index}\n onClick={() => onVariableClick?.(token.value)}\n data-variable={token.value}\n data-value-source={token.valueSource}\n className={\n token.valueSource === \"value\"\n ? \"inline px-1 mx-0.5 rounded-md bg-emerald-400/15 text-emerald-700 dark:text-emerald-300 border-b border-emerald-400/60 cursor-pointer\"\n : \"inline px-1 mx-0.5 rounded-md bg-violet-400/10 text-violet-600 dark:text-violet-300 italic border-b border-dashed border-violet-400/60 cursor-pointer\"\n }\n title={details}\n >\n {token.resolvedValue}\n </span>\n );\n }\n\n return (\n <span\n key={index}\n onClick={() => onVariableClick?.(token.value)}\n data-variable={token.value}\n className=\"inline-flex items-center px-1.5 py-0.5 mx-0.5 text-xs font-medium rounded-md border border-violet-400/40 bg-violet-400/15 text-violet-600 dark:text-violet-300 hover:brightness-110 cursor-pointer transition-all\"\n title={details}\n >\n {`{${token.value}`}\n {token.defaultValue !== undefined && (\n <span className=\"opacity-60\">{`|${token.defaultValue}`}</span>\n )}\n {\"}\"}\n </span>\n );\n }\n\n if (token.type === \"conditional\" && token.conditional) {\n return (\n <span\n key={index}\n data-conditional={token.conditional}\n className=\"inline-flex items-center px-1 py-0.5 mx-0.5 text-xs font-medium rounded-md border border-amber-400/40 bg-amber-400/15 text-amber-700 dark:text-amber-300\"\n title={\n token.conditional === \"end\"\n ? `End of section: ${token.value}`\n : token.conditional === \"if\"\n ? `Shown when \"${token.value}\" has a value`\n : `Shown when \"${token.value}\" is empty`\n }\n >\n {`{${CONDITIONAL_PREFIX[token.conditional]}${token.value}}`}\n </span>\n );\n }\n\n if (token.type === \"instruction\") {\n return (\n <span\n key={index}\n className=\"inline-flex items-center px-1.5 py-0.5 mx-0.5 text-xs italic font-medium rounded-md border border-rose-400/40 bg-rose-400/15 text-rose-600 dark:text-rose-300\"\n title={`Instruction: ${token.value}`}\n >\n {`__${token.value}__`}\n </span>\n );\n }\n\n return <span key={index}>{token.value}</span>;\n })}\n </div>\n );\n};\n","import React, { useId, useMemo, useState } from \"react\";\nimport {\n compactVariableValues,\n getVariableFormFields,\n PromptValues,\n Template,\n VariableFormField,\n} from \"@pixerate/editor\";\n\nexport interface VariableFormProps {\n /** Prompt whose variables become form fields */\n content: string;\n /** Templates searched recursively for further variables */\n templates?: Template[];\n /** Template version bindings */\n bindings?: Record<string, string>;\n /** Entered text per variable (controlled). Omit to let the form keep its own state. */\n values?: Record<string, string>;\n /** Initial entered text when uncontrolled */\n defaultValues?: Record<string, string>;\n /**\n * Called on every edit with the values to resolve with (blank fields\n * dropped so defaults apply) and the raw entered text.\n */\n onChange?: (values: PromptValues, entered: Record<string, string>) => void;\n /** Custom class name for the wrapper */\n className?: string;\n}\n\n/**\n * Renders one input per prompt variable: labelled with its description,\n * using its default as the placeholder. Variables only used by `{?name}`\n * conditions render as checkboxes.\n */\nexport const VariableForm: React.FC<VariableFormProps> = ({\n content,\n templates,\n bindings,\n values,\n defaultValues,\n onChange,\n className = \"flex flex-col gap-3 text-sm\",\n}) => {\n const idPrefix = useId();\n const [internal, setInternal] = useState<Record<string, string>>(\n () => defaultValues ?? {},\n );\n const entered = values ?? internal;\n\n const fields = useMemo<VariableFormField[]>(\n () => getVariableFormFields(content, { templates, bindings }),\n [content, templates, bindings],\n );\n\n const update = (name: string, value: string) => {\n const next = { ...entered, [name]: value };\n if (values === undefined) setInternal(next);\n onChange?.(compactVariableValues(next), next);\n };\n\n if (fields.length === 0) return null;\n\n return (\n <form className={className} onSubmit={(event) => event.preventDefault()}>\n {fields.map((field) => {\n const id = `${idPrefix}-${field.name}`;\n if (field.conditionOnly) {\n return (\n <label\n key={field.name}\n htmlFor={id}\n className=\"flex items-center gap-2\"\n data-variable-field={field.name}\n >\n <input\n id={id}\n name={field.name}\n type=\"checkbox\"\n checked={(entered[field.name] ?? \"\") !== \"\"}\n onChange={(event) =>\n update(field.name, event.target.checked ? \"true\" : \"\")\n }\n />\n <span>{field.label}</span>\n </label>\n );\n }\n return (\n <label\n key={field.name}\n htmlFor={id}\n className=\"flex flex-col gap-1\"\n data-variable-field={field.name}\n >\n <span className=\"font-medium\">\n {field.label}\n {field.required && (\n <span className=\"text-rose-500\" aria-hidden=\"true\">\n {\" *\"}\n </span>\n )}\n </span>\n <input\n id={id}\n name={field.name}\n type=\"text\"\n value={entered[field.name] ?? \"\"}\n placeholder={field.placeholder}\n aria-required={field.required || undefined}\n onChange={(event) => update(field.name, event.target.value)}\n className=\"px-2 py-1 rounded-md border border-violet-400/40 bg-transparent\"\n />\n </label>\n );\n })}\n </form>\n );\n};\n","import { useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { createOutlineStore, type OutlineSnapshot } from \"@pixerate/editor\";\n\nexport type { OutlineHeading, OutlineSnapshot, OutlineTreeItem } from \"@pixerate/editor\";\n\n/**\n * Subscribes to an editor's heading outline. Returns the headings (flat and\n * nested) and the id of the heading whose section contains the selection.\n * Re-renders only when the outline or the active heading changes.\n *\n * Install the `Outline` extension (`richTextOptions: { outline: true }`) for\n * stable heading ids; without it, headings are still listed.\n */\nexport function useOutline(editor: Editor | null | undefined): OutlineSnapshot {\n // The store only listens to the editor while subscribed, so it needs no\n // explicit cleanup (and survives StrictMode's double effects).\n const store = useMemo(() => createOutlineStore(editor), [editor]);\n return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n}\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { navigateToHeading, type OutlineHeading } from \"@pixerate/editor\";\nimport { useOutline } from \"../hooks/useOutline\";\n\nexport interface OutlinePanelProps {\n editor: Editor | null;\n /** Heading shown above the list. Pass `null` to hide it. */\n title?: React.ReactNode;\n /** Content shown when the document has no headings. */\n emptyState?: React.ReactNode;\n /** Deepest heading level listed. Defaults to 6. */\n maxLevel?: number;\n /** Whether clicking an entry focuses the editor. Defaults to `true`. */\n focusOnNavigate?: boolean;\n /** Custom class name for the wrapper. */\n className?: string;\n /** Class name for each entry button. */\n itemClassName?: string;\n /** Class name added to the entry of the section containing the selection. */\n activeItemClassName?: string;\n /** Called after navigating to a heading. */\n onNavigate?: (heading: OutlineHeading) => void;\n}\n\n/**\n * Navigation sidebar listing the document's headings (Word's Navigation pane).\n * Clicking an entry moves the caret to that heading; the entry for the\n * section containing the selection is highlighted.\n */\nexport const OutlinePanel: React.FC<OutlinePanelProps> = ({\n editor,\n title = \"Outline\",\n emptyState = \"Add headings to see the outline.\",\n maxLevel = 6,\n focusOnNavigate = true,\n className = \"flex flex-col gap-1 text-sm\",\n itemClassName = \"w-full truncate rounded px-2 py-1 text-left hover:bg-black/5\",\n activeItemClassName = \"font-semibold bg-black/5\",\n onNavigate,\n}) => {\n const { headings, activeId } = useOutline(editor);\n const visible = headings.filter((h) => h.level <= maxLevel);\n\n return (\n <nav className={className} aria-label=\"Document outline\" data-outline-panel=\"\">\n {title != null && <div className=\"pixerate-outline-title\">{title}</div>}\n {visible.length === 0 ? (\n <div className=\"pixerate-outline-empty\">{emptyState}</div>\n ) : (\n <ul role=\"list\" style={{ listStyle: \"none\", margin: 0, padding: 0 }}>\n {visible.map((heading) => {\n const active = heading.id === activeId;\n return (\n <li key={heading.id} data-level={heading.level}>\n <button\n type=\"button\"\n className={active ? `${itemClassName} ${activeItemClassName}` : itemClassName}\n style={{ paddingLeft: `${0.5 + heading.depth * 0.75}rem` }}\n aria-current={active ? \"location\" : undefined}\n data-heading-id={heading.id}\n onClick={() => {\n if (!editor) return;\n if (navigateToHeading(editor, heading, { focus: focusOnNavigate })) {\n onNavigate?.(heading);\n }\n }}\n >\n {heading.text || \"Untitled\"}\n </button>\n </li>\n );\n })}\n </ul>\n )}\n </nav>\n );\n};\n","import { useState, useRef, useCallback, useMemo } from 'react';\nimport {\n SpreadsheetController,\n bindSpreadsheetTableActions,\n type SpreadsheetControllerOptions,\n type SpreadsheetDocument,\n type CellCoordinate,\n type CellRange,\n type SpreadsheetColumn,\n type SpreadsheetRow,\n type SpreadsheetDataSource\n} from '@pixerate/editor/spreadsheet';\n\nexport function useSpreadsheetEditor(options: SpreadsheetControllerOptions = {}) {\n // Callbacks are read through a ref so they are never stale.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const settersRef = useRef<{\n setDoc?: (doc: SpreadsheetDocument) => void;\n setActiveCell?: (cell: CellCoordinate | null) => void;\n setSelectedRange?: (range: CellRange | null) => void;\n }>({});\n\n // Create the controller first so the initial state reflects its document\n // (including default rows and columns when no document is passed).\n const [controller] = useState(\n () =>\n new SpreadsheetController({\n ...options,\n onDocumentChange: (updated) => {\n settersRef.current.setDoc?.({ ...updated });\n optionsRef.current.onDocumentChange?.(updated);\n },\n onSelectionChange: (active, range) => {\n settersRef.current.setActiveCell?.(active);\n settersRef.current.setSelectedRange?.(range);\n optionsRef.current.onSelectionChange?.(active, range);\n },\n onCellCommit: (rowId, colId, raw, value) => {\n optionsRef.current.onCellCommit?.(rowId, colId, raw, value);\n },\n }),\n );\n\n const [doc, setDoc] = useState<SpreadsheetDocument>(() => ({ ...controller.document }));\n const [activeCell, setActiveCell] = useState<CellCoordinate | null>(controller.activeCell);\n const [selectedRange, setSelectedRange] = useState<CellRange | null>(controller.selectedRange);\n const [editingCell, setEditingCell] = useState<CellCoordinate | null>(null);\n const [draftValue, setDraftState] = useState<string>('');\n settersRef.current = { setDoc, setActiveCell, setSelectedRange };\n\n // The controller commits its own `draftValue` (`commitEditing()` without an\n // argument), so typed text must reach it, not just React state.\n const setDraftValue = useCallback((value: string) => {\n controller.draftValue = value;\n setDraftState(value);\n }, [controller]);\n\n const setCellValue = useCallback((rowId: string, colId: string, raw: string) => {\n controller.setCellValue(rowId, colId, raw);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const selectCell = useCallback((row: number, col: number, extendSelection = false) => {\n controller.selectCell(row, col, extendSelection);\n setActiveCell(controller.activeCell);\n setSelectedRange(controller.selectedRange);\n }, [controller]);\n\n const selectRange = useCallback((range: CellRange) => {\n controller.selectRange(range);\n setSelectedRange(controller.selectedRange);\n }, [controller]);\n\n const startEditing = useCallback((row?: number, col?: number, initialVal?: string) => {\n controller.startEditing(row, col, initialVal);\n setActiveCell(controller.activeCell);\n setEditingCell(controller.editingCell);\n setDraftValue(controller.draftValue);\n }, [controller]);\n\n const commitEditing = useCallback((val?: string) => {\n controller.commitEditing(val);\n setEditingCell(null);\n setDraftValue('');\n setDoc({ ...controller.document });\n }, [controller]);\n\n const cancelEditing = useCallback(() => {\n controller.cancelEditing();\n setEditingCell(null);\n setDraftValue('');\n }, [controller]);\n\n const moveCursor = useCallback((dir: 'up' | 'down' | 'left' | 'right', extend = false) => {\n controller.moveCursor(dir, extend);\n setActiveCell(controller.activeCell);\n setSelectedRange(controller.selectedRange);\n }, [controller]);\n\n const insertColumn = useCallback((index: number, config?: Partial<SpreadsheetColumn>) => {\n controller.insertColumn(index, config);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const deleteColumn = useCallback((colId: string) => {\n controller.deleteColumn(colId);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const insertRow = useCallback((index: number, config?: Partial<SpreadsheetRow>) => {\n controller.insertRow(index, config);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const deleteRow = useCallback((rowId: string) => {\n controller.deleteRow(rowId);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const setColumnWidth = useCallback((colId: string, width: number) => {\n controller.setColumnWidth(colId, width);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const autoFitColumnWidth = useCallback((colId: string, customWidth?: number) => {\n controller.autoFitColumnWidth(colId, customWidth);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const registerDataSource = useCallback((ds: SpreadsheetDataSource) => {\n controller.registerDataSource(ds);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const setPrimaryDataSource = useCallback((id: string | undefined) => {\n controller.setPrimaryDataSource(id);\n setDoc({ ...controller.document });\n }, [controller]);\n\n const recalculateAll = useCallback(() => {\n controller.recalculateAll();\n setDoc({ ...controller.document });\n }, [controller]);\n\n const undo = useCallback(() => {\n controller.undo();\n setDoc({ ...controller.document });\n }, [controller]);\n\n const redo = useCallback(() => {\n controller.redo();\n setDoc({ ...controller.document });\n }, [controller]);\n\n // Table operations (sort, filters, freeze, hide, merge, autofill, categories,\n // transpose, CSV, clipboard). The controller reports their changes through\n // onDocumentChange / onSelectionChange, which update the state above.\n const tableActions = useMemo(() => bindSpreadsheetTableActions(controller), [controller]);\n // What to render: visible rows (with group headers) and columns, frozen\n // offsets and merged-cell spans. Recomputed whenever the document changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const viewModel = useMemo(() => controller.getViewModel(), [controller, doc]);\n\n return {\n document: doc,\n activeCell,\n selectedRange,\n editingCell,\n draftValue,\n setDraftValue,\n controller,\n getCell: (rowId: string, colId: string) => controller.getCell(rowId, colId),\n setCellValue,\n selectCell,\n selectRange,\n startEditing,\n commitEditing,\n cancelEditing,\n moveCursor,\n insertColumn,\n deleteColumn,\n insertRow,\n deleteRow,\n setColumnWidth,\n autoFitColumnWidth,\n loadDocument: (document: SpreadsheetDocument) => {\n controller.loadDocument(document);\n setDoc({ ...controller.document });\n setActiveCell(null);\n setSelectedRange(null);\n setEditingCell(null);\n setDraftValue('');\n },\n syncWithDataSource: () => {\n controller.syncWithDataSource();\n controller.recalculateAll();\n setDoc({ ...controller.document });\n },\n registerDataSource,\n setPrimaryDataSource,\n recalculateAll,\n exportToTsv: (range?: CellRange | null) => controller.exportToTsv(range),\n importFromTsv: (data: string) => {\n controller.importFromTsv(data);\n setDoc({ ...controller.document });\n },\n ...tableActions,\n viewModel,\n undo,\n redo\n };\n}\n","import React, { useRef, useState, useMemo, useEffect, useCallback } from 'react';\nimport {\n indexToColName,\n getSpreadsheetMenuItems,\n normalizeRange,\n rangeContains,\n type SpreadsheetColumn,\n type SpreadsheetRow,\n type CellData,\n type CellRange,\n type SpreadsheetMenuItem,\n type SpreadsheetViewColumn,\n type SpreadsheetViewRow,\n formatCellDisplay\n} from '@pixerate/editor/spreadsheet';\nimport { useSpreadsheetEditor } from './useSpreadsheetEditor';\nimport { SpreadsheetContextMenu } from './SpreadsheetContextMenu';\nimport { SpreadsheetGroupRow } from './SpreadsheetGroupRow';\nimport { useFillHandle, useSpreadsheetClipboard } from './useSpreadsheetTableInteractions';\n\n// Sizes of the sticky header row and row-number column, for frozen-pane offsets.\nconst COLUMN_HEADER_HEIGHT = 28;\nconst ROW_HEADER_WIDTH = 48;\n\n/** Sticky positioning for cells in frozen rows and/or columns. */\nfunction frozenCellStyle(\n viewRow: Extract<SpreadsheetViewRow, { kind: 'row' }>,\n viewCol: SpreadsheetViewColumn\n): React.CSSProperties | undefined {\n if (!viewRow.frozen && !viewCol.frozen) return undefined;\n return {\n position: 'sticky',\n ...(viewRow.frozen ? { top: COLUMN_HEADER_HEIGHT + viewRow.stickyTop } : {}),\n ...(viewCol.frozen ? { left: ROW_HEADER_WIDTH + viewCol.stickyLeft } : {}),\n zIndex: viewRow.frozen && viewCol.frozen ? 14 : viewRow.frozen ? 12 : 11,\n background: 'var(--background, #fff)'\n };\n}\nimport { FormulaHints } from './FormulaHints';\n\nconst coordKey = (cell: { row: number; col: number } | null) => (cell ? `${indexToColName(cell.col)}${cell.row + 1}` : '');\n\n/** Thin border drawn on the outer edges of a dynamic array's spill range. */\nfunction spillBorderStyle(range: CellRange, row: number, col: number): React.CSSProperties {\n const line = '1px solid color-mix(in srgb, var(--primary, #6366f1) 60%, transparent)';\n return {\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n zIndex: 5,\n borderTop: row === range.startRow ? line : undefined,\n borderBottom: row === range.endRow ? line : undefined,\n borderLeft: col === range.startCol ? line : undefined,\n borderRight: col === range.endCol ? line : undefined\n };\n}\n\nexport interface SpreadsheetEditorProps {\n state?: ReturnType<typeof useSpreadsheetEditor>;\n readOnly?: boolean;\n customCellRenderer?: (props: { row: SpreadsheetRow; col: SpreadsheetColumn; cell: CellData }) => React.ReactNode;\n onAddColumnClick?: () => void;\n onColumnHeaderClick?: (col: SpreadsheetColumn) => void;\n onColumnResize?: (colId: string, width: number) => void;\n}\n\nexport const SpreadsheetEditor: React.FC<SpreadsheetEditorProps> = ({\n state: externalState,\n readOnly = false,\n customCellRenderer,\n onAddColumnClick,\n onColumnHeaderClick,\n onColumnResize\n}) => {\n const defaultState = useSpreadsheetEditor();\n const state = externalState || defaultState;\n const gridRef = useRef<HTMLDivElement>(null);\n const formulaBarRef = useRef<HTMLInputElement>(null);\n const cellInputRef = useRef<HTMLInputElement>(null);\n\n const [resizingColId, setResizingColId] = useState<string | null>(null);\n const [hoveredColId, setHoveredColId] = useState<string | null>(null);\n const [resizeStartX, setResizeStartX] = useState(0);\n const [resizeStartWidth, setResizeStartWidth] = useState(0);\n\n // Table operations: render model, clipboard, fill handle and context menu.\n const view = state.viewModel;\n const { copyShortcutFallback } = useSpreadsheetClipboard(gridRef, state, readOnly);\n const { fillTarget, startFill, extendFill } = useFillHandle(state);\n const [menu, setMenu] = useState<{ x: number; y: number; items: SpreadsheetMenuItem[] } | null>(null);\n const filter = state.document.table?.filter;\n const filteredColIds = useMemo(\n () => new Set(filter?.enabled ? filter.rules.map((r) => r.colId) : []),\n [filter]\n );\n\n const handleCellContextMenu = useCallback((rIdx: number, cIdx: number, e: React.MouseEvent) => {\n if (readOnly) return;\n e.preventDefault();\n if (state.editingCell) state.commitEditing();\n if (!state.selectedRange || !rangeContains(state.selectedRange, rIdx, cIdx)) {\n state.selectCell(rIdx, cIdx);\n }\n setMenu({ x: e.clientX, y: e.clientY, items: getSpreadsheetMenuItems(state.controller, { row: rIdx, col: cIdx }) });\n }, [readOnly, state]);\n\n const activeRawValue = useMemo(() => {\n if (!state.activeCell) return '';\n const row = state.document.rows[state.activeCell.row];\n const col = state.document.columns[state.activeCell.col];\n if (!row || !col) return '';\n return state.getCell(row.id, col.id).raw;\n }, [state.activeCell, state.document]);\n\n // The dynamic array under the active cell (anchor or spilled cell): it gets\n // a border, and a spilled cell shows the anchor's formula greyed out.\n const activeSpill = useMemo(\n () => (state.activeCell ? state.controller.getSpillAt(state.activeCell.row, state.activeCell.col) : null),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [state.controller, state.activeCell, state.document]\n );\n const spillFormula = activeSpill && !activeRawValue && activeSpill.key !== coordKey(state.activeCell) ? activeSpill.formula : '';\n\n const coordLabel = useMemo(() => {\n if (!state.activeCell) return '--';\n const colName = indexToColName(state.activeCell.col);\n return `${colName}${state.activeCell.row + 1}`;\n }, [state.activeCell]);\n\n // Text typed in the formula bar while no cell editor is open.\n const [formulaDraft, setFormulaDraft] = useState<string | null>(null);\n const activeColumn = state.activeCell ? state.document.columns[state.activeCell.col] : undefined;\n const formulaBarReadOnly = readOnly || !state.activeCell || !!activeColumn?.readOnly;\n\n useEffect(() => {\n setFormulaDraft(null);\n }, [state.activeCell?.row, state.activeCell?.col]);\n\n const commitFormulaBar = () => {\n if (state.editingCell) {\n state.commitEditing();\n return;\n }\n if (formulaDraft === null || !state.activeCell) return;\n const row = state.document.rows[state.activeCell.row];\n const col = state.document.columns[state.activeCell.col];\n if (row && col && !formulaBarReadOnly && formulaDraft !== activeRawValue) {\n state.setCellValue(row.id, col.id, formulaDraft);\n }\n setFormulaDraft(null);\n };\n\n const handleCellClick = useCallback((rIdx: number, cIdx: number, e: React.MouseEvent) => {\n if (state.editingCell && (state.editingCell.row !== rIdx || state.editingCell.col !== cIdx)) {\n state.commitEditing();\n }\n state.selectCell(rIdx, cIdx, e.shiftKey);\n }, [state]);\n\n const handleCellDblClick = useCallback((rIdx: number, cIdx: number) => {\n if (readOnly) return;\n const col = state.document.columns[cIdx];\n if (col?.readOnly) return;\n state.startEditing(rIdx, cIdx);\n }, [readOnly, state]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (state.editingCell) {\n if (e.key === 'Enter') {\n e.preventDefault();\n state.commitEditing();\n state.moveCursor('down');\n } else if (e.key === 'Escape') {\n e.preventDefault();\n state.cancelEditing();\n } else if (e.key === 'Tab') {\n e.preventDefault();\n state.commitEditing();\n state.moveCursor(e.shiftKey ? 'left' : 'right');\n } else {\n return;\n }\n // The cell input unmounts; keep focus on the grid so typing continues.\n gridRef.current?.focus();\n return;\n }\n\n if (!state.activeCell) return;\n\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n state.moveCursor('up', e.shiftKey);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n state.moveCursor('down', e.shiftKey);\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n state.moveCursor('left', e.shiftKey);\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n state.moveCursor('right', e.shiftKey);\n } else if (e.key === 'Tab') {\n e.preventDefault();\n state.moveCursor(e.shiftKey ? 'left' : 'right');\n } else if (e.key === 'Enter') {\n e.preventDefault();\n const col = state.document.columns[state.activeCell.col];\n if (!readOnly && !col?.readOnly) {\n state.startEditing();\n }\n } else if (e.key === 'Backspace' || e.key === 'Delete') {\n if (readOnly) return;\n const row = state.document.rows[state.activeCell.row];\n const col = state.document.columns[state.activeCell.col];\n if (row && col && !col.readOnly) {\n e.preventDefault();\n state.setCellValue(row.id, col.id, '');\n }\n } else if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'z') {\n // With Shift held, e.key is 'Z'.\n e.preventDefault();\n if (e.shiftKey) {\n state.redo();\n } else {\n state.undo();\n }\n } else if (e.ctrlKey && !e.metaKey && e.key.toLowerCase() === 'y') {\n e.preventDefault();\n state.redo();\n } else if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'c') {\n // Copy the selection, not the whole sheet. The browser's copy event\n // writes TSV, HTML and the internal format; the fallback writes TSV.\n copyShortcutFallback();\n } else if (!readOnly && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n const col = state.document.columns[state.activeCell.col];\n if (!col?.readOnly) {\n // The key becomes the draft; without preventDefault the browser would\n // also type it into the newly focused cell input (\"1\" -> \"11\").\n e.preventDefault();\n state.startEditing(state.activeCell.row, state.activeCell.col, e.key);\n }\n }\n }, [readOnly, state, copyShortcutFallback]);\n // The resize effect reads these through refs: re-running it on every width\n // update would reset the in-progress drag (and skip onColumnResize).\n const stateRef = useRef(state);\n stateRef.current = state;\n const onColumnResizeRef = useRef(onColumnResize);\n onColumnResizeRef.current = onColumnResize;\n\n useEffect(() => {\n if (!resizingColId) return;\n\n if (typeof document !== 'undefined') {\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n }\n\n let rafId: number | null = null;\n let pendingWidth = resizeStartWidth;\n let hasDragged = false;\n\n const handleMouseMove = (e: MouseEvent) => {\n const delta = e.clientX - resizeStartX;\n if (Math.abs(delta) > 2) {\n hasDragged = true;\n }\n pendingWidth = Math.max(30, resizeStartWidth + delta);\n\n if (rafId === null) {\n rafId = requestAnimationFrame(() => {\n rafId = null;\n stateRef.current.setColumnWidth(resizingColId, pendingWidth);\n });\n }\n };\n\n const handleMouseUp = () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n if (hasDragged) {\n stateRef.current.setColumnWidth(resizingColId, pendingWidth);\n onColumnResizeRef.current?.(resizingColId, pendingWidth);\n }\n setResizingColId(null);\n if (typeof document !== 'undefined') {\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n }\n };\n\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n return () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n if (typeof document !== 'undefined') {\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n }\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n }, [resizingColId, resizeStartX, resizeStartWidth]);\n\n const measureElementContentWidth = useCallback((el: HTMLElement, container: HTMLElement): number => {\n if (typeof document === 'undefined') return 0;\n\n let maxW = el.scrollWidth || 0;\n const firstChild = el.firstElementChild as HTMLElement | null;\n if (firstChild && firstChild.scrollWidth > maxW) {\n maxW = firstChild.scrollWidth;\n }\n\n const truncated = el.querySelectorAll<HTMLElement>('.truncate, [title], span, div');\n truncated.forEach((node) => {\n if (node.scrollWidth > maxW) {\n maxW = node.scrollWidth;\n }\n });\n\n try {\n const clone = (firstChild ? firstChild.cloneNode(true) : el.cloneNode(true)) as HTMLElement;\n clone.style.cssText = `\n position: absolute !important;\n visibility: hidden !important;\n width: max-content !important;\n min-width: max-content !important;\n max-width: none !important;\n overflow: visible !important;\n white-space: nowrap !important;\n pointer-events: none !important;\n top: -9999px !important;\n left: -9999px !important;\n `;\n\n const allNodes = clone.querySelectorAll<HTMLElement>('*');\n allNodes.forEach((node) => {\n node.style.maxWidth = 'none';\n node.style.overflow = 'visible';\n node.style.textOverflow = 'clip';\n node.style.whiteSpace = 'nowrap';\n if (\n node.classList.contains('truncate') ||\n node.classList.contains('min-w-0') ||\n node.classList.contains('w-full') ||\n node.classList.contains('max-w-0') ||\n node.classList.contains('flex-1')\n ) {\n node.style.width = 'max-content';\n node.style.minWidth = 'max-content';\n }\n });\n\n container.appendChild(clone);\n const rect = clone.getBoundingClientRect();\n container.removeChild(clone);\n\n if (rect.width > maxW) {\n maxW = rect.width;\n }\n } catch {\n // Ignore cloning/measuring errors\n }\n\n return maxW;\n }, []);\n\n const autoFitColumn = useCallback((colId: string, colIndex: number) => {\n const col = state.document.columns.find((c) => c.id === colId);\n if (!col) return;\n\n let calculatedWidth = 0;\n\n if (gridRef.current && typeof document !== 'undefined') {\n const table = gridRef.current.querySelector('table');\n if (table) {\n // Look cells up by column index: hidden columns and merges shift DOM positions.\n const th = table.querySelector(`thead th[data-col=\"${colIndex}\"]`) as HTMLElement | null;\n if (th) {\n const headerInner = (th.firstElementChild as HTMLElement) || th;\n const headerW = measureElementContentWidth(headerInner, gridRef.current);\n calculatedWidth = Math.max(calculatedWidth, headerW + 28);\n }\n\n const rows = table.querySelectorAll('tbody tr');\n const sampleLimit = Math.min(rows.length, 150);\n for (let r = 0; r < sampleLimit; r++) {\n const tr = rows[r];\n const td = tr.querySelector(`td[data-col=\"${colIndex}\"][colspan=\"1\"]`) as HTMLElement | null;\n if (td) {\n const cellW = measureElementContentWidth(td, gridRef.current);\n calculatedWidth = Math.max(calculatedWidth, cellW + 20);\n }\n }\n }\n }\n\n if (calculatedWidth > 0) {\n const finalWidth = Math.min(600, Math.max(50, Math.ceil(calculatedWidth)));\n state.setColumnWidth(colId, finalWidth);\n } else {\n state.autoFitColumnWidth?.(colId);\n }\n\n const updatedCol = state.document.columns.find((c) => c.id === colId);\n if (updatedCol && onColumnResize) {\n onColumnResize(updatedCol.id, updatedCol.width || 130);\n }\n }, [state, measureElementContentWidth, onColumnResize]);\n\n const handleResizeDblClick = useCallback((colId: string, colIndex: number, e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n autoFitColumn(colId, colIndex);\n }, [autoFitColumn]);\n\n const handleHeaderDblClick = useCallback((colId: string, colIndex: number, e: React.MouseEvent) => {\n const target = e.currentTarget as HTMLElement | null;\n if (target) {\n const rect = target.getBoundingClientRect();\n if (rect.right - e.clientX <= 12) {\n e.preventDefault();\n e.stopPropagation();\n autoFitColumn(colId, colIndex);\n }\n }\n }, [autoFitColumn]);\n\n const isCellSelected = (rIdx: number, cIdx: number) => {\n if (!state.selectedRange) return false;\n const minR = Math.min(state.selectedRange.startRow, state.selectedRange.endRow);\n const maxR = Math.max(state.selectedRange.startRow, state.selectedRange.endRow);\n const minC = Math.min(state.selectedRange.startCol, state.selectedRange.endCol);\n const maxC = Math.max(state.selectedRange.startCol, state.selectedRange.endCol);\n return rIdx >= minR && rIdx <= maxR && cIdx >= minC && cIdx <= maxC;\n };\n\n const isActiveCell = (rIdx: number, cIdx: number) => {\n return state.activeCell?.row === rIdx && state.activeCell?.col === cIdx;\n };\n\n return (\n <div\n ref={gridRef}\n className=\"flex flex-col h-full w-full overflow-hidden border border-border bg-background select-none outline-none text-foreground font-sans text-xs\"\n tabIndex={0}\n onKeyDown={handleKeyDown}\n role=\"grid\"\n aria-label=\"Spreadsheet\"\n >\n {/* Formula Bar */}\n <div className=\"flex items-center gap-2 border-b border-border bg-muted/20 px-3 py-1.5 text-xs font-mono\">\n <div className=\"flex h-6 min-w-[3rem] items-center justify-center rounded border border-border bg-background px-1.5 font-semibold text-foreground\">\n {coordLabel}\n </div>\n <div className=\"flex items-center text-muted-foreground select-none\">\n <span className=\"italic font-serif font-bold text-sm text-primary\">fx</span>\n </div>\n <input\n ref={formulaBarRef}\n type=\"text\"\n className=\"flex-1 bg-transparent px-2 py-0.5 outline-none font-sans text-xs text-foreground placeholder:text-muted-foreground/60 focus:bg-background focus:ring-1 focus:ring-primary rounded\"\n placeholder=\"Enter a value or formula (e.g. =SUM(A1:A5))\"\n aria-label=\"Formula bar\"\n readOnly={formulaBarReadOnly}\n data-spill-formula={!state.editingCell && formulaDraft === null && spillFormula ? 'true' : undefined}\n style={!state.editingCell && formulaDraft === null && spillFormula ? { color: 'var(--muted-foreground, #94a3b8)' } : undefined}\n value={state.editingCell ? state.draftValue : formulaDraft ?? (activeRawValue || spillFormula)}\n onFocus={() => {\n if (!state.editingCell) setFormulaDraft(activeRawValue);\n }}\n onChange={(e) => {\n if (state.editingCell) {\n state.setDraftValue(e.target.value);\n } else if (state.activeCell) {\n setFormulaDraft(e.target.value);\n }\n }}\n onBlur={() => commitFormulaBar()}\n onKeyDown={(e) => {\n // Keys typed here must not reach the grid's navigation handler.\n e.stopPropagation();\n if (e.key === 'Enter') {\n e.preventDefault();\n commitFormulaBar();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setFormulaDraft(null);\n if (state.editingCell) state.cancelEditing();\n }\n }}\n />\n {!formulaBarReadOnly && (\n <FormulaHints\n inputRef={formulaBarRef}\n value={state.editingCell ? state.draftValue : formulaDraft ?? activeRawValue}\n onAccept={(next) => (state.editingCell ? state.setDraftValue(next) : setFormulaDraft(next))}\n />\n )}\n </div>\n\n {/* Main Grid */}\n <div className=\"relative flex-1 overflow-auto\">\n <table className=\"border-collapse table-fixed w-max min-w-full\">\n <thead>\n <tr className=\"h-7 bg-muted sticky top-0 z-20 border-b border-border shadow-xs\">\n <th className=\"w-12 min-w-[3rem] sticky left-0 z-30 bg-muted border-r border-border text-center text-[10px] text-muted-foreground font-medium\">\n #\n </th>\n {view.columns.map(({ column: col, index: cIdx, frozen, stickyLeft }) => (\n <th\n key={col.id}\n data-col={cIdx}\n className={`relative border-r border-border px-2 text-left font-medium text-muted-foreground hover:bg-muted/90 transition-colors group overflow-hidden max-w-0 ${\n onColumnHeaderClick ? 'cursor-pointer' : 'cursor-default'\n }`}\n style={{\n width: col.width || 130,\n minWidth: col.width || 130,\n maxWidth: col.width || 130,\n overflow: 'hidden',\n ...(frozen ? { position: 'sticky', left: ROW_HEADER_WIDTH + stickyLeft, zIndex: 25, background: 'var(--muted, #f4f4f5)' } : {})\n }}\n onClick={() => onColumnHeaderClick?.(col)}\n onDoubleClick={(e) => handleHeaderDblClick(col.id, cIdx, e)}\n >\n <div className=\"flex items-center justify-between gap-1 min-w-0 overflow-hidden truncate\">\n <span className=\"truncate font-semibold text-foreground text-xs min-w-0\">{col.title}</span>\n {filteredColIds.has(col.id) && (\n <span className=\"text-[10px] text-primary shrink-0\" title=\"Filtered\" data-filtered=\"true\">⏷</span>\n )}\n <span className=\"text-[10px] text-muted-foreground/70 font-mono font-normal shrink-0\">({col.key})</span>\n </div>\n {/* Column Resize Handle */}\n <div\n className=\"col-resize-handle\"\n style={{ position: 'absolute', top: 0, bottom: 0, width: 12, right: -6, cursor: 'col-resize', zIndex: 20, display: 'flex', justifyContent: 'center', touchAction: 'none' }}\n onMouseEnter={() => setHoveredColId(col.id)}\n onMouseLeave={() => setHoveredColId((cur) => cur === col.id ? null : cur)}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setResizingColId(col.id);\n setResizeStartX(e.clientX);\n setResizeStartWidth(col.width || 130);\n }}\n onDoubleClick={(e) => handleResizeDblClick(col.id, cIdx, e)}\n role=\"separator\"\n aria-orientation=\"vertical\"\n >\n <div\n className=\"col-resize-handle-line\"\n style={{\n width: 2,\n height: '100%',\n pointerEvents: 'none',\n transition: 'background-color 150ms ease',\n backgroundColor: resizingColId === col.id ? 'var(--primary, #6366f1)' : hoveredColId === col.id ? 'color-mix(in srgb, var(--primary, #6366f1) 75%, transparent)' : 'transparent'\n }}\n />\n </div>\n </th>\n ))}\n {onAddColumnClick && (\n <th\n className=\"w-10 min-w-[2.5rem] px-1 text-center bg-muted/40 hover:bg-muted cursor-pointer transition-colors\"\n onClick={onAddColumnClick}\n title=\"Add Column\"\n >\n <span className=\"text-xs font-bold text-muted-foreground\">+</span>\n </th>\n )}\n </tr>\n </thead>\n <tbody>\n {view.rows.map((viewRow) => {\n if (viewRow.kind === 'group') {\n return (\n <SpreadsheetGroupRow\n key={`group:${viewRow.group.key}`}\n group={viewRow.group}\n columns={view.columns}\n groupColId={state.document.table?.grouping?.colId ?? ''}\n onToggle={state.toggleGroupCollapsed}\n trailingCell={!!onAddColumnClick}\n />\n );\n }\n const displayRowIndex = viewRow.index;\n const selection = state.selectedRange ? normalizeRange(state.selectedRange) : null;\n return (\n <tr\n key={viewRow.row.id}\n data-row={displayRowIndex}\n className={`border-b border-border hover:bg-muted/10 transition-colors ${viewRow.section !== 'body' ? 'bg-muted/30 font-semibold' : ''}`}\n style={{ height: viewRow.row.height || 32 }}\n >\n <td\n className=\"w-12 min-w-[3rem] sticky left-0 z-10 bg-muted border-r border-border text-center text-[10px] text-muted-foreground font-mono select-none\"\n style={viewRow.frozen ? { top: COLUMN_HEADER_HEIGHT + viewRow.stickyTop, zIndex: 15 } : undefined}\n >\n {displayRowIndex + 1}\n </td>\n {view.columns.map((viewCol) => {\n // A merged cell renders its top-left cell, spanning the merge.\n const span = view.getCellSpan(displayRowIndex, viewCol.index);\n if (!span) return null;\n const rIdx = span.source.row;\n const cIdx = span.source.col;\n const row = state.document.rows[rIdx];\n const col = state.document.columns[cIdx];\n const cell = state.getCell(row.id, col.id);\n const selected = isCellSelected(rIdx, cIdx);\n const active = isActiveCell(rIdx, cIdx);\n const isEditing = state.editingCell?.row === rIdx && state.editingCell?.col === cIdx;\n\n const inFillPreview = !!fillTarget && !selected && rangeContains(fillTarget, displayRowIndex, viewCol.index);\n const showFillHandle =\n !readOnly &&\n !isEditing &&\n !!selection &&\n (span.merge\n ? rangeContains(span.merge, selection.endRow, selection.endCol)\n : selection.endRow === rIdx && selection.endCol === cIdx);\n\n return (\n <td\n key={viewCol.column.id}\n data-row={rIdx}\n data-col={cIdx}\n rowSpan={span.rowSpan}\n colSpan={span.colSpan}\n className={`relative border-r border-border px-2 py-1 truncate max-w-0 text-foreground transition-colors ${\n selected ? 'bg-primary/10' : ''\n } ${active ? 'ring-2 ring-primary ring-inset z-10' : ''} ${viewCol.header ? 'font-semibold' : ''}`}\n style={{\n maxWidth: 0,\n overflow: 'hidden',\n ...frozenCellStyle(viewRow, viewCol),\n ...(inFillPreview ? { outline: '1px dashed var(--primary, #6366f1)', outlineOffset: -1 } : {})\n }}\n onClick={(e) => handleCellClick(rIdx, cIdx, e)}\n onDoubleClick={() => handleCellDblClick(rIdx, cIdx)}\n onContextMenu={(e) => handleCellContextMenu(rIdx, cIdx, e)}\n onMouseOver={() => extendFill(displayRowIndex, viewCol.index)}\n >\n {isEditing ? (\n <>\n <input\n ref={cellInputRef}\n type=\"text\"\n className=\"absolute inset-0 w-full h-full px-2 py-1 bg-background text-foreground outline-none font-sans text-xs border-2 border-primary z-20\"\n value={state.draftValue}\n onChange={(e) => state.setDraftValue(e.target.value)}\n onBlur={() => state.commitEditing()}\n onFocus={(e) => {\n // Caret after the draft (e.g. the key that started editing).\n const end = e.currentTarget.value.length;\n e.currentTarget.setSelectionRange(end, end);\n }}\n autoFocus\n />\n <FormulaHints inputRef={cellInputRef} value={state.draftValue} onAccept={state.setDraftValue} />\n </>\n ) : customCellRenderer ? (\n customCellRenderer({ row, col, cell })\n ) : (\n <span\n className={`truncate block max-w-full ${cell.error ? 'text-destructive font-semibold' : ''}`}\n title={cell.error ? cell.errorMessage ?? cell.error : undefined}\n >\n {formatCellDisplay(cell)}\n </span>\n )}\n {activeSpill && rangeContains(activeSpill.range, rIdx, cIdx) && (\n <span aria-hidden=\"true\" className=\"spreadsheet-spill-border\" style={spillBorderStyle(activeSpill.range, rIdx, cIdx)} />\n )}\n {showFillHandle && (\n <div\n className=\"spreadsheet-fill-handle\"\n aria-label=\"Fill handle\"\n onMouseDown={startFill}\n onClick={(e) => e.stopPropagation()}\n style={{ position: 'absolute', right: 0, bottom: 0, width: 7, height: 7, background: 'var(--primary, #6366f1)', cursor: 'crosshair', zIndex: 25 }}\n />\n )}\n </td>\n );\n })}\n {onAddColumnClick && <td className=\"w-10 min-w-[2.5rem] bg-muted/10 border-r border-border\" />}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n {menu && (\n <SpreadsheetContextMenu\n items={menu.items}\n x={menu.x}\n y={menu.y}\n onClose={() => {\n setMenu(null);\n gridRef.current?.focus();\n }}\n />\n )}\n <style>{`\n .col-resize-handle:hover .col-resize-handle-line {\n background-color: var(--primary, #6366f1);\n opacity: 0.75;\n }\n .col-resize-handle.active .col-resize-handle-line {\n background-color: var(--primary, #6366f1);\n opacity: 1;\n }\n table.table-fixed th {\n overflow: hidden;\n }\n table.table-fixed td {\n max-width: 0;\n overflow: hidden;\n }\n `}</style>\n </div>\n );\n};\n","import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { clampMenuPosition, type SpreadsheetMenuItem } from '@pixerate/editor/spreadsheet';\n\n// Gap kept between the menu and the viewport edges.\nconst VIEWPORT_MARGIN = 4;\n\nexport interface SpreadsheetContextMenuProps {\n items: SpreadsheetMenuItem[];\n x: number;\n y: number;\n onClose: () => void;\n}\n\n/** The table context menu (sort, filter, freeze, hide, merge, categories, transpose). */\nexport const SpreadsheetContextMenu: React.FC<SpreadsheetContextMenuProps> = ({ items, x, y, onClose }) => {\n const menuRef = useRef<HTMLDivElement>(null);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n const [position, setPosition] = useState({ x, y });\n\n // Keep the (fixed) menu inside the viewport: near the right or bottom edge\n // it opens to the left of / above the pointer instead of being cut off.\n useLayoutEffect(() => {\n const menu = menuRef.current;\n if (!menu || typeof window === 'undefined') return;\n const { width, height } = menu.getBoundingClientRect();\n const next = clampMenuPosition(\n { x, y },\n { width, height },\n { width: window.innerWidth, height: window.innerHeight },\n VIEWPORT_MARGIN\n );\n setPosition((prev) => (prev.x === next.x && prev.y === next.y ? prev : next));\n }, [x, y, items]);\n\n useEffect(() => {\n const handlePointer = (e: MouseEvent) => {\n if (!menuRef.current?.contains(e.target as Node)) onCloseRef.current();\n };\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onCloseRef.current();\n };\n window.addEventListener('mousedown', handlePointer);\n window.addEventListener('keydown', handleKey);\n return () => {\n window.removeEventListener('mousedown', handlePointer);\n window.removeEventListener('keydown', handleKey);\n };\n }, []);\n\n return (\n <div\n ref={menuRef}\n role=\"menu\"\n aria-label=\"Table actions\"\n className=\"fixed z-50 min-w-[14rem] rounded-md border border-border bg-popover py-1 text-xs text-popover-foreground shadow-lg\"\n style={{\n left: position.x,\n top: position.y,\n maxHeight: `calc(100vh - ${VIEWPORT_MARGIN * 2}px)`,\n overflowY: 'auto',\n background: 'var(--popover, var(--background, #fff))'\n }}\n onContextMenu={(e) => e.preventDefault()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n {items.map((item) => (\n <React.Fragment key={item.id}>\n {item.separatorBefore && <div role=\"separator\" className=\"my-1 h-px bg-border\" />}\n <button\n type=\"button\"\n role=\"menuitem\"\n data-action={item.id}\n disabled={item.disabled}\n className=\"block w-full px-3 py-1 text-left hover:bg-muted disabled:cursor-default disabled:opacity-40 disabled:hover:bg-transparent\"\n onClick={() => {\n onClose();\n item.run();\n }}\n >\n {item.label}\n </button>\n </React.Fragment>\n ))}\n </div>\n );\n};\n","import React from 'react';\nimport type { SpreadsheetRowGroup, SpreadsheetViewColumn } from '@pixerate/editor/spreadsheet';\n\nexport interface SpreadsheetGroupRowProps {\n group: SpreadsheetRowGroup;\n columns: SpreadsheetViewColumn[];\n /** Column the rows are grouped by: shows the group label and toggle. */\n groupColId: string;\n onToggle: (key: string) => void;\n /** Render a trailing cell for the \"add column\" column. */\n trailingCell?: boolean;\n}\n\nconst formatSummary = (value: number | null) => (value === null ? '–' : String(value));\n\n/** A category header row: collapse toggle, label, row count and per-column summaries. */\nexport const SpreadsheetGroupRow: React.FC<SpreadsheetGroupRowProps> = ({\n group,\n columns,\n groupColId,\n onToggle,\n trailingCell\n}) => {\n // The label goes in the grouping column, or the first column when that one is hidden.\n const labelColId = columns.some((c) => c.column.id === groupColId) ? groupColId : columns[0]?.column.id;\n return (\n <tr className=\"border-b border-border bg-muted/40 font-semibold\" data-group-key={group.key} style={{ height: 28 }}>\n <td className=\"w-12 min-w-[3rem] sticky left-0 z-10 bg-muted border-r border-border text-center\">\n <button\n type=\"button\"\n aria-label={`${group.collapsed ? 'Expand' : 'Collapse'} group ${group.label}`}\n aria-expanded={!group.collapsed}\n className=\"h-5 w-5 rounded text-[10px] text-muted-foreground hover:bg-muted\"\n onClick={(e) => {\n e.stopPropagation();\n onToggle(group.key);\n }}\n >\n {group.collapsed ? '▸' : '▾'}\n </button>\n </td>\n {columns.map(({ column }) => {\n const summary = group.summaries[column.id];\n return (\n <td key={column.id} className=\"border-r border-border px-2 py-1 truncate max-w-0 text-foreground\" style={{ maxWidth: 0, overflow: 'hidden' }}>\n {column.id === labelColId ? (\n <span className=\"truncate\">\n {group.label} <span className=\"font-normal text-muted-foreground\">({group.rowIndices.length})</span>\n </span>\n ) : summary !== undefined ? (\n <span className=\"truncate\" data-summary={column.id}>{formatSummary(summary)}</span>\n ) : null}\n </td>\n );\n })}\n {trailingCell && <td className=\"w-10 min-w-[2.5rem] bg-muted/10 border-r border-border\" />}\n </tr>\n );\n};\n","import { useCallback, useEffect, useRef, useState, type RefObject } from 'react';\nimport {\n computeFillTarget,\n normalizeRange,\n type CellRange\n} from '@pixerate/editor/spreadsheet';\nimport type { useSpreadsheetEditor } from './useSpreadsheetEditor';\n\ntype SpreadsheetState = ReturnType<typeof useSpreadsheetEditor>;\n\n/** True when focus is in the grid itself, not in a text input (cell editor, formula bar). */\nfunction gridHasFocus(grid: HTMLElement | null): boolean {\n if (!grid || typeof document === 'undefined') return false;\n const active = document.activeElement;\n if (!active || !grid.contains(active)) return false;\n return !(active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement);\n}\n\n/**\n * Copy and paste for the grid. Copy writes TSV, an HTML table and the\n * lossless `application/x.pixerate.spreadsheet+json` format; paste prefers\n * that format, then HTML, then TSV.\n *\n * The listeners are on `document`: with no text selection the browser fires\n * `copy`/`paste` at `<body>`, not at the focused grid. Text inputs inside the\n * grid keep native copy/paste.\n */\nexport function useSpreadsheetClipboard(\n gridRef: RefObject<HTMLElement | null>,\n state: SpreadsheetState,\n readOnly: boolean\n) {\n const stateRef = useRef(state);\n stateRef.current = state;\n const readOnlyRef = useRef(readOnly);\n readOnlyRef.current = readOnly;\n // Set when a copy event wrote the selection, so the keyboard fallback is skipped.\n const copiedRef = useRef(false);\n\n useEffect(() => {\n if (typeof document === 'undefined') return;\n const handleCopy = (e: ClipboardEvent) => {\n const s = stateRef.current;\n if (!gridHasFocus(gridRef.current) || s.editingCell || !e.clipboardData || !s.selectedRange) return;\n for (const [type, data] of Object.entries(s.copyToClipboardData(s.selectedRange))) {\n e.clipboardData.setData(type, data);\n }\n copiedRef.current = true;\n e.preventDefault();\n };\n const handlePaste = (e: ClipboardEvent) => {\n const s = stateRef.current;\n if (readOnlyRef.current || !gridHasFocus(gridRef.current) || s.editingCell || !e.clipboardData) return;\n if (s.pasteClipboardData(e.clipboardData)) e.preventDefault();\n };\n document.addEventListener('copy', handleCopy);\n document.addEventListener('paste', handlePaste);\n return () => {\n document.removeEventListener('copy', handleCopy);\n document.removeEventListener('paste', handlePaste);\n };\n }, [gridRef]);\n\n /**\n * Call on Mod+C (without preventing default). The browser normally follows\n * with a `copy` event; where it doesn't (no selection in some browsers),\n * the selection is written as plain TSV instead.\n */\n const copyShortcutFallback = useCallback(() => {\n copiedRef.current = false;\n setTimeout(() => {\n if (copiedRef.current) return;\n const s = stateRef.current;\n // Rejected when clipboard access is denied; nothing else to fall back to.\n Promise.resolve(navigator.clipboard?.writeText(s.exportToTsv(s.selectedRange))).catch(() => {});\n }, 0);\n }, []);\n\n return { copyShortcutFallback };\n}\n\n/**\n * Fill handle dragging: press on the handle, move over cells, release to\n * autofill from the selection into the dragged range (one undo step).\n */\nexport function useFillHandle(state: SpreadsheetState) {\n const [drag, setDrag] = useState<{ source: CellRange; target: CellRange | null } | null>(null);\n const dragRef = useRef(drag);\n dragRef.current = drag;\n const stateRef = useRef(state);\n stateRef.current = state;\n const dragging = drag !== null;\n\n useEffect(() => {\n if (!dragging) return;\n const handleMouseUp = () => {\n const current = dragRef.current;\n setDrag(null);\n if (current?.target) stateRef.current.autofill(current.source, current.target);\n };\n window.addEventListener('mouseup', handleMouseUp);\n return () => window.removeEventListener('mouseup', handleMouseUp);\n }, [dragging]);\n\n const startFill = useCallback((e: { preventDefault(): void; stopPropagation(): void }) => {\n e.preventDefault();\n e.stopPropagation();\n const range = stateRef.current.selectedRange;\n if (range) setDrag({ source: normalizeRange(range), target: null });\n }, []);\n\n const extendFill = useCallback((row: number, col: number) => {\n const current = dragRef.current;\n if (!current) return;\n setDrag({ source: current.source, target: computeFillTarget(current.source, { row, col }) });\n }, []);\n\n return { fillTarget: drag?.target ?? null, isFilling: dragging, startFill, extendFill };\n}\n","import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { applyFormulaSuggestion, getFormulaHints } from '@pixerate/editor/spreadsheet';\n\nexport interface FormulaHintsProps {\n /** The input being edited (a cell editor or the formula bar). */\n inputRef: React.RefObject<HTMLInputElement | null>;\n /** The input's current value. */\n value: string;\n /** Called with the new value when a suggestion is accepted. */\n onAccept: (value: string) => void;\n /** Maximum number of function suggestions (default 8). */\n limit?: number;\n}\n\n/**\n * Formula autocomplete for an input: while the value starts with `=`, lists\n * functions matching the name at the caret (name, signature, description) and,\n * inside a call, shows the signature with the current argument highlighted.\n *\n * Keys are handled on the input itself, before the grid sees them: ArrowUp /\n * ArrowDown move the selection, Tab accepts it, Escape closes the list.\n * Enter is left alone so it still commits the cell.\n */\nexport const FormulaHints: React.FC<FormulaHintsProps> = ({ inputRef, value, onAccept, limit = 8 }) => {\n const [caret, setCaret] = useState<number | null>(null);\n const [focused, setFocused] = useState(false);\n const [selected, setSelected] = useState(0);\n const [dismissed, setDismissed] = useState(false);\n const [position, setPosition] = useState<{ top: number; left: number; width: number } | null>(null);\n const pendingCaret = useRef<number | null>(null);\n\n const hints = useMemo(\n () => getFormulaHints(value, caret ?? value.length, { limit }),\n [value, caret, limit],\n );\n const suggestions = dismissed ? [] : hints.suggestions;\n const selectedIndex = Math.max(0, Math.min(selected, suggestions.length - 1));\n const visible = focused && value.trimStart().startsWith('=') && (suggestions.length > 0 || !!hints.activeCall);\n\n // The key listener reads the latest state through a ref.\n const latest = useRef({ suggestions, selected: selectedIndex, value, caret, onAccept });\n latest.current = { suggestions, selected: selectedIndex, value, caret, onAccept };\n\n const accept = (index: number) => {\n const { suggestions: list, value: current, caret: at, onAccept: commit } = latest.current;\n const suggestion = list[index];\n if (!suggestion) return;\n const next = applyFormulaSuggestion(current, at ?? current.length, suggestion.name);\n pendingCaret.current = next.caret;\n commit(next.value);\n };\n\n useEffect(() => {\n const input = inputRef.current;\n if (!input) return;\n const syncCaret = () => setCaret(input.selectionStart ?? input.value.length);\n const onInput = () => {\n setDismissed(false);\n setSelected(0);\n syncCaret();\n };\n const onFocus = () => {\n setFocused(true);\n syncCaret();\n };\n const onBlur = () => setFocused(false);\n // A native listener on the input runs before React's delegated handlers,\n // so stopping propagation keeps these keys away from the grid.\n const onKeyDown = (e: KeyboardEvent) => {\n const { suggestions: list } = latest.current;\n if (list.length === 0) return;\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n e.stopPropagation();\n const step = e.key === 'ArrowDown' ? 1 : -1;\n setSelected((i) => (i + step + list.length) % list.length);\n } else if (e.key === 'Tab' && !e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n accept(latest.current.selected);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n setDismissed(true);\n }\n };\n\n input.addEventListener('input', onInput);\n input.addEventListener('keyup', syncCaret);\n input.addEventListener('click', syncCaret);\n input.addEventListener('select', syncCaret);\n input.addEventListener('focus', onFocus);\n input.addEventListener('blur', onBlur);\n input.addEventListener('keydown', onKeyDown);\n // Inputs focused on mount (autoFocus) fired `focus` before this effect ran.\n if (typeof document !== 'undefined' && document.activeElement === input) onFocus();\n return () => {\n input.removeEventListener('input', onInput);\n input.removeEventListener('keyup', syncCaret);\n input.removeEventListener('click', syncCaret);\n input.removeEventListener('select', syncCaret);\n input.removeEventListener('focus', onFocus);\n input.removeEventListener('blur', onBlur);\n input.removeEventListener('keydown', onKeyDown);\n };\n }, [inputRef]);\n\n // After accepting, put the caret inside the inserted parenthesis.\n useLayoutEffect(() => {\n const input = inputRef.current;\n const at = pendingCaret.current;\n if (!input || at === null || input.value !== value) return;\n pendingCaret.current = null;\n input.setSelectionRange(at, at);\n setCaret(at);\n setSelected(0);\n }, [value, inputRef]);\n\n useLayoutEffect(() => {\n const input = inputRef.current;\n if (!visible || !input) return;\n const rect = input.getBoundingClientRect();\n setPosition({ top: rect.bottom + 2, left: rect.left, width: rect.width });\n }, [visible, value, inputRef]);\n\n if (!visible) return null;\n\n const { activeCall } = hints;\n return (\n <div\n data-formula-hints=\"\"\n className=\"rounded-md border border-border bg-popover text-popover-foreground shadow-md text-xs font-sans overflow-hidden\"\n style={{\n position: 'fixed',\n top: position?.top ?? 0,\n left: position?.left ?? 0,\n minWidth: Math.max(260, position?.width ?? 0),\n maxWidth: 440,\n zIndex: 50,\n visibility: position ? 'visible' : 'hidden'\n }}\n onMouseDown={(e) => e.preventDefault()}\n >\n {activeCall && (\n <div data-formula-signature=\"\" className=\"px-2 py-1.5 border-b border-border bg-muted/30\">\n <div className=\"font-mono\">\n {activeCall.parts.map((part, i) => (\n <span\n key={i}\n data-active={part.active ? '' : undefined}\n className={part.active ? 'font-bold text-primary underline' : ''}\n >\n {part.text}\n </span>\n ))}\n </div>\n <div className=\"mt-0.5 text-muted-foreground\">\n {activeCall.argument ? (\n <>\n <span className=\"font-semibold\">{activeCall.argument.name}</span>: {activeCall.argument.description}\n </>\n ) : (\n activeCall.description\n )}\n </div>\n </div>\n )}\n {suggestions.length > 0 && (\n <ul role=\"listbox\" aria-label=\"Formula suggestions\" className=\"max-h-64 overflow-auto py-1 m-0 list-none p-0\">\n {suggestions.map((s, i) => (\n <li\n key={s.name}\n role=\"option\"\n aria-selected={i === selectedIndex}\n className={`cursor-pointer px-2 py-1 ${i === selectedIndex ? 'bg-primary/10' : 'hover:bg-muted/50'}`}\n onMouseEnter={() => setSelected(i)}\n onMouseDown={(e) => {\n // Keep focus in the input so the edit isn't committed by blur.\n e.preventDefault();\n accept(i);\n }}\n >\n <div className=\"font-mono font-semibold text-foreground\">{s.signature}</div>\n <div className=\"text-muted-foreground truncate\">{s.description}</div>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n","import React, { createContext, useContext, useMemo } from 'react';\nimport type {\n\tButtonSlotProps,\n\tEditorSlotsMap,\n\tNodeHeaderSlotProps,\n\tTooltipSlotProps\n} from '@pixerate/editor';\n\nconst defaultSlots: EditorSlotsMap = {\n\tButton: (props: ButtonSlotProps) => (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={`pixerate-btn ${props.className || ''}`}\n\t\t\tonClick={props.onClick}\n\t\t\tdisabled={props.disabled}\n\t\t>\n\t\t\t{props.children}\n\t\t</button>\n\t),\n\tTooltip: (props: TooltipSlotProps) => (\n\t\t<div className={`pixerate-tooltip-container ${props.className || ''}`} title={String(props.content)}>\n\t\t\t{props.children}\n\t\t</div>\n\t),\n\tNodeHeader: (props: NodeHeaderSlotProps) => (\n\t\t<div className={`pixerate-node-header flex items-center justify-between ${props.className || ''}`}>\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t{props.icon}\n\t\t\t\t<span className=\"font-semibold\">{props.title}</span>\n\t\t\t</div>\n\t\t\t{props.onClose && (\n\t\t\t\t<button type=\"button\" onClick={props.onClose} className=\"opacity-70 hover:opacity-100\">\n\t\t\t\t\t×\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t)\n};\n\nconst EditorSlotsContext = createContext<EditorSlotsMap>(defaultSlots);\n\nexport interface EditorSlotsProviderProps {\n\tslots?: Partial<EditorSlotsMap>;\n\tchildren: React.ReactNode;\n}\n\n/**\n * Context provider allowing consumers to inject custom design system components into the editor.\n */\nexport function EditorSlotsProvider({ slots, children }: EditorSlotsProviderProps) {\n\tconst mergedSlots = useMemo(() => ({ ...defaultSlots, ...slots }), [slots]);\n\n\treturn (\n\t\t<EditorSlotsContext.Provider value={mergedSlots}>\n\t\t\t{children}\n\t\t</EditorSlotsContext.Provider>\n\t);\n}\n\n/**\n * Hook to access injected design system slots.\n */\nexport function useEditorSlots(): EditorSlotsMap {\n\treturn useContext(EditorSlotsContext);\n}\n","import { useRef, useState, useEffect, useCallback, useMemo } from 'react';\nimport {\n ImageEditorController,\n type ImageEditorOptions,\n type ImageEditorState,\n type ImageEditorTool,\n type CropBox,\n type AspectRatio,\n type ImageAdjustments,\n type DepthMaskOptions,\n type Annotation,\n type CreateAnnotationPayload,\n type ExportOptions,\n type SerializedImageEditorState,\n type ImagePoint,\n} from '@pixerate/editor/image-editor';\n\nexport interface UseImageEditorReturn {\n controller: ImageEditorController;\n state: ImageEditorState;\n canUndo: boolean;\n canRedo: boolean;\n setTool: (tool: ImageEditorTool) => void;\n setCrop: (crop: CropBox | null, addToHistory?: boolean) => void;\n applyCropPreset: (ratio: AspectRatio) => void;\n resetCrop: () => void;\n rotate: (degrees: number) => void;\n setRotation: (degrees: number) => void;\n flipHorizontal: () => void;\n flipVertical: () => void;\n setAdjustments: (partial: Partial<ImageAdjustments>, commitToHistory?: boolean) => void;\n resetAdjustments: () => void;\n /** Update to Current Process: re-render the adjustments with the latest process (one undo step). */\n upgradeProcess: () => boolean;\n setDepthMask: (partial: Partial<DepthMaskOptions>) => void;\n resetDepthMask: () => void;\n addAnnotation: (annotation: CreateAnnotationPayload) => string;\n updateAnnotation: (id: string, partial: Partial<Annotation>, commitToHistory?: boolean) => void;\n removeAnnotation: (id: string) => void;\n clearAnnotations: () => void;\n selectAnnotation: (id: string | null) => void;\n undo: () => boolean;\n redo: () => boolean;\n reset: () => void;\n zoomIn: (factor?: number) => void;\n zoomOut: (factor?: number) => void;\n resetZoom: () => void;\n setZoom: (zoom: number) => void;\n setPan: (pan: ImagePoint) => void;\n setComparing: (comparing: boolean) => void;\n loadImage: (src: string | HTMLImageElement) => Promise<void>;\n toDataURL: (options?: ExportOptions) => Promise<string>;\n toBlob: (options?: ExportOptions) => Promise<Blob>;\n toJSON: () => SerializedImageEditorState;\n loadJSON: (data: SerializedImageEditorState) => void;\n renderMask: (options?: { useAnnotations?: boolean; useCrop?: boolean }) => Promise<HTMLCanvasElement>;\n toMaskDataURL: (options?: { useAnnotations?: boolean; useCrop?: boolean }) => Promise<string>;\n toSourceDataURL: (options?: Pick<ExportOptions, 'format' | 'quality'>) => Promise<string>;\n applyInpaintedImage: (newDataUrl: string) => Promise<void>;\n applyBackgroundRemovedImage: (newDataUrl: string) => Promise<void>;\n}\n\nexport function useImageEditor(options: ImageEditorOptions = {}): UseImageEditorReturn {\n const controllerRef = useRef<ImageEditorController | null>(null);\n\n if (!controllerRef.current) {\n controllerRef.current = new ImageEditorController(options);\n }\n\n const controller = controllerRef.current;\n const [state, setState] = useState<ImageEditorState>(() => controller.getState());\n const [historyTicks, setHistoryTicks] = useState(0);\n\n useEffect(() => {\n const unsub = controller.subscribe((next) => {\n setState(next);\n setHistoryTicks((t) => t + 1);\n });\n return unsub;\n }, [controller]);\n\n // The constructor loads the initial image. Reload only when the `image`\n // option itself changes, not whenever the controller's source differs from\n // it (AI edits replace the source with a data URL and must not be reverted).\n const loadedImageRef = useRef(options.image);\n useEffect(() => {\n if (options.image === loadedImageRef.current) return;\n loadedImageRef.current = options.image;\n if (options.image) {\n controller.loadImage(options.image);\n }\n }, [options.image, controller]);\n\n const setTool = useCallback((tool: ImageEditorTool) => controller.setTool(tool), [controller]);\n const setCrop = useCallback(\n (crop: CropBox | null, addToHistory = true) => controller.setCrop(crop, addToHistory),\n [controller]\n );\n const applyCropPreset = useCallback((ratio: AspectRatio) => controller.applyCropPreset(ratio), [controller]);\n const resetCrop = useCallback(() => controller.resetCrop(), [controller]);\n const rotate = useCallback((deg: number) => controller.rotate(deg), [controller]);\n const setRotation = useCallback((deg: number) => controller.setRotation(deg), [controller]);\n const flipHorizontal = useCallback(() => controller.flipHorizontal(), [controller]);\n const flipVertical = useCallback(() => controller.flipVertical(), [controller]);\n const setAdjustments = useCallback(\n (partial: Partial<ImageAdjustments>, commitToHistory = true) =>\n controller.setAdjustments(partial, commitToHistory),\n [controller]\n );\n const resetAdjustments = useCallback(() => controller.resetAdjustments(), [controller]);\n const upgradeProcess = useCallback(() => controller.upgradeProcess(), [controller]);\n const setDepthMask = useCallback((partial: Partial<DepthMaskOptions>) => controller.setDepthMask(partial), [controller]);\n const resetDepthMask = useCallback(() => controller.resetDepthMask(), [controller]);\n const addAnnotation = useCallback((ann: CreateAnnotationPayload) => controller.addAnnotation(ann), [controller]);\n const updateAnnotation = useCallback(\n (id: string, partial: Partial<Annotation>, commitToHistory = true) =>\n controller.updateAnnotation(id, partial, commitToHistory),\n [controller]\n );\n const removeAnnotation = useCallback((id: string) => controller.removeAnnotation(id), [controller]);\n const clearAnnotations = useCallback(() => controller.clearAnnotations(), [controller]);\n const selectAnnotation = useCallback((id: string | null) => controller.selectAnnotation(id), [controller]);\n const undo = useCallback(() => controller.undo(), [controller]);\n const redo = useCallback(() => controller.redo(), [controller]);\n const reset = useCallback(() => controller.reset(), [controller]);\n const zoomIn = useCallback((factor?: number) => controller.zoomIn(factor), [controller]);\n const zoomOut = useCallback((factor?: number) => controller.zoomOut(factor), [controller]);\n const resetZoom = useCallback(() => controller.resetZoom(), [controller]);\n const setZoom = useCallback((zoom: number) => controller.setZoom(zoom), [controller]);\n const setPan = useCallback((pan: ImagePoint) => controller.setPan(pan), [controller]);\n const setComparing = useCallback((comp: boolean) => controller.setComparing(comp), [controller]);\n const loadImage = useCallback((src: string | HTMLImageElement) => controller.loadImage(src), [controller]);\n const toDataURL = useCallback((opts?: ExportOptions) => controller.toDataURL(opts), [controller]);\n const toBlob = useCallback((opts?: ExportOptions) => controller.toBlob(opts), [controller]);\n const toJSON = useCallback(() => controller.toJSON(), [controller]);\n const loadJSON = useCallback((data: SerializedImageEditorState) => controller.loadJSON(data), [controller]);\n const renderMask = useCallback(\n (opts?: { useAnnotations?: boolean; useCrop?: boolean }) => controller.renderMask(opts),\n [controller]\n );\n const toMaskDataURL = useCallback(\n (opts?: { useAnnotations?: boolean; useCrop?: boolean }) => controller.toMaskDataURL(opts),\n [controller]\n );\n const toSourceDataURL = useCallback(\n (opts?: Pick<ExportOptions, 'format' | 'quality'>) => controller.toSourceDataURL(opts),\n [controller]\n );\n const applyInpaintedImage = useCallback(\n (newDataUrl: string) => controller.applyInpaintedImage(newDataUrl),\n [controller]\n );\n const applyBackgroundRemovedImage = useCallback(\n (newDataUrl: string) => controller.applyBackgroundRemovedImage(newDataUrl),\n [controller]\n );\n\n return useMemo(\n () => ({\n controller,\n state,\n canUndo: controller.canUndo,\n canRedo: controller.canRedo,\n setTool,\n setCrop,\n applyCropPreset,\n resetCrop,\n rotate,\n setRotation,\n flipHorizontal,\n flipVertical,\n setAdjustments,\n resetAdjustments,\n upgradeProcess,\n setDepthMask,\n resetDepthMask,\n addAnnotation,\n updateAnnotation,\n removeAnnotation,\n clearAnnotations,\n selectAnnotation,\n undo,\n redo,\n reset,\n zoomIn,\n zoomOut,\n resetZoom,\n setZoom,\n setPan,\n setComparing,\n loadImage,\n toDataURL,\n toBlob,\n toJSON,\n loadJSON,\n renderMask,\n toMaskDataURL,\n toSourceDataURL,\n applyInpaintedImage,\n applyBackgroundRemovedImage,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [controller, state, historyTicks]\n );\n}\n","import React, { useRef, useEffect, useState, useCallback } from 'react';\nimport type {\n Annotation,\n CropBox,\n CropHandle,\n ExportOptions,\n ImageEditorTool,\n ImagePoint,\n InpaintHook,\n RemoveBackgroundHook,\n ImageEditorAIHooks,\n} from '@pixerate/editor/image-editor';\nimport {\n canvasToImagePoint,\n hitTestCrop,\n getCropCursor,\n calculateCropDrag,\n hitTestAnnotation,\n normalizeProcessVersion,\n LATEST_PROCESS_VERSION,\n} from '@pixerate/editor/image-editor';\nimport { useImageEditor, type UseImageEditorReturn } from './useImageEditor';\n\nexport interface ImageEditorProps {\n editor?: UseImageEditorReturn;\n src?: string;\n className?: string;\n style?: React.CSSProperties;\n onSave?: (dataUrl: string) => void;\n exportOptions?: ExportOptions;\n onInpaint?: InpaintHook;\n onRemoveBackground?: RemoveBackgroundHook;\n aiHooks?: ImageEditorAIHooks;\n}\n\ntype TabType = 'crop' | 'adjust' | 'annotate' | 'depth' | 'ai';\n\nexport const ImageEditor: React.FC<ImageEditorProps> = ({\n editor: externalEditor,\n src,\n className = '',\n style,\n onSave,\n exportOptions,\n onInpaint,\n onRemoveBackground,\n aiHooks,\n}) => {\n const internalEditor = useImageEditor({ image: src });\n const editor = externalEditor || internalEditor;\n const { state, controller } = editor;\n const legacyProcess = normalizeProcessVersion(state.adjustments.process) < LATEST_PROCESS_VERSION;\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const [activeTab, setActiveTab] = useState<TabType>('crop');\n const [activeCropRatio, setActiveCropRatio] = useState<number | null>(null);\n\n // AI Tools state\n const [inpaintPrompt, setInpaintPrompt] = useState('');\n const [inpaintMaskMode, setInpaintMaskMode] = useState<'annotations' | 'crop'>('annotations');\n const [isRemovingBg, setIsRemovingBg] = useState(false);\n const [isInpainting, setIsInpainting] = useState(false);\n const [aiError, setAiError] = useState<string | null>(null);\n const [aiSuccess, setAiSuccess] = useState<string | null>(null);\n\n const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;\n const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;\n\n const handleRemoveBackground = async () => {\n if (!effectiveOnRemoveBg) {\n setAiError('No background removal hook is configured.');\n return;\n }\n setAiError(null);\n setAiSuccess(null);\n setIsRemovingBg(true);\n try {\n // AI hooks work on the untransformed source image (natural pixels); crop, rotation,\n // adjustments and annotations stay non-destructive and are re-applied on top.\n const imageDataUrl = await editor.toSourceDataURL();\n const result = await effectiveOnRemoveBg({ imageDataUrl });\n if (typeof result === 'string') {\n await editor.applyBackgroundRemovedImage(result);\n setAiSuccess('Background removed successfully!');\n } else {\n setAiSuccess('Background removal complete.');\n }\n } catch (err: any) {\n setAiError(err?.message || 'Failed to remove background.');\n } finally {\n setIsRemovingBg(false);\n }\n };\n\n const handleInpaint = async () => {\n if (!effectiveOnInpaint) {\n setAiError('No inpainting hook is configured.');\n return;\n }\n if (!inpaintPrompt.trim()) {\n setAiError('Please enter an inpainting prompt.');\n return;\n }\n setAiError(null);\n setAiSuccess(null);\n setIsInpainting(true);\n try {\n // Source image and mask share natural image space so they line up exactly.\n const imageDataUrl = await editor.toSourceDataURL();\n const maskDataUrl = await editor.toMaskDataURL({\n useAnnotations: inpaintMaskMode === 'annotations',\n useCrop: inpaintMaskMode === 'crop',\n });\n const result = await effectiveOnInpaint({\n prompt: inpaintPrompt.trim(),\n imageDataUrl,\n maskDataUrl,\n cropBox: inpaintMaskMode === 'crop' ? editor.state.crop : null,\n });\n if (typeof result === 'string') {\n await editor.applyInpaintedImage(result);\n setAiSuccess('Inpainting applied successfully!');\n } else {\n setAiSuccess('Inpainting complete.');\n }\n } catch (err: any) {\n setAiError(err?.message || 'Failed to apply inpainting.');\n } finally {\n setIsInpainting(false);\n }\n };\n\n // Annotation drafting state\n const [activeColor, setActiveColor] = useState('#ef4444');\n const [strokeWidth, setStrokeWidth] = useState(3);\n const [fontSize, setFontSize] = useState(24);\n const [textInput, setTextInput] = useState('');\n\n // Live draft and drag references\n const draftAnnotationRef = useRef<Annotation | null>(null);\n const draftCropRef = useRef<CropBox | null>(null);\n const cropDragInfoRef = useRef<{\n handle: CropHandle | 'new';\n startCanvasPt: ImagePoint;\n startImgPt: ImagePoint;\n startCrop: CropBox;\n } | null>(null);\n const annotationDragInfoRef = useRef<{\n annId: string;\n startImgPt: ImagePoint;\n initialAnn: Annotation;\n } | null>(null);\n const isDrawingRef = useRef(false);\n const currentPathRef = useRef<ImagePoint[]>([]);\n const dragStartPointRef = useRef<ImagePoint | null>(null);\n\n // Canvas viewport sizing and re-render\n const renderCanvas = useCallback(\n async (draftAnnotation?: Annotation | null, draftCrop?: CropBox | null) => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const vpWidth = container.clientWidth || 800;\n const vpHeight = container.clientHeight || 500;\n\n await controller.render(canvas, {\n viewportWidth: vpWidth,\n viewportHeight: vpHeight,\n showCropOverlay: activeTab === 'crop',\n showSelectionOverlay: true,\n interactive: true,\n draftAnnotation: draftAnnotation !== undefined ? draftAnnotation : draftAnnotationRef.current,\n draftCrop: draftCrop !== undefined ? draftCrop : draftCropRef.current,\n });\n },\n [controller, activeTab]\n );\n\n useEffect(() => {\n const raf =\n typeof requestAnimationFrame !== 'undefined'\n ? requestAnimationFrame\n : (cb: () => void) => setTimeout(cb, 0) as unknown as number;\n const caf =\n typeof cancelAnimationFrame !== 'undefined'\n ? cancelAnimationFrame\n : (id: number) => clearTimeout(id);\n\n const animId = raf(() => {\n renderCanvas();\n });\n return () => caf(animId);\n }, [renderCanvas, state]);\n\n // Synchronize initial tool with activeTab\n useEffect(() => {\n if (activeTab === 'crop' && editor.state.activeTool !== 'crop') {\n editor.setTool('crop');\n }\n }, [activeTab, editor]);\n\n // Container resize observer to safely adapt viewport without feedback loops\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(() => {\n renderCanvas();\n });\n observer.observe(container);\n return () => observer.disconnect();\n } else {\n const handleResize = () => renderCanvas();\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }\n }, [renderCanvas]);\n\n // Convert mouse event coordinates to internal canvas pixel space\n const getCanvasEventPoint = (e: React.MouseEvent<HTMLCanvasElement>): ImagePoint => {\n const canvas = canvasRef.current;\n if (!canvas) return { x: 0, y: 0 };\n const rect = canvas.getBoundingClientRect();\n const scaleX = rect.width > 0 ? canvas.width / rect.width : 1;\n const scaleY = rect.height > 0 ? canvas.height / rect.height : 1;\n return {\n x: (e.clientX - rect.left) * scaleX,\n y: (e.clientY - rect.top) * scaleY,\n };\n };\n\n // Pointer event handlers for drawing and annotations\n const handleMouseDown = (e: React.MouseEvent<HTMLCanvasElement>) => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const canvasPt = getCanvasEventPoint(e);\n\n if (activeTab === 'crop') {\n const activeCrop = draftCropRef.current || state.crop || {\n x: 0,\n y: 0,\n width: state.imageDimensions.width,\n height: state.imageDimensions.height,\n };\n const handle = hitTestCrop(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);\n const startImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, true);\n\n if (handle) {\n cropDragInfoRef.current = {\n handle,\n startCanvasPt: canvasPt,\n startImgPt,\n startCrop: activeCrop,\n };\n } else {\n // Clicked outside crop box: start new crop selection\n cropDragInfoRef.current = {\n handle: 'new',\n startCanvasPt: canvasPt,\n startImgPt,\n startCrop: { x: startImgPt.x, y: startImgPt.y, width: 0, height: 0 },\n };\n }\n return;\n }\n\n if (activeTab === 'annotate') {\n const imgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n dragStartPointRef.current = imgPt;\n\n if (state.activeTool === 'select') {\n for (let i = state.annotations.length - 1; i >= 0; i--) {\n const ann = state.annotations[i];\n if (hitTestAnnotation(imgPt, ann)) {\n editor.selectAnnotation(ann.id);\n annotationDragInfoRef.current = {\n annId: ann.id,\n startImgPt: imgPt,\n initialAnn: { ...ann },\n };\n return;\n }\n }\n editor.selectAnnotation(null);\n return;\n }\n\n if (state.activeTool === 'pen') {\n isDrawingRef.current = true;\n currentPathRef.current = [imgPt];\n const draft: Annotation = {\n id: 'draft',\n type: 'pen',\n x: 0,\n y: 0,\n points: [imgPt],\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n }\n }\n };\n\n const handleMouseMove = (e: React.MouseEvent<HTMLCanvasElement>) => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const canvasPt = getCanvasEventPoint(e);\n\n if (activeTab === 'crop') {\n const drag = cropDragInfoRef.current;\n if (drag) {\n const currentImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, true);\n let newCrop: CropBox;\n\n if (drag.handle === 'new') {\n const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));\n const minY = Math.max(0, Math.min(drag.startImgPt.y, currentImgPt.y));\n const maxX = Math.min(state.imageDimensions.width, Math.max(drag.startImgPt.x, currentImgPt.x));\n const maxY = Math.min(state.imageDimensions.height, Math.max(drag.startImgPt.y, currentImgPt.y));\n newCrop = {\n x: Math.round(minX),\n y: Math.round(minY),\n width: Math.round(Math.max(20, maxX - minX)),\n height: Math.round(Math.max(20, maxY - minY)),\n };\n } else {\n newCrop = calculateCropDrag(\n drag.startCrop,\n drag.handle,\n drag.startImgPt,\n currentImgPt,\n state.imageDimensions.width,\n state.imageDimensions.height,\n activeCropRatio,\n state.transform\n );\n }\n\n draftCropRef.current = newCrop;\n renderCanvas(null, newCrop);\n } else {\n const activeCrop = draftCropRef.current || state.crop || {\n x: 0,\n y: 0,\n width: state.imageDimensions.width,\n height: state.imageDimensions.height,\n };\n const handle = hitTestCrop(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);\n canvas.style.cursor = getCropCursor(handle, state.transform);\n }\n return;\n }\n\n if (activeTab === 'annotate') {\n // If moving selected annotation\n if (annotationDragInfoRef.current) {\n const drag = annotationDragInfoRef.current;\n const currentImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n const dx = currentImgPt.x - drag.startImgPt.x;\n const dy = currentImgPt.y - drag.startImgPt.y;\n editor.updateAnnotation(drag.annId, {\n x: Math.round(drag.initialAnn.x + dx),\n y: Math.round(drag.initialAnn.y + dy),\n });\n return;\n }\n\n const startPt = dragStartPointRef.current;\n if (!startPt) {\n // Update cursor for hover on select tool\n if (state.activeTool === 'select') {\n const imgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n let hovered = false;\n for (let i = state.annotations.length - 1; i >= 0; i--) {\n if (hitTestAnnotation(imgPt, state.annotations[i])) {\n hovered = true;\n break;\n }\n }\n canvas.style.cursor = hovered ? 'move' : 'default';\n } else {\n canvas.style.cursor = 'crosshair';\n }\n return;\n }\n\n const currentImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n\n if (state.activeTool === 'pen' && isDrawingRef.current) {\n currentPathRef.current.push(currentImgPt);\n const draft: Annotation = {\n id: 'draft',\n type: 'pen',\n x: 0,\n y: 0,\n points: [...currentPathRef.current],\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n } else if (state.activeTool === 'rect') {\n const w = currentImgPt.x - startPt.x;\n const h = currentImgPt.y - startPt.y;\n const draft: Annotation = {\n id: 'draft',\n type: 'rect',\n x: Math.min(startPt.x, currentImgPt.x),\n y: Math.min(startPt.y, currentImgPt.y),\n width: Math.abs(w),\n height: Math.abs(h),\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n } else if (state.activeTool === 'circle') {\n const rx = Math.abs(currentImgPt.x - startPt.x) / 2;\n const ry = Math.abs(currentImgPt.y - startPt.y) / 2;\n const draft: Annotation = {\n id: 'draft',\n type: 'circle',\n x: Math.min(startPt.x, currentImgPt.x) + rx,\n y: Math.min(startPt.y, currentImgPt.y) + ry,\n radiusX: rx,\n radiusY: ry,\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n } else if (state.activeTool === 'arrow') {\n const draft: Annotation = {\n id: 'draft',\n type: 'arrow',\n x: startPt.x,\n y: startPt.y,\n endX: currentImgPt.x,\n endY: currentImgPt.y,\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n } else if (state.activeTool === 'line') {\n const draft: Annotation = {\n id: 'draft',\n type: 'line',\n x: startPt.x,\n y: startPt.y,\n endX: currentImgPt.x,\n endY: currentImgPt.y,\n strokeColor: activeColor,\n strokeWidth,\n };\n draftAnnotationRef.current = draft;\n renderCanvas(draft);\n }\n }\n };\n\n const handleMouseUp = (e: React.MouseEvent<HTMLCanvasElement>) => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const canvasPt = getCanvasEventPoint(e);\n\n if (activeTab === 'crop') {\n if (cropDragInfoRef.current) {\n if (\n draftCropRef.current &&\n draftCropRef.current.width >= 20 &&\n draftCropRef.current.height >= 20\n ) {\n editor.setCrop(draftCropRef.current, true);\n }\n cropDragInfoRef.current = null;\n draftCropRef.current = null;\n renderCanvas();\n }\n return;\n }\n\n if (activeTab === 'annotate') {\n if (annotationDragInfoRef.current) {\n annotationDragInfoRef.current = null;\n return;\n }\n\n const startPt = dragStartPointRef.current;\n if (startPt) {\n const currentImgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);\n\n if (state.activeTool === 'pen' && isDrawingRef.current) {\n if (currentPathRef.current.length > 1) {\n editor.addAnnotation({\n type: 'pen',\n x: 0,\n y: 0,\n points: [...currentPathRef.current],\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n isDrawingRef.current = false;\n currentPathRef.current = [];\n } else if (state.activeTool === 'rect') {\n const w = Math.abs(currentImgPt.x - startPt.x);\n const h = Math.abs(currentImgPt.y - startPt.y);\n if (w > 4 && h > 4) {\n editor.addAnnotation({\n type: 'rect',\n x: Math.min(startPt.x, currentImgPt.x),\n y: Math.min(startPt.y, currentImgPt.y),\n width: w,\n height: h,\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n } else if (state.activeTool === 'circle') {\n const rx = Math.abs(currentImgPt.x - startPt.x) / 2;\n const ry = Math.abs(currentImgPt.y - startPt.y) / 2;\n if (rx > 4 && ry > 4) {\n editor.addAnnotation({\n type: 'circle',\n x: Math.min(startPt.x, currentImgPt.x) + rx,\n y: Math.min(startPt.y, currentImgPt.y) + ry,\n radiusX: rx,\n radiusY: ry,\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n } else if (state.activeTool === 'arrow') {\n if (Math.hypot(currentImgPt.x - startPt.x, currentImgPt.y - startPt.y) > 4) {\n editor.addAnnotation({\n type: 'arrow',\n x: startPt.x,\n y: startPt.y,\n endX: currentImgPt.x,\n endY: currentImgPt.y,\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n } else if (state.activeTool === 'line') {\n if (Math.hypot(currentImgPt.x - startPt.x, currentImgPt.y - startPt.y) > 4) {\n editor.addAnnotation({\n type: 'line',\n x: startPt.x,\n y: startPt.y,\n endX: currentImgPt.x,\n endY: currentImgPt.y,\n strokeColor: activeColor,\n strokeWidth,\n });\n }\n }\n\n draftAnnotationRef.current = null;\n dragStartPointRef.current = null;\n renderCanvas();\n }\n }\n };\n\n const handleAddText = () => {\n if (!textInput.trim()) return;\n editor.addAnnotation({\n type: 'text',\n x: 50,\n y: 50,\n text: textInput.trim(),\n fontSize,\n color: activeColor,\n });\n setTextInput('');\n };\n\n const handleExport = async () => {\n const dataUrl = await editor.toDataURL(exportOptions);\n if (onSave) {\n onSave(dataUrl);\n } else {\n // Default download trigger\n const link = document.createElement('a');\n link.download = `edited-image-${Date.now()}.png`;\n link.href = dataUrl;\n link.click();\n }\n };\n\n return (\n <div\n className={`flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`}\n style={style}\n >\n {/* Top Action Header */}\n <div className=\"flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3\">\n {/* Navigation Tabs */}\n <div className=\"flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs\">\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('crop');\n editor.setTool('crop');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors ${\n activeTab === 'crop' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n Transform & Crop\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('adjust');\n editor.setTool('select');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors ${\n activeTab === 'adjust' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n Adjustments\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('annotate');\n editor.setTool('pen');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors ${\n activeTab === 'annotate' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n Annotations\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('depth');\n editor.setTool('select');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors ${\n activeTab === 'depth' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n Depth Mask\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('ai');\n editor.setTool('select');\n }}\n className={`px-3 py-1.5 rounded-md font-medium transition-colors flex items-center gap-1.5 ${\n activeTab === 'ai' ? 'bg-indigo-600 text-white shadow' : 'text-slate-400 hover:text-slate-200'\n }`}\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83\" />\n </svg>\n AI Tools\n </button>\n </div>\n\n {/* Global Action Tools (Undo/Redo, Zoom, Compare, Save) */}\n <div className=\"flex items-center gap-2 text-xs\">\n <button\n type=\"button\"\n disabled={!editor.canUndo}\n onClick={() => editor.undo()}\n className=\"p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-slate-800\"\n title=\"Undo\"\n >\n ↩\n </button>\n <button\n type=\"button\"\n disabled={!editor.canRedo}\n onClick={() => editor.redo()}\n className=\"p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-slate-800\"\n title=\"Redo\"\n >\n ↪\n </button>\n <button\n type=\"button\"\n onClick={() => editor.reset()}\n className=\"px-2 py-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-400 hover:text-slate-200 hover:bg-slate-800\"\n >\n Reset\n </button>\n\n <div className=\"h-4 w-px bg-slate-800 mx-1\" />\n\n {/* Zoom */}\n <button\n type=\"button\"\n onClick={() => editor.zoomOut()}\n className=\"p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 hover:bg-slate-800\"\n title=\"Zoom Out\"\n >\n -\n </button>\n <span className=\"font-mono text-slate-400 w-10 text-center\">{Math.round(state.zoom * 100)}%</span>\n <button\n type=\"button\"\n onClick={() => editor.zoomIn()}\n className=\"p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 hover:bg-slate-800\"\n title=\"Zoom In\"\n >\n +\n </button>\n\n <div className=\"h-4 w-px bg-slate-800 mx-1\" />\n\n {/* Live Compare */}\n <button\n type=\"button\"\n onMouseDown={() => editor.setComparing(true)}\n onMouseUp={() => editor.setComparing(false)}\n onMouseLeave={() => editor.setComparing(false)}\n className=\"px-2.5 py-1.5 rounded-lg border border-slate-800 bg-slate-900 text-amber-400 hover:bg-slate-800 select-none active:bg-amber-950/40\"\n >\n Hold Compare\n </button>\n\n {/* Save / Export */}\n <button\n type=\"button\"\n onClick={handleExport}\n className=\"px-4 py-1.5 rounded-lg bg-emerald-600 hover:bg-emerald-500 text-white font-medium shadow-md shadow-emerald-900/30 transition-colors\"\n >\n Export Image\n </button>\n </div>\n </div>\n\n {/* Main Viewport + Sidebar Layout */}\n <div className=\"flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]\">\n {/* Canvas Area */}\n <div\n ref={containerRef}\n className=\"relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none\"\n >\n <canvas\n ref={canvasRef}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n className=\"absolute inset-0 w-full h-full block\"\n />\n </div>\n\n {/* Tab Controls Sidebar */}\n <div className=\"w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]\">\n {/* TAB 1: CROP & TRANSFORM */}\n {activeTab === 'crop' && (\n <div className=\"flex flex-col gap-4 text-xs\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Aspect Ratio Presets\n </span>\n <div className=\"grid grid-cols-3 gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(null);\n editor.applyCropPreset(null);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === null && state.crop\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n Freeform\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(1);\n editor.applyCropPreset(1);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === 1\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n 1:1 Square\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(4 / 3);\n editor.applyCropPreset(4 / 3);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === 4 / 3\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n 4:3 Standard\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(16 / 9);\n editor.applyCropPreset(16 / 9);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === 16 / 9\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n 16:9 Wide\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(3 / 2);\n editor.applyCropPreset(3 / 2);\n }}\n className={`px-2.5 py-2 rounded-lg border font-medium ${\n activeCropRatio === 3 / 2\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'\n }`}\n >\n 3:2 Photo\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActiveCropRatio(null);\n editor.resetCrop();\n }}\n className=\"px-2.5 py-2 rounded-lg bg-rose-950/40 hover:bg-rose-900/60 text-rose-300 border border-rose-800/40 font-medium\"\n >\n Clear Crop\n </button>\n </div>\n\n <div className=\"h-px bg-slate-800 my-1\" />\n\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Orientation & Flips\n </span>\n <div className=\"grid grid-cols-2 gap-2\">\n <button\n type=\"button\"\n onClick={() => editor.rotate(-90)}\n className=\"px-3 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 border border-slate-700\"\n >\n Rotate -90°\n </button>\n <button\n type=\"button\"\n onClick={() => editor.rotate(90)}\n className=\"px-3 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 border border-slate-700\"\n >\n Rotate +90°\n </button>\n <button\n type=\"button\"\n onClick={() => editor.flipHorizontal()}\n className={`px-3 py-2 rounded-lg border transition-colors ${\n state.transform.flipH\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-200 hover:bg-slate-700'\n }`}\n >\n Flip Horizontal\n </button>\n <button\n type=\"button\"\n onClick={() => editor.flipVertical()}\n className={`px-3 py-2 rounded-lg border transition-colors ${\n state.transform.flipV\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-200 hover:bg-slate-700'\n }`}\n >\n Flip Vertical\n </button>\n </div>\n </div>\n )}\n\n {/* TAB 2: ADJUSTMENTS */}\n {activeTab === 'adjust' && (\n <div className=\"flex flex-col gap-3 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Color Adjustments\n </span>\n <button\n type=\"button\"\n onClick={() => editor.resetAdjustments()}\n className=\"text-[10px] text-rose-400 hover:underline\"\n >\n Reset Sliders\n </button>\n </div>\n\n {/* Brightness */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Brightness</span>\n <span className=\"font-mono\">{state.adjustments.brightness}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.brightness}\n onChange={(e) => editor.setAdjustments({ brightness: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Contrast */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Contrast</span>\n <span className=\"font-mono\">{state.adjustments.contrast}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.contrast}\n onChange={(e) => editor.setAdjustments({ contrast: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Saturation */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Saturation</span>\n <span className=\"font-mono\">{state.adjustments.saturation}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.saturation}\n onChange={(e) => editor.setAdjustments({ saturation: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Exposure */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Exposure</span>\n <span className=\"font-mono\">{state.adjustments.exposure}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.exposure}\n onChange={(e) => editor.setAdjustments({ exposure: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Temperature / Warmth */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Warmth / Temperature</span>\n <span className=\"font-mono\">{state.adjustments.temperature}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n value={state.adjustments.temperature}\n onChange={(e) => editor.setAdjustments({ temperature: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Tint (process 2 white balance) */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Tint</span>\n <span className=\"font-mono\">{state.adjustments.tint ?? 0}</span>\n </div>\n <input\n type=\"range\"\n min=\"-100\"\n max=\"100\"\n aria-label=\"Tint\"\n disabled={legacyProcess}\n value={state.adjustments.tint ?? 0}\n onChange={(e) => editor.setAdjustments({ tint: Number(e.target.value) })}\n className=\"w-full accent-indigo-500 disabled:opacity-40\"\n />\n </div>\n\n {legacyProcess && (\n <div\n className=\"flex items-center justify-between gap-2 rounded border border-amber-500/30 bg-amber-500/10 px-2 py-1.5 text-[10px] text-amber-200\"\n data-testid=\"image-editor-process-notice\"\n >\n <span>Legacy rendering (process 1). Tint needs the current process.</span>\n <button\n type=\"button\"\n onClick={() => editor.upgradeProcess()}\n className=\"shrink-0 rounded bg-amber-500/20 px-2 py-0.5 hover:bg-amber-500/30\"\n >\n Update\n </button>\n </div>\n )}\n\n {/* Blur */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Blur</span>\n <span className=\"font-mono\">{state.adjustments.blur}px</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"30\"\n value={state.adjustments.blur}\n onChange={(e) => editor.setAdjustments({ blur: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n {/* Opacity */}\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Opacity</span>\n <span className=\"font-mono\">{Math.round(state.adjustments.opacity * 100)}%</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n value={state.adjustments.opacity}\n onChange={(e) => editor.setAdjustments({ opacity: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n </div>\n )}\n\n {/* TAB 3: ANNOTATIONS */}\n {activeTab === 'annotate' && (\n <div className=\"flex flex-col gap-3 text-xs\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Draw & Annotate\n </span>\n\n {/* Tool Picker */}\n <div className=\"grid grid-cols-3 gap-1.5\">\n {(['pen', 'rect', 'circle', 'arrow', 'line'] as ImageEditorTool[]).map((t) => (\n <button\n key={t}\n type=\"button\"\n onClick={() => editor.setTool(t)}\n className={`py-1.5 px-2 rounded-lg font-medium capitalize border transition-colors ${\n state.activeTool === t\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-300 hover:bg-slate-700'\n }`}\n >\n {t}\n </button>\n ))}\n </div>\n\n {/* Color & Size */}\n <div className=\"flex items-center gap-2 mt-2\">\n <label className=\"text-slate-400\">Color:</label>\n <input\n type=\"color\"\n value={activeColor}\n onChange={(e) => setActiveColor(e.target.value)}\n className=\"w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent\"\n />\n <div className=\"flex-1 ml-2\">\n <div className=\"flex justify-between text-slate-400 mb-0.5\">\n <span>Width:</span>\n <span className=\"font-mono\">{strokeWidth}px</span>\n </div>\n <input\n type=\"range\"\n min=\"1\"\n max=\"20\"\n value={strokeWidth}\n onChange={(e) => setStrokeWidth(Number(e.target.value))}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n </div>\n\n <div className=\"h-px bg-slate-800 my-1\" />\n\n {/* Text Tool */}\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">Add Text</span>\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n placeholder=\"Type watermark or label...\"\n value={textInput}\n onChange={(e) => setTextInput(e.target.value)}\n onKeyDown={(e) => e.key === 'Enter' && handleAddText()}\n className=\"flex-1 bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1.5 text-xs text-slate-100 placeholder-slate-500 focus:outline-none focus:border-indigo-500\"\n />\n <button\n type=\"button\"\n onClick={handleAddText}\n className=\"px-3 py-1.5 rounded-lg bg-indigo-600 hover:bg-indigo-500 text-white font-medium shadow\"\n >\n Add\n </button>\n </div>\n <div className=\"flex items-center justify-between text-slate-400\">\n <span>Font Size:</span>\n <span className=\"font-mono\">{fontSize}px</span>\n </div>\n <input\n type=\"range\"\n min=\"12\"\n max=\"72\"\n value={fontSize}\n onChange={(e) => setFontSize(Number(e.target.value))}\n className=\"w-full accent-indigo-500\"\n />\n\n {/* Layers & Selected Annotation */}\n <div className=\"h-px bg-slate-800 my-1\" />\n <div className=\"flex items-center justify-between\">\n <span className=\"text-slate-400\">Layers ({state.annotations.length})</span>\n {state.selectedAnnotationId && (\n <button\n type=\"button\"\n onClick={() => editor.removeAnnotation(state.selectedAnnotationId!)}\n className=\"text-rose-400 hover:underline text-[11px]\"\n >\n Delete Selected\n </button>\n )}\n {state.annotations.length > 0 && (\n <button\n type=\"button\"\n onClick={() => editor.clearAnnotations()}\n className=\"text-slate-400 hover:text-slate-200 text-[11px]\"\n >\n Clear All\n </button>\n )}\n </div>\n </div>\n )}\n\n {/* TAB 4: GLEAMFORGE DEPTH MASKING */}\n {activeTab === 'depth' && (\n <div className=\"flex flex-col gap-3 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px]\">\n Depth Masking\n </span>\n <button\n type=\"button\"\n onClick={() => editor.resetDepthMask()}\n className=\"text-[10px] text-rose-400 hover:underline\"\n >\n Reset Mask\n </button>\n </div>\n\n <label className=\"flex items-center gap-2 cursor-pointer text-slate-300\">\n <input\n type=\"checkbox\"\n checked={state.depthMask.enabled}\n onChange={(e) => editor.setDepthMask({ enabled: e.target.checked })}\n className=\"rounded accent-indigo-500\"\n />\n <span>Enable Depth / Alpha Mask</span>\n </label>\n\n {state.depthMask.enabled && (\n <>\n <div>\n <label className=\"text-slate-400 block mb-1\">Mask Image URL:</label>\n <input\n type=\"text\"\n placeholder=\"https://.../depthmap.png\"\n value={state.depthMask.maskSource || ''}\n onChange={(e) => editor.setDepthMask({ maskSource: e.target.value || null })}\n className=\"w-full bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1.5 text-xs text-slate-100 placeholder-slate-500\"\n />\n </div>\n\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={() => editor.setDepthMask({ mode: 'threshold' })}\n className={`flex-1 py-1.5 rounded-lg border text-xs font-medium ${\n state.depthMask.mode === 'threshold'\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-300'\n }`}\n >\n Threshold Mode\n </button>\n <button\n type=\"button\"\n onClick={() => editor.setDepthMask({ mode: 'brightness' })}\n className={`flex-1 py-1.5 rounded-lg border text-xs font-medium ${\n state.depthMask.mode === 'brightness'\n ? 'bg-indigo-600 border-indigo-500 text-white'\n : 'bg-slate-800 border-slate-700 text-slate-300'\n }`}\n >\n Brightness Mode\n </button>\n </div>\n\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Depth Start (Lower):</span>\n <span className=\"font-mono\">{state.depthMask.depthRange[0]}</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"255\"\n value={state.depthMask.depthRange[0]}\n onChange={(e) =>\n editor.setDepthMask({\n depthRange: [Number(e.target.value), state.depthMask.depthRange[1]],\n })\n }\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Depth Stop (Upper):</span>\n <span className=\"font-mono\">{state.depthMask.depthRange[1]}</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"255\"\n value={state.depthMask.depthRange[1]}\n onChange={(e) =>\n editor.setDepthMask({\n depthRange: [state.depthMask.depthRange[0], Number(e.target.value)],\n })\n }\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n <div>\n <div className=\"flex justify-between text-slate-400 mb-1\">\n <span>Softness:</span>\n <span className=\"font-mono\">{state.depthMask.softness}</span>\n </div>\n <input\n type=\"range\"\n min=\"1\"\n max=\"50\"\n value={state.depthMask.softness}\n onChange={(e) => editor.setDepthMask({ softness: Number(e.target.value) })}\n className=\"w-full accent-indigo-500\"\n />\n </div>\n\n <label className=\"flex items-center gap-2 cursor-pointer text-slate-300 mt-1\">\n <input\n type=\"checkbox\"\n checked={state.depthMask.invert}\n onChange={(e) => editor.setDepthMask({ invert: e.target.checked })}\n className=\"rounded accent-indigo-500\"\n />\n <span>Invert Mask</span>\n </label>\n </>\n )}\n </div>\n )}\n\n {/* TAB 5: AI TOOLS / INPAINTING & BACKGROUND REMOVAL */}\n {activeTab === 'ai' && (\n <div className=\"flex flex-col gap-4 text-xs\">\n {/* Background Removal Section */}\n <div className=\"p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5\">\n <svg className=\"w-3.5 h-3.5 text-indigo-400\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z\" />\n </svg>\n Background Removal\n </span>\n {isRemovingBg && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse\">\n Removing...\n </span>\n )}\n </div>\n\n <p className=\"text-slate-400 text-[11px] leading-relaxed\">\n Isolate foreground subject with AI alpha transparency segmentation.\n </p>\n\n <button\n type=\"button\"\n onClick={handleRemoveBackground}\n disabled={isRemovingBg || isInpainting}\n className=\"mt-1 px-3 py-2 rounded-lg bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2\"\n >\n {isRemovingBg ? (\n <>\n <div className=\"w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin\" />\n Removing Background...\n </>\n ) : (\n <>\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83\" />\n </svg>\n Remove Background\n </>\n )}\n </button>\n </div>\n\n {/* AI Inpainting / Generative Fill Section */}\n <div className=\"p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5\">\n <svg className=\"w-3.5 h-3.5 text-purple-400\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z\" />\n <path d=\"m14 7 3 3\" />\n </svg>\n Generative Inpainting\n </span>\n {isInpainting && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse\">\n Inpainting...\n </span>\n )}\n </div>\n\n <p className=\"text-slate-400 text-[11px] leading-relaxed\">\n Replace, modify, or fill selected regions using prompt-guided generative inpainting.\n </p>\n\n <div className=\"flex flex-col gap-1\">\n <label htmlFor=\"ai-inpaint-prompt-react\" className=\"text-slate-300 text-[11px] font-medium\">Prompt</label>\n <textarea\n id=\"ai-inpaint-prompt-react\"\n value={inpaintPrompt}\n onChange={(e) => setInpaintPrompt(e.target.value)}\n placeholder=\"e.g. replace sunglasses with steampunk goggles, remove person in background...\"\n rows={3}\n className=\"w-full bg-slate-900 border border-slate-700 rounded-lg p-2 text-xs text-slate-100 placeholder-slate-500 focus:outline-none focus:border-indigo-500 resize-none\"\n />\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-slate-300 text-[11px] font-medium\">Target Mask Region</span>\n <div className=\"grid grid-cols-2 gap-1.5\">\n <button\n type=\"button\"\n onClick={() => setInpaintMaskMode('annotations')}\n className={`px-2 py-1.5 rounded border text-[11px] font-medium text-left transition-colors ${\n inpaintMaskMode === 'annotations'\n ? 'bg-purple-600/30 border-purple-500 text-purple-200'\n : 'bg-slate-900 border-slate-700 text-slate-400 hover:text-slate-200'\n }`}\n >\n Drawn Shapes ({state.annotations.length})\n </button>\n <button\n type=\"button\"\n onClick={() => setInpaintMaskMode('crop')}\n className={`px-2 py-1.5 rounded border text-[11px] font-medium text-left transition-colors ${\n inpaintMaskMode === 'crop'\n ? 'bg-purple-600/30 border-purple-500 text-purple-200'\n : 'bg-slate-900 border-slate-700 text-slate-400 hover:text-slate-200'\n }`}\n >\n Crop Box ({state.crop ? 'Selected' : 'Full'})\n </button>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={handleInpaint}\n disabled={isInpainting || isRemovingBg || !inpaintPrompt.trim()}\n className=\"mt-1 px-3 py-2 rounded-lg bg-purple-600 hover:bg-purple-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2\"\n >\n {isInpainting ? (\n <>\n <div className=\"w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin\" />\n Generating Inpaint...\n </>\n ) : (\n <>\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83\" />\n </svg>\n Apply Inpainting\n </>\n )}\n </button>\n </div>\n\n {aiError && (\n <div className=\"p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]\">\n {aiError}\n </div>\n )}\n\n {aiSuccess && (\n <div className=\"p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]\">\n {aiSuccess}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n};\n","import { useCallback, useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n getCommentStore,\n getTrackChangesStore,\n type CommentStore,\n type CommentStoreSnapshot,\n type TrackChangesSnapshot,\n type TrackedChange,\n} from \"@pixerate/editor\";\n\nconst EMPTY_COMMENTS: CommentStoreSnapshot = Object.freeze({\n threads: [],\n activeThreadId: null,\n}) as CommentStoreSnapshot;\n\nconst EMPTY_TRACK_CHANGES: TrackChangesSnapshot = Object.freeze({\n enabled: false,\n author: { id: \"anonymous\", name: \"Anonymous\" },\n changes: [],\n currentChangeId: null,\n}) as TrackChangesSnapshot;\n\nconst noopUnsubscribe = () => {};\n\nfunction isCommentStore(value: unknown): value is CommentStore {\n return (\n !!value &&\n typeof (value as CommentStore).getSnapshot === \"function\" &&\n typeof (value as CommentStore).createThread === \"function\"\n );\n}\n\nexport interface UseCommentsResult extends CommentStoreSnapshot {\n store: CommentStore | null;\n}\n\n/**\n * Subscribes to a comment store: pass the store itself, or an editor using\n * the `Comments` extension (`null` while the editor is being created).\n */\nexport function useComments(\n source: Editor | CommentStore | null | undefined,\n): UseCommentsResult {\n const store = isCommentStore(source) ? source : getCommentStore(source as Editor | null);\n const subscribe = useCallback(\n (onChange: () => void) => (store ? store.subscribe(() => onChange()) : noopUnsubscribe),\n [store],\n );\n const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n return useMemo(() => ({ ...snapshot, store }), [snapshot, store]);\n}\n\nexport interface UseTrackChangesResult extends TrackChangesSnapshot {\n currentChange: TrackedChange | null;\n setEnabled: (enabled: boolean) => void;\n toggle: () => void;\n accept: (id: string) => void;\n reject: (id: string) => void;\n acceptAll: () => void;\n rejectAll: () => void;\n next: () => void;\n previous: () => void;\n}\n\n/**\n * Subscribes to the tracked-change state of an editor using the\n * `TrackChanges` extension and exposes its commands.\n */\nexport function useTrackChanges(editor: Editor | null | undefined): UseTrackChangesResult {\n const store = getTrackChangesStore(editor ?? null);\n const subscribe = useCallback(\n (onChange: () => void) => (store ? store.subscribe(() => onChange()) : noopUnsubscribe),\n [store],\n );\n const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return useMemo(() => {\n const run = (fn: (e: Editor) => void) => () => {\n if (editor && !editor.isDestroyed) fn(editor);\n };\n return {\n ...snapshot,\n currentChange:\n snapshot.changes.find((c) => c.id === snapshot.currentChangeId) ?? null,\n setEnabled: (enabled: boolean) => run((e) => e.commands.setTrackChanges(enabled))(),\n toggle: run((e) => e.commands.toggleTrackChanges()),\n accept: (id: string) => run((e) => e.commands.acceptChange(id))(),\n reject: (id: string) => run((e) => e.commands.rejectChange(id))(),\n acceptAll: run((e) => e.commands.acceptAllChanges()),\n rejectAll: run((e) => e.commands.rejectAllChanges()),\n next: run((e) => e.chain().focus().selectNextChange().run()),\n previous: run((e) => e.chain().focus().selectPreviousChange().run()),\n };\n }, [snapshot, editor]);\n}\n","import React, { useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n formatReviewTime,\n getCommentAuthor,\n type CommentStore,\n type CommentThread,\n type ReviewAuthor,\n} from \"@pixerate/editor\";\nimport { useComments } from \"./useReview\";\n\nexport interface CommentsPanelProps {\n editor: Editor | null;\n /** Defaults to the store of the editor's `Comments` extension. */\n store?: CommentStore;\n /** Author of replies. Defaults to the `Comments` extension's author. */\n author?: ReviewAuthor;\n /** Initially show resolved threads. */\n showResolved?: boolean;\n className?: string;\n formatTime?: (timestamp: number) => string;\n emptyMessage?: string;\n}\n\nconst buttonClass =\n \"rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50\";\nconst primaryButtonClass =\n \"rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50\";\nconst textareaClass =\n \"w-full resize-y rounded-md border border-input bg-background p-2 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary\";\n\n/**\n * Lists comment threads with reply, resolve and delete actions. Clicking a\n * thread selects its text in the editor. Threads with an empty body are\n * drafts (e.g. created by `CommentButton`) and show a compose box.\n */\nexport const CommentsPanel: React.FC<CommentsPanelProps> = ({\n editor,\n store: storeProp,\n author: authorProp,\n showResolved: showResolvedInitial = false,\n className = \"flex flex-col gap-2 text-sm text-foreground\",\n formatTime = (t) => formatReviewTime(t),\n emptyMessage = \"No comments yet. Select text and add a comment.\",\n}) => {\n const { threads, activeThreadId, store } = useComments(storeProp ?? editor);\n const [showResolved, setShowResolved] = useState(showResolvedInitial);\n const author = authorProp ?? getCommentAuthor(editor) ?? { id: \"anonymous\", name: \"Anonymous\" };\n\n const visible = threads.filter((t) => showResolved || !t.resolved);\n const resolvedCount = threads.filter((t) => t.resolved).length;\n\n return (\n <aside className={className} aria-label=\"Comments\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n {threads.length - resolvedCount} open\n {resolvedCount > 0 ? ` · ${resolvedCount} resolved` : \"\"}\n </span>\n {resolvedCount > 0 && (\n <button\n type=\"button\"\n className={buttonClass}\n aria-pressed={showResolved}\n onClick={() => setShowResolved((v) => !v)}\n >\n {showResolved ? \"Hide resolved\" : \"Show resolved\"}\n </button>\n )}\n </div>\n {visible.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">{emptyMessage}</p>\n ) : (\n <ul className=\"flex flex-col gap-2\" role=\"list\">\n {visible.map((thread) => (\n <CommentThreadCard\n key={thread.id}\n thread={thread}\n active={thread.id === activeThreadId}\n editor={editor}\n store={store}\n author={author}\n formatTime={formatTime}\n />\n ))}\n </ul>\n )}\n </aside>\n );\n};\n\ninterface CommentThreadCardProps {\n thread: CommentThread;\n active: boolean;\n editor: Editor | null;\n store: CommentStore | null;\n author: ReviewAuthor;\n formatTime: (timestamp: number) => string;\n}\n\nconst CommentThreadCard: React.FC<CommentThreadCardProps> = ({\n thread,\n active,\n editor,\n store,\n author,\n formatTime,\n}) => {\n const [draft, setDraft] = useState(\"\");\n const isDraft = thread.body === \"\";\n const quote = thread.anchor?.quote ?? thread.lastQuote ?? \"\";\n const live = editor && !editor.isDestroyed ? editor : null;\n\n const focus = () => {\n if (!active) {\n if (live && !thread.orphaned) live.commands.focusComment(thread.id);\n else store?.setActiveThread(thread.id);\n }\n };\n const remove = () => {\n if (live) live.commands.deleteComment(thread.id);\n else store?.deleteThread(thread.id);\n };\n const setResolved = (resolved: boolean) => {\n if (live) live.commands.resolveComment(thread.id, resolved);\n else store?.resolveThread(thread.id, resolved, author);\n };\n const submit = () => {\n const body = draft.trim();\n if (!body || !store) return;\n if (isDraft) store.editComment(thread.id, body);\n else store.addReply(thread.id, { body, author });\n setDraft(\"\");\n };\n const stop = (e: React.SyntheticEvent) => e.stopPropagation();\n\n return (\n <li\n className={`flex flex-col gap-2 rounded-md border bg-background p-3 cursor-pointer ${\n active ? \"border-primary ring-1 ring-primary\" : \"border-border\"\n } ${thread.resolved ? \"opacity-70\" : \"\"}`}\n data-thread-id={thread.id}\n data-active={active || undefined}\n aria-current={active || undefined}\n tabIndex={0}\n onClick={focus}\n onKeyDown={(e) => {\n if (e.target === e.currentTarget && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n focus();\n }\n }}\n >\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"font-medium\">{thread.author.name}</span>\n <span className=\"text-xs text-muted-foreground\">{formatTime(thread.createdAt)}</span>\n </div>\n {quote && (\n <blockquote className=\"border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2\">\n {quote}\n </blockquote>\n )}\n {thread.orphaned && (\n <span className=\"text-xs text-destructive\">The commented text was deleted.</span>\n )}\n {thread.resolved && <span className=\"text-xs text-muted-foreground\">Resolved</span>}\n {!isDraft && <p className=\"whitespace-pre-wrap break-words\">{thread.body}</p>}\n {thread.replies.length > 0 && (\n <ul className=\"flex flex-col gap-2 border-l border-border pl-3\" role=\"list\">\n {thread.replies.map((reply) => (\n <li key={reply.id} className=\"flex flex-col gap-0.5\" data-reply-id={reply.id}>\n <span className=\"text-xs\">\n <span className=\"font-medium\">{reply.author.name}</span>{\" \"}\n <span className=\"text-muted-foreground\">{formatTime(reply.createdAt)}</span>\n </span>\n <p className=\"whitespace-pre-wrap break-words\">{reply.body}</p>\n </li>\n ))}\n </ul>\n )}\n {(active || isDraft) && !thread.resolved && (\n <div className=\"flex flex-col gap-1\" onClick={stop}>\n <textarea\n className={textareaClass}\n rows={2}\n value={draft}\n aria-label={isDraft ? \"Comment\" : \"Reply\"}\n placeholder={isDraft ? \"Add a comment…\" : \"Reply…\"}\n autoFocus={isDraft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n }}\n />\n <div className=\"flex justify-end gap-1\">\n {isDraft && (\n <button type=\"button\" className={buttonClass} onClick={remove}>\n Cancel\n </button>\n )}\n <button\n type=\"button\"\n className={primaryButtonClass}\n disabled={!draft.trim()}\n onClick={submit}\n >\n {isDraft ? \"Comment\" : \"Reply\"}\n </button>\n </div>\n </div>\n )}\n {!isDraft && (\n <div className=\"flex justify-end gap-1\" onClick={stop}>\n <button type=\"button\" className={buttonClass} onClick={() => setResolved(!thread.resolved)}>\n {thread.resolved ? \"Reopen\" : \"Resolve\"}\n </button>\n <button\n type=\"button\"\n className={`${buttonClass} hover:text-destructive`}\n onClick={remove}\n >\n Delete\n </button>\n </div>\n )}\n </li>\n );\n};\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { useTrackChanges } from \"./useReview\";\n\nexport interface ReviewToolbarProps {\n editor: Editor | null;\n className?: string;\n /**\n * Show the current change's author and description (e.g. \"Alice: Formatted:\n * Bold\"). Defaults to `true`.\n */\n showDescription?: boolean;\n /** Class of the description label. */\n descriptionClassName?: string;\n}\n\nconst defaultDescriptionClass = \"max-w-[16rem] truncate px-1 text-xs text-muted-foreground\";\n\nconst buttonClass =\n \"rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent\";\n\n/**\n * Toolbar for tracked changes: toggle tracking, step through changes\n * (insertions, deletions, formatting and block changes, with a description\n * of the current one), and accept or reject the current change or all\n * changes.\n */\nexport const ReviewToolbar: React.FC<ReviewToolbarProps> = ({\n editor,\n className = \"flex flex-wrap items-center gap-1 rounded-md border border-border bg-background p-1 text-sm\",\n showDescription = true,\n descriptionClassName = defaultDescriptionClass,\n}) => {\n const review = useTrackChanges(editor);\n const count = review.changes.length;\n const current = review.currentChange;\n const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;\n\n return (\n <div className={className} role=\"toolbar\" aria-label=\"Review\">\n <button\n type=\"button\"\n className={`${buttonClass} ${review.enabled ? \"bg-primary/10 text-primary\" : \"\"}`}\n aria-pressed={review.enabled}\n disabled={!editor}\n onClick={review.toggle}\n >\n {review.enabled ? \"Tracking on\" : \"Track changes\"}\n </button>\n <span className=\"mx-1 h-4 w-px bg-border\" aria-hidden=\"true\" />\n <button\n type=\"button\"\n className={buttonClass}\n aria-label=\"Previous change\"\n disabled={count === 0}\n onClick={review.previous}\n >\n ‹\n </button>\n <span className=\"min-w-[4rem] text-center text-xs text-muted-foreground\" aria-live=\"polite\">\n {count === 0 ? \"No changes\" : current ? `${index} of ${count}` : `${count} changes`}\n </span>\n <button\n type=\"button\"\n className={buttonClass}\n aria-label=\"Next change\"\n disabled={count === 0}\n onClick={review.next}\n >\n ›\n </button>\n {showDescription && current && (\n <span\n className={descriptionClassName}\n data-change-type={current.type}\n title={`${current.author.name}: ${current.description}`}\n >\n {current.author.name ? `${current.author.name}: ` : \"\"}\n {current.description}\n </span>\n )}\n <span className=\"mx-1 h-4 w-px bg-border\" aria-hidden=\"true\" />\n <button\n type=\"button\"\n className={buttonClass}\n disabled={!current}\n onClick={() => current && review.accept(current.id)}\n >\n Accept\n </button>\n <button\n type=\"button\"\n className={buttonClass}\n disabled={!current}\n onClick={() => current && review.reject(current.id)}\n >\n Reject\n </button>\n <button type=\"button\" className={buttonClass} disabled={count === 0} onClick={review.acceptAll}>\n Accept all\n </button>\n <button type=\"button\" className={buttonClass} disabled={count === 0} onClick={review.rejectAll}>\n Reject all\n </button>\n </div>\n );\n};\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\n\nexport interface CommentButtonProps {\n editor: Editor | null;\n className?: string;\n children?: React.ReactNode;\n}\n\n/**\n * Adds a draft comment on the selection; drop it into a `BubbleMenu`. The\n * draft is completed in `CommentsPanel`.\n */\nexport const CommentButton: React.FC<CommentButtonProps> = ({\n editor,\n className = \"rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted\",\n children = \"Comment\",\n}) => (\n <button\n type=\"button\"\n className={className}\n disabled={!editor}\n onClick={() => editor?.chain().focus().addComment().run()}\n >\n {children}\n </button>\n);\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n createCommandPaletteController,\n matchPaletteHotkey,\n type CommandPaletteController,\n type CommandPaletteOptions,\n type CommandPaletteState,\n type CommandRegistry,\n} from '@pixerate/editor/commands';\n\nexport interface UseCommandPaletteOptions<TContext = any> extends CommandPaletteOptions<TContext> {\n /** Chord that toggles the palette from anywhere, also while typing (e.g. `Mod+K`). */\n hotkey?: string;\n /** Element or window the hotkey listens on (default: `window`). */\n hotkeyTarget?: Window | HTMLElement | null;\n}\n\nexport interface UseCommandPaletteResult extends CommandPaletteState {\n controller: CommandPaletteController;\n setOpen: (open: boolean) => void;\n toggle: () => void;\n setQuery: (query: string) => void;\n setActiveIndex: (index: number) => void;\n move: (delta: number) => void;\n run: CommandPaletteController['run'];\n runActive: CommandPaletteController['runActive'];\n handleKeyDown: CommandPaletteController['handleKeyDown'];\n}\n\n/**\n * Command palette state over a `CommandRegistry` (ranked rows with shortcuts and\n * disabled reasons, active row, recents). Render it with `<CommandPalette palette={…} />`\n * or your own UI. Options are read live; the registry identity is the dependency.\n */\nexport function useCommandPalette<TContext = any>(\n registry: CommandRegistry<TContext>,\n options: UseCommandPaletteOptions<TContext> = {},\n): UseCommandPaletteResult {\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const controller = useMemo(\n () =>\n createCommandPaletteController(registry, {\n context: () => {\n const c = optionsRef.current.context;\n if (c === undefined) return registry.context;\n return (typeof c === 'function' ? (c as () => TContext)() : c) as TContext;\n },\n scope: () => {\n const s = optionsRef.current.scope;\n return typeof s === 'function' ? s() : s;\n },\n recents: options.recents,\n recentLimit: options.recentLimit,\n limit: options.limit,\n platform: options.platform,\n onRecentsChange: (recents) => optionsRef.current.onRecentsChange?.(recents),\n onRun: (result) => optionsRef.current.onRun?.(result),\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [registry],\n );\n\n const state = useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n\n const { hotkey, hotkeyTarget } = options;\n useEffect(() => {\n if (!hotkey) return;\n const target = hotkeyTarget ?? (typeof window !== 'undefined' ? window : null);\n if (!target) return;\n const onKeyDown = (event: Event) => {\n const e = event as KeyboardEvent;\n if (e.defaultPrevented || !matchPaletteHotkey(e, hotkey, optionsRef.current.platform)) return;\n e.preventDefault();\n controller.toggle();\n };\n target.addEventListener('keydown', onKeyDown);\n return () => target.removeEventListener('keydown', onKeyDown);\n }, [controller, hotkey, hotkeyTarget]);\n\n return {\n ...state,\n controller,\n setOpen: controller.setOpen,\n toggle: controller.toggle,\n setQuery: controller.setQuery,\n setActiveIndex: controller.setActiveIndex,\n move: controller.move,\n run: controller.run,\n runActive: controller.runActive,\n handleKeyDown: controller.handleKeyDown,\n };\n}\n","import React, { useEffect, useId, useRef } from 'react';\nimport type { CommandPaletteItem } from '@pixerate/editor/commands';\nimport type { UseCommandPaletteResult } from './useCommandPalette';\n\nexport interface CommandPaletteProps {\n /** State from `useCommandPalette`. */\n palette: UseCommandPaletteResult;\n placeholder?: string;\n emptyMessage?: string;\n /** Extra classes for the dialog panel. */\n className?: string;\n}\n\n/** Label with the fuzzy-matched characters emphasised. */\nfunction HighlightedLabel({ item }: { item: CommandPaletteItem }) {\n if (item.labelIndices.length === 0) return <>{item.label}</>;\n const marked = new Set(item.labelIndices);\n return (\n <>\n {Array.from(item.label).map((ch, i) =>\n marked.has(i) ? (\n <span key={i} className=\"font-semibold text-foreground\" data-match=\"\">\n {ch}\n </span>\n ) : (\n <React.Fragment key={i}>{ch}</React.Fragment>\n ),\n )}\n </>\n );\n}\n\n/**\n * Headless-styled command palette (Tailwind + theme tokens): a search box over the\n * registry's commands showing each command's group, shortcut and, for disabled\n * commands, the reason. Arrow keys move, Enter runs, Escape or a backdrop click closes.\n */\nexport const CommandPalette: React.FC<CommandPaletteProps> = ({\n palette,\n placeholder = 'Type a command…',\n emptyMessage = 'No matching commands',\n className = '',\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLUListElement>(null);\n const baseId = useId();\n const listId = `${baseId}-list`;\n const optionId = (index: number) => `${baseId}-option-${index}`;\n const { open, query, items, activeIndex } = palette;\n\n useEffect(() => {\n if (open) inputRef.current?.focus();\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n const active = listRef.current?.querySelector<HTMLElement>('[aria-selected=\"true\"]');\n active?.scrollIntoView?.({ block: 'nearest' });\n }, [open, activeIndex]);\n\n if (!open) return null;\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]\"\n data-command-palette-backdrop=\"\"\n onMouseDown={(e) => {\n if (e.target === e.currentTarget) palette.setOpen(false);\n }}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Command palette\"\n className={`w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl ${className}`}\n style={{ background: 'var(--popover, var(--background, #fff))' }}\n >\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n aria-expanded=\"true\"\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={items.length ? optionId(activeIndex) : undefined}\n aria-label=\"Search commands\"\n placeholder={placeholder}\n value={query}\n onChange={(e) => palette.setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (palette.handleKeyDown(e.nativeEvent)) e.stopPropagation();\n }}\n className=\"w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground\"\n />\n {items.length === 0 ? (\n <div className=\"px-3 py-6 text-center text-sm text-muted-foreground\">{emptyMessage}</div>\n ) : (\n <ul ref={listRef} id={listId} role=\"listbox\" aria-label=\"Commands\" className=\"max-h-80 overflow-y-auto py-1\">\n {items.map((item, index) => (\n <li\n key={item.id}\n id={optionId(index)}\n role=\"option\"\n aria-selected={index === activeIndex}\n aria-disabled={!item.enabled || undefined}\n data-command-id={item.id}\n data-recent={item.recent ? '' : undefined}\n title={item.disabledReason}\n onMouseMove={() => index !== activeIndex && palette.setActiveIndex(index)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => palette.run(item.id)}\n className={`flex cursor-pointer items-center gap-2 px-3 py-1.5 text-sm ${\n index === activeIndex ? 'bg-muted' : ''\n } ${item.enabled ? '' : 'cursor-default opacity-50'}`}\n >\n <span className=\"min-w-0 flex-1 truncate\">\n <HighlightedLabel item={item} />\n {item.disabledReason && (\n <span className=\"ml-2 text-xs text-muted-foreground\" data-disabled-reason=\"\">\n {item.disabledReason}\n </span>\n )}\n </span>\n {item.group && <span className=\"shrink-0 text-xs text-muted-foreground\">{item.group}</span>}\n {item.shortcut && (\n <kbd className=\"shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground\">\n {item.shortcut}\n </kbd>\n )}\n </li>\n ))}\n </ul>\n )}\n </div>\n </div>\n );\n};\n","import { useEffect, useRef } from 'react';\nimport type { CommandRegistry, CommandResult, CommandSpec } from '@pixerate/editor/commands';\n\nexport interface UseCommandShortcutsOptions<TContext = any> {\n /** Default `true`. */\n enabled?: boolean;\n /** Element or window to listen on (default: `window`). */\n target?: Window | HTMLElement | null;\n /** Active scopes, most specific first (e.g. `'canvas'` while the canvas has focus). */\n scopes?: string | readonly string[];\n /** Context for the commands (default: the registry's). */\n context?: TContext;\n /** Fire even while typing in inputs / contenteditable (default: per binding). */\n allowInEditable?: boolean;\n /** Called after a shortcut ran a command. */\n onRun?: (result: CommandResult) => void;\n}\n\n/**\n * Runs the registry's commands from their keyboard shortcuts (`registry.handleKeyDown`).\n * Typing in inputs and editors is never hijacked, and disabled commands leave the\n * event alone. Options are read live.\n */\nexport function useCommandShortcuts<TContext = any>(\n registry: CommandRegistry<TContext> | null | undefined,\n options: UseCommandShortcutsOptions<TContext> = {},\n): void {\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const { enabled = true, target } = options;\n\n useEffect(() => {\n if (!registry || !enabled) return;\n const eventTarget = target ?? (typeof window !== 'undefined' ? window : null);\n if (!eventTarget) return;\n const onKeyDown = (event: Event) => {\n const { scopes, context, allowInEditable, onRun } = optionsRef.current;\n const result = registry.handleKeyDown(event as KeyboardEvent, {\n scopes,\n ...(allowInEditable !== undefined ? { allowInEditable } : {}),\n ...(context !== undefined ? { context } : {}),\n });\n if (result) onRun?.(result);\n };\n eventTarget.addEventListener('keydown', onKeyDown);\n return () => eventTarget.removeEventListener('keydown', onKeyDown);\n }, [registry, enabled, target]);\n}\n\n/**\n * Registers commands while the component is mounted. Memoize `specs` (e.g. with\n * `useMemo(() => createHistoryCommands(manager), [manager])`): a new array re-registers.\n */\nexport function useRegisterCommands<TContext = any>(\n registry: CommandRegistry<TContext> | null | undefined,\n specs: readonly CommandSpec<TContext>[] | null | undefined,\n): void {\n useEffect(() => {\n if (!registry || !specs || specs.length === 0) return;\n return registry.register(specs);\n }, [registry, specs]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAA2C;AAC3C,IAAAC,gBAA0B;AAC1B,yBAAuB;AACvB,mCAAwB;AACxB,mBAAsB;AACtB,oBAYO;AAyDP,IAAM,oBAAgC,CAAC;AACvC,IAAM,oBAAoB,oBAAI,IAA2B;AAAA,EACvD,CAAC,WAAW,EAAE,MAAM,WAAW,IAAI,UAAU,CAAC;AAChD,CAAC;AACD,IAAM,qBACJ;AAEF,IAAM,oBAAoB,CAAC,SAAiB,KAAK,QAAQ,UAAU,IAAI;AAEhE,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAAqB;AAAA,EACrB;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,EACR;AACF,GAAyB;AACvB,QAAM,oBAAgB,qBAAO,UAAU;AACvC,gBAAc,UAAU;AACxB,QAAM,oBAAoB,CAAC,CAAC;AAE5B,QAAM,4BAAwB,qBAAO,kBAAkB;AACvD,wBAAsB,UAAU;AAEhC,QAAM,2BAAuB,qBAAO,iBAAiB;AACrD,uBAAqB,UAAU;AAE/B,QAAM,kBAAc,qBAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,QAAM,mBAAe,qBAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,2BAAuB,qBAAO,iBAAiB;AACrD,uBAAqB,UAAU;AAE/B,QAAM,6BAAyB,qBAAO,mBAAmB;AACzD,yBAAuB,UAAU;AAEjC,QAAM,yBAAqB,qBAAO,eAAe;AACjD,qBAAmB,UAAU;AAE7B,QAAM,qBAAiB,qBAAO,WAAW;AACzC,iBAAe,UAAU;AAEzB,QAAM,qBAAiB,qBAAO,WAAW;AACzC,iBAAe,UAAU;AAEzB,QAAM,kBAAc,sBAAQ,MAAM;AAChC,YAAQ,aAAa,CAAC,GACnB,IAAI,CAAC,MAAM,GAAG,EAAE,MAAM,EAAE,IAAI,IAAK,EAAU,iBAAiB,EAAE,EAAE,EAChE,KAAK,EACL,KAAK,GAAG;AAAA,EACb,GAAG,CAAC,SAAS,CAAC;AAId,QAAM,cAAc,eAChB,KAAK,UAAU,MAAM,KAAK,aAAa,QAAQ,CAAC,CAAC,IACjD;AACJ,QAAM,uBAAmB,sBAAQ,MAAM;AACrC,QAAI,aAAc,QAAO;AACzB,UAAM,MAAM,oBAAI,IAA2B;AAC3C,cAAU,QAAQ,CAAC,MAAM;AACvB,UAAI,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,IAAI,UAAU,CAAC;AAAA,IACpD,CAAC;AACD,WAAO,IAAI,OAAO,IAAI,MAAM;AAAA,EAC9B,GAAG,CAAC,aAAa,WAAW,CAAC;AAE7B,QAAM,oBAAoB,iBAAiB,CAAC,GAAG,KAAK,IAAQ;AAE5D,QAAM,2BAAuB,qBAAO,oBAAI,IAAY,CAAC;AAErD,QAAM,gBACH,mBAAAC,SAAoB,YACjB,mBAAAA,UACC,mBAAAA,SAAoB,SAAS,YAC3B,mBAAAA,SAAoB,UACrB,mBAAAA;AAER,QAAM,iBACH,6BAAAC,SAAqB,YAClB,6BAAAA,UACC,6BAAAA,SAAqB,SAAS,YAC5B,6BAAAA,SAAqB,UACtB,6BAAAA;AAER,QAAM,aAAS;AAAA,IACb;AAAA,MACE,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,UAAU;AAAA,MACV,YAAY;AAAA,QACV,cAAc,UAAU;AAAA,UACtB,SAAS;AAAA,UACT,WAAW;AAAA,QACb,CAAC;AAAA,QACD,eAAe,UAAU,EAAE,YAAY,CAAC;AAAA,QACxC,2BAAa,UAAU;AAAA,UACrB,kBAAkB;AAAA,UAClB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,QACD,kCAAoB,UAAU;AAAA,UAC5B;AAAA,QACF,CAAC;AAAA,QACD;AAAA,QACA,GAAI,oBACA;AAAA,UACE,yBAAW,UAAU;AAAA,YACnB,GAAI,OAAO,cAAc,YAAY,WAAW,cAAc,UAAU,CAAC;AAAA;AAAA,YAEzE,aAAa;AAAA,UACf,CAAC;AAAA,QACH,IACA,CAAC;AAAA,MACP;AAAA,MACA,aAAS,qCAAsB,OAAO;AAAA,MACtC,UAAU,CAAC,EAAE,QAAQ,GAAG,MAAM;AAC5B,cAAM,gBAAY,6BAAc,EAAE;AAClC,2BAAmB,UAAU,SAAS;AAEtC,YAAI,eAAe,SAAS;AAC1B,gBAAM,UAAU,qBAAqB;AACrC,qBAAW,aAAS,8BAAe,SAAS,GAAG;AAC7C,kBAAM,YACJ,MAAM,SAAS,aACX,kBACA,MAAM,SAAS,gBACb,eACA;AACR,gBAAI,aAAa,CAAC,QAAQ,IAAI,SAAS,GAAG;AACxC,sBAAQ,IAAI,SAAS;AACrB,6BAAe,QAAQ,SAAS;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAEA,cAAM,EAAE,OAAO,KAAK,IAAI;AACxB,cAAM,EAAE,UAAU,IAAI;AACtB,cAAM,EAAE,OAAO,MAAM,GAAG,IAAI;AAE5B,6BAAqB,UAAU,EAAE,MAAM,GAAG,CAAC;AAE3C,YAAI,uBAAuB,WAAW,qBAAqB,SAAS;AAClE,gBAAM,mBAAmB,OAAO,QAAQ,cACpC,MAAM,OAAO,YAAY,GAAG,MAAM,YAAY,IAC9C;AACJ,gBAAM,aAAa,iBAAiB;AAAA,YAClC;AAAA,UACF;AAEA,cAAI,YAAY;AACd,kBAAM,SAAS,KAAK,YAAY,MAAM,GAAG;AACzC,kBAAM,cACJ,SAAS,eAAe,eAAe,OAAO,KAC9C,SAAS,eAAe,kBAAkB,KACzC,KAAK,IAAI,UAAU,WAAW;AACjC,kBAAM,kBAAkB,aAAa,sBAAsB;AAE3D,gBAAI,iBAAiB;AACnB,qCAAuB;AAAA,gBACrB;AAAA,gBACA,MAAM,MACJ,WAAW,CAAC,EAAE,UACb,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,IAAI;AAAA,gBACvC,MAAM;AAAA,gBACN;AAAA,kBACE,KAAK,OAAO,SAAS,gBAAgB,MAAM;AAAA,kBAC3C,MAAM,OAAO,OAAO,gBAAgB;AAAA,gBACtC;AAAA,cACF;AAAA,YACF;AAAA,UACF,OAAO;AACL,iCAAqB,QAAQ;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AAAA,MACA,mBAAmB,CAAC,EAAE,QAAQ,GAAG,MAAM;AACrC,cAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;AAC9B,6BAAqB,UAAU,EAAE,MAAM,GAAG,CAAC;AAAA,MAC7C;AAAA,MACA,aAAa;AAAA,QACX,YAAY;AAAA,UACV,OAAO,aAAa;AAAA,UACpB,MAAM;AAAA,UACN,cAAc;AAAA,QAChB;AAAA,QACA,cAAc,MAAM,OAAO;AACzB,cAAI,sBAAsB,SAAS;AACjC,gBACE,MAAM,QAAQ,aACd,MAAM,QAAQ,eACd,MAAM,QAAQ,SACd;AACA,oBAAM,eAAe;AACrB,qBAAO;AAAA,YACT;AACA,gBAAI,MAAM,QAAQ,UAAU;AAC1B,mCAAqB,UAAU;AAC/B,oBAAM,eAAe;AACrB,oBAAM,gBAAgB;AACtB,qBAAO;AAAA,YACT;AAAA,UACF;AACA,cAAI,aAAa,WAAW,aAAa,QAAQ,KAAsB,GAAG;AACxE,mBAAO;AAAA,UACT;AACA,cAAI,MAAM,QAAQ,YAAY,YAAY,SAAS;AACjD,wBAAY,QAAQ;AACpB,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT;AAAA,QACA,aAAa,CAAC,MAAM,UAAU;AAE5B,gBAAM,OAAO,MAAM,eAAe,QAAQ,YAAY;AACtD,cAAI,CAAC,KAAM,QAAO;AAClB,gBAAM,eAAe;AACrB,gBAAM,SAAS,KAAK,MAAM;AAC1B,cAAI,CAAC,OAAQ,QAAO;AACpB,eAAK;AAAA,YACH,KAAK,MAAM,GAAG,qBAAiB,gCAAiB,MAAM,MAAM,CAAC;AAAA,UAC/D;AACA,iBAAO;AAAA,QACT;AAAA,QACA,qBAAqB,CAAC,MAAM,SAAS,QAAQ,SAAS;AACpD,gBAAM,SACH,SAAiB,KAAK,MAAM,UAC5B,SAAiB,UAClB,MAAM,OAAO;AAEf,cAAI,CAAC,OAAQ,QAAO,mBAAM;AAC1B,qBAAO,gCAAiB,MAAM,MAAM;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA,IAGA,CAAC,kBAAkB,aAAa,OAAO,kBAAkB,iBAAiB;AAAA,EAC5E;AAEA,8BAAU,MAAM;AACd,QAAI,UAAU,CAAC,OAAO,aAAa;AACjC,aAAO,YAAY,SAAS;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,CAAC;AAGtB,8BAAU,MAAM;AACd,QAAI,CAAC,UAAU,OAAO,YAAa;AACnC,QAAI,kBAAkB,OAAO,UAAM,6BAAc,MAAM,EAAG;AAC1D,UAAM,EAAE,MAAM,GAAG,IAAI,OAAO,MAAM;AAClC,WAAO,SAAS,eAAW,qCAAsB,OAAO,GAAG,KAAK;AAChE,UAAM,MAAM,OAAO,MAAM,IAAI,QAAQ;AACrC,WAAO,SAAS,iBAAiB;AAAA,MAC/B,MAAM,KAAK,IAAI,MAAM,GAAG;AAAA,MACxB,IAAI,KAAK,IAAI,IAAI,GAAG;AAAA,IACtB,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,8BAAU,MAAM;AACd,QAAI,CAAC,UAAU,OAAO,YAAa;AACnC,WAAO,WAAW;AAAA,MAChB,aAAa;AAAA,QACX,GAAG,OAAO,QAAQ;AAAA,QAClB,YAAY;AAAA,UACV,GAAI,OAAO,QAAQ,YAAY;AAAA,UAC/B,OAAO,aAAa;AAAA,QACtB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,8BAAU,MAAM;AACd,QAAI,CAAC,UAAU,OAAO,YAAa;AACnC,UAAM,iBAAiB,OAAO,iBAAiB,WAAW;AAAA,MACxD,CAAC,QAAQ,IAAI,SAAS;AAAA,IACxB;AACA,QAAI,CAAC,kBAAkB,eAAe,QAAQ,gBAAgB,aAAa;AACzE;AAAA,IACF;AACA,mBAAe,QAAQ,cAAc;AAErC,WAAO,KAAK,SAAS,OAAO,MAAM,EAAE;AAAA,EACtC,GAAG,CAAC,QAAQ,WAAW,CAAC;AAExB,SAAO;AACT;;;ACvXA,IAAAC,gBAA+D;AAC/D,IAAAC,iBAKO;AAoBA,SAASC,WAAU,UAA8B,CAAC,GAAG;AAC1D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,CAAC;AAAA,IACd,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,aAAS,qCAAqB;AAAA,IAClC,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,IACjD,GAAI,kBAAkB,SAAY,EAAE,cAAc,IAAI,CAAC;AAAA,IACvD,GAAG;AAAA,EACL,CAAC;AACD,QAAM,qBAAqB,CAAC,GAAG,QAAQ,GAAG,UAAU;AAEpD,aAAO,cAAAC,WAAgB;AAAA,IACrB,YAAY;AAAA,IACZ,GAAG;AAAA,EACL,CAAC;AACH;;;AC9CA,IAAAC,gBAAyD;AA8BlD,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AACF,GAAwD;AACtD,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,KAAK;AACpD,QAAM,CAAC,YAAY,aAAa,QAAI,wBAAwB,IAAI;AAEhE,QAAM,oBAAgB,sBAAO,UAAU;AACvC,gBAAc,UAAU;AAExB,QAAM,mBAAe,sBAAO,SAAS;AACrC,eAAa,UAAU;AAGvB,+BAAU,MAAM;AACd,QAAI,OAAO,WAAW,YAAa;AACnC,QAAI,CAAC,WAAW,CAAC,QAAS;AAE1B,UAAM,qBAAqB,CAAC,MAAyB;AACnD,QAAE,eAAe;AACjB,QAAE,cAAc;AAAA,IAClB;AAEA,WAAO,iBAAiB,gBAAgB,kBAAkB;AAC1D,WAAO,MAAM;AACX,aAAO,oBAAoB,gBAAgB,kBAAkB;AAAA,IAC/D;AAAA,EACF,GAAG,CAAC,SAAS,OAAO,CAAC;AAGrB,+BAAU,MAAM;AACd,QAAI,OAAO,aAAa,eAAe,OAAO,WAAW;AACvD;AACF,QAAI,CAAC,WAAW,CAAC,QAAS;AAE1B,UAAM,cAAc,CAAC,MAAkB;AACrC,YAAM,SAAS,EAAE;AACjB,YAAM,SAAS,QAAQ,UAAU,GAAG;AAEpC,UAAI,CAAC,OAAQ;AACb,UAAI,OAAO,WAAW,SAAU;AAGhC,YAAM,aAAa,OAAO,SAAS,OAAO,SAAS;AACnD,UAAI,CAAC,WAAY;AAGjB,UACE,OAAO,aAAa,OAAO,SAAS,YACpC,OAAO,WAAW,OAAO,SAAS,QAClC;AACA;AAAA,MACF;AAEA,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAElB,YAAM,OAAO,OAAO;AACpB,oBAAc,IAAI;AAClB,qBAAe,IAAI;AACnB,mBAAa,UAAU,IAAI;AAAA,IAC7B;AAEA,aAAS,iBAAiB,SAAS,aAAa,EAAE,SAAS,KAAK,CAAC;AACjE,WAAO,MAAM;AACX,eAAS,oBAAoB,SAAS,aAAa,EAAE,SAAS,KAAK,CAAC;AAAA,IACtE;AAAA,EACF,GAAG,CAAC,SAAS,OAAO,CAAC;AAErB,QAAM,mBAAe,2BAAY,MAAM;AACrC,mBAAe,KAAK;AACpB,QAAI,YAAY;AACd,UAAI,cAAc,SAAS;AACzB,sBAAc,QAAQ,UAAU;AAAA,MAClC,WAAW,OAAO,WAAW,aAAa;AACxC,eAAO,SAAS,OAAO;AAAA,MACzB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,kBAAc,2BAAY,MAAM;AACpC,mBAAe,KAAK;AACpB,kBAAc,IAAI;AAAA,EACpB,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC5HA,IAAAC,gBAA8C;AA6BvC,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,UAAU;AAAA,EACV;AACF,GAAkD;AAChD,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,KAAK;AAEpD,QAAM,mBAAe,sBAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,qBAAiB,2BAAY,MAAM;AACvC,QAAI,WAAW,SAAS;AACtB,qBAAe,IAAI;AAAA,IACrB,OAAO;AACL,mBAAa,UAAU;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,SAAS,OAAO,CAAC;AAErB,QAAM,qBAAiB,2BAAY,MAAM;AACvC,mBAAe,KAAK;AACpB,iBAAa,UAAU;AAAA,EACzB,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAgB,2BAAY,MAAM;AACtC,mBAAe,KAAK;AAAA,EACtB,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAgB;AAAA,IACpB,CAAC,UAA+C;AAC9C,UAAI,MAAM,QAAQ,UAAU;AAC1B,YAAI,MAAM,iBAAkB,QAAO;AACnC,cAAM,eAAe;AACrB,uBAAe;AACf,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC7EA,IAAAC,gBAAmE;AACnE,IAAAC,iBASO;AA4BA,SAAS,WACd,kBACkB;AAGlB,QAAM,oBAAgB,sBAA8B,IAAI;AACxD,MAAI;AACJ,MAAI,4BAA4B,+BAAgB;AAC9C,cAAU;AAAA,EACZ,OAAO;AACL,kBAAc,gBAAY,qCAAqB,gBAAgB;AAC/D,cAAU,cAAc;AAAA,EAC1B;AAEA,QAAM,YAAQ;AAAA,QACZ;AAAA,MACE,CAAC,kBAAkB,QAAQ,UAAU,aAAa;AAAA,MAClD,CAAC,OAAO;AAAA,IACV;AAAA,IACA,MAAM,QAAQ,SAAS;AAAA,IACvB,MAAM,QAAQ,SAAS;AAAA,EACzB;AAIA,QAAM,cAAU,uBAAQ,MAAM,QAAQ,WAAW,GAAG,CAAC,SAAS,KAAK,CAAC;AAEpE,QAAM,WAAO,2BAAY,MAAM,QAAQ,KAAK,GAAG,CAAC,OAAO,CAAC;AACxD,QAAM,WAAO,2BAAY,MAAM,QAAQ,KAAK,GAAG,CAAC,OAAO,CAAC;AACxD,QAAM,YAAQ,2BAAY,MAAM,QAAQ,MAAM,GAAG,CAAC,OAAO,CAAC;AAC1D,QAAM,cAAU;AAAA,IACd,CAAC,QAAiB,QAAQ,QAAQ,GAAG;AAAA,IACrC,CAAC,OAAO;AAAA,EACV;AACA,QAAM,oBAAgB;AAAA,IACpB,CAAC,KAAc,SACb,QAAQ,cAAc,KAAK,IAAI;AAAA,IACjC,CAAC,OAAO;AAAA,EACV;AACA,QAAM,YAAQ;AAAA,IACZ,CAAC,MAAc,OAAmB,QAAQ,MAAM,MAAM,EAAE;AAAA,IACxD,CAAC,OAAO;AAAA,EACV;AACA,QAAM,WAAO,2BAAY,CAAC,UAAkB,QAAQ,KAAK,KAAK,GAAG,CAAC,OAAO,CAAC;AAC1E,QAAM,WAAO,2BAAY,MAAM,QAAQ,KAAK,GAAG,CAAC,OAAO,CAAC;AACxD,QAAM,eAAW;AAAA,IACf,CAAC,MAAmB,QAAQ,SAAS,CAAC;AAAA,IACtC,CAAC,OAAO;AAAA,EACV;AACA,QAAM,mBAAe;AAAA,IACnB,CAAC,QAAgB,QAAQ,aAAa,GAAG;AAAA,IACzC,CAAC,OAAO;AAAA,EACV;AACA,QAAM,iBAAa,2BAAY,MAAM,QAAQ,WAAW,GAAG,CAAC,OAAO,CAAC;AAEpE,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC7GA,IAAAC,gBAA+E;AAC/E,IAAAC,iBAMO;AA6BA,SAAS,gBACd,SAC0B;AAC1B,QAAM,kBAAc,sBAAO,QAAQ,QAAQ;AAC3C,cAAY,UAAU,QAAQ;AAE9B,QAAM,CAAC,OAAO,QAAI;AAAA,IAChB,MACE,QAAQ,WACR,IAAI,4BAAgB,QAAQ,SAAS,GAAG;AAAA,MACtC,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAAA,EACL;AAEA,QAAM,iBAAa,sBAAsC,IAAI;AAC7D,+BAAU,MAAM;AACd,UAAM,cAAU,mCAAsB;AAAA,MACpC,SAAS,QAAQ;AAAA,MACjB,UAAU,MAAM,YAAY,QAAQ;AAAA,MACpC;AAAA,IACF,CAAC;AACD,eAAW,UAAU;AACrB,WAAO,MAAM;AACX,cAAQ,QAAQ;AAChB,UAAI,WAAW,YAAY,QAAS,YAAW,UAAU;AAAA,IAC3D;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,OAAO,CAAC;AAE7B,QAAM,cAAU;AAAA,QACd,2BAAY,CAAC,aAAa,QAAQ,UAAU,QAAQ,GAAG,CAAC,OAAO,CAAC;AAAA,IAChE,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,EAChB;AAEA,QAAM,gBAAY;AAAA,IAChB,MAAM,QAAQ,UAAU,YAAY,QAAQ,CAAC;AAAA,IAC7C,CAAC,OAAO;AAAA,EACV;AACA,QAAM,eAAW;AAAA,IACf,CAAK,OACH,WAAW,UAAU,WAAW,QAAQ,SAAS,EAAE,IAAI,QAAQ,SAAS,EAAE;AAAA,IAC5E,CAAC,OAAO;AAAA,EACV;AACA,QAAM,cAAU;AAAA,IACd,MAAM,QAAQ,OAAO,YAAY,QAAQ,CAAC;AAAA,IAC1C,CAAC,OAAO;AAAA,EACV;AAEA,SAAO,EAAE,SAAS,WAAW,UAAU,SAAS,QAAQ;AAC1D;;;ACtFA,IAAAC,gBAA0B;AAE1B,sBAAqC;AAsB9B,SAAS,oBACd,SACA,UAAmC,CAAC,GAC9B;AACN,QAAM;AAAA,IACJ,UAAU;AAAA,IACV;AAAA,IACA,yBAAyB;AAAA,EAC3B,IAAI;AAEJ,+BAAU,MAAM;AACd,QAAI,CAAC,QAAS;AAEd,UAAM,cAAc,WAAW,OAAO,WAAW,cAAc,SAAS;AACxE,QAAI,CAAC,YAAa;AAElB,UAAM,gBAAgB,CAAC,UAAiB;AACtC,YAAM,IAAI;AAGV,YAAM,aAAS,sCAAqB,GAAG,EAAE,iBAAiB,CAAC,uBAAuB,CAAC;AACnF,UAAI,WAAW,UAAU,QAAQ,SAAS,EAAE,SAAS;AACnD,UAAE,eAAe;AACjB,gBAAQ,KAAK;AAAA,MACf,WAAW,WAAW,UAAU,QAAQ,SAAS,EAAE,SAAS;AAC1D,UAAE,eAAe;AACjB,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAEA,gBAAY,iBAAiB,WAAW,aAAa;AACrD,WAAO,MAAM;AACX,kBAAY,oBAAoB,WAAW,aAAa;AAAA,IAC1D;AAAA,EACF,GAAG,CAAC,SAAS,SAAS,QAAQ,sBAAsB,CAAC;AACvD;;;AC3DA,IAAAC,gBAAiE;AAEjE,IAAAC,iBAIO;AAgBA,SAAS,cACd,QACA,UAAuC,CAAC,GACnB;AACrB,QAAM,gBAAY,sBAAO,MAAM;AAC/B,YAAU,UAAU;AAEpB,QAAM,iBAAa;AAAA,IACjB,MACE,IAAI,oCAAqB,MAAM;AAC7B,YAAM,UAAU,UAAU;AAC1B,aAAO,WAAW,CAAC,QAAQ,cAAc,UAAU;AAAA,IACrD,GAAG,OAAO;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,+BAAU,MAAM;AACd,eAAW,WAAW,OAAO;AAAA,EAC/B,CAAC;AAED,QAAM,YAAQ,oCAAqB,WAAW,WAAW,WAAW,UAAU,WAAW,QAAQ;AAEjG,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,WAAW;AAAA,IACnB,gBAAgB,WAAW;AAAA,IAC3B,aAAa,WAAW;AAAA,EAC1B;AACF;;;AClDA,IAAAC,iBAA0B;AAYnB,SAAS,qBACd,UACA,UACM;AACN,gCAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,SAAU;AAC5B,WAAO,SAAS,SAAS,QAAQ;AAAA,EACnC,GAAG,CAAC,UAAU,QAAQ,CAAC;AACzB;;;ACnBA,IAAAC,iBAGO;AAaD;AAPC,IAAM,gBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,SACE,4CAAC,SAAI,WACH,sDAAC,eAAAC,eAAA,EAAoB,QAAiB,GAAG,OAAO,GAClD;AAEJ;;;ACpBA,IAAAC,iBAAmD;AACnD,uBAA6B;AAC7B,mCAGO;AAaA,IAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,eAAe,EAAE,UAAU,IAAI;AAAA,EAC/B,aAAa;AAAA,EACb,YAAY;AAAA,EACZ;AACF,MAAM;AACJ,QAAM,aAAS,uBAA8B,IAAI;AACjD,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAE5C,MAAI,CAAC,OAAO,WAAW,OAAO,aAAa,aAAa;AACtD,WAAO,UAAU,SAAS,cAAc,KAAK;AAAA,EAC/C;AAEA,gCAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,OAAO,WAAW,OAAO,aAAa;AACpD;AAAA,IACF;AAEA,UAAM,UAAU,OAAO;AACvB,YAAQ,YAAY;AAEpB,UAAM,aAAS,+CAAiB;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO,eAAe,MAAM;AAC5B,eAAW,IAAI;AAEf,WAAO,MAAM;AACX,iBAAW,KAAK;AAChB,aAAO,iBAAiB,SAAS;AACjC,UAAI,QAAQ,YAAY;AACtB,gBAAQ,WAAW,YAAY,OAAO;AAAA,MACxC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,WAAW,SAAS,CAAC;AAEjC,MAAI,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,SAAS;AAC1C,WAAO;AAAA,EACT;AAEA,aAAO,+BAAa,UAAU,OAAO,OAAO;AAC9C;;;ACpEA,IAAAC,iBAA+B;AAC/B,IAAAC,iBAMO;AA8DK,IAAAC,sBAAA;AApCZ,IAAM,qBAAqB,EAAE,IAAI,KAAK,QAAQ,KAAK,KAAK,IAAI;AAErD,IAAM,mBAAoD,CAAC;AAAA,EAChE;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AACF,MAAM;AACJ,QAAM,kBAAc,wBAAQ,MAAM;AAChC,QAAI,CAAC,WAAW,UAAU,WAAW,EAAG,QAAO;AAC/C,eAAO,iCAAiB,SAAS,WAAW,EAAE,SAAS,CAAC;AAAA,EAC1D,GAAG,CAAC,SAAS,WAAW,SAAS,QAAQ,CAAC;AAE1C,QAAM,aAAS,wBAAQ,MAAM;AAC3B,eAAO,qCAAqB,aAAa,MAAM;AAAA,EACjD,GAAG,CAAC,aAAa,MAAM,CAAC;AAExB,SACE,6CAAC,SAAI,WACF,iBAAO,IAAI,CAAC,OAAO,UAAU;AAC5B,QAAI,MAAM,SAAS,YAAY;AAC7B,YAAM,SAAS,kBAAkB,IAAI,MAAM,KAAK,KAAK;AAAA,QACnD,MAAM;AAAA,QACN,IAAI;AAAA,MACN;AACA,YAAM,QAAQ;AAAA,QACZ,gBAAgB,OAAO;AAAA,QACvB,cAAc,OAAO;AAAA,MACvB;AAEA,aACE;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,SAAS,MAAM,kBAAkB,MAAM,KAAK;AAAA,UAC5C,WAAU;AAAA,UACV,OAAO,aAAa,MAAM,KAAK;AAAA,UAE9B,eAAK,MAAM,KAAK;AAAA;AAAA,QANZ;AAAA,MAOP;AAAA,IAEJ;AAEA,QAAI,MAAM,SAAS,YAAY;AAC7B,YAAM,UAAU;AAAA,QACd,aAAa,MAAM,KAAK;AAAA,QACxB,MAAM;AAAA,QACN,MAAM,iBAAiB,SACnB,YAAY,MAAM,gBAAgB,SAAS,KAC3C;AAAA,MACN,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAEZ,UAAI,MAAM,kBAAkB,QAAW;AACrC,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,SAAS,MAAM,kBAAkB,MAAM,KAAK;AAAA,YAC5C,iBAAe,MAAM;AAAA,YACrB,qBAAmB,MAAM;AAAA,YACzB,WACE,MAAM,gBAAgB,UAClB,yIACA;AAAA,YAEN,OAAO;AAAA,YAEN,gBAAM;AAAA;AAAA,UAXF;AAAA,QAYP;AAAA,MAEJ;AAEA,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,SAAS,MAAM,kBAAkB,MAAM,KAAK;AAAA,UAC5C,iBAAe,MAAM;AAAA,UACrB,WAAU;AAAA,UACV,OAAO;AAAA,UAEN;AAAA,gBAAI,MAAM,KAAK;AAAA,YACf,MAAM,iBAAiB,UACtB,6CAAC,UAAK,WAAU,cAAc,cAAI,MAAM,YAAY,IAAG;AAAA,YAExD;AAAA;AAAA;AAAA,QAVI;AAAA,MAWP;AAAA,IAEJ;AAEA,QAAI,MAAM,SAAS,iBAAiB,MAAM,aAAa;AACrD,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,oBAAkB,MAAM;AAAA,UACxB,WAAU;AAAA,UACV,OACE,MAAM,gBAAgB,QAClB,mBAAmB,MAAM,KAAK,KAC9B,MAAM,gBAAgB,OACpB,eAAe,MAAM,KAAK,kBAC1B,eAAe,MAAM,KAAK;AAAA,UAGjC,cAAI,mBAAmB,MAAM,WAAW,CAAC,GAAG,MAAM,KAAK;AAAA;AAAA,QAXnD;AAAA,MAYP;AAAA,IAEJ;AAEA,QAAI,MAAM,SAAS,eAAe;AAChC,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UACV,OAAO,gBAAgB,MAAM,KAAK;AAAA,UAEjC,eAAK,MAAM,KAAK;AAAA;AAAA,QAJZ;AAAA,MAKP;AAAA,IAEJ;AAEA,WAAO,6CAAC,UAAkB,gBAAM,SAAd,KAAoB;AAAA,EACxC,CAAC,GACH;AAEJ;;;ACnKA,IAAAC,iBAAgD;AAChD,IAAAC,iBAMO;AA6DK,IAAAC,sBAAA;AAlCL,IAAM,eAA4C,CAAC;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AACd,MAAM;AACJ,QAAM,eAAW,sBAAM;AACvB,QAAM,CAAC,UAAU,WAAW,QAAI;AAAA,IAC9B,MAAM,iBAAiB,CAAC;AAAA,EAC1B;AACA,QAAM,UAAU,UAAU;AAE1B,QAAM,aAAS;AAAA,IACb,UAAM,sCAAsB,SAAS,EAAE,WAAW,SAAS,CAAC;AAAA,IAC5D,CAAC,SAAS,WAAW,QAAQ;AAAA,EAC/B;AAEA,QAAM,SAAS,CAAC,MAAc,UAAkB;AAC9C,UAAM,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,GAAG,MAAM;AACzC,QAAI,WAAW,OAAW,aAAY,IAAI;AAC1C,mBAAW,sCAAsB,IAAI,GAAG,IAAI;AAAA,EAC9C;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SACE,6CAAC,UAAK,WAAsB,UAAU,CAAC,UAAU,MAAM,eAAe,GACnE,iBAAO,IAAI,CAAC,UAAU;AACrB,UAAM,KAAK,GAAG,QAAQ,IAAI,MAAM,IAAI;AACpC,QAAI,MAAM,eAAe;AACvB,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,SAAS;AAAA,UACT,WAAU;AAAA,UACV,uBAAqB,MAAM;AAAA,UAE3B;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA,MAAM,MAAM;AAAA,gBACZ,MAAK;AAAA,gBACL,UAAU,QAAQ,MAAM,IAAI,KAAK,QAAQ;AAAA,gBACzC,UAAU,CAAC,UACT,OAAO,MAAM,MAAM,MAAM,OAAO,UAAU,SAAS,EAAE;AAAA;AAAA,YAEzD;AAAA,YACA,6CAAC,UAAM,gBAAM,OAAM;AAAA;AAAA;AAAA,QAdd,MAAM;AAAA,MAeb;AAAA,IAEJ;AACA,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,SAAS;AAAA,QACT,WAAU;AAAA,QACV,uBAAqB,MAAM;AAAA,QAE3B;AAAA,wDAAC,UAAK,WAAU,eACb;AAAA,kBAAM;AAAA,YACN,MAAM,YACL,6CAAC,UAAK,WAAU,iBAAgB,eAAY,QACzC,gBACH;AAAA,aAEJ;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,MAAM,MAAM;AAAA,cACZ,MAAK;AAAA,cACL,OAAO,QAAQ,MAAM,IAAI,KAAK;AAAA,cAC9B,aAAa,MAAM;AAAA,cACnB,iBAAe,MAAM,YAAY;AAAA,cACjC,UAAU,CAAC,UAAU,OAAO,MAAM,MAAM,MAAM,OAAO,KAAK;AAAA,cAC1D,WAAU;AAAA;AAAA,UACZ;AAAA;AAAA;AAAA,MAtBK,MAAM;AAAA,IAuBb;AAAA,EAEJ,CAAC,GACH;AAEJ;;;ACrHA,IAAAC,iBAA8C;AAE9C,IAAAC,iBAAyD;AAYlD,SAAS,WAAW,QAAoD;AAG7E,QAAM,YAAQ,wBAAQ,UAAM,mCAAmB,MAAM,GAAG,CAAC,MAAM,CAAC;AAChE,aAAO,qCAAqB,MAAM,WAAW,MAAM,aAAa,MAAM,WAAW;AACnF;;;ACjBA,IAAAC,iBAAuD;AA2CnD,IAAAC,sBAAA;AAfG,IAAM,eAA4C,CAAC;AAAA,EACxD;AAAA,EACA,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB;AACF,MAAM;AACJ,QAAM,EAAE,UAAU,SAAS,IAAI,WAAW,MAAM;AAChD,QAAM,UAAU,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ;AAE1D,SACE,8CAAC,SAAI,WAAsB,cAAW,oBAAmB,sBAAmB,IACzE;AAAA,aAAS,QAAQ,6CAAC,SAAI,WAAU,0BAA0B,iBAAM;AAAA,IAChE,QAAQ,WAAW,IAClB,6CAAC,SAAI,WAAU,0BAA0B,sBAAW,IAEpD,6CAAC,QAAG,MAAK,QAAO,OAAO,EAAE,WAAW,QAAQ,QAAQ,GAAG,SAAS,EAAE,GAC/D,kBAAQ,IAAI,CAAC,YAAY;AACxB,YAAM,SAAS,QAAQ,OAAO;AAC9B,aACE,6CAAC,QAAoB,cAAY,QAAQ,OACvC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW,SAAS,GAAG,aAAa,IAAI,mBAAmB,KAAK;AAAA,UAChE,OAAO,EAAE,aAAa,GAAG,MAAM,QAAQ,QAAQ,IAAI,MAAM;AAAA,UACzD,gBAAc,SAAS,aAAa;AAAA,UACpC,mBAAiB,QAAQ;AAAA,UACzB,SAAS,MAAM;AACb,gBAAI,CAAC,OAAQ;AACb,oBAAI,kCAAkB,QAAQ,SAAS,EAAE,OAAO,gBAAgB,CAAC,GAAG;AAClE,2BAAa,OAAO;AAAA,YACtB;AAAA,UACF;AAAA,UAEC,kBAAQ,QAAQ;AAAA;AAAA,MACnB,KAfO,QAAQ,EAgBjB;AAAA,IAEJ,CAAC,GACH;AAAA,KAEJ;AAEJ;;;Af5DA,IAAAC,kBAQO;;;AgBzBP,IAAAC,iBAAuD;AACvD,yBAUO;AAEA,SAAS,qBAAqB,UAAwC,CAAC,GAAG;AAE/E,QAAM,iBAAa,uBAAO,OAAO;AACjC,aAAW,UAAU;AACrB,QAAM,iBAAa,uBAIhB,CAAC,CAAC;AAIL,QAAM,CAAC,UAAU,QAAI;AAAA,IACnB,MACE,IAAI,yCAAsB;AAAA,MACxB,GAAG;AAAA,MACH,kBAAkB,CAAC,YAAY;AAC7B,mBAAW,QAAQ,SAAS,EAAE,GAAG,QAAQ,CAAC;AAC1C,mBAAW,QAAQ,mBAAmB,OAAO;AAAA,MAC/C;AAAA,MACA,mBAAmB,CAAC,QAAQ,UAAU;AACpC,mBAAW,QAAQ,gBAAgB,MAAM;AACzC,mBAAW,QAAQ,mBAAmB,KAAK;AAC3C,mBAAW,QAAQ,oBAAoB,QAAQ,KAAK;AAAA,MACtD;AAAA,MACA,cAAc,CAAC,OAAO,OAAO,KAAK,UAAU;AAC1C,mBAAW,QAAQ,eAAe,OAAO,OAAO,KAAK,KAAK;AAAA,MAC5D;AAAA,IACF,CAAC;AAAA,EACL;AAEA,QAAM,CAAC,KAAK,MAAM,QAAI,yBAA8B,OAAO,EAAE,GAAG,WAAW,SAAS,EAAE;AACtF,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAgC,WAAW,UAAU;AACzF,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAA2B,WAAW,aAAa;AAC7F,QAAM,CAAC,aAAa,cAAc,QAAI,yBAAgC,IAAI;AAC1E,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAiB,EAAE;AACvD,aAAW,UAAU,EAAE,QAAQ,eAAe,iBAAiB;AAI/D,QAAM,oBAAgB,4BAAY,CAAC,UAAkB;AACnD,eAAW,aAAa;AACxB,kBAAc,KAAK;AAAA,EACrB,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,mBAAe,4BAAY,CAAC,OAAe,OAAe,QAAgB;AAC9E,eAAW,aAAa,OAAO,OAAO,GAAG;AACzC,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,iBAAa,4BAAY,CAAC,KAAa,KAAa,kBAAkB,UAAU;AACpF,eAAW,WAAW,KAAK,KAAK,eAAe;AAC/C,kBAAc,WAAW,UAAU;AACnC,qBAAiB,WAAW,aAAa;AAAA,EAC3C,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,kBAAc,4BAAY,CAAC,UAAqB;AACpD,eAAW,YAAY,KAAK;AAC5B,qBAAiB,WAAW,aAAa;AAAA,EAC3C,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,mBAAe,4BAAY,CAAC,KAAc,KAAc,eAAwB;AACpF,eAAW,aAAa,KAAK,KAAK,UAAU;AAC5C,kBAAc,WAAW,UAAU;AACnC,mBAAe,WAAW,WAAW;AACrC,kBAAc,WAAW,UAAU;AAAA,EACrC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,oBAAgB,4BAAY,CAAC,QAAiB;AAClD,eAAW,cAAc,GAAG;AAC5B,mBAAe,IAAI;AACnB,kBAAc,EAAE;AAChB,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,oBAAgB,4BAAY,MAAM;AACtC,eAAW,cAAc;AACzB,mBAAe,IAAI;AACnB,kBAAc,EAAE;AAAA,EAClB,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,iBAAa,4BAAY,CAAC,KAAuC,SAAS,UAAU;AACxF,eAAW,WAAW,KAAK,MAAM;AACjC,kBAAc,WAAW,UAAU;AACnC,qBAAiB,WAAW,aAAa;AAAA,EAC3C,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,mBAAe,4BAAY,CAAC,OAAe,WAAwC;AACvF,eAAW,aAAa,OAAO,MAAM;AACrC,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,mBAAe,4BAAY,CAAC,UAAkB;AAClD,eAAW,aAAa,KAAK;AAC7B,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,gBAAY,4BAAY,CAAC,OAAe,WAAqC;AACjF,eAAW,UAAU,OAAO,MAAM;AAClC,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,gBAAY,4BAAY,CAAC,UAAkB;AAC/C,eAAW,UAAU,KAAK;AAC1B,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,qBAAiB,4BAAY,CAAC,OAAe,UAAkB;AACnE,eAAW,eAAe,OAAO,KAAK;AACtC,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,yBAAqB,4BAAY,CAAC,OAAe,gBAAyB;AAC9E,eAAW,mBAAmB,OAAO,WAAW;AAChD,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,yBAAqB,4BAAY,CAAC,OAA8B;AACpE,eAAW,mBAAmB,EAAE;AAChC,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,2BAAuB,4BAAY,CAAC,OAA2B;AACnE,eAAW,qBAAqB,EAAE;AAClC,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,qBAAiB,4BAAY,MAAM;AACvC,eAAW,eAAe;AAC1B,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,WAAO,4BAAY,MAAM;AAC7B,eAAW,KAAK;AAChB,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,WAAO,4BAAY,MAAM;AAC7B,eAAW,KAAK;AAChB,WAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAKf,QAAM,mBAAe,wBAAQ,UAAM,gDAA4B,UAAU,GAAG,CAAC,UAAU,CAAC;AAIxF,QAAM,gBAAY,wBAAQ,MAAM,WAAW,aAAa,GAAG,CAAC,YAAY,GAAG,CAAC;AAE5E,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,CAAC,OAAe,UAAkB,WAAW,QAAQ,OAAO,KAAK;AAAA,IAC1E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,CAACC,cAAkC;AAC/C,iBAAW,aAAaA,SAAQ;AAChC,aAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AACjC,oBAAc,IAAI;AAClB,uBAAiB,IAAI;AACrB,qBAAe,IAAI;AACnB,oBAAc,EAAE;AAAA,IAClB;AAAA,IACA,oBAAoB,MAAM;AACxB,iBAAW,mBAAmB;AAC9B,iBAAW,eAAe;AAC1B,aAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,CAAC,UAA6B,WAAW,YAAY,KAAK;AAAA,IACvE,eAAe,CAAC,SAAiB;AAC/B,iBAAW,cAAc,IAAI;AAC7B,aAAO,EAAE,GAAG,WAAW,SAAS,CAAC;AAAA,IACnC;AAAA,IACA,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACpNA,IAAAC,iBAAyE;AACzE,IAAAC,sBAaO;;;ACdP,IAAAC,iBAAoE;AACpE,IAAAC,sBAA4D;AAkEpD,IAAAC,sBAAA;AA/DR,IAAM,kBAAkB;AAUjB,IAAM,yBAAgE,CAAC,EAAE,OAAO,GAAG,GAAG,QAAQ,MAAM;AACzG,QAAM,cAAU,uBAAuB,IAAI;AAC3C,QAAM,iBAAa,uBAAO,OAAO;AACjC,aAAW,UAAU;AACrB,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,EAAE,GAAG,EAAE,CAAC;AAIjD,sCAAgB,MAAM;AACpB,UAAM,OAAO,QAAQ;AACrB,QAAI,CAAC,QAAQ,OAAO,WAAW,YAAa;AAC5C,UAAM,EAAE,OAAO,OAAO,IAAI,KAAK,sBAAsB;AACrD,UAAM,WAAO;AAAA,MACX,EAAE,GAAG,EAAE;AAAA,MACP,EAAE,OAAO,OAAO;AAAA,MAChB,EAAE,OAAO,OAAO,YAAY,QAAQ,OAAO,YAAY;AAAA,MACvD;AAAA,IACF;AACA,gBAAY,CAAC,SAAU,KAAK,MAAM,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,OAAO,IAAK;AAAA,EAC9E,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC;AAEhB,gCAAU,MAAM;AACd,UAAM,gBAAgB,CAAC,MAAkB;AACvC,UAAI,CAAC,QAAQ,SAAS,SAAS,EAAE,MAAc,EAAG,YAAW,QAAQ;AAAA,IACvE;AACA,UAAM,YAAY,CAAC,MAAqB;AACtC,UAAI,EAAE,QAAQ,SAAU,YAAW,QAAQ;AAAA,IAC7C;AACA,WAAO,iBAAiB,aAAa,aAAa;AAClD,WAAO,iBAAiB,WAAW,SAAS;AAC5C,WAAO,MAAM;AACX,aAAO,oBAAoB,aAAa,aAAa;AACrD,aAAO,oBAAoB,WAAW,SAAS;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,MAAK;AAAA,MACL,cAAW;AAAA,MACX,WAAU;AAAA,MACV,OAAO;AAAA,QACL,MAAM,SAAS;AAAA,QACf,KAAK,SAAS;AAAA,QACd,WAAW,gBAAgB,kBAAkB,CAAC;AAAA,QAC9C,WAAW;AAAA,QACX,YAAY;AAAA,MACd;AAAA,MACA,eAAe,CAAC,MAAM,EAAE,eAAe;AAAA,MACvC,WAAW,CAAC,MAAM,EAAE,gBAAgB;AAAA,MAEnC,gBAAM,IAAI,CAAC,SACV,8CAAC,eAAAC,QAAM,UAAN,EACE;AAAA,aAAK,mBAAmB,6CAAC,SAAI,MAAK,aAAY,WAAU,uBAAsB;AAAA,QAC/E;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,eAAa,KAAK;AAAA,YAClB,UAAU,KAAK;AAAA,YACf,WAAU;AAAA,YACV,SAAS,MAAM;AACb,sBAAQ;AACR,mBAAK,IAAI;AAAA,YACX;AAAA,YAEC,eAAK;AAAA;AAAA,QACR;AAAA,WAdmB,KAAK,EAe1B,CACD;AAAA;AAAA,EACH;AAEJ;;;AC1DM,IAAAC,sBAAA;AAfN,IAAM,gBAAgB,CAAC,UAA0B,UAAU,OAAO,WAAM,OAAO,KAAK;AAG7E,IAAM,sBAA0D,CAAC;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AAEJ,QAAM,aAAa,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO,UAAU,IAAI,aAAa,QAAQ,CAAC,GAAG,OAAO;AACrG,SACA,8CAAC,QAAG,WAAU,oDAAmD,kBAAgB,MAAM,KAAK,OAAO,EAAE,QAAQ,GAAG,GAC9G;AAAA,iDAAC,QAAG,WAAU,oFACZ;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,GAAG,MAAM,YAAY,WAAW,UAAU,UAAU,MAAM,KAAK;AAAA,QAC3E,iBAAe,CAAC,MAAM;AAAA,QACtB,WAAU;AAAA,QACV,SAAS,CAAC,MAAM;AACd,YAAE,gBAAgB;AAClB,mBAAS,MAAM,GAAG;AAAA,QACpB;AAAA,QAEC,gBAAM,YAAY,WAAM;AAAA;AAAA,IAC3B,GACF;AAAA,IACC,QAAQ,IAAI,CAAC,EAAE,OAAO,MAAM;AAC3B,YAAM,UAAU,MAAM,UAAU,OAAO,EAAE;AACzC,aACE,6CAAC,QAAmB,WAAU,qEAAoE,OAAO,EAAE,UAAU,GAAG,UAAU,SAAS,GACxI,iBAAO,OAAO,aACb,8CAAC,UAAK,WAAU,YACb;AAAA,cAAM;AAAA,QAAM;AAAA,QAAC,8CAAC,UAAK,WAAU,qCAAoC;AAAA;AAAA,UAAE,MAAM,WAAW;AAAA,UAAO;AAAA,WAAC;AAAA,SAC/F,IACE,YAAY,SACd,6CAAC,UAAK,WAAU,YAAW,gBAAc,OAAO,IAAK,wBAAc,OAAO,GAAE,IAC1E,QAPG,OAAO,EAQhB;AAAA,IAEJ,CAAC;AAAA,IACA,gBAAgB,6CAAC,QAAG,WAAU,0DAAyD;AAAA,KAC1F;AAEF;;;AC1DA,IAAAC,iBAAyE;AACzE,IAAAC,sBAIO;AAMP,SAAS,aAAa,MAAmC;AACvD,MAAI,CAAC,QAAQ,OAAO,aAAa,YAAa,QAAO;AACrD,QAAM,SAAS,SAAS;AACxB,MAAI,CAAC,UAAU,CAAC,KAAK,SAAS,MAAM,EAAG,QAAO;AAC9C,SAAO,EAAE,kBAAkB,oBAAoB,kBAAkB;AACnE;AAWO,SAAS,wBACd,SACA,OACA,UACA;AACA,QAAM,eAAW,uBAAO,KAAK;AAC7B,WAAS,UAAU;AACnB,QAAM,kBAAc,uBAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,QAAM,gBAAY,uBAAO,KAAK;AAE9B,gCAAU,MAAM;AACd,QAAI,OAAO,aAAa,YAAa;AACrC,UAAM,aAAa,CAAC,MAAsB;AACxC,YAAM,IAAI,SAAS;AACnB,UAAI,CAAC,aAAa,QAAQ,OAAO,KAAK,EAAE,eAAe,CAAC,EAAE,iBAAiB,CAAC,EAAE,cAAe;AAC7F,iBAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,EAAE,oBAAoB,EAAE,aAAa,CAAC,GAAG;AACjF,UAAE,cAAc,QAAQ,MAAM,IAAI;AAAA,MACpC;AACA,gBAAU,UAAU;AACpB,QAAE,eAAe;AAAA,IACnB;AACA,UAAM,cAAc,CAAC,MAAsB;AACzC,YAAM,IAAI,SAAS;AACnB,UAAI,YAAY,WAAW,CAAC,aAAa,QAAQ,OAAO,KAAK,EAAE,eAAe,CAAC,EAAE,cAAe;AAChG,UAAI,EAAE,mBAAmB,EAAE,aAAa,EAAG,GAAE,eAAe;AAAA,IAC9D;AACA,aAAS,iBAAiB,QAAQ,UAAU;AAC5C,aAAS,iBAAiB,SAAS,WAAW;AAC9C,WAAO,MAAM;AACX,eAAS,oBAAoB,QAAQ,UAAU;AAC/C,eAAS,oBAAoB,SAAS,WAAW;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAOZ,QAAM,2BAAuB,4BAAY,MAAM;AAC7C,cAAU,UAAU;AACpB,eAAW,MAAM;AACf,UAAI,UAAU,QAAS;AACvB,YAAM,IAAI,SAAS;AAEnB,cAAQ,QAAQ,UAAU,WAAW,UAAU,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAChG,GAAG,CAAC;AAAA,EACN,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,qBAAqB;AAChC;AAMO,SAAS,cAAc,OAAyB;AACrD,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAiE,IAAI;AAC7F,QAAM,cAAU,uBAAO,IAAI;AAC3B,UAAQ,UAAU;AAClB,QAAM,eAAW,uBAAO,KAAK;AAC7B,WAAS,UAAU;AACnB,QAAM,WAAW,SAAS;AAE1B,gCAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,UAAM,gBAAgB,MAAM;AAC1B,YAAM,UAAU,QAAQ;AACxB,cAAQ,IAAI;AACZ,UAAI,SAAS,OAAQ,UAAS,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,MAAM;AAAA,IAC/E;AACA,WAAO,iBAAiB,WAAW,aAAa;AAChD,WAAO,MAAM,OAAO,oBAAoB,WAAW,aAAa;AAAA,EAClE,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,gBAAY,4BAAY,CAAC,MAA2D;AACxF,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAClB,UAAM,QAAQ,SAAS,QAAQ;AAC/B,QAAI,MAAO,SAAQ,EAAE,YAAQ,oCAAe,KAAK,GAAG,QAAQ,KAAK,CAAC;AAAA,EACpE,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAa,4BAAY,CAAC,KAAa,QAAgB;AAC3D,UAAM,UAAU,QAAQ;AACxB,QAAI,CAAC,QAAS;AACd,YAAQ,EAAE,QAAQ,QAAQ,QAAQ,YAAQ,uCAAkB,QAAQ,QAAQ,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,EAC7F,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,YAAY,MAAM,UAAU,MAAM,WAAW,UAAU,WAAW,WAAW;AACxF;;;ACtHA,IAAAC,iBAA6E;AAC7E,IAAAC,sBAAwD;AAkJ1C,IAAAC,sBAAA;AA5HP,IAAM,eAA4C,CAAC,EAAE,UAAU,OAAO,UAAU,QAAQ,EAAE,MAAM;AACrG,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAwB,IAAI;AACtD,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAC5C,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,CAAC;AAC1C,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAS,KAAK;AAChD,QAAM,CAAC,UAAU,WAAW,QAAI,yBAA8D,IAAI;AAClG,QAAM,mBAAe,uBAAsB,IAAI;AAE/C,QAAM,YAAQ;AAAA,IACZ,UAAM,qCAAgB,OAAO,SAAS,MAAM,QAAQ,EAAE,MAAM,CAAC;AAAA,IAC7D,CAAC,OAAO,OAAO,KAAK;AAAA,EACtB;AACA,QAAM,cAAc,YAAY,CAAC,IAAI,MAAM;AAC3C,QAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,UAAU,YAAY,SAAS,CAAC,CAAC;AAC5E,QAAM,UAAU,WAAW,MAAM,UAAU,EAAE,WAAW,GAAG,MAAM,YAAY,SAAS,KAAK,CAAC,CAAC,MAAM;AAGnG,QAAM,aAAS,uBAAO,EAAE,aAAa,UAAU,eAAe,OAAO,OAAO,SAAS,CAAC;AACtF,SAAO,UAAU,EAAE,aAAa,UAAU,eAAe,OAAO,OAAO,SAAS;AAEhF,QAAM,SAAS,CAAC,UAAkB;AAChC,UAAM,EAAE,aAAa,MAAM,OAAO,SAAS,OAAO,IAAI,UAAU,OAAO,IAAI,OAAO;AAClF,UAAM,aAAa,KAAK,KAAK;AAC7B,QAAI,CAAC,WAAY;AACjB,UAAM,WAAO,4CAAuB,SAAS,MAAM,QAAQ,QAAQ,WAAW,IAAI;AAClF,iBAAa,UAAU,KAAK;AAC5B,WAAO,KAAK,KAAK;AAAA,EACnB;AAEA,gCAAU,MAAM;AACd,UAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,MAAO;AACZ,UAAM,YAAY,MAAM,SAAS,MAAM,kBAAkB,MAAM,MAAM,MAAM;AAC3E,UAAM,UAAU,MAAM;AACpB,mBAAa,KAAK;AAClB,kBAAY,CAAC;AACb,gBAAU;AAAA,IACZ;AACA,UAAM,UAAU,MAAM;AACpB,iBAAW,IAAI;AACf,gBAAU;AAAA,IACZ;AACA,UAAM,SAAS,MAAM,WAAW,KAAK;AAGrC,UAAM,YAAY,CAAC,MAAqB;AACtC,YAAM,EAAE,aAAa,KAAK,IAAI,OAAO;AACrC,UAAI,KAAK,WAAW,EAAG;AACvB,UAAI,EAAE,QAAQ,eAAe,EAAE,QAAQ,WAAW;AAChD,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,cAAM,OAAO,EAAE,QAAQ,cAAc,IAAI;AACzC,oBAAY,CAAC,OAAO,IAAI,OAAO,KAAK,UAAU,KAAK,MAAM;AAAA,MAC3D,WAAW,EAAE,QAAQ,SAAS,CAAC,EAAE,UAAU;AACzC,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,eAAO,OAAO,QAAQ,QAAQ;AAAA,MAChC,WAAW,EAAE,QAAQ,UAAU;AAC7B,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,qBAAa,IAAI;AAAA,MACnB;AAAA,IACF;AAEA,UAAM,iBAAiB,SAAS,OAAO;AACvC,UAAM,iBAAiB,SAAS,SAAS;AACzC,UAAM,iBAAiB,SAAS,SAAS;AACzC,UAAM,iBAAiB,UAAU,SAAS;AAC1C,UAAM,iBAAiB,SAAS,OAAO;AACvC,UAAM,iBAAiB,QAAQ,MAAM;AACrC,UAAM,iBAAiB,WAAW,SAAS;AAE3C,QAAI,OAAO,aAAa,eAAe,SAAS,kBAAkB,MAAO,SAAQ;AACjF,WAAO,MAAM;AACX,YAAM,oBAAoB,SAAS,OAAO;AAC1C,YAAM,oBAAoB,SAAS,SAAS;AAC5C,YAAM,oBAAoB,SAAS,SAAS;AAC5C,YAAM,oBAAoB,UAAU,SAAS;AAC7C,YAAM,oBAAoB,SAAS,OAAO;AAC1C,YAAM,oBAAoB,QAAQ,MAAM;AACxC,YAAM,oBAAoB,WAAW,SAAS;AAAA,IAChD;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAGb,sCAAgB,MAAM;AACpB,UAAM,QAAQ,SAAS;AACvB,UAAM,KAAK,aAAa;AACxB,QAAI,CAAC,SAAS,OAAO,QAAQ,MAAM,UAAU,MAAO;AACpD,iBAAa,UAAU;AACvB,UAAM,kBAAkB,IAAI,EAAE;AAC9B,aAAS,EAAE;AACX,gBAAY,CAAC;AAAA,EACf,GAAG,CAAC,OAAO,QAAQ,CAAC;AAEpB,sCAAgB,MAAM;AACpB,UAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,WAAW,CAAC,MAAO;AACxB,UAAM,OAAO,MAAM,sBAAsB;AACzC,gBAAY,EAAE,KAAK,KAAK,SAAS,GAAG,MAAM,KAAK,MAAM,OAAO,KAAK,MAAM,CAAC;AAAA,EAC1E,GAAG,CAAC,SAAS,OAAO,QAAQ,CAAC;AAE7B,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,EAAE,WAAW,IAAI;AACvB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,sBAAmB;AAAA,MACnB,WAAU;AAAA,MACV,OAAO;AAAA,QACL,UAAU;AAAA,QACV,KAAK,UAAU,OAAO;AAAA,QACtB,MAAM,UAAU,QAAQ;AAAA,QACxB,UAAU,KAAK,IAAI,KAAK,UAAU,SAAS,CAAC;AAAA,QAC5C,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY,WAAW,YAAY;AAAA,MACrC;AAAA,MACA,aAAa,CAAC,MAAM,EAAE,eAAe;AAAA,MAEpC;AAAA,sBACC,8CAAC,SAAI,0BAAuB,IAAG,WAAU,kDACvC;AAAA,uDAAC,SAAI,WAAU,aACZ,qBAAW,MAAM,IAAI,CAAC,MAAM,MAC3B;AAAA,YAAC;AAAA;AAAA,cAEC,eAAa,KAAK,SAAS,KAAK;AAAA,cAChC,WAAW,KAAK,SAAS,qCAAqC;AAAA,cAE7D,eAAK;AAAA;AAAA,YAJD;AAAA,UAKP,CACD,GACH;AAAA,UACA,6CAAC,SAAI,WAAU,gCACZ,qBAAW,WACV,8EACE;AAAA,yDAAC,UAAK,WAAU,iBAAiB,qBAAW,SAAS,MAAK;AAAA,YAAO;AAAA,YAAG,WAAW,SAAS;AAAA,aAC1F,IAEA,WAAW,aAEf;AAAA,WACF;AAAA,QAED,YAAY,SAAS,KACpB,6CAAC,QAAG,MAAK,WAAU,cAAW,uBAAsB,WAAU,iDAC3D,sBAAY,IAAI,CAAC,GAAG,MACnB;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,iBAAe,MAAM;AAAA,YACrB,WAAW,4BAA4B,MAAM,gBAAgB,kBAAkB,mBAAmB;AAAA,YAClG,cAAc,MAAM,YAAY,CAAC;AAAA,YACjC,aAAa,CAAC,MAAM;AAElB,gBAAE,eAAe;AACjB,qBAAO,CAAC;AAAA,YACV;AAAA,YAEA;AAAA,2DAAC,SAAI,WAAU,2CAA2C,YAAE,WAAU;AAAA,cACtE,6CAAC,SAAI,WAAU,kCAAkC,YAAE,aAAY;AAAA;AAAA;AAAA,UAZ1D,EAAE;AAAA,QAaT,CACD,GACH;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AJyQM,IAAAC,sBAAA;AAlbN,IAAM,uBAAuB;AAC7B,IAAM,mBAAmB;AAGzB,SAAS,gBACP,SACA,SACiC;AACjC,MAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,OAAQ,QAAO;AAC/C,SAAO;AAAA,IACL,UAAU;AAAA,IACV,GAAI,QAAQ,SAAS,EAAE,KAAK,uBAAuB,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC1E,GAAI,QAAQ,SAAS,EAAE,MAAM,mBAAmB,QAAQ,WAAW,IAAI,CAAC;AAAA,IACxE,QAAQ,QAAQ,UAAU,QAAQ,SAAS,KAAK,QAAQ,SAAS,KAAK;AAAA,IACtE,YAAY;AAAA,EACd;AACF;AAGA,IAAM,WAAW,CAAC,SAA+C,OAAO,OAAG,oCAAe,KAAK,GAAG,CAAC,GAAG,KAAK,MAAM,CAAC,KAAK;AAGvH,SAAS,iBAAiB,OAAkB,KAAa,KAAkC;AACzF,QAAM,OAAO;AACb,SAAO;AAAA,IACL,UAAU;AAAA,IACV,OAAO;AAAA,IACP,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,WAAW,QAAQ,MAAM,WAAW,OAAO;AAAA,IAC3C,cAAc,QAAQ,MAAM,SAAS,OAAO;AAAA,IAC5C,YAAY,QAAQ,MAAM,WAAW,OAAO;AAAA,IAC5C,aAAa,QAAQ,MAAM,SAAS,OAAO;AAAA,EAC7C;AACF;AAWO,IAAM,oBAAsD,CAAC;AAAA,EAClE,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,eAAe,qBAAqB;AAC1C,QAAM,QAAQ,iBAAiB;AAC/B,QAAM,cAAU,uBAAuB,IAAI;AAC3C,QAAM,oBAAgB,uBAAyB,IAAI;AACnD,QAAM,mBAAe,uBAAyB,IAAI;AAElD,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAAwB,IAAI;AACtE,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAwB,IAAI;AACpE,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,CAAC;AAClD,QAAM,CAAC,kBAAkB,mBAAmB,QAAI,yBAAS,CAAC;AAG1D,QAAM,OAAO,MAAM;AACnB,QAAM,EAAE,qBAAqB,IAAI,wBAAwB,SAAS,OAAO,QAAQ;AACjF,QAAM,EAAE,YAAY,WAAW,WAAW,IAAI,cAAc,KAAK;AACjE,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAwE,IAAI;AACpG,QAAM,SAAS,MAAM,SAAS,OAAO;AACrC,QAAM,qBAAiB;AAAA,IACrB,MAAM,IAAI,IAAI,QAAQ,UAAU,OAAO,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,CAAC;AAAA,IACrE,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,4BAAwB,4BAAY,CAAC,MAAc,MAAc,MAAwB;AAC7F,QAAI,SAAU;AACd,MAAE,eAAe;AACjB,QAAI,MAAM,YAAa,OAAM,cAAc;AAC3C,QAAI,CAAC,MAAM,iBAAiB,KAAC,mCAAc,MAAM,eAAe,MAAM,IAAI,GAAG;AAC3E,YAAM,WAAW,MAAM,IAAI;AAAA,IAC7B;AACA,YAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,SAAS,WAAO,6CAAwB,MAAM,YAAY,EAAE,KAAK,MAAM,KAAK,KAAK,CAAC,EAAE,CAAC;AAAA,EACpH,GAAG,CAAC,UAAU,KAAK,CAAC;AAEpB,QAAM,qBAAiB,wBAAQ,MAAM;AACnC,QAAI,CAAC,MAAM,WAAY,QAAO;AAC9B,UAAM,MAAM,MAAM,SAAS,KAAK,MAAM,WAAW,GAAG;AACpD,UAAM,MAAM,MAAM,SAAS,QAAQ,MAAM,WAAW,GAAG;AACvD,QAAI,CAAC,OAAO,CAAC,IAAK,QAAO;AACzB,WAAO,MAAM,QAAQ,IAAI,IAAI,IAAI,EAAE,EAAE;AAAA,EACvC,GAAG,CAAC,MAAM,YAAY,MAAM,QAAQ,CAAC;AAIrC,QAAM,kBAAc;AAAA,IAClB,MAAO,MAAM,aAAa,MAAM,WAAW,WAAW,MAAM,WAAW,KAAK,MAAM,WAAW,GAAG,IAAI;AAAA;AAAA,IAEpG,CAAC,MAAM,YAAY,MAAM,YAAY,MAAM,QAAQ;AAAA,EACrD;AACA,QAAM,eAAe,eAAe,CAAC,kBAAkB,YAAY,QAAQ,SAAS,MAAM,UAAU,IAAI,YAAY,UAAU;AAE9H,QAAM,iBAAa,wBAAQ,MAAM;AAC/B,QAAI,CAAC,MAAM,WAAY,QAAO;AAC9B,UAAM,cAAU,oCAAe,MAAM,WAAW,GAAG;AACnD,WAAO,GAAG,OAAO,GAAG,MAAM,WAAW,MAAM,CAAC;AAAA,EAC9C,GAAG,CAAC,MAAM,UAAU,CAAC;AAGrB,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAwB,IAAI;AACpE,QAAM,eAAe,MAAM,aAAa,MAAM,SAAS,QAAQ,MAAM,WAAW,GAAG,IAAI;AACvF,QAAM,qBAAqB,YAAY,CAAC,MAAM,cAAc,CAAC,CAAC,cAAc;AAE5E,gCAAU,MAAM;AACd,oBAAgB,IAAI;AAAA,EACtB,GAAG,CAAC,MAAM,YAAY,KAAK,MAAM,YAAY,GAAG,CAAC;AAEjD,QAAM,mBAAmB,MAAM;AAC7B,QAAI,MAAM,aAAa;AACrB,YAAM,cAAc;AACpB;AAAA,IACF;AACA,QAAI,iBAAiB,QAAQ,CAAC,MAAM,WAAY;AAChD,UAAM,MAAM,MAAM,SAAS,KAAK,MAAM,WAAW,GAAG;AACpD,UAAM,MAAM,MAAM,SAAS,QAAQ,MAAM,WAAW,GAAG;AACvD,QAAI,OAAO,OAAO,CAAC,sBAAsB,iBAAiB,gBAAgB;AACxE,YAAM,aAAa,IAAI,IAAI,IAAI,IAAI,YAAY;AAAA,IACjD;AACA,oBAAgB,IAAI;AAAA,EACtB;AAEA,QAAM,sBAAkB,4BAAY,CAAC,MAAc,MAAc,MAAwB;AACvF,QAAI,MAAM,gBAAgB,MAAM,YAAY,QAAQ,QAAQ,MAAM,YAAY,QAAQ,OAAO;AAC3F,YAAM,cAAc;AAAA,IACtB;AACA,UAAM,WAAW,MAAM,MAAM,EAAE,QAAQ;AAAA,EACzC,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,yBAAqB,4BAAY,CAAC,MAAc,SAAiB;AACrE,QAAI,SAAU;AACd,UAAM,MAAM,MAAM,SAAS,QAAQ,IAAI;AACvC,QAAI,KAAK,SAAU;AACnB,UAAM,aAAa,MAAM,IAAI;AAAA,EAC/B,GAAG,CAAC,UAAU,KAAK,CAAC;AAEpB,QAAM,oBAAgB,4BAAY,CAAC,MAA2B;AAC5D,QAAI,MAAM,aAAa;AACrB,UAAI,EAAE,QAAQ,SAAS;AACrB,UAAE,eAAe;AACjB,cAAM,cAAc;AACpB,cAAM,WAAW,MAAM;AAAA,MACzB,WAAW,EAAE,QAAQ,UAAU;AAC7B,UAAE,eAAe;AACjB,cAAM,cAAc;AAAA,MACtB,WAAW,EAAE,QAAQ,OAAO;AAC1B,UAAE,eAAe;AACjB,cAAM,cAAc;AACpB,cAAM,WAAW,EAAE,WAAW,SAAS,OAAO;AAAA,MAChD,OAAO;AACL;AAAA,MACF;AAEA,cAAQ,SAAS,MAAM;AACvB;AAAA,IACF;AAEA,QAAI,CAAC,MAAM,WAAY;AAEvB,QAAI,EAAE,QAAQ,WAAW;AACvB,QAAE,eAAe;AACjB,YAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACnC,WAAW,EAAE,QAAQ,aAAa;AAChC,QAAE,eAAe;AACjB,YAAM,WAAW,QAAQ,EAAE,QAAQ;AAAA,IACrC,WAAW,EAAE,QAAQ,aAAa;AAChC,QAAE,eAAe;AACjB,YAAM,WAAW,QAAQ,EAAE,QAAQ;AAAA,IACrC,WAAW,EAAE,QAAQ,cAAc;AACjC,QAAE,eAAe;AACjB,YAAM,WAAW,SAAS,EAAE,QAAQ;AAAA,IACtC,WAAW,EAAE,QAAQ,OAAO;AAC1B,QAAE,eAAe;AACjB,YAAM,WAAW,EAAE,WAAW,SAAS,OAAO;AAAA,IAChD,WAAW,EAAE,QAAQ,SAAS;AAC5B,QAAE,eAAe;AACjB,YAAM,MAAM,MAAM,SAAS,QAAQ,MAAM,WAAW,GAAG;AACvD,UAAI,CAAC,YAAY,CAAC,KAAK,UAAU;AAC/B,cAAM,aAAa;AAAA,MACrB;AAAA,IACF,WAAW,EAAE,QAAQ,eAAe,EAAE,QAAQ,UAAU;AACtD,UAAI,SAAU;AACd,YAAM,MAAM,MAAM,SAAS,KAAK,MAAM,WAAW,GAAG;AACpD,YAAM,MAAM,MAAM,SAAS,QAAQ,MAAM,WAAW,GAAG;AACvD,UAAI,OAAO,OAAO,CAAC,IAAI,UAAU;AAC/B,UAAE,eAAe;AACjB,cAAM,aAAa,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA,MACvC;AAAA,IACF,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,YAAY,MAAM,KAAK;AAElE,QAAE,eAAe;AACjB,UAAI,EAAE,UAAU;AACd,cAAM,KAAK;AAAA,MACb,OAAO;AACL,cAAM,KAAK;AAAA,MACb;AAAA,IACF,WAAW,EAAE,WAAW,CAAC,EAAE,WAAW,EAAE,IAAI,YAAY,MAAM,KAAK;AACjE,QAAE,eAAe;AACjB,YAAM,KAAK;AAAA,IACb,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,YAAY,MAAM,KAAK;AAGlE,2BAAqB;AAAA,IACvB,WAAW,CAAC,YAAY,EAAE,IAAI,WAAW,KAAK,CAAC,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,EAAE,QAAQ;AACnF,YAAM,MAAM,MAAM,SAAS,QAAQ,MAAM,WAAW,GAAG;AACvD,UAAI,CAAC,KAAK,UAAU;AAGlB,UAAE,eAAe;AACjB,cAAM,aAAa,MAAM,WAAW,KAAK,MAAM,WAAW,KAAK,EAAE,GAAG;AAAA,MACtE;AAAA,IACF;AAAA,EACF,GAAG,CAAC,UAAU,OAAO,oBAAoB,CAAC;AAG1C,QAAM,eAAW,uBAAO,KAAK;AAC7B,WAAS,UAAU;AACnB,QAAM,wBAAoB,uBAAO,cAAc;AAC/C,oBAAkB,UAAU;AAE5B,gCAAU,MAAM;AACd,QAAI,CAAC,cAAe;AAEpB,QAAI,OAAO,aAAa,aAAa;AACnC,eAAS,KAAK,MAAM,SAAS;AAC7B,eAAS,KAAK,MAAM,aAAa;AAAA,IACnC;AAEA,QAAI,QAAuB;AAC3B,QAAI,eAAe;AACnB,QAAI,aAAa;AAEjB,UAAM,kBAAkB,CAAC,MAAkB;AACzC,YAAM,QAAQ,EAAE,UAAU;AAC1B,UAAI,KAAK,IAAI,KAAK,IAAI,GAAG;AACvB,qBAAa;AAAA,MACf;AACA,qBAAe,KAAK,IAAI,IAAI,mBAAmB,KAAK;AAEpD,UAAI,UAAU,MAAM;AAClB,gBAAQ,sBAAsB,MAAM;AAClC,kBAAQ;AACR,mBAAS,QAAQ,eAAe,eAAe,YAAY;AAAA,QAC7D,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM;AAC1B,UAAI,UAAU,MAAM;AAClB,6BAAqB,KAAK;AAC1B,gBAAQ;AAAA,MACV;AACA,UAAI,YAAY;AACd,iBAAS,QAAQ,eAAe,eAAe,YAAY;AAC3D,0BAAkB,UAAU,eAAe,YAAY;AAAA,MACzD;AACA,uBAAiB,IAAI;AACrB,UAAI,OAAO,aAAa,aAAa;AACnC,iBAAS,KAAK,MAAM,SAAS;AAC7B,iBAAS,KAAK,MAAM,aAAa;AAAA,MACnC;AAAA,IACF;AAEA,WAAO,iBAAiB,aAAa,eAAe;AACpD,WAAO,iBAAiB,WAAW,aAAa;AAChD,WAAO,MAAM;AACX,UAAI,UAAU,MAAM;AAClB,6BAAqB,KAAK;AAAA,MAC5B;AACA,UAAI,OAAO,aAAa,aAAa;AACnC,iBAAS,KAAK,MAAM,SAAS;AAC7B,iBAAS,KAAK,MAAM,aAAa;AAAA,MACnC;AACA,aAAO,oBAAoB,aAAa,eAAe;AACvD,aAAO,oBAAoB,WAAW,aAAa;AAAA,IACrD;AAAA,EACF,GAAG,CAAC,eAAe,cAAc,gBAAgB,CAAC;AAElD,QAAM,iCAA6B,4BAAY,CAAC,IAAiB,cAAmC;AAClG,QAAI,OAAO,aAAa,YAAa,QAAO;AAE5C,QAAI,OAAO,GAAG,eAAe;AAC7B,UAAM,aAAa,GAAG;AACtB,QAAI,cAAc,WAAW,cAAc,MAAM;AAC/C,aAAO,WAAW;AAAA,IACpB;AAEA,UAAM,YAAY,GAAG,iBAA8B,+BAA+B;AAClF,cAAU,QAAQ,CAAC,SAAS;AAC1B,UAAI,KAAK,cAAc,MAAM;AAC3B,eAAO,KAAK;AAAA,MACd;AAAA,IACF,CAAC;AAED,QAAI;AACF,YAAM,QAAS,aAAa,WAAW,UAAU,IAAI,IAAI,GAAG,UAAU,IAAI;AAC1E,YAAM,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAatB,YAAM,WAAW,MAAM,iBAA8B,GAAG;AACxD,eAAS,QAAQ,CAAC,SAAS;AACzB,aAAK,MAAM,WAAW;AACtB,aAAK,MAAM,WAAW;AACtB,aAAK,MAAM,eAAe;AAC1B,aAAK,MAAM,aAAa;AACxB,YACE,KAAK,UAAU,SAAS,UAAU,KAClC,KAAK,UAAU,SAAS,SAAS,KACjC,KAAK,UAAU,SAAS,QAAQ,KAChC,KAAK,UAAU,SAAS,SAAS,KACjC,KAAK,UAAU,SAAS,QAAQ,GAChC;AACA,eAAK,MAAM,QAAQ;AACnB,eAAK,MAAM,WAAW;AAAA,QACxB;AAAA,MACF,CAAC;AAED,gBAAU,YAAY,KAAK;AAC3B,YAAM,OAAO,MAAM,sBAAsB;AACzC,gBAAU,YAAY,KAAK;AAE3B,UAAI,KAAK,QAAQ,MAAM;AACrB,eAAO,KAAK;AAAA,MACd;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAgB,4BAAY,CAAC,OAAe,aAAqB;AACrE,UAAM,MAAM,MAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK;AAC7D,QAAI,CAAC,IAAK;AAEV,QAAI,kBAAkB;AAEtB,QAAI,QAAQ,WAAW,OAAO,aAAa,aAAa;AACtD,YAAM,QAAQ,QAAQ,QAAQ,cAAc,OAAO;AACnD,UAAI,OAAO;AAET,cAAM,KAAK,MAAM,cAAc,sBAAsB,QAAQ,IAAI;AACjE,YAAI,IAAI;AACN,gBAAM,cAAe,GAAG,qBAAqC;AAC7D,gBAAM,UAAU,2BAA2B,aAAa,QAAQ,OAAO;AACvE,4BAAkB,KAAK,IAAI,iBAAiB,UAAU,EAAE;AAAA,QAC1D;AAEA,cAAM,OAAO,MAAM,iBAAiB,UAAU;AAC9C,cAAM,cAAc,KAAK,IAAI,KAAK,QAAQ,GAAG;AAC7C,iBAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,gBAAM,KAAK,KAAK,CAAC;AACjB,gBAAM,KAAK,GAAG,cAAc,gBAAgB,QAAQ,iBAAiB;AACrE,cAAI,IAAI;AACN,kBAAM,QAAQ,2BAA2B,IAAI,QAAQ,OAAO;AAC5D,8BAAkB,KAAK,IAAI,iBAAiB,QAAQ,EAAE;AAAA,UACxD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,kBAAkB,GAAG;AACvB,YAAM,aAAa,KAAK,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,eAAe,CAAC,CAAC;AACzE,YAAM,eAAe,OAAO,UAAU;AAAA,IACxC,OAAO;AACL,YAAM,qBAAqB,KAAK;AAAA,IAClC;AAEA,UAAM,aAAa,MAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK;AACpE,QAAI,cAAc,gBAAgB;AAChC,qBAAe,WAAW,IAAI,WAAW,SAAS,GAAG;AAAA,IACvD;AAAA,EACF,GAAG,CAAC,OAAO,4BAA4B,cAAc,CAAC;AAEtD,QAAM,2BAAuB,4BAAY,CAAC,OAAe,UAAkB,MAAwB;AACjG,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAClB,kBAAc,OAAO,QAAQ;AAAA,EAC/B,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,2BAAuB,4BAAY,CAAC,OAAe,UAAkB,MAAwB;AACjG,UAAM,SAAS,EAAE;AACjB,QAAI,QAAQ;AACV,YAAM,OAAO,OAAO,sBAAsB;AAC1C,UAAI,KAAK,QAAQ,EAAE,WAAW,IAAI;AAChC,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,sBAAc,OAAO,QAAQ;AAAA,MAC/B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,iBAAiB,CAAC,MAAc,SAAiB;AACrD,QAAI,CAAC,MAAM,cAAe,QAAO;AACjC,UAAM,OAAO,KAAK,IAAI,MAAM,cAAc,UAAU,MAAM,cAAc,MAAM;AAC9E,UAAM,OAAO,KAAK,IAAI,MAAM,cAAc,UAAU,MAAM,cAAc,MAAM;AAC9E,UAAM,OAAO,KAAK,IAAI,MAAM,cAAc,UAAU,MAAM,cAAc,MAAM;AAC9E,UAAM,OAAO,KAAK,IAAI,MAAM,cAAc,UAAU,MAAM,cAAc,MAAM;AAC9E,WAAO,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ;AAAA,EACjE;AAEA,QAAM,eAAe,CAAC,MAAc,SAAiB;AACnD,WAAO,MAAM,YAAY,QAAQ,QAAQ,MAAM,YAAY,QAAQ;AAAA,EACrE;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAU;AAAA,MACV,UAAU;AAAA,MACV,WAAW;AAAA,MACX,MAAK;AAAA,MACL,cAAW;AAAA,MAGX;AAAA,sDAAC,SAAI,WAAU,4FACb;AAAA,uDAAC,SAAI,WAAU,qIACZ,sBACH;AAAA,UACA,6CAAC,SAAI,WAAU,uDACb,uDAAC,UAAK,WAAU,oDAAmD,gBAAE,GACvE;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,MAAK;AAAA,cACL,WAAU;AAAA,cACV,aAAY;AAAA,cACZ,cAAW;AAAA,cACX,UAAU;AAAA,cACV,sBAAoB,CAAC,MAAM,eAAe,iBAAiB,QAAQ,eAAe,SAAS;AAAA,cAC3F,OAAO,CAAC,MAAM,eAAe,iBAAiB,QAAQ,eAAe,EAAE,OAAO,mCAAmC,IAAI;AAAA,cACrH,OAAO,MAAM,cAAc,MAAM,aAAa,iBAAiB,kBAAkB;AAAA,cACjF,SAAS,MAAM;AACb,oBAAI,CAAC,MAAM,YAAa,iBAAgB,cAAc;AAAA,cACxD;AAAA,cACA,UAAU,CAAC,MAAM;AACf,oBAAI,MAAM,aAAa;AACrB,wBAAM,cAAc,EAAE,OAAO,KAAK;AAAA,gBACpC,WAAW,MAAM,YAAY;AAC3B,kCAAgB,EAAE,OAAO,KAAK;AAAA,gBAChC;AAAA,cACF;AAAA,cACA,QAAQ,MAAM,iBAAiB;AAAA,cAC/B,WAAW,CAAC,MAAM;AAEhB,kBAAE,gBAAgB;AAClB,oBAAI,EAAE,QAAQ,SAAS;AACrB,oBAAE,eAAe;AACjB,mCAAiB;AAAA,gBACnB,WAAW,EAAE,QAAQ,UAAU;AAC7B,oBAAE,eAAe;AACjB,kCAAgB,IAAI;AACpB,sBAAI,MAAM,YAAa,OAAM,cAAc;AAAA,gBAC7C;AAAA,cACF;AAAA;AAAA,UACF;AAAA,UACC,CAAC,sBACA;AAAA,YAAC;AAAA;AAAA,cACC,UAAU;AAAA,cACV,OAAO,MAAM,cAAc,MAAM,aAAa,gBAAgB;AAAA,cAC9D,UAAU,CAAC,SAAU,MAAM,cAAc,MAAM,cAAc,IAAI,IAAI,gBAAgB,IAAI;AAAA;AAAA,UAC3F;AAAA,WAEJ;AAAA,QAGA,6CAAC,SAAI,WAAU,iCACb,wDAAC,WAAM,WAAU,gDACf;AAAA,uDAAC,WACC,wDAAC,QAAG,WAAU,mEACZ;AAAA,yDAAC,QAAG,WAAU,kIAAiI,eAE/I;AAAA,YACC,KAAK,QAAQ,IAAI,CAAC,EAAE,QAAQ,KAAK,OAAO,MAAM,QAAQ,WAAW,MAChE;AAAA,cAAC;AAAA;AAAA,gBAEC,YAAU;AAAA,gBACV,WAAW,sJACT,sBAAsB,mBAAmB,gBAC3C;AAAA,gBACA,OAAO;AAAA,kBACL,OAAO,IAAI,SAAS;AAAA,kBACpB,UAAU,IAAI,SAAS;AAAA,kBACvB,UAAU,IAAI,SAAS;AAAA,kBACvB,UAAU;AAAA,kBACV,GAAI,SAAS,EAAE,UAAU,UAAU,MAAM,mBAAmB,YAAY,QAAQ,IAAI,YAAY,wBAAwB,IAAI,CAAC;AAAA,gBAC/H;AAAA,gBACA,SAAS,MAAM,sBAAsB,GAAG;AAAA,gBACxC,eAAe,CAAC,MAAM,qBAAqB,IAAI,IAAI,MAAM,CAAC;AAAA,gBAE1D;AAAA,gEAAC,SAAI,WAAU,4EACb;AAAA,iEAAC,UAAK,WAAU,0DAA0D,cAAI,OAAM;AAAA,oBACnF,eAAe,IAAI,IAAI,EAAE,KACxB,6CAAC,UAAK,WAAU,qCAAoC,OAAM,YAAW,iBAAc,QAAO,oBAAC;AAAA,oBAE7F,8CAAC,UAAK,WAAU,uEAAsE;AAAA;AAAA,sBAAE,IAAI;AAAA,sBAAI;AAAA,uBAAC;AAAA,qBACnG;AAAA,kBAEA;AAAA,oBAAC;AAAA;AAAA,sBACC,WAAU;AAAA,sBACV,OAAO,EAAE,UAAU,YAAY,KAAK,GAAG,QAAQ,GAAG,OAAO,IAAI,OAAO,IAAI,QAAQ,cAAc,QAAQ,IAAI,SAAS,QAAQ,gBAAgB,UAAU,aAAa,OAAO;AAAA,sBACzK,cAAc,MAAM,gBAAgB,IAAI,EAAE;AAAA,sBAC1C,cAAc,MAAM,gBAAgB,CAAC,QAAQ,QAAQ,IAAI,KAAK,OAAO,GAAG;AAAA,sBACxE,aAAa,CAAC,MAAM;AAClB,0BAAE,eAAe;AACjB,0BAAE,gBAAgB;AAClB,yCAAiB,IAAI,EAAE;AACvB,wCAAgB,EAAE,OAAO;AACzB,4CAAoB,IAAI,SAAS,GAAG;AAAA,sBACtC;AAAA,sBACA,eAAe,CAAC,MAAM,qBAAqB,IAAI,IAAI,MAAM,CAAC;AAAA,sBAC1D,MAAK;AAAA,sBACL,oBAAiB;AAAA,sBAEjB;AAAA,wBAAC;AAAA;AAAA,0BACC,WAAU;AAAA,0BACV,OAAO;AAAA,4BACL,OAAO;AAAA,4BACP,QAAQ;AAAA,4BACR,eAAe;AAAA,4BACf,YAAY;AAAA,4BACZ,iBAAiB,kBAAkB,IAAI,KAAK,4BAA4B,iBAAiB,IAAI,KAAK,iEAAiE;AAAA,0BACrK;AAAA;AAAA,sBACF;AAAA;AAAA,kBACF;AAAA;AAAA;AAAA,cAjDK,IAAI;AAAA,YAkDX,CACD;AAAA,YACA,oBACC;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,SAAS;AAAA,gBACT,OAAM;AAAA,gBAEN,uDAAC,UAAK,WAAU,2CAA0C,eAAC;AAAA;AAAA,YAC7D;AAAA,aAEJ,GACF;AAAA,UACA,6CAAC,WACE,eAAK,KAAK,IAAI,CAAC,YAAY;AAC1B,gBAAI,QAAQ,SAAS,SAAS;AAC5B,qBACE;AAAA,gBAAC;AAAA;AAAA,kBAEC,OAAO,QAAQ;AAAA,kBACf,SAAS,KAAK;AAAA,kBACd,YAAY,MAAM,SAAS,OAAO,UAAU,SAAS;AAAA,kBACrD,UAAU,MAAM;AAAA,kBAChB,cAAc,CAAC,CAAC;AAAA;AAAA,gBALX,SAAS,QAAQ,MAAM,GAAG;AAAA,cAMjC;AAAA,YAEJ;AACA,kBAAM,kBAAkB,QAAQ;AAChC,kBAAM,YAAY,MAAM,oBAAgB,oCAAe,MAAM,aAAa,IAAI;AAC9E,mBACA;AAAA,cAAC;AAAA;AAAA,gBAEC,YAAU;AAAA,gBACV,WAAW,8DAA8D,QAAQ,YAAY,SAAS,8BAA8B,EAAE;AAAA,gBACtI,OAAO,EAAE,QAAQ,QAAQ,IAAI,UAAU,GAAG;AAAA,gBAE1C;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,WAAU;AAAA,sBACV,OAAO,QAAQ,SAAS,EAAE,KAAK,uBAAuB,QAAQ,WAAW,QAAQ,GAAG,IAAI;AAAA,sBAEvF,4BAAkB;AAAA;AAAA,kBACrB;AAAA,kBACC,KAAK,QAAQ,IAAI,CAAC,YAAY;AAE7B,0BAAM,OAAO,KAAK,YAAY,iBAAiB,QAAQ,KAAK;AAC5D,wBAAI,CAAC,KAAM,QAAO;AAClB,0BAAM,OAAO,KAAK,OAAO;AACzB,0BAAM,OAAO,KAAK,OAAO;AACzB,0BAAM,MAAM,MAAM,SAAS,KAAK,IAAI;AACpC,0BAAM,MAAM,MAAM,SAAS,QAAQ,IAAI;AACvC,0BAAM,OAAO,MAAM,QAAQ,IAAI,IAAI,IAAI,EAAE;AACzC,0BAAM,WAAW,eAAe,MAAM,IAAI;AAC1C,0BAAM,SAAS,aAAa,MAAM,IAAI;AACtC,0BAAM,YAAY,MAAM,aAAa,QAAQ,QAAQ,MAAM,aAAa,QAAQ;AAEhF,0BAAM,gBAAgB,CAAC,CAAC,cAAc,CAAC,gBAAY,mCAAc,YAAY,iBAAiB,QAAQ,KAAK;AAC3G,0BAAM,iBACJ,CAAC,YACD,CAAC,aACD,CAAC,CAAC,cACD,KAAK,YACF,mCAAc,KAAK,OAAO,UAAU,QAAQ,UAAU,MAAM,IAC5D,UAAU,WAAW,QAAQ,UAAU,WAAW;AAExD,2BACE;AAAA,sBAAC;AAAA;AAAA,wBAEC,YAAU;AAAA,wBACV,YAAU;AAAA,wBACV,SAAS,KAAK;AAAA,wBACd,SAAS,KAAK;AAAA,wBACd,WAAW,gGACT,WAAW,kBAAkB,EAC/B,IAAI,SAAS,wCAAwC,EAAE,IAAI,QAAQ,SAAS,kBAAkB,EAAE;AAAA,wBAChG,OAAO;AAAA,0BACL,UAAU;AAAA,0BACV,UAAU;AAAA,0BACV,GAAG,gBAAgB,SAAS,OAAO;AAAA,0BACnC,GAAI,gBAAgB,EAAE,SAAS,sCAAsC,eAAe,GAAG,IAAI,CAAC;AAAA,wBAC9F;AAAA,wBACA,SAAS,CAAC,MAAM,gBAAgB,MAAM,MAAM,CAAC;AAAA,wBAC7C,eAAe,MAAM,mBAAmB,MAAM,IAAI;AAAA,wBAClD,eAAe,CAAC,MAAM,sBAAsB,MAAM,MAAM,CAAC;AAAA,wBACzD,aAAa,MAAM,WAAW,iBAAiB,QAAQ,KAAK;AAAA,wBAE3D;AAAA,sCACC,8EACE;AAAA;AAAA,8BAAC;AAAA;AAAA,gCACC,KAAK;AAAA,gCACL,MAAK;AAAA,gCACL,WAAU;AAAA,gCACV,OAAO,MAAM;AAAA,gCACb,UAAU,CAAC,MAAM,MAAM,cAAc,EAAE,OAAO,KAAK;AAAA,gCACnD,QAAQ,MAAM,MAAM,cAAc;AAAA,gCAClC,SAAS,CAAC,MAAM;AAEd,wCAAM,MAAM,EAAE,cAAc,MAAM;AAClC,oCAAE,cAAc,kBAAkB,KAAK,GAAG;AAAA,gCAC5C;AAAA,gCACA,WAAS;AAAA;AAAA,4BACX;AAAA,4BACA,6CAAC,gBAAa,UAAU,cAAc,OAAO,MAAM,YAAY,UAAU,MAAM,eAAe;AAAA,6BAChG,IACE,qBACF,mBAAmB,EAAE,KAAK,KAAK,KAAK,CAAC,IAErC;AAAA,4BAAC;AAAA;AAAA,8BACC,WAAW,6BAA6B,KAAK,QAAQ,mCAAmC,EAAE;AAAA,8BAC1F,OAAO,KAAK,QAAQ,KAAK,gBAAgB,KAAK,QAAQ;AAAA,8BAErD,qDAAkB,IAAI;AAAA;AAAA,0BACzB;AAAA,0BAED,mBAAe,mCAAc,YAAY,OAAO,MAAM,IAAI,KACzD,6CAAC,UAAK,eAAY,QAAO,WAAU,4BAA2B,OAAO,iBAAiB,YAAY,OAAO,MAAM,IAAI,GAAG;AAAA,0BAEvH,kBACC;AAAA,4BAAC;AAAA;AAAA,8BACC,WAAU;AAAA,8BACV,cAAW;AAAA,8BACX,aAAa;AAAA,8BACb,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,8BAClC,OAAO,EAAE,UAAU,YAAY,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,2BAA2B,QAAQ,aAAa,QAAQ,GAAG;AAAA;AAAA,0BAClJ;AAAA;AAAA;AAAA,sBAzDG,QAAQ,OAAO;AAAA,oBA2DtB;AAAA,kBAEJ,CAAC;AAAA,kBACA,oBAAoB,6CAAC,QAAG,WAAU,0DAAyD;AAAA;AAAA;AAAA,cAjGvF,QAAQ,IAAI;AAAA,YAkGnB;AAAA,UAEF,CAAC,GACH;AAAA,WACF,GACF;AAAA,QACC,QACC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,KAAK;AAAA,YACZ,GAAG,KAAK;AAAA,YACR,GAAG,KAAK;AAAA,YACR,SAAS,MAAM;AACb,sBAAQ,IAAI;AACZ,sBAAQ,SAAS,MAAM;AAAA,YACzB;AAAA;AAAA,QACF;AAAA,QAEF,6CAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAgBN;AAAA;AAAA;AAAA,EACJ;AAEJ;;;AK1tBA,IAAAC,iBAA0D;AAUxD,IAAAC,sBAAA;AAFF,IAAM,eAA+B;AAAA,EACpC,QAAQ,CAAC,UACR;AAAA,IAAC;AAAA;AAAA,MACA,MAAK;AAAA,MACL,WAAW,gBAAgB,MAAM,aAAa,EAAE;AAAA,MAChD,SAAS,MAAM;AAAA,MACf,UAAU,MAAM;AAAA,MAEf,gBAAM;AAAA;AAAA,EACR;AAAA,EAED,SAAS,CAAC,UACT,6CAAC,SAAI,WAAW,8BAA8B,MAAM,aAAa,EAAE,IAAI,OAAO,OAAO,MAAM,OAAO,GAChG,gBAAM,UACR;AAAA,EAED,YAAY,CAAC,UACZ,8CAAC,SAAI,WAAW,0DAA0D,MAAM,aAAa,EAAE,IAC9F;AAAA,kDAAC,SAAI,WAAU,2BACb;AAAA,YAAM;AAAA,MACP,6CAAC,UAAK,WAAU,iBAAiB,gBAAM,OAAM;AAAA,OAC9C;AAAA,IACC,MAAM,WACN,6CAAC,YAAO,MAAK,UAAS,SAAS,MAAM,SAAS,WAAU,gCAA+B,kBAEvF;AAAA,KAEF;AAEF;AAEA,IAAM,yBAAqB,8BAA8B,YAAY;AAU9D,SAAS,oBAAoB,EAAE,OAAO,SAAS,GAA6B;AAClF,QAAM,kBAAc,wBAAQ,OAAO,EAAE,GAAG,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;AAE1E,SACC,6CAAC,mBAAmB,UAAnB,EAA4B,OAAO,aAClC,UACF;AAEF;AAKO,SAAS,iBAAiC;AAChD,aAAO,2BAAW,kBAAkB;AACrC;;;AChEA,IAAAC,iBAAkE;AAClE,0BAcO;AA+CA,SAAS,eAAe,UAA8B,CAAC,GAAyB;AACrF,QAAM,oBAAgB,uBAAqC,IAAI;AAE/D,MAAI,CAAC,cAAc,SAAS;AAC1B,kBAAc,UAAU,IAAI,0CAAsB,OAAO;AAAA,EAC3D;AAEA,QAAM,aAAa,cAAc;AACjC,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAA2B,MAAM,WAAW,SAAS,CAAC;AAChF,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,CAAC;AAElD,gCAAU,MAAM;AACd,UAAM,QAAQ,WAAW,UAAU,CAAC,SAAS;AAC3C,eAAS,IAAI;AACb,sBAAgB,CAAC,MAAM,IAAI,CAAC;AAAA,IAC9B,CAAC;AACD,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,CAAC;AAKf,QAAM,qBAAiB,uBAAO,QAAQ,KAAK;AAC3C,gCAAU,MAAM;AACd,QAAI,QAAQ,UAAU,eAAe,QAAS;AAC9C,mBAAe,UAAU,QAAQ;AACjC,QAAI,QAAQ,OAAO;AACjB,iBAAW,UAAU,QAAQ,KAAK;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,QAAQ,OAAO,UAAU,CAAC;AAE9B,QAAM,cAAU,4BAAY,CAAC,SAA0B,WAAW,QAAQ,IAAI,GAAG,CAAC,UAAU,CAAC;AAC7F,QAAM,cAAU;AAAA,IACd,CAAC,MAAsB,eAAe,SAAS,WAAW,QAAQ,MAAM,YAAY;AAAA,IACpF,CAAC,UAAU;AAAA,EACb;AACA,QAAM,sBAAkB,4BAAY,CAAC,UAAuB,WAAW,gBAAgB,KAAK,GAAG,CAAC,UAAU,CAAC;AAC3G,QAAM,gBAAY,4BAAY,MAAM,WAAW,UAAU,GAAG,CAAC,UAAU,CAAC;AACxE,QAAM,aAAS,4BAAY,CAAC,QAAgB,WAAW,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC;AAChF,QAAM,kBAAc,4BAAY,CAAC,QAAgB,WAAW,YAAY,GAAG,GAAG,CAAC,UAAU,CAAC;AAC1F,QAAM,qBAAiB,4BAAY,MAAM,WAAW,eAAe,GAAG,CAAC,UAAU,CAAC;AAClF,QAAM,mBAAe,4BAAY,MAAM,WAAW,aAAa,GAAG,CAAC,UAAU,CAAC;AAC9E,QAAM,qBAAiB;AAAA,IACrB,CAAC,SAAoC,kBAAkB,SACrD,WAAW,eAAe,SAAS,eAAe;AAAA,IACpD,CAAC,UAAU;AAAA,EACb;AACA,QAAM,uBAAmB,4BAAY,MAAM,WAAW,iBAAiB,GAAG,CAAC,UAAU,CAAC;AACtF,QAAM,qBAAiB,4BAAY,MAAM,WAAW,eAAe,GAAG,CAAC,UAAU,CAAC;AAClF,QAAM,mBAAe,4BAAY,CAAC,YAAuC,WAAW,aAAa,OAAO,GAAG,CAAC,UAAU,CAAC;AACvH,QAAM,qBAAiB,4BAAY,MAAM,WAAW,eAAe,GAAG,CAAC,UAAU,CAAC;AAClF,QAAM,oBAAgB,4BAAY,CAAC,QAAiC,WAAW,cAAc,GAAG,GAAG,CAAC,UAAU,CAAC;AAC/G,QAAM,uBAAmB;AAAA,IACvB,CAAC,IAAY,SAA8B,kBAAkB,SAC3D,WAAW,iBAAiB,IAAI,SAAS,eAAe;AAAA,IAC1D,CAAC,UAAU;AAAA,EACb;AACA,QAAM,uBAAmB,4BAAY,CAAC,OAAe,WAAW,iBAAiB,EAAE,GAAG,CAAC,UAAU,CAAC;AAClG,QAAM,uBAAmB,4BAAY,MAAM,WAAW,iBAAiB,GAAG,CAAC,UAAU,CAAC;AACtF,QAAM,uBAAmB,4BAAY,CAAC,OAAsB,WAAW,iBAAiB,EAAE,GAAG,CAAC,UAAU,CAAC;AACzG,QAAM,WAAO,4BAAY,MAAM,WAAW,KAAK,GAAG,CAAC,UAAU,CAAC;AAC9D,QAAM,WAAO,4BAAY,MAAM,WAAW,KAAK,GAAG,CAAC,UAAU,CAAC;AAC9D,QAAM,YAAQ,4BAAY,MAAM,WAAW,MAAM,GAAG,CAAC,UAAU,CAAC;AAChE,QAAM,aAAS,4BAAY,CAAC,WAAoB,WAAW,OAAO,MAAM,GAAG,CAAC,UAAU,CAAC;AACvF,QAAM,cAAU,4BAAY,CAAC,WAAoB,WAAW,QAAQ,MAAM,GAAG,CAAC,UAAU,CAAC;AACzF,QAAM,gBAAY,4BAAY,MAAM,WAAW,UAAU,GAAG,CAAC,UAAU,CAAC;AACxE,QAAM,cAAU,4BAAY,CAAC,SAAiB,WAAW,QAAQ,IAAI,GAAG,CAAC,UAAU,CAAC;AACpF,QAAM,aAAS,4BAAY,CAAC,QAAoB,WAAW,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC;AACpF,QAAM,mBAAe,4BAAY,CAAC,SAAkB,WAAW,aAAa,IAAI,GAAG,CAAC,UAAU,CAAC;AAC/F,QAAM,gBAAY,4BAAY,CAAC,QAAmC,WAAW,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;AACzG,QAAM,gBAAY,4BAAY,CAAC,SAAyB,WAAW,UAAU,IAAI,GAAG,CAAC,UAAU,CAAC;AAChG,QAAM,aAAS,4BAAY,CAAC,SAAyB,WAAW,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC;AAC1F,QAAM,aAAS,4BAAY,MAAM,WAAW,OAAO,GAAG,CAAC,UAAU,CAAC;AAClE,QAAM,eAAW,4BAAY,CAAC,SAAqC,WAAW,SAAS,IAAI,GAAG,CAAC,UAAU,CAAC;AAC1G,QAAM,iBAAa;AAAA,IACjB,CAAC,SAA2D,WAAW,WAAW,IAAI;AAAA,IACtF,CAAC,UAAU;AAAA,EACb;AACA,QAAM,oBAAgB;AAAA,IACpB,CAAC,SAA2D,WAAW,cAAc,IAAI;AAAA,IACzF,CAAC,UAAU;AAAA,EACb;AACA,QAAM,sBAAkB;AAAA,IACtB,CAAC,SAAqD,WAAW,gBAAgB,IAAI;AAAA,IACrF,CAAC,UAAU;AAAA,EACb;AACA,QAAM,0BAAsB;AAAA,IAC1B,CAAC,eAAuB,WAAW,oBAAoB,UAAU;AAAA,IACjE,CAAC,UAAU;AAAA,EACb;AACA,QAAM,kCAA8B;AAAA,IAClC,CAAC,eAAuB,WAAW,4BAA4B,UAAU;AAAA,IACzE,CAAC,UAAU;AAAA,EACb;AAEA,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS,WAAW;AAAA,MACpB,SAAS,WAAW;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,IAEA,CAAC,YAAY,OAAO,YAAY;AAAA,EAClC;AACF;;;AC5MA,IAAAC,iBAAgE;AAYhE,IAAAC,uBAQO;AA0kBG,IAAAC,uBAAA;AAzjBH,IAAM,cAA0C,CAAC;AAAA,EACtD,QAAQ;AAAA,EACR;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,iBAAiB,eAAe,EAAE,OAAO,IAAI,CAAC;AACpD,QAAM,SAAS,kBAAkB;AACjC,QAAM,EAAE,OAAO,WAAW,IAAI;AAC9B,QAAM,oBAAgB,8CAAwB,MAAM,YAAY,OAAO,IAAI;AAE3E,QAAM,gBAAY,uBAA0B,IAAI;AAChD,QAAM,mBAAe,uBAAuB,IAAI;AAChD,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAkB,MAAM;AAC1D,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,yBAAwB,IAAI;AAG1E,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAAS,EAAE;AACrD,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,yBAAiC,aAAa;AAC5F,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,KAAK;AACtD,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,KAAK;AACtD,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAwB,IAAI;AAC1D,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAwB,IAAI;AAE9D,QAAM,qBAAqB,aAAa,SAAS;AACjD,QAAM,sBAAsB,sBAAsB,SAAS;AAE3D,QAAM,yBAAyB,YAAY;AACzC,QAAI,CAAC,qBAAqB;AACxB,iBAAW,2CAA2C;AACtD;AAAA,IACF;AACA,eAAW,IAAI;AACf,iBAAa,IAAI;AACjB,oBAAgB,IAAI;AACpB,QAAI;AAGF,YAAM,eAAe,MAAM,OAAO,gBAAgB;AAClD,YAAM,SAAS,MAAM,oBAAoB,EAAE,aAAa,CAAC;AACzD,UAAI,OAAO,WAAW,UAAU;AAC9B,cAAM,OAAO,4BAA4B,MAAM;AAC/C,qBAAa,kCAAkC;AAAA,MACjD,OAAO;AACL,qBAAa,8BAA8B;AAAA,MAC7C;AAAA,IACF,SAAS,KAAU;AACjB,iBAAW,KAAK,WAAW,8BAA8B;AAAA,IAC3D,UAAE;AACA,sBAAgB,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,gBAAgB,YAAY;AAChC,QAAI,CAAC,oBAAoB;AACvB,iBAAW,mCAAmC;AAC9C;AAAA,IACF;AACA,QAAI,CAAC,cAAc,KAAK,GAAG;AACzB,iBAAW,oCAAoC;AAC/C;AAAA,IACF;AACA,eAAW,IAAI;AACf,iBAAa,IAAI;AACjB,oBAAgB,IAAI;AACpB,QAAI;AAEF,YAAM,eAAe,MAAM,OAAO,gBAAgB;AAClD,YAAM,cAAc,MAAM,OAAO,cAAc;AAAA,QAC7C,gBAAgB,oBAAoB;AAAA,QACpC,SAAS,oBAAoB;AAAA,MAC/B,CAAC;AACD,YAAM,SAAS,MAAM,mBAAmB;AAAA,QACtC,QAAQ,cAAc,KAAK;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,SAAS,oBAAoB,SAAS,OAAO,MAAM,OAAO;AAAA,MAC5D,CAAC;AACD,UAAI,OAAO,WAAW,UAAU;AAC9B,cAAM,OAAO,oBAAoB,MAAM;AACvC,qBAAa,kCAAkC;AAAA,MACjD,OAAO;AACL,qBAAa,sBAAsB;AAAA,MACrC;AAAA,IACF,SAAS,KAAU;AACjB,iBAAW,KAAK,WAAW,6BAA6B;AAAA,IAC1D,UAAE;AACA,sBAAgB,KAAK;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,CAAC,aAAa,cAAc,QAAI,yBAAS,SAAS;AACxD,QAAM,CAAC,aAAa,cAAc,QAAI,yBAAS,CAAC;AAChD,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,EAAE;AAC3C,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAS,EAAE;AAG7C,QAAM,yBAAqB,uBAA0B,IAAI;AACzD,QAAM,mBAAe,uBAAuB,IAAI;AAChD,QAAM,sBAAkB,uBAKd,IAAI;AACd,QAAM,4BAAwB,uBAIpB,IAAI;AACd,QAAM,mBAAe,uBAAO,KAAK;AACjC,QAAM,qBAAiB,uBAAqB,CAAC,CAAC;AAC9C,QAAM,wBAAoB,uBAA0B,IAAI;AAGxD,QAAM,mBAAe;AAAA,IACnB,OAAO,iBAAqC,cAA+B;AACzE,YAAM,SAAS,UAAU;AACzB,YAAM,YAAY,aAAa;AAC/B,UAAI,CAAC,UAAU,CAAC,UAAW;AAE3B,YAAM,UAAU,UAAU,eAAe;AACzC,YAAM,WAAW,UAAU,gBAAgB;AAE3C,YAAM,WAAW,OAAO,QAAQ;AAAA,QAC9B,eAAe;AAAA,QACf,gBAAgB;AAAA,QAChB,iBAAiB,cAAc;AAAA,QAC/B,sBAAsB;AAAA,QACtB,aAAa;AAAA,QACb,iBAAiB,oBAAoB,SAAY,kBAAkB,mBAAmB;AAAA,QACtF,WAAW,cAAc,SAAY,YAAY,aAAa;AAAA,MAChE,CAAC;AAAA,IACH;AAAA,IACA,CAAC,YAAY,SAAS;AAAA,EACxB;AAEA,gCAAU,MAAM;AACd,UAAM,MACJ,OAAO,0BAA0B,cAC7B,wBACA,CAAC,OAAmB,WAAW,IAAI,CAAC;AAC1C,UAAM,MACJ,OAAO,yBAAyB,cAC5B,uBACA,CAAC,OAAe,aAAa,EAAE;AAErC,UAAM,SAAS,IAAI,MAAM;AACvB,mBAAa;AAAA,IACf,CAAC;AACD,WAAO,MAAM,IAAI,MAAM;AAAA,EACzB,GAAG,CAAC,cAAc,KAAK,CAAC;AAGxB,gCAAU,MAAM;AACd,QAAI,cAAc,UAAU,OAAO,MAAM,eAAe,QAAQ;AAC9D,aAAO,QAAQ,MAAM;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,WAAW,MAAM,CAAC;AAGtB,gCAAU,MAAM;AACd,UAAM,YAAY,aAAa;AAC/B,QAAI,CAAC,UAAW;AAEhB,QAAI,OAAO,mBAAmB,aAAa;AACzC,YAAM,WAAW,IAAI,eAAe,MAAM;AACxC,qBAAa;AAAA,MACf,CAAC;AACD,eAAS,QAAQ,SAAS;AAC1B,aAAO,MAAM,SAAS,WAAW;AAAA,IACnC,OAAO;AACL,YAAM,eAAe,MAAM,aAAa;AACxC,aAAO,iBAAiB,UAAU,YAAY;AAC9C,aAAO,MAAM,OAAO,oBAAoB,UAAU,YAAY;AAAA,IAChE;AAAA,EACF,GAAG,CAAC,YAAY,CAAC;AAGjB,QAAM,sBAAsB,CAAC,MAAuD;AAClF,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ,QAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AACjC,UAAM,OAAO,OAAO,sBAAsB;AAC1C,UAAM,SAAS,KAAK,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;AAC5D,UAAM,SAAS,KAAK,SAAS,IAAI,OAAO,SAAS,KAAK,SAAS;AAC/D,WAAO;AAAA,MACL,IAAI,EAAE,UAAU,KAAK,QAAQ;AAAA,MAC7B,IAAI,EAAE,UAAU,KAAK,OAAO;AAAA,IAC9B;AAAA,EACF;AAGA,QAAM,kBAAkB,CAAC,MAA2C;AAClE,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ;AACb,UAAM,WAAW,oBAAoB,CAAC;AAEtC,QAAI,cAAc,QAAQ;AACxB,YAAM,aAAa,aAAa,WAAW,MAAM,QAAQ;AAAA,QACvD,GAAG;AAAA,QACH,GAAG;AAAA,QACH,OAAO,MAAM,gBAAgB;AAAA,QAC7B,QAAQ,MAAM,gBAAgB;AAAA,MAChC;AACA,YAAM,aAAS,kCAAY,UAAU,OAAO,OAAO,OAAO,OAAO,QAAQ,IAAI,UAAU;AACvF,YAAM,iBAAa,yCAAmB,UAAU,OAAO,OAAO,OAAO,OAAO,QAAQ,IAAI;AAExF,UAAI,QAAQ;AACV,wBAAgB,UAAU;AAAA,UACxB;AAAA,UACA,eAAe;AAAA,UACf;AAAA,UACA,WAAW;AAAA,QACb;AAAA,MACF,OAAO;AAEL,wBAAgB,UAAU;AAAA,UACxB,QAAQ;AAAA,UACR,eAAe;AAAA,UACf;AAAA,UACA,WAAW,EAAE,GAAG,WAAW,GAAG,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,EAAE;AAAA,QACrE;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,cAAc,YAAY;AAC5B,YAAM,YAAQ,yCAAmB,UAAU,OAAO,OAAO,OAAO,OAAO,QAAQ,KAAK;AACpF,wBAAkB,UAAU;AAE5B,UAAI,MAAM,eAAe,UAAU;AACjC,iBAAS,IAAI,MAAM,YAAY,SAAS,GAAG,KAAK,GAAG,KAAK;AACtD,gBAAM,MAAM,MAAM,YAAY,CAAC;AAC/B,kBAAI,wCAAkB,OAAO,GAAG,GAAG;AACjC,mBAAO,iBAAiB,IAAI,EAAE;AAC9B,kCAAsB,UAAU;AAAA,cAC9B,OAAO,IAAI;AAAA,cACX,YAAY;AAAA,cACZ,YAAY,EAAE,GAAG,IAAI;AAAA,YACvB;AACA;AAAA,UACF;AAAA,QACF;AACA,eAAO,iBAAiB,IAAI;AAC5B;AAAA,MACF;AAEA,UAAI,MAAM,eAAe,OAAO;AAC9B,qBAAa,UAAU;AACvB,uBAAe,UAAU,CAAC,KAAK;AAC/B,cAAM,QAAoB;AAAA,UACxB,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,GAAG;AAAA,UACH,GAAG;AAAA,UACH,QAAQ,CAAC,KAAK;AAAA,UACd,aAAa;AAAA,UACb;AAAA,QACF;AACA,2BAAmB,UAAU;AAC7B,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,kBAAkB,CAAC,MAA2C;AAClE,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ;AACb,UAAM,WAAW,oBAAoB,CAAC;AAEtC,QAAI,cAAc,QAAQ;AACxB,YAAM,OAAO,gBAAgB;AAC7B,UAAI,MAAM;AACR,cAAM,mBAAe,yCAAmB,UAAU,OAAO,OAAO,OAAO,OAAO,QAAQ,IAAI;AAC1F,YAAI;AAEJ,YAAI,KAAK,WAAW,OAAO;AACzB,gBAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,WAAW,GAAG,aAAa,CAAC,CAAC;AACpE,gBAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,WAAW,GAAG,aAAa,CAAC,CAAC;AACpE,gBAAM,OAAO,KAAK,IAAI,MAAM,gBAAgB,OAAO,KAAK,IAAI,KAAK,WAAW,GAAG,aAAa,CAAC,CAAC;AAC9F,gBAAM,OAAO,KAAK,IAAI,MAAM,gBAAgB,QAAQ,KAAK,IAAI,KAAK,WAAW,GAAG,aAAa,CAAC,CAAC;AAC/F,oBAAU;AAAA,YACR,GAAG,KAAK,MAAM,IAAI;AAAA,YAClB,GAAG,KAAK,MAAM,IAAI;AAAA,YAClB,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC;AAAA,YAC3C,QAAQ,KAAK,MAAM,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC;AAAA,UAC9C;AAAA,QACF,OAAO;AACL,wBAAU;AAAA,YACR,KAAK;AAAA,YACL,KAAK;AAAA,YACL,KAAK;AAAA,YACL;AAAA,YACA,MAAM,gBAAgB;AAAA,YACtB,MAAM,gBAAgB;AAAA,YACtB;AAAA,YACA,MAAM;AAAA,UACR;AAAA,QACF;AAEA,qBAAa,UAAU;AACvB,qBAAa,MAAM,OAAO;AAAA,MAC5B,OAAO;AACL,cAAM,aAAa,aAAa,WAAW,MAAM,QAAQ;AAAA,UACvD,GAAG;AAAA,UACH,GAAG;AAAA,UACH,OAAO,MAAM,gBAAgB;AAAA,UAC7B,QAAQ,MAAM,gBAAgB;AAAA,QAChC;AACA,cAAM,aAAS,kCAAY,UAAU,OAAO,OAAO,OAAO,OAAO,QAAQ,IAAI,UAAU;AACvF,eAAO,MAAM,aAAS,oCAAc,QAAQ,MAAM,SAAS;AAAA,MAC7D;AACA;AAAA,IACF;AAEA,QAAI,cAAc,YAAY;AAE5B,UAAI,sBAAsB,SAAS;AACjC,cAAM,OAAO,sBAAsB;AACnC,cAAMC,oBAAe,yCAAmB,UAAU,OAAO,OAAO,OAAO,OAAO,QAAQ,KAAK;AAC3F,cAAM,KAAKA,cAAa,IAAI,KAAK,WAAW;AAC5C,cAAM,KAAKA,cAAa,IAAI,KAAK,WAAW;AAC5C,eAAO,iBAAiB,KAAK,OAAO;AAAA,UAClC,GAAG,KAAK,MAAM,KAAK,WAAW,IAAI,EAAE;AAAA,UACpC,GAAG,KAAK,MAAM,KAAK,WAAW,IAAI,EAAE;AAAA,QACtC,CAAC;AACD;AAAA,MACF;AAEA,YAAM,UAAU,kBAAkB;AAClC,UAAI,CAAC,SAAS;AAEZ,YAAI,MAAM,eAAe,UAAU;AACjC,gBAAM,YAAQ,yCAAmB,UAAU,OAAO,OAAO,OAAO,OAAO,QAAQ,KAAK;AACpF,cAAI,UAAU;AACd,mBAAS,IAAI,MAAM,YAAY,SAAS,GAAG,KAAK,GAAG,KAAK;AACtD,oBAAI,wCAAkB,OAAO,MAAM,YAAY,CAAC,CAAC,GAAG;AAClD,wBAAU;AACV;AAAA,YACF;AAAA,UACF;AACA,iBAAO,MAAM,SAAS,UAAU,SAAS;AAAA,QAC3C,OAAO;AACL,iBAAO,MAAM,SAAS;AAAA,QACxB;AACA;AAAA,MACF;AAEA,YAAM,mBAAe,yCAAmB,UAAU,OAAO,OAAO,OAAO,OAAO,QAAQ,KAAK;AAE3F,UAAI,MAAM,eAAe,SAAS,aAAa,SAAS;AACtD,uBAAe,QAAQ,KAAK,YAAY;AACxC,cAAM,QAAoB;AAAA,UACxB,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,GAAG;AAAA,UACH,GAAG;AAAA,UACH,QAAQ,CAAC,GAAG,eAAe,OAAO;AAAA,UAClC,aAAa;AAAA,UACb;AAAA,QACF;AACA,2BAAmB,UAAU;AAC7B,qBAAa,KAAK;AAAA,MACpB,WAAW,MAAM,eAAe,QAAQ;AACtC,cAAM,IAAI,aAAa,IAAI,QAAQ;AACnC,cAAM,IAAI,aAAa,IAAI,QAAQ;AACnC,cAAM,QAAoB;AAAA,UACxB,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,GAAG,KAAK,IAAI,QAAQ,GAAG,aAAa,CAAC;AAAA,UACrC,GAAG,KAAK,IAAI,QAAQ,GAAG,aAAa,CAAC;AAAA,UACrC,OAAO,KAAK,IAAI,CAAC;AAAA,UACjB,QAAQ,KAAK,IAAI,CAAC;AAAA,UAClB,aAAa;AAAA,UACb;AAAA,QACF;AACA,2BAAmB,UAAU;AAC7B,qBAAa,KAAK;AAAA,MACpB,WAAW,MAAM,eAAe,UAAU;AACxC,cAAM,KAAK,KAAK,IAAI,aAAa,IAAI,QAAQ,CAAC,IAAI;AAClD,cAAM,KAAK,KAAK,IAAI,aAAa,IAAI,QAAQ,CAAC,IAAI;AAClD,cAAM,QAAoB;AAAA,UACxB,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,GAAG,KAAK,IAAI,QAAQ,GAAG,aAAa,CAAC,IAAI;AAAA,UACzC,GAAG,KAAK,IAAI,QAAQ,GAAG,aAAa,CAAC,IAAI;AAAA,UACzC,SAAS;AAAA,UACT,SAAS;AAAA,UACT,aAAa;AAAA,UACb;AAAA,QACF;AACA,2BAAmB,UAAU;AAC7B,qBAAa,KAAK;AAAA,MACpB,WAAW,MAAM,eAAe,SAAS;AACvC,cAAM,QAAoB;AAAA,UACxB,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,GAAG,QAAQ;AAAA,UACX,GAAG,QAAQ;AAAA,UACX,MAAM,aAAa;AAAA,UACnB,MAAM,aAAa;AAAA,UACnB,aAAa;AAAA,UACb;AAAA,QACF;AACA,2BAAmB,UAAU;AAC7B,qBAAa,KAAK;AAAA,MACpB,WAAW,MAAM,eAAe,QAAQ;AACtC,cAAM,QAAoB;AAAA,UACxB,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,GAAG,QAAQ;AAAA,UACX,GAAG,QAAQ;AAAA,UACX,MAAM,aAAa;AAAA,UACnB,MAAM,aAAa;AAAA,UACnB,aAAa;AAAA,UACb;AAAA,QACF;AACA,2BAAmB,UAAU;AAC7B,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,MAA2C;AAChE,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ;AACb,UAAM,WAAW,oBAAoB,CAAC;AAEtC,QAAI,cAAc,QAAQ;AACxB,UAAI,gBAAgB,SAAS;AAC3B,YACE,aAAa,WACb,aAAa,QAAQ,SAAS,MAC9B,aAAa,QAAQ,UAAU,IAC/B;AACA,iBAAO,QAAQ,aAAa,SAAS,IAAI;AAAA,QAC3C;AACA,wBAAgB,UAAU;AAC1B,qBAAa,UAAU;AACvB,qBAAa;AAAA,MACf;AACA;AAAA,IACF;AAEA,QAAI,cAAc,YAAY;AAC5B,UAAI,sBAAsB,SAAS;AACjC,8BAAsB,UAAU;AAChC;AAAA,MACF;AAEA,YAAM,UAAU,kBAAkB;AAClC,UAAI,SAAS;AACX,cAAM,mBAAe,yCAAmB,UAAU,OAAO,OAAO,OAAO,OAAO,QAAQ,KAAK;AAE3F,YAAI,MAAM,eAAe,SAAS,aAAa,SAAS;AACtD,cAAI,eAAe,QAAQ,SAAS,GAAG;AACrC,mBAAO,cAAc;AAAA,cACnB,MAAM;AAAA,cACN,GAAG;AAAA,cACH,GAAG;AAAA,cACH,QAAQ,CAAC,GAAG,eAAe,OAAO;AAAA,cAClC,aAAa;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH;AACA,uBAAa,UAAU;AACvB,yBAAe,UAAU,CAAC;AAAA,QAC5B,WAAW,MAAM,eAAe,QAAQ;AACtC,gBAAM,IAAI,KAAK,IAAI,aAAa,IAAI,QAAQ,CAAC;AAC7C,gBAAM,IAAI,KAAK,IAAI,aAAa,IAAI,QAAQ,CAAC;AAC7C,cAAI,IAAI,KAAK,IAAI,GAAG;AAClB,mBAAO,cAAc;AAAA,cACnB,MAAM;AAAA,cACN,GAAG,KAAK,IAAI,QAAQ,GAAG,aAAa,CAAC;AAAA,cACrC,GAAG,KAAK,IAAI,QAAQ,GAAG,aAAa,CAAC;AAAA,cACrC,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,aAAa;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,WAAW,MAAM,eAAe,UAAU;AACxC,gBAAM,KAAK,KAAK,IAAI,aAAa,IAAI,QAAQ,CAAC,IAAI;AAClD,gBAAM,KAAK,KAAK,IAAI,aAAa,IAAI,QAAQ,CAAC,IAAI;AAClD,cAAI,KAAK,KAAK,KAAK,GAAG;AACpB,mBAAO,cAAc;AAAA,cACnB,MAAM;AAAA,cACN,GAAG,KAAK,IAAI,QAAQ,GAAG,aAAa,CAAC,IAAI;AAAA,cACzC,GAAG,KAAK,IAAI,QAAQ,GAAG,aAAa,CAAC,IAAI;AAAA,cACzC,SAAS;AAAA,cACT,SAAS;AAAA,cACT,aAAa;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,WAAW,MAAM,eAAe,SAAS;AACvC,cAAI,KAAK,MAAM,aAAa,IAAI,QAAQ,GAAG,aAAa,IAAI,QAAQ,CAAC,IAAI,GAAG;AAC1E,mBAAO,cAAc;AAAA,cACnB,MAAM;AAAA,cACN,GAAG,QAAQ;AAAA,cACX,GAAG,QAAQ;AAAA,cACX,MAAM,aAAa;AAAA,cACnB,MAAM,aAAa;AAAA,cACnB,aAAa;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,WAAW,MAAM,eAAe,QAAQ;AACtC,cAAI,KAAK,MAAM,aAAa,IAAI,QAAQ,GAAG,aAAa,IAAI,QAAQ,CAAC,IAAI,GAAG;AAC1E,mBAAO,cAAc;AAAA,cACnB,MAAM;AAAA,cACN,GAAG,QAAQ;AAAA,cACX,GAAG,QAAQ;AAAA,cACX,MAAM,aAAa;AAAA,cACnB,MAAM,aAAa;AAAA,cACnB,aAAa;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAEA,2BAAmB,UAAU;AAC7B,0BAAkB,UAAU;AAC5B,qBAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,gBAAgB,MAAM;AAC1B,QAAI,CAAC,UAAU,KAAK,EAAG;AACvB,WAAO,cAAc;AAAA,MACnB,MAAM;AAAA,MACN,GAAG;AAAA,MACH,GAAG;AAAA,MACH,MAAM,UAAU,KAAK;AAAA,MACrB;AAAA,MACA,OAAO;AAAA,IACT,CAAC;AACD,iBAAa,EAAE;AAAA,EACjB;AAEA,QAAM,eAAe,YAAY;AAC/B,UAAM,UAAU,MAAM,OAAO,UAAU,aAAa;AACpD,QAAI,QAAQ;AACV,aAAO,OAAO;AAAA,IAChB,OAAO;AAEL,YAAM,OAAO,SAAS,cAAc,GAAG;AACvC,WAAK,WAAW,gBAAgB,KAAK,IAAI,CAAC;AAC1C,WAAK,OAAO;AACZ,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,2GAA2G,SAAS;AAAA,MAC/H;AAAA,MAGA;AAAA,uDAAC,SAAI,WAAU,yGAEb;AAAA,yDAAC,SAAI,WAAU,uFACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM;AACb,+BAAa,MAAM;AACnB,yBAAO,QAAQ,MAAM;AAAA,gBACvB;AAAA,gBACA,WAAW,wDACT,cAAc,SAAS,oCAAoC,qCAC7D;AAAA,gBACD;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM;AACb,+BAAa,QAAQ;AACrB,yBAAO,QAAQ,QAAQ;AAAA,gBACzB;AAAA,gBACA,WAAW,wDACT,cAAc,WAAW,oCAAoC,qCAC/D;AAAA,gBACD;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM;AACb,+BAAa,UAAU;AACvB,yBAAO,QAAQ,KAAK;AAAA,gBACtB;AAAA,gBACA,WAAW,wDACT,cAAc,aAAa,oCAAoC,qCACjE;AAAA,gBACD;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM;AACb,+BAAa,OAAO;AACpB,yBAAO,QAAQ,QAAQ;AAAA,gBACzB;AAAA,gBACA,WAAW,wDACT,cAAc,UAAU,oCAAoC,qCAC9D;AAAA,gBACD;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM;AACb,+BAAa,IAAI;AACjB,yBAAO,QAAQ,QAAQ;AAAA,gBACzB;AAAA,gBACA,WAAW,kFACT,cAAc,OAAO,oCAAoC,qCAC3D;AAAA,gBAEA;AAAA,gEAAC,SAAI,WAAU,eAAc,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAC7F,wDAAC,UAAK,GAAE,sHAAqH,GAC/H;AAAA,kBAAM;AAAA;AAAA;AAAA,YAER;AAAA,aACF;AAAA,UAGA,+CAAC,SAAI,WAAU,mCACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,UAAU,CAAC,OAAO;AAAA,gBAClB,SAAS,MAAM,OAAO,KAAK;AAAA,gBAC3B,WAAU;AAAA,gBACV,OAAM;AAAA,gBACP;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,UAAU,CAAC,OAAO;AAAA,gBAClB,SAAS,MAAM,OAAO,KAAK;AAAA,gBAC3B,WAAU;AAAA,gBACV,OAAM;AAAA,gBACP;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM,OAAO,MAAM;AAAA,gBAC5B,WAAU;AAAA,gBACX;AAAA;AAAA,YAED;AAAA,YAEA,8CAAC,SAAI,WAAU,8BAA6B;AAAA,YAG5C;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM,OAAO,QAAQ;AAAA,gBAC9B,WAAU;AAAA,gBACV,OAAM;AAAA,gBACP;AAAA;AAAA,YAED;AAAA,YACA,+CAAC,UAAK,WAAU,6CAA6C;AAAA,mBAAK,MAAM,MAAM,OAAO,GAAG;AAAA,cAAE;AAAA,eAAC;AAAA,YAC3F;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM,OAAO,OAAO;AAAA,gBAC7B,WAAU;AAAA,gBACV,OAAM;AAAA,gBACP;AAAA;AAAA,YAED;AAAA,YAEA,8CAAC,SAAI,WAAU,8BAA6B;AAAA,YAG5C;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,aAAa,MAAM,OAAO,aAAa,IAAI;AAAA,gBAC3C,WAAW,MAAM,OAAO,aAAa,KAAK;AAAA,gBAC1C,cAAc,MAAM,OAAO,aAAa,KAAK;AAAA,gBAC7C,WAAU;AAAA,gBACX;AAAA;AAAA,YAED;AAAA,YAGA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS;AAAA,gBACT,WAAU;AAAA,gBACX;AAAA;AAAA,YAED;AAAA,aACF;AAAA,WACF;AAAA,QAGA,+CAAC,SAAI,WAAU,+DAEb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,WAAU;AAAA,cAEV;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAK;AAAA,kBACL,aAAa;AAAA,kBACb,aAAa;AAAA,kBACb,WAAW;AAAA,kBACX,cAAc;AAAA,kBACd,WAAU;AAAA;AAAA,cACZ;AAAA;AAAA,UACF;AAAA,UAGA,+CAAC,SAAI,WAAU,4IAEZ;AAAA,0BAAc,UACb,+CAAC,SAAI,WAAU,+BACb;AAAA,4DAAC,UAAK,WAAU,qEAAoE,kCAEpF;AAAA,cACA,+CAAC,SAAI,WAAU,0BACb;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM;AACb,yCAAmB,IAAI;AACvB,6BAAO,gBAAgB,IAAI;AAAA,oBAC7B;AAAA,oBACA,WAAW,6CACT,oBAAoB,QAAQ,MAAM,OAC9B,+CACA,iEACN;AAAA,oBACD;AAAA;AAAA,gBAED;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM;AACb,yCAAmB,CAAC;AACpB,6BAAO,gBAAgB,CAAC;AAAA,oBAC1B;AAAA,oBACA,WAAW,6CACT,oBAAoB,IAChB,+CACA,iEACN;AAAA,oBACD;AAAA;AAAA,gBAED;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM;AACb,yCAAmB,IAAI,CAAC;AACxB,6BAAO,gBAAgB,IAAI,CAAC;AAAA,oBAC9B;AAAA,oBACA,WAAW,6CACT,oBAAoB,IAAI,IACpB,+CACA,iEACN;AAAA,oBACD;AAAA;AAAA,gBAED;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM;AACb,yCAAmB,KAAK,CAAC;AACzB,6BAAO,gBAAgB,KAAK,CAAC;AAAA,oBAC/B;AAAA,oBACA,WAAW,6CACT,oBAAoB,KAAK,IACrB,+CACA,iEACN;AAAA,oBACD;AAAA;AAAA,gBAED;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM;AACb,yCAAmB,IAAI,CAAC;AACxB,6BAAO,gBAAgB,IAAI,CAAC;AAAA,oBAC9B;AAAA,oBACA,WAAW,6CACT,oBAAoB,IAAI,IACpB,+CACA,iEACN;AAAA,oBACD;AAAA;AAAA,gBAED;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM;AACb,yCAAmB,IAAI;AACvB,6BAAO,UAAU;AAAA,oBACnB;AAAA,oBACA,WAAU;AAAA,oBACX;AAAA;AAAA,gBAED;AAAA,iBACF;AAAA,cAEA,8CAAC,SAAI,WAAU,0BAAyB;AAAA,cAExC,8CAAC,UAAK,WAAU,qEAAoE,iCAEpF;AAAA,cACA,+CAAC,SAAI,WAAU,0BACb;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,OAAO,OAAO,GAAG;AAAA,oBAChC,WAAU;AAAA,oBACX;AAAA;AAAA,gBAED;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,OAAO,OAAO,EAAE;AAAA,oBAC/B,WAAU;AAAA,oBACX;AAAA;AAAA,gBAED;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,OAAO,eAAe;AAAA,oBACrC,WAAW,iDACT,MAAM,UAAU,QACZ,+CACA,iEACN;AAAA,oBACD;AAAA;AAAA,gBAED;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,OAAO,aAAa;AAAA,oBACnC,WAAW,iDACT,MAAM,UAAU,QACZ,+CACA,iEACN;AAAA,oBACD;AAAA;AAAA,gBAED;AAAA,iBACF;AAAA,eACF;AAAA,YAID,cAAc,YACb,+CAAC,SAAI,WAAU,+BACb;AAAA,6DAAC,SAAI,WAAU,qCACb;AAAA,8DAAC,UAAK,WAAU,qEAAoE,+BAEpF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,OAAO,iBAAiB;AAAA,oBACvC,WAAU;AAAA,oBACX;AAAA;AAAA,gBAED;AAAA,iBACF;AAAA,cAGA,+CAAC,SACC;AAAA,+DAAC,SAAI,WAAU,4CACb;AAAA,gEAAC,UAAK,wBAAU;AAAA,kBAChB,8CAAC,UAAK,WAAU,aAAa,gBAAM,YAAY,YAAW;AAAA,mBAC5D;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAI;AAAA,oBACJ,KAAI;AAAA,oBACJ,OAAO,MAAM,YAAY;AAAA,oBACzB,UAAU,CAAC,MAAM,OAAO,eAAe,EAAE,YAAY,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,oBAC7E,WAAU;AAAA;AAAA,gBACZ;AAAA,iBACF;AAAA,cAGA,+CAAC,SACC;AAAA,+DAAC,SAAI,WAAU,4CACb;AAAA,gEAAC,UAAK,sBAAQ;AAAA,kBACd,8CAAC,UAAK,WAAU,aAAa,gBAAM,YAAY,UAAS;AAAA,mBAC1D;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAI;AAAA,oBACJ,KAAI;AAAA,oBACJ,OAAO,MAAM,YAAY;AAAA,oBACzB,UAAU,CAAC,MAAM,OAAO,eAAe,EAAE,UAAU,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,oBAC3E,WAAU;AAAA;AAAA,gBACZ;AAAA,iBACF;AAAA,cAGA,+CAAC,SACC;AAAA,+DAAC,SAAI,WAAU,4CACb;AAAA,gEAAC,UAAK,wBAAU;AAAA,kBAChB,8CAAC,UAAK,WAAU,aAAa,gBAAM,YAAY,YAAW;AAAA,mBAC5D;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAI;AAAA,oBACJ,KAAI;AAAA,oBACJ,OAAO,MAAM,YAAY;AAAA,oBACzB,UAAU,CAAC,MAAM,OAAO,eAAe,EAAE,YAAY,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,oBAC7E,WAAU;AAAA;AAAA,gBACZ;AAAA,iBACF;AAAA,cAGA,+CAAC,SACC;AAAA,+DAAC,SAAI,WAAU,4CACb;AAAA,gEAAC,UAAK,sBAAQ;AAAA,kBACd,8CAAC,UAAK,WAAU,aAAa,gBAAM,YAAY,UAAS;AAAA,mBAC1D;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAI;AAAA,oBACJ,KAAI;AAAA,oBACJ,OAAO,MAAM,YAAY;AAAA,oBACzB,UAAU,CAAC,MAAM,OAAO,eAAe,EAAE,UAAU,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,oBAC3E,WAAU;AAAA;AAAA,gBACZ;AAAA,iBACF;AAAA,cAGA,+CAAC,SACC;AAAA,+DAAC,SAAI,WAAU,4CACb;AAAA,gEAAC,UAAK,kCAAoB;AAAA,kBAC1B,8CAAC,UAAK,WAAU,aAAa,gBAAM,YAAY,aAAY;AAAA,mBAC7D;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAI;AAAA,oBACJ,KAAI;AAAA,oBACJ,OAAO,MAAM,YAAY;AAAA,oBACzB,UAAU,CAAC,MAAM,OAAO,eAAe,EAAE,aAAa,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,oBAC9E,WAAU;AAAA;AAAA,gBACZ;AAAA,iBACF;AAAA,cAGA,+CAAC,SACC;AAAA,+DAAC,SAAI,WAAU,4CACb;AAAA,gEAAC,UAAK,kBAAI;AAAA,kBACV,8CAAC,UAAK,WAAU,aAAa,gBAAM,YAAY,QAAQ,GAAE;AAAA,mBAC3D;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAI;AAAA,oBACJ,KAAI;AAAA,oBACJ,cAAW;AAAA,oBACX,UAAU;AAAA,oBACV,OAAO,MAAM,YAAY,QAAQ;AAAA,oBACjC,UAAU,CAAC,MAAM,OAAO,eAAe,EAAE,MAAM,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,oBACvE,WAAU;AAAA;AAAA,gBACZ;AAAA,iBACF;AAAA,cAEC,iBACC;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,eAAY;AAAA,kBAEZ;AAAA,kEAAC,UAAK,2EAA6D;AAAA,oBACnE;AAAA,sBAAC;AAAA;AAAA,wBACC,MAAK;AAAA,wBACL,SAAS,MAAM,OAAO,eAAe;AAAA,wBACrC,WAAU;AAAA,wBACX;AAAA;AAAA,oBAED;AAAA;AAAA;AAAA,cACF;AAAA,cAIF,+CAAC,SACC;AAAA,+DAAC,SAAI,WAAU,4CACb;AAAA,gEAAC,UAAK,kBAAI;AAAA,kBACV,+CAAC,UAAK,WAAU,aAAa;AAAA,0BAAM,YAAY;AAAA,oBAAK;AAAA,qBAAE;AAAA,mBACxD;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAI;AAAA,oBACJ,KAAI;AAAA,oBACJ,OAAO,MAAM,YAAY;AAAA,oBACzB,UAAU,CAAC,MAAM,OAAO,eAAe,EAAE,MAAM,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,oBACvE,WAAU;AAAA;AAAA,gBACZ;AAAA,iBACF;AAAA,cAGA,+CAAC,SACC;AAAA,+DAAC,SAAI,WAAU,4CACb;AAAA,gEAAC,UAAK,qBAAO;AAAA,kBACb,+CAAC,UAAK,WAAU,aAAa;AAAA,yBAAK,MAAM,MAAM,YAAY,UAAU,GAAG;AAAA,oBAAE;AAAA,qBAAC;AAAA,mBAC5E;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAI;AAAA,oBACJ,KAAI;AAAA,oBACJ,MAAK;AAAA,oBACL,OAAO,MAAM,YAAY;AAAA,oBACzB,UAAU,CAAC,MAAM,OAAO,eAAe,EAAE,SAAS,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,oBAC1E,WAAU;AAAA;AAAA,gBACZ;AAAA,iBACF;AAAA,eACF;AAAA,YAID,cAAc,cACb,+CAAC,SAAI,WAAU,+BACb;AAAA,4DAAC,UAAK,WAAU,qEAAoE,6BAEpF;AAAA,cAGA,8CAAC,SAAI,WAAU,4BACX,WAAC,OAAO,QAAQ,UAAU,SAAS,MAAM,EAAwB,IAAI,CAAC,MACtE;AAAA,gBAAC;AAAA;AAAA,kBAEC,MAAK;AAAA,kBACL,SAAS,MAAM,OAAO,QAAQ,CAAC;AAAA,kBAC/B,WAAW,0EACT,MAAM,eAAe,IACjB,+CACA,iEACN;AAAA,kBAEC;AAAA;AAAA,gBATI;AAAA,cAUP,CACD,GACH;AAAA,cAGA,+CAAC,SAAI,WAAU,gCACb;AAAA,8DAAC,WAAM,WAAU,kBAAiB,oBAAM;AAAA,gBACxC;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,OAAO;AAAA,oBACP,UAAU,CAAC,MAAM,eAAe,EAAE,OAAO,KAAK;AAAA,oBAC9C,WAAU;AAAA;AAAA,gBACZ;AAAA,gBACA,+CAAC,SAAI,WAAU,eACb;AAAA,iEAAC,SAAI,WAAU,8CACb;AAAA,kEAAC,UAAK,oBAAM;AAAA,oBACZ,+CAAC,UAAK,WAAU,aAAa;AAAA;AAAA,sBAAY;AAAA,uBAAE;AAAA,qBAC7C;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,KAAI;AAAA,sBACJ,KAAI;AAAA,sBACJ,OAAO;AAAA,sBACP,UAAU,CAAC,MAAM,eAAe,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,sBACtD,WAAU;AAAA;AAAA,kBACZ;AAAA,mBACF;AAAA,iBACF;AAAA,cAEA,8CAAC,SAAI,WAAU,0BAAyB;AAAA,cAGxC,8CAAC,UAAK,WAAU,qEAAoE,sBAAQ;AAAA,cAC5F,+CAAC,SAAI,WAAU,cACb;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,aAAY;AAAA,oBACZ,OAAO;AAAA,oBACP,UAAU,CAAC,MAAM,aAAa,EAAE,OAAO,KAAK;AAAA,oBAC5C,WAAW,CAAC,MAAM,EAAE,QAAQ,WAAW,cAAc;AAAA,oBACrD,WAAU;AAAA;AAAA,gBACZ;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS;AAAA,oBACT,WAAU;AAAA,oBACX;AAAA;AAAA,gBAED;AAAA,iBACF;AAAA,cACA,+CAAC,SAAI,WAAU,oDACb;AAAA,8DAAC,UAAK,wBAAU;AAAA,gBAChB,+CAAC,UAAK,WAAU,aAAa;AAAA;AAAA,kBAAS;AAAA,mBAAE;AAAA,iBAC1C;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,UAAU,CAAC,MAAM,YAAY,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,kBACnD,WAAU;AAAA;AAAA,cACZ;AAAA,cAGA,8CAAC,SAAI,WAAU,0BAAyB;AAAA,cACxC,+CAAC,SAAI,WAAU,qCACb;AAAA,+DAAC,UAAK,WAAU,kBAAiB;AAAA;AAAA,kBAAS,MAAM,YAAY;AAAA,kBAAO;AAAA,mBAAC;AAAA,gBACnE,MAAM,wBACL;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,OAAO,iBAAiB,MAAM,oBAAqB;AAAA,oBAClE,WAAU;AAAA,oBACX;AAAA;AAAA,gBAED;AAAA,gBAED,MAAM,YAAY,SAAS,KAC1B;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,OAAO,iBAAiB;AAAA,oBACvC,WAAU;AAAA,oBACX;AAAA;AAAA,gBAED;AAAA,iBAEJ;AAAA,eACF;AAAA,YAID,cAAc,WACb,+CAAC,SAAI,WAAU,+BACb;AAAA,6DAAC,SAAI,WAAU,qCACb;AAAA,8DAAC,UAAK,WAAU,qEAAoE,2BAEpF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,OAAO,eAAe;AAAA,oBACrC,WAAU;AAAA,oBACX;AAAA;AAAA,gBAED;AAAA,iBACF;AAAA,cAEA,+CAAC,WAAM,WAAU,yDACf;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,UAAU;AAAA,oBACzB,UAAU,CAAC,MAAM,OAAO,aAAa,EAAE,SAAS,EAAE,OAAO,QAAQ,CAAC;AAAA,oBAClE,WAAU;AAAA;AAAA,gBACZ;AAAA,gBACA,8CAAC,UAAK,uCAAyB;AAAA,iBACjC;AAAA,cAEC,MAAM,UAAU,WACf,gFACE;AAAA,+DAAC,SACC;AAAA,gEAAC,WAAM,WAAU,6BAA4B,6BAAe;AAAA,kBAC5D;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,aAAY;AAAA,sBACZ,OAAO,MAAM,UAAU,cAAc;AAAA,sBACrC,UAAU,CAAC,MAAM,OAAO,aAAa,EAAE,YAAY,EAAE,OAAO,SAAS,KAAK,CAAC;AAAA,sBAC3E,WAAU;AAAA;AAAA,kBACZ;AAAA,mBACF;AAAA,gBAEA,+CAAC,SAAI,WAAU,cACb;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,SAAS,MAAM,OAAO,aAAa,EAAE,MAAM,YAAY,CAAC;AAAA,sBACxD,WAAW,uDACT,MAAM,UAAU,SAAS,cACrB,+CACA,8CACN;AAAA,sBACD;AAAA;AAAA,kBAED;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,SAAS,MAAM,OAAO,aAAa,EAAE,MAAM,aAAa,CAAC;AAAA,sBACzD,WAAW,uDACT,MAAM,UAAU,SAAS,eACrB,+CACA,8CACN;AAAA,sBACD;AAAA;AAAA,kBAED;AAAA,mBACF;AAAA,gBAEA,+CAAC,SACC;AAAA,iEAAC,SAAI,WAAU,4CACb;AAAA,kEAAC,UAAK,kCAAoB;AAAA,oBAC1B,8CAAC,UAAK,WAAU,aAAa,gBAAM,UAAU,WAAW,CAAC,GAAE;AAAA,qBAC7D;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,KAAI;AAAA,sBACJ,KAAI;AAAA,sBACJ,OAAO,MAAM,UAAU,WAAW,CAAC;AAAA,sBACnC,UAAU,CAAC,MACT,OAAO,aAAa;AAAA,wBAClB,YAAY,CAAC,OAAO,EAAE,OAAO,KAAK,GAAG,MAAM,UAAU,WAAW,CAAC,CAAC;AAAA,sBACpE,CAAC;AAAA,sBAEH,WAAU;AAAA;AAAA,kBACZ;AAAA,mBACF;AAAA,gBAEA,+CAAC,SACC;AAAA,iEAAC,SAAI,WAAU,4CACb;AAAA,kEAAC,UAAK,iCAAmB;AAAA,oBACzB,8CAAC,UAAK,WAAU,aAAa,gBAAM,UAAU,WAAW,CAAC,GAAE;AAAA,qBAC7D;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,KAAI;AAAA,sBACJ,KAAI;AAAA,sBACJ,OAAO,MAAM,UAAU,WAAW,CAAC;AAAA,sBACnC,UAAU,CAAC,MACT,OAAO,aAAa;AAAA,wBAClB,YAAY,CAAC,MAAM,UAAU,WAAW,CAAC,GAAG,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,sBACpE,CAAC;AAAA,sBAEH,WAAU;AAAA;AAAA,kBACZ;AAAA,mBACF;AAAA,gBAEA,+CAAC,SACC;AAAA,iEAAC,SAAI,WAAU,4CACb;AAAA,kEAAC,UAAK,uBAAS;AAAA,oBACf,8CAAC,UAAK,WAAU,aAAa,gBAAM,UAAU,UAAS;AAAA,qBACxD;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,KAAI;AAAA,sBACJ,KAAI;AAAA,sBACJ,OAAO,MAAM,UAAU;AAAA,sBACvB,UAAU,CAAC,MAAM,OAAO,aAAa,EAAE,UAAU,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,sBACzE,WAAU;AAAA;AAAA,kBACZ;AAAA,mBACF;AAAA,gBAEA,+CAAC,WAAM,WAAU,8DACf;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,SAAS,MAAM,UAAU;AAAA,sBACzB,UAAU,CAAC,MAAM,OAAO,aAAa,EAAE,QAAQ,EAAE,OAAO,QAAQ,CAAC;AAAA,sBACjE,WAAU;AAAA;AAAA,kBACZ;AAAA,kBACA,8CAAC,UAAK,yBAAW;AAAA,mBACnB;AAAA,iBACF;AAAA,eAEJ;AAAA,YAID,cAAc,QACb,+CAAC,SAAI,WAAU,+BAEb;AAAA,6DAAC,SAAI,WAAU,gFACb;AAAA,+DAAC,SAAI,WAAU,qCACb;AAAA,iEAAC,UAAK,WAAU,+FACd;AAAA,kEAAC,SAAI,WAAU,+BAA8B,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAC7G,wDAAC,UAAK,GAAE,+EAA8E,GACxF;AAAA,oBAAM;AAAA,qBAER;AAAA,kBACC,gBACC,8CAAC,UAAK,WAAU,yHAAwH,yBAExI;AAAA,mBAEJ;AAAA,gBAEA,8CAAC,OAAE,WAAU,8CAA6C,iFAE1D;AAAA,gBAEA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS;AAAA,oBACT,UAAU,gBAAgB;AAAA,oBAC1B,WAAU;AAAA,oBAET,yBACC,gFACE;AAAA,oEAAC,SAAI,WAAU,iFAAgF;AAAA,sBAAE;AAAA,uBAEnG,IAEA,gFACE;AAAA,oEAAC,SAAI,WAAU,eAAc,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAC7F,wDAAC,UAAK,GAAE,sHAAqH,GAC/H;AAAA,sBAAM;AAAA,uBAER;AAAA;AAAA,gBAEJ;AAAA,iBACF;AAAA,cAGA,+CAAC,SAAI,WAAU,gFACb;AAAA,+DAAC,SAAI,WAAU,qCACb;AAAA,iEAAC,UAAK,WAAU,+FACd;AAAA,mEAAC,SAAI,WAAU,+BAA8B,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAC7G;AAAA,oEAAC,UAAK,GAAE,8GAA6G;AAAA,sBACrH,8CAAC,UAAK,GAAE,aAAY;AAAA,uBACtB;AAAA,oBAAM;AAAA,qBAER;AAAA,kBACC,gBACC,8CAAC,UAAK,WAAU,yHAAwH,2BAExI;AAAA,mBAEJ;AAAA,gBAEA,8CAAC,OAAE,WAAU,8CAA6C,kGAE1D;AAAA,gBAEA,+CAAC,SAAI,WAAU,uBACb;AAAA,gEAAC,WAAM,SAAQ,2BAA0B,WAAU,0CAAyC,oBAAM;AAAA,kBAClG;AAAA,oBAAC;AAAA;AAAA,sBACC,IAAG;AAAA,sBACH,OAAO;AAAA,sBACP,UAAU,CAAC,MAAM,iBAAiB,EAAE,OAAO,KAAK;AAAA,sBAChD,aAAY;AAAA,sBACZ,MAAM;AAAA,sBACN,WAAU;AAAA;AAAA,kBACZ;AAAA,mBACF;AAAA,gBAEA,+CAAC,SAAI,WAAU,uBACb;AAAA,gEAAC,UAAK,WAAU,0CAAyC,gCAAkB;AAAA,kBAC3E,+CAAC,SAAI,WAAU,4BACb;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,MAAK;AAAA,wBACL,SAAS,MAAM,mBAAmB,aAAa;AAAA,wBAC/C,WAAW,kFACT,oBAAoB,gBAChB,uDACA,mEACN;AAAA,wBACD;AAAA;AAAA,0BACgB,MAAM,YAAY;AAAA,0BAAO;AAAA;AAAA;AAAA,oBAC1C;AAAA,oBACA;AAAA,sBAAC;AAAA;AAAA,wBACC,MAAK;AAAA,wBACL,SAAS,MAAM,mBAAmB,MAAM;AAAA,wBACxC,WAAW,kFACT,oBAAoB,SAChB,uDACA,mEACN;AAAA,wBACD;AAAA;AAAA,0BACY,MAAM,OAAO,aAAa;AAAA,0BAAO;AAAA;AAAA;AAAA,oBAC9C;AAAA,qBACF;AAAA,mBACF;AAAA,gBAEA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS;AAAA,oBACT,UAAU,gBAAgB,gBAAgB,CAAC,cAAc,KAAK;AAAA,oBAC9D,WAAU;AAAA,oBAET,yBACC,gFACE;AAAA,oEAAC,SAAI,WAAU,iFAAgF;AAAA,sBAAE;AAAA,uBAEnG,IAEA,gFACE;AAAA,oEAAC,SAAI,WAAU,eAAc,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAC7F,wDAAC,UAAK,GAAE,sHAAqH,GAC/H;AAAA,sBAAM;AAAA,uBAER;AAAA;AAAA,gBAEJ;AAAA,iBACF;AAAA,cAEC,WACC,8CAAC,SAAI,WAAU,oFACZ,mBACH;AAAA,cAGD,aACC,8CAAC,SAAI,WAAU,6FACZ,qBACH;AAAA,eAEJ;AAAA,aAEJ;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACz6CA,IAAAC,iBAA2D;AAE3D,IAAAC,kBAOO;AAEP,IAAM,iBAAuC,OAAO,OAAO;AAAA,EACzD,SAAS,CAAC;AAAA,EACV,gBAAgB;AAClB,CAAC;AAED,IAAM,sBAA4C,OAAO,OAAO;AAAA,EAC9D,SAAS;AAAA,EACT,QAAQ,EAAE,IAAI,aAAa,MAAM,YAAY;AAAA,EAC7C,SAAS,CAAC;AAAA,EACV,iBAAiB;AACnB,CAAC;AAED,IAAM,kBAAkB,MAAM;AAAC;AAE/B,SAAS,eAAe,OAAuC;AAC7D,SACE,CAAC,CAAC,SACF,OAAQ,MAAuB,gBAAgB,cAC/C,OAAQ,MAAuB,iBAAiB;AAEpD;AAUO,SAAS,YACd,QACmB;AACnB,QAAM,QAAQ,eAAe,MAAM,IAAI,aAAS,iCAAgB,MAAuB;AACvF,QAAM,gBAAY;AAAA,IAChB,CAAC,aAA0B,QAAQ,MAAM,UAAU,MAAM,SAAS,CAAC,IAAI;AAAA,IACvE,CAAC,KAAK;AAAA,EACR;AACA,QAAM,cAAc,MAAM,OAAO,YAAY,KAAK;AAClD,QAAM,eAAW,qCAAqB,WAAW,aAAa,WAAW;AACzE,aAAO,wBAAQ,OAAO,EAAE,GAAG,UAAU,MAAM,IAAI,CAAC,UAAU,KAAK,CAAC;AAClE;AAkBO,SAAS,gBAAgB,QAA0D;AACxF,QAAM,YAAQ,sCAAqB,UAAU,IAAI;AACjD,QAAM,gBAAY;AAAA,IAChB,CAAC,aAA0B,QAAQ,MAAM,UAAU,MAAM,SAAS,CAAC,IAAI;AAAA,IACvE,CAAC,KAAK;AAAA,EACR;AACA,QAAM,cAAc,MAAM,OAAO,YAAY,KAAK;AAClD,QAAM,eAAW,qCAAqB,WAAW,aAAa,WAAW;AAEzE,aAAO,wBAAQ,MAAM;AACnB,UAAM,MAAM,CAAC,OAA4B,MAAM;AAC7C,UAAI,UAAU,CAAC,OAAO,YAAa,IAAG,MAAM;AAAA,IAC9C;AACA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,eACE,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,eAAe,KAAK;AAAA,MACrE,YAAY,CAAC,YAAqB,IAAI,CAAC,MAAM,EAAE,SAAS,gBAAgB,OAAO,CAAC,EAAE;AAAA,MAClF,QAAQ,IAAI,CAAC,MAAM,EAAE,SAAS,mBAAmB,CAAC;AAAA,MAClD,QAAQ,CAAC,OAAe,IAAI,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC,EAAE;AAAA,MAChE,QAAQ,CAAC,OAAe,IAAI,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC,EAAE;AAAA,MAChE,WAAW,IAAI,CAAC,MAAM,EAAE,SAAS,iBAAiB,CAAC;AAAA,MACnD,WAAW,IAAI,CAAC,MAAM,EAAE,SAAS,iBAAiB,CAAC;AAAA,MACnD,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,CAAC;AAAA,MAC3D,UAAU,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,IAAI,CAAC;AAAA,IACrE;AAAA,EACF,GAAG,CAAC,UAAU,MAAM,CAAC;AACvB;;;ACjGA,IAAAC,iBAAgC;AAEhC,IAAAC,kBAMO;AA+CC,IAAAC,uBAAA;AA/BR,IAAM,cACJ;AACF,IAAM,qBACJ;AACF,IAAM,gBACJ;AAOK,IAAM,gBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,cAAc,sBAAsB;AAAA,EACpC,YAAY;AAAA,EACZ,aAAa,CAAC,UAAM,kCAAiB,CAAC;AAAA,EACtC,eAAe;AACjB,MAAM;AACJ,QAAM,EAAE,SAAS,gBAAgB,MAAM,IAAI,YAAY,aAAa,MAAM;AAC1E,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,mBAAmB;AACpE,QAAM,SAAS,kBAAc,kCAAiB,MAAM,KAAK,EAAE,IAAI,aAAa,MAAM,YAAY;AAE9F,QAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,gBAAgB,CAAC,EAAE,QAAQ;AACjE,QAAM,gBAAgB,QAAQ,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE;AAExD,SACE,+CAAC,WAAM,WAAsB,cAAW,YACtC;AAAA,mDAAC,SAAI,WAAU,2CACb;AAAA,qDAAC,UAAK,WAAU,6CACb;AAAA,gBAAQ,SAAS;AAAA,QAAc;AAAA,QAC/B,gBAAgB,IAAI,SAAM,aAAa,cAAc;AAAA,SACxD;AAAA,MACC,gBAAgB,KACf;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW;AAAA,UACX,gBAAc;AAAA,UACd,SAAS,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAAA,UAEvC,yBAAe,kBAAkB;AAAA;AAAA,MACpC;AAAA,OAEJ;AAAA,IACC,QAAQ,WAAW,IAClB,8CAAC,OAAE,WAAU,iCAAiC,wBAAa,IAE3D,8CAAC,QAAG,WAAU,uBAAsB,MAAK,QACtC,kBAAQ,IAAI,CAAC,WACZ;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA,QAAQ,OAAO,OAAO;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,MANK,OAAO;AAAA,IAOd,CACD,GACH;AAAA,KAEJ;AAEJ;AAWA,IAAM,oBAAsD,CAAC;AAAA,EAC3D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,UAAU,OAAO,SAAS;AAChC,QAAM,QAAQ,OAAO,QAAQ,SAAS,OAAO,aAAa;AAC1D,QAAM,OAAO,UAAU,CAAC,OAAO,cAAc,SAAS;AAEtD,QAAM,QAAQ,MAAM;AAClB,QAAI,CAAC,QAAQ;AACX,UAAI,QAAQ,CAAC,OAAO,SAAU,MAAK,SAAS,aAAa,OAAO,EAAE;AAAA,UAC7D,QAAO,gBAAgB,OAAO,EAAE;AAAA,IACvC;AAAA,EACF;AACA,QAAM,SAAS,MAAM;AACnB,QAAI,KAAM,MAAK,SAAS,cAAc,OAAO,EAAE;AAAA,QAC1C,QAAO,aAAa,OAAO,EAAE;AAAA,EACpC;AACA,QAAM,cAAc,CAAC,aAAsB;AACzC,QAAI,KAAM,MAAK,SAAS,eAAe,OAAO,IAAI,QAAQ;AAAA,QACrD,QAAO,cAAc,OAAO,IAAI,UAAU,MAAM;AAAA,EACvD;AACA,QAAM,SAAS,MAAM;AACnB,UAAM,OAAO,MAAM,KAAK;AACxB,QAAI,CAAC,QAAQ,CAAC,MAAO;AACrB,QAAI,QAAS,OAAM,YAAY,OAAO,IAAI,IAAI;AAAA,QACzC,OAAM,SAAS,OAAO,IAAI,EAAE,MAAM,OAAO,CAAC;AAC/C,aAAS,EAAE;AAAA,EACb;AACA,QAAM,OAAO,CAAC,MAA4B,EAAE,gBAAgB;AAE5D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,0EACT,SAAS,uCAAuC,eAClD,IAAI,OAAO,WAAW,eAAe,EAAE;AAAA,MACvC,kBAAgB,OAAO;AAAA,MACvB,eAAa,UAAU;AAAA,MACvB,gBAAc,UAAU;AAAA,MACxB,UAAU;AAAA,MACV,SAAS;AAAA,MACT,WAAW,CAAC,MAAM;AAChB,YAAI,EAAE,WAAW,EAAE,kBAAkB,EAAE,QAAQ,WAAW,EAAE,QAAQ,MAAM;AACxE,YAAE,eAAe;AACjB,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,MAEA;AAAA,uDAAC,SAAI,WAAU,6CACb;AAAA,wDAAC,UAAK,WAAU,eAAe,iBAAO,OAAO,MAAK;AAAA,UAClD,8CAAC,UAAK,WAAU,iCAAiC,qBAAW,OAAO,SAAS,GAAE;AAAA,WAChF;AAAA,QACC,SACC,8CAAC,gBAAW,WAAU,4EACnB,iBACH;AAAA,QAED,OAAO,YACN,8CAAC,UAAK,WAAU,4BAA2B,6CAA+B;AAAA,QAE3E,OAAO,YAAY,8CAAC,UAAK,WAAU,iCAAgC,sBAAQ;AAAA,QAC3E,CAAC,WAAW,8CAAC,OAAE,WAAU,mCAAmC,iBAAO,MAAK;AAAA,QACxE,OAAO,QAAQ,SAAS,KACvB,8CAAC,QAAG,WAAU,mDAAkD,MAAK,QAClE,iBAAO,QAAQ,IAAI,CAAC,UACnB,+CAAC,QAAkB,WAAU,yBAAwB,iBAAe,MAAM,IACxE;AAAA,yDAAC,UAAK,WAAU,WACd;AAAA,0DAAC,UAAK,WAAU,eAAe,gBAAM,OAAO,MAAK;AAAA,YAAQ;AAAA,YACzD,8CAAC,UAAK,WAAU,yBAAyB,qBAAW,MAAM,SAAS,GAAE;AAAA,aACvE;AAAA,UACA,8CAAC,OAAE,WAAU,mCAAmC,gBAAM,MAAK;AAAA,aALpD,MAAM,EAMf,CACD,GACH;AAAA,SAEA,UAAU,YAAY,CAAC,OAAO,YAC9B,+CAAC,SAAI,WAAU,uBAAsB,SAAS,MAC5C;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,WAAW;AAAA,cACX,MAAM;AAAA,cACN,OAAO;AAAA,cACP,cAAY,UAAU,YAAY;AAAA,cAClC,aAAa,UAAU,wBAAmB;AAAA,cAC1C,WAAW;AAAA,cACX,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,cACxC,WAAW,CAAC,MAAM;AAChB,oBAAI,EAAE,QAAQ,YAAY,EAAE,WAAW,EAAE,UAAU;AACjD,oBAAE,eAAe;AACjB,yBAAO;AAAA,gBACT;AAAA,cACF;AAAA;AAAA,UACF;AAAA,UACA,+CAAC,SAAI,WAAU,0BACZ;AAAA,uBACC,8CAAC,YAAO,MAAK,UAAS,WAAW,aAAa,SAAS,QAAQ,oBAE/D;AAAA,YAEF;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAW;AAAA,gBACX,UAAU,CAAC,MAAM,KAAK;AAAA,gBACtB,SAAS;AAAA,gBAER,oBAAU,YAAY;AAAA;AAAA,YACzB;AAAA,aACF;AAAA,WACF;AAAA,QAED,CAAC,WACA,+CAAC,SAAI,WAAU,0BAAyB,SAAS,MAC/C;AAAA,wDAAC,YAAO,MAAK,UAAS,WAAW,aAAa,SAAS,MAAM,YAAY,CAAC,OAAO,QAAQ,GACtF,iBAAO,WAAW,WAAW,WAChC;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAW,GAAG,WAAW;AAAA,cACzB,SAAS;AAAA,cACV;AAAA;AAAA,UAED;AAAA,WACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AC9LM,IAAAC,uBAAA;AAxBN,IAAM,0BAA0B;AAEhC,IAAMC,eACJ;AAQK,IAAM,gBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,uBAAuB;AACzB,MAAM;AACJ,QAAM,SAAS,gBAAgB,MAAM;AACrC,QAAM,QAAQ,OAAO,QAAQ;AAC7B,QAAM,UAAU,OAAO;AACvB,QAAM,QAAQ,UAAU,OAAO,QAAQ,UAAU,CAAC,MAAM,EAAE,OAAO,QAAQ,EAAE,IAAI,IAAI;AAEnF,SACE,+CAAC,SAAI,WAAsB,MAAK,WAAU,cAAW,UACnD;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAW,GAAGA,YAAW,IAAI,OAAO,UAAU,+BAA+B,EAAE;AAAA,QAC/E,gBAAc,OAAO;AAAA,QACrB,UAAU,CAAC;AAAA,QACX,SAAS,OAAO;AAAA,QAEf,iBAAO,UAAU,gBAAgB;AAAA;AAAA,IACpC;AAAA,IACA,8CAAC,UAAK,WAAU,2BAA0B,eAAY,QAAO;AAAA,IAC7D;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWA;AAAA,QACX,cAAW;AAAA,QACX,UAAU,UAAU;AAAA,QACpB,SAAS,OAAO;AAAA,QACjB;AAAA;AAAA,IAED;AAAA,IACA,8CAAC,UAAK,WAAU,0DAAyD,aAAU,UAChF,oBAAU,IAAI,eAAe,UAAU,GAAG,KAAK,OAAO,KAAK,KAAK,GAAG,KAAK,YAC3E;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWA;AAAA,QACX,cAAW;AAAA,QACX,UAAU,UAAU;AAAA,QACpB,SAAS,OAAO;AAAA,QACjB;AAAA;AAAA,IAED;AAAA,IACC,mBAAmB,WAClB;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,QACX,oBAAkB,QAAQ;AAAA,QAC1B,OAAO,GAAG,QAAQ,OAAO,IAAI,KAAK,QAAQ,WAAW;AAAA,QAEpD;AAAA,kBAAQ,OAAO,OAAO,GAAG,QAAQ,OAAO,IAAI,OAAO;AAAA,UACnD,QAAQ;AAAA;AAAA;AAAA,IACX;AAAA,IAEF,8CAAC,UAAK,WAAU,2BAA0B,eAAY,QAAO;AAAA,IAC7D;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWA;AAAA,QACX,UAAU,CAAC;AAAA,QACX,SAAS,MAAM,WAAW,OAAO,OAAO,QAAQ,EAAE;AAAA,QACnD;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWA;AAAA,QACX,UAAU,CAAC;AAAA,QACX,SAAS,MAAM,WAAW,OAAO,OAAO,QAAQ,EAAE;AAAA,QACnD;AAAA;AAAA,IAED;AAAA,IACA,8CAAC,YAAO,MAAK,UAAS,WAAWA,cAAa,UAAU,UAAU,GAAG,SAAS,OAAO,WAAW,wBAEhG;AAAA,IACA,8CAAC,YAAO,MAAK,UAAS,WAAWA,cAAa,UAAU,UAAU,GAAG,SAAS,OAAO,WAAW,wBAEhG;AAAA,KACF;AAEJ;;;ACxFE,IAAAC,uBAAA;AALK,IAAM,gBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AACb,MACE;AAAA,EAAC;AAAA;AAAA,IACC,MAAK;AAAA,IACL;AAAA,IACA,UAAU,CAAC;AAAA,IACX,SAAS,MAAM,QAAQ,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI;AAAA,IAEvD;AAAA;AACH;;;ACzBF,IAAAC,iBAAiE;AACjE,IAAAC,mBAOO;AA0BA,SAAS,kBACd,UACA,UAA8C,CAAC,GACtB;AACzB,QAAM,iBAAa,uBAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,iBAAa;AAAA,IACjB,UACE,iDAA+B,UAAU;AAAA,MACvC,SAAS,MAAM;AACb,cAAM,IAAI,WAAW,QAAQ;AAC7B,YAAI,MAAM,OAAW,QAAO,SAAS;AACrC,eAAQ,OAAO,MAAM,aAAc,EAAqB,IAAI;AAAA,MAC9D;AAAA,MACA,OAAO,MAAM;AACX,cAAM,IAAI,WAAW,QAAQ;AAC7B,eAAO,OAAO,MAAM,aAAa,EAAE,IAAI;AAAA,MACzC;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,UAAU,QAAQ;AAAA,MAClB,iBAAiB,CAAC,YAAY,WAAW,QAAQ,kBAAkB,OAAO;AAAA,MAC1E,OAAO,CAAC,WAAW,WAAW,QAAQ,QAAQ,MAAM;AAAA,IACtD,CAAC;AAAA;AAAA,IAEH,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,YAAQ,qCAAqB,WAAW,WAAW,WAAW,UAAU,WAAW,QAAQ;AAEjG,QAAM,EAAE,QAAQ,aAAa,IAAI;AACjC,gCAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,UAAM,SAAS,iBAAiB,OAAO,WAAW,cAAc,SAAS;AACzE,QAAI,CAAC,OAAQ;AACb,UAAM,YAAY,CAAC,UAAiB;AAClC,YAAM,IAAI;AACV,UAAI,EAAE,oBAAoB,KAAC,qCAAmB,GAAG,QAAQ,WAAW,QAAQ,QAAQ,EAAG;AACvF,QAAE,eAAe;AACjB,iBAAW,OAAO;AAAA,IACpB;AACA,WAAO,iBAAiB,WAAW,SAAS;AAC5C,WAAO,MAAM,OAAO,oBAAoB,WAAW,SAAS;AAAA,EAC9D,GAAG,CAAC,YAAY,QAAQ,YAAY,CAAC;AAErC,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,SAAS,WAAW;AAAA,IACpB,QAAQ,WAAW;AAAA,IACnB,UAAU,WAAW;AAAA,IACrB,gBAAgB,WAAW;AAAA,IAC3B,MAAM,WAAW;AAAA,IACjB,KAAK,WAAW;AAAA,IAChB,WAAW,WAAW;AAAA,IACtB,eAAe,WAAW;AAAA,EAC5B;AACF;;;AC7FA,IAAAC,iBAAgD;AAeH,IAAAC,uBAAA;AAD7C,SAAS,iBAAiB,EAAE,KAAK,GAAiC;AAChE,MAAI,KAAK,aAAa,WAAW,EAAG,QAAO,+EAAG,eAAK,OAAM;AACzD,QAAM,SAAS,IAAI,IAAI,KAAK,YAAY;AACxC,SACE,+EACG,gBAAM,KAAK,KAAK,KAAK,EAAE;AAAA,IAAI,CAAC,IAAI,MAC/B,OAAO,IAAI,CAAC,IACV,8CAAC,UAAa,WAAU,iCAAgC,cAAW,IAChE,gBADQ,CAEX,IAEA,8CAAC,eAAAC,QAAM,UAAN,EAAwB,gBAAJ,CAAO;AAAA,EAEhC,GACF;AAEJ;AAOO,IAAM,iBAAgD,CAAC;AAAA,EAC5D;AAAA,EACA,cAAc;AAAA,EACd,eAAe;AAAA,EACf,YAAY;AACd,MAAM;AACJ,QAAM,eAAW,uBAAyB,IAAI;AAC9C,QAAM,cAAU,uBAAyB,IAAI;AAC7C,QAAM,aAAS,sBAAM;AACrB,QAAM,SAAS,GAAG,MAAM;AACxB,QAAM,WAAW,CAAC,UAAkB,GAAG,MAAM,WAAW,KAAK;AAC7D,QAAM,EAAE,MAAM,OAAO,OAAO,YAAY,IAAI;AAE5C,gCAAU,MAAM;AACd,QAAI,KAAM,UAAS,SAAS,MAAM;AAAA,EACpC,GAAG,CAAC,IAAI,CAAC;AAET,gCAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,SAAS,QAAQ,SAAS,cAA2B,wBAAwB;AACnF,YAAQ,iBAAiB,EAAE,OAAO,UAAU,CAAC;AAAA,EAC/C,GAAG,CAAC,MAAM,WAAW,CAAC;AAEtB,MAAI,CAAC,KAAM,QAAO;AAElB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,iCAA8B;AAAA,MAC9B,aAAa,CAAC,MAAM;AAClB,YAAI,EAAE,WAAW,EAAE,cAAe,SAAQ,QAAQ,KAAK;AAAA,MACzD;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAW;AAAA,UACX,cAAW;AAAA,UACX,WAAW,gHAAgH,SAAS;AAAA,UACpI,OAAO,EAAE,YAAY,0CAA0C;AAAA,UAE/D;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,KAAK;AAAA,gBACL,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,iBAAc;AAAA,gBACd,iBAAe;AAAA,gBACf,qBAAkB;AAAA,gBAClB,yBAAuB,MAAM,SAAS,SAAS,WAAW,IAAI;AAAA,gBAC9D,cAAW;AAAA,gBACX;AAAA,gBACA,OAAO;AAAA,gBACP,UAAU,CAAC,MAAM,QAAQ,SAAS,EAAE,OAAO,KAAK;AAAA,gBAChD,WAAW,CAAC,MAAM;AAChB,sBAAI,QAAQ,cAAc,EAAE,WAAW,EAAG,GAAE,gBAAgB;AAAA,gBAC9D;AAAA,gBACA,WAAU;AAAA;AAAA,YACZ;AAAA,YACC,MAAM,WAAW,IAChB,8CAAC,SAAI,WAAU,uDAAuD,wBAAa,IAEnF,8CAAC,QAAG,KAAK,SAAS,IAAI,QAAQ,MAAK,WAAU,cAAW,YAAW,WAAU,iCAC1E,gBAAM,IAAI,CAAC,MAAM,UAChB;AAAA,cAAC;AAAA;AAAA,gBAEC,IAAI,SAAS,KAAK;AAAA,gBAClB,MAAK;AAAA,gBACL,iBAAe,UAAU;AAAA,gBACzB,iBAAe,CAAC,KAAK,WAAW;AAAA,gBAChC,mBAAiB,KAAK;AAAA,gBACtB,eAAa,KAAK,SAAS,KAAK;AAAA,gBAChC,OAAO,KAAK;AAAA,gBACZ,aAAa,MAAM,UAAU,eAAe,QAAQ,eAAe,KAAK;AAAA,gBACxE,aAAa,CAAC,MAAM,EAAE,eAAe;AAAA,gBACrC,SAAS,MAAM,QAAQ,IAAI,KAAK,EAAE;AAAA,gBAClC,WAAW,8DACT,UAAU,cAAc,aAAa,EACvC,IAAI,KAAK,UAAU,KAAK,2BAA2B;AAAA,gBAEnD;AAAA,iEAAC,UAAK,WAAU,2BACd;AAAA,kEAAC,oBAAiB,MAAY;AAAA,oBAC7B,KAAK,kBACJ,8CAAC,UAAK,WAAU,sCAAqC,wBAAqB,IACvE,eAAK,gBACR;AAAA,qBAEJ;AAAA,kBACC,KAAK,SAAS,8CAAC,UAAK,WAAU,0CAA0C,eAAK,OAAM;AAAA,kBACnF,KAAK,YACJ,8CAAC,SAAI,WAAU,4FACZ,eAAK,UACR;AAAA;AAAA;AAAA,cA3BG,KAAK;AAAA,YA6BZ,CACD,GACH;AAAA;AAAA;AAAA,MAEJ;AAAA;AAAA,EACF;AAEJ;;;ACxIA,IAAAC,iBAAkC;AAuB3B,SAAS,oBACd,UACA,UAAgD,CAAC,GAC3C;AACN,QAAM,iBAAa,uBAAO,OAAO;AACjC,aAAW,UAAU;AACrB,QAAM,EAAE,UAAU,MAAM,OAAO,IAAI;AAEnC,gCAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,QAAS;AAC3B,UAAM,cAAc,WAAW,OAAO,WAAW,cAAc,SAAS;AACxE,QAAI,CAAC,YAAa;AAClB,UAAM,YAAY,CAAC,UAAiB;AAClC,YAAM,EAAE,QAAQ,SAAS,iBAAiB,MAAM,IAAI,WAAW;AAC/D,YAAM,SAAS,SAAS,cAAc,OAAwB;AAAA,QAC5D;AAAA,QACA,GAAI,oBAAoB,SAAY,EAAE,gBAAgB,IAAI,CAAC;AAAA,QAC3D,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7C,CAAC;AACD,UAAI,OAAQ,SAAQ,MAAM;AAAA,IAC5B;AACA,gBAAY,iBAAiB,WAAW,SAAS;AACjD,WAAO,MAAM,YAAY,oBAAoB,WAAW,SAAS;AAAA,EACnE,GAAG,CAAC,UAAU,SAAS,MAAM,CAAC;AAChC;AAMO,SAAS,oBACd,UACA,OACM;AACN,gCAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,SAAS,MAAM,WAAW,EAAG;AAC/C,WAAO,SAAS,SAAS,KAAK;AAAA,EAChC,GAAG,CAAC,UAAU,KAAK,CAAC;AACtB;","names":["useEditor","import_react","StarterKit","Placeholder","import_react","import_editor","useEditor","useTipTapEditor","import_react","import_react","import_react","import_editor","import_react","import_editor","import_react","import_react","import_editor","import_react","import_react","TipTapEditorContent","import_react","import_react","import_editor","import_jsx_runtime","import_react","import_editor","import_jsx_runtime","import_react","import_editor","import_editor","import_jsx_runtime","import_editor","import_react","document","import_react","import_spreadsheet","import_react","import_spreadsheet","import_jsx_runtime","React","import_jsx_runtime","import_react","import_spreadsheet","import_react","import_spreadsheet","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_image_editor","import_jsx_runtime","currentImgPt","import_react","import_editor","import_react","import_editor","import_jsx_runtime","import_jsx_runtime","buttonClass","import_jsx_runtime","import_react","import_commands","import_react","import_jsx_runtime","React","import_react"]}
|