@pixerate/editor-react 0.63.0 → 0.65.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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/useDocxExport.ts","../src/components/ExportDocxButton.tsx","../src/hooks/useAgentToolProvider.ts","../src/hooks/useToolBridge.ts","../src/components/EditorContent.tsx","../src/components/BubbleMenu.tsx","../src/components/TemplateRenderer.tsx","../src/components/VariableForm.tsx","../src/components/MergePreview.tsx","../src/hooks/useMergePreview.ts","../src/hooks/useOutline.ts","../src/components/OutlinePanel.tsx","../src/hooks/useParagraphStyles.ts","../src/components/StylesGallery.tsx","../src/index.ts","../src/slots.tsx","../src/review/useReview.ts","../src/review/CommentsPanel.tsx","../src/review/ReviewToolbar.tsx","../src/review/CommentButton.tsx","../src/review/useDocumentCompare.ts","../src/review/TrackedChangesList.tsx","../src/find-replace/useFindReplace.ts","../src/find-replace/FindReplaceBar.tsx","../src/tables/useTableMenu.ts","../src/tables/TableToolbar.tsx","../src/tables/InsertTableGrid.tsx","../src/tables/TableBubbleMenu.tsx","../src/chart-node/ChartNodeView.tsx"],"sourcesContent":["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 summarizeImportStructure,\n type FileImportControllerOptions,\n type FileImportState,\n type ImportStructureSummary,\n} from \"@pixerate/editor\";\n\nexport interface UseFileImportResult extends FileImportState {\n /**\n * Structures detected in the last import (headings, lists, tables, columns),\n * or `null` when no adapter reported any (only structure-aware adapters such\n * as PDF do). Turn PDF detection off with\n * `useFileImport(editor, { adapterOptions: { pdf: { structure: false } } })`.\n */\n structureSummary: ImportStructureSummary | null;\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 const structureSummary = useMemo(() => summarizeImportStructure(state.lastOutcomes), [state.lastOutcomes]);\n\n return {\n ...state,\n structureSummary,\n accept: controller.accept,\n openFilePicker: controller.openFilePicker,\n importFiles: controller.importFiles,\n };\n}\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n DocxExportController,\n type DocxExportControllerOptions,\n type DocxExportReport,\n type DocxExportState,\n} from \"@pixerate/editor/export\";\n\nexport interface UseDocxExportResult extends DocxExportState {\n /** Exports the editor (with its comments, tracked changes and styles) and downloads the `.docx`. */\n download: (fileName?: string) => Promise<DocxExportReport | null>;\n /** Builds the `.docx` without downloading it. */\n exportBlob: DocxExportController[\"exportBlob\"];\n}\n\n/**\n * \"Export to Word\": downloads the editor's document as a `.docx` with its\n * comments (from the `Comments` store), tracked changes and paragraph styles.\n * `lastReport` lists anything the export had to leave out.\n */\nexport function useDocxExport(\n editor: Editor | null | undefined,\n options: DocxExportControllerOptions = {},\n): UseDocxExportResult {\n const editorRef = useRef(editor);\n editorRef.current = editor;\n\n const controller = useMemo(\n () =>\n new DocxExportController(() => {\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 return {\n ...state,\n download: (fileName?: string) => controller.download(fileName),\n exportBlob: () => controller.exportBlob(),\n };\n}\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport type { DocxExportControllerOptions, DocxExportReport } from \"@pixerate/editor/export\";\nimport { useDocxExport } from \"../hooks/useDocxExport\";\n\nexport interface ExportDocxButtonProps extends DocxExportControllerOptions {\n editor: Editor | null;\n className?: string;\n children?: React.ReactNode;\n /** Called after the download with the export report. */\n onExported?: (report: DocxExportReport) => void;\n}\n\n/** A button that downloads the editor's document as a Word file (`.docx`). */\nexport const ExportDocxButton: React.FC<ExportDocxButtonProps> = ({\n editor,\n className = \"rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-50\",\n children = \"Export to Word\",\n onExported,\n ...options\n}) => {\n const docx = useDocxExport(editor, options);\n return (\n <button\n type=\"button\"\n className={className}\n disabled={!editor || docx.isExporting}\n aria-busy={docx.isExporting || undefined}\n title={docx.error ? `Export failed: ${docx.error.message}` : undefined}\n onClick={async () => {\n const report = await docx.download();\n if (report) onExported?.(report);\n }}\n >\n {children}\n </button>\n );\n};\n","import { useEffect } from \"react\";\nimport type { AgentToolProvider, ToolRegistry } from \"@pixerate/editor/tools\";\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 { useEffect, useState } from \"react\";\nimport { connectToolBridge, type ConnectToolBridgeOptions, type ToolBridgeConnection, type ToolBridgeStatus, type ToolRegistry } from \"@pixerate/editor/tools\";\n\nexport interface UseToolBridgeResult {\n status: ToolBridgeStatus | \"off\";\n /** Why the last connection ended (e.g. \"Bad token\"), when the bridge said. */\n detail?: string;\n /** The id the bridge gave this editor (`list_editors`). */\n editorId: string | null;\n}\n\n/**\n * Connects a `ToolRegistry` to a local MCP bridge (`pixerate-mcp-bridge`) while mounted, so an\n * MCP client can call the page's tools. Pass `null` options to stay disconnected. Memoize the\n * options: changing `url`, `token` or `name` reconnects.\n */\nexport function useToolBridge(registry: ToolRegistry | null | undefined, options: ConnectToolBridgeOptions | null): UseToolBridgeResult {\n const [state, setState] = useState<UseToolBridgeResult>({ status: \"off\", editorId: null });\n const key = options ? JSON.stringify([options.url, options.token, options.name, options.kind, options.reconnect]) : null;\n useEffect(() => {\n if (!registry || !options) {\n setState({ status: \"off\", editorId: null });\n return;\n }\n let connection: ToolBridgeConnection | undefined;\n connection = connectToolBridge(registry, {\n ...options,\n onStatus: (status, detail) => {\n setState({ status, detail, editorId: connection?.editorId ?? null });\n options.onStatus?.(status, detail);\n },\n });\n setState({ status: connection.status, editorId: null });\n return () => connection?.close();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [registry, key]);\n return state;\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 describeConditionalTag,\n evaluatePromptTokens,\n formatConditionalTag,\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\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={describeConditionalTag(token)}\n >\n {formatConditionalTag(token)}\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 React, { useId, useState } from \"react\";\nimport type {\n ColorGradient,\n MergeRecordsOptions,\n MergeRecordsResult,\n ParseDataSourceOptions,\n Template,\n} from \"@pixerate/editor\";\nimport { TemplateRenderer } from \"./TemplateRenderer\";\nimport { useMergePreview } from \"../hooks/useMergePreview\";\n\nexport interface MergePreviewProps {\n /** The prompt merged with each record. */\n content: string;\n templates?: Template[];\n bindings?: Record<string, string>;\n templateColorMap?: Map<string, ColorGradient>;\n /** Initial CSV / TSV / JSON data source text. */\n defaultSource?: string;\n parseOptions?: ParseDataSourceOptions;\n /** Drop records matching this condition (e.g. `\"status=void\"`) when merging. */\n skipIf?: MergeRecordsOptions[\"skipIf\"];\n /** Separator between merged outputs (default a blank line; `\"none\"` for nothing). */\n separator?: string;\n maxOutputs?: number;\n /** Called after \"Merge all\". */\n onMerge?: (result: MergeRecordsResult) => void;\n /** Base file name for downloads (default `merged`). */\n downloadName?: string;\n className?: string;\n}\n\n/** Saves text as a file through a temporary link. */\nfunction downloadText(text: string, fileName: string, type: string): void {\n if (typeof document === \"undefined\" || typeof URL.createObjectURL !== \"function\") {\n return;\n }\n const url = URL.createObjectURL(new Blob([text], { type }));\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = fileName;\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\n/**\n * Mail-merge preview: paste or pick a CSV / JSON data source, check the\n * automatic field mapping, step through records with the resolved prompt\n * shown by `TemplateRenderer`, and merge every record into text or JSON.\n */\nexport const MergePreview: React.FC<MergePreviewProps> = ({\n content,\n templates,\n bindings,\n templateColorMap,\n defaultSource,\n parseOptions,\n skipIf,\n separator,\n maxOutputs,\n onMerge,\n downloadName = \"merged\",\n className = \"flex flex-col gap-3 text-sm\",\n}) => {\n const id = useId();\n const merge = useMergePreview({\n template: content,\n templates,\n bindings,\n initialSource: defaultSource,\n parseOptions,\n skipIf,\n separator,\n maxOutputs,\n });\n const [copied, setCopied] = useState(false);\n const { source, result } = merge;\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(merge.serialize(\"text\"));\n setCopied(true);\n } catch {\n setCopied(false);\n }\n };\n\n return (\n <div className={className} data-merge-preview=\"\">\n <label htmlFor={`${id}-source`} className=\"flex flex-col gap-1\">\n <span className=\"font-medium\">Data source (CSV, TSV or JSON)</span>\n <textarea\n id={`${id}-source`}\n data-merge-source=\"\"\n value={merge.sourceText}\n rows={5}\n spellCheck={false}\n onChange={(event) => merge.setSourceText(event.target.value)}\n className=\"px-2 py-1 font-mono text-xs rounded-md border border-violet-400/40 bg-transparent\"\n />\n </label>\n <div className=\"flex flex-wrap items-center gap-2\">\n <input\n type=\"file\"\n accept=\".csv,.tsv,.txt,.json,text/csv,application/json\"\n aria-label=\"Load data source file\"\n data-merge-file=\"\"\n onChange={(event) => {\n const file = event.target.files?.[0];\n if (file) void merge.loadFile(file);\n }}\n />\n <span data-merge-summary=\"\" className=\"opacity-70\">\n {`${source.records.length} record${source.records.length === 1 ? \"\" : \"s\"} · ${source.fields.length} field${source.fields.length === 1 ? \"\" : \"s\"}`}\n </span>\n </div>\n {source.warnings.length > 0 && merge.sourceText.trim() !== \"\" && (\n <ul data-merge-warnings=\"\" className=\"text-amber-600 text-xs\">\n {source.warnings.map((warning, i) => (\n <li key={i}>{warning.message}</li>\n ))}\n </ul>\n )}\n\n {merge.variables.length > 0 && (\n <fieldset className=\"flex flex-col gap-1\">\n <legend className=\"font-medium\">Field mapping</legend>\n {merge.variables.map((variable) => (\n <label\n key={variable}\n className=\"flex items-center gap-2\"\n data-merge-mapping={variable}\n >\n <span className=\"min-w-24 font-mono\">{`{${variable}}`}</span>\n <select\n value={merge.mapping[variable] ?? \"\"}\n aria-label={`Field for ${variable}`}\n onChange={(event) =>\n merge.setFieldMapping(variable, event.target.value || null)\n }\n className=\"px-1 py-0.5 rounded-md border border-violet-400/40 bg-transparent\"\n >\n <option value=\"\">(none)</option>\n {source.fields.map((field) => (\n <option key={field} value={field}>\n {field}\n </option>\n ))}\n </select>\n </label>\n ))}\n </fieldset>\n )}\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-merge-prev=\"\"\n onClick={merge.prev}\n disabled={merge.index <= 0}\n >\n Prev\n </button>\n <span data-merge-position=\"\">\n {merge.count === 0\n ? \"No records\"\n : `Record ${merge.index + 1} of ${merge.count}`}\n </span>\n <button\n type=\"button\"\n data-merge-next=\"\"\n onClick={merge.next}\n disabled={merge.index >= merge.count - 1}\n >\n Next\n </button>\n </div>\n\n <div data-merge-output=\"\">\n <TemplateRenderer\n content={content}\n templates={templates}\n bindings={bindings}\n templateColorMap={templateColorMap}\n resolve={!!templates && templates.length > 0}\n values={merge.values}\n />\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n data-merge-all=\"\"\n disabled={merge.count === 0}\n onClick={() => {\n const merged = merge.merge();\n setCopied(false);\n onMerge?.(merged);\n }}\n >\n Merge all\n </button>\n {result && (\n <>\n <span data-merge-result=\"\">\n {`${result.outputs.length} merged${result.skipped.length ? `, ${result.skipped.length} skipped` : \"\"}${result.truncated ? \" (stopped early)\" : \"\"}`}\n </span>\n <button type=\"button\" data-merge-copy=\"\" onClick={copy}>\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n <button\n type=\"button\"\n data-merge-download=\"text\"\n onClick={() => downloadText(merge.serialize(\"text\"), `${downloadName}.txt`, \"text/plain\")}\n >\n Download .txt\n </button>\n <button\n type=\"button\"\n data-merge-download=\"json\"\n onClick={() =>\n downloadText(merge.serialize(\"json\"), `${downloadName}.json`, \"application/json\")\n }\n >\n Download .json\n </button>\n </>\n )}\n </div>\n {result && (\n <textarea\n readOnly\n aria-label=\"Merged output\"\n data-merge-text=\"\"\n rows={6}\n value={merge.serialize(\"text\")}\n className=\"px-2 py-1 font-mono text-xs rounded-md border border-violet-400/40 bg-transparent\"\n />\n )}\n </div>\n );\n};\n","import { useCallback, useMemo, useState } from \"react\";\nimport {\n extractVariables,\n matchFields,\n mergeRecords,\n parseDataSource,\n recordToValues,\n serializeMergeOutputs,\n type MergeDataSource,\n type MergeRecord,\n type MergeRecordsOptions,\n type MergeRecordsResult,\n type ParseDataSourceOptions,\n type PromptValues,\n type Template,\n} from \"@pixerate/editor\";\n\nexport interface UseMergePreviewOptions {\n /** The prompt merged with each record. */\n template: string;\n templates?: Template[];\n bindings?: Record<string, string>;\n /** Initial CSV / TSV / JSON text. */\n initialSource?: string;\n /** How to read the data source text. */\n parseOptions?: ParseDataSourceOptions;\n /** Passed to `mergeRecords` by `merge()`. */\n skipIf?: MergeRecordsOptions[\"skipIf\"];\n separator?: string;\n maxOutputs?: number;\n}\n\nexport interface MergePreviewState {\n sourceText: string;\n setSourceText: (text: string) => void;\n /** Reads a picked file (CSV, TSV or JSON) into `sourceText`. */\n loadFile: (file: Blob) => Promise<void>;\n source: MergeDataSource;\n /** Variable names the template uses, in order. */\n variables: string[];\n /** Variable → field: automatic matches with the user's overrides applied. */\n mapping: Record<string, string | null>;\n setFieldMapping: (variable: string, field: string | null) => void;\n resetMapping: () => void;\n /** 0-based index of the previewed record. */\n index: number;\n count: number;\n setIndex: (index: number) => void;\n next: () => void;\n prev: () => void;\n record: MergeRecord | undefined;\n /** Prompt values for the previewed record. */\n values: PromptValues;\n /** Merges every record with the current mapping and stores the result. */\n merge: () => MergeRecordsResult;\n result: MergeRecordsResult | null;\n /** The last merge's outputs as text or JSON. */\n serialize: (format: \"text\" | \"json\") => string;\n}\n\n/**\n * Headless state for a mail-merge preview (the counterpart of Svelte's\n * `createMergePreview`): parses a pasted or loaded data source, matches its\n * fields to the template's variables (editable), steps through records and\n * merges them all with `mergeRecords`.\n */\nexport function useMergePreview(options: UseMergePreviewOptions): MergePreviewState {\n const { template, templates, bindings, parseOptions } = options;\n const [sourceText, setSourceTextState] = useState(options.initialSource ?? \"\");\n const [overrides, setOverrides] = useState<Record<string, string | null>>({});\n const [index, setIndexState] = useState(0);\n const [result, setResult] = useState<MergeRecordsResult | null>(null);\n\n const source = useMemo(\n () => parseDataSource(sourceText, parseOptions),\n [sourceText, parseOptions],\n );\n const variables = useMemo(\n () => extractVariables(template, { templates, bindings }).map((v) => v.name),\n [template, templates, bindings],\n );\n const mapping = useMemo(() => {\n const merged: Record<string, string | null> = {\n ...matchFields(variables, source.fields).mapping,\n };\n for (const [variable, field] of Object.entries(overrides)) {\n if (variables.includes(variable) && (field === null || source.fields.includes(field))) {\n merged[variable] = field;\n }\n }\n return merged;\n }, [variables, source.fields, overrides]);\n\n const count = source.records.length;\n const current = count === 0 ? 0 : Math.min(index, count - 1);\n const record = source.records[current];\n const values = useMemo(\n () => (record ? recordToValues(record, mapping) : {}),\n [record, mapping],\n );\n\n const setSourceText = useCallback((text: string) => {\n setSourceTextState(text);\n setIndexState(0);\n setResult(null);\n }, []);\n const loadFile = useCallback(\n async (file: Blob) => setSourceText(await file.text()),\n [setSourceText],\n );\n const setIndex = useCallback(\n (next: number) => setIndexState(Math.max(0, Math.min(next, count - 1))),\n [count],\n );\n const setFieldMapping = useCallback((variable: string, field: string | null) => {\n setOverrides((previous) => ({ ...previous, [variable]: field }));\n setResult(null);\n }, []);\n const resetMapping = useCallback(() => setOverrides({}), []);\n\n const merge = useCallback(() => {\n const merged = mergeRecords(template, source, {\n templates,\n bindings,\n mapping,\n skipIf: options.skipIf,\n separator: options.separator,\n maxOutputs: options.maxOutputs,\n });\n setResult(merged);\n return merged;\n }, [template, source, templates, bindings, mapping, options.skipIf, options.separator, options.maxOutputs]);\n\n const serialize = useCallback(\n (format: \"text\" | \"json\") =>\n result ? serializeMergeOutputs(result.outputs, format, options.separator) : \"\",\n [result, options.separator],\n );\n\n return {\n sourceText,\n setSourceText,\n loadFile,\n source,\n variables,\n mapping,\n setFieldMapping,\n resetMapping,\n index: current,\n count,\n setIndex,\n next: () => setIndex(current + 1),\n prev: () => setIndex(current - 1),\n record,\n values,\n merge,\n result,\n serialize,\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 { useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n createParagraphStylesStore,\n getStyleRegistry,\n type CreateStyleFromSelectionOptions,\n type ParagraphStylesSnapshot,\n type StyleDefinition,\n type StyleRegistry,\n} from \"@pixerate/editor\";\n\nexport type { ParagraphStylesSnapshot, StyleDefinition } from \"@pixerate/editor\";\n\nexport interface UseParagraphStylesResult extends ParagraphStylesSnapshot {\n registry: StyleRegistry | null;\n /** The style of the block at the selection. */\n currentStyle: StyleDefinition | null;\n /** Applies a paragraph style to the selected blocks. */\n apply: (id: string) => boolean;\n /** Resets the selected blocks to Normal. */\n clear: () => boolean;\n /** Updates a style (default: the current one) to the formatting at the selection. */\n updateFromSelection: (id?: string) => boolean;\n /** Creates (and applies) a style from the formatting at the selection; returns its id. */\n createFromSelection: (name: string, options?: CreateStyleFromSelectionOptions) => string | null;\n /** Applies a character style to the selection. */\n applyCharacterStyle: (id: string) => boolean;\n}\n\n/**\n * Subscribes to an editor's paragraph styles (`ParagraphStyles` extension):\n * the gallery, all styles and the style at the selection, with commands.\n * Re-renders only when the styles or the current style change.\n */\nexport function useParagraphStyles(editor: Editor | null | undefined): UseParagraphStylesResult {\n // The store only listens to the editor while subscribed (StrictMode-safe).\n const store = useMemo(() => createParagraphStylesStore(editor), [editor]);\n const snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n return useMemo(() => {\n const registry = getStyleRegistry(editor);\n const live = () => (editor && !editor.isDestroyed ? editor : null);\n return {\n ...snapshot,\n registry,\n currentStyle: (snapshot.currentStyleId && registry?.get(snapshot.currentStyleId)) || null,\n apply: (id) => !!live()?.chain().focus().setParagraphStyle(id).run(),\n clear: () => !!live()?.chain().focus().clearParagraphStyle().run(),\n updateFromSelection: (id) => !!live()?.chain().focus().updateParagraphStyleFromSelection(id).run(),\n createFromSelection: (name, options) => {\n const e = live();\n if (!e || !registry) return null;\n const id = options?.id ?? registry.newId(name.trim());\n const ok = e.chain().focus().createParagraphStyleFromSelection(name, { ...options, id }).run();\n return ok ? id : null;\n },\n applyCharacterStyle: (id) => !!live()?.chain().focus().setCharacterStyle(id).run(),\n };\n }, [snapshot, editor]);\n}\n","import React, { useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { useParagraphStyles } from \"../hooks/useParagraphStyles\";\n\nexport interface StylesGalleryProps {\n editor: Editor | null;\n /**\n * `dropdown` (default): a button showing the current style that opens the\n * list. `gallery`: the styles are always shown, in a row.\n */\n variant?: \"dropdown\" | \"gallery\";\n /** List every available paragraph style instead of the gallery (quick) styles. */\n showAllStyles?: boolean;\n /** Show the \"Update to match selection\" and \"New style from selection\" actions. Defaults to `true`. */\n showActions?: boolean;\n /** Preview each style's font, weight, style and color in its entry. Defaults to `true`. */\n preview?: boolean;\n className?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n /** Called after a style is applied, updated or created. */\n onChange?: (event: { type: \"apply\" | \"update\" | \"create\"; id: string }) => void;\n}\n\nconst camel = (property: string) => property.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());\n\nconst keepSelection = (event: React.MouseEvent) => event.preventDefault();\n\n/**\n * Paragraph styles picker (Word's Styles gallery): shows the style at the\n * selection, applies a style on click, updates the current style to match\n * the selection and creates a new style from the selection. Needs the\n * `ParagraphStyles` extension (`richTextOptions: { paragraphStyles: true }`).\n */\nexport const StylesGallery: React.FC<StylesGalleryProps> = ({\n editor,\n variant = \"dropdown\",\n showAllStyles = false,\n showActions = true,\n preview = true,\n className = \"relative inline-flex flex-wrap items-center gap-1 text-sm\",\n itemClassName = \"rounded px-2 py-1 text-left text-xs text-foreground hover:bg-muted\",\n activeItemClassName = \"bg-primary/10 text-primary\",\n onChange,\n}) => {\n const styles = useParagraphStyles(editor);\n const [open, setOpen] = useState(false);\n const [creating, setCreating] = useState(false);\n const [name, setName] = useState(\"\");\n const list = showAllStyles ? styles.styles : styles.gallery;\n const current = styles.currentStyle;\n const expanded = variant === \"gallery\" || open;\n const close = () => {\n if (variant === \"dropdown\") setOpen(false);\n setCreating(false);\n setName(\"\");\n };\n\n const previewStyle = (id: string): React.CSSProperties | undefined => {\n if (!preview || !styles.registry) return undefined;\n return Object.fromEntries(\n Object.entries(styles.registry.previewDeclarations(id)).map(([k, v]) => [camel(k), v]),\n ) as React.CSSProperties;\n };\n\n const apply = (id: string) => {\n if (styles.apply(id)) onChange?.({ type: \"apply\", id });\n close();\n };\n\n const create = (event: React.FormEvent) => {\n event.preventDefault();\n const id = name.trim() ? styles.createFromSelection(name) : null;\n if (id) onChange?.({ type: \"create\", id });\n close();\n };\n\n return (\n <div className={className} role=\"group\" aria-label=\"Paragraph styles\" data-styles-gallery={variant}>\n {variant === \"dropdown\" && (\n <button\n type=\"button\"\n className={itemClassName}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n disabled={!editor || !styles.registry}\n onMouseDown={keepSelection}\n onClick={() => setOpen((value) => !value)}\n >\n {current?.name ?? \"Styles\"} ▾\n </button>\n )}\n {expanded && (\n <div\n className={\n variant === \"dropdown\"\n ? \"absolute left-0 top-full z-20 mt-1 flex min-w-[12rem] flex-col gap-0.5 rounded-md border border-border bg-background p-1 shadow-md\"\n : \"flex flex-wrap items-center gap-1\"\n }\n >\n <div role=\"listbox\" aria-label=\"Styles\" className={variant === \"dropdown\" ? \"flex flex-col gap-0.5\" : \"flex flex-wrap gap-1\"}>\n {list.map((style) => {\n const active = style.id === styles.currentStyleId;\n return (\n <button\n key={style.id}\n type=\"button\"\n role=\"option\"\n aria-selected={active}\n data-style-id={style.id}\n className={active ? `${itemClassName} ${activeItemClassName}` : itemClassName}\n style={previewStyle(style.id)}\n onMouseDown={keepSelection}\n onClick={() => apply(style.id)}\n >\n {style.name}\n </button>\n );\n })}\n </div>\n {showActions && (\n <div className={variant === \"dropdown\" ? \"mt-1 flex flex-col gap-0.5 border-t border-border pt-1\" : \"flex items-center gap-1\"}>\n <button\n type=\"button\"\n className={itemClassName}\n disabled={!current}\n onMouseDown={keepSelection}\n onClick={() => {\n if (current && styles.updateFromSelection(current.id)) {\n onChange?.({ type: \"update\", id: current.id });\n }\n close();\n }}\n >\n {current ? `Update ${current.name} to match selection` : \"Update to match selection\"}\n </button>\n {creating ? (\n <form className=\"flex items-center gap-1\" onSubmit={create}>\n <input\n aria-label=\"New style name\"\n className=\"w-32 rounded border border-border bg-background px-1 py-0.5 text-xs\"\n value={name}\n autoFocus\n onChange={(event) => setName(event.target.value)}\n />\n <button type=\"submit\" className={itemClassName} disabled={!name.trim()}>\n Create\n </button>\n </form>\n ) : (\n <button\n type=\"button\"\n className={itemClassName}\n disabled={!editor || !styles.registry}\n onMouseDown={keepSelection}\n onClick={() => setCreating(true)}\n >\n New style from selection\n </button>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n","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/useDocxExport\";\nexport * from \"./components/ExportDocxButton\";\nexport * from \"./hooks/useAgentToolProvider\";\nexport * from \"./hooks/useToolBridge\";\nexport * from \"./components/EditorContent\";\nexport * from \"./components/BubbleMenu\";\nexport * from \"./components/TemplateRenderer\";\nexport * from \"./components/VariableForm\";\nexport * from \"./components/MergePreview\";\nexport * from \"./hooks/useMergePreview\";\nexport * from \"./hooks/useOutline\";\nexport * from \"./components/OutlinePanel\";\nexport * from \"./hooks/useParagraphStyles\";\nexport * from \"./components/StylesGallery\";\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 MergeDataSource,\n MergeRecord,\n MergeRecordsResult,\n MergeOutput,\n} from \"@pixerate/editor\";\n\nexport * from \"./spreadsheet\";\nexport * from \"./slots\";\nexport * from \"./image-editor\";\nexport * from \"./review\";\nexport * from \"./commands\";\nexport * from \"./persistence\";\nexport * from \"./generation\";\nexport * from \"./find-replace\";\nexport * from \"./tables\";\nexport * from \"./chart-node\";\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 { 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 /** Selects a change in the editor. */\n select: (id: string) => void;\n /** Accepts a tracked move (both ends). */\n acceptMove: (id: string) => void;\n /** Rejects a tracked move (both ends). */\n rejectMove: (id: string) => 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 select: (id: string) => run((e) => e.chain().focus().selectChange(id).run())(),\n acceptMove: (id: string) => run((e) => e.commands.acceptMove(id))(),\n rejectMove: (id: string) => run((e) => e.commands.rejectMove(id))(),\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 { useCallback, useMemo, useRef, useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n applyDocumentComparison,\n type CompareSource,\n type CompareSummary,\n type EditorCompareOptions,\n} from \"@pixerate/editor\";\n\nexport type { CompareSource, CompareSummary, EditorCompareOptions } from \"@pixerate/editor\";\n\nexport interface UseDocumentCompareResult {\n /** Summary of the last comparison, or `null`. */\n summary: CompareSummary | null;\n /**\n * Replaces the editor content with the comparison of two versions (nodes,\n * JSON or HTML) as tracked changes, ready to review with `ReviewToolbar`.\n * Returns the summary, or `null` without an editor.\n */\n compare: (\n original: CompareSource,\n revised: CompareSource,\n options?: EditorCompareOptions,\n ) => CompareSummary | null;\n /** Forgets the last summary. */\n clear: () => void;\n}\n\n/**\n * Compare two document versions into an editor using `TrackChanges`.\n * `options` are defaults for every comparison.\n */\nexport function useDocumentCompare(\n editor: Editor | null | undefined,\n options?: EditorCompareOptions,\n): UseDocumentCompareResult {\n const [summary, setSummary] = useState<CompareSummary | null>(null);\n const defaults = useRef(options);\n defaults.current = options;\n const compare = useCallback(\n (original: CompareSource, revised: CompareSource, overrides?: EditorCompareOptions) => {\n if (!editor || editor.isDestroyed) return null;\n const result = applyDocumentComparison(editor, original, revised, {\n ...defaults.current,\n ...overrides,\n });\n setSummary(result.summary);\n return result.summary;\n },\n [editor],\n );\n const clear = useCallback(() => setSummary(null), []);\n return useMemo(() => ({ summary, compare, clear }), [summary, compare, clear]);\n}\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { trackedChangeLabel } from \"@pixerate/editor\";\nimport { useTrackChanges } from \"./useReview\";\n\nexport interface TrackedChangesListProps {\n editor: Editor | null;\n className?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n /** Content shown when there are no changes. */\n emptyState?: React.ReactNode;\n}\n\nconst buttonClass =\n \"rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40\";\n\n/**\n * Lists the document's tracked changes (insertions, deletions, moves,\n * formatting and block changes) with their author and description, and\n * accepts or rejects each one. A move is one entry: accepting or rejecting\n * it resolves both its source and its destination. Clicking an entry\n * selects the change in the editor.\n */\nexport const TrackedChangesList: React.FC<TrackedChangesListProps> = ({\n editor,\n className = \"flex flex-col gap-1 text-sm\",\n itemClassName = \"flex items-center gap-2 rounded px-2 py-1 hover:bg-muted/50\",\n activeItemClassName = \"bg-primary/10\",\n emptyState = \"No tracked changes.\",\n}) => {\n const review = useTrackChanges(editor);\n\n if (review.changes.length === 0) {\n return (\n <div className={className} data-tracked-changes-list=\"\">\n <div className=\"pixerate-changes-empty text-xs text-muted-foreground\">{emptyState}</div>\n </div>\n );\n }\n\n return (\n <ul className={className} role=\"list\" aria-label=\"Tracked changes\" data-tracked-changes-list=\"\">\n {review.changes.map((change) => {\n const active = change.id === review.currentChangeId;\n return (\n <li\n key={`${change.type}:${change.id}`}\n className={active ? `${itemClassName} ${activeItemClassName}` : itemClassName}\n data-change-type={change.type}\n data-change-id={change.id}\n >\n <button\n type=\"button\"\n className=\"min-w-0 flex-1 truncate text-left text-xs\"\n title={`${change.author.name}: ${change.description}`}\n onClick={() => review.select(change.id)}\n >\n <span className=\"font-medium\">{trackedChangeLabel(change)}</span>\n {change.author.name ? ` · ${change.author.name}` : \"\"}\n <span className=\"block truncate text-muted-foreground\">{change.description}</span>\n </button>\n <button type=\"button\" className={buttonClass} onClick={() => review.accept(change.id)}>\n Accept\n </button>\n <button type=\"button\" className={buttonClass} onClick={() => review.reject(change.id)}>\n Reject\n </button>\n </li>\n );\n })}\n </ul>\n );\n};\n","import { useCallback, useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n EMPTY_FIND_REPLACE_SNAPSHOT,\n getFindReplaceStore,\n type FindOptions,\n type FindReplaceMode,\n type FindReplaceSnapshot,\n} from \"@pixerate/editor\";\n\nexport interface UseFindReplaceResult extends FindReplaceSnapshot {\n /** Whether the editor has the `FindReplace` extension. */\n available: boolean;\n matchCount: number;\n open: boolean;\n show: (mode?: FindReplaceMode) => void;\n close: () => void;\n setQuery: (query: string) => void;\n setReplacement: (replacement: string) => void;\n setOptions: (options: Partial<FindOptions>) => void;\n toggleOption: (option: keyof FindOptions) => void;\n next: () => void;\n previous: () => void;\n replace: () => void;\n replaceAll: () => void;\n clear: () => void;\n}\n\nconst noopUnsubscribe = () => {};\n\n/**\n * Subscribes to an editor's Find and Replace state (`FindReplace` extension)\n * and exposes its commands.\n */\nexport function useFindReplace(editor: Editor | null | undefined): UseFindReplaceResult {\n const store = getFindReplaceStore(editor ?? null);\n const subscribe = useCallback(\n (onChange: () => void) => (store ? store.subscribe(() => onChange()) : noopUnsubscribe),\n [store],\n );\n const getSnapshot = () => store?.getSnapshot() ?? EMPTY_FIND_REPLACE_SNAPSHOT;\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return useMemo(() => {\n const run = (fn: (e: Editor) => void) => {\n if (editor && !editor.isDestroyed && store) fn(editor);\n };\n return {\n ...snapshot,\n available: !!store,\n matchCount: snapshot.matches.length,\n show: (mode: FindReplaceMode = \"find\") =>\n run((e) => e.commands.openFindReplace({ mode })),\n close: () => run((e) => e.commands.closeFindReplace()),\n setQuery: (query: string) => run((e) => e.commands.setSearch({ query })),\n setReplacement: (replacement: string) => run((e) => e.commands.setSearch({ replacement })),\n setOptions: (options: Partial<FindOptions>) => run((e) => e.commands.setSearch({ options })),\n toggleOption: (option: keyof FindOptions) =>\n run((e) => e.commands.setSearch({ options: { [option]: !snapshot.options[option] } })),\n next: () => run((e) => e.commands.findNext()),\n previous: () => run((e) => e.commands.findPrevious()),\n replace: () => run((e) => e.commands.replaceCurrent()),\n replaceAll: () => run((e) => e.commands.replaceAll()),\n clear: () => run((e) => e.commands.clearSearch()),\n };\n }, [snapshot, editor, store]);\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { FIND_OPTION_TOGGLES, formatFindStatus } from \"@pixerate/editor\";\nimport { useFindReplace } from \"./useFindReplace\";\n\nexport interface FindReplaceBarProps {\n editor: Editor | null;\n className?: string;\n /** Render even while the find state is closed (default: only after Mod+F / Mod+H / `openFindReplace`). */\n alwaysOpen?: boolean;\n /** Show the \"More options\" toggle (prefix, suffix, ignore punctuation/white space, literal). Default `true`. */\n showMoreOptions?: boolean;\n /** Called after the bar closes (Escape or the close button). */\n onClose?: () => void;\n}\n\nconst inputClass =\n \"min-w-0 flex-1 rounded border border-input bg-background px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-ring\";\nconst buttonClass =\n \"rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent\";\nconst toggleClass = (on: boolean) =>\n `${buttonClass} font-mono ${on ? \"bg-primary/10 text-primary\" : \"text-muted-foreground\"}`;\n\nconst isMod = (e: React.KeyboardEvent) => e.metaKey || e.ctrlKey;\n\n/**\n * Word-style find bar for an editor using the `FindReplace` extension: find\n * and replace fields, option toggles, \"3 of 12\" counter, previous/next,\n * Replace and Replace All. Enter / Shift+Enter step through matches, Enter in\n * the replace field replaces, Mod+Enter replaces all, Escape closes.\n */\nexport const FindReplaceBar: React.FC<FindReplaceBarProps> = ({\n editor,\n className = \"flex flex-col gap-1 rounded-md border border-border bg-background p-1 text-sm shadow-sm\",\n alwaysOpen = false,\n showMoreOptions = true,\n onClose,\n}) => {\n const find = useFindReplace(editor);\n const findInput = useRef<HTMLInputElement>(null);\n const [moreOpen, setMoreOpen] = useState(false);\n const visible = find.available && (alwaysOpen || find.open);\n\n // Mod+F / Mod+H (in the editor or the bar) focus and select the find field.\n useEffect(() => {\n if (!visible || find.focusRequest === 0) return;\n findInput.current?.focus();\n findInput.current?.select();\n }, [visible, find.focusRequest]);\n\n if (!visible) return null;\n\n const showReplace = find.mode === \"replace\";\n const status = formatFindStatus(find);\n const hasMatches = find.matchCount > 0;\n\n const close = () => {\n find.close();\n editor?.commands.focus();\n onClose?.();\n };\n\n const onBarKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n close();\n } else if (isMod(e) && (e.key === \"f\" || e.key === \"F\")) {\n e.preventDefault();\n find.show(\"find\");\n } else if (isMod(e) && (e.key === \"h\" || e.key === \"H\")) {\n e.preventDefault();\n find.show(\"replace\");\n }\n };\n\n const onFindKeyDown = (e: React.KeyboardEvent) => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n if (e.shiftKey) find.previous();\n else find.next();\n };\n\n const onReplaceKeyDown = (e: React.KeyboardEvent) => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n if (isMod(e)) find.replaceAll();\n else find.replace();\n };\n\n return (\n <div className={className} role=\"search\" aria-label=\"Find and replace\" onKeyDown={onBarKeyDown}>\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n className={buttonClass}\n aria-label=\"Toggle replace\"\n aria-expanded={showReplace}\n onClick={() => find.show(showReplace ? \"find\" : \"replace\")}\n >\n {showReplace ? \"▾\" : \"▸\"}\n </button>\n <input\n ref={findInput}\n type=\"text\"\n className={inputClass}\n placeholder=\"Find\"\n aria-label=\"Find\"\n aria-invalid={!!find.error}\n value={find.query}\n onChange={(e) => find.setQuery(e.target.value)}\n onKeyDown={onFindKeyDown}\n />\n {FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => (\n <button\n key={t.key}\n type=\"button\"\n className={toggleClass(!!find.options[t.key])}\n aria-label={t.label}\n title={t.label}\n aria-pressed={!!find.options[t.key]}\n onClick={() => find.toggleOption(t.key)}\n >\n {t.short}\n </button>\n ))}\n <span\n className={`min-w-[5rem] px-1 text-center text-xs ${find.error ? \"text-destructive\" : \"text-muted-foreground\"}`}\n aria-live=\"polite\"\n role={find.error ? \"alert\" : \"status\"}\n data-testid=\"find-status\"\n >\n {status}\n </span>\n <button type=\"button\" className={buttonClass} aria-label=\"Previous match\" disabled={!hasMatches} onClick={find.previous}>\n ↑\n </button>\n <button type=\"button\" className={buttonClass} aria-label=\"Next match\" disabled={!hasMatches} onClick={find.next}>\n ↓\n </button>\n {showMoreOptions && (\n <button\n type=\"button\"\n className={buttonClass}\n aria-label=\"More options\"\n aria-expanded={moreOpen}\n onClick={() => setMoreOpen((v) => !v)}\n >\n …\n </button>\n )}\n <button type=\"button\" className={buttonClass} aria-label=\"Close find\" onClick={close}>\n ×\n </button>\n </div>\n {showReplace && (\n <div className=\"flex items-center gap-1 pl-7\">\n <input\n type=\"text\"\n className={inputClass}\n placeholder=\"Replace\"\n aria-label=\"Replace\"\n value={find.replacement}\n onChange={(e) => find.setReplacement(e.target.value)}\n onKeyDown={onReplaceKeyDown}\n />\n <button\n type=\"button\"\n className={buttonClass}\n disabled={!hasMatches || find.currentIndex < 0}\n onClick={find.replace}\n >\n Replace\n </button>\n <button type=\"button\" className={buttonClass} disabled={!hasMatches} onClick={find.replaceAll}>\n Replace all\n </button>\n {find.lastReplaceCount !== null && (\n <span className=\"px-1 text-xs text-muted-foreground\" aria-live=\"polite\">\n {find.lastReplaceCount === 1 ? \"1 replaced\" : `${find.lastReplaceCount} replaced`}\n </span>\n )}\n </div>\n )}\n {showMoreOptions && moreOpen && (\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1 pl-7 text-xs text-muted-foreground\">\n {FIND_OPTION_TOGGLES.filter((t) => t.advanced).map((t) => (\n <label key={t.key} className=\"flex items-center gap-1\">\n <input\n type=\"checkbox\"\n checked={!!find.options[t.key]}\n onChange={() => find.toggleOption(t.key)}\n />\n {t.label}\n </label>\n ))}\n </div>\n )}\n </div>\n );\n};\n","import { useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n createTableStore,\n getTableActionState,\n runTableAction,\n type TableAction,\n type TableActionParams,\n type TableState,\n} from \"@pixerate/editor\";\n\nexport type { TableAction, TableActionParams, TableState } from \"@pixerate/editor\";\n\nexport interface UseTableMenuResult extends TableState {\n /** Runs a table action (focusing the editor); `false` when it cannot run. */\n run: (action: TableAction, params?: TableActionParams) => boolean;\n /** `true`, or why the action cannot run with these params. */\n check: (action: TableAction, params?: TableActionParams) => true | string;\n}\n\n/**\n * Subscribes to the table at the editor's selection: whether the selection\n * is in a table, its size, header state, the cell's alignment and\n * background, and the enablement (with reasons) of every table action.\n * Re-renders only when that state changes. The Svelte counterpart is\n * `createTableMenu`.\n */\nexport function useTableMenu(editor: Editor | null | undefined): UseTableMenuResult {\n // The store only listens to the editor while subscribed (StrictMode-safe).\n const store = useMemo(() => createTableStore(editor), [editor]);\n const snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n return useMemo(\n () => ({\n ...snapshot,\n run: (action, params) => runTableAction(editor, action, params, { focus: true }),\n check: (action, params) => getTableActionState(editor, action, params),\n }),\n [snapshot, editor],\n );\n}\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { DEFAULT_TABLE_TOOLBAR, type TableToolbarItem } from \"@pixerate/editor\";\nimport { useTableMenu } from \"./useTableMenu\";\n\nexport interface TableToolbarProps {\n editor: Editor | null;\n /** Buttons to show (default `DEFAULT_TABLE_TOOLBAR`). */\n items?: readonly TableToolbarItem[];\n /** Render (with disabled buttons) when the selection is not in a table. Default `false`. */\n showWhenOutside?: boolean;\n className?: string;\n buttonClassName?: string;\n activeButtonClassName?: string;\n separatorClassName?: string;\n /** Called after a button ran its action. */\n onAction?: (item: TableToolbarItem) => void;\n}\n\nconst keepSelection = (event: React.MouseEvent) => event.preventDefault();\n\n/**\n * Table toolbar: insert/delete rows and columns, merge/split cells, header\n * toggles, cell alignment and delete table. Rendered only while the\n * selection is in a table (unless `showWhenOutside`); disabled buttons say\n * why in their tooltip. Use it inline, or inside `TableBubbleMenu`.\n */\nexport const TableToolbar: React.FC<TableToolbarProps> = ({\n editor,\n items = DEFAULT_TABLE_TOOLBAR,\n showWhenOutside = false,\n className = \"flex flex-wrap items-center gap-1 text-xs\",\n buttonClassName = \"rounded px-2 py-1 text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent\",\n activeButtonClassName = \"bg-primary/10 text-primary\",\n separatorClassName = \"mx-1 h-4 w-px bg-border\",\n onAction,\n}) => {\n const table = useTableMenu(editor);\n if (!editor || (!table.inTable && !showWhenOutside)) return null;\n\n return (\n <div className={className} role=\"toolbar\" aria-label=\"Table\" data-table-toolbar=\"\">\n {items.map((item, index) => {\n const status = table.check(item.action, item.params);\n const enabled = status === true;\n const active = item.active?.(table);\n const separator = index > 0 && items[index - 1].group !== item.group;\n return (\n <React.Fragment key={item.id}>\n {separator && <span className={separatorClassName} aria-hidden=\"true\" />}\n <button\n type=\"button\"\n data-action={item.id}\n aria-label={item.title}\n title={enabled ? item.title : `${item.title}: ${status}`}\n {...(item.active ? { \"aria-pressed\": !!active } : {})}\n disabled={!enabled}\n className={active ? `${buttonClassName} ${activeButtonClassName}` : buttonClassName}\n onMouseDown={keepSelection}\n onClick={() => {\n if (table.run(item.action, item.params)) onAction?.(item);\n }}\n >\n {item.label}\n </button>\n </React.Fragment>\n );\n })}\n </div>\n );\n};\n","import React, { useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { useTableMenu } from \"./useTableMenu\";\n\nexport interface InsertTableGridProps {\n editor: Editor | null;\n /** Grid size offered (default 8 × 8). */\n rows?: number;\n cols?: number;\n /** Insert with a header row (default `true`). */\n withHeaderRow?: boolean;\n className?: string;\n cellClassName?: string;\n activeCellClassName?: string;\n /** Called after a table was inserted. */\n onInsert?: (size: { rows: number; cols: number }) => void;\n}\n\nconst keepSelection = (event: React.MouseEvent) => event.preventDefault();\n\n/**\n * Word-style insert-table picker: hover (or focus) a cell of the grid to\n * choose the size, click to insert a table of that size at the cursor. The\n * grid is disabled (with the reason as its title) where a table cannot be\n * inserted, e.g. inside another table.\n */\nexport const InsertTableGrid: React.FC<InsertTableGridProps> = ({\n editor,\n rows = 8,\n cols = 8,\n withHeaderRow = true,\n className = \"inline-flex flex-col gap-1 rounded-md border border-border bg-background p-2 text-xs shadow-md\",\n cellClassName = \"h-4 w-4 rounded-sm border border-border bg-background disabled:opacity-40\",\n activeCellClassName = \"border-primary bg-primary/20\",\n onInsert,\n}) => {\n const table = useTableMenu(editor);\n const [hover, setHover] = useState<{ rows: number; cols: number } | null>(null);\n const status = table.actions.insertTable;\n const disabled = !editor || !status.enabled;\n\n const insert = (size: { rows: number; cols: number }) => {\n if (table.run(\"insertTable\", { ...size, withHeaderRow })) onInsert?.(size);\n setHover(null);\n };\n\n return (\n <div\n className={className}\n role=\"group\"\n aria-label=\"Insert table\"\n title={disabled ? status.reason : undefined}\n data-insert-table-grid=\"\"\n onMouseLeave={() => setHover(null)}\n >\n <div\n role=\"grid\"\n aria-label=\"Table size\"\n style={{ display: \"grid\", gridTemplateColumns: `repeat(${cols}, max-content)`, gap: 2 }}\n >\n {Array.from({ length: rows * cols }, (_, i) => {\n const size = { rows: Math.floor(i / cols) + 1, cols: (i % cols) + 1 };\n const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;\n return (\n <button\n key={i}\n type=\"button\"\n data-rows={size.rows}\n data-cols={size.cols}\n data-active={active}\n aria-label={`${size.rows} × ${size.cols} table`}\n disabled={disabled}\n className={active ? `${cellClassName} ${activeCellClassName}` : cellClassName}\n onMouseDown={keepSelection}\n onMouseEnter={() => setHover(size)}\n onFocus={() => setHover(size)}\n onClick={() => insert(size)}\n />\n );\n })}\n </div>\n <div aria-live=\"polite\" data-testid=\"insert-table-size\">\n {disabled ? status.reason : hover ? `${hover.rows} × ${hover.cols}` : \"Insert table\"}\n </div>\n </div>\n );\n};\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { shouldShowTableBubbleMenu } from \"@pixerate/editor\";\nimport { BubbleMenu, type BubbleMenuProps } from \"../components/BubbleMenu\";\nimport { TableToolbar, type TableToolbarProps } from \"./TableToolbar\";\n\nexport interface TableBubbleMenuProps\n extends Omit<BubbleMenuProps, \"editor\" | \"children\" | \"shouldShow\"> {\n editor: Editor | null;\n /** Custom content (default: a `TableToolbar`). */\n children?: React.ReactNode;\n /** Props for the default `TableToolbar`. */\n toolbarProps?: Omit<TableToolbarProps, \"editor\">;\n}\n\n/**\n * A bubble menu that follows the selection while it is in a table (even a\n * collapsed cursor), with the table toolbar or your own `children`. It uses\n * its own plugin key (`tableBubbleMenu`), so it can be combined with the\n * formatting `BubbleMenu`.\n */\nexport const TableBubbleMenu: React.FC<TableBubbleMenuProps> = ({\n editor,\n children,\n toolbarProps,\n pluginKey = \"tableBubbleMenu\",\n ...rest\n}) => (\n <BubbleMenu editor={editor} pluginKey={pluginKey} shouldShow={shouldShowTableBubbleMenu as BubbleMenuProps[\"shouldShow\"]} {...rest}>\n {children ?? <TableToolbar editor={editor} {...toolbarProps} />}\n </BubbleMenu>\n);\n","import React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport type { ChartNodeViewMount, ChartNodeViewState } from '@pixerate/editor';\nimport type { ChartTheme } from '@pixerate/editor/chart';\nimport { ChartCanvas } from '../chart/ChartCanvas';\nimport { ChartDataGrid } from '../chart/ChartDataGrid';\nimport { ChartInspector } from '../chart/ChartInspector';\nimport { chartButtonClass } from '../chart/styles';\n\nexport interface ChartNodeViewProps {\n /** What the editor's `chart` node passes (see `ChartNodeViewState`). */\n state: ChartNodeViewState;\n /** Chart colours (default: the CSS-variable theme). */\n theme?: Partial<ChartTheme>;\n /** Show the data grid under the chart while editing (default `true`). */\n showDataGrid?: boolean;\n}\n\n/**\n * A chart inside a rich-text document: read-only until clicked, then editable on the canvas\n * with the data grid and the inspector in a panel below (side by side when there is room). \"Done\", Escape or moving the\n * selection away closes it. Edits are written back to the document as undo steps.\n */\nexport function ChartNodeView({ state, theme, showDataGrid = true }: ChartNodeViewProps) {\n const { controller, editing, editable, selected, width, height, setEditing } = state;\n const open = () => {\n if (editable && !editing) setEditing(true);\n };\n return (\n <div\n className={`not-prose my-2 rounded-md border bg-background p-1 ${selected ? 'border-primary ring-1 ring-primary' : 'border-border'}`}\n data-chart-node-view=\"\"\n data-editing={editing ? '' : undefined}\n onKeyDown={(e) => {\n if (editing && e.key === 'Escape') {\n e.stopPropagation();\n setEditing(false);\n }\n }}\n >\n {editing && (\n <div className=\"mb-1 flex items-center justify-between gap-2 px-1\" data-chart-node-toolbar=\"\">\n <span className=\"text-xs text-muted-foreground\">Editing chart</span>\n <button type=\"button\" className={chartButtonClass} data-action=\"done\" onClick={() => setEditing(false)}>\n Done\n </button>\n </div>\n )}\n <div\n className={editable && !editing ? 'cursor-pointer' : undefined}\n onClick={open}\n title={editable && !editing ? 'Click to edit the chart' : undefined}\n data-chart-node-canvas=\"\"\n >\n <ChartCanvas controller={controller} width={width ?? 640} height={height} responsive={width === null} editable={editing} theme={theme} />\n </div>\n {editing && (\n // Wraps by the document's width, not the viewport's: side by side when there is room.\n <div className=\"mt-2 flex flex-wrap items-start gap-2\" data-chart-node-panel=\"\">\n {showDataGrid && (\n <div className=\"min-w-0 flex-[1_1_20rem] overflow-x-auto\">\n <ChartDataGrid controller={controller} />\n </div>\n )}\n <ChartInspector controller={controller} className=\"max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3\" />\n </div>\n )}\n </div>\n );\n}\n\nexport interface ReactChartNodeViewOptions extends Omit<ChartNodeViewProps, 'state'> {\n /** Draw something else for each chart (default `ChartNodeView`). */\n component?: React.ComponentType<ChartNodeViewProps>;\n}\n\n/**\n * The `nodeView` for the core `chart` node, drawing `ChartNodeView` in its own React root:\n * `createRichTextPreset({ chart: { nodeView: createReactChartNodeView() } })`. Works with any\n * TipTap editor (it does not need `EditorContent`); app context does not reach the chart.\n */\nexport function createReactChartNodeView(options: ReactChartNodeViewOptions = {}): ChartNodeViewMount {\n const { component: Component = ChartNodeView, ...props } = options;\n return (dom, state) => {\n const root = createRoot(dom);\n let latest = state;\n let scheduled = false;\n let destroyed = false;\n // ProseMirror creates and updates node views inside other renders (e.g. while\n // `EditorContent` mounts), where rendering another root is an error: render in a microtask.\n const schedule = () => {\n if (scheduled) return;\n scheduled = true;\n queueMicrotask(() => {\n scheduled = false;\n if (!destroyed) root.render(<Component {...props} state={latest} />);\n });\n };\n schedule();\n return {\n update: (next) => {\n latest = next;\n schedule();\n },\n destroy: () => {\n destroyed = true;\n queueMicrotask(() => root.unmount());\n },\n };\n };\n}\n"],"mappings":"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","names":["useEditor","useEffect","useRef","useState","useCallback","useRef","useRef","useCallback","useMemo","useCallback","useEffect","useRef","useState","useSyncExternalStore","useEffect","useEffect","useMemo","useRef","useSyncExternalStore","useEffect","useMemo","useRef","useSyncExternalStore","useEffect","useEffect","useState","jsx","useEffect","useRef","useState","useMemo","jsx","useMemo","useState","jsx","jsxs","useId","useState","useCallback","useMemo","useState","jsx","jsxs","useId","useState","useMemo","useSyncExternalStore","jsx","jsxs","useMemo","useSyncExternalStore","useState","jsx","jsxs","useState","DirtyTracker","HistoryManager","createHistoryManager","bindDirtyToHistory","useMemo","jsx","jsxs","useCallback","useMemo","useSyncExternalStore","useState","jsx","jsxs","useState","jsx","jsxs","buttonClass","jsx","useCallback","useMemo","useRef","useState","jsx","jsxs","buttonClass","useCallback","useMemo","useSyncExternalStore","noopUnsubscribe","useEffect","useRef","useState","jsx","jsxs","buttonClass","useRef","useState","useEffect","useMemo","useSyncExternalStore","React","jsx","jsxs","keepSelection","React","useState","jsx","jsxs","keepSelection","useState","jsx","jsx","jsxs"]}
1
+ {"version":3,"sources":["../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/useDocxExport.ts","../src/components/ExportDocxButton.tsx","../src/hooks/useAgentToolProvider.ts","../src/hooks/useToolBridge.ts","../src/components/EditorContent.tsx","../src/components/BubbleMenu.tsx","../src/components/TemplateRenderer.tsx","../src/components/VariableForm.tsx","../src/components/MergePreview.tsx","../src/hooks/useMergePreview.ts","../src/hooks/useOutline.ts","../src/components/OutlinePanel.tsx","../src/hooks/useParagraphStyles.ts","../src/components/StylesGallery.tsx","../src/index.ts","../src/slots.tsx","../src/review/useReview.ts","../src/review/CommentsPanel.tsx","../src/review/ReviewToolbar.tsx","../src/review/CommentButton.tsx","../src/review/useDocumentCompare.ts","../src/review/TrackedChangesList.tsx","../src/find-replace/useFindReplace.ts","../src/find-replace/FindReplaceBar.tsx","../src/tables/useTableMenu.ts","../src/tables/TableToolbar.tsx","../src/tables/InsertTableGrid.tsx","../src/tables/TableBubbleMenu.tsx","../src/chart-node/ChartNodeView.tsx"],"sourcesContent":["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 summarizeImportStructure,\n type FileImportControllerOptions,\n type FileImportState,\n type ImportStructureSummary,\n} from \"@pixerate/editor\";\n\nexport interface UseFileImportResult extends FileImportState {\n /**\n * Structures detected in the last import (headings, lists, tables, columns),\n * or `null` when no adapter reported any (only structure-aware adapters such\n * as PDF do). Turn PDF detection off with\n * `useFileImport(editor, { adapterOptions: { pdf: { structure: false } } })`.\n */\n structureSummary: ImportStructureSummary | null;\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 const structureSummary = useMemo(() => summarizeImportStructure(state.lastOutcomes), [state.lastOutcomes]);\n\n return {\n ...state,\n structureSummary,\n accept: controller.accept,\n openFilePicker: controller.openFilePicker,\n importFiles: controller.importFiles,\n };\n}\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n DocxExportController,\n type DocxExportControllerOptions,\n type DocxExportReport,\n type DocxExportState,\n} from \"@pixerate/editor/export\";\n\nexport interface UseDocxExportResult extends DocxExportState {\n /** Exports the editor (with its comments, tracked changes and styles) and downloads the `.docx`. */\n download: (fileName?: string) => Promise<DocxExportReport | null>;\n /** Builds the `.docx` without downloading it. */\n exportBlob: DocxExportController[\"exportBlob\"];\n}\n\n/**\n * \"Export to Word\": downloads the editor's document as a `.docx` with its\n * comments (from the `Comments` store), tracked changes and paragraph styles.\n * `lastReport` lists anything the export had to leave out.\n */\nexport function useDocxExport(\n editor: Editor | null | undefined,\n options: DocxExportControllerOptions = {},\n): UseDocxExportResult {\n const editorRef = useRef(editor);\n editorRef.current = editor;\n\n const controller = useMemo(\n () =>\n new DocxExportController(() => {\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 return {\n ...state,\n download: (fileName?: string) => controller.download(fileName),\n exportBlob: () => controller.exportBlob(),\n };\n}\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport type { DocxExportControllerOptions, DocxExportReport } from \"@pixerate/editor/export\";\nimport { useDocxExport } from \"../hooks/useDocxExport\";\n\nexport interface ExportDocxButtonProps extends DocxExportControllerOptions {\n editor: Editor | null;\n className?: string;\n children?: React.ReactNode;\n /** Called after the download with the export report. */\n onExported?: (report: DocxExportReport) => void;\n}\n\n/** A button that downloads the editor's document as a Word file (`.docx`). */\nexport const ExportDocxButton: React.FC<ExportDocxButtonProps> = ({\n editor,\n className = \"rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-50\",\n children = \"Export to Word\",\n onExported,\n ...options\n}) => {\n const docx = useDocxExport(editor, options);\n return (\n <button\n type=\"button\"\n className={className}\n disabled={!editor || docx.isExporting}\n aria-busy={docx.isExporting || undefined}\n title={docx.error ? `Export failed: ${docx.error.message}` : undefined}\n onClick={async () => {\n const report = await docx.download();\n if (report) onExported?.(report);\n }}\n >\n {children}\n </button>\n );\n};\n","import { useEffect } from \"react\";\nimport type { AgentToolProvider, ToolRegistry } from \"@pixerate/editor/tools\";\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 { useEffect, useState } from \"react\";\nimport { connectToolBridge, type ConnectToolBridgeOptions, type ToolBridgeConnection, type ToolBridgeStatus, type ToolRegistry } from \"@pixerate/editor/tools\";\n\nexport interface UseToolBridgeResult {\n status: ToolBridgeStatus | \"off\";\n /** Why the last connection ended (e.g. \"Bad token\"), when the bridge said. */\n detail?: string;\n /** The id the bridge gave this editor (`list_editors`). */\n editorId: string | null;\n}\n\n/**\n * Connects a `ToolRegistry` to a local MCP bridge (`pixerate-mcp-bridge`) while mounted, so an\n * MCP client can call the page's tools. Pass `null` options to stay disconnected. Memoize the\n * options: changing `url`, `token` or `name` reconnects.\n */\nexport function useToolBridge(registry: ToolRegistry | null | undefined, options: ConnectToolBridgeOptions | null): UseToolBridgeResult {\n const [state, setState] = useState<UseToolBridgeResult>({ status: \"off\", editorId: null });\n const key = options ? JSON.stringify([options.url, options.token, options.name, options.kind, options.reconnect]) : null;\n useEffect(() => {\n if (!registry || !options) {\n setState({ status: \"off\", editorId: null });\n return;\n }\n let connection: ToolBridgeConnection | undefined;\n connection = connectToolBridge(registry, {\n ...options,\n onStatus: (status, detail) => {\n setState({ status, detail, editorId: connection?.editorId ?? null });\n options.onStatus?.(status, detail);\n },\n });\n setState({ status: connection.status, editorId: null });\n return () => connection?.close();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [registry, key]);\n return state;\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 describeConditionalTag,\n evaluatePromptTokens,\n formatConditionalTag,\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\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={describeConditionalTag(token)}\n >\n {formatConditionalTag(token)}\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 React, { useId, useState } from \"react\";\nimport type {\n ColorGradient,\n MergeRecordsOptions,\n MergeRecordsResult,\n ParseDataSourceOptions,\n Template,\n} from \"@pixerate/editor\";\nimport { TemplateRenderer } from \"./TemplateRenderer\";\nimport { useMergePreview } from \"../hooks/useMergePreview\";\n\nexport interface MergePreviewProps {\n /** The prompt merged with each record. */\n content: string;\n templates?: Template[];\n bindings?: Record<string, string>;\n templateColorMap?: Map<string, ColorGradient>;\n /** Initial CSV / TSV / JSON data source text. */\n defaultSource?: string;\n parseOptions?: ParseDataSourceOptions;\n /** Drop records matching this condition (e.g. `\"status=void\"`) when merging. */\n skipIf?: MergeRecordsOptions[\"skipIf\"];\n /** Separator between merged outputs (default a blank line; `\"none\"` for nothing). */\n separator?: string;\n maxOutputs?: number;\n /** Called after \"Merge all\". */\n onMerge?: (result: MergeRecordsResult) => void;\n /** Base file name for downloads (default `merged`). */\n downloadName?: string;\n className?: string;\n}\n\n/** Saves text as a file through a temporary link. */\nfunction downloadText(text: string, fileName: string, type: string): void {\n if (typeof document === \"undefined\" || typeof URL.createObjectURL !== \"function\") {\n return;\n }\n const url = URL.createObjectURL(new Blob([text], { type }));\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = fileName;\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\n/**\n * Mail-merge preview: paste or pick a CSV / JSON data source, check the\n * automatic field mapping, step through records with the resolved prompt\n * shown by `TemplateRenderer`, and merge every record into text or JSON.\n */\nexport const MergePreview: React.FC<MergePreviewProps> = ({\n content,\n templates,\n bindings,\n templateColorMap,\n defaultSource,\n parseOptions,\n skipIf,\n separator,\n maxOutputs,\n onMerge,\n downloadName = \"merged\",\n className = \"flex flex-col gap-3 text-sm\",\n}) => {\n const id = useId();\n const merge = useMergePreview({\n template: content,\n templates,\n bindings,\n initialSource: defaultSource,\n parseOptions,\n skipIf,\n separator,\n maxOutputs,\n });\n const [copied, setCopied] = useState(false);\n const { source, result } = merge;\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(merge.serialize(\"text\"));\n setCopied(true);\n } catch {\n setCopied(false);\n }\n };\n\n return (\n <div className={className} data-merge-preview=\"\">\n <label htmlFor={`${id}-source`} className=\"flex flex-col gap-1\">\n <span className=\"font-medium\">Data source (CSV, TSV or JSON)</span>\n <textarea\n id={`${id}-source`}\n data-merge-source=\"\"\n value={merge.sourceText}\n rows={5}\n spellCheck={false}\n onChange={(event) => merge.setSourceText(event.target.value)}\n className=\"px-2 py-1 font-mono text-xs rounded-md border border-violet-400/40 bg-transparent\"\n />\n </label>\n <div className=\"flex flex-wrap items-center gap-2\">\n <input\n type=\"file\"\n accept=\".csv,.tsv,.txt,.json,text/csv,application/json\"\n aria-label=\"Load data source file\"\n data-merge-file=\"\"\n onChange={(event) => {\n const file = event.target.files?.[0];\n if (file) void merge.loadFile(file);\n }}\n />\n <span data-merge-summary=\"\" className=\"opacity-70\">\n {`${source.records.length} record${source.records.length === 1 ? \"\" : \"s\"} · ${source.fields.length} field${source.fields.length === 1 ? \"\" : \"s\"}`}\n </span>\n </div>\n {source.warnings.length > 0 && merge.sourceText.trim() !== \"\" && (\n <ul data-merge-warnings=\"\" className=\"text-amber-600 text-xs\">\n {source.warnings.map((warning, i) => (\n <li key={i}>{warning.message}</li>\n ))}\n </ul>\n )}\n\n {merge.variables.length > 0 && (\n <fieldset className=\"flex flex-col gap-1\">\n <legend className=\"font-medium\">Field mapping</legend>\n {merge.variables.map((variable) => (\n <label\n key={variable}\n className=\"flex items-center gap-2\"\n data-merge-mapping={variable}\n >\n <span className=\"min-w-24 font-mono\">{`{${variable}}`}</span>\n <select\n value={merge.mapping[variable] ?? \"\"}\n aria-label={`Field for ${variable}`}\n onChange={(event) =>\n merge.setFieldMapping(variable, event.target.value || null)\n }\n className=\"px-1 py-0.5 rounded-md border border-violet-400/40 bg-transparent\"\n >\n <option value=\"\">(none)</option>\n {source.fields.map((field) => (\n <option key={field} value={field}>\n {field}\n </option>\n ))}\n </select>\n </label>\n ))}\n </fieldset>\n )}\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-merge-prev=\"\"\n onClick={merge.prev}\n disabled={merge.index <= 0}\n >\n Prev\n </button>\n <span data-merge-position=\"\">\n {merge.count === 0\n ? \"No records\"\n : `Record ${merge.index + 1} of ${merge.count}`}\n </span>\n <button\n type=\"button\"\n data-merge-next=\"\"\n onClick={merge.next}\n disabled={merge.index >= merge.count - 1}\n >\n Next\n </button>\n </div>\n\n <div data-merge-output=\"\">\n <TemplateRenderer\n content={content}\n templates={templates}\n bindings={bindings}\n templateColorMap={templateColorMap}\n resolve={!!templates && templates.length > 0}\n values={merge.values}\n />\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n data-merge-all=\"\"\n disabled={merge.count === 0}\n onClick={() => {\n const merged = merge.merge();\n setCopied(false);\n onMerge?.(merged);\n }}\n >\n Merge all\n </button>\n {result && (\n <>\n <span data-merge-result=\"\">\n {`${result.outputs.length} merged${result.skipped.length ? `, ${result.skipped.length} skipped` : \"\"}${result.truncated ? \" (stopped early)\" : \"\"}`}\n </span>\n <button type=\"button\" data-merge-copy=\"\" onClick={copy}>\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n <button\n type=\"button\"\n data-merge-download=\"text\"\n onClick={() => downloadText(merge.serialize(\"text\"), `${downloadName}.txt`, \"text/plain\")}\n >\n Download .txt\n </button>\n <button\n type=\"button\"\n data-merge-download=\"json\"\n onClick={() =>\n downloadText(merge.serialize(\"json\"), `${downloadName}.json`, \"application/json\")\n }\n >\n Download .json\n </button>\n </>\n )}\n </div>\n {result && (\n <textarea\n readOnly\n aria-label=\"Merged output\"\n data-merge-text=\"\"\n rows={6}\n value={merge.serialize(\"text\")}\n className=\"px-2 py-1 font-mono text-xs rounded-md border border-violet-400/40 bg-transparent\"\n />\n )}\n </div>\n );\n};\n","import { useCallback, useMemo, useState } from \"react\";\nimport {\n extractVariables,\n matchFields,\n mergeRecords,\n parseDataSource,\n recordToValues,\n serializeMergeOutputs,\n type MergeDataSource,\n type MergeRecord,\n type MergeRecordsOptions,\n type MergeRecordsResult,\n type ParseDataSourceOptions,\n type PromptValues,\n type Template,\n} from \"@pixerate/editor\";\n\nexport interface UseMergePreviewOptions {\n /** The prompt merged with each record. */\n template: string;\n templates?: Template[];\n bindings?: Record<string, string>;\n /** Initial CSV / TSV / JSON text. */\n initialSource?: string;\n /** How to read the data source text. */\n parseOptions?: ParseDataSourceOptions;\n /** Passed to `mergeRecords` by `merge()`. */\n skipIf?: MergeRecordsOptions[\"skipIf\"];\n separator?: string;\n maxOutputs?: number;\n}\n\nexport interface MergePreviewState {\n sourceText: string;\n setSourceText: (text: string) => void;\n /** Reads a picked file (CSV, TSV or JSON) into `sourceText`. */\n loadFile: (file: Blob) => Promise<void>;\n source: MergeDataSource;\n /** Variable names the template uses, in order. */\n variables: string[];\n /** Variable → field: automatic matches with the user's overrides applied. */\n mapping: Record<string, string | null>;\n setFieldMapping: (variable: string, field: string | null) => void;\n resetMapping: () => void;\n /** 0-based index of the previewed record. */\n index: number;\n count: number;\n setIndex: (index: number) => void;\n next: () => void;\n prev: () => void;\n record: MergeRecord | undefined;\n /** Prompt values for the previewed record. */\n values: PromptValues;\n /** Merges every record with the current mapping and stores the result. */\n merge: () => MergeRecordsResult;\n result: MergeRecordsResult | null;\n /** The last merge's outputs as text or JSON. */\n serialize: (format: \"text\" | \"json\") => string;\n}\n\n/**\n * Headless state for a mail-merge preview (the counterpart of Svelte's\n * `createMergePreview`): parses a pasted or loaded data source, matches its\n * fields to the template's variables (editable), steps through records and\n * merges them all with `mergeRecords`.\n */\nexport function useMergePreview(options: UseMergePreviewOptions): MergePreviewState {\n const { template, templates, bindings, parseOptions } = options;\n const [sourceText, setSourceTextState] = useState(options.initialSource ?? \"\");\n const [overrides, setOverrides] = useState<Record<string, string | null>>({});\n const [index, setIndexState] = useState(0);\n const [result, setResult] = useState<MergeRecordsResult | null>(null);\n\n const source = useMemo(\n () => parseDataSource(sourceText, parseOptions),\n [sourceText, parseOptions],\n );\n const variables = useMemo(\n () => extractVariables(template, { templates, bindings }).map((v) => v.name),\n [template, templates, bindings],\n );\n const mapping = useMemo(() => {\n const merged: Record<string, string | null> = {\n ...matchFields(variables, source.fields).mapping,\n };\n for (const [variable, field] of Object.entries(overrides)) {\n if (variables.includes(variable) && (field === null || source.fields.includes(field))) {\n merged[variable] = field;\n }\n }\n return merged;\n }, [variables, source.fields, overrides]);\n\n const count = source.records.length;\n const current = count === 0 ? 0 : Math.min(index, count - 1);\n const record = source.records[current];\n const values = useMemo(\n () => (record ? recordToValues(record, mapping) : {}),\n [record, mapping],\n );\n\n const setSourceText = useCallback((text: string) => {\n setSourceTextState(text);\n setIndexState(0);\n setResult(null);\n }, []);\n const loadFile = useCallback(\n async (file: Blob) => setSourceText(await file.text()),\n [setSourceText],\n );\n const setIndex = useCallback(\n (next: number) => setIndexState(Math.max(0, Math.min(next, count - 1))),\n [count],\n );\n const setFieldMapping = useCallback((variable: string, field: string | null) => {\n setOverrides((previous) => ({ ...previous, [variable]: field }));\n setResult(null);\n }, []);\n const resetMapping = useCallback(() => setOverrides({}), []);\n\n const merge = useCallback(() => {\n const merged = mergeRecords(template, source, {\n templates,\n bindings,\n mapping,\n skipIf: options.skipIf,\n separator: options.separator,\n maxOutputs: options.maxOutputs,\n });\n setResult(merged);\n return merged;\n }, [template, source, templates, bindings, mapping, options.skipIf, options.separator, options.maxOutputs]);\n\n const serialize = useCallback(\n (format: \"text\" | \"json\") =>\n result ? serializeMergeOutputs(result.outputs, format, options.separator) : \"\",\n [result, options.separator],\n );\n\n return {\n sourceText,\n setSourceText,\n loadFile,\n source,\n variables,\n mapping,\n setFieldMapping,\n resetMapping,\n index: current,\n count,\n setIndex,\n next: () => setIndex(current + 1),\n prev: () => setIndex(current - 1),\n record,\n values,\n merge,\n result,\n serialize,\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 { useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n createParagraphStylesStore,\n getStyleRegistry,\n type CreateStyleFromSelectionOptions,\n type ParagraphStylesSnapshot,\n type StyleDefinition,\n type StyleRegistry,\n} from \"@pixerate/editor\";\n\nexport type { ParagraphStylesSnapshot, StyleDefinition } from \"@pixerate/editor\";\n\nexport interface UseParagraphStylesResult extends ParagraphStylesSnapshot {\n registry: StyleRegistry | null;\n /** The style of the block at the selection. */\n currentStyle: StyleDefinition | null;\n /** Applies a paragraph style to the selected blocks. */\n apply: (id: string) => boolean;\n /** Resets the selected blocks to Normal. */\n clear: () => boolean;\n /** Updates a style (default: the current one) to the formatting at the selection. */\n updateFromSelection: (id?: string) => boolean;\n /** Creates (and applies) a style from the formatting at the selection; returns its id. */\n createFromSelection: (name: string, options?: CreateStyleFromSelectionOptions) => string | null;\n /** Applies a character style to the selection. */\n applyCharacterStyle: (id: string) => boolean;\n}\n\n/**\n * Subscribes to an editor's paragraph styles (`ParagraphStyles` extension):\n * the gallery, all styles and the style at the selection, with commands.\n * Re-renders only when the styles or the current style change.\n */\nexport function useParagraphStyles(editor: Editor | null | undefined): UseParagraphStylesResult {\n // The store only listens to the editor while subscribed (StrictMode-safe).\n const store = useMemo(() => createParagraphStylesStore(editor), [editor]);\n const snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n return useMemo(() => {\n const registry = getStyleRegistry(editor);\n const live = () => (editor && !editor.isDestroyed ? editor : null);\n return {\n ...snapshot,\n registry,\n currentStyle: (snapshot.currentStyleId && registry?.get(snapshot.currentStyleId)) || null,\n apply: (id) => !!live()?.chain().focus().setParagraphStyle(id).run(),\n clear: () => !!live()?.chain().focus().clearParagraphStyle().run(),\n updateFromSelection: (id) => !!live()?.chain().focus().updateParagraphStyleFromSelection(id).run(),\n createFromSelection: (name, options) => {\n const e = live();\n if (!e || !registry) return null;\n const id = options?.id ?? registry.newId(name.trim());\n const ok = e.chain().focus().createParagraphStyleFromSelection(name, { ...options, id }).run();\n return ok ? id : null;\n },\n applyCharacterStyle: (id) => !!live()?.chain().focus().setCharacterStyle(id).run(),\n };\n }, [snapshot, editor]);\n}\n","import React, { useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { useParagraphStyles } from \"../hooks/useParagraphStyles\";\n\nexport interface StylesGalleryProps {\n editor: Editor | null;\n /**\n * `dropdown` (default): a button showing the current style that opens the\n * list. `gallery`: the styles are always shown, in a row.\n */\n variant?: \"dropdown\" | \"gallery\";\n /** List every available paragraph style instead of the gallery (quick) styles. */\n showAllStyles?: boolean;\n /** Show the \"Update to match selection\" and \"New style from selection\" actions. Defaults to `true`. */\n showActions?: boolean;\n /** Preview each style's font, weight, style and color in its entry. Defaults to `true`. */\n preview?: boolean;\n className?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n /** Called after a style is applied, updated or created. */\n onChange?: (event: { type: \"apply\" | \"update\" | \"create\"; id: string }) => void;\n}\n\nconst camel = (property: string) => property.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());\n\nconst keepSelection = (event: React.MouseEvent) => event.preventDefault();\n\n/**\n * Paragraph styles picker (Word's Styles gallery): shows the style at the\n * selection, applies a style on click, updates the current style to match\n * the selection and creates a new style from the selection. Needs the\n * `ParagraphStyles` extension (`richTextOptions: { paragraphStyles: true }`).\n */\nexport const StylesGallery: React.FC<StylesGalleryProps> = ({\n editor,\n variant = \"dropdown\",\n showAllStyles = false,\n showActions = true,\n preview = true,\n className = \"relative inline-flex flex-wrap items-center gap-1 text-sm\",\n itemClassName = \"rounded px-2 py-1 text-left text-xs text-foreground hover:bg-muted\",\n activeItemClassName = \"bg-primary/10 text-primary\",\n onChange,\n}) => {\n const styles = useParagraphStyles(editor);\n const [open, setOpen] = useState(false);\n const [creating, setCreating] = useState(false);\n const [name, setName] = useState(\"\");\n const list = showAllStyles ? styles.styles : styles.gallery;\n const current = styles.currentStyle;\n const expanded = variant === \"gallery\" || open;\n const close = () => {\n if (variant === \"dropdown\") setOpen(false);\n setCreating(false);\n setName(\"\");\n };\n\n const previewStyle = (id: string): React.CSSProperties | undefined => {\n if (!preview || !styles.registry) return undefined;\n return Object.fromEntries(\n Object.entries(styles.registry.previewDeclarations(id)).map(([k, v]) => [camel(k), v]),\n ) as React.CSSProperties;\n };\n\n const apply = (id: string) => {\n if (styles.apply(id)) onChange?.({ type: \"apply\", id });\n close();\n };\n\n const create = (event: React.FormEvent) => {\n event.preventDefault();\n const id = name.trim() ? styles.createFromSelection(name) : null;\n if (id) onChange?.({ type: \"create\", id });\n close();\n };\n\n return (\n <div className={className} role=\"group\" aria-label=\"Paragraph styles\" data-styles-gallery={variant}>\n {variant === \"dropdown\" && (\n <button\n type=\"button\"\n className={itemClassName}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n disabled={!editor || !styles.registry}\n onMouseDown={keepSelection}\n onClick={() => setOpen((value) => !value)}\n >\n {current?.name ?? \"Styles\"} ▾\n </button>\n )}\n {expanded && (\n <div\n className={\n variant === \"dropdown\"\n ? \"absolute left-0 top-full z-20 mt-1 flex min-w-[12rem] flex-col gap-0.5 rounded-md border border-border bg-background p-1 shadow-md\"\n : \"flex flex-wrap items-center gap-1\"\n }\n >\n <div role=\"listbox\" aria-label=\"Styles\" className={variant === \"dropdown\" ? \"flex flex-col gap-0.5\" : \"flex flex-wrap gap-1\"}>\n {list.map((style) => {\n const active = style.id === styles.currentStyleId;\n return (\n <button\n key={style.id}\n type=\"button\"\n role=\"option\"\n aria-selected={active}\n data-style-id={style.id}\n className={active ? `${itemClassName} ${activeItemClassName}` : itemClassName}\n style={previewStyle(style.id)}\n onMouseDown={keepSelection}\n onClick={() => apply(style.id)}\n >\n {style.name}\n </button>\n );\n })}\n </div>\n {showActions && (\n <div className={variant === \"dropdown\" ? \"mt-1 flex flex-col gap-0.5 border-t border-border pt-1\" : \"flex items-center gap-1\"}>\n <button\n type=\"button\"\n className={itemClassName}\n disabled={!current}\n onMouseDown={keepSelection}\n onClick={() => {\n if (current && styles.updateFromSelection(current.id)) {\n onChange?.({ type: \"update\", id: current.id });\n }\n close();\n }}\n >\n {current ? `Update ${current.name} to match selection` : \"Update to match selection\"}\n </button>\n {creating ? (\n <form className=\"flex items-center gap-1\" onSubmit={create}>\n <input\n aria-label=\"New style name\"\n className=\"w-32 rounded border border-border bg-background px-1 py-0.5 text-xs\"\n value={name}\n autoFocus\n onChange={(event) => setName(event.target.value)}\n />\n <button type=\"submit\" className={itemClassName} disabled={!name.trim()}>\n Create\n </button>\n </form>\n ) : (\n <button\n type=\"button\"\n className={itemClassName}\n disabled={!editor || !styles.registry}\n onMouseDown={keepSelection}\n onClick={() => setCreating(true)}\n >\n New style from selection\n </button>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n","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/useDocxExport\";\nexport * from \"./components/ExportDocxButton\";\nexport * from \"./hooks/useAgentToolProvider\";\nexport * from \"./hooks/useToolBridge\";\nexport * from \"./components/EditorContent\";\nexport * from \"./components/BubbleMenu\";\nexport * from \"./components/TemplateRenderer\";\nexport * from \"./components/VariableForm\";\nexport * from \"./components/MergePreview\";\nexport * from \"./hooks/useMergePreview\";\nexport * from \"./hooks/useOutline\";\nexport * from \"./components/OutlinePanel\";\nexport * from \"./hooks/useParagraphStyles\";\nexport * from \"./components/StylesGallery\";\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 MergeDataSource,\n MergeRecord,\n MergeRecordsResult,\n MergeOutput,\n} from \"@pixerate/editor\";\n\nexport * from \"./spreadsheet\";\nexport * from \"./slots\";\nexport * from \"./image-editor\";\nexport * from \"./review\";\nexport * from \"./commands\";\nexport * from \"./persistence\";\nexport * from \"./generation\";\nexport * from \"./find-replace\";\nexport * from \"./tables\";\nexport * from \"./chart-node\";\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 { 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 /** Selects a change in the editor. */\n select: (id: string) => void;\n /** Accepts a tracked move (both ends). */\n acceptMove: (id: string) => void;\n /** Rejects a tracked move (both ends). */\n rejectMove: (id: string) => 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 select: (id: string) => run((e) => e.chain().focus().selectChange(id).run())(),\n acceptMove: (id: string) => run((e) => e.commands.acceptMove(id))(),\n rejectMove: (id: string) => run((e) => e.commands.rejectMove(id))(),\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 { useCallback, useMemo, useRef, useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n applyDocumentComparison,\n type CompareSource,\n type CompareSummary,\n type EditorCompareOptions,\n} from \"@pixerate/editor\";\n\nexport type { CompareSource, CompareSummary, EditorCompareOptions } from \"@pixerate/editor\";\n\nexport interface UseDocumentCompareResult {\n /** Summary of the last comparison, or `null`. */\n summary: CompareSummary | null;\n /**\n * Replaces the editor content with the comparison of two versions (nodes,\n * JSON or HTML) as tracked changes, ready to review with `ReviewToolbar`.\n * Returns the summary, or `null` without an editor.\n */\n compare: (\n original: CompareSource,\n revised: CompareSource,\n options?: EditorCompareOptions,\n ) => CompareSummary | null;\n /** Forgets the last summary. */\n clear: () => void;\n}\n\n/**\n * Compare two document versions into an editor using `TrackChanges`.\n * `options` are defaults for every comparison.\n */\nexport function useDocumentCompare(\n editor: Editor | null | undefined,\n options?: EditorCompareOptions,\n): UseDocumentCompareResult {\n const [summary, setSummary] = useState<CompareSummary | null>(null);\n const defaults = useRef(options);\n defaults.current = options;\n const compare = useCallback(\n (original: CompareSource, revised: CompareSource, overrides?: EditorCompareOptions) => {\n if (!editor || editor.isDestroyed) return null;\n const result = applyDocumentComparison(editor, original, revised, {\n ...defaults.current,\n ...overrides,\n });\n setSummary(result.summary);\n return result.summary;\n },\n [editor],\n );\n const clear = useCallback(() => setSummary(null), []);\n return useMemo(() => ({ summary, compare, clear }), [summary, compare, clear]);\n}\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { trackedChangeLabel } from \"@pixerate/editor\";\nimport { useTrackChanges } from \"./useReview\";\n\nexport interface TrackedChangesListProps {\n editor: Editor | null;\n className?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n /** Content shown when there are no changes. */\n emptyState?: React.ReactNode;\n}\n\nconst buttonClass =\n \"rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40\";\n\n/**\n * Lists the document's tracked changes (insertions, deletions, moves,\n * formatting and block changes) with their author and description, and\n * accepts or rejects each one. A move is one entry: accepting or rejecting\n * it resolves both its source and its destination. Clicking an entry\n * selects the change in the editor.\n */\nexport const TrackedChangesList: React.FC<TrackedChangesListProps> = ({\n editor,\n className = \"flex flex-col gap-1 text-sm\",\n itemClassName = \"flex items-center gap-2 rounded px-2 py-1 hover:bg-muted/50\",\n activeItemClassName = \"bg-primary/10\",\n emptyState = \"No tracked changes.\",\n}) => {\n const review = useTrackChanges(editor);\n\n if (review.changes.length === 0) {\n return (\n <div className={className} data-tracked-changes-list=\"\">\n <div className=\"pixerate-changes-empty text-xs text-muted-foreground\">{emptyState}</div>\n </div>\n );\n }\n\n return (\n <ul className={className} role=\"list\" aria-label=\"Tracked changes\" data-tracked-changes-list=\"\">\n {review.changes.map((change) => {\n const active = change.id === review.currentChangeId;\n return (\n <li\n key={`${change.type}:${change.id}`}\n className={active ? `${itemClassName} ${activeItemClassName}` : itemClassName}\n data-change-type={change.type}\n data-change-id={change.id}\n >\n <button\n type=\"button\"\n className=\"min-w-0 flex-1 truncate text-left text-xs\"\n title={`${change.author.name}: ${change.description}`}\n onClick={() => review.select(change.id)}\n >\n <span className=\"font-medium\">{trackedChangeLabel(change)}</span>\n {change.author.name ? ` · ${change.author.name}` : \"\"}\n <span className=\"block truncate text-muted-foreground\">{change.description}</span>\n </button>\n <button type=\"button\" className={buttonClass} onClick={() => review.accept(change.id)}>\n Accept\n </button>\n <button type=\"button\" className={buttonClass} onClick={() => review.reject(change.id)}>\n Reject\n </button>\n </li>\n );\n })}\n </ul>\n );\n};\n","import { useCallback, useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n EMPTY_FIND_REPLACE_SNAPSHOT,\n getFindReplaceStore,\n type FindOptions,\n type FindReplaceMode,\n type FindReplaceSnapshot,\n} from \"@pixerate/editor\";\n\nexport interface UseFindReplaceResult extends FindReplaceSnapshot {\n /** Whether the editor has the `FindReplace` extension. */\n available: boolean;\n matchCount: number;\n open: boolean;\n show: (mode?: FindReplaceMode) => void;\n close: () => void;\n setQuery: (query: string) => void;\n setReplacement: (replacement: string) => void;\n setOptions: (options: Partial<FindOptions>) => void;\n toggleOption: (option: keyof FindOptions) => void;\n next: () => void;\n previous: () => void;\n replace: () => void;\n replaceAll: () => void;\n clear: () => void;\n}\n\nconst noopUnsubscribe = () => {};\n\n/**\n * Subscribes to an editor's Find and Replace state (`FindReplace` extension)\n * and exposes its commands.\n */\nexport function useFindReplace(editor: Editor | null | undefined): UseFindReplaceResult {\n const store = getFindReplaceStore(editor ?? null);\n const subscribe = useCallback(\n (onChange: () => void) => (store ? store.subscribe(() => onChange()) : noopUnsubscribe),\n [store],\n );\n const getSnapshot = () => store?.getSnapshot() ?? EMPTY_FIND_REPLACE_SNAPSHOT;\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return useMemo(() => {\n const run = (fn: (e: Editor) => void) => {\n if (editor && !editor.isDestroyed && store) fn(editor);\n };\n return {\n ...snapshot,\n available: !!store,\n matchCount: snapshot.matches.length,\n show: (mode: FindReplaceMode = \"find\") =>\n run((e) => e.commands.openFindReplace({ mode })),\n close: () => run((e) => e.commands.closeFindReplace()),\n setQuery: (query: string) => run((e) => e.commands.setSearch({ query })),\n setReplacement: (replacement: string) => run((e) => e.commands.setSearch({ replacement })),\n setOptions: (options: Partial<FindOptions>) => run((e) => e.commands.setSearch({ options })),\n toggleOption: (option: keyof FindOptions) =>\n run((e) => e.commands.setSearch({ options: { [option]: !snapshot.options[option] } })),\n next: () => run((e) => e.commands.findNext()),\n previous: () => run((e) => e.commands.findPrevious()),\n replace: () => run((e) => e.commands.replaceCurrent()),\n replaceAll: () => run((e) => e.commands.replaceAll()),\n clear: () => run((e) => e.commands.clearSearch()),\n };\n }, [snapshot, editor, store]);\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { FIND_OPTION_TOGGLES, formatFindStatus } from \"@pixerate/editor\";\nimport { useFindReplace } from \"./useFindReplace\";\n\nexport interface FindReplaceBarProps {\n editor: Editor | null;\n className?: string;\n /** Render even while the find state is closed (default: only after Mod+F / Mod+H / `openFindReplace`). */\n alwaysOpen?: boolean;\n /** Show the \"More options\" toggle (prefix, suffix, ignore punctuation/white space, literal). Default `true`. */\n showMoreOptions?: boolean;\n /** Called after the bar closes (Escape or the close button). */\n onClose?: () => void;\n}\n\nconst inputClass =\n \"min-w-0 flex-1 rounded border border-input bg-background px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-ring\";\nconst buttonClass =\n \"rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent\";\nconst toggleClass = (on: boolean) =>\n `${buttonClass} font-mono ${on ? \"bg-primary/10 text-primary\" : \"text-muted-foreground\"}`;\n\nconst isMod = (e: React.KeyboardEvent) => e.metaKey || e.ctrlKey;\n\n/**\n * Word-style find bar for an editor using the `FindReplace` extension: find\n * and replace fields, option toggles, \"3 of 12\" counter, previous/next,\n * Replace and Replace All. Enter / Shift+Enter step through matches, Enter in\n * the replace field replaces, Mod+Enter replaces all, Escape closes.\n */\nexport const FindReplaceBar: React.FC<FindReplaceBarProps> = ({\n editor,\n className = \"flex flex-col gap-1 rounded-md border border-border bg-background p-1 text-sm shadow-sm\",\n alwaysOpen = false,\n showMoreOptions = true,\n onClose,\n}) => {\n const find = useFindReplace(editor);\n const findInput = useRef<HTMLInputElement>(null);\n const [moreOpen, setMoreOpen] = useState(false);\n const visible = find.available && (alwaysOpen || find.open);\n\n // Mod+F / Mod+H (in the editor or the bar) focus and select the find field.\n useEffect(() => {\n if (!visible || find.focusRequest === 0) return;\n findInput.current?.focus();\n findInput.current?.select();\n }, [visible, find.focusRequest]);\n\n if (!visible) return null;\n\n const showReplace = find.mode === \"replace\";\n const status = formatFindStatus(find);\n const hasMatches = find.matchCount > 0;\n\n const close = () => {\n find.close();\n editor?.commands.focus();\n onClose?.();\n };\n\n const onBarKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n close();\n } else if (isMod(e) && (e.key === \"f\" || e.key === \"F\")) {\n e.preventDefault();\n find.show(\"find\");\n } else if (isMod(e) && (e.key === \"h\" || e.key === \"H\")) {\n e.preventDefault();\n find.show(\"replace\");\n }\n };\n\n const onFindKeyDown = (e: React.KeyboardEvent) => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n if (e.shiftKey) find.previous();\n else find.next();\n };\n\n const onReplaceKeyDown = (e: React.KeyboardEvent) => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n if (isMod(e)) find.replaceAll();\n else find.replace();\n };\n\n return (\n <div className={className} role=\"search\" aria-label=\"Find and replace\" onKeyDown={onBarKeyDown}>\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n className={buttonClass}\n aria-label=\"Toggle replace\"\n aria-expanded={showReplace}\n onClick={() => find.show(showReplace ? \"find\" : \"replace\")}\n >\n {showReplace ? \"▾\" : \"▸\"}\n </button>\n <input\n ref={findInput}\n type=\"text\"\n className={inputClass}\n placeholder=\"Find\"\n aria-label=\"Find\"\n aria-invalid={!!find.error}\n value={find.query}\n onChange={(e) => find.setQuery(e.target.value)}\n onKeyDown={onFindKeyDown}\n />\n {FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => (\n <button\n key={t.key}\n type=\"button\"\n className={toggleClass(!!find.options[t.key])}\n aria-label={t.label}\n title={t.label}\n aria-pressed={!!find.options[t.key]}\n onClick={() => find.toggleOption(t.key)}\n >\n {t.short}\n </button>\n ))}\n <span\n className={`min-w-[5rem] px-1 text-center text-xs ${find.error ? \"text-destructive\" : \"text-muted-foreground\"}`}\n aria-live=\"polite\"\n role={find.error ? \"alert\" : \"status\"}\n data-testid=\"find-status\"\n >\n {status}\n </span>\n <button type=\"button\" className={buttonClass} aria-label=\"Previous match\" disabled={!hasMatches} onClick={find.previous}>\n ↑\n </button>\n <button type=\"button\" className={buttonClass} aria-label=\"Next match\" disabled={!hasMatches} onClick={find.next}>\n ↓\n </button>\n {showMoreOptions && (\n <button\n type=\"button\"\n className={buttonClass}\n aria-label=\"More options\"\n aria-expanded={moreOpen}\n onClick={() => setMoreOpen((v) => !v)}\n >\n …\n </button>\n )}\n <button type=\"button\" className={buttonClass} aria-label=\"Close find\" onClick={close}>\n ×\n </button>\n </div>\n {showReplace && (\n <div className=\"flex items-center gap-1 pl-7\">\n <input\n type=\"text\"\n className={inputClass}\n placeholder=\"Replace\"\n aria-label=\"Replace\"\n value={find.replacement}\n onChange={(e) => find.setReplacement(e.target.value)}\n onKeyDown={onReplaceKeyDown}\n />\n <button\n type=\"button\"\n className={buttonClass}\n disabled={!hasMatches || find.currentIndex < 0}\n onClick={find.replace}\n >\n Replace\n </button>\n <button type=\"button\" className={buttonClass} disabled={!hasMatches} onClick={find.replaceAll}>\n Replace all\n </button>\n {find.lastReplaceCount !== null && (\n <span className=\"px-1 text-xs text-muted-foreground\" aria-live=\"polite\">\n {find.lastReplaceCount === 1 ? \"1 replaced\" : `${find.lastReplaceCount} replaced`}\n </span>\n )}\n </div>\n )}\n {showMoreOptions && moreOpen && (\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1 pl-7 text-xs text-muted-foreground\">\n {FIND_OPTION_TOGGLES.filter((t) => t.advanced).map((t) => (\n <label key={t.key} className=\"flex items-center gap-1\">\n <input\n type=\"checkbox\"\n checked={!!find.options[t.key]}\n onChange={() => find.toggleOption(t.key)}\n />\n {t.label}\n </label>\n ))}\n </div>\n )}\n </div>\n );\n};\n","import { useMemo, useSyncExternalStore } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n createTableStore,\n getTableActionState,\n runTableAction,\n type TableAction,\n type TableActionParams,\n type TableState,\n} from \"@pixerate/editor\";\n\nexport type { TableAction, TableActionParams, TableState } from \"@pixerate/editor\";\n\nexport interface UseTableMenuResult extends TableState {\n /** Runs a table action (focusing the editor); `false` when it cannot run. */\n run: (action: TableAction, params?: TableActionParams) => boolean;\n /** `true`, or why the action cannot run with these params. */\n check: (action: TableAction, params?: TableActionParams) => true | string;\n}\n\n/**\n * Subscribes to the table at the editor's selection: whether the selection\n * is in a table, its size, header state, the cell's alignment and\n * background, and the enablement (with reasons) of every table action.\n * Re-renders only when that state changes. The Svelte counterpart is\n * `createTableMenu`.\n */\nexport function useTableMenu(editor: Editor | null | undefined): UseTableMenuResult {\n // The store only listens to the editor while subscribed (StrictMode-safe).\n const store = useMemo(() => createTableStore(editor), [editor]);\n const snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n return useMemo(\n () => ({\n ...snapshot,\n run: (action, params) => runTableAction(editor, action, params, { focus: true }),\n check: (action, params) => getTableActionState(editor, action, params),\n }),\n [snapshot, editor],\n );\n}\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { DEFAULT_TABLE_TOOLBAR, type TableToolbarItem } from \"@pixerate/editor\";\nimport { useTableMenu } from \"./useTableMenu\";\n\nexport interface TableToolbarProps {\n editor: Editor | null;\n /** Buttons to show (default `DEFAULT_TABLE_TOOLBAR`). */\n items?: readonly TableToolbarItem[];\n /** Render (with disabled buttons) when the selection is not in a table. Default `false`. */\n showWhenOutside?: boolean;\n className?: string;\n buttonClassName?: string;\n activeButtonClassName?: string;\n separatorClassName?: string;\n /** Called after a button ran its action. */\n onAction?: (item: TableToolbarItem) => void;\n}\n\nconst keepSelection = (event: React.MouseEvent) => event.preventDefault();\n\n/**\n * Table toolbar: insert/delete rows and columns, merge/split cells, header\n * toggles, cell alignment and delete table. Rendered only while the\n * selection is in a table (unless `showWhenOutside`); disabled buttons say\n * why in their tooltip. Use it inline, or inside `TableBubbleMenu`.\n */\nexport const TableToolbar: React.FC<TableToolbarProps> = ({\n editor,\n items = DEFAULT_TABLE_TOOLBAR,\n showWhenOutside = false,\n className = \"flex flex-wrap items-center gap-1 text-xs\",\n buttonClassName = \"rounded px-2 py-1 text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent\",\n activeButtonClassName = \"bg-primary/10 text-primary\",\n separatorClassName = \"mx-1 h-4 w-px bg-border\",\n onAction,\n}) => {\n const table = useTableMenu(editor);\n if (!editor || (!table.inTable && !showWhenOutside)) return null;\n\n return (\n <div className={className} role=\"toolbar\" aria-label=\"Table\" data-table-toolbar=\"\">\n {items.map((item, index) => {\n const status = table.check(item.action, item.params);\n const enabled = status === true;\n const active = item.active?.(table);\n const separator = index > 0 && items[index - 1].group !== item.group;\n return (\n <React.Fragment key={item.id}>\n {separator && <span className={separatorClassName} aria-hidden=\"true\" />}\n <button\n type=\"button\"\n data-action={item.id}\n aria-label={item.title}\n title={enabled ? item.title : `${item.title}: ${status}`}\n {...(item.active ? { \"aria-pressed\": !!active } : {})}\n disabled={!enabled}\n className={active ? `${buttonClassName} ${activeButtonClassName}` : buttonClassName}\n onMouseDown={keepSelection}\n onClick={() => {\n if (table.run(item.action, item.params)) onAction?.(item);\n }}\n >\n {item.label}\n </button>\n </React.Fragment>\n );\n })}\n </div>\n );\n};\n","import React, { useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { useTableMenu } from \"./useTableMenu\";\n\nexport interface InsertTableGridProps {\n editor: Editor | null;\n /** Grid size offered (default 8 × 8). */\n rows?: number;\n cols?: number;\n /** Insert with a header row (default `true`). */\n withHeaderRow?: boolean;\n className?: string;\n cellClassName?: string;\n activeCellClassName?: string;\n /** Called after a table was inserted. */\n onInsert?: (size: { rows: number; cols: number }) => void;\n}\n\nconst keepSelection = (event: React.MouseEvent) => event.preventDefault();\n\n/**\n * Word-style insert-table picker: hover (or focus) a cell of the grid to\n * choose the size, click to insert a table of that size at the cursor. The\n * grid is disabled (with the reason as its title) where a table cannot be\n * inserted, e.g. inside another table.\n */\nexport const InsertTableGrid: React.FC<InsertTableGridProps> = ({\n editor,\n rows = 8,\n cols = 8,\n withHeaderRow = true,\n className = \"inline-flex flex-col gap-1 rounded-md border border-border bg-background p-2 text-xs shadow-md\",\n cellClassName = \"h-4 w-4 rounded-sm border border-border bg-background disabled:opacity-40\",\n activeCellClassName = \"border-primary bg-primary/20\",\n onInsert,\n}) => {\n const table = useTableMenu(editor);\n const [hover, setHover] = useState<{ rows: number; cols: number } | null>(null);\n const status = table.actions.insertTable;\n const disabled = !editor || !status.enabled;\n\n const insert = (size: { rows: number; cols: number }) => {\n if (table.run(\"insertTable\", { ...size, withHeaderRow })) onInsert?.(size);\n setHover(null);\n };\n\n return (\n <div\n className={className}\n role=\"group\"\n aria-label=\"Insert table\"\n title={disabled ? status.reason : undefined}\n data-insert-table-grid=\"\"\n onMouseLeave={() => setHover(null)}\n >\n <div\n role=\"grid\"\n aria-label=\"Table size\"\n style={{ display: \"grid\", gridTemplateColumns: `repeat(${cols}, max-content)`, gap: 2 }}\n >\n {Array.from({ length: rows * cols }, (_, i) => {\n const size = { rows: Math.floor(i / cols) + 1, cols: (i % cols) + 1 };\n const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;\n return (\n <button\n key={i}\n type=\"button\"\n data-rows={size.rows}\n data-cols={size.cols}\n data-active={active}\n aria-label={`${size.rows} × ${size.cols} table`}\n disabled={disabled}\n className={active ? `${cellClassName} ${activeCellClassName}` : cellClassName}\n onMouseDown={keepSelection}\n onMouseEnter={() => setHover(size)}\n onFocus={() => setHover(size)}\n onClick={() => insert(size)}\n />\n );\n })}\n </div>\n <div aria-live=\"polite\" data-testid=\"insert-table-size\">\n {disabled ? status.reason : hover ? `${hover.rows} × ${hover.cols}` : \"Insert table\"}\n </div>\n </div>\n );\n};\n","import React from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { shouldShowTableBubbleMenu } from \"@pixerate/editor\";\nimport { BubbleMenu, type BubbleMenuProps } from \"../components/BubbleMenu\";\nimport { TableToolbar, type TableToolbarProps } from \"./TableToolbar\";\n\nexport interface TableBubbleMenuProps\n extends Omit<BubbleMenuProps, \"editor\" | \"children\" | \"shouldShow\"> {\n editor: Editor | null;\n /** Custom content (default: a `TableToolbar`). */\n children?: React.ReactNode;\n /** Props for the default `TableToolbar`. */\n toolbarProps?: Omit<TableToolbarProps, \"editor\">;\n}\n\n/**\n * A bubble menu that follows the selection while it is in a table (even a\n * collapsed cursor), with the table toolbar or your own `children`. It uses\n * its own plugin key (`tableBubbleMenu`), so it can be combined with the\n * formatting `BubbleMenu`.\n */\nexport const TableBubbleMenu: React.FC<TableBubbleMenuProps> = ({\n editor,\n children,\n toolbarProps,\n pluginKey = \"tableBubbleMenu\",\n ...rest\n}) => (\n <BubbleMenu editor={editor} pluginKey={pluginKey} shouldShow={shouldShowTableBubbleMenu as BubbleMenuProps[\"shouldShow\"]} {...rest}>\n {children ?? <TableToolbar editor={editor} {...toolbarProps} />}\n </BubbleMenu>\n);\n","import React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport type { ChartNodeViewMount, ChartNodeViewState } from '@pixerate/editor';\nimport type { ChartTheme } from '@pixerate/editor/chart';\nimport { ChartCanvas } from '../chart/ChartCanvas';\nimport { ChartDataGrid } from '../chart/ChartDataGrid';\nimport { ChartInspector } from '../chart/ChartInspector';\nimport { chartButtonClass } from '../chart/styles';\n\nexport interface ChartNodeViewProps {\n /** What the editor's `chart` node passes (see `ChartNodeViewState`). */\n state: ChartNodeViewState;\n /** Chart colours (default: the CSS-variable theme). */\n theme?: Partial<ChartTheme>;\n /** Show the data grid under the chart while editing (default `true`). */\n showDataGrid?: boolean;\n}\n\n/**\n * A chart inside a rich-text document: read-only until clicked, then editable on the canvas\n * with the data grid and the inspector in a panel below (side by side when there is room). \"Done\", Escape or moving the\n * selection away closes it. Edits are written back to the document as undo steps.\n */\nexport function ChartNodeView({ state, theme, showDataGrid = true }: ChartNodeViewProps) {\n const { controller, editing, editable, selected, width, height, setEditing } = state;\n const open = () => {\n if (editable && !editing) setEditing(true);\n };\n return (\n <div\n className={`not-prose my-2 rounded-md border bg-background p-1 ${selected ? 'border-primary ring-1 ring-primary' : 'border-border'}`}\n data-chart-node-view=\"\"\n data-editing={editing ? '' : undefined}\n onKeyDown={(e) => {\n if (editing && e.key === 'Escape') {\n e.stopPropagation();\n setEditing(false);\n }\n }}\n >\n {editing && (\n <div className=\"mb-1 flex items-center justify-between gap-2 px-1\" data-chart-node-toolbar=\"\">\n <span className=\"text-xs text-muted-foreground\">Editing chart</span>\n <button type=\"button\" className={chartButtonClass} data-action=\"done\" onClick={() => setEditing(false)}>\n Done\n </button>\n </div>\n )}\n <div\n className={editable && !editing ? 'cursor-pointer' : undefined}\n onClick={open}\n title={editable && !editing ? 'Click to edit the chart' : undefined}\n data-chart-node-canvas=\"\"\n >\n <ChartCanvas controller={controller} width={width ?? 640} height={height} responsive={width === null} editable={editing} theme={theme} />\n </div>\n {editing && (\n // Wraps by the document's width, not the viewport's: side by side when there is room.\n <div className=\"mt-2 flex flex-wrap items-start gap-2\" data-chart-node-panel=\"\">\n {showDataGrid && (\n <div className=\"min-w-0 flex-[1_1_20rem] overflow-x-auto\">\n <ChartDataGrid controller={controller} />\n </div>\n )}\n <ChartInspector controller={controller} className=\"max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3\" />\n </div>\n )}\n </div>\n );\n}\n\nexport interface ReactChartNodeViewOptions extends Omit<ChartNodeViewProps, 'state'> {\n /** Draw something else for each chart (default `ChartNodeView`). */\n component?: React.ComponentType<ChartNodeViewProps>;\n}\n\n/**\n * The `nodeView` for the core `chart` node, drawing `ChartNodeView` in its own React root:\n * `createRichTextPreset({ chart: { nodeView: createReactChartNodeView() } })`. Works with any\n * TipTap editor (it does not need `EditorContent`); app context does not reach the chart.\n */\nexport function createReactChartNodeView(options: ReactChartNodeViewOptions = {}): ChartNodeViewMount {\n const { component: Component = ChartNodeView, ...props } = options;\n return (dom, state) => {\n const root = createRoot(dom);\n let latest = state;\n let scheduled = false;\n let destroyed = false;\n // ProseMirror creates and updates node views inside other renders (e.g. while\n // `EditorContent` mounts), where rendering another root is an error: render in a microtask.\n const schedule = () => {\n if (scheduled) return;\n scheduled = true;\n queueMicrotask(() => {\n scheduled = false;\n if (!destroyed) root.render(<Component {...props} state={latest} />);\n });\n };\n schedule();\n return {\n update: (next) => {\n latest = next;\n schedule();\n },\n destroy: () => {\n destroyed = true;\n queueMicrotask(() => root.unmount());\n },\n };\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS,WAAW,cAAc;AAC3C,SAAS,iBAAiB;AAC1B,OAAO,gBAAgB;AACvB,OAAO,iBAAiB;AACxB,SAAS,aAAa;AACtB;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;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,gBAAgB,OAAO,UAAU;AACvC,gBAAc,UAAU;AACxB,QAAM,oBAAoB,CAAC,CAAC;AAE5B,QAAM,wBAAwB,OAAO,kBAAkB;AACvD,wBAAsB,UAAU;AAEhC,QAAM,uBAAuB,OAAO,iBAAiB;AACrD,uBAAqB,UAAU;AAE/B,QAAM,cAAc,OAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,QAAM,eAAe,OAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,uBAAuB,OAAO,iBAAiB;AACrD,uBAAqB,UAAU;AAE/B,QAAM,yBAAyB,OAAO,mBAAmB;AACzD,yBAAuB,UAAU;AAEjC,QAAM,qBAAqB,OAAO,eAAe;AACjD,qBAAmB,UAAU;AAE7B,QAAM,iBAAiB,OAAO,WAAW;AACzC,iBAAe,UAAU;AAEzB,QAAM,iBAAiB,OAAO,WAAW;AACzC,iBAAe,UAAU;AAEzB,QAAM,cAAc,QAAQ,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,mBAAmB,QAAQ,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,uBAAuB,OAAO,oBAAI,IAAY,CAAC;AAErD,QAAM,gBACH,YAAoB,YACjB,aACC,YAAoB,SAAS,YAC3B,YAAoB,UACrB;AAER,QAAM,iBACH,aAAqB,YAClB,cACC,aAAqB,SAAS,YAC5B,aAAqB,UACtB;AAER,QAAM,SAAS;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,aAAa,UAAU;AAAA,UACrB,kBAAkB;AAAA,UAClB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,QACD,oBAAoB,UAAU;AAAA,UAC5B;AAAA,QACF,CAAC;AAAA,QACD;AAAA,QACA,GAAI,oBACA;AAAA,UACE,WAAW,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,SAAS,sBAAsB,OAAO;AAAA,MACtC,UAAU,CAAC,EAAE,QAAQ,GAAG,MAAM;AAC5B,cAAM,YAAY,cAAc,EAAE;AAClC,2BAAmB,UAAU,SAAS;AAEtC,YAAI,eAAe,SAAS;AAC1B,gBAAM,UAAU,qBAAqB;AACrC,qBAAW,SAAS,eAAe,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,iBAAiB,iBAAiB,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,MAAM;AAC1B,iBAAO,iBAAiB,MAAM,MAAM;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA,IAGA,CAAC,kBAAkB,aAAa,OAAO,kBAAkB,iBAAiB;AAAA,EAC5E;AAEA,YAAU,MAAM;AACd,QAAI,UAAU,CAAC,OAAO,aAAa;AACjC,aAAO,YAAY,SAAS;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,CAAC;AAGtB,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,OAAO,YAAa;AACnC,QAAI,kBAAkB,OAAO,MAAM,cAAc,MAAM,EAAG;AAC1D,UAAM,EAAE,MAAM,GAAG,IAAI,OAAO,MAAM;AAClC,WAAO,SAAS,WAAW,sBAAsB,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,YAAU,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,YAAU,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,SAAS,aAAa,uBAAyC;AAC/D;AAAA,EACE;AAAA,OAIK;AAoBA,SAASA,WAAU,UAA8B,CAAC,GAAG;AAC1D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,CAAC;AAAA,IACd,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,SAAS,qBAAqB;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,SAAO,gBAAgB;AAAA,IACrB,YAAY;AAAA,IACZ,GAAG;AAAA,EACL,CAAC;AACH;;;AC9CA,SAAS,UAAU,aAAAC,YAAW,aAAa,UAAAC,eAAc;AA8BlD,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AACF,GAAwD;AACtD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAwB,IAAI;AAEhE,QAAM,gBAAgBA,QAAO,UAAU;AACvC,gBAAc,UAAU;AAExB,QAAM,eAAeA,QAAO,SAAS;AACrC,eAAa,UAAU;AAGvB,EAAAD,WAAU,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,EAAAA,WAAU,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,eAAe,YAAY,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,cAAc,YAAY,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,SAAS,YAAAE,WAAU,eAAAC,cAAa,UAAAC,eAAc;AA6BvC,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,UAAU;AAAA,EACV;AACF,GAAkD;AAChD,QAAM,CAAC,aAAa,cAAc,IAAIF,UAAS,KAAK;AAEpD,QAAM,eAAeE,QAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,iBAAiBD,aAAY,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,iBAAiBA,aAAY,MAAM;AACvC,mBAAe,KAAK;AACpB,iBAAa,UAAU;AAAA,EACzB,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgBA,aAAY,MAAM;AACtC,mBAAe,KAAK;AAAA,EACtB,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgBA;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,SAAS,sBAAsB,UAAAE,SAAQ,eAAAC,cAAa,WAAAC,gBAAe;AACnE;AAAA,EACE;AAAA,EAMA;AAAA,OAEK;AA4BA,SAAS,WACd,kBACkB;AAGlB,QAAM,gBAAgBF,QAA8B,IAAI;AACxD,MAAI;AACJ,MAAI,4BAA4B,gBAAgB;AAC9C,cAAU;AAAA,EACZ,OAAO;AACL,kBAAc,YAAY,qBAAqB,gBAAgB;AAC/D,cAAU,cAAc;AAAA,EAC1B;AAEA,QAAM,QAAQ;AAAA,IACZC;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,UAAUC,SAAQ,MAAM,QAAQ,WAAW,GAAG,CAAC,SAAS,KAAK,CAAC;AAEpE,QAAM,OAAOD,aAAY,MAAM,QAAQ,KAAK,GAAG,CAAC,OAAO,CAAC;AACxD,QAAM,OAAOA,aAAY,MAAM,QAAQ,KAAK,GAAG,CAAC,OAAO,CAAC;AACxD,QAAM,QAAQA,aAAY,MAAM,QAAQ,MAAM,GAAG,CAAC,OAAO,CAAC;AAC1D,QAAM,UAAUA;AAAA,IACd,CAAC,QAAiB,QAAQ,QAAQ,GAAG;AAAA,IACrC,CAAC,OAAO;AAAA,EACV;AACA,QAAM,gBAAgBA;AAAA,IACpB,CAAC,KAAc,SACb,QAAQ,cAAc,KAAK,IAAI;AAAA,IACjC,CAAC,OAAO;AAAA,EACV;AACA,QAAM,QAAQA;AAAA,IACZ,CAAC,MAAc,OAAmB,QAAQ,MAAM,MAAM,EAAE;AAAA,IACxD,CAAC,OAAO;AAAA,EACV;AACA,QAAM,OAAOA,aAAY,CAAC,UAAkB,QAAQ,KAAK,KAAK,GAAG,CAAC,OAAO,CAAC;AAC1E,QAAM,OAAOA,aAAY,MAAM,QAAQ,KAAK,GAAG,CAAC,OAAO,CAAC;AACxD,QAAM,WAAWA;AAAA,IACf,CAAC,MAAmB,QAAQ,SAAS,CAAC;AAAA,IACtC,CAAC,OAAO;AAAA,EACV;AACA,QAAM,eAAeA;AAAA,IACnB,CAAC,QAAgB,QAAQ,aAAa,GAAG;AAAA,IACzC,CAAC,OAAO;AAAA,EACV;AACA,QAAM,aAAaA,aAAY,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,SAAS,eAAAE,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,WAAU,wBAAAC,6BAA4B;AAC/E;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AA6BA,SAAS,gBACd,SAC0B;AAC1B,QAAM,cAAcF,QAAO,QAAQ,QAAQ;AAC3C,cAAY,UAAU,QAAQ;AAE9B,QAAM,CAAC,OAAO,IAAIC;AAAA,IAChB,MACE,QAAQ,WACR,IAAI,aAAgB,QAAQ,SAAS,GAAG;AAAA,MACtC,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAAA,EACL;AAEA,QAAM,aAAaD,QAAsC,IAAI;AAC7D,EAAAD,WAAU,MAAM;AACd,UAAM,UAAU,mBAAsB;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,UAAUG;AAAA,IACdJ,aAAY,CAAC,aAAa,QAAQ,UAAU,QAAQ,GAAG,CAAC,OAAO,CAAC;AAAA,IAChE,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,EAChB;AAEA,QAAM,YAAYA;AAAA,IAChB,MAAM,QAAQ,UAAU,YAAY,QAAQ,CAAC;AAAA,IAC7C,CAAC,OAAO;AAAA,EACV;AACA,QAAM,WAAWA;AAAA,IACf,CAAK,OACH,WAAW,UAAU,WAAW,QAAQ,SAAS,EAAE,IAAI,QAAQ,SAAS,EAAE;AAAA,IAC5E,CAAC,OAAO;AAAA,EACV;AACA,QAAM,UAAUA;AAAA,IACd,MAAM,QAAQ,OAAO,YAAY,QAAQ,CAAC;AAAA,IAC1C,CAAC,OAAO;AAAA,EACV;AAEA,SAAO,EAAE,SAAS,WAAW,UAAU,SAAS,QAAQ;AAC1D;;;ACtFA,SAAS,aAAAK,kBAAiB;AAE1B,SAAS,4BAA4B;AAsB9B,SAAS,oBACd,SACA,UAAmC,CAAC,GAC9B;AACN,QAAM;AAAA,IACJ,UAAU;AAAA,IACV;AAAA,IACA,yBAAyB;AAAA,EAC3B,IAAI;AAEJ,EAAAA,WAAU,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,SAAS,qBAAqB,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,SAAS,aAAAC,YAAW,WAAAC,UAAS,UAAAC,SAAQ,wBAAAC,6BAA4B;AAEjE;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAuBA,SAAS,cACd,QACA,UAAuC,CAAC,GACnB;AACrB,QAAM,YAAYD,QAAO,MAAM;AAC/B,YAAU,UAAU;AAEpB,QAAM,aAAaD;AAAA,IACjB,MACE,IAAI,qBAAqB,MAAM;AAC7B,YAAM,UAAU,UAAU;AAC1B,aAAO,WAAW,CAAC,QAAQ,cAAc,UAAU;AAAA,IACrD,GAAG,OAAO;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,EAAAD,WAAU,MAAM;AACd,eAAW,WAAW,OAAO;AAAA,EAC/B,CAAC;AAED,QAAM,QAAQG,sBAAqB,WAAW,WAAW,WAAW,UAAU,WAAW,QAAQ;AACjG,QAAM,mBAAmBF,SAAQ,MAAM,yBAAyB,MAAM,YAAY,GAAG,CAAC,MAAM,YAAY,CAAC;AAEzG,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,QAAQ,WAAW;AAAA,IACnB,gBAAgB,WAAW;AAAA,IAC3B,aAAa,WAAW;AAAA,EAC1B;AACF;;;AC7DA,SAAS,aAAAG,YAAW,WAAAC,UAAS,UAAAC,SAAQ,wBAAAC,6BAA4B;AAEjE;AAAA,EACE;AAAA,OAIK;AAcA,SAAS,cACd,QACA,UAAuC,CAAC,GACnB;AACrB,QAAM,YAAYD,QAAO,MAAM;AAC/B,YAAU,UAAU;AAEpB,QAAM,aAAaD;AAAA,IACjB,MACE,IAAI,qBAAqB,MAAM;AAC7B,YAAM,UAAU,UAAU;AAC1B,aAAO,WAAW,CAAC,QAAQ,cAAc,UAAU;AAAA,IACrD,GAAG,OAAO;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,EAAAD,WAAU,MAAM;AACd,eAAW,WAAW,OAAO;AAAA,EAC/B,CAAC;AAED,QAAM,QAAQG,sBAAqB,WAAW,WAAW,WAAW,UAAU,WAAW,QAAQ;AACjG,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU,CAAC,aAAsB,WAAW,SAAS,QAAQ;AAAA,IAC7D,YAAY,MAAM,WAAW,WAAW;AAAA,EAC1C;AACF;;;ACxBI;AATG,IAAM,mBAAoD,CAAC;AAAA,EAChE;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX;AAAA,EACA,GAAG;AACL,MAAM;AACJ,QAAM,OAAO,cAAc,QAAQ,OAAO;AAC1C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA,UAAU,CAAC,UAAU,KAAK;AAAA,MAC1B,aAAW,KAAK,eAAe;AAAA,MAC/B,OAAO,KAAK,QAAQ,kBAAkB,KAAK,MAAM,OAAO,KAAK;AAAA,MAC7D,SAAS,YAAY;AACnB,cAAM,SAAS,MAAM,KAAK,SAAS;AACnC,YAAI,OAAQ,cAAa,MAAM;AAAA,MACjC;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;;;ACrCA,SAAS,aAAAC,kBAAiB;AAYnB,SAAS,qBACd,UACA,UACM;AACN,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,SAAU;AAC5B,WAAO,SAAS,SAAS,QAAQ;AAAA,EACnC,GAAG,CAAC,UAAU,QAAQ,CAAC;AACzB;;;ACpBA,SAAS,aAAAC,YAAW,YAAAC,iBAAgB;AACpC,SAAS,yBAA6H;AAe/H,SAAS,cAAc,UAA2C,SAA+D;AACtI,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAA8B,EAAE,QAAQ,OAAO,UAAU,KAAK,CAAC;AACzF,QAAM,MAAM,UAAU,KAAK,UAAU,CAAC,QAAQ,KAAK,QAAQ,OAAO,QAAQ,MAAM,QAAQ,MAAM,QAAQ,SAAS,CAAC,IAAI;AACpH,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,SAAS;AACzB,eAAS,EAAE,QAAQ,OAAO,UAAU,KAAK,CAAC;AAC1C;AAAA,IACF;AACA,QAAI;AACJ,iBAAa,kBAAkB,UAAU;AAAA,MACvC,GAAG;AAAA,MACH,UAAU,CAAC,QAAQ,WAAW;AAC5B,iBAAS,EAAE,QAAQ,QAAQ,UAAU,YAAY,YAAY,KAAK,CAAC;AACnE,gBAAQ,WAAW,QAAQ,MAAM;AAAA,MACnC;AAAA,IACF,CAAC;AACD,aAAS,EAAE,QAAQ,WAAW,QAAQ,UAAU,KAAK,CAAC;AACtD,WAAO,MAAM,YAAY,MAAM;AAAA,EAEjC,GAAG,CAAC,UAAU,GAAG,CAAC;AAClB,SAAO;AACT;;;ACpCA;AAAA,EACE,iBAAiB;AAAA,OAEZ;AAaD,gBAAAE,YAAA;AAPC,IAAM,gBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,SACE,gBAAAA,KAAC,SAAI,WACH,0BAAAA,KAAC,uBAAoB,QAAiB,GAAG,OAAO,GAClD;AAEJ;;;ACpBA,SAAgB,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AACnD,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,OAEK;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,SAASD,QAA8B,IAAI;AACjD,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAS,KAAK;AAE5C,MAAI,CAAC,OAAO,WAAW,OAAO,aAAa,aAAa;AACtD,WAAO,UAAU,SAAS,cAAc,KAAK;AAAA,EAC/C;AAEA,EAAAF,WAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,OAAO,WAAW,OAAO,aAAa;AACpD;AAAA,IACF;AAEA,UAAM,UAAU,OAAO;AACvB,YAAQ,YAAY;AAEpB,UAAM,SAAS,iBAAiB;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,SAAO,aAAa,UAAU,OAAO,OAAO;AAC9C;;;ACpEA,SAAgB,WAAAG,gBAAe;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AA6DK,gBAAAC,MA2CA,YA3CA;AAlCL,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,cAAcD,SAAQ,MAAM;AAChC,QAAI,CAAC,WAAW,UAAU,WAAW,EAAG,QAAO;AAC/C,WAAO,iBAAiB,SAAS,WAAW,EAAE,SAAS,CAAC;AAAA,EAC1D,GAAG,CAAC,SAAS,WAAW,SAAS,QAAQ,CAAC;AAE1C,QAAM,SAASA,SAAQ,MAAM;AAC3B,WAAO,qBAAqB,aAAa,MAAM;AAAA,EACjD,GAAG,CAAC,aAAa,MAAM,CAAC;AAExB,SACE,gBAAAC,KAAC,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,gBAAAA;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,gBAAAA;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,gBAAAA,KAAC,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,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,oBAAkB,MAAM;AAAA,UACxB,WAAU;AAAA,UACV,OAAO,uBAAuB,KAAK;AAAA,UAElC,+BAAqB,KAAK;AAAA;AAAA,QALtB;AAAA,MAMP;AAAA,IAEJ;AAEA,QAAI,MAAM,SAAS,eAAe;AAChC,aACE,gBAAAA;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,gBAAAA,KAAC,UAAkB,gBAAM,SAAd,KAAoB;AAAA,EACxC,CAAC,GACH;AAEJ;;;AC9JA,SAAgB,OAAO,WAAAC,UAAS,YAAAC,iBAAgB;AAChD;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AA6DK,SAME,OAAAC,MANF,QAAAC,aAAA;AAlCL,IAAM,eAA4C,CAAC;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AACd,MAAM;AACJ,QAAM,WAAW,MAAM;AACvB,QAAM,CAAC,UAAU,WAAW,IAAIF;AAAA,IAC9B,MAAM,iBAAiB,CAAC;AAAA,EAC1B;AACA,QAAM,UAAU,UAAU;AAE1B,QAAM,SAASD;AAAA,IACb,MAAM,sBAAsB,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,eAAW,sBAAsB,IAAI,GAAG,IAAI;AAAA,EAC9C;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SACE,gBAAAE,KAAC,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,gBAAAC;AAAA,QAAC;AAAA;AAAA,UAEC,SAAS;AAAA,UACT,WAAU;AAAA,UACV,uBAAqB,MAAM;AAAA,UAE3B;AAAA,4BAAAD;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,gBAAAA,KAAC,UAAM,gBAAM,OAAM;AAAA;AAAA;AAAA,QAdd,MAAM;AAAA,MAeb;AAAA,IAEJ;AACA,WACE,gBAAAC;AAAA,MAAC;AAAA;AAAA,QAEC,SAAS;AAAA,QACT,WAAU;AAAA,QACV,uBAAqB,MAAM;AAAA,QAE3B;AAAA,0BAAAA,MAAC,UAAK,WAAU,eACb;AAAA,kBAAM;AAAA,YACN,MAAM,YACL,gBAAAD,KAAC,UAAK,WAAU,iBAAgB,eAAY,QACzC,gBACH;AAAA,aAEJ;AAAA,UACA,gBAAAA;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,SAAgB,SAAAE,QAAO,YAAAC,iBAAgB;;;ACAvC,SAAS,eAAAC,cAAa,WAAAC,UAAS,YAAAC,iBAAgB;AAC/C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;AAmDA,SAAS,gBAAgB,SAAoD;AAClF,QAAM,EAAE,UAAU,WAAW,UAAU,aAAa,IAAI;AACxD,QAAM,CAAC,YAAY,kBAAkB,IAAIA,UAAS,QAAQ,iBAAiB,EAAE;AAC7E,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAwC,CAAC,CAAC;AAC5E,QAAM,CAAC,OAAO,aAAa,IAAIA,UAAS,CAAC;AACzC,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAoC,IAAI;AAEpE,QAAM,SAASD;AAAA,IACb,MAAM,gBAAgB,YAAY,YAAY;AAAA,IAC9C,CAAC,YAAY,YAAY;AAAA,EAC3B;AACA,QAAM,YAAYA;AAAA,IAChB,MAAM,iBAAiB,UAAU,EAAE,WAAW,SAAS,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IAC3E,CAAC,UAAU,WAAW,QAAQ;AAAA,EAChC;AACA,QAAM,UAAUA,SAAQ,MAAM;AAC5B,UAAM,SAAwC;AAAA,MAC5C,GAAG,YAAY,WAAW,OAAO,MAAM,EAAE;AAAA,IAC3C;AACA,eAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACzD,UAAI,UAAU,SAAS,QAAQ,MAAM,UAAU,QAAQ,OAAO,OAAO,SAAS,KAAK,IAAI;AACrF,eAAO,QAAQ,IAAI;AAAA,MACrB;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,WAAW,OAAO,QAAQ,SAAS,CAAC;AAExC,QAAM,QAAQ,OAAO,QAAQ;AAC7B,QAAM,UAAU,UAAU,IAAI,IAAI,KAAK,IAAI,OAAO,QAAQ,CAAC;AAC3D,QAAM,SAAS,OAAO,QAAQ,OAAO;AACrC,QAAM,SAASA;AAAA,IACb,MAAO,SAAS,eAAe,QAAQ,OAAO,IAAI,CAAC;AAAA,IACnD,CAAC,QAAQ,OAAO;AAAA,EAClB;AAEA,QAAM,gBAAgBD,aAAY,CAAC,SAAiB;AAClD,uBAAmB,IAAI;AACvB,kBAAc,CAAC;AACf,cAAU,IAAI;AAAA,EAChB,GAAG,CAAC,CAAC;AACL,QAAM,WAAWA;AAAA,IACf,OAAO,SAAe,cAAc,MAAM,KAAK,KAAK,CAAC;AAAA,IACrD,CAAC,aAAa;AAAA,EAChB;AACA,QAAM,WAAWA;AAAA,IACf,CAAC,SAAiB,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,QAAQ,CAAC,CAAC,CAAC;AAAA,IACtE,CAAC,KAAK;AAAA,EACR;AACA,QAAM,kBAAkBA,aAAY,CAAC,UAAkB,UAAyB;AAC9E,iBAAa,CAAC,cAAc,EAAE,GAAG,UAAU,CAAC,QAAQ,GAAG,MAAM,EAAE;AAC/D,cAAU,IAAI;AAAA,EAChB,GAAG,CAAC,CAAC;AACL,QAAM,eAAeA,aAAY,MAAM,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC;AAE3D,QAAM,QAAQA,aAAY,MAAM;AAC9B,UAAM,SAAS,aAAa,UAAU,QAAQ;AAAA,MAC5C;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB,WAAW,QAAQ;AAAA,MACnB,YAAY,QAAQ;AAAA,IACtB,CAAC;AACD,cAAU,MAAM;AAChB,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,QAAQ,WAAW,UAAU,SAAS,QAAQ,QAAQ,QAAQ,WAAW,QAAQ,UAAU,CAAC;AAE1G,QAAM,YAAYA;AAAA,IAChB,CAAC,WACC,SAAS,sBAAsB,OAAO,SAAS,QAAQ,QAAQ,SAAS,IAAI;AAAA,IAC9E,CAAC,QAAQ,QAAQ,SAAS;AAAA,EAC5B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,MAAM,MAAM,SAAS,UAAU,CAAC;AAAA,IAChC,MAAM,MAAM,SAAS,UAAU,CAAC;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ADtEM,SAkHI,UAjHF,OAAAG,MADF,QAAAC,aAAA;AAxDN,SAAS,aAAa,MAAc,UAAkB,MAAoB;AACxE,MAAI,OAAO,aAAa,eAAe,OAAO,IAAI,oBAAoB,YAAY;AAChF;AAAA,EACF;AACA,QAAM,MAAM,IAAI,gBAAgB,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,KAAK,CAAC,CAAC;AAC1D,QAAM,OAAO,SAAS,cAAc,GAAG;AACvC,OAAK,OAAO;AACZ,OAAK,WAAW;AAChB,OAAK,MAAM;AACX,aAAW,MAAM,IAAI,gBAAgB,GAAG,GAAG,CAAC;AAC9C;AAOO,IAAM,eAA4C,CAAC;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,YAAY;AACd,MAAM;AACJ,QAAM,KAAKC,OAAM;AACjB,QAAM,QAAQ,gBAAgB;AAAA,IAC5B,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAC1C,QAAM,EAAE,QAAQ,OAAO,IAAI;AAE3B,QAAM,OAAO,YAAY;AACvB,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,MAAM,UAAU,MAAM,CAAC;AAC3D,gBAAU,IAAI;AAAA,IAChB,QAAQ;AACN,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAEA,SACE,gBAAAF,MAAC,SAAI,WAAsB,sBAAmB,IAC5C;AAAA,oBAAAA,MAAC,WAAM,SAAS,GAAG,EAAE,WAAW,WAAU,uBACxC;AAAA,sBAAAD,KAAC,UAAK,WAAU,eAAc,4CAA8B;AAAA,MAC5D,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,IAAI,GAAG,EAAE;AAAA,UACT,qBAAkB;AAAA,UAClB,OAAO,MAAM;AAAA,UACb,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,UAAU,CAAC,UAAU,MAAM,cAAc,MAAM,OAAO,KAAK;AAAA,UAC3D,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IACA,gBAAAC,MAAC,SAAI,WAAU,qCACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,QAAO;AAAA,UACP,cAAW;AAAA,UACX,mBAAgB;AAAA,UAChB,UAAU,CAAC,UAAU;AACnB,kBAAM,OAAO,MAAM,OAAO,QAAQ,CAAC;AACnC,gBAAI,KAAM,MAAK,MAAM,SAAS,IAAI;AAAA,UACpC;AAAA;AAAA,MACF;AAAA,MACA,gBAAAA,KAAC,UAAK,sBAAmB,IAAG,WAAU,cACnC,aAAG,OAAO,QAAQ,MAAM,UAAU,OAAO,QAAQ,WAAW,IAAI,KAAK,GAAG,SAAM,OAAO,OAAO,MAAM,SAAS,OAAO,OAAO,WAAW,IAAI,KAAK,GAAG,IACnJ;AAAA,OACF;AAAA,IACC,OAAO,SAAS,SAAS,KAAK,MAAM,WAAW,KAAK,MAAM,MACzD,gBAAAA,KAAC,QAAG,uBAAoB,IAAG,WAAU,0BAClC,iBAAO,SAAS,IAAI,CAAC,SAAS,MAC7B,gBAAAA,KAAC,QAAY,kBAAQ,WAAZ,CAAoB,CAC9B,GACH;AAAA,IAGD,MAAM,UAAU,SAAS,KACxB,gBAAAC,MAAC,cAAS,WAAU,uBAClB;AAAA,sBAAAD,KAAC,YAAO,WAAU,eAAc,2BAAa;AAAA,MAC5C,MAAM,UAAU,IAAI,CAAC,aACpB,gBAAAC;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UACV,sBAAoB;AAAA,UAEpB;AAAA,4BAAAD,KAAC,UAAK,WAAU,sBAAsB,cAAI,QAAQ,KAAI;AAAA,YACtD,gBAAAC;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,MAAM,QAAQ,QAAQ,KAAK;AAAA,gBAClC,cAAY,aAAa,QAAQ;AAAA,gBACjC,UAAU,CAAC,UACT,MAAM,gBAAgB,UAAU,MAAM,OAAO,SAAS,IAAI;AAAA,gBAE5D,WAAU;AAAA,gBAEV;AAAA,kCAAAD,KAAC,YAAO,OAAM,IAAG,oBAAM;AAAA,kBACtB,OAAO,OAAO,IAAI,CAAC,UAClB,gBAAAA,KAAC,YAAmB,OAAO,OACxB,mBADU,KAEb,CACD;AAAA;AAAA;AAAA,YACH;AAAA;AAAA;AAAA,QAnBK;AAAA,MAoBP,CACD;AAAA,OACH;AAAA,IAGF,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,mBAAgB;AAAA,UAChB,SAAS,MAAM;AAAA,UACf,UAAU,MAAM,SAAS;AAAA,UAC1B;AAAA;AAAA,MAED;AAAA,MACA,gBAAAA,KAAC,UAAK,uBAAoB,IACvB,gBAAM,UAAU,IACb,eACA,UAAU,MAAM,QAAQ,CAAC,OAAO,MAAM,KAAK,IACjD;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,mBAAgB;AAAA,UAChB,SAAS,MAAM;AAAA,UACf,UAAU,MAAM,SAAS,MAAM,QAAQ;AAAA,UACxC;AAAA;AAAA,MAED;AAAA,OACF;AAAA,IAEA,gBAAAA,KAAC,SAAI,qBAAkB,IACrB,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,CAAC,CAAC,aAAa,UAAU,SAAS;AAAA,QAC3C,QAAQ,MAAM;AAAA;AAAA,IAChB,GACF;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAU,qCACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,kBAAe;AAAA,UACf,UAAU,MAAM,UAAU;AAAA,UAC1B,SAAS,MAAM;AACb,kBAAM,SAAS,MAAM,MAAM;AAC3B,sBAAU,KAAK;AACf,sBAAU,MAAM;AAAA,UAClB;AAAA,UACD;AAAA;AAAA,MAED;AAAA,MACC,UACC,gBAAAC,MAAA,YACE;AAAA,wBAAAD,KAAC,UAAK,qBAAkB,IACrB,aAAG,OAAO,QAAQ,MAAM,UAAU,OAAO,QAAQ,SAAS,KAAK,OAAO,QAAQ,MAAM,aAAa,EAAE,GAAG,OAAO,YAAY,qBAAqB,EAAE,IACnJ;AAAA,QACA,gBAAAA,KAAC,YAAO,MAAK,UAAS,mBAAgB,IAAG,SAAS,MAC/C,mBAAS,WAAW,QACvB;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,uBAAoB;AAAA,YACpB,SAAS,MAAM,aAAa,MAAM,UAAU,MAAM,GAAG,GAAG,YAAY,QAAQ,YAAY;AAAA,YACzF;AAAA;AAAA,QAED;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,uBAAoB;AAAA,YACpB,SAAS,MACP,aAAa,MAAM,UAAU,MAAM,GAAG,GAAG,YAAY,SAAS,kBAAkB;AAAA,YAEnF;AAAA;AAAA,QAED;AAAA,SACF;AAAA,OAEJ;AAAA,IACC,UACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,UAAQ;AAAA,QACR,cAAW;AAAA,QACX,mBAAgB;AAAA,QAChB,MAAM;AAAA,QACN,OAAO,MAAM,UAAU,MAAM;AAAA,QAC7B,WAAU;AAAA;AAAA,IACZ;AAAA,KAEJ;AAEJ;;;AEjPA,SAAS,WAAAI,UAAS,wBAAAC,6BAA4B;AAE9C,SAAS,0BAAgD;AAYlD,SAAS,WAAW,QAAoD;AAG7E,QAAM,QAAQD,SAAQ,MAAM,mBAAmB,MAAM,GAAG,CAAC,MAAM,CAAC;AAChE,SAAOC,sBAAqB,MAAM,WAAW,MAAM,aAAa,MAAM,WAAW;AACnF;;;ACjBA,SAAS,yBAA8C;AA2CnD,SACoB,OAAAC,MADpB,QAAAC,aAAA;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,gBAAAA,MAAC,SAAI,WAAsB,cAAW,oBAAmB,sBAAmB,IACzE;AAAA,aAAS,QAAQ,gBAAAD,KAAC,SAAI,WAAU,0BAA0B,iBAAM;AAAA,IAChE,QAAQ,WAAW,IAClB,gBAAAA,KAAC,SAAI,WAAU,0BAA0B,sBAAW,IAEpD,gBAAAA,KAAC,QAAG,MAAK,QAAO,OAAO,EAAE,WAAW,QAAQ,QAAQ,GAAG,SAAS,EAAE,GAC/D,kBAAQ,IAAI,CAAC,YAAY;AACxB,YAAM,SAAS,QAAQ,OAAO;AAC9B,aACE,gBAAAA,KAAC,QAAoB,cAAY,QAAQ,OACvC,0BAAAA;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,gBAAI,kBAAkB,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;;;AC7EA,SAAS,WAAAE,UAAS,wBAAAC,6BAA4B;AAE9C;AAAA,EACE;AAAA,EACA;AAAA,OAKK;AAyBA,SAAS,mBAAmB,QAA6D;AAE9F,QAAM,QAAQD,SAAQ,MAAM,2BAA2B,MAAM,GAAG,CAAC,MAAM,CAAC;AACxE,QAAM,WAAWC,sBAAqB,MAAM,WAAW,MAAM,aAAa,MAAM,WAAW;AAE3F,SAAOD,SAAQ,MAAM;AACnB,UAAM,WAAW,iBAAiB,MAAM;AACxC,UAAM,OAAO,MAAO,UAAU,CAAC,OAAO,cAAc,SAAS;AAC7D,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,cAAe,SAAS,kBAAkB,UAAU,IAAI,SAAS,cAAc,KAAM;AAAA,MACrF,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,GAAG,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,IAAI;AAAA,MACnE,OAAO,MAAM,CAAC,CAAC,KAAK,GAAG,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,IAAI;AAAA,MACjE,qBAAqB,CAAC,OAAO,CAAC,CAAC,KAAK,GAAG,MAAM,EAAE,MAAM,EAAE,kCAAkC,EAAE,EAAE,IAAI;AAAA,MACjG,qBAAqB,CAAC,MAAM,YAAY;AACtC,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,KAAK,CAAC,SAAU,QAAO;AAC5B,cAAM,KAAK,SAAS,MAAM,SAAS,MAAM,KAAK,KAAK,CAAC;AACpD,cAAM,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,kCAAkC,MAAM,EAAE,GAAG,SAAS,GAAG,CAAC,EAAE,IAAI;AAC7F,eAAO,KAAK,KAAK;AAAA,MACnB;AAAA,MACA,qBAAqB,CAAC,OAAO,CAAC,CAAC,KAAK,GAAG,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,IAAI;AAAA,IACnF;AAAA,EACF,GAAG,CAAC,UAAU,MAAM,CAAC;AACvB;;;AC3DA,SAAgB,YAAAE,iBAAgB;AAgFxB,SAwBQ,OAAAC,MAxBR,QAAAC,aAAA;AAxDR,IAAM,QAAQ,CAAC,aAAqB,SAAS,QAAQ,aAAa,CAAC,GAAG,MAAc,EAAE,YAAY,CAAC;AAEnG,IAAM,gBAAgB,CAAC,UAA4B,MAAM,eAAe;AAQjE,IAAM,gBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB;AACF,MAAM;AACJ,QAAM,SAAS,mBAAmB,MAAM;AACxC,QAAM,CAAC,MAAM,OAAO,IAAIC,UAAS,KAAK;AACtC,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAS,EAAE;AACnC,QAAM,OAAO,gBAAgB,OAAO,SAAS,OAAO;AACpD,QAAM,UAAU,OAAO;AACvB,QAAM,WAAW,YAAY,aAAa;AAC1C,QAAM,QAAQ,MAAM;AAClB,QAAI,YAAY,WAAY,SAAQ,KAAK;AACzC,gBAAY,KAAK;AACjB,YAAQ,EAAE;AAAA,EACZ;AAEA,QAAM,eAAe,CAAC,OAAgD;AACpE,QAAI,CAAC,WAAW,CAAC,OAAO,SAAU,QAAO;AACzC,WAAO,OAAO;AAAA,MACZ,OAAO,QAAQ,OAAO,SAAS,oBAAoB,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAAA,IACvF;AAAA,EACF;AAEA,QAAM,QAAQ,CAAC,OAAe;AAC5B,QAAI,OAAO,MAAM,EAAE,EAAG,YAAW,EAAE,MAAM,SAAS,GAAG,CAAC;AACtD,UAAM;AAAA,EACR;AAEA,QAAM,SAAS,CAAC,UAA2B;AACzC,UAAM,eAAe;AACrB,UAAM,KAAK,KAAK,KAAK,IAAI,OAAO,oBAAoB,IAAI,IAAI;AAC5D,QAAI,GAAI,YAAW,EAAE,MAAM,UAAU,GAAG,CAAC;AACzC,UAAM;AAAA,EACR;AAEA,SACE,gBAAAD,MAAC,SAAI,WAAsB,MAAK,SAAQ,cAAW,oBAAmB,uBAAqB,SACxF;AAAA,gBAAY,cACX,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAW;AAAA,QACX,iBAAc;AAAA,QACd,iBAAe;AAAA,QACf,UAAU,CAAC,UAAU,CAAC,OAAO;AAAA,QAC7B,aAAa;AAAA,QACb,SAAS,MAAM,QAAQ,CAAC,UAAU,CAAC,KAAK;AAAA,QAEvC;AAAA,mBAAS,QAAQ;AAAA,UAAS;AAAA;AAAA;AAAA,IAC7B;AAAA,IAED,YACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WACE,YAAY,aACR,uIACA;AAAA,QAGN;AAAA,0BAAAD,KAAC,SAAI,MAAK,WAAU,cAAW,UAAS,WAAW,YAAY,aAAa,0BAA0B,wBACnG,eAAK,IAAI,CAAC,UAAU;AACnB,kBAAM,SAAS,MAAM,OAAO,OAAO;AACnC,mBACE,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,iBAAe;AAAA,gBACf,iBAAe,MAAM;AAAA,gBACrB,WAAW,SAAS,GAAG,aAAa,IAAI,mBAAmB,KAAK;AAAA,gBAChE,OAAO,aAAa,MAAM,EAAE;AAAA,gBAC5B,aAAa;AAAA,gBACb,SAAS,MAAM,MAAM,MAAM,EAAE;AAAA,gBAE5B,gBAAM;AAAA;AAAA,cAVF,MAAM;AAAA,YAWb;AAAA,UAEJ,CAAC,GACH;AAAA,UACC,eACC,gBAAAC,MAAC,SAAI,WAAW,YAAY,aAAa,2DAA2D,2BAClG;AAAA,4BAAAD;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAW;AAAA,gBACX,UAAU,CAAC;AAAA,gBACX,aAAa;AAAA,gBACb,SAAS,MAAM;AACb,sBAAI,WAAW,OAAO,oBAAoB,QAAQ,EAAE,GAAG;AACrD,+BAAW,EAAE,MAAM,UAAU,IAAI,QAAQ,GAAG,CAAC;AAAA,kBAC/C;AACA,wBAAM;AAAA,gBACR;AAAA,gBAEC,oBAAU,UAAU,QAAQ,IAAI,wBAAwB;AAAA;AAAA,YAC3D;AAAA,YACC,WACC,gBAAAC,MAAC,UAAK,WAAU,2BAA0B,UAAU,QAClD;AAAA,8BAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,cAAW;AAAA,kBACX,WAAU;AAAA,kBACV,OAAO;AAAA,kBACP,WAAS;AAAA,kBACT,UAAU,CAAC,UAAU,QAAQ,MAAM,OAAO,KAAK;AAAA;AAAA,cACjD;AAAA,cACA,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,eAAe,UAAU,CAAC,KAAK,KAAK,GAAG,oBAExE;AAAA,eACF,IAEA,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAW;AAAA,gBACX,UAAU,CAAC,UAAU,CAAC,OAAO;AAAA,gBAC7B,aAAa;AAAA,gBACb,SAAS,MAAM,YAAY,IAAI;AAAA,gBAChC;AAAA;AAAA,YAED;AAAA,aAEJ;AAAA;AAAA;AAAA,IAEJ;AAAA,KAEJ;AAEJ;;;AC9IA;AAAA,EACE,gBAAAG;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA;AAAA,OACK;;;AChCP,SAAgB,eAAe,YAAY,WAAAC,iBAAe;AAUxD,gBAAAC,MAgBC,QAAAC,aAhBD;AAFF,IAAM,eAA+B;AAAA,EACpC,QAAQ,CAAC,UACR,gBAAAD;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,gBAAAA,KAAC,SAAI,WAAW,8BAA8B,MAAM,aAAa,EAAE,IAAI,OAAO,OAAO,MAAM,OAAO,GAChG,gBAAM,UACR;AAAA,EAED,YAAY,CAAC,UACZ,gBAAAC,MAAC,SAAI,WAAW,0DAA0D,MAAM,aAAa,EAAE,IAC9F;AAAA,oBAAAA,MAAC,SAAI,WAAU,2BACb;AAAA,YAAM;AAAA,MACP,gBAAAD,KAAC,UAAK,WAAU,iBAAiB,gBAAM,OAAM;AAAA,OAC9C;AAAA,IACC,MAAM,WACN,gBAAAA,KAAC,YAAO,MAAK,UAAS,SAAS,MAAM,SAAS,WAAU,gCAA+B,kBAEvF;AAAA,KAEF;AAEF;AAEA,IAAM,qBAAqB,cAA8B,YAAY;AAU9D,SAAS,oBAAoB,EAAE,OAAO,SAAS,GAA6B;AAClF,QAAM,cAAcD,UAAQ,OAAO,EAAE,GAAG,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;AAE1E,SACC,gBAAAC,KAAC,mBAAmB,UAAnB,EAA4B,OAAO,aAClC,UACF;AAEF;AAKO,SAAS,iBAAiC;AAChD,SAAO,WAAW,kBAAkB;AACrC;;;AChEA,SAAS,eAAAE,cAAa,WAAAC,WAAS,wBAAAC,6BAA4B;AAE3D;AAAA,EACE;AAAA,EACA;AAAA,OAKK;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,SAAS,gBAAgB,MAAuB;AACvF,QAAM,YAAYF;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,WAAWE,sBAAqB,WAAW,aAAa,WAAW;AACzE,SAAOD,UAAQ,OAAO,EAAE,GAAG,UAAU,MAAM,IAAI,CAAC,UAAU,KAAK,CAAC;AAClE;AAwBO,SAAS,gBAAgB,QAA0D;AACxF,QAAM,QAAQ,qBAAqB,UAAU,IAAI;AACjD,QAAM,YAAYD;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,WAAWE,sBAAqB,WAAW,aAAa,WAAW;AAEzE,SAAOD,UAAQ,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,MACnE,QAAQ,CAAC,OAAe,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,IAAI,CAAC,EAAE;AAAA,MAC7E,YAAY,CAAC,OAAe,IAAI,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC,EAAE;AAAA,MAClE,YAAY,CAAC,OAAe,IAAI,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC,EAAE;AAAA,IACpE;AAAA,EACF,GAAG,CAAC,UAAU,MAAM,CAAC;AACvB;;;AC1GA,SAAgB,YAAAE,kBAAgB;AAEhC;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AA+CC,SAKE,OAAAC,MALF,QAAAC,aAAA;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,MAAM,iBAAiB,CAAC;AAAA,EACtC,eAAe;AACjB,MAAM;AACJ,QAAM,EAAE,SAAS,gBAAgB,MAAM,IAAI,YAAY,aAAa,MAAM;AAC1E,QAAM,CAAC,cAAc,eAAe,IAAIC,WAAS,mBAAmB;AACpE,QAAM,SAAS,cAAc,iBAAiB,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,gBAAAD,MAAC,WAAM,WAAsB,cAAW,YACtC;AAAA,oBAAAA,MAAC,SAAI,WAAU,2CACb;AAAA,sBAAAA,MAAC,UAAK,WAAU,6CACb;AAAA,gBAAQ,SAAS;AAAA,QAAc;AAAA,QAC/B,gBAAgB,IAAI,SAAM,aAAa,cAAc;AAAA,SACxD;AAAA,MACC,gBAAgB,KACf,gBAAAD;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,gBAAAA,KAAC,OAAE,WAAU,iCAAiC,wBAAa,IAE3D,gBAAAA,KAAC,QAAG,WAAU,uBAAsB,MAAK,QACtC,kBAAQ,IAAI,CAAC,WACZ,gBAAAA;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,IAAIE,WAAS,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,gBAAAD;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,wBAAAA,MAAC,SAAI,WAAU,6CACb;AAAA,0BAAAD,KAAC,UAAK,WAAU,eAAe,iBAAO,OAAO,MAAK;AAAA,UAClD,gBAAAA,KAAC,UAAK,WAAU,iCAAiC,qBAAW,OAAO,SAAS,GAAE;AAAA,WAChF;AAAA,QACC,SACC,gBAAAA,KAAC,gBAAW,WAAU,4EACnB,iBACH;AAAA,QAED,OAAO,YACN,gBAAAA,KAAC,UAAK,WAAU,4BAA2B,6CAA+B;AAAA,QAE3E,OAAO,YAAY,gBAAAA,KAAC,UAAK,WAAU,iCAAgC,sBAAQ;AAAA,QAC3E,CAAC,WAAW,gBAAAA,KAAC,OAAE,WAAU,mCAAmC,iBAAO,MAAK;AAAA,QACxE,OAAO,QAAQ,SAAS,KACvB,gBAAAA,KAAC,QAAG,WAAU,mDAAkD,MAAK,QAClE,iBAAO,QAAQ,IAAI,CAAC,UACnB,gBAAAC,MAAC,QAAkB,WAAU,yBAAwB,iBAAe,MAAM,IACxE;AAAA,0BAAAA,MAAC,UAAK,WAAU,WACd;AAAA,4BAAAD,KAAC,UAAK,WAAU,eAAe,gBAAM,OAAO,MAAK;AAAA,YAAQ;AAAA,YACzD,gBAAAA,KAAC,UAAK,WAAU,yBAAyB,qBAAW,MAAM,SAAS,GAAE;AAAA,aACvE;AAAA,UACA,gBAAAA,KAAC,OAAE,WAAU,mCAAmC,gBAAM,MAAK;AAAA,aALpD,MAAM,EAMf,CACD,GACH;AAAA,SAEA,UAAU,YAAY,CAAC,OAAO,YAC9B,gBAAAC,MAAC,SAAI,WAAU,uBAAsB,SAAS,MAC5C;AAAA,0BAAAD;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,gBAAAC,MAAC,SAAI,WAAU,0BACZ;AAAA,uBACC,gBAAAD,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,SAAS,QAAQ,oBAE/D;AAAA,YAEF,gBAAAA;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,gBAAAC,MAAC,SAAI,WAAU,0BAAyB,SAAS,MAC/C;AAAA,0BAAAD,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,SAAS,MAAM,YAAY,CAAC,OAAO,QAAQ,GACtF,iBAAO,WAAW,WAAW,WAChC;AAAA,UACA,gBAAAA;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,gBAAAG,OAgCE,QAAAC,aAhCF;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,gBAAAD,MAAC,SAAI,WAAsB,MAAK,WAAU,cAAW,UACnD;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAW,GAAGE,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,gBAAAF,MAAC,UAAK,WAAU,2BAA0B,eAAY,QAAO;AAAA,IAC7D,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWE;AAAA,QACX,cAAW;AAAA,QACX,UAAU,UAAU;AAAA,QACpB,SAAS,OAAO;AAAA,QACjB;AAAA;AAAA,IAED;AAAA,IACA,gBAAAF,MAAC,UAAK,WAAU,0DAAyD,aAAU,UAChF,oBAAU,IAAI,eAAe,UAAU,GAAG,KAAK,OAAO,KAAK,KAAK,GAAG,KAAK,YAC3E;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWE;AAAA,QACX,cAAW;AAAA,QACX,UAAU,UAAU;AAAA,QACpB,SAAS,OAAO;AAAA,QACjB;AAAA;AAAA,IAED;AAAA,IACC,mBAAmB,WAClB,gBAAAD;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,gBAAAD,MAAC,UAAK,WAAU,2BAA0B,eAAY,QAAO;AAAA,IAC7D,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWE;AAAA,QACX,UAAU,CAAC;AAAA,QACX,SAAS,MAAM,WAAW,OAAO,OAAO,QAAQ,EAAE;AAAA,QACnD;AAAA;AAAA,IAED;AAAA,IACA,gBAAAF;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWE;AAAA,QACX,UAAU,CAAC;AAAA,QACX,SAAS,MAAM,WAAW,OAAO,OAAO,QAAQ,EAAE;AAAA,QACnD;AAAA;AAAA,IAED;AAAA,IACA,gBAAAF,MAAC,YAAO,MAAK,UAAS,WAAWE,cAAa,UAAU,UAAU,GAAG,SAAS,OAAO,WAAW,wBAEhG;AAAA,IACA,gBAAAF,MAAC,YAAO,MAAK,UAAS,WAAWE,cAAa,UAAU,UAAU,GAAG,SAAS,OAAO,WAAW,wBAEhG;AAAA,KACF;AAEJ;;;ACxFE,gBAAAC,aAAA;AALK,IAAM,gBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AACb,MACE,gBAAAA;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,SAAS,eAAAC,cAAa,WAAAC,WAAS,UAAAC,SAAQ,YAAAC,kBAAgB;AAEvD;AAAA,EACE;AAAA,OAIK;AAyBA,SAAS,mBACd,QACA,SAC0B;AAC1B,QAAM,CAAC,SAAS,UAAU,IAAIA,WAAgC,IAAI;AAClE,QAAM,WAAWD,QAAO,OAAO;AAC/B,WAAS,UAAU;AACnB,QAAM,UAAUF;AAAA,IACd,CAAC,UAAyB,SAAwB,cAAqC;AACrF,UAAI,CAAC,UAAU,OAAO,YAAa,QAAO;AAC1C,YAAM,SAAS,wBAAwB,QAAQ,UAAU,SAAS;AAAA,QAChE,GAAG,SAAS;AAAA,QACZ,GAAG;AAAA,MACL,CAAC;AACD,iBAAW,OAAO,OAAO;AACzB,aAAO,OAAO;AAAA,IAChB;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AACA,QAAM,QAAQA,aAAY,MAAM,WAAW,IAAI,GAAG,CAAC,CAAC;AACpD,SAAOC,UAAQ,OAAO,EAAE,SAAS,SAAS,MAAM,IAAI,CAAC,SAAS,SAAS,KAAK,CAAC;AAC/E;;;ACnDA,SAAS,0BAA0B;AAkC3B,gBAAAG,OAgBI,QAAAC,aAhBJ;AAtBR,IAAMC,eACJ;AASK,IAAM,qBAAwD,CAAC;AAAA,EACpE;AAAA,EACA,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,aAAa;AACf,MAAM;AACJ,QAAM,SAAS,gBAAgB,MAAM;AAErC,MAAI,OAAO,QAAQ,WAAW,GAAG;AAC/B,WACE,gBAAAF,MAAC,SAAI,WAAsB,6BAA0B,IACnD,0BAAAA,MAAC,SAAI,WAAU,wDAAwD,sBAAW,GACpF;AAAA,EAEJ;AAEA,SACE,gBAAAA,MAAC,QAAG,WAAsB,MAAK,QAAO,cAAW,mBAAkB,6BAA0B,IAC1F,iBAAO,QAAQ,IAAI,CAAC,WAAW;AAC9B,UAAM,SAAS,OAAO,OAAO,OAAO;AACpC,WACE,gBAAAC;AAAA,MAAC;AAAA;AAAA,QAEC,WAAW,SAAS,GAAG,aAAa,IAAI,mBAAmB,KAAK;AAAA,QAChE,oBAAkB,OAAO;AAAA,QACzB,kBAAgB,OAAO;AAAA,QAEvB;AAAA,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,OAAO,GAAG,OAAO,OAAO,IAAI,KAAK,OAAO,WAAW;AAAA,cACnD,SAAS,MAAM,OAAO,OAAO,OAAO,EAAE;AAAA,cAEtC;AAAA,gCAAAD,MAAC,UAAK,WAAU,eAAe,6BAAmB,MAAM,GAAE;AAAA,gBACzD,OAAO,OAAO,OAAO,SAAM,OAAO,OAAO,IAAI,KAAK;AAAA,gBACnD,gBAAAA,MAAC,UAAK,WAAU,wCAAwC,iBAAO,aAAY;AAAA;AAAA;AAAA,UAC7E;AAAA,UACA,gBAAAA,MAAC,YAAO,MAAK,UAAS,WAAWE,cAAa,SAAS,MAAM,OAAO,OAAO,OAAO,EAAE,GAAG,oBAEvF;AAAA,UACA,gBAAAF,MAAC,YAAO,MAAK,UAAS,WAAWE,cAAa,SAAS,MAAM,OAAO,OAAO,OAAO,EAAE,GAAG,oBAEvF;AAAA;AAAA;AAAA,MApBK,GAAG,OAAO,IAAI,IAAI,OAAO,EAAE;AAAA,IAqBlC;AAAA,EAEJ,CAAC,GACH;AAEJ;;;ACzEA,SAAS,eAAAC,cAAa,WAAAC,WAAS,wBAAAC,6BAA4B;AAE3D;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAoBP,IAAMC,mBAAkB,MAAM;AAAC;AAMxB,SAAS,eAAe,QAAyD;AACtF,QAAM,QAAQ,oBAAoB,UAAU,IAAI;AAChD,QAAM,YAAYH;AAAA,IAChB,CAAC,aAA0B,QAAQ,MAAM,UAAU,MAAM,SAAS,CAAC,IAAIG;AAAA,IACvE,CAAC,KAAK;AAAA,EACR;AACA,QAAM,cAAc,MAAM,OAAO,YAAY,KAAK;AAClD,QAAM,WAAWD,sBAAqB,WAAW,aAAa,WAAW;AAEzE,SAAOD,UAAQ,MAAM;AACnB,UAAM,MAAM,CAAC,OAA4B;AACvC,UAAI,UAAU,CAAC,OAAO,eAAe,MAAO,IAAG,MAAM;AAAA,IACvD;AACA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,WAAW,CAAC,CAAC;AAAA,MACb,YAAY,SAAS,QAAQ;AAAA,MAC7B,MAAM,CAAC,OAAwB,WAC7B,IAAI,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,KAAK,CAAC,CAAC;AAAA,MACjD,OAAO,MAAM,IAAI,CAAC,MAAM,EAAE,SAAS,iBAAiB,CAAC;AAAA,MACrD,UAAU,CAAC,UAAkB,IAAI,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,MAAM,CAAC,CAAC;AAAA,MACvE,gBAAgB,CAAC,gBAAwB,IAAI,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,YAAY,CAAC,CAAC;AAAA,MACzF,YAAY,CAAC,YAAkC,IAAI,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,QAAQ,CAAC,CAAC;AAAA,MAC3F,cAAc,CAAC,WACb,IAAI,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS,EAAE,CAAC,MAAM,GAAG,CAAC,SAAS,QAAQ,MAAM,EAAE,EAAE,CAAC,CAAC;AAAA,MACvF,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,SAAS,SAAS,CAAC;AAAA,MAC5C,UAAU,MAAM,IAAI,CAAC,MAAM,EAAE,SAAS,aAAa,CAAC;AAAA,MACpD,SAAS,MAAM,IAAI,CAAC,MAAM,EAAE,SAAS,eAAe,CAAC;AAAA,MACrD,YAAY,MAAM,IAAI,CAAC,MAAM,EAAE,SAAS,WAAW,CAAC;AAAA,MACpD,OAAO,MAAM,IAAI,CAAC,MAAM,EAAE,SAAS,YAAY,CAAC;AAAA,IAClD;AAAA,EACF,GAAG,CAAC,UAAU,QAAQ,KAAK,CAAC;AAC9B;;;AClEA,SAAgB,aAAAG,aAAW,UAAAC,UAAQ,YAAAC,kBAAgB;AAEnD,SAAS,qBAAqB,wBAAwB;AAyFhD,SACE,OAAAC,OADF,QAAAC,cAAA;AA3EN,IAAM,aACJ;AACF,IAAMC,eACJ;AACF,IAAM,cAAc,CAAC,OACnB,GAAGA,YAAW,cAAc,KAAK,+BAA+B,uBAAuB;AAEzF,IAAM,QAAQ,CAAC,MAA2B,EAAE,WAAW,EAAE;AAQlD,IAAM,iBAAgD,CAAC;AAAA,EAC5D;AAAA,EACA,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB;AACF,MAAM;AACJ,QAAM,OAAO,eAAe,MAAM;AAClC,QAAM,YAAYC,SAAyB,IAAI;AAC/C,QAAM,CAAC,UAAU,WAAW,IAAIC,WAAS,KAAK;AAC9C,QAAM,UAAU,KAAK,cAAc,cAAc,KAAK;AAGtD,EAAAC,YAAU,MAAM;AACd,QAAI,CAAC,WAAW,KAAK,iBAAiB,EAAG;AACzC,cAAU,SAAS,MAAM;AACzB,cAAU,SAAS,OAAO;AAAA,EAC5B,GAAG,CAAC,SAAS,KAAK,YAAY,CAAC;AAE/B,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,cAAc,KAAK,SAAS;AAClC,QAAM,SAAS,iBAAiB,IAAI;AACpC,QAAM,aAAa,KAAK,aAAa;AAErC,QAAM,QAAQ,MAAM;AAClB,SAAK,MAAM;AACX,YAAQ,SAAS,MAAM;AACvB,cAAU;AAAA,EACZ;AAEA,QAAM,eAAe,CAAC,MAA2B;AAC/C,QAAI,EAAE,QAAQ,UAAU;AACtB,QAAE,eAAe;AACjB,YAAM;AAAA,IACR,WAAW,MAAM,CAAC,MAAM,EAAE,QAAQ,OAAO,EAAE,QAAQ,MAAM;AACvD,QAAE,eAAe;AACjB,WAAK,KAAK,MAAM;AAAA,IAClB,WAAW,MAAM,CAAC,MAAM,EAAE,QAAQ,OAAO,EAAE,QAAQ,MAAM;AACvD,QAAE,eAAe;AACjB,WAAK,KAAK,SAAS;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,MAA2B;AAChD,QAAI,EAAE,QAAQ,QAAS;AACvB,MAAE,eAAe;AACjB,QAAI,EAAE,SAAU,MAAK,SAAS;AAAA,QACzB,MAAK,KAAK;AAAA,EACjB;AAEA,QAAM,mBAAmB,CAAC,MAA2B;AACnD,QAAI,EAAE,QAAQ,QAAS;AACvB,MAAE,eAAe;AACjB,QAAI,MAAM,CAAC,EAAG,MAAK,WAAW;AAAA,QACzB,MAAK,QAAQ;AAAA,EACpB;AAEA,SACE,gBAAAJ,OAAC,SAAI,WAAsB,MAAK,UAAS,cAAW,oBAAmB,WAAW,cAChF;AAAA,oBAAAA,OAAC,SAAI,WAAU,2BACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAWE;AAAA,UACX,cAAW;AAAA,UACX,iBAAe;AAAA,UACf,SAAS,MAAM,KAAK,KAAK,cAAc,SAAS,SAAS;AAAA,UAExD,wBAAc,WAAM;AAAA;AAAA,MACvB;AAAA,MACA,gBAAAF;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,WAAW;AAAA,UACX,aAAY;AAAA,UACZ,cAAW;AAAA,UACX,gBAAc,CAAC,CAAC,KAAK;AAAA,UACrB,OAAO,KAAK;AAAA,UACZ,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,OAAO,KAAK;AAAA,UAC7C,WAAW;AAAA;AAAA,MACb;AAAA,MACC,oBAAoB,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,MACnD,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,WAAW,YAAY,CAAC,CAAC,KAAK,QAAQ,EAAE,GAAG,CAAC;AAAA,UAC5C,cAAY,EAAE;AAAA,UACd,OAAO,EAAE;AAAA,UACT,gBAAc,CAAC,CAAC,KAAK,QAAQ,EAAE,GAAG;AAAA,UAClC,SAAS,MAAM,KAAK,aAAa,EAAE,GAAG;AAAA,UAErC,YAAE;AAAA;AAAA,QARE,EAAE;AAAA,MAST,CACD;AAAA,MACD,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,yCAAyC,KAAK,QAAQ,qBAAqB,uBAAuB;AAAA,UAC7G,aAAU;AAAA,UACV,MAAM,KAAK,QAAQ,UAAU;AAAA,UAC7B,eAAY;AAAA,UAEX;AAAA;AAAA,MACH;AAAA,MACA,gBAAAA,MAAC,YAAO,MAAK,UAAS,WAAWE,cAAa,cAAW,kBAAiB,UAAU,CAAC,YAAY,SAAS,KAAK,UAAU,oBAEzH;AAAA,MACA,gBAAAF,MAAC,YAAO,MAAK,UAAS,WAAWE,cAAa,cAAW,cAAa,UAAU,CAAC,YAAY,SAAS,KAAK,MAAM,oBAEjH;AAAA,MACC,mBACC,gBAAAF;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAWE;AAAA,UACX,cAAW;AAAA,UACX,iBAAe;AAAA,UACf,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,UACrC;AAAA;AAAA,MAED;AAAA,MAEF,gBAAAF,MAAC,YAAO,MAAK,UAAS,WAAWE,cAAa,cAAW,cAAa,SAAS,OAAO,kBAEtF;AAAA,OACF;AAAA,IACC,eACC,gBAAAD,OAAC,SAAI,WAAU,gCACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW;AAAA,UACX,aAAY;AAAA,UACZ,cAAW;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,UAAU,CAAC,MAAM,KAAK,eAAe,EAAE,OAAO,KAAK;AAAA,UACnD,WAAW;AAAA;AAAA,MACb;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAWE;AAAA,UACX,UAAU,CAAC,cAAc,KAAK,eAAe;AAAA,UAC7C,SAAS,KAAK;AAAA,UACf;AAAA;AAAA,MAED;AAAA,MACA,gBAAAF,MAAC,YAAO,MAAK,UAAS,WAAWE,cAAa,UAAU,CAAC,YAAY,SAAS,KAAK,YAAY,yBAE/F;AAAA,MACC,KAAK,qBAAqB,QACzB,gBAAAF,MAAC,UAAK,WAAU,sCAAqC,aAAU,UAC5D,eAAK,qBAAqB,IAAI,eAAe,GAAG,KAAK,gBAAgB,aACxE;AAAA,OAEJ;AAAA,IAED,mBAAmB,YAClB,gBAAAA,MAAC,SAAI,WAAU,kFACZ,8BAAoB,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,MAClD,gBAAAC,OAAC,WAAkB,WAAU,2BAC3B;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,CAAC,CAAC,KAAK,QAAQ,EAAE,GAAG;AAAA,UAC7B,UAAU,MAAM,KAAK,aAAa,EAAE,GAAG;AAAA;AAAA,MACzC;AAAA,MACC,EAAE;AAAA,SANO,EAAE,GAOd,CACD,GACH;AAAA,KAEJ;AAEJ;;;ACvMA,SAAS,WAAAM,WAAS,wBAAAC,6BAA4B;AAE9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAkBA,SAAS,aAAa,QAAuD;AAElF,QAAM,QAAQD,UAAQ,MAAM,iBAAiB,MAAM,GAAG,CAAC,MAAM,CAAC;AAC9D,QAAM,WAAWC,sBAAqB,MAAM,WAAW,MAAM,aAAa,MAAM,WAAW;AAC3F,SAAOD;AAAA,IACL,OAAO;AAAA,MACL,GAAG;AAAA,MACH,KAAK,CAAC,QAAQ,WAAW,eAAe,QAAQ,QAAQ,QAAQ,EAAE,OAAO,KAAK,CAAC;AAAA,MAC/E,OAAO,CAAC,QAAQ,WAAW,oBAAoB,QAAQ,QAAQ,MAAM;AAAA,IACvE;AAAA,IACA,CAAC,UAAU,MAAM;AAAA,EACnB;AACF;;;ACvCA,OAAOE,YAAW;AAElB,SAAS,6BAAoD;AA8CnD,SACgB,OAAAC,OADhB,QAAAC,cAAA;AA7BV,IAAMC,iBAAgB,CAAC,UAA4B,MAAM,eAAe;AAQjE,IAAM,eAA4C,CAAC;AAAA,EACxD;AAAA,EACA,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EACxB,qBAAqB;AAAA,EACrB;AACF,MAAM;AACJ,QAAM,QAAQ,aAAa,MAAM;AACjC,MAAI,CAAC,UAAW,CAAC,MAAM,WAAW,CAAC,gBAAkB,QAAO;AAE5D,SACE,gBAAAF,MAAC,SAAI,WAAsB,MAAK,WAAU,cAAW,SAAQ,sBAAmB,IAC7E,gBAAM,IAAI,CAAC,MAAM,UAAU;AAC1B,UAAM,SAAS,MAAM,MAAM,KAAK,QAAQ,KAAK,MAAM;AACnD,UAAM,UAAU,WAAW;AAC3B,UAAM,SAAS,KAAK,SAAS,KAAK;AAClC,UAAM,YAAY,QAAQ,KAAK,MAAM,QAAQ,CAAC,EAAE,UAAU,KAAK;AAC/D,WACE,gBAAAC,OAACE,OAAM,UAAN,EACE;AAAA,mBAAa,gBAAAH,MAAC,UAAK,WAAW,oBAAoB,eAAY,QAAO;AAAA,MACtE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,eAAa,KAAK;AAAA,UAClB,cAAY,KAAK;AAAA,UACjB,OAAO,UAAU,KAAK,QAAQ,GAAG,KAAK,KAAK,KAAK,MAAM;AAAA,UACrD,GAAI,KAAK,SAAS,EAAE,gBAAgB,CAAC,CAAC,OAAO,IAAI,CAAC;AAAA,UACnD,UAAU,CAAC;AAAA,UACX,WAAW,SAAS,GAAG,eAAe,IAAI,qBAAqB,KAAK;AAAA,UACpE,aAAaE;AAAA,UACb,SAAS,MAAM;AACb,gBAAI,MAAM,IAAI,KAAK,QAAQ,KAAK,MAAM,EAAG,YAAW,IAAI;AAAA,UAC1D;AAAA,UAEC,eAAK;AAAA;AAAA,MACR;AAAA,SAhBmB,KAAK,EAiB1B;AAAA,EAEJ,CAAC,GACH;AAEJ;;;ACtEA,SAAgB,YAAAE,kBAAgB;AA+C5B,SAiBQ,OAAAC,OAjBR,QAAAC,cAAA;AA7BJ,IAAMC,iBAAgB,CAAC,UAA4B,MAAM,eAAe;AAQjE,IAAM,kBAAkD,CAAC;AAAA,EAC9D;AAAA,EACA,OAAO;AAAA,EACP,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB;AACF,MAAM;AACJ,QAAM,QAAQ,aAAa,MAAM;AACjC,QAAM,CAAC,OAAO,QAAQ,IAAIC,WAAgD,IAAI;AAC9E,QAAM,SAAS,MAAM,QAAQ;AAC7B,QAAM,WAAW,CAAC,UAAU,CAAC,OAAO;AAEpC,QAAM,SAAS,CAAC,SAAyC;AACvD,QAAI,MAAM,IAAI,eAAe,EAAE,GAAG,MAAM,cAAc,CAAC,EAAG,YAAW,IAAI;AACzE,aAAS,IAAI;AAAA,EACf;AAEA,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAK;AAAA,MACL,cAAW;AAAA,MACX,OAAO,WAAW,OAAO,SAAS;AAAA,MAClC,0BAAuB;AAAA,MACvB,cAAc,MAAM,SAAS,IAAI;AAAA,MAEjC;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,cAAW;AAAA,YACX,OAAO,EAAE,SAAS,QAAQ,qBAAqB,UAAU,IAAI,kBAAkB,KAAK,EAAE;AAAA,YAErF,gBAAM,KAAK,EAAE,QAAQ,OAAO,KAAK,GAAG,CAAC,GAAG,MAAM;AAC7C,oBAAM,OAAO,EAAE,MAAM,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,MAAO,IAAI,OAAQ,EAAE;AACpE,oBAAM,SAAS,CAAC,CAAC,SAAS,KAAK,QAAQ,MAAM,QAAQ,KAAK,QAAQ,MAAM;AACxE,qBACE,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBAEC,MAAK;AAAA,kBACL,aAAW,KAAK;AAAA,kBAChB,aAAW,KAAK;AAAA,kBAChB,eAAa;AAAA,kBACb,cAAY,GAAG,KAAK,IAAI,SAAM,KAAK,IAAI;AAAA,kBACvC;AAAA,kBACA,WAAW,SAAS,GAAG,aAAa,IAAI,mBAAmB,KAAK;AAAA,kBAChE,aAAaE;AAAA,kBACb,cAAc,MAAM,SAAS,IAAI;AAAA,kBACjC,SAAS,MAAM,SAAS,IAAI;AAAA,kBAC5B,SAAS,MAAM,OAAO,IAAI;AAAA;AAAA,gBAXrB;AAAA,cAYP;AAAA,YAEJ,CAAC;AAAA;AAAA,QACH;AAAA,QACA,gBAAAF,MAAC,SAAI,aAAU,UAAS,eAAY,qBACjC,qBAAW,OAAO,SAAS,QAAQ,GAAG,MAAM,IAAI,SAAM,MAAM,IAAI,KAAK,gBACxE;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACpFA,SAAS,iCAAiC;AA2BzB,gBAAAI,aAAA;AARV,IAAM,kBAAkD,CAAC;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,GAAG;AACL,MACE,gBAAAA,MAAC,cAAW,QAAgB,WAAsB,YAAY,2BAA6D,GAAG,MAC3H,sBAAY,gBAAAA,MAAC,gBAAa,QAAiB,GAAG,cAAc,GAC/D;;;AC7BF,SAAS,kBAAkB;AAwCnB,SACE,OAAAC,OADF,QAAAC,cAAA;AAlBD,SAAS,cAAc,EAAE,OAAO,OAAO,eAAe,KAAK,GAAuB;AACvF,QAAM,EAAE,YAAY,SAAS,UAAU,UAAU,OAAO,QAAQ,WAAW,IAAI;AAC/E,QAAM,OAAO,MAAM;AACjB,QAAI,YAAY,CAAC,QAAS,YAAW,IAAI;AAAA,EAC3C;AACA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,sDAAsD,WAAW,uCAAuC,eAAe;AAAA,MAClI,wBAAqB;AAAA,MACrB,gBAAc,UAAU,KAAK;AAAA,MAC7B,WAAW,CAAC,MAAM;AAChB,YAAI,WAAW,EAAE,QAAQ,UAAU;AACjC,YAAE,gBAAgB;AAClB,qBAAW,KAAK;AAAA,QAClB;AAAA,MACF;AAAA,MAEC;AAAA,mBACC,gBAAAA,OAAC,SAAI,WAAU,qDAAoD,2BAAwB,IACzF;AAAA,0BAAAD,MAAC,UAAK,WAAU,iCAAgC,2BAAa;AAAA,UAC7D,gBAAAA,MAAC,YAAO,MAAK,UAAS,WAAW,kBAAkB,eAAY,QAAO,SAAS,MAAM,WAAW,KAAK,GAAG,kBAExG;AAAA,WACF;AAAA,QAEF,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,YAAY,CAAC,UAAU,mBAAmB;AAAA,YACrD,SAAS;AAAA,YACT,OAAO,YAAY,CAAC,UAAU,4BAA4B;AAAA,YAC1D,0BAAuB;AAAA,YAEvB,0BAAAA,MAAC,eAAY,YAAwB,OAAO,SAAS,KAAK,QAAgB,YAAY,UAAU,MAAM,UAAU,SAAS,OAAc;AAAA;AAAA,QACzI;AAAA,QACC;AAAA,QAEC,gBAAAC,OAAC,SAAI,WAAU,yCAAwC,yBAAsB,IAC1E;AAAA,0BACC,gBAAAD,MAAC,SAAI,WAAU,4CACb,0BAAAA,MAAC,iBAAc,YAAwB,GACzC;AAAA,UAEF,gBAAAA,MAAC,kBAAe,YAAwB,WAAU,yFAAwF;AAAA,WAC5I;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAYO,SAAS,yBAAyB,UAAqC,CAAC,GAAuB;AACpG,QAAM,EAAE,WAAW,YAAY,eAAe,GAAG,MAAM,IAAI;AAC3D,SAAO,CAAC,KAAK,UAAU;AACrB,UAAM,OAAO,WAAW,GAAG;AAC3B,QAAI,SAAS;AACb,QAAI,YAAY;AAChB,QAAI,YAAY;AAGhB,UAAM,WAAW,MAAM;AACrB,UAAI,UAAW;AACf,kBAAY;AACZ,qBAAe,MAAM;AACnB,oBAAY;AACZ,YAAI,CAAC,UAAW,MAAK,OAAO,gBAAAA,MAAC,aAAW,GAAG,OAAO,OAAO,QAAQ,CAAE;AAAA,MACrE,CAAC;AAAA,IACH;AACA,aAAS;AACT,WAAO;AAAA,MACL,QAAQ,CAAC,SAAS;AAChB,iBAAS;AACT,iBAAS;AAAA,MACX;AAAA,MACA,SAAS,MAAM;AACb,oBAAY;AACZ,uBAAe,MAAM,KAAK,QAAQ,CAAC;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AACF;","names":["useEditor","useEffect","useRef","useState","useCallback","useRef","useRef","useCallback","useMemo","useCallback","useEffect","useRef","useState","useSyncExternalStore","useEffect","useEffect","useMemo","useRef","useSyncExternalStore","useEffect","useMemo","useRef","useSyncExternalStore","useEffect","useEffect","useState","jsx","useEffect","useRef","useState","useMemo","jsx","useMemo","useState","jsx","jsxs","useId","useState","useCallback","useMemo","useState","jsx","jsxs","useId","useState","useMemo","useSyncExternalStore","jsx","jsxs","useMemo","useSyncExternalStore","useState","jsx","jsxs","useState","DirtyTracker","HistoryManager","createHistoryManager","bindDirtyToHistory","useMemo","jsx","jsxs","useCallback","useMemo","useSyncExternalStore","useState","jsx","jsxs","useState","jsx","jsxs","buttonClass","jsx","useCallback","useMemo","useRef","useState","jsx","jsxs","buttonClass","useCallback","useMemo","useSyncExternalStore","noopUnsubscribe","useEffect","useRef","useState","jsx","jsxs","buttonClass","useRef","useState","useEffect","useMemo","useSyncExternalStore","React","jsx","jsxs","keepSelection","React","useState","jsx","jsxs","keepSelection","useState","jsx","jsx","jsxs"]}