@elia-ori/editor 0.1.8 → 0.1.10

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.cjs CHANGED
@@ -273,7 +273,7 @@ function ToolbarButton({
273
273
  onPressedChange,
274
274
  disabled,
275
275
  title,
276
- className: "h-9 w-9 p-0 border-0 bg-transparent rounded-lg hover:bg-muted data-[state=on]:bg-zinc-900 data-[state=on]:text-white dark:data-[state=on]:bg-zinc-100 dark:data-[state=on]:text-zinc-900 disabled:opacity-30",
276
+ className: "h-9 w-9 p-0 border-0 bg-transparent rounded-lg hover:bg-muted data-[state=on]:bg-zinc-900 data-[state=on]:text-white disabled:opacity-30",
277
277
  children
278
278
  }
279
279
  );
@@ -553,7 +553,7 @@ function ColorPicker({ editor, iconSize = "h-4 w-4" }) {
553
553
  "button",
554
554
  {
555
555
  type: "button",
556
- className: "w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform",
556
+ className: "w-6 h-6 rounded border border-border hover:scale-110 transition-transform",
557
557
  style: { backgroundColor: color.value },
558
558
  onClick: () => editor.chain().focus().setColor(color.value).run(),
559
559
  title: color.name,
@@ -565,7 +565,7 @@ function ColorPicker({ editor, iconSize = "h-4 w-4" }) {
565
565
  "button",
566
566
  {
567
567
  type: "button",
568
- className: "w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform flex items-center justify-center bg-background",
568
+ className: "w-6 h-6 rounded border border-border hover:scale-110 transition-transform flex items-center justify-center bg-background",
569
569
  onClick: () => editor.chain().focus().unsetColor().run(),
570
570
  title: "\u6E05\u9664\u6587\u5B57\u984F\u8272",
571
571
  "aria-label": "\u6E05\u9664\u6587\u5B57\u984F\u8272",
@@ -580,7 +580,7 @@ function ColorPicker({ editor, iconSize = "h-4 w-4" }) {
580
580
  "button",
581
581
  {
582
582
  type: "button",
583
- className: "w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform",
583
+ className: "w-6 h-6 rounded border border-border hover:scale-110 transition-transform",
584
584
  style: { backgroundColor: color.value },
585
585
  onClick: () => editor.chain().focus().toggleHighlight({ color: color.value }).run(),
586
586
  title: color.name,
@@ -592,7 +592,7 @@ function ColorPicker({ editor, iconSize = "h-4 w-4" }) {
592
592
  "button",
593
593
  {
594
594
  type: "button",
595
- className: "w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform flex items-center justify-center bg-background",
595
+ className: "w-6 h-6 rounded border border-border hover:scale-110 transition-transform flex items-center justify-center bg-background",
596
596
  onClick: () => editor.chain().focus().unsetHighlight().run(),
597
597
  title: "\u6E05\u9664\u80CC\u666F\u8272",
598
598
  "aria-label": "\u6E05\u9664\u80CC\u666F\u8272",
@@ -765,7 +765,7 @@ function Toolbar({
765
765
  return null;
766
766
  }
767
767
  };
768
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex items-center justify-center mb-2 relative", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between px-2 py-1.5 bg-white dark:bg-zinc-900 rounded-lg shadow-sm w-full max-w-7xl mx-auto", children: [
768
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex items-center justify-center mb-2 relative", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `flex items-center justify-between px-2 py-1.5 rounded-lg shadow-sm w-full max-w-7xl mx-auto ${theme === "dark" ? "bg-zinc-900" : "bg-white"}`, children: [
769
769
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-0.5", children: [
770
770
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
771
771
  "input",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/EliaEditor.tsx","../src/extensions/callout.ts","../src/components/Toolbar.tsx","../src/lib/compress-image.ts","../src/ui/button.tsx","../src/lib/utils.ts","../src/ui/toggle.tsx","../src/components/ToolbarButton.tsx","../src/components/ToolbarDivider.tsx","../src/ui/dropdown-menu.tsx","../src/components/HeadingDropdown.tsx","../src/components/ListDropdown.tsx","../src/components/TableDropdown.tsx","../src/components/CalloutDropdown.tsx","../src/components/ColorPicker.tsx"],"sourcesContent":["// Elia Editor - 基於 TipTap 的富文字編輯器\nexport { EliaEditor } from './EliaEditor';\nexport type { EliaEditorProps } from './EliaEditor';\n\n// Utils\nexport { cn } from './lib/utils';\n\n// UI Components\nexport { Button } from './ui/button';\nexport type { ButtonProps } from './ui/button';\nexport { Toggle } from './ui/toggle';\nexport type { ToggleProps } from './ui/toggle';\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n} from './ui/dropdown-menu';\n\n// Toolbar Components\nexport { Toolbar } from './components/Toolbar';\nexport type { ToolbarProps, ToolbarItem, ToolbarButtonConfig } from './components/Toolbar';\nexport { ToolbarButton } from './components/ToolbarButton';\nexport type { ToolbarButtonProps } from './components/ToolbarButton';\nexport { ToolbarDivider } from './components/ToolbarDivider';\nexport { HeadingDropdown } from './components/HeadingDropdown';\nexport type { HeadingDropdownProps } from './components/HeadingDropdown';\nexport { ListDropdown } from './components/ListDropdown';\nexport type { ListDropdownProps } from './components/ListDropdown';\nexport { TableDropdown } from './components/TableDropdown';\nexport type { TableDropdownProps } from './components/TableDropdown';\nexport { CalloutDropdown } from './components/CalloutDropdown';\nexport type { CalloutDropdownProps } from './components/CalloutDropdown';\nexport { ColorPicker } from './components/ColorPicker';\nexport type { ColorPickerProps } from './components/ColorPicker';\n\n// TipTap Extensions\nexport { Callout } from './extensions/callout';\nexport type { CalloutOptions, CalloutType } from './extensions/callout';\n","import { useRef, useEffect, useCallback } from 'react';\nimport { useEditor, EditorContent, type Editor } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport Underline from '@tiptap/extension-underline';\nimport TextAlign from '@tiptap/extension-text-align';\nimport Link from '@tiptap/extension-link';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport { Color } from '@tiptap/extension-color';\nimport { Highlight } from '@tiptap/extension-highlight';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport TaskList from '@tiptap/extension-task-list';\nimport TaskItem from '@tiptap/extension-task-item';\nimport { Table } from '@tiptap/extension-table';\nimport { TableRow } from '@tiptap/extension-table-row';\nimport { TableHeader } from '@tiptap/extension-table-header';\nimport { TableCell } from '@tiptap/extension-table-cell';\nimport ImageResize from 'tiptap-extension-resize-image';\nimport { Callout } from './extensions/callout';\nimport { Toolbar, type ToolbarItem } from './components/Toolbar';\nimport { cn } from './lib/utils';\n\nexport interface EliaEditorProps {\n // 內容\n content?: string;\n onChange?: (html: string) => void;\n placeholder?: string;\n\n // Toolbar 配置\n toolbar?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';\n\n // 插槽\n header?: React.ReactNode;\n toolbarStart?: React.ReactNode;\n toolbarEnd?: React.ReactNode;\n footer?: React.ReactNode;\n\n // 樣式\n className?: string;\n editorClassName?: string;\n\n // 其他\n autofocus?: boolean;\n readOnly?: boolean;\n\n // Toolbar 相關\n theme?: 'light' | 'dark';\n onThemeToggle?: () => void;\n onImageUpload?: (file: File) => Promise<string> | void;\n}\n\nexport function EliaEditor({\n content = '',\n onChange,\n placeholder = '開始寫作...',\n toolbar = 'all',\n header,\n toolbarStart,\n toolbarEnd,\n footer,\n className,\n editorClassName,\n autofocus = false,\n readOnly = false,\n theme = 'light',\n onThemeToggle,\n onImageUpload,\n}: EliaEditorProps) {\n const isInternalUpdate = useRef(false);\n\n const handleUpdate = useCallback(\n ({ editor }: { editor: Editor }) => {\n isInternalUpdate.current = true;\n onChange?.(editor.getHTML());\n },\n [onChange]\n );\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n heading: {\n levels: [1, 2, 3],\n },\n }),\n Placeholder.configure({\n placeholder,\n }),\n Underline,\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Link.configure({\n openOnClick: false,\n HTMLAttributes: {\n class: 'text-primary underline underline-offset-4',\n },\n }),\n TextStyle,\n Color,\n Highlight.configure({\n multicolor: true,\n }),\n Subscript,\n Superscript,\n TaskList,\n TaskItem.configure({\n nested: true,\n }),\n Table.configure({\n resizable: true,\n }),\n TableRow,\n TableHeader,\n TableCell,\n ImageResize.configure({\n allowBase64: true,\n }),\n Callout,\n ],\n content,\n autofocus,\n editable: !readOnly,\n editorProps: {\n attributes: {\n class: cn(\n 'tiptap-editor min-h-[300px] p-4 focus:outline-none',\n editorClassName\n ),\n },\n },\n onUpdate: handleUpdate,\n });\n\n useEffect(() => {\n if (editor && !isInternalUpdate.current && content !== editor.getHTML()) {\n editor.commands.setContent(content);\n }\n isInternalUpdate.current = false;\n }, [content, editor]);\n\n useEffect(() => {\n if (editor) {\n editor.setEditable(!readOnly);\n }\n }, [readOnly, editor]);\n\n return (\n <div className={cn('ori-editor', theme === 'dark' && 'dark', className)}>\n {header && <div className=\"ori-editor-header\">{header}</div>}\n\n <Toolbar\n editor={editor}\n config={toolbar}\n toolbarStart={toolbarStart}\n toolbarEnd={toolbarEnd}\n theme={theme}\n onThemeToggle={onThemeToggle}\n onImageUpload={onImageUpload}\n />\n\n <EditorContent editor={editor} />\n\n {footer && <div className=\"ori-editor-footer\">{footer}</div>}\n </div>\n );\n}\n","import { Node, mergeAttributes } from \"@tiptap/core\";\n\nexport type CalloutType = 'success' | 'warning' | 'error' | 'info';\n\nexport interface CalloutOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nconst CALLOUT_ARIA_LABELS: Record<CalloutType, string> = {\n success: '成功提示',\n warning: '警告提示',\n error: '錯誤提示',\n info: '資訊提示',\n};\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n callout: {\n setCallout: (attributes?: { type: CalloutType }) => ReturnType;\n toggleCallout: (attributes?: { type: CalloutType }) => ReturnType;\n unsetCallout: () => ReturnType;\n };\n }\n}\n\nexport const Callout = Node.create<CalloutOptions>({\n name: \"callout\",\n group: \"block\",\n content: \"block+\",\n defining: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n addAttributes() {\n return {\n type: {\n default: \"info\" as CalloutType,\n parseHTML: (element) => element.getAttribute(\"data-type\") as CalloutType,\n renderHTML: (attributes) => ({\n \"data-type\": attributes.type,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"div[data-callout]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const type = (node.attrs.type as CalloutType) || 'info';\n\n return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n \"data-callout\": \"\",\n \"class\": `callout callout-${type}`,\n \"role\": \"note\",\n \"aria-label\": CALLOUT_ARIA_LABELS[type],\n }),\n 0,\n ];\n },\n\n addCommands() {\n return {\n setCallout:\n (attributes) =>\n ({ commands }) => {\n return commands.wrapIn(this.name, attributes);\n },\n toggleCallout:\n (attributes) =>\n ({ commands }) => {\n return commands.toggleWrap(this.name, attributes);\n },\n unsetCallout:\n () =>\n ({ commands }) => {\n return commands.lift(this.name);\n },\n };\n },\n});\n","import { useRef } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport { compressImage } from '../lib/compress-image';\nimport { Button } from '../ui/button';\nimport { ToolbarButton } from './ToolbarButton';\nimport { ToolbarDivider } from './ToolbarDivider';\nimport { HeadingDropdown } from './HeadingDropdown';\nimport { ListDropdown } from './ListDropdown';\nimport { TableDropdown } from './TableDropdown';\nimport { CalloutDropdown } from './CalloutDropdown';\nimport { ColorPicker } from './ColorPicker';\nimport {\n Bold,\n Italic,\n Code,\n Underline as UnderlineIcon,\n Link as LinkIcon,\n Superscript as SuperscriptIcon,\n Subscript as SubscriptIcon,\n AlignLeft,\n AlignCenter,\n AlignRight,\n ImagePlus,\n Sun,\n Moon,\n type LucideProps,\n} from 'lucide-react';\nimport type { ComponentType } from 'react';\n\ntype ToolbarButtonConfig = {\n key: string;\n icon: ComponentType<LucideProps>;\n title: string;\n isActive: (editor: Editor) => boolean;\n action: (editor: Editor) => void;\n};\n\ntype ToolbarItem =\n | 'heading'\n | 'list'\n | 'format'\n | 'script'\n | 'align'\n | 'color'\n | 'link'\n | 'image'\n | 'table'\n | 'callout'\n | 'themeToggle';\n\ninterface ToolbarProps {\n editor: Editor | null;\n config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';\n toolbarStart?: React.ReactNode;\n toolbarEnd?: React.ReactNode;\n theme?: 'light' | 'dark';\n onThemeToggle?: () => void;\n onImageUpload?: (file: File) => Promise<string> | void;\n}\n\nconst ICON_SIZE = \"h-4 w-4\";\n\nconst TEXT_FORMAT_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"bold\", icon: Bold, title: \"粗體\", isActive: (e) => e.isActive(\"bold\"), action: (e) => (e.chain().focus() as any).toggleBold().run() },\n { key: \"italic\", icon: Italic, title: \"斜體\", isActive: (e) => e.isActive(\"italic\"), action: (e) => (e.chain().focus() as any).toggleItalic().run() },\n { key: \"code\", icon: Code, title: \"行內程式碼\", isActive: (e) => e.isActive(\"code\"), action: (e) => (e.chain().focus() as any).toggleCode().run() },\n { key: \"underline\", icon: UnderlineIcon, title: \"底線\", isActive: (e) => e.isActive(\"underline\"), action: (e) => (e.chain().focus() as any).toggleUnderline().run() },\n];\n\nconst SCRIPT_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"superscript\", icon: SuperscriptIcon, title: \"上標\", isActive: (e) => e.isActive(\"superscript\"), action: (e) => (e.chain().focus() as any).toggleSuperscript().run() },\n { key: \"subscript\", icon: SubscriptIcon, title: \"下標\", isActive: (e) => e.isActive(\"subscript\"), action: (e) => (e.chain().focus() as any).toggleSubscript().run() },\n];\n\nconst ALIGN_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"left\", icon: AlignLeft, title: \"靠左對齊\", isActive: (e) => e.isActive({ textAlign: \"left\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"left\").run() },\n { key: \"center\", icon: AlignCenter, title: \"置中對齊\", isActive: (e) => e.isActive({ textAlign: \"center\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"center\").run() },\n { key: \"right\", icon: AlignRight, title: \"靠右對齊\", isActive: (e) => e.isActive({ textAlign: \"right\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"right\").run() },\n];\n\nfunction ToolbarButtonGroup({ buttons, editor }: { buttons: ToolbarButtonConfig[]; editor: Editor }) {\n return (\n <>\n {buttons.map(({ key, icon: Icon, title, isActive, action }) => (\n <ToolbarButton\n key={key}\n pressed={isActive(editor)}\n onPressedChange={() => action(editor)}\n title={title}\n >\n <Icon className={ICON_SIZE} />\n </ToolbarButton>\n ))}\n </>\n );\n}\n\nfunction normalizeConfig(config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none'): ToolbarItem[][] {\n if (config === 'none') return [];\n if (config === 'all' || !config) {\n return [\n ['heading', 'list', 'table', 'callout'],\n ['format', 'link', 'color'],\n ['script'],\n ['align'],\n ['image'],\n ['themeToggle'],\n ];\n }\n\n if (Array.isArray(config)) {\n // 檢查是否為二維陣列\n if (config.length > 0 && Array.isArray(config[0])) {\n return config as ToolbarItem[][];\n }\n // 一維陣列,轉為二維\n return [config as ToolbarItem[]];\n }\n\n return [];\n}\n\nexport function Toolbar({\n editor,\n config,\n toolbarStart,\n toolbarEnd,\n theme,\n onThemeToggle,\n onImageUpload,\n}: ToolbarProps) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n if (!editor) return null;\n\n const groups = normalizeConfig(config);\n\n const setLink = () => {\n const previousUrl = editor.getAttributes(\"link\").href;\n const url = window.prompt(\"輸入連結網址\", previousUrl);\n\n if (url === null) return;\n if (url === \"\") {\n (editor.chain().focus().extendMarkRange(\"link\") as any).unsetLink().run();\n return;\n }\n\n (editor.chain().focus().extendMarkRange(\"link\") as any).setLink({ href: url }).run();\n };\n\n const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n try {\n const compressed = await compressImage(file);\n\n if (onImageUpload) {\n const result = onImageUpload(compressed);\n if (result instanceof Promise) {\n const url = await result;\n if (url) {\n (editor.chain().focus() as any).setImage({ src: url }).run();\n }\n }\n } else {\n const reader = new FileReader();\n reader.onload = () => {\n const base64 = reader.result as string;\n (editor.chain().focus() as any).setImage({ src: base64 }).run();\n };\n reader.onerror = () => {\n console.error(\"圖片讀取失敗\");\n };\n reader.readAsDataURL(compressed);\n }\n } catch (error) {\n console.error(\"圖片處理失敗:\", error);\n }\n\n e.target.value = \"\";\n };\n\n const renderToolbarItem = (item: ToolbarItem) => {\n switch (item) {\n case 'heading':\n return <HeadingDropdown key=\"heading\" editor={editor} iconSize={ICON_SIZE} />;\n case 'list':\n return <ListDropdown key=\"list\" editor={editor} iconSize={ICON_SIZE} />;\n case 'table':\n return <TableDropdown key=\"table\" editor={editor} iconSize={ICON_SIZE} />;\n case 'callout':\n return <CalloutDropdown key=\"callout\" editor={editor} iconSize={ICON_SIZE} />;\n case 'format':\n return <ToolbarButtonGroup key=\"format\" buttons={TEXT_FORMAT_BUTTONS} editor={editor} />;\n case 'link':\n return (\n <ToolbarButton\n key=\"link\"\n pressed={editor.isActive(\"link\")}\n onPressedChange={setLink}\n title=\"連結\"\n >\n <LinkIcon className={ICON_SIZE} />\n </ToolbarButton>\n );\n case 'color':\n return <ColorPicker key=\"color\" editor={editor} iconSize={ICON_SIZE} />;\n case 'script':\n return <ToolbarButtonGroup key=\"script\" buttons={SCRIPT_BUTTONS} editor={editor} />;\n case 'align':\n return <ToolbarButtonGroup key=\"align\" buttons={ALIGN_BUTTONS} editor={editor} />;\n case 'image':\n return (\n <Button\n key=\"image\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 px-2 gap-1\"\n onClick={() => fileInputRef.current?.click()}\n title=\"插入圖片\"\n >\n <ImagePlus className={ICON_SIZE} />\n </Button>\n );\n case 'themeToggle':\n return onThemeToggle ? (\n <Button\n key=\"themeToggle\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n onClick={onThemeToggle}\n title={theme === \"dark\" ? \"切換淺色模式\" : \"切換深色模式\"}\n >\n {theme === \"dark\" ? <Moon className={ICON_SIZE} /> : <Sun className={ICON_SIZE} />}\n </Button>\n ) : null;\n default:\n return null;\n }\n };\n\n return (\n <div className=\"flex items-center justify-center mb-2 relative\">\n <div className=\"flex items-center justify-between px-2 py-1.5 bg-white dark:bg-zinc-900 rounded-lg shadow-sm w-full max-w-7xl mx-auto\">\n <div className=\"flex items-center gap-0.5\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handleImageUpload}\n aria-label=\"上傳圖片\"\n />\n\n {toolbarStart}\n\n {groups.map((group, groupIndex) => (\n <div key={groupIndex} className=\"flex items-center gap-0.5\">\n {groupIndex > 0 && <ToolbarDivider />}\n {group.map(item => renderToolbarItem(item))}\n </div>\n ))}\n </div>\n\n <div className=\"flex items-center gap-0.5\">\n {toolbarEnd}\n </div>\n </div>\n </div>\n );\n}\n\nexport type { ToolbarProps, ToolbarItem, ToolbarButtonConfig };\n","const DEFAULT_MAX_SIZE_MB = 1;\nconst DEFAULT_MAX_DIMENSION = 1920;\nconst DEFAULT_QUALITY = 0.85;\n\ninterface CompressOptions {\n maxSizeMB?: number;\n maxDimension?: number;\n quality?: number;\n}\n\nexport async function compressImage(\n file: File,\n options: CompressOptions = {}\n): Promise<File> {\n const {\n maxSizeMB = DEFAULT_MAX_SIZE_MB,\n maxDimension = DEFAULT_MAX_DIMENSION,\n quality = DEFAULT_QUALITY,\n } = options;\n\n if (file.size <= maxSizeMB * 1024 * 1024) {\n return file;\n }\n\n const img = new Image();\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d')!;\n\n return new Promise((resolve, reject) => {\n img.onload = () => {\n let { width, height } = img;\n\n if (width > maxDimension || height > maxDimension) {\n const ratio = Math.min(maxDimension / width, maxDimension / height);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n\n canvas.width = width;\n canvas.height = height;\n ctx.drawImage(img, 0, 0, width, height);\n\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error('圖片壓縮失敗'));\n return;\n }\n resolve(new File([blob], file.name, { type: 'image/jpeg' }));\n },\n 'image/jpeg',\n quality\n );\n };\n\n img.onerror = () => reject(new Error('圖片載入失敗'));\n img.src = URL.createObjectURL(file);\n });\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'default' | 'ghost' | 'outline';\n size?: 'default' | 'sm' | 'lg';\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'default', size = 'default', ...props }, ref) => {\n const variantStyles = {\n default: 'bg-transparent text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800',\n ghost: 'hover:bg-zinc-100 dark:hover:bg-zinc-800',\n outline: 'border border-zinc-200 dark:border-zinc-700 bg-transparent hover:bg-zinc-100 dark:hover:bg-zinc-800',\n };\n\n const sizeStyles = {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 px-3 text-xs',\n lg: 'h-10 px-8',\n };\n\n return (\n <button\n className={cn(\n 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n 'disabled:pointer-events-none disabled:opacity-50',\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\n\nButton.displayName = 'Button';\n\nexport { Button };\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from 'react';\nimport * as TogglePrimitive from '@radix-ui/react-toggle';\nimport { cn } from '../lib/utils';\n\nexport interface ToggleProps extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> {\n size?: 'default' | 'sm';\n}\n\nconst Toggle = React.forwardRef<React.ElementRef<typeof TogglePrimitive.Root>, ToggleProps>(\n ({ className, size = 'default', ...props }, ref) => {\n const sizeStyles = {\n default: 'h-9 px-3',\n sm: 'h-8 px-2',\n };\n\n return (\n <TogglePrimitive.Root\n ref={ref}\n className={cn(\n 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',\n 'hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n 'disabled:pointer-events-none disabled:opacity-50',\n 'data-[state=on]:bg-[var(--accent)] data-[state=on]:text-[var(--accent-foreground)]',\n sizeStyles[size],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nToggle.displayName = TogglePrimitive.Root.displayName;\n\nexport { Toggle };\n","import { Toggle } from '../ui/toggle';\n\ninterface ToolbarButtonProps {\n pressed: boolean;\n onPressedChange: () => void;\n disabled?: boolean;\n children: React.ReactNode;\n title?: string;\n}\n\nexport function ToolbarButton({\n pressed,\n onPressedChange,\n disabled,\n children,\n title,\n}: ToolbarButtonProps) {\n return (\n <Toggle\n size=\"sm\"\n pressed={pressed}\n onPressedChange={onPressedChange}\n disabled={disabled}\n title={title}\n className=\"h-9 w-9 p-0 border-0 bg-transparent rounded-lg hover:bg-muted data-[state=on]:bg-zinc-900 data-[state=on]:text-white dark:data-[state=on]:bg-zinc-100 dark:data-[state=on]:text-zinc-900 disabled:opacity-30\"\n >\n {children}\n </Toggle>\n );\n}\n\nexport type { ToolbarButtonProps };\n","export function ToolbarDivider() {\n return <div className=\"w-px h-5 bg-border mx-1.5\" />;\n}\n","import * as React from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { cn } from '../lib/utils';\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border border-[var(--border)] bg-[var(--popover)] p-1 text-[var(--popover-foreground)] shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors',\n 'hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)] focus:bg-[var(--accent)] focus:text-[var(--accent-foreground)]',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-[var(--border)]', className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nexport { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, Heading1, Heading2, Heading3 } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface HeadingDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function HeadingDropdown({ editor, iconSize = \"h-4 w-4\" }: HeadingDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1 font-normal\">\n <span className=\"text-sm font-semibold\">H</span>\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 1 }).run()}>\n <Heading1 className={cn(iconSize, \"mr-2\")} />\n 標題 1\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 2 }).run()}>\n <Heading2 className={cn(iconSize, \"mr-2\")} />\n 標題 2\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 3 }).run()}>\n <Heading3 className={cn(iconSize, \"mr-2\")} />\n 標題 3\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).setParagraph().run()}>\n 內文\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { HeadingDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, List, ListOrdered, ListTodo } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface ListDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function ListDropdown({ editor, iconSize = \"h-4 w-4\" }: ListDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <List className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleBulletList().run()}>\n <List className={cn(iconSize, \"mr-2\")} />\n 項目清單\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleOrderedList().run()}>\n <ListOrdered className={cn(iconSize, \"mr-2\")} />\n 編號清單\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleTaskList().run()}>\n <ListTodo className={cn(iconSize, \"mr-2\")} />\n 任務清單\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { ListDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, Plus, Trash2, Table as TableIcon } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface TableDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function TableDropdown({ editor, iconSize = \"h-4 w-4\" }: TableDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <TableIcon className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}\n >\n <Plus className={cn(iconSize, \"mr-2\")} />\n 插入表格 (3x3)\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).addColumnAfter().run()}\n disabled={!(editor.can() as any).addColumnAfter()}\n >\n 新增欄\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).addRowAfter().run()}\n disabled={!(editor.can() as any).addRowAfter()}\n >\n 新增列\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteColumn().run()}\n disabled={!(editor.can() as any).deleteColumn()}\n >\n 刪除欄\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteRow().run()}\n disabled={!(editor.can() as any).deleteRow()}\n >\n 刪除列\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteTable().run()}\n disabled={!(editor.can() as any).deleteTable()}\n className=\"text-destructive\"\n >\n <Trash2 className={cn(iconSize, \"mr-2\")} />\n 刪除表格\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { TableDropdownProps };\n","import { useState } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, MessageSquare } from 'lucide-react';\n\ninterface CalloutDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function CalloutDropdown({ editor, iconSize = \"h-4 w-4\" }: CalloutDropdownProps) {\n const [open, setOpen] = useState(false);\n\n return (\n <DropdownMenu open={open} onOpenChange={setOpen} modal={false}>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <MessageSquare className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"min-w-0 p-1.5\">\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-emerald-100 border border-emerald-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"success\" }).run();\n }, 0);\n }}\n title=\"成功提示\"\n aria-label=\"成功提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-amber-100 border border-amber-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"warning\" }).run();\n }, 0);\n }}\n title=\"警告提示\"\n aria-label=\"警告提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-red-100 border border-red-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"error\" }).run();\n }, 0);\n }}\n title=\"錯誤提示\"\n aria-label=\"錯誤提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-sky-100 border border-sky-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"info\" }).run();\n }, 0);\n }}\n title=\"資訊提示\"\n aria-label=\"資訊提示\"\n />\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { CalloutDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { Palette, X } from 'lucide-react';\n\nconst COLOR_PALETTE = [\n { name: \"黑色\", value: \"#000000\" },\n { name: \"灰色\", value: \"#6B7280\" },\n { name: \"紅色\", value: \"#EF4444\" },\n { name: \"橙色\", value: \"#F97316\" },\n { name: \"黃色\", value: \"#EAB308\" },\n { name: \"綠色\", value: \"#22C55E\" },\n { name: \"藍色\", value: \"#3B82F6\" },\n { name: \"紫色\", value: \"#8B5CF6\" },\n];\n\ninterface ColorPickerProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function ColorPicker({ editor, iconSize = \"h-4 w-4\" }: ColorPickerProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\" title=\"顏色\">\n <Palette className={iconSize} />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-72\">\n <div className=\"p-2\">\n <div className=\"text-xs font-medium text-muted-foreground mb-2\">文字顏色</div>\n <div className=\"flex gap-1.5 mb-3\">\n {COLOR_PALETTE.map((color) => (\n <button\n key={`text-${color.value}`}\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform\"\n style={{ backgroundColor: color.value }}\n onClick={() => (editor.chain().focus() as any).setColor(color.value).run()}\n title={color.name}\n aria-label={`文字顏色:${color.name}`}\n />\n ))}\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform flex items-center justify-center bg-background\"\n onClick={() => (editor.chain().focus() as any).unsetColor().run()}\n title=\"清除文字顏色\"\n aria-label=\"清除文字顏色\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </div>\n\n <DropdownMenuSeparator />\n\n <div className=\"text-xs font-medium text-muted-foreground mb-2 mt-2\">背景色</div>\n <div className=\"flex gap-1.5\">\n {COLOR_PALETTE.map((color) => (\n <button\n key={`bg-${color.value}`}\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform\"\n style={{ backgroundColor: color.value }}\n onClick={() => (editor.chain().focus() as any).toggleHighlight({ color: color.value }).run()}\n title={color.name}\n aria-label={`背景色:${color.name}`}\n />\n ))}\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform flex items-center justify-center bg-background\"\n onClick={() => (editor.chain().focus() as any).unsetHighlight().run()}\n title=\"清除背景色\"\n aria-label=\"清除背景色\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </div>\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { ColorPickerProps };\nexport { COLOR_PALETTE };\n"],"mappings":"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","names":["import_react","import_react","React","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","TableIcon","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","UnderlineIcon","SuperscriptIcon","SubscriptIcon","LinkIcon","import_jsx_runtime","editor","StarterKit","Placeholder","Underline","TextAlign","Link","Subscript","Superscript","TaskList","TaskItem","ImageResize"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/EliaEditor.tsx","../src/extensions/callout.ts","../src/components/Toolbar.tsx","../src/lib/compress-image.ts","../src/ui/button.tsx","../src/lib/utils.ts","../src/ui/toggle.tsx","../src/components/ToolbarButton.tsx","../src/components/ToolbarDivider.tsx","../src/ui/dropdown-menu.tsx","../src/components/HeadingDropdown.tsx","../src/components/ListDropdown.tsx","../src/components/TableDropdown.tsx","../src/components/CalloutDropdown.tsx","../src/components/ColorPicker.tsx"],"sourcesContent":["// Elia Editor - 基於 TipTap 的富文字編輯器\nexport { EliaEditor } from './EliaEditor';\nexport type { EliaEditorProps } from './EliaEditor';\n\n// Utils\nexport { cn } from './lib/utils';\n\n// UI Components\nexport { Button } from './ui/button';\nexport type { ButtonProps } from './ui/button';\nexport { Toggle } from './ui/toggle';\nexport type { ToggleProps } from './ui/toggle';\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n} from './ui/dropdown-menu';\n\n// Toolbar Components\nexport { Toolbar } from './components/Toolbar';\nexport type { ToolbarProps, ToolbarItem, ToolbarButtonConfig } from './components/Toolbar';\nexport { ToolbarButton } from './components/ToolbarButton';\nexport type { ToolbarButtonProps } from './components/ToolbarButton';\nexport { ToolbarDivider } from './components/ToolbarDivider';\nexport { HeadingDropdown } from './components/HeadingDropdown';\nexport type { HeadingDropdownProps } from './components/HeadingDropdown';\nexport { ListDropdown } from './components/ListDropdown';\nexport type { ListDropdownProps } from './components/ListDropdown';\nexport { TableDropdown } from './components/TableDropdown';\nexport type { TableDropdownProps } from './components/TableDropdown';\nexport { CalloutDropdown } from './components/CalloutDropdown';\nexport type { CalloutDropdownProps } from './components/CalloutDropdown';\nexport { ColorPicker } from './components/ColorPicker';\nexport type { ColorPickerProps } from './components/ColorPicker';\n\n// TipTap Extensions\nexport { Callout } from './extensions/callout';\nexport type { CalloutOptions, CalloutType } from './extensions/callout';\n","import { useRef, useEffect, useCallback } from 'react';\nimport { useEditor, EditorContent, type Editor } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport Underline from '@tiptap/extension-underline';\nimport TextAlign from '@tiptap/extension-text-align';\nimport Link from '@tiptap/extension-link';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport { Color } from '@tiptap/extension-color';\nimport { Highlight } from '@tiptap/extension-highlight';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport TaskList from '@tiptap/extension-task-list';\nimport TaskItem from '@tiptap/extension-task-item';\nimport { Table } from '@tiptap/extension-table';\nimport { TableRow } from '@tiptap/extension-table-row';\nimport { TableHeader } from '@tiptap/extension-table-header';\nimport { TableCell } from '@tiptap/extension-table-cell';\nimport ImageResize from 'tiptap-extension-resize-image';\nimport { Callout } from './extensions/callout';\nimport { Toolbar, type ToolbarItem } from './components/Toolbar';\nimport { cn } from './lib/utils';\n\nexport interface EliaEditorProps {\n // 內容\n content?: string;\n onChange?: (html: string) => void;\n placeholder?: string;\n\n // Toolbar 配置\n toolbar?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';\n\n // 插槽\n header?: React.ReactNode;\n toolbarStart?: React.ReactNode;\n toolbarEnd?: React.ReactNode;\n footer?: React.ReactNode;\n\n // 樣式\n className?: string;\n editorClassName?: string;\n\n // 其他\n autofocus?: boolean;\n readOnly?: boolean;\n\n // Toolbar 相關\n theme?: 'light' | 'dark';\n onThemeToggle?: () => void;\n onImageUpload?: (file: File) => Promise<string> | void;\n}\n\nexport function EliaEditor({\n content = '',\n onChange,\n placeholder = '開始寫作...',\n toolbar = 'all',\n header,\n toolbarStart,\n toolbarEnd,\n footer,\n className,\n editorClassName,\n autofocus = false,\n readOnly = false,\n theme = 'light',\n onThemeToggle,\n onImageUpload,\n}: EliaEditorProps) {\n const isInternalUpdate = useRef(false);\n\n const handleUpdate = useCallback(\n ({ editor }: { editor: Editor }) => {\n isInternalUpdate.current = true;\n onChange?.(editor.getHTML());\n },\n [onChange]\n );\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n heading: {\n levels: [1, 2, 3],\n },\n }),\n Placeholder.configure({\n placeholder,\n }),\n Underline,\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Link.configure({\n openOnClick: false,\n HTMLAttributes: {\n class: 'text-primary underline underline-offset-4',\n },\n }),\n TextStyle,\n Color,\n Highlight.configure({\n multicolor: true,\n }),\n Subscript,\n Superscript,\n TaskList,\n TaskItem.configure({\n nested: true,\n }),\n Table.configure({\n resizable: true,\n }),\n TableRow,\n TableHeader,\n TableCell,\n ImageResize.configure({\n allowBase64: true,\n }),\n Callout,\n ],\n content,\n autofocus,\n editable: !readOnly,\n editorProps: {\n attributes: {\n class: cn(\n 'tiptap-editor min-h-[300px] p-4 focus:outline-none',\n editorClassName\n ),\n },\n },\n onUpdate: handleUpdate,\n });\n\n useEffect(() => {\n if (editor && !isInternalUpdate.current && content !== editor.getHTML()) {\n editor.commands.setContent(content);\n }\n isInternalUpdate.current = false;\n }, [content, editor]);\n\n useEffect(() => {\n if (editor) {\n editor.setEditable(!readOnly);\n }\n }, [readOnly, editor]);\n\n return (\n <div className={cn('ori-editor', theme === 'dark' && 'dark', className)}>\n {header && <div className=\"ori-editor-header\">{header}</div>}\n\n <Toolbar\n editor={editor}\n config={toolbar}\n toolbarStart={toolbarStart}\n toolbarEnd={toolbarEnd}\n theme={theme}\n onThemeToggle={onThemeToggle}\n onImageUpload={onImageUpload}\n />\n\n <EditorContent editor={editor} />\n\n {footer && <div className=\"ori-editor-footer\">{footer}</div>}\n </div>\n );\n}\n","import { Node, mergeAttributes } from \"@tiptap/core\";\n\nexport type CalloutType = 'success' | 'warning' | 'error' | 'info';\n\nexport interface CalloutOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nconst CALLOUT_ARIA_LABELS: Record<CalloutType, string> = {\n success: '成功提示',\n warning: '警告提示',\n error: '錯誤提示',\n info: '資訊提示',\n};\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n callout: {\n setCallout: (attributes?: { type: CalloutType }) => ReturnType;\n toggleCallout: (attributes?: { type: CalloutType }) => ReturnType;\n unsetCallout: () => ReturnType;\n };\n }\n}\n\nexport const Callout = Node.create<CalloutOptions>({\n name: \"callout\",\n group: \"block\",\n content: \"block+\",\n defining: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n addAttributes() {\n return {\n type: {\n default: \"info\" as CalloutType,\n parseHTML: (element) => element.getAttribute(\"data-type\") as CalloutType,\n renderHTML: (attributes) => ({\n \"data-type\": attributes.type,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"div[data-callout]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const type = (node.attrs.type as CalloutType) || 'info';\n\n return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n \"data-callout\": \"\",\n \"class\": `callout callout-${type}`,\n \"role\": \"note\",\n \"aria-label\": CALLOUT_ARIA_LABELS[type],\n }),\n 0,\n ];\n },\n\n addCommands() {\n return {\n setCallout:\n (attributes) =>\n ({ commands }) => {\n return commands.wrapIn(this.name, attributes);\n },\n toggleCallout:\n (attributes) =>\n ({ commands }) => {\n return commands.toggleWrap(this.name, attributes);\n },\n unsetCallout:\n () =>\n ({ commands }) => {\n return commands.lift(this.name);\n },\n };\n },\n});\n","import { useRef } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport { compressImage } from '../lib/compress-image';\nimport { Button } from '../ui/button';\nimport { ToolbarButton } from './ToolbarButton';\nimport { ToolbarDivider } from './ToolbarDivider';\nimport { HeadingDropdown } from './HeadingDropdown';\nimport { ListDropdown } from './ListDropdown';\nimport { TableDropdown } from './TableDropdown';\nimport { CalloutDropdown } from './CalloutDropdown';\nimport { ColorPicker } from './ColorPicker';\nimport {\n Bold,\n Italic,\n Code,\n Underline as UnderlineIcon,\n Link as LinkIcon,\n Superscript as SuperscriptIcon,\n Subscript as SubscriptIcon,\n AlignLeft,\n AlignCenter,\n AlignRight,\n ImagePlus,\n Sun,\n Moon,\n type LucideProps,\n} from 'lucide-react';\nimport type { ComponentType } from 'react';\n\ntype ToolbarButtonConfig = {\n key: string;\n icon: ComponentType<LucideProps>;\n title: string;\n isActive: (editor: Editor) => boolean;\n action: (editor: Editor) => void;\n};\n\ntype ToolbarItem =\n | 'heading'\n | 'list'\n | 'format'\n | 'script'\n | 'align'\n | 'color'\n | 'link'\n | 'image'\n | 'table'\n | 'callout'\n | 'themeToggle';\n\ninterface ToolbarProps {\n editor: Editor | null;\n config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';\n toolbarStart?: React.ReactNode;\n toolbarEnd?: React.ReactNode;\n theme?: 'light' | 'dark';\n onThemeToggle?: () => void;\n onImageUpload?: (file: File) => Promise<string> | void;\n}\n\nconst ICON_SIZE = \"h-4 w-4\";\n\nconst TEXT_FORMAT_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"bold\", icon: Bold, title: \"粗體\", isActive: (e) => e.isActive(\"bold\"), action: (e) => (e.chain().focus() as any).toggleBold().run() },\n { key: \"italic\", icon: Italic, title: \"斜體\", isActive: (e) => e.isActive(\"italic\"), action: (e) => (e.chain().focus() as any).toggleItalic().run() },\n { key: \"code\", icon: Code, title: \"行內程式碼\", isActive: (e) => e.isActive(\"code\"), action: (e) => (e.chain().focus() as any).toggleCode().run() },\n { key: \"underline\", icon: UnderlineIcon, title: \"底線\", isActive: (e) => e.isActive(\"underline\"), action: (e) => (e.chain().focus() as any).toggleUnderline().run() },\n];\n\nconst SCRIPT_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"superscript\", icon: SuperscriptIcon, title: \"上標\", isActive: (e) => e.isActive(\"superscript\"), action: (e) => (e.chain().focus() as any).toggleSuperscript().run() },\n { key: \"subscript\", icon: SubscriptIcon, title: \"下標\", isActive: (e) => e.isActive(\"subscript\"), action: (e) => (e.chain().focus() as any).toggleSubscript().run() },\n];\n\nconst ALIGN_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"left\", icon: AlignLeft, title: \"靠左對齊\", isActive: (e) => e.isActive({ textAlign: \"left\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"left\").run() },\n { key: \"center\", icon: AlignCenter, title: \"置中對齊\", isActive: (e) => e.isActive({ textAlign: \"center\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"center\").run() },\n { key: \"right\", icon: AlignRight, title: \"靠右對齊\", isActive: (e) => e.isActive({ textAlign: \"right\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"right\").run() },\n];\n\nfunction ToolbarButtonGroup({ buttons, editor }: { buttons: ToolbarButtonConfig[]; editor: Editor }) {\n return (\n <>\n {buttons.map(({ key, icon: Icon, title, isActive, action }) => (\n <ToolbarButton\n key={key}\n pressed={isActive(editor)}\n onPressedChange={() => action(editor)}\n title={title}\n >\n <Icon className={ICON_SIZE} />\n </ToolbarButton>\n ))}\n </>\n );\n}\n\nfunction normalizeConfig(config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none'): ToolbarItem[][] {\n if (config === 'none') return [];\n if (config === 'all' || !config) {\n return [\n ['heading', 'list', 'table', 'callout'],\n ['format', 'link', 'color'],\n ['script'],\n ['align'],\n ['image'],\n ['themeToggle'],\n ];\n }\n\n if (Array.isArray(config)) {\n // 檢查是否為二維陣列\n if (config.length > 0 && Array.isArray(config[0])) {\n return config as ToolbarItem[][];\n }\n // 一維陣列,轉為二維\n return [config as ToolbarItem[]];\n }\n\n return [];\n}\n\nexport function Toolbar({\n editor,\n config,\n toolbarStart,\n toolbarEnd,\n theme,\n onThemeToggle,\n onImageUpload,\n}: ToolbarProps) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n if (!editor) return null;\n\n const groups = normalizeConfig(config);\n\n const setLink = () => {\n const previousUrl = editor.getAttributes(\"link\").href;\n const url = window.prompt(\"輸入連結網址\", previousUrl);\n\n if (url === null) return;\n if (url === \"\") {\n (editor.chain().focus().extendMarkRange(\"link\") as any).unsetLink().run();\n return;\n }\n\n (editor.chain().focus().extendMarkRange(\"link\") as any).setLink({ href: url }).run();\n };\n\n const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n try {\n const compressed = await compressImage(file);\n\n if (onImageUpload) {\n const result = onImageUpload(compressed);\n if (result instanceof Promise) {\n const url = await result;\n if (url) {\n (editor.chain().focus() as any).setImage({ src: url }).run();\n }\n }\n } else {\n const reader = new FileReader();\n reader.onload = () => {\n const base64 = reader.result as string;\n (editor.chain().focus() as any).setImage({ src: base64 }).run();\n };\n reader.onerror = () => {\n console.error(\"圖片讀取失敗\");\n };\n reader.readAsDataURL(compressed);\n }\n } catch (error) {\n console.error(\"圖片處理失敗:\", error);\n }\n\n e.target.value = \"\";\n };\n\n const renderToolbarItem = (item: ToolbarItem) => {\n switch (item) {\n case 'heading':\n return <HeadingDropdown key=\"heading\" editor={editor} iconSize={ICON_SIZE} />;\n case 'list':\n return <ListDropdown key=\"list\" editor={editor} iconSize={ICON_SIZE} />;\n case 'table':\n return <TableDropdown key=\"table\" editor={editor} iconSize={ICON_SIZE} />;\n case 'callout':\n return <CalloutDropdown key=\"callout\" editor={editor} iconSize={ICON_SIZE} />;\n case 'format':\n return <ToolbarButtonGroup key=\"format\" buttons={TEXT_FORMAT_BUTTONS} editor={editor} />;\n case 'link':\n return (\n <ToolbarButton\n key=\"link\"\n pressed={editor.isActive(\"link\")}\n onPressedChange={setLink}\n title=\"連結\"\n >\n <LinkIcon className={ICON_SIZE} />\n </ToolbarButton>\n );\n case 'color':\n return <ColorPicker key=\"color\" editor={editor} iconSize={ICON_SIZE} />;\n case 'script':\n return <ToolbarButtonGroup key=\"script\" buttons={SCRIPT_BUTTONS} editor={editor} />;\n case 'align':\n return <ToolbarButtonGroup key=\"align\" buttons={ALIGN_BUTTONS} editor={editor} />;\n case 'image':\n return (\n <Button\n key=\"image\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 px-2 gap-1\"\n onClick={() => fileInputRef.current?.click()}\n title=\"插入圖片\"\n >\n <ImagePlus className={ICON_SIZE} />\n </Button>\n );\n case 'themeToggle':\n return onThemeToggle ? (\n <Button\n key=\"themeToggle\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n onClick={onThemeToggle}\n title={theme === \"dark\" ? \"切換淺色模式\" : \"切換深色模式\"}\n >\n {theme === \"dark\" ? <Moon className={ICON_SIZE} /> : <Sun className={ICON_SIZE} />}\n </Button>\n ) : null;\n default:\n return null;\n }\n };\n\n return (\n <div className=\"flex items-center justify-center mb-2 relative\">\n <div className={`flex items-center justify-between px-2 py-1.5 rounded-lg shadow-sm w-full max-w-7xl mx-auto ${theme === 'dark' ? 'bg-zinc-900' : 'bg-white'}`}>\n <div className=\"flex items-center gap-0.5\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handleImageUpload}\n aria-label=\"上傳圖片\"\n />\n\n {toolbarStart}\n\n {groups.map((group, groupIndex) => (\n <div key={groupIndex} className=\"flex items-center gap-0.5\">\n {groupIndex > 0 && <ToolbarDivider />}\n {group.map(item => renderToolbarItem(item))}\n </div>\n ))}\n </div>\n\n <div className=\"flex items-center gap-0.5\">\n {toolbarEnd}\n </div>\n </div>\n </div>\n );\n}\n\nexport type { ToolbarProps, ToolbarItem, ToolbarButtonConfig };\n","const DEFAULT_MAX_SIZE_MB = 1;\nconst DEFAULT_MAX_DIMENSION = 1920;\nconst DEFAULT_QUALITY = 0.85;\n\ninterface CompressOptions {\n maxSizeMB?: number;\n maxDimension?: number;\n quality?: number;\n}\n\nexport async function compressImage(\n file: File,\n options: CompressOptions = {}\n): Promise<File> {\n const {\n maxSizeMB = DEFAULT_MAX_SIZE_MB,\n maxDimension = DEFAULT_MAX_DIMENSION,\n quality = DEFAULT_QUALITY,\n } = options;\n\n if (file.size <= maxSizeMB * 1024 * 1024) {\n return file;\n }\n\n const img = new Image();\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d')!;\n\n return new Promise((resolve, reject) => {\n img.onload = () => {\n let { width, height } = img;\n\n if (width > maxDimension || height > maxDimension) {\n const ratio = Math.min(maxDimension / width, maxDimension / height);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n\n canvas.width = width;\n canvas.height = height;\n ctx.drawImage(img, 0, 0, width, height);\n\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error('圖片壓縮失敗'));\n return;\n }\n resolve(new File([blob], file.name, { type: 'image/jpeg' }));\n },\n 'image/jpeg',\n quality\n );\n };\n\n img.onerror = () => reject(new Error('圖片載入失敗'));\n img.src = URL.createObjectURL(file);\n });\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'default' | 'ghost' | 'outline';\n size?: 'default' | 'sm' | 'lg';\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'default', size = 'default', ...props }, ref) => {\n const variantStyles = {\n default: 'bg-transparent text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800',\n ghost: 'hover:bg-zinc-100 dark:hover:bg-zinc-800',\n outline: 'border border-zinc-200 dark:border-zinc-700 bg-transparent hover:bg-zinc-100 dark:hover:bg-zinc-800',\n };\n\n const sizeStyles = {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 px-3 text-xs',\n lg: 'h-10 px-8',\n };\n\n return (\n <button\n className={cn(\n 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n 'disabled:pointer-events-none disabled:opacity-50',\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\n\nButton.displayName = 'Button';\n\nexport { Button };\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from 'react';\nimport * as TogglePrimitive from '@radix-ui/react-toggle';\nimport { cn } from '../lib/utils';\n\nexport interface ToggleProps extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> {\n size?: 'default' | 'sm';\n}\n\nconst Toggle = React.forwardRef<React.ElementRef<typeof TogglePrimitive.Root>, ToggleProps>(\n ({ className, size = 'default', ...props }, ref) => {\n const sizeStyles = {\n default: 'h-9 px-3',\n sm: 'h-8 px-2',\n };\n\n return (\n <TogglePrimitive.Root\n ref={ref}\n className={cn(\n 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',\n 'hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n 'disabled:pointer-events-none disabled:opacity-50',\n 'data-[state=on]:bg-[var(--accent)] data-[state=on]:text-[var(--accent-foreground)]',\n sizeStyles[size],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nToggle.displayName = TogglePrimitive.Root.displayName;\n\nexport { Toggle };\n","import { Toggle } from '../ui/toggle';\n\ninterface ToolbarButtonProps {\n pressed: boolean;\n onPressedChange: () => void;\n disabled?: boolean;\n children: React.ReactNode;\n title?: string;\n}\n\nexport function ToolbarButton({\n pressed,\n onPressedChange,\n disabled,\n children,\n title,\n}: ToolbarButtonProps) {\n return (\n <Toggle\n size=\"sm\"\n pressed={pressed}\n onPressedChange={onPressedChange}\n disabled={disabled}\n title={title}\n className=\"h-9 w-9 p-0 border-0 bg-transparent rounded-lg hover:bg-muted data-[state=on]:bg-zinc-900 data-[state=on]:text-white disabled:opacity-30\"\n >\n {children}\n </Toggle>\n );\n}\n\nexport type { ToolbarButtonProps };\n","export function ToolbarDivider() {\n return <div className=\"w-px h-5 bg-border mx-1.5\" />;\n}\n","import * as React from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { cn } from '../lib/utils';\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border border-[var(--border)] bg-[var(--popover)] p-1 text-[var(--popover-foreground)] shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors',\n 'hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)] focus:bg-[var(--accent)] focus:text-[var(--accent-foreground)]',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-[var(--border)]', className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nexport { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, Heading1, Heading2, Heading3 } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface HeadingDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function HeadingDropdown({ editor, iconSize = \"h-4 w-4\" }: HeadingDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1 font-normal\">\n <span className=\"text-sm font-semibold\">H</span>\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 1 }).run()}>\n <Heading1 className={cn(iconSize, \"mr-2\")} />\n 標題 1\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 2 }).run()}>\n <Heading2 className={cn(iconSize, \"mr-2\")} />\n 標題 2\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 3 }).run()}>\n <Heading3 className={cn(iconSize, \"mr-2\")} />\n 標題 3\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).setParagraph().run()}>\n 內文\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { HeadingDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, List, ListOrdered, ListTodo } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface ListDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function ListDropdown({ editor, iconSize = \"h-4 w-4\" }: ListDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <List className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleBulletList().run()}>\n <List className={cn(iconSize, \"mr-2\")} />\n 項目清單\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleOrderedList().run()}>\n <ListOrdered className={cn(iconSize, \"mr-2\")} />\n 編號清單\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleTaskList().run()}>\n <ListTodo className={cn(iconSize, \"mr-2\")} />\n 任務清單\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { ListDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, Plus, Trash2, Table as TableIcon } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface TableDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function TableDropdown({ editor, iconSize = \"h-4 w-4\" }: TableDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <TableIcon className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}\n >\n <Plus className={cn(iconSize, \"mr-2\")} />\n 插入表格 (3x3)\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).addColumnAfter().run()}\n disabled={!(editor.can() as any).addColumnAfter()}\n >\n 新增欄\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).addRowAfter().run()}\n disabled={!(editor.can() as any).addRowAfter()}\n >\n 新增列\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteColumn().run()}\n disabled={!(editor.can() as any).deleteColumn()}\n >\n 刪除欄\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteRow().run()}\n disabled={!(editor.can() as any).deleteRow()}\n >\n 刪除列\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteTable().run()}\n disabled={!(editor.can() as any).deleteTable()}\n className=\"text-destructive\"\n >\n <Trash2 className={cn(iconSize, \"mr-2\")} />\n 刪除表格\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { TableDropdownProps };\n","import { useState } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, MessageSquare } from 'lucide-react';\n\ninterface CalloutDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function CalloutDropdown({ editor, iconSize = \"h-4 w-4\" }: CalloutDropdownProps) {\n const [open, setOpen] = useState(false);\n\n return (\n <DropdownMenu open={open} onOpenChange={setOpen} modal={false}>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <MessageSquare className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"min-w-0 p-1.5\">\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-emerald-100 border border-emerald-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"success\" }).run();\n }, 0);\n }}\n title=\"成功提示\"\n aria-label=\"成功提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-amber-100 border border-amber-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"warning\" }).run();\n }, 0);\n }}\n title=\"警告提示\"\n aria-label=\"警告提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-red-100 border border-red-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"error\" }).run();\n }, 0);\n }}\n title=\"錯誤提示\"\n aria-label=\"錯誤提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-sky-100 border border-sky-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"info\" }).run();\n }, 0);\n }}\n title=\"資訊提示\"\n aria-label=\"資訊提示\"\n />\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { CalloutDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { Palette, X } from 'lucide-react';\n\nconst COLOR_PALETTE = [\n { name: \"黑色\", value: \"#000000\" },\n { name: \"灰色\", value: \"#6B7280\" },\n { name: \"紅色\", value: \"#EF4444\" },\n { name: \"橙色\", value: \"#F97316\" },\n { name: \"黃色\", value: \"#EAB308\" },\n { name: \"綠色\", value: \"#22C55E\" },\n { name: \"藍色\", value: \"#3B82F6\" },\n { name: \"紫色\", value: \"#8B5CF6\" },\n];\n\ninterface ColorPickerProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function ColorPicker({ editor, iconSize = \"h-4 w-4\" }: ColorPickerProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\" title=\"顏色\">\n <Palette className={iconSize} />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-72\">\n <div className=\"p-2\">\n <div className=\"text-xs font-medium text-muted-foreground mb-2\">文字顏色</div>\n <div className=\"flex gap-1.5 mb-3\">\n {COLOR_PALETTE.map((color) => (\n <button\n key={`text-${color.value}`}\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border hover:scale-110 transition-transform\"\n style={{ backgroundColor: color.value }}\n onClick={() => (editor.chain().focus() as any).setColor(color.value).run()}\n title={color.name}\n aria-label={`文字顏色:${color.name}`}\n />\n ))}\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border hover:scale-110 transition-transform flex items-center justify-center bg-background\"\n onClick={() => (editor.chain().focus() as any).unsetColor().run()}\n title=\"清除文字顏色\"\n aria-label=\"清除文字顏色\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </div>\n\n <DropdownMenuSeparator />\n\n <div className=\"text-xs font-medium text-muted-foreground mb-2 mt-2\">背景色</div>\n <div className=\"flex gap-1.5\">\n {COLOR_PALETTE.map((color) => (\n <button\n key={`bg-${color.value}`}\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border hover:scale-110 transition-transform\"\n style={{ backgroundColor: color.value }}\n onClick={() => (editor.chain().focus() as any).toggleHighlight({ color: color.value }).run()}\n title={color.name}\n aria-label={`背景色:${color.name}`}\n />\n ))}\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border hover:scale-110 transition-transform flex items-center justify-center bg-background\"\n onClick={() => (editor.chain().focus() as any).unsetHighlight().run()}\n title=\"清除背景色\"\n aria-label=\"清除背景色\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </div>\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { ColorPickerProps };\nexport { COLOR_PALETTE };\n"],"mappings":"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","names":["import_react","import_react","React","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","TableIcon","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","UnderlineIcon","SuperscriptIcon","SubscriptIcon","LinkIcon","import_jsx_runtime","editor","StarterKit","Placeholder","Underline","TextAlign","Link","Subscript","Superscript","TaskList","TaskItem","ImageResize"]}
package/dist/index.js CHANGED
@@ -220,7 +220,7 @@ function ToolbarButton({
220
220
  onPressedChange,
221
221
  disabled,
222
222
  title,
223
- className: "h-9 w-9 p-0 border-0 bg-transparent rounded-lg hover:bg-muted data-[state=on]:bg-zinc-900 data-[state=on]:text-white dark:data-[state=on]:bg-zinc-100 dark:data-[state=on]:text-zinc-900 disabled:opacity-30",
223
+ className: "h-9 w-9 p-0 border-0 bg-transparent rounded-lg hover:bg-muted data-[state=on]:bg-zinc-900 data-[state=on]:text-white disabled:opacity-30",
224
224
  children
225
225
  }
226
226
  );
@@ -500,7 +500,7 @@ function ColorPicker({ editor, iconSize = "h-4 w-4" }) {
500
500
  "button",
501
501
  {
502
502
  type: "button",
503
- className: "w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform",
503
+ className: "w-6 h-6 rounded border border-border hover:scale-110 transition-transform",
504
504
  style: { backgroundColor: color.value },
505
505
  onClick: () => editor.chain().focus().setColor(color.value).run(),
506
506
  title: color.name,
@@ -512,7 +512,7 @@ function ColorPicker({ editor, iconSize = "h-4 w-4" }) {
512
512
  "button",
513
513
  {
514
514
  type: "button",
515
- className: "w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform flex items-center justify-center bg-background",
515
+ className: "w-6 h-6 rounded border border-border hover:scale-110 transition-transform flex items-center justify-center bg-background",
516
516
  onClick: () => editor.chain().focus().unsetColor().run(),
517
517
  title: "\u6E05\u9664\u6587\u5B57\u984F\u8272",
518
518
  "aria-label": "\u6E05\u9664\u6587\u5B57\u984F\u8272",
@@ -527,7 +527,7 @@ function ColorPicker({ editor, iconSize = "h-4 w-4" }) {
527
527
  "button",
528
528
  {
529
529
  type: "button",
530
- className: "w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform",
530
+ className: "w-6 h-6 rounded border border-border hover:scale-110 transition-transform",
531
531
  style: { backgroundColor: color.value },
532
532
  onClick: () => editor.chain().focus().toggleHighlight({ color: color.value }).run(),
533
533
  title: color.name,
@@ -539,7 +539,7 @@ function ColorPicker({ editor, iconSize = "h-4 w-4" }) {
539
539
  "button",
540
540
  {
541
541
  type: "button",
542
- className: "w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform flex items-center justify-center bg-background",
542
+ className: "w-6 h-6 rounded border border-border hover:scale-110 transition-transform flex items-center justify-center bg-background",
543
543
  onClick: () => editor.chain().focus().unsetHighlight().run(),
544
544
  title: "\u6E05\u9664\u80CC\u666F\u8272",
545
545
  "aria-label": "\u6E05\u9664\u80CC\u666F\u8272",
@@ -726,7 +726,7 @@ function Toolbar({
726
726
  return null;
727
727
  }
728
728
  };
729
- return /* @__PURE__ */ jsx11("div", { className: "flex items-center justify-center mb-2 relative", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between px-2 py-1.5 bg-white dark:bg-zinc-900 rounded-lg shadow-sm w-full max-w-7xl mx-auto", children: [
729
+ return /* @__PURE__ */ jsx11("div", { className: "flex items-center justify-center mb-2 relative", children: /* @__PURE__ */ jsxs6("div", { className: `flex items-center justify-between px-2 py-1.5 rounded-lg shadow-sm w-full max-w-7xl mx-auto ${theme === "dark" ? "bg-zinc-900" : "bg-white"}`, children: [
730
730
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-0.5", children: [
731
731
  /* @__PURE__ */ jsx11(
732
732
  "input",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/EliaEditor.tsx","../src/extensions/callout.ts","../src/components/Toolbar.tsx","../src/lib/compress-image.ts","../src/ui/button.tsx","../src/lib/utils.ts","../src/ui/toggle.tsx","../src/components/ToolbarButton.tsx","../src/components/ToolbarDivider.tsx","../src/ui/dropdown-menu.tsx","../src/components/HeadingDropdown.tsx","../src/components/ListDropdown.tsx","../src/components/TableDropdown.tsx","../src/components/CalloutDropdown.tsx","../src/components/ColorPicker.tsx"],"sourcesContent":["import { useRef, useEffect, useCallback } from 'react';\nimport { useEditor, EditorContent, type Editor } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport Underline from '@tiptap/extension-underline';\nimport TextAlign from '@tiptap/extension-text-align';\nimport Link from '@tiptap/extension-link';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport { Color } from '@tiptap/extension-color';\nimport { Highlight } from '@tiptap/extension-highlight';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport TaskList from '@tiptap/extension-task-list';\nimport TaskItem from '@tiptap/extension-task-item';\nimport { Table } from '@tiptap/extension-table';\nimport { TableRow } from '@tiptap/extension-table-row';\nimport { TableHeader } from '@tiptap/extension-table-header';\nimport { TableCell } from '@tiptap/extension-table-cell';\nimport ImageResize from 'tiptap-extension-resize-image';\nimport { Callout } from './extensions/callout';\nimport { Toolbar, type ToolbarItem } from './components/Toolbar';\nimport { cn } from './lib/utils';\n\nexport interface EliaEditorProps {\n // 內容\n content?: string;\n onChange?: (html: string) => void;\n placeholder?: string;\n\n // Toolbar 配置\n toolbar?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';\n\n // 插槽\n header?: React.ReactNode;\n toolbarStart?: React.ReactNode;\n toolbarEnd?: React.ReactNode;\n footer?: React.ReactNode;\n\n // 樣式\n className?: string;\n editorClassName?: string;\n\n // 其他\n autofocus?: boolean;\n readOnly?: boolean;\n\n // Toolbar 相關\n theme?: 'light' | 'dark';\n onThemeToggle?: () => void;\n onImageUpload?: (file: File) => Promise<string> | void;\n}\n\nexport function EliaEditor({\n content = '',\n onChange,\n placeholder = '開始寫作...',\n toolbar = 'all',\n header,\n toolbarStart,\n toolbarEnd,\n footer,\n className,\n editorClassName,\n autofocus = false,\n readOnly = false,\n theme = 'light',\n onThemeToggle,\n onImageUpload,\n}: EliaEditorProps) {\n const isInternalUpdate = useRef(false);\n\n const handleUpdate = useCallback(\n ({ editor }: { editor: Editor }) => {\n isInternalUpdate.current = true;\n onChange?.(editor.getHTML());\n },\n [onChange]\n );\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n heading: {\n levels: [1, 2, 3],\n },\n }),\n Placeholder.configure({\n placeholder,\n }),\n Underline,\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Link.configure({\n openOnClick: false,\n HTMLAttributes: {\n class: 'text-primary underline underline-offset-4',\n },\n }),\n TextStyle,\n Color,\n Highlight.configure({\n multicolor: true,\n }),\n Subscript,\n Superscript,\n TaskList,\n TaskItem.configure({\n nested: true,\n }),\n Table.configure({\n resizable: true,\n }),\n TableRow,\n TableHeader,\n TableCell,\n ImageResize.configure({\n allowBase64: true,\n }),\n Callout,\n ],\n content,\n autofocus,\n editable: !readOnly,\n editorProps: {\n attributes: {\n class: cn(\n 'tiptap-editor min-h-[300px] p-4 focus:outline-none',\n editorClassName\n ),\n },\n },\n onUpdate: handleUpdate,\n });\n\n useEffect(() => {\n if (editor && !isInternalUpdate.current && content !== editor.getHTML()) {\n editor.commands.setContent(content);\n }\n isInternalUpdate.current = false;\n }, [content, editor]);\n\n useEffect(() => {\n if (editor) {\n editor.setEditable(!readOnly);\n }\n }, [readOnly, editor]);\n\n return (\n <div className={cn('ori-editor', theme === 'dark' && 'dark', className)}>\n {header && <div className=\"ori-editor-header\">{header}</div>}\n\n <Toolbar\n editor={editor}\n config={toolbar}\n toolbarStart={toolbarStart}\n toolbarEnd={toolbarEnd}\n theme={theme}\n onThemeToggle={onThemeToggle}\n onImageUpload={onImageUpload}\n />\n\n <EditorContent editor={editor} />\n\n {footer && <div className=\"ori-editor-footer\">{footer}</div>}\n </div>\n );\n}\n","import { Node, mergeAttributes } from \"@tiptap/core\";\n\nexport type CalloutType = 'success' | 'warning' | 'error' | 'info';\n\nexport interface CalloutOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nconst CALLOUT_ARIA_LABELS: Record<CalloutType, string> = {\n success: '成功提示',\n warning: '警告提示',\n error: '錯誤提示',\n info: '資訊提示',\n};\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n callout: {\n setCallout: (attributes?: { type: CalloutType }) => ReturnType;\n toggleCallout: (attributes?: { type: CalloutType }) => ReturnType;\n unsetCallout: () => ReturnType;\n };\n }\n}\n\nexport const Callout = Node.create<CalloutOptions>({\n name: \"callout\",\n group: \"block\",\n content: \"block+\",\n defining: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n addAttributes() {\n return {\n type: {\n default: \"info\" as CalloutType,\n parseHTML: (element) => element.getAttribute(\"data-type\") as CalloutType,\n renderHTML: (attributes) => ({\n \"data-type\": attributes.type,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"div[data-callout]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const type = (node.attrs.type as CalloutType) || 'info';\n\n return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n \"data-callout\": \"\",\n \"class\": `callout callout-${type}`,\n \"role\": \"note\",\n \"aria-label\": CALLOUT_ARIA_LABELS[type],\n }),\n 0,\n ];\n },\n\n addCommands() {\n return {\n setCallout:\n (attributes) =>\n ({ commands }) => {\n return commands.wrapIn(this.name, attributes);\n },\n toggleCallout:\n (attributes) =>\n ({ commands }) => {\n return commands.toggleWrap(this.name, attributes);\n },\n unsetCallout:\n () =>\n ({ commands }) => {\n return commands.lift(this.name);\n },\n };\n },\n});\n","import { useRef } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport { compressImage } from '../lib/compress-image';\nimport { Button } from '../ui/button';\nimport { ToolbarButton } from './ToolbarButton';\nimport { ToolbarDivider } from './ToolbarDivider';\nimport { HeadingDropdown } from './HeadingDropdown';\nimport { ListDropdown } from './ListDropdown';\nimport { TableDropdown } from './TableDropdown';\nimport { CalloutDropdown } from './CalloutDropdown';\nimport { ColorPicker } from './ColorPicker';\nimport {\n Bold,\n Italic,\n Code,\n Underline as UnderlineIcon,\n Link as LinkIcon,\n Superscript as SuperscriptIcon,\n Subscript as SubscriptIcon,\n AlignLeft,\n AlignCenter,\n AlignRight,\n ImagePlus,\n Sun,\n Moon,\n type LucideProps,\n} from 'lucide-react';\nimport type { ComponentType } from 'react';\n\ntype ToolbarButtonConfig = {\n key: string;\n icon: ComponentType<LucideProps>;\n title: string;\n isActive: (editor: Editor) => boolean;\n action: (editor: Editor) => void;\n};\n\ntype ToolbarItem =\n | 'heading'\n | 'list'\n | 'format'\n | 'script'\n | 'align'\n | 'color'\n | 'link'\n | 'image'\n | 'table'\n | 'callout'\n | 'themeToggle';\n\ninterface ToolbarProps {\n editor: Editor | null;\n config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';\n toolbarStart?: React.ReactNode;\n toolbarEnd?: React.ReactNode;\n theme?: 'light' | 'dark';\n onThemeToggle?: () => void;\n onImageUpload?: (file: File) => Promise<string> | void;\n}\n\nconst ICON_SIZE = \"h-4 w-4\";\n\nconst TEXT_FORMAT_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"bold\", icon: Bold, title: \"粗體\", isActive: (e) => e.isActive(\"bold\"), action: (e) => (e.chain().focus() as any).toggleBold().run() },\n { key: \"italic\", icon: Italic, title: \"斜體\", isActive: (e) => e.isActive(\"italic\"), action: (e) => (e.chain().focus() as any).toggleItalic().run() },\n { key: \"code\", icon: Code, title: \"行內程式碼\", isActive: (e) => e.isActive(\"code\"), action: (e) => (e.chain().focus() as any).toggleCode().run() },\n { key: \"underline\", icon: UnderlineIcon, title: \"底線\", isActive: (e) => e.isActive(\"underline\"), action: (e) => (e.chain().focus() as any).toggleUnderline().run() },\n];\n\nconst SCRIPT_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"superscript\", icon: SuperscriptIcon, title: \"上標\", isActive: (e) => e.isActive(\"superscript\"), action: (e) => (e.chain().focus() as any).toggleSuperscript().run() },\n { key: \"subscript\", icon: SubscriptIcon, title: \"下標\", isActive: (e) => e.isActive(\"subscript\"), action: (e) => (e.chain().focus() as any).toggleSubscript().run() },\n];\n\nconst ALIGN_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"left\", icon: AlignLeft, title: \"靠左對齊\", isActive: (e) => e.isActive({ textAlign: \"left\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"left\").run() },\n { key: \"center\", icon: AlignCenter, title: \"置中對齊\", isActive: (e) => e.isActive({ textAlign: \"center\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"center\").run() },\n { key: \"right\", icon: AlignRight, title: \"靠右對齊\", isActive: (e) => e.isActive({ textAlign: \"right\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"right\").run() },\n];\n\nfunction ToolbarButtonGroup({ buttons, editor }: { buttons: ToolbarButtonConfig[]; editor: Editor }) {\n return (\n <>\n {buttons.map(({ key, icon: Icon, title, isActive, action }) => (\n <ToolbarButton\n key={key}\n pressed={isActive(editor)}\n onPressedChange={() => action(editor)}\n title={title}\n >\n <Icon className={ICON_SIZE} />\n </ToolbarButton>\n ))}\n </>\n );\n}\n\nfunction normalizeConfig(config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none'): ToolbarItem[][] {\n if (config === 'none') return [];\n if (config === 'all' || !config) {\n return [\n ['heading', 'list', 'table', 'callout'],\n ['format', 'link', 'color'],\n ['script'],\n ['align'],\n ['image'],\n ['themeToggle'],\n ];\n }\n\n if (Array.isArray(config)) {\n // 檢查是否為二維陣列\n if (config.length > 0 && Array.isArray(config[0])) {\n return config as ToolbarItem[][];\n }\n // 一維陣列,轉為二維\n return [config as ToolbarItem[]];\n }\n\n return [];\n}\n\nexport function Toolbar({\n editor,\n config,\n toolbarStart,\n toolbarEnd,\n theme,\n onThemeToggle,\n onImageUpload,\n}: ToolbarProps) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n if (!editor) return null;\n\n const groups = normalizeConfig(config);\n\n const setLink = () => {\n const previousUrl = editor.getAttributes(\"link\").href;\n const url = window.prompt(\"輸入連結網址\", previousUrl);\n\n if (url === null) return;\n if (url === \"\") {\n (editor.chain().focus().extendMarkRange(\"link\") as any).unsetLink().run();\n return;\n }\n\n (editor.chain().focus().extendMarkRange(\"link\") as any).setLink({ href: url }).run();\n };\n\n const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n try {\n const compressed = await compressImage(file);\n\n if (onImageUpload) {\n const result = onImageUpload(compressed);\n if (result instanceof Promise) {\n const url = await result;\n if (url) {\n (editor.chain().focus() as any).setImage({ src: url }).run();\n }\n }\n } else {\n const reader = new FileReader();\n reader.onload = () => {\n const base64 = reader.result as string;\n (editor.chain().focus() as any).setImage({ src: base64 }).run();\n };\n reader.onerror = () => {\n console.error(\"圖片讀取失敗\");\n };\n reader.readAsDataURL(compressed);\n }\n } catch (error) {\n console.error(\"圖片處理失敗:\", error);\n }\n\n e.target.value = \"\";\n };\n\n const renderToolbarItem = (item: ToolbarItem) => {\n switch (item) {\n case 'heading':\n return <HeadingDropdown key=\"heading\" editor={editor} iconSize={ICON_SIZE} />;\n case 'list':\n return <ListDropdown key=\"list\" editor={editor} iconSize={ICON_SIZE} />;\n case 'table':\n return <TableDropdown key=\"table\" editor={editor} iconSize={ICON_SIZE} />;\n case 'callout':\n return <CalloutDropdown key=\"callout\" editor={editor} iconSize={ICON_SIZE} />;\n case 'format':\n return <ToolbarButtonGroup key=\"format\" buttons={TEXT_FORMAT_BUTTONS} editor={editor} />;\n case 'link':\n return (\n <ToolbarButton\n key=\"link\"\n pressed={editor.isActive(\"link\")}\n onPressedChange={setLink}\n title=\"連結\"\n >\n <LinkIcon className={ICON_SIZE} />\n </ToolbarButton>\n );\n case 'color':\n return <ColorPicker key=\"color\" editor={editor} iconSize={ICON_SIZE} />;\n case 'script':\n return <ToolbarButtonGroup key=\"script\" buttons={SCRIPT_BUTTONS} editor={editor} />;\n case 'align':\n return <ToolbarButtonGroup key=\"align\" buttons={ALIGN_BUTTONS} editor={editor} />;\n case 'image':\n return (\n <Button\n key=\"image\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 px-2 gap-1\"\n onClick={() => fileInputRef.current?.click()}\n title=\"插入圖片\"\n >\n <ImagePlus className={ICON_SIZE} />\n </Button>\n );\n case 'themeToggle':\n return onThemeToggle ? (\n <Button\n key=\"themeToggle\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n onClick={onThemeToggle}\n title={theme === \"dark\" ? \"切換淺色模式\" : \"切換深色模式\"}\n >\n {theme === \"dark\" ? <Moon className={ICON_SIZE} /> : <Sun className={ICON_SIZE} />}\n </Button>\n ) : null;\n default:\n return null;\n }\n };\n\n return (\n <div className=\"flex items-center justify-center mb-2 relative\">\n <div className=\"flex items-center justify-between px-2 py-1.5 bg-white dark:bg-zinc-900 rounded-lg shadow-sm w-full max-w-7xl mx-auto\">\n <div className=\"flex items-center gap-0.5\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handleImageUpload}\n aria-label=\"上傳圖片\"\n />\n\n {toolbarStart}\n\n {groups.map((group, groupIndex) => (\n <div key={groupIndex} className=\"flex items-center gap-0.5\">\n {groupIndex > 0 && <ToolbarDivider />}\n {group.map(item => renderToolbarItem(item))}\n </div>\n ))}\n </div>\n\n <div className=\"flex items-center gap-0.5\">\n {toolbarEnd}\n </div>\n </div>\n </div>\n );\n}\n\nexport type { ToolbarProps, ToolbarItem, ToolbarButtonConfig };\n","const DEFAULT_MAX_SIZE_MB = 1;\nconst DEFAULT_MAX_DIMENSION = 1920;\nconst DEFAULT_QUALITY = 0.85;\n\ninterface CompressOptions {\n maxSizeMB?: number;\n maxDimension?: number;\n quality?: number;\n}\n\nexport async function compressImage(\n file: File,\n options: CompressOptions = {}\n): Promise<File> {\n const {\n maxSizeMB = DEFAULT_MAX_SIZE_MB,\n maxDimension = DEFAULT_MAX_DIMENSION,\n quality = DEFAULT_QUALITY,\n } = options;\n\n if (file.size <= maxSizeMB * 1024 * 1024) {\n return file;\n }\n\n const img = new Image();\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d')!;\n\n return new Promise((resolve, reject) => {\n img.onload = () => {\n let { width, height } = img;\n\n if (width > maxDimension || height > maxDimension) {\n const ratio = Math.min(maxDimension / width, maxDimension / height);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n\n canvas.width = width;\n canvas.height = height;\n ctx.drawImage(img, 0, 0, width, height);\n\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error('圖片壓縮失敗'));\n return;\n }\n resolve(new File([blob], file.name, { type: 'image/jpeg' }));\n },\n 'image/jpeg',\n quality\n );\n };\n\n img.onerror = () => reject(new Error('圖片載入失敗'));\n img.src = URL.createObjectURL(file);\n });\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'default' | 'ghost' | 'outline';\n size?: 'default' | 'sm' | 'lg';\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'default', size = 'default', ...props }, ref) => {\n const variantStyles = {\n default: 'bg-transparent text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800',\n ghost: 'hover:bg-zinc-100 dark:hover:bg-zinc-800',\n outline: 'border border-zinc-200 dark:border-zinc-700 bg-transparent hover:bg-zinc-100 dark:hover:bg-zinc-800',\n };\n\n const sizeStyles = {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 px-3 text-xs',\n lg: 'h-10 px-8',\n };\n\n return (\n <button\n className={cn(\n 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n 'disabled:pointer-events-none disabled:opacity-50',\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\n\nButton.displayName = 'Button';\n\nexport { Button };\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from 'react';\nimport * as TogglePrimitive from '@radix-ui/react-toggle';\nimport { cn } from '../lib/utils';\n\nexport interface ToggleProps extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> {\n size?: 'default' | 'sm';\n}\n\nconst Toggle = React.forwardRef<React.ElementRef<typeof TogglePrimitive.Root>, ToggleProps>(\n ({ className, size = 'default', ...props }, ref) => {\n const sizeStyles = {\n default: 'h-9 px-3',\n sm: 'h-8 px-2',\n };\n\n return (\n <TogglePrimitive.Root\n ref={ref}\n className={cn(\n 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',\n 'hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n 'disabled:pointer-events-none disabled:opacity-50',\n 'data-[state=on]:bg-[var(--accent)] data-[state=on]:text-[var(--accent-foreground)]',\n sizeStyles[size],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nToggle.displayName = TogglePrimitive.Root.displayName;\n\nexport { Toggle };\n","import { Toggle } from '../ui/toggle';\n\ninterface ToolbarButtonProps {\n pressed: boolean;\n onPressedChange: () => void;\n disabled?: boolean;\n children: React.ReactNode;\n title?: string;\n}\n\nexport function ToolbarButton({\n pressed,\n onPressedChange,\n disabled,\n children,\n title,\n}: ToolbarButtonProps) {\n return (\n <Toggle\n size=\"sm\"\n pressed={pressed}\n onPressedChange={onPressedChange}\n disabled={disabled}\n title={title}\n className=\"h-9 w-9 p-0 border-0 bg-transparent rounded-lg hover:bg-muted data-[state=on]:bg-zinc-900 data-[state=on]:text-white dark:data-[state=on]:bg-zinc-100 dark:data-[state=on]:text-zinc-900 disabled:opacity-30\"\n >\n {children}\n </Toggle>\n );\n}\n\nexport type { ToolbarButtonProps };\n","export function ToolbarDivider() {\n return <div className=\"w-px h-5 bg-border mx-1.5\" />;\n}\n","import * as React from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { cn } from '../lib/utils';\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border border-[var(--border)] bg-[var(--popover)] p-1 text-[var(--popover-foreground)] shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors',\n 'hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)] focus:bg-[var(--accent)] focus:text-[var(--accent-foreground)]',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-[var(--border)]', className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nexport { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, Heading1, Heading2, Heading3 } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface HeadingDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function HeadingDropdown({ editor, iconSize = \"h-4 w-4\" }: HeadingDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1 font-normal\">\n <span className=\"text-sm font-semibold\">H</span>\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 1 }).run()}>\n <Heading1 className={cn(iconSize, \"mr-2\")} />\n 標題 1\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 2 }).run()}>\n <Heading2 className={cn(iconSize, \"mr-2\")} />\n 標題 2\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 3 }).run()}>\n <Heading3 className={cn(iconSize, \"mr-2\")} />\n 標題 3\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).setParagraph().run()}>\n 內文\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { HeadingDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, List, ListOrdered, ListTodo } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface ListDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function ListDropdown({ editor, iconSize = \"h-4 w-4\" }: ListDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <List className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleBulletList().run()}>\n <List className={cn(iconSize, \"mr-2\")} />\n 項目清單\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleOrderedList().run()}>\n <ListOrdered className={cn(iconSize, \"mr-2\")} />\n 編號清單\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleTaskList().run()}>\n <ListTodo className={cn(iconSize, \"mr-2\")} />\n 任務清單\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { ListDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, Plus, Trash2, Table as TableIcon } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface TableDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function TableDropdown({ editor, iconSize = \"h-4 w-4\" }: TableDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <TableIcon className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}\n >\n <Plus className={cn(iconSize, \"mr-2\")} />\n 插入表格 (3x3)\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).addColumnAfter().run()}\n disabled={!(editor.can() as any).addColumnAfter()}\n >\n 新增欄\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).addRowAfter().run()}\n disabled={!(editor.can() as any).addRowAfter()}\n >\n 新增列\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteColumn().run()}\n disabled={!(editor.can() as any).deleteColumn()}\n >\n 刪除欄\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteRow().run()}\n disabled={!(editor.can() as any).deleteRow()}\n >\n 刪除列\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteTable().run()}\n disabled={!(editor.can() as any).deleteTable()}\n className=\"text-destructive\"\n >\n <Trash2 className={cn(iconSize, \"mr-2\")} />\n 刪除表格\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { TableDropdownProps };\n","import { useState } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, MessageSquare } from 'lucide-react';\n\ninterface CalloutDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function CalloutDropdown({ editor, iconSize = \"h-4 w-4\" }: CalloutDropdownProps) {\n const [open, setOpen] = useState(false);\n\n return (\n <DropdownMenu open={open} onOpenChange={setOpen} modal={false}>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <MessageSquare className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"min-w-0 p-1.5\">\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-emerald-100 border border-emerald-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"success\" }).run();\n }, 0);\n }}\n title=\"成功提示\"\n aria-label=\"成功提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-amber-100 border border-amber-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"warning\" }).run();\n }, 0);\n }}\n title=\"警告提示\"\n aria-label=\"警告提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-red-100 border border-red-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"error\" }).run();\n }, 0);\n }}\n title=\"錯誤提示\"\n aria-label=\"錯誤提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-sky-100 border border-sky-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"info\" }).run();\n }, 0);\n }}\n title=\"資訊提示\"\n aria-label=\"資訊提示\"\n />\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { CalloutDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { Palette, X } from 'lucide-react';\n\nconst COLOR_PALETTE = [\n { name: \"黑色\", value: \"#000000\" },\n { name: \"灰色\", value: \"#6B7280\" },\n { name: \"紅色\", value: \"#EF4444\" },\n { name: \"橙色\", value: \"#F97316\" },\n { name: \"黃色\", value: \"#EAB308\" },\n { name: \"綠色\", value: \"#22C55E\" },\n { name: \"藍色\", value: \"#3B82F6\" },\n { name: \"紫色\", value: \"#8B5CF6\" },\n];\n\ninterface ColorPickerProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function ColorPicker({ editor, iconSize = \"h-4 w-4\" }: ColorPickerProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\" title=\"顏色\">\n <Palette className={iconSize} />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-72\">\n <div className=\"p-2\">\n <div className=\"text-xs font-medium text-muted-foreground mb-2\">文字顏色</div>\n <div className=\"flex gap-1.5 mb-3\">\n {COLOR_PALETTE.map((color) => (\n <button\n key={`text-${color.value}`}\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform\"\n style={{ backgroundColor: color.value }}\n onClick={() => (editor.chain().focus() as any).setColor(color.value).run()}\n title={color.name}\n aria-label={`文字顏色:${color.name}`}\n />\n ))}\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform flex items-center justify-center bg-background\"\n onClick={() => (editor.chain().focus() as any).unsetColor().run()}\n title=\"清除文字顏色\"\n aria-label=\"清除文字顏色\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </div>\n\n <DropdownMenuSeparator />\n\n <div className=\"text-xs font-medium text-muted-foreground mb-2 mt-2\">背景色</div>\n <div className=\"flex gap-1.5\">\n {COLOR_PALETTE.map((color) => (\n <button\n key={`bg-${color.value}`}\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform\"\n style={{ backgroundColor: color.value }}\n onClick={() => (editor.chain().focus() as any).toggleHighlight({ color: color.value }).run()}\n title={color.name}\n aria-label={`背景色:${color.name}`}\n />\n ))}\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border dark:border-zinc-600 hover:scale-110 transition-transform flex items-center justify-center bg-background\"\n onClick={() => (editor.chain().focus() as any).unsetHighlight().run()}\n title=\"清除背景色\"\n aria-label=\"清除背景色\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </div>\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { ColorPickerProps };\nexport { COLOR_PALETTE };\n"],"mappings":"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","names":["useRef","React","jsx","jsx","jsx","React","jsx","jsx","ChevronDown","jsx","jsxs","ChevronDown","ChevronDown","jsx","jsxs","ChevronDown","ChevronDown","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","useRef","editor"]}
1
+ {"version":3,"sources":["../src/EliaEditor.tsx","../src/extensions/callout.ts","../src/components/Toolbar.tsx","../src/lib/compress-image.ts","../src/ui/button.tsx","../src/lib/utils.ts","../src/ui/toggle.tsx","../src/components/ToolbarButton.tsx","../src/components/ToolbarDivider.tsx","../src/ui/dropdown-menu.tsx","../src/components/HeadingDropdown.tsx","../src/components/ListDropdown.tsx","../src/components/TableDropdown.tsx","../src/components/CalloutDropdown.tsx","../src/components/ColorPicker.tsx"],"sourcesContent":["import { useRef, useEffect, useCallback } from 'react';\nimport { useEditor, EditorContent, type Editor } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport Underline from '@tiptap/extension-underline';\nimport TextAlign from '@tiptap/extension-text-align';\nimport Link from '@tiptap/extension-link';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport { Color } from '@tiptap/extension-color';\nimport { Highlight } from '@tiptap/extension-highlight';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport TaskList from '@tiptap/extension-task-list';\nimport TaskItem from '@tiptap/extension-task-item';\nimport { Table } from '@tiptap/extension-table';\nimport { TableRow } from '@tiptap/extension-table-row';\nimport { TableHeader } from '@tiptap/extension-table-header';\nimport { TableCell } from '@tiptap/extension-table-cell';\nimport ImageResize from 'tiptap-extension-resize-image';\nimport { Callout } from './extensions/callout';\nimport { Toolbar, type ToolbarItem } from './components/Toolbar';\nimport { cn } from './lib/utils';\n\nexport interface EliaEditorProps {\n // 內容\n content?: string;\n onChange?: (html: string) => void;\n placeholder?: string;\n\n // Toolbar 配置\n toolbar?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';\n\n // 插槽\n header?: React.ReactNode;\n toolbarStart?: React.ReactNode;\n toolbarEnd?: React.ReactNode;\n footer?: React.ReactNode;\n\n // 樣式\n className?: string;\n editorClassName?: string;\n\n // 其他\n autofocus?: boolean;\n readOnly?: boolean;\n\n // Toolbar 相關\n theme?: 'light' | 'dark';\n onThemeToggle?: () => void;\n onImageUpload?: (file: File) => Promise<string> | void;\n}\n\nexport function EliaEditor({\n content = '',\n onChange,\n placeholder = '開始寫作...',\n toolbar = 'all',\n header,\n toolbarStart,\n toolbarEnd,\n footer,\n className,\n editorClassName,\n autofocus = false,\n readOnly = false,\n theme = 'light',\n onThemeToggle,\n onImageUpload,\n}: EliaEditorProps) {\n const isInternalUpdate = useRef(false);\n\n const handleUpdate = useCallback(\n ({ editor }: { editor: Editor }) => {\n isInternalUpdate.current = true;\n onChange?.(editor.getHTML());\n },\n [onChange]\n );\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n heading: {\n levels: [1, 2, 3],\n },\n }),\n Placeholder.configure({\n placeholder,\n }),\n Underline,\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Link.configure({\n openOnClick: false,\n HTMLAttributes: {\n class: 'text-primary underline underline-offset-4',\n },\n }),\n TextStyle,\n Color,\n Highlight.configure({\n multicolor: true,\n }),\n Subscript,\n Superscript,\n TaskList,\n TaskItem.configure({\n nested: true,\n }),\n Table.configure({\n resizable: true,\n }),\n TableRow,\n TableHeader,\n TableCell,\n ImageResize.configure({\n allowBase64: true,\n }),\n Callout,\n ],\n content,\n autofocus,\n editable: !readOnly,\n editorProps: {\n attributes: {\n class: cn(\n 'tiptap-editor min-h-[300px] p-4 focus:outline-none',\n editorClassName\n ),\n },\n },\n onUpdate: handleUpdate,\n });\n\n useEffect(() => {\n if (editor && !isInternalUpdate.current && content !== editor.getHTML()) {\n editor.commands.setContent(content);\n }\n isInternalUpdate.current = false;\n }, [content, editor]);\n\n useEffect(() => {\n if (editor) {\n editor.setEditable(!readOnly);\n }\n }, [readOnly, editor]);\n\n return (\n <div className={cn('ori-editor', theme === 'dark' && 'dark', className)}>\n {header && <div className=\"ori-editor-header\">{header}</div>}\n\n <Toolbar\n editor={editor}\n config={toolbar}\n toolbarStart={toolbarStart}\n toolbarEnd={toolbarEnd}\n theme={theme}\n onThemeToggle={onThemeToggle}\n onImageUpload={onImageUpload}\n />\n\n <EditorContent editor={editor} />\n\n {footer && <div className=\"ori-editor-footer\">{footer}</div>}\n </div>\n );\n}\n","import { Node, mergeAttributes } from \"@tiptap/core\";\n\nexport type CalloutType = 'success' | 'warning' | 'error' | 'info';\n\nexport interface CalloutOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nconst CALLOUT_ARIA_LABELS: Record<CalloutType, string> = {\n success: '成功提示',\n warning: '警告提示',\n error: '錯誤提示',\n info: '資訊提示',\n};\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n callout: {\n setCallout: (attributes?: { type: CalloutType }) => ReturnType;\n toggleCallout: (attributes?: { type: CalloutType }) => ReturnType;\n unsetCallout: () => ReturnType;\n };\n }\n}\n\nexport const Callout = Node.create<CalloutOptions>({\n name: \"callout\",\n group: \"block\",\n content: \"block+\",\n defining: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n addAttributes() {\n return {\n type: {\n default: \"info\" as CalloutType,\n parseHTML: (element) => element.getAttribute(\"data-type\") as CalloutType,\n renderHTML: (attributes) => ({\n \"data-type\": attributes.type,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"div[data-callout]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const type = (node.attrs.type as CalloutType) || 'info';\n\n return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n \"data-callout\": \"\",\n \"class\": `callout callout-${type}`,\n \"role\": \"note\",\n \"aria-label\": CALLOUT_ARIA_LABELS[type],\n }),\n 0,\n ];\n },\n\n addCommands() {\n return {\n setCallout:\n (attributes) =>\n ({ commands }) => {\n return commands.wrapIn(this.name, attributes);\n },\n toggleCallout:\n (attributes) =>\n ({ commands }) => {\n return commands.toggleWrap(this.name, attributes);\n },\n unsetCallout:\n () =>\n ({ commands }) => {\n return commands.lift(this.name);\n },\n };\n },\n});\n","import { useRef } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport { compressImage } from '../lib/compress-image';\nimport { Button } from '../ui/button';\nimport { ToolbarButton } from './ToolbarButton';\nimport { ToolbarDivider } from './ToolbarDivider';\nimport { HeadingDropdown } from './HeadingDropdown';\nimport { ListDropdown } from './ListDropdown';\nimport { TableDropdown } from './TableDropdown';\nimport { CalloutDropdown } from './CalloutDropdown';\nimport { ColorPicker } from './ColorPicker';\nimport {\n Bold,\n Italic,\n Code,\n Underline as UnderlineIcon,\n Link as LinkIcon,\n Superscript as SuperscriptIcon,\n Subscript as SubscriptIcon,\n AlignLeft,\n AlignCenter,\n AlignRight,\n ImagePlus,\n Sun,\n Moon,\n type LucideProps,\n} from 'lucide-react';\nimport type { ComponentType } from 'react';\n\ntype ToolbarButtonConfig = {\n key: string;\n icon: ComponentType<LucideProps>;\n title: string;\n isActive: (editor: Editor) => boolean;\n action: (editor: Editor) => void;\n};\n\ntype ToolbarItem =\n | 'heading'\n | 'list'\n | 'format'\n | 'script'\n | 'align'\n | 'color'\n | 'link'\n | 'image'\n | 'table'\n | 'callout'\n | 'themeToggle';\n\ninterface ToolbarProps {\n editor: Editor | null;\n config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';\n toolbarStart?: React.ReactNode;\n toolbarEnd?: React.ReactNode;\n theme?: 'light' | 'dark';\n onThemeToggle?: () => void;\n onImageUpload?: (file: File) => Promise<string> | void;\n}\n\nconst ICON_SIZE = \"h-4 w-4\";\n\nconst TEXT_FORMAT_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"bold\", icon: Bold, title: \"粗體\", isActive: (e) => e.isActive(\"bold\"), action: (e) => (e.chain().focus() as any).toggleBold().run() },\n { key: \"italic\", icon: Italic, title: \"斜體\", isActive: (e) => e.isActive(\"italic\"), action: (e) => (e.chain().focus() as any).toggleItalic().run() },\n { key: \"code\", icon: Code, title: \"行內程式碼\", isActive: (e) => e.isActive(\"code\"), action: (e) => (e.chain().focus() as any).toggleCode().run() },\n { key: \"underline\", icon: UnderlineIcon, title: \"底線\", isActive: (e) => e.isActive(\"underline\"), action: (e) => (e.chain().focus() as any).toggleUnderline().run() },\n];\n\nconst SCRIPT_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"superscript\", icon: SuperscriptIcon, title: \"上標\", isActive: (e) => e.isActive(\"superscript\"), action: (e) => (e.chain().focus() as any).toggleSuperscript().run() },\n { key: \"subscript\", icon: SubscriptIcon, title: \"下標\", isActive: (e) => e.isActive(\"subscript\"), action: (e) => (e.chain().focus() as any).toggleSubscript().run() },\n];\n\nconst ALIGN_BUTTONS: ToolbarButtonConfig[] = [\n { key: \"left\", icon: AlignLeft, title: \"靠左對齊\", isActive: (e) => e.isActive({ textAlign: \"left\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"left\").run() },\n { key: \"center\", icon: AlignCenter, title: \"置中對齊\", isActive: (e) => e.isActive({ textAlign: \"center\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"center\").run() },\n { key: \"right\", icon: AlignRight, title: \"靠右對齊\", isActive: (e) => e.isActive({ textAlign: \"right\" }), action: (e) => (e.chain().focus() as any).setTextAlign(\"right\").run() },\n];\n\nfunction ToolbarButtonGroup({ buttons, editor }: { buttons: ToolbarButtonConfig[]; editor: Editor }) {\n return (\n <>\n {buttons.map(({ key, icon: Icon, title, isActive, action }) => (\n <ToolbarButton\n key={key}\n pressed={isActive(editor)}\n onPressedChange={() => action(editor)}\n title={title}\n >\n <Icon className={ICON_SIZE} />\n </ToolbarButton>\n ))}\n </>\n );\n}\n\nfunction normalizeConfig(config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none'): ToolbarItem[][] {\n if (config === 'none') return [];\n if (config === 'all' || !config) {\n return [\n ['heading', 'list', 'table', 'callout'],\n ['format', 'link', 'color'],\n ['script'],\n ['align'],\n ['image'],\n ['themeToggle'],\n ];\n }\n\n if (Array.isArray(config)) {\n // 檢查是否為二維陣列\n if (config.length > 0 && Array.isArray(config[0])) {\n return config as ToolbarItem[][];\n }\n // 一維陣列,轉為二維\n return [config as ToolbarItem[]];\n }\n\n return [];\n}\n\nexport function Toolbar({\n editor,\n config,\n toolbarStart,\n toolbarEnd,\n theme,\n onThemeToggle,\n onImageUpload,\n}: ToolbarProps) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n if (!editor) return null;\n\n const groups = normalizeConfig(config);\n\n const setLink = () => {\n const previousUrl = editor.getAttributes(\"link\").href;\n const url = window.prompt(\"輸入連結網址\", previousUrl);\n\n if (url === null) return;\n if (url === \"\") {\n (editor.chain().focus().extendMarkRange(\"link\") as any).unsetLink().run();\n return;\n }\n\n (editor.chain().focus().extendMarkRange(\"link\") as any).setLink({ href: url }).run();\n };\n\n const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n try {\n const compressed = await compressImage(file);\n\n if (onImageUpload) {\n const result = onImageUpload(compressed);\n if (result instanceof Promise) {\n const url = await result;\n if (url) {\n (editor.chain().focus() as any).setImage({ src: url }).run();\n }\n }\n } else {\n const reader = new FileReader();\n reader.onload = () => {\n const base64 = reader.result as string;\n (editor.chain().focus() as any).setImage({ src: base64 }).run();\n };\n reader.onerror = () => {\n console.error(\"圖片讀取失敗\");\n };\n reader.readAsDataURL(compressed);\n }\n } catch (error) {\n console.error(\"圖片處理失敗:\", error);\n }\n\n e.target.value = \"\";\n };\n\n const renderToolbarItem = (item: ToolbarItem) => {\n switch (item) {\n case 'heading':\n return <HeadingDropdown key=\"heading\" editor={editor} iconSize={ICON_SIZE} />;\n case 'list':\n return <ListDropdown key=\"list\" editor={editor} iconSize={ICON_SIZE} />;\n case 'table':\n return <TableDropdown key=\"table\" editor={editor} iconSize={ICON_SIZE} />;\n case 'callout':\n return <CalloutDropdown key=\"callout\" editor={editor} iconSize={ICON_SIZE} />;\n case 'format':\n return <ToolbarButtonGroup key=\"format\" buttons={TEXT_FORMAT_BUTTONS} editor={editor} />;\n case 'link':\n return (\n <ToolbarButton\n key=\"link\"\n pressed={editor.isActive(\"link\")}\n onPressedChange={setLink}\n title=\"連結\"\n >\n <LinkIcon className={ICON_SIZE} />\n </ToolbarButton>\n );\n case 'color':\n return <ColorPicker key=\"color\" editor={editor} iconSize={ICON_SIZE} />;\n case 'script':\n return <ToolbarButtonGroup key=\"script\" buttons={SCRIPT_BUTTONS} editor={editor} />;\n case 'align':\n return <ToolbarButtonGroup key=\"align\" buttons={ALIGN_BUTTONS} editor={editor} />;\n case 'image':\n return (\n <Button\n key=\"image\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 px-2 gap-1\"\n onClick={() => fileInputRef.current?.click()}\n title=\"插入圖片\"\n >\n <ImagePlus className={ICON_SIZE} />\n </Button>\n );\n case 'themeToggle':\n return onThemeToggle ? (\n <Button\n key=\"themeToggle\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n onClick={onThemeToggle}\n title={theme === \"dark\" ? \"切換淺色模式\" : \"切換深色模式\"}\n >\n {theme === \"dark\" ? <Moon className={ICON_SIZE} /> : <Sun className={ICON_SIZE} />}\n </Button>\n ) : null;\n default:\n return null;\n }\n };\n\n return (\n <div className=\"flex items-center justify-center mb-2 relative\">\n <div className={`flex items-center justify-between px-2 py-1.5 rounded-lg shadow-sm w-full max-w-7xl mx-auto ${theme === 'dark' ? 'bg-zinc-900' : 'bg-white'}`}>\n <div className=\"flex items-center gap-0.5\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handleImageUpload}\n aria-label=\"上傳圖片\"\n />\n\n {toolbarStart}\n\n {groups.map((group, groupIndex) => (\n <div key={groupIndex} className=\"flex items-center gap-0.5\">\n {groupIndex > 0 && <ToolbarDivider />}\n {group.map(item => renderToolbarItem(item))}\n </div>\n ))}\n </div>\n\n <div className=\"flex items-center gap-0.5\">\n {toolbarEnd}\n </div>\n </div>\n </div>\n );\n}\n\nexport type { ToolbarProps, ToolbarItem, ToolbarButtonConfig };\n","const DEFAULT_MAX_SIZE_MB = 1;\nconst DEFAULT_MAX_DIMENSION = 1920;\nconst DEFAULT_QUALITY = 0.85;\n\ninterface CompressOptions {\n maxSizeMB?: number;\n maxDimension?: number;\n quality?: number;\n}\n\nexport async function compressImage(\n file: File,\n options: CompressOptions = {}\n): Promise<File> {\n const {\n maxSizeMB = DEFAULT_MAX_SIZE_MB,\n maxDimension = DEFAULT_MAX_DIMENSION,\n quality = DEFAULT_QUALITY,\n } = options;\n\n if (file.size <= maxSizeMB * 1024 * 1024) {\n return file;\n }\n\n const img = new Image();\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d')!;\n\n return new Promise((resolve, reject) => {\n img.onload = () => {\n let { width, height } = img;\n\n if (width > maxDimension || height > maxDimension) {\n const ratio = Math.min(maxDimension / width, maxDimension / height);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n\n canvas.width = width;\n canvas.height = height;\n ctx.drawImage(img, 0, 0, width, height);\n\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error('圖片壓縮失敗'));\n return;\n }\n resolve(new File([blob], file.name, { type: 'image/jpeg' }));\n },\n 'image/jpeg',\n quality\n );\n };\n\n img.onerror = () => reject(new Error('圖片載入失敗'));\n img.src = URL.createObjectURL(file);\n });\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'default' | 'ghost' | 'outline';\n size?: 'default' | 'sm' | 'lg';\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'default', size = 'default', ...props }, ref) => {\n const variantStyles = {\n default: 'bg-transparent text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800',\n ghost: 'hover:bg-zinc-100 dark:hover:bg-zinc-800',\n outline: 'border border-zinc-200 dark:border-zinc-700 bg-transparent hover:bg-zinc-100 dark:hover:bg-zinc-800',\n };\n\n const sizeStyles = {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 px-3 text-xs',\n lg: 'h-10 px-8',\n };\n\n return (\n <button\n className={cn(\n 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n 'disabled:pointer-events-none disabled:opacity-50',\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\n\nButton.displayName = 'Button';\n\nexport { Button };\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from 'react';\nimport * as TogglePrimitive from '@radix-ui/react-toggle';\nimport { cn } from '../lib/utils';\n\nexport interface ToggleProps extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> {\n size?: 'default' | 'sm';\n}\n\nconst Toggle = React.forwardRef<React.ElementRef<typeof TogglePrimitive.Root>, ToggleProps>(\n ({ className, size = 'default', ...props }, ref) => {\n const sizeStyles = {\n default: 'h-9 px-3',\n sm: 'h-8 px-2',\n };\n\n return (\n <TogglePrimitive.Root\n ref={ref}\n className={cn(\n 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',\n 'hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n 'disabled:pointer-events-none disabled:opacity-50',\n 'data-[state=on]:bg-[var(--accent)] data-[state=on]:text-[var(--accent-foreground)]',\n sizeStyles[size],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nToggle.displayName = TogglePrimitive.Root.displayName;\n\nexport { Toggle };\n","import { Toggle } from '../ui/toggle';\n\ninterface ToolbarButtonProps {\n pressed: boolean;\n onPressedChange: () => void;\n disabled?: boolean;\n children: React.ReactNode;\n title?: string;\n}\n\nexport function ToolbarButton({\n pressed,\n onPressedChange,\n disabled,\n children,\n title,\n}: ToolbarButtonProps) {\n return (\n <Toggle\n size=\"sm\"\n pressed={pressed}\n onPressedChange={onPressedChange}\n disabled={disabled}\n title={title}\n className=\"h-9 w-9 p-0 border-0 bg-transparent rounded-lg hover:bg-muted data-[state=on]:bg-zinc-900 data-[state=on]:text-white disabled:opacity-30\"\n >\n {children}\n </Toggle>\n );\n}\n\nexport type { ToolbarButtonProps };\n","export function ToolbarDivider() {\n return <div className=\"w-px h-5 bg-border mx-1.5\" />;\n}\n","import * as React from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { cn } from '../lib/utils';\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border border-[var(--border)] bg-[var(--popover)] p-1 text-[var(--popover-foreground)] shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors',\n 'hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)] focus:bg-[var(--accent)] focus:text-[var(--accent-foreground)]',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-[var(--border)]', className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nexport { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, Heading1, Heading2, Heading3 } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface HeadingDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function HeadingDropdown({ editor, iconSize = \"h-4 w-4\" }: HeadingDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1 font-normal\">\n <span className=\"text-sm font-semibold\">H</span>\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 1 }).run()}>\n <Heading1 className={cn(iconSize, \"mr-2\")} />\n 標題 1\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 2 }).run()}>\n <Heading2 className={cn(iconSize, \"mr-2\")} />\n 標題 2\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleHeading({ level: 3 }).run()}>\n <Heading3 className={cn(iconSize, \"mr-2\")} />\n 標題 3\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).setParagraph().run()}>\n 內文\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { HeadingDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, List, ListOrdered, ListTodo } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface ListDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function ListDropdown({ editor, iconSize = \"h-4 w-4\" }: ListDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <List className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleBulletList().run()}>\n <List className={cn(iconSize, \"mr-2\")} />\n 項目清單\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleOrderedList().run()}>\n <ListOrdered className={cn(iconSize, \"mr-2\")} />\n 編號清單\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => (editor.chain().focus() as any).toggleTaskList().run()}>\n <ListTodo className={cn(iconSize, \"mr-2\")} />\n 任務清單\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { ListDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, Plus, Trash2, Table as TableIcon } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\ninterface TableDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function TableDropdown({ editor, iconSize = \"h-4 w-4\" }: TableDropdownProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <TableIcon className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}\n >\n <Plus className={cn(iconSize, \"mr-2\")} />\n 插入表格 (3x3)\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).addColumnAfter().run()}\n disabled={!(editor.can() as any).addColumnAfter()}\n >\n 新增欄\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).addRowAfter().run()}\n disabled={!(editor.can() as any).addRowAfter()}\n >\n 新增列\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteColumn().run()}\n disabled={!(editor.can() as any).deleteColumn()}\n >\n 刪除欄\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteRow().run()}\n disabled={!(editor.can() as any).deleteRow()}\n >\n 刪除列\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => (editor.chain().focus() as any).deleteTable().run()}\n disabled={!(editor.can() as any).deleteTable()}\n className=\"text-destructive\"\n >\n <Trash2 className={cn(iconSize, \"mr-2\")} />\n 刪除表格\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { TableDropdownProps };\n","import { useState } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { ChevronDown, MessageSquare } from 'lucide-react';\n\ninterface CalloutDropdownProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function CalloutDropdown({ editor, iconSize = \"h-4 w-4\" }: CalloutDropdownProps) {\n const [open, setOpen] = useState(false);\n\n return (\n <DropdownMenu open={open} onOpenChange={setOpen} modal={false}>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\">\n <MessageSquare className={iconSize} />\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"min-w-0 p-1.5\">\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-emerald-100 border border-emerald-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"success\" }).run();\n }, 0);\n }}\n title=\"成功提示\"\n aria-label=\"成功提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-amber-100 border border-amber-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"warning\" }).run();\n }, 0);\n }}\n title=\"警告提示\"\n aria-label=\"警告提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-red-100 border border-red-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"error\" }).run();\n }, 0);\n }}\n title=\"錯誤提示\"\n aria-label=\"錯誤提示\"\n />\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded bg-sky-100 border border-sky-300 hover:scale-110 transition-transform\"\n onClick={() => {\n setOpen(false);\n setTimeout(() => {\n (editor.chain().focus() as any).setCallout({ type: \"info\" }).run();\n }, 0);\n }}\n title=\"資訊提示\"\n aria-label=\"資訊提示\"\n />\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { CalloutDropdownProps };\n","import type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { Palette, X } from 'lucide-react';\n\nconst COLOR_PALETTE = [\n { name: \"黑色\", value: \"#000000\" },\n { name: \"灰色\", value: \"#6B7280\" },\n { name: \"紅色\", value: \"#EF4444\" },\n { name: \"橙色\", value: \"#F97316\" },\n { name: \"黃色\", value: \"#EAB308\" },\n { name: \"綠色\", value: \"#22C55E\" },\n { name: \"藍色\", value: \"#3B82F6\" },\n { name: \"紫色\", value: \"#8B5CF6\" },\n];\n\ninterface ColorPickerProps {\n editor: Editor;\n iconSize?: string;\n}\n\nexport function ColorPicker({ editor, iconSize = \"h-4 w-4\" }: ColorPickerProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-8 px-2 gap-1\" title=\"顏色\">\n <Palette className={iconSize} />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-72\">\n <div className=\"p-2\">\n <div className=\"text-xs font-medium text-muted-foreground mb-2\">文字顏色</div>\n <div className=\"flex gap-1.5 mb-3\">\n {COLOR_PALETTE.map((color) => (\n <button\n key={`text-${color.value}`}\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border hover:scale-110 transition-transform\"\n style={{ backgroundColor: color.value }}\n onClick={() => (editor.chain().focus() as any).setColor(color.value).run()}\n title={color.name}\n aria-label={`文字顏色:${color.name}`}\n />\n ))}\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border hover:scale-110 transition-transform flex items-center justify-center bg-background\"\n onClick={() => (editor.chain().focus() as any).unsetColor().run()}\n title=\"清除文字顏色\"\n aria-label=\"清除文字顏色\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </div>\n\n <DropdownMenuSeparator />\n\n <div className=\"text-xs font-medium text-muted-foreground mb-2 mt-2\">背景色</div>\n <div className=\"flex gap-1.5\">\n {COLOR_PALETTE.map((color) => (\n <button\n key={`bg-${color.value}`}\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border hover:scale-110 transition-transform\"\n style={{ backgroundColor: color.value }}\n onClick={() => (editor.chain().focus() as any).toggleHighlight({ color: color.value }).run()}\n title={color.name}\n aria-label={`背景色:${color.name}`}\n />\n ))}\n <button\n type=\"button\"\n className=\"w-6 h-6 rounded border border-border hover:scale-110 transition-transform flex items-center justify-center bg-background\"\n onClick={() => (editor.chain().focus() as any).unsetHighlight().run()}\n title=\"清除背景色\"\n aria-label=\"清除背景色\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </div>\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport type { ColorPickerProps };\nexport { COLOR_PALETTE };\n"],"mappings":";AAAA,SAAS,UAAAA,SAAQ,WAAW,mBAAmB;AAC/C,SAAS,WAAW,qBAAkC;AACtD,OAAO,gBAAgB;AACvB,OAAO,iBAAiB;AACxB,OAAO,eAAe;AACtB,OAAO,eAAe;AACtB,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAC1B,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAC1B,OAAO,eAAe;AACtB,OAAO,iBAAiB;AACxB,OAAO,cAAc;AACrB,OAAO,cAAc;AACrB,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,OAAO,iBAAiB;;;AClBxB,SAAS,MAAM,uBAAuB;AAQtC,IAAM,sBAAmD;AAAA,EACvD,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AAAA,EACP,MAAM;AACR;AAYO,IAAM,UAAU,KAAK,OAAuB;AAAA,EACjD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EAEV,aAAa;AACX,WAAO;AAAA,MACL,gBAAgB,CAAC;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,gBAAgB;AACd,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,WAAW,CAAC,YAAY,QAAQ,aAAa,WAAW;AAAA,QACxD,YAAY,CAAC,gBAAgB;AAAA,UAC3B,aAAa,WAAW;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY;AACV,WAAO;AAAA,MACL;AAAA,QACE,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,MAAM,eAAe,GAAG;AACnC,UAAM,OAAQ,KAAK,MAAM,QAAwB;AAEjD,WAAO;AAAA,MACL;AAAA,MACA,gBAAgB,KAAK,QAAQ,gBAAgB,gBAAgB;AAAA,QAC3D,gBAAgB;AAAA,QAChB,SAAS,mBAAmB,IAAI;AAAA,QAChC,QAAQ;AAAA,QACR,cAAc,oBAAoB,IAAI;AAAA,MACxC,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAc;AACZ,WAAO;AAAA,MACL,YACE,CAAC,eACD,CAAC,EAAE,SAAS,MAAM;AAChB,eAAO,SAAS,OAAO,KAAK,MAAM,UAAU;AAAA,MAC9C;AAAA,MACF,eACE,CAAC,eACD,CAAC,EAAE,SAAS,MAAM;AAChB,eAAO,SAAS,WAAW,KAAK,MAAM,UAAU;AAAA,MAClD;AAAA,MACF,cACE,MACA,CAAC,EAAE,SAAS,MAAM;AAChB,eAAO,SAAS,KAAK,KAAK,IAAI;AAAA,MAChC;AAAA,IACJ;AAAA,EACF;AACF,CAAC;;;AC3FD,SAAS,cAAc;;;ACAvB,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAC9B,IAAM,kBAAkB;AAQxB,eAAsB,cACpB,MACA,UAA2B,CAAC,GACb;AACf,QAAM;AAAA,IACJ,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,UAAU;AAAA,EACZ,IAAI;AAEJ,MAAI,KAAK,QAAQ,YAAY,OAAO,MAAM;AACxC,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,IAAI,MAAM;AACtB,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,QAAM,MAAM,OAAO,WAAW,IAAI;AAElC,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI,SAAS,MAAM;AACjB,UAAI,EAAE,OAAO,OAAO,IAAI;AAExB,UAAI,QAAQ,gBAAgB,SAAS,cAAc;AACjD,cAAM,QAAQ,KAAK,IAAI,eAAe,OAAO,eAAe,MAAM;AAClE,gBAAQ,KAAK,MAAM,QAAQ,KAAK;AAChC,iBAAS,KAAK,MAAM,SAAS,KAAK;AAAA,MACpC;AAEA,aAAO,QAAQ;AACf,aAAO,SAAS;AAChB,UAAI,UAAU,KAAK,GAAG,GAAG,OAAO,MAAM;AAEtC,aAAO;AAAA,QACL,CAAC,SAAS;AACR,cAAI,CAAC,MAAM;AACT,mBAAO,IAAI,MAAM,sCAAQ,CAAC;AAC1B;AAAA,UACF;AACA,kBAAQ,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC,CAAC;AAAA,QAC7D;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,MAAM,OAAO,IAAI,MAAM,sCAAQ,CAAC;AAC9C,QAAI,MAAM,IAAI,gBAAgB,IAAI;AAAA,EACpC,CAAC;AACH;;;AC1DA,YAAY,WAAW;;;ACAvB,SAA0B,YAAY;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;ADkBM;AAfN,IAAM,SAAe;AAAA,EACnB,CAAC,EAAE,WAAW,UAAU,WAAW,OAAO,WAAW,GAAG,MAAM,GAAG,QAAQ;AACvE,UAAM,gBAAgB;AAAA,MACpB,SAAS;AAAA,MACT,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAEA,UAAM,aAAa;AAAA,MACjB,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA,cAAc,OAAO;AAAA,UACrB,WAAW,IAAI;AAAA,UACf;AAAA,QACF;AAAA,QACA;AAAA,QACC,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AAEA,OAAO,cAAc;;;AEvCrB,YAAYC,YAAW;AACvB,YAAY,qBAAqB;AAe3B,gBAAAC,YAAA;AARN,IAAM,SAAe;AAAA,EACnB,CAAC,EAAE,WAAW,OAAO,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClD,UAAM,aAAa;AAAA,MACjB,SAAS;AAAA,MACT,IAAI;AAAA,IACN;AAEA,WACE,gBAAAA;AAAA,MAAiB;AAAA,MAAhB;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW,IAAI;AAAA,UACf;AAAA,QACF;AAAA,QACC,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AAEA,OAAO,cAA8B,qBAAK;;;ACftC,gBAAAC,YAAA;AARG,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAU;AAAA,MAET;AAAA;AAAA,EACH;AAEJ;;;AC5BS,gBAAAC,YAAA;AADF,SAAS,iBAAiB;AAC/B,SAAO,gBAAAA,KAAC,SAAI,WAAU,6BAA4B;AACpD;;;ACFA,YAAYC,YAAW;AACvB,YAAY,2BAA2B;AAYnC,gBAAAC,YAAA;AATJ,IAAM,eAAqC;AAE3C,IAAM,sBAA4C;AAElD,IAAM,sBAA4B,kBAGhC,CAAC,EAAE,WAAW,aAAa,GAAG,GAAG,MAAM,GAAG,QAC1C,gBAAAA,KAAuB,8BAAtB,EACC,0BAAAA;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,GACF,CACD;AACD,oBAAoB,cAAoC,8BAAQ;AAEhE,IAAM,mBAAyB,kBAG7B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,iBAAiB,cAAoC,2BAAK;AAE1D,IAAM,wBAA8B,kBAGlC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,sCAAsC,SAAS;AAAA,IAC5D,GAAG;AAAA;AACN,CACD;AACD,sBAAsB,cAAoC,gCAAU;;;AC/CpE,SAAS,aAAa,UAAU,UAAU,gBAAgB;AAYlD,SACE,OAAAC,MADF;AAJD,SAAS,gBAAgB,EAAE,QAAQ,WAAW,UAAU,GAAyB;AACtF,SACE,qBAAC,gBACC;AAAA,oBAAAA,KAAC,uBAAoB,SAAO,MAC1B,+BAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,WAAU,8BAC1C;AAAA,sBAAAA,KAAC,UAAK,WAAU,yBAAwB,eAAC;AAAA,MACzC,gBAAAA,KAAC,eAAY,WAAU,WAAU;AAAA,OACnC,GACF;AAAA,IACA,qBAAC,uBAAoB,OAAM,SACzB;AAAA,2BAAC,oBAAiB,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,cAAc,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,GAC/F;AAAA,wBAAAA,KAAC,YAAS,WAAW,GAAG,UAAU,MAAM,GAAG;AAAA,QAAE;AAAA,SAE/C;AAAA,MACA,qBAAC,oBAAiB,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,cAAc,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,GAC/F;AAAA,wBAAAA,KAAC,YAAS,WAAW,GAAG,UAAU,MAAM,GAAG;AAAA,QAAE;AAAA,SAE/C;AAAA,MACA,qBAAC,oBAAiB,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,cAAc,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,GAC/F;AAAA,wBAAAA,KAAC,YAAS,WAAW,GAAG,UAAU,MAAM,GAAG;AAAA,QAAE;AAAA,SAE/C;AAAA,MACA,gBAAAA,KAAC,oBAAiB,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,aAAa,EAAE,IAAI,GAAG,0BAEvF;AAAA,OACF;AAAA,KACF;AAEJ;;;ACpCA,SAAS,eAAAC,cAAa,MAAM,aAAa,gBAAgB;AAYjD,SACE,OAAAC,MADF,QAAAC,aAAA;AAJD,SAAS,aAAa,EAAE,QAAQ,WAAW,UAAU,GAAsB;AAChF,SACE,gBAAAA,MAAC,gBACC;AAAA,oBAAAD,KAAC,uBAAoB,SAAO,MAC1B,0BAAAC,MAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,WAAU,kBAC1C;AAAA,sBAAAD,KAAC,QAAK,WAAW,UAAU;AAAA,MAC3B,gBAAAA,KAACE,cAAA,EAAY,WAAU,WAAU;AAAA,OACnC,GACF;AAAA,IACA,gBAAAD,MAAC,uBAAoB,OAAM,SACzB;AAAA,sBAAAA,MAAC,oBAAiB,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,iBAAiB,EAAE,IAAI,GACtF;AAAA,wBAAAD,KAAC,QAAK,WAAW,GAAG,UAAU,MAAM,GAAG;AAAA,QAAE;AAAA,SAE3C;AAAA,MACA,gBAAAC,MAAC,oBAAiB,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,kBAAkB,EAAE,IAAI,GACvF;AAAA,wBAAAD,KAAC,eAAY,WAAW,GAAG,UAAU,MAAM,GAAG;AAAA,QAAE;AAAA,SAElD;AAAA,MACA,gBAAAC,MAAC,oBAAiB,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,eAAe,EAAE,IAAI,GACpF;AAAA,wBAAAD,KAAC,YAAS,WAAW,GAAG,UAAU,MAAM,GAAG;AAAA,QAAE;AAAA,SAE/C;AAAA,OACF;AAAA,KACF;AAEJ;;;AChCA,SAAS,eAAAG,cAAa,MAAM,QAAQ,SAAS,iBAAiB;AAYtD,SACE,OAAAC,MADF,QAAAC,aAAA;AAJD,SAAS,cAAc,EAAE,QAAQ,WAAW,UAAU,GAAuB;AAClF,SACE,gBAAAA,MAAC,gBACC;AAAA,oBAAAD,KAAC,uBAAoB,SAAO,MAC1B,0BAAAC,MAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,WAAU,kBAC1C;AAAA,sBAAAD,KAAC,aAAU,WAAW,UAAU;AAAA,MAChC,gBAAAA,KAACE,cAAA,EAAY,WAAU,WAAU;AAAA,OACnC,GACF;AAAA,IACA,gBAAAD,MAAC,uBAAoB,OAAM,SACzB;AAAA,sBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,KAAK,CAAC,EAAE,IAAI;AAAA,UAE1G;AAAA,4BAAAD,KAAC,QAAK,WAAW,GAAG,UAAU,MAAM,GAAG;AAAA,YAAE;AAAA;AAAA;AAAA,MAE3C;AAAA,MACA,gBAAAA,KAAC,yBAAsB;AAAA,MACvB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,eAAe,EAAE,IAAI;AAAA,UACpE,UAAU,CAAE,OAAO,IAAI,EAAU,eAAe;AAAA,UACjD;AAAA;AAAA,MAED;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,YAAY,EAAE,IAAI;AAAA,UACjE,UAAU,CAAE,OAAO,IAAI,EAAU,YAAY;AAAA,UAC9C;AAAA;AAAA,MAED;AAAA,MACA,gBAAAA,KAAC,yBAAsB;AAAA,MACvB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,aAAa,EAAE,IAAI;AAAA,UAClE,UAAU,CAAE,OAAO,IAAI,EAAU,aAAa;AAAA,UAC/C;AAAA;AAAA,MAED;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,UAAU,EAAE,IAAI;AAAA,UAC/D,UAAU,CAAE,OAAO,IAAI,EAAU,UAAU;AAAA,UAC5C;AAAA;AAAA,MAED;AAAA,MACA,gBAAAA,KAAC,yBAAsB;AAAA,MACvB,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,YAAY,EAAE,IAAI;AAAA,UACjE,UAAU,CAAE,OAAO,IAAI,EAAU,YAAY;AAAA,UAC7C,WAAU;AAAA,UAEV;AAAA,4BAAAD,KAAC,UAAO,WAAW,GAAG,UAAU,MAAM,GAAG;AAAA,YAAE;AAAA;AAAA;AAAA,MAE7C;AAAA,OACF;AAAA,KACF;AAEJ;;;ACvEA,SAAS,gBAAgB;AAQzB,SAAS,eAAAG,cAAa,qBAAqB;AAanC,SACE,OAAAC,MADF,QAAAC,aAAA;AAND,SAAS,gBAAgB,EAAE,QAAQ,WAAW,UAAU,GAAyB;AACtF,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AAEtC,SACE,gBAAAA,MAAC,gBAAa,MAAY,cAAc,SAAS,OAAO,OACtD;AAAA,oBAAAD,KAAC,uBAAoB,SAAO,MAC1B,0BAAAC,MAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,WAAU,kBAC1C;AAAA,sBAAAD,KAAC,iBAAc,WAAW,UAAU;AAAA,MACpC,gBAAAA,KAACD,cAAA,EAAY,WAAU,WAAU;AAAA,OACnC,GACF;AAAA,IACA,gBAAAC,KAAC,uBAAoB,OAAM,SAAQ,WAAU,iBAC3C,0BAAAC,MAAC,SAAI,WAAU,cACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS,MAAM;AACb,oBAAQ,KAAK;AACb,uBAAW,MAAM;AACf,cAAC,OAAO,MAAM,EAAE,MAAM,EAAU,WAAW,EAAE,MAAM,UAAU,CAAC,EAAE,IAAI;AAAA,YACtE,GAAG,CAAC;AAAA,UACN;AAAA,UACA,OAAM;AAAA,UACN,cAAW;AAAA;AAAA,MACb;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS,MAAM;AACb,oBAAQ,KAAK;AACb,uBAAW,MAAM;AACf,cAAC,OAAO,MAAM,EAAE,MAAM,EAAU,WAAW,EAAE,MAAM,UAAU,CAAC,EAAE,IAAI;AAAA,YACtE,GAAG,CAAC;AAAA,UACN;AAAA,UACA,OAAM;AAAA,UACN,cAAW;AAAA;AAAA,MACb;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS,MAAM;AACb,oBAAQ,KAAK;AACb,uBAAW,MAAM;AACf,cAAC,OAAO,MAAM,EAAE,MAAM,EAAU,WAAW,EAAE,MAAM,QAAQ,CAAC,EAAE,IAAI;AAAA,YACpE,GAAG,CAAC;AAAA,UACN;AAAA,UACA,OAAM;AAAA,UACN,cAAW;AAAA;AAAA,MACb;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS,MAAM;AACb,oBAAQ,KAAK;AACb,uBAAW,MAAM;AACf,cAAC,OAAO,MAAM,EAAE,MAAM,EAAU,WAAW,EAAE,MAAM,OAAO,CAAC,EAAE,IAAI;AAAA,YACnE,GAAG,CAAC;AAAA,UACN;AAAA,UACA,OAAM;AAAA,UACN,cAAW;AAAA;AAAA,MACb;AAAA,OACF,GACF;AAAA,KACF;AAEJ;;;ACxEA,SAAS,SAAS,SAAS;AAuBjB,gBAAAE,OAMA,QAAAC,aANA;AArBV,IAAM,gBAAgB;AAAA,EACpB,EAAE,MAAM,gBAAM,OAAO,UAAU;AAAA,EAC/B,EAAE,MAAM,gBAAM,OAAO,UAAU;AAAA,EAC/B,EAAE,MAAM,gBAAM,OAAO,UAAU;AAAA,EAC/B,EAAE,MAAM,gBAAM,OAAO,UAAU;AAAA,EAC/B,EAAE,MAAM,gBAAM,OAAO,UAAU;AAAA,EAC/B,EAAE,MAAM,gBAAM,OAAO,UAAU;AAAA,EAC/B,EAAE,MAAM,gBAAM,OAAO,UAAU;AAAA,EAC/B,EAAE,MAAM,gBAAM,OAAO,UAAU;AACjC;AAOO,SAAS,YAAY,EAAE,QAAQ,WAAW,UAAU,GAAqB;AAC9E,SACE,gBAAAA,MAAC,gBACC;AAAA,oBAAAD,MAAC,uBAAoB,SAAO,MAC1B,0BAAAA,MAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,WAAU,kBAAiB,OAAM,gBACjE,0BAAAA,MAAC,WAAQ,WAAW,UAAU,GAChC,GACF;AAAA,IACA,gBAAAA,MAAC,uBAAoB,OAAM,SAAQ,WAAU,QAC3C,0BAAAC,MAAC,SAAI,WAAU,OACb;AAAA,sBAAAD,MAAC,SAAI,WAAU,kDAAiD,sCAAI;AAAA,MACpE,gBAAAC,MAAC,SAAI,WAAU,qBACZ;AAAA,sBAAc,IAAI,CAAC,UAClB,gBAAAD;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,OAAO,EAAE,iBAAiB,MAAM,MAAM;AAAA,YACtC,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,YACzE,OAAO,MAAM;AAAA,YACb,cAAY,iCAAQ,MAAM,IAAI;AAAA;AAAA,UANzB,QAAQ,MAAM,KAAK;AAAA,QAO1B,CACD;AAAA,QACD,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,WAAW,EAAE,IAAI;AAAA,YAChE,OAAM;AAAA,YACN,cAAW;AAAA,YAEX,0BAAAA,MAAC,KAAE,WAAU,WAAU;AAAA;AAAA,QACzB;AAAA,SACF;AAAA,MAEA,gBAAAA,MAAC,yBAAsB;AAAA,MAEvB,gBAAAA,MAAC,SAAI,WAAU,uDAAsD,gCAAG;AAAA,MACxE,gBAAAC,MAAC,SAAI,WAAU,gBACZ;AAAA,sBAAc,IAAI,CAAC,UAClB,gBAAAD;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,OAAO,EAAE,iBAAiB,MAAM,MAAM;AAAA,YACtC,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,gBAAgB,EAAE,OAAO,MAAM,MAAM,CAAC,EAAE,IAAI;AAAA,YAC3F,OAAO,MAAM;AAAA,YACb,cAAY,2BAAO,MAAM,IAAI;AAAA;AAAA,UANxB,MAAM,MAAM,KAAK;AAAA,QAOxB,CACD;AAAA,QACD,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAO,OAAO,MAAM,EAAE,MAAM,EAAU,eAAe,EAAE,IAAI;AAAA,YACpE,OAAM;AAAA,YACN,cAAW;AAAA,YAEX,0BAAAA,MAAC,KAAE,WAAU,WAAU;AAAA;AAAA,QACzB;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;;;AZ9EA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAwDH,mBAQM,OAAAE,OAyKE,QAAAC,aAjLR;AAtBJ,IAAM,YAAY;AAElB,IAAM,sBAA6C;AAAA,EACjD,EAAE,KAAK,QAAQ,MAAM,MAAM,OAAO,gBAAM,UAAU,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG,QAAQ,CAAC,MAAO,EAAE,MAAM,EAAE,MAAM,EAAU,WAAW,EAAE,IAAI,EAAE;AAAA,EAC1I,EAAE,KAAK,UAAU,MAAM,QAAQ,OAAO,gBAAM,UAAU,CAAC,MAAM,EAAE,SAAS,QAAQ,GAAG,QAAQ,CAAC,MAAO,EAAE,MAAM,EAAE,MAAM,EAAU,aAAa,EAAE,IAAI,EAAE;AAAA,EAClJ,EAAE,KAAK,QAAQ,MAAM,MAAM,OAAO,kCAAS,UAAU,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG,QAAQ,CAAC,MAAO,EAAE,MAAM,EAAE,MAAM,EAAU,WAAW,EAAE,IAAI,EAAE;AAAA,EAC7I,EAAE,KAAK,aAAa,MAAM,eAAe,OAAO,gBAAM,UAAU,CAAC,MAAM,EAAE,SAAS,WAAW,GAAG,QAAQ,CAAC,MAAO,EAAE,MAAM,EAAE,MAAM,EAAU,gBAAgB,EAAE,IAAI,EAAE;AACpK;AAEA,IAAM,iBAAwC;AAAA,EAC5C,EAAE,KAAK,eAAe,MAAM,iBAAiB,OAAO,gBAAM,UAAU,CAAC,MAAM,EAAE,SAAS,aAAa,GAAG,QAAQ,CAAC,MAAO,EAAE,MAAM,EAAE,MAAM,EAAU,kBAAkB,EAAE,IAAI,EAAE;AAAA,EAC1K,EAAE,KAAK,aAAa,MAAM,eAAe,OAAO,gBAAM,UAAU,CAAC,MAAM,EAAE,SAAS,WAAW,GAAG,QAAQ,CAAC,MAAO,EAAE,MAAM,EAAE,MAAM,EAAU,gBAAgB,EAAE,IAAI,EAAE;AACpK;AAEA,IAAM,gBAAuC;AAAA,EAC3C,EAAE,KAAK,QAAQ,MAAM,WAAW,OAAO,4BAAQ,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAO,EAAE,MAAM,EAAE,MAAM,EAAU,aAAa,MAAM,EAAE,IAAI,EAAE;AAAA,EACxK,EAAE,KAAK,UAAU,MAAM,aAAa,OAAO,4BAAQ,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,SAAS,CAAC,GAAG,QAAQ,CAAC,MAAO,EAAE,MAAM,EAAE,MAAM,EAAU,aAAa,QAAQ,EAAE,IAAI,EAAE;AAAA,EAChL,EAAE,KAAK,SAAS,MAAM,YAAY,OAAO,4BAAQ,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,QAAQ,CAAC,GAAG,QAAQ,CAAC,MAAO,EAAE,MAAM,EAAE,MAAM,EAAU,aAAa,OAAO,EAAE,IAAI,EAAE;AAC9K;AAEA,SAAS,mBAAmB,EAAE,SAAS,OAAO,GAAuD;AACnG,SACE,gBAAAD,MAAA,YACG,kBAAQ,IAAI,CAAC,EAAE,KAAK,MAAM,MAAM,OAAO,UAAU,OAAO,MACvD,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAEC,SAAS,SAAS,MAAM;AAAA,MACxB,iBAAiB,MAAM,OAAO,MAAM;AAAA,MACpC;AAAA,MAEA,0BAAAA,MAAC,QAAK,WAAW,WAAW;AAAA;AAAA,IALvB;AAAA,EAMP,CACD,GACH;AAEJ;AAEA,SAAS,gBAAgB,QAA4E;AACnG,MAAI,WAAW,OAAQ,QAAO,CAAC;AAC/B,MAAI,WAAW,SAAS,CAAC,QAAQ;AAC/B,WAAO;AAAA,MACL,CAAC,WAAW,QAAQ,SAAS,SAAS;AAAA,MACtC,CAAC,UAAU,QAAQ,OAAO;AAAA,MAC1B,CAAC,QAAQ;AAAA,MACT,CAAC,OAAO;AAAA,MACR,CAAC,OAAO;AAAA,MACR,CAAC,aAAa;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,MAAM,GAAG;AAEzB,QAAI,OAAO,SAAS,KAAK,MAAM,QAAQ,OAAO,CAAC,CAAC,GAAG;AACjD,aAAO;AAAA,IACT;AAEA,WAAO,CAAC,MAAuB;AAAA,EACjC;AAEA,SAAO,CAAC;AACV;AAEO,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAiB;AACf,QAAM,eAAe,OAAyB,IAAI;AAElD,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,SAAS,gBAAgB,MAAM;AAErC,QAAM,UAAU,MAAM;AACpB,UAAM,cAAc,OAAO,cAAc,MAAM,EAAE;AACjD,UAAM,MAAM,OAAO,OAAO,wCAAU,WAAW;AAE/C,QAAI,QAAQ,KAAM;AAClB,QAAI,QAAQ,IAAI;AACd,MAAC,OAAO,MAAM,EAAE,MAAM,EAAE,gBAAgB,MAAM,EAAU,UAAU,EAAE,IAAI;AACxE;AAAA,IACF;AAEA,IAAC,OAAO,MAAM,EAAE,MAAM,EAAE,gBAAgB,MAAM,EAAU,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAE,IAAI;AAAA,EACrF;AAEA,QAAM,oBAAoB,OAAO,MAA2C;AAC1E,UAAM,OAAO,EAAE,OAAO,QAAQ,CAAC;AAC/B,QAAI,CAAC,KAAM;AAEX,QAAI;AACF,YAAM,aAAa,MAAM,cAAc,IAAI;AAE3C,UAAI,eAAe;AACjB,cAAM,SAAS,cAAc,UAAU;AACvC,YAAI,kBAAkB,SAAS;AAC7B,gBAAM,MAAM,MAAM;AAClB,cAAI,KAAK;AACP,YAAC,OAAO,MAAM,EAAE,MAAM,EAAU,SAAS,EAAE,KAAK,IAAI,CAAC,EAAE,IAAI;AAAA,UAC7D;AAAA,QACF;AAAA,MACF,OAAO;AACL,cAAM,SAAS,IAAI,WAAW;AAC9B,eAAO,SAAS,MAAM;AACpB,gBAAM,SAAS,OAAO;AACtB,UAAC,OAAO,MAAM,EAAE,MAAM,EAAU,SAAS,EAAE,KAAK,OAAO,CAAC,EAAE,IAAI;AAAA,QAChE;AACA,eAAO,UAAU,MAAM;AACrB,kBAAQ,MAAM,sCAAQ;AAAA,QACxB;AACA,eAAO,cAAc,UAAU;AAAA,MACjC;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,yCAAW,KAAK;AAAA,IAChC;AAEA,MAAE,OAAO,QAAQ;AAAA,EACnB;AAEA,QAAM,oBAAoB,CAAC,SAAsB;AAC/C,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,gBAAAA,MAAC,mBAA8B,QAAgB,UAAU,aAApC,SAA+C;AAAA,MAC7E,KAAK;AACH,eAAO,gBAAAA,MAAC,gBAAwB,QAAgB,UAAU,aAAjC,MAA4C;AAAA,MACvE,KAAK;AACH,eAAO,gBAAAA,MAAC,iBAA0B,QAAgB,UAAU,aAAlC,OAA6C;AAAA,MACzE,KAAK;AACH,eAAO,gBAAAA,MAAC,mBAA8B,QAAgB,UAAU,aAApC,SAA+C;AAAA,MAC7E,KAAK;AACH,eAAO,gBAAAA,MAAC,sBAAgC,SAAS,qBAAqB,UAAvC,QAAuD;AAAA,MACxF,KAAK;AACH,eACE,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,SAAS,OAAO,SAAS,MAAM;AAAA,YAC/B,iBAAiB;AAAA,YACjB,OAAM;AAAA,YAEN,0BAAAA,MAAC,YAAS,WAAW,WAAW;AAAA;AAAA,UAL5B;AAAA,QAMN;AAAA,MAEJ,KAAK;AACH,eAAO,gBAAAA,MAAC,eAAwB,QAAgB,UAAU,aAAlC,OAA6C;AAAA,MACvE,KAAK;AACH,eAAO,gBAAAA,MAAC,sBAAgC,SAAS,gBAAgB,UAAlC,QAAkD;AAAA,MACnF,KAAK;AACH,eAAO,gBAAAA,MAAC,sBAA+B,SAAS,eAAe,UAAhC,OAAgD;AAAA,MACjF,KAAK;AACH,eACE,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAM,aAAa,SAAS,MAAM;AAAA,YAC3C,OAAM;AAAA,YAEN,0BAAAA,MAAC,aAAU,WAAW,WAAW;AAAA;AAAA,UAP7B;AAAA,QAQN;AAAA,MAEJ,KAAK;AACH,eAAO,gBACL,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS;AAAA,YACT,OAAO,UAAU,SAAS,yCAAW;AAAA,YAEpC,oBAAU,SAAS,gBAAAA,MAAC,QAAK,WAAW,WAAW,IAAK,gBAAAA,MAAC,OAAI,WAAW,WAAW;AAAA;AAAA,UAP5E;AAAA,QAQN,IACE;AAAA,MACN;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAEA,SACE,gBAAAA,MAAC,SAAI,WAAU,kDACb,0BAAAC,MAAC,SAAI,WAAW,+FAA+F,UAAU,SAAS,gBAAgB,UAAU,IAC1J;AAAA,oBAAAA,MAAC,SAAI,WAAU,6BACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,QAAO;AAAA,UACP,WAAU;AAAA,UACV,UAAU;AAAA,UACV,cAAW;AAAA;AAAA,MACb;AAAA,MAEC;AAAA,MAEA,OAAO,IAAI,CAAC,OAAO,eAClB,gBAAAC,MAAC,SAAqB,WAAU,6BAC7B;AAAA,qBAAa,KAAK,gBAAAD,MAAC,kBAAe;AAAA,QAClC,MAAM,IAAI,UAAQ,kBAAkB,IAAI,CAAC;AAAA,WAFlC,UAGV,CACD;AAAA,OACH;AAAA,IAEA,gBAAAA,MAAC,SAAI,WAAU,6BACZ,sBACH;AAAA,KACF,GACF;AAEJ;;;AF3HI,SACa,OAAAE,OADb,QAAAC,aAAA;AAjGG,SAAS,WAAW;AAAA,EACzB,UAAU;AAAA,EACV;AAAA,EACA,cAAc;AAAA,EACd,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,QAAQ;AAAA,EACR;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,mBAAmBC,QAAO,KAAK;AAErC,QAAM,eAAe;AAAA,IACnB,CAAC,EAAE,QAAAC,QAAO,MAA0B;AAClC,uBAAiB,UAAU;AAC3B,iBAAWA,QAAO,QAAQ,CAAC;AAAA,IAC7B;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,SAAS,UAAU;AAAA,IACvB,YAAY;AAAA,MACV,WAAW,UAAU;AAAA,QACnB,SAAS;AAAA,UACP,QAAQ,CAAC,GAAG,GAAG,CAAC;AAAA,QAClB;AAAA,MACF,CAAC;AAAA,MACD,YAAY,UAAU;AAAA,QACpB;AAAA,MACF,CAAC;AAAA,MACD;AAAA,MACA,UAAU,UAAU;AAAA,QAClB,OAAO,CAAC,WAAW,WAAW;AAAA,MAChC,CAAC;AAAA,MACD,KAAK,UAAU;AAAA,QACb,aAAa;AAAA,QACb,gBAAgB;AAAA,UACd,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AAAA,MACD;AAAA,MACA;AAAA,MACA,UAAU,UAAU;AAAA,QAClB,YAAY;AAAA,MACd,CAAC;AAAA,MACD;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,UAAU;AAAA,QACjB,QAAQ;AAAA,MACV,CAAC;AAAA,MACD,MAAM,UAAU;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAAA,MACD;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,UAAU;AAAA,QACpB,aAAa;AAAA,MACf,CAAC;AAAA,MACD;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,CAAC;AAAA,IACX,aAAa;AAAA,MACX,YAAY;AAAA,QACV,OAAO;AAAA,UACL;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU;AAAA,EACZ,CAAC;AAED,YAAU,MAAM;AACd,QAAI,UAAU,CAAC,iBAAiB,WAAW,YAAY,OAAO,QAAQ,GAAG;AACvE,aAAO,SAAS,WAAW,OAAO;AAAA,IACpC;AACA,qBAAiB,UAAU;AAAA,EAC7B,GAAG,CAAC,SAAS,MAAM,CAAC;AAEpB,YAAU,MAAM;AACd,QAAI,QAAQ;AACV,aAAO,YAAY,CAAC,QAAQ;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,UAAU,MAAM,CAAC;AAErB,SACE,gBAAAF,MAAC,SAAI,WAAW,GAAG,cAAc,UAAU,UAAU,QAAQ,SAAS,GACnE;AAAA,cAAU,gBAAAD,MAAC,SAAI,WAAU,qBAAqB,kBAAO;AAAA,IAEtD,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IAEA,gBAAAA,MAAC,iBAAc,QAAgB;AAAA,IAE9B,UAAU,gBAAAA,MAAC,SAAI,WAAU,qBAAqB,kBAAO;AAAA,KACxD;AAEJ;","names":["useRef","React","jsx","jsx","jsx","React","jsx","jsx","ChevronDown","jsx","jsxs","ChevronDown","ChevronDown","jsx","jsxs","ChevronDown","ChevronDown","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","useRef","editor"]}
@@ -1,6 +1,6 @@
1
1
  /* Tailwind utilities */
2
2
  /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
3
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-100:oklch(93.6% .032 17.717);--color-red-300:oklch(80.8% .114 19.571);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-300:oklch(84.5% .143 164.978);--color-sky-100:oklch(95.1% .026 236.824);--color-sky-300:oklch(82.8% .111 230.318);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-white:#fff;--spacing:.25rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-mx-1{margin-inline:calc(var(--spacing)*-1)}.mx-1\.5{margin-inline:calc(var(--spacing)*1.5)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.block{display:block}.flex{display:flex}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-px{height:1px}.min-h-\[300px\]{min-height:300px}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-72{width:calc(var(--spacing)*72)}.w-full{width:100%}.w-px{width:1px}.max-w-7xl{max-width:var(--container-7xl)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\[8rem\]{min-width:8rem}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-default{cursor:default}.resize{resize:both}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-\[var\(--border\)\]{border-color:var(--border)}.border-amber-300{border-color:var(--color-amber-300)}.border-emerald-300{border-color:var(--color-emerald-300)}.border-red-300{border-color:var(--color-red-300)}.border-sky-300{border-color:var(--color-sky-300)}.border-zinc-200{border-color:var(--color-zinc-200)}.bg-\[var\(--border\)\]{background-color:var(--border)}.bg-\[var\(--popover\)\]{background-color:var(--popover)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-red-100{background-color:var(--color-red-100)}.bg-sky-100{background-color:var(--color-sky-100)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.p-0{padding:calc(var(--spacing)*0)}.p-1{padding:calc(var(--spacing)*1)}.p-1\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-4{padding:calc(var(--spacing)*4)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-\[var\(--popover-foreground\)\]{color:var(--popover-foreground)}.text-zinc-700{color:var(--color-zinc-700)}.capitalize{text-transform:capitalize}.italic{font-style:italic}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:scale-110:hover{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x)var(--tw-scale-y)}.hover\:bg-\[var\(--accent\)\]:hover{background-color:var(--accent)}.hover\:bg-zinc-100:hover{background-color:var(--color-zinc-100)}.hover\:text-\[var\(--accent-foreground\)\]:hover{color:var(--accent-foreground)}}.focus\:bg-\[var\(--accent\)\]:focus{background-color:var(--accent)}.focus\:text-\[var\(--accent-foreground\)\]:focus{color:var(--accent-foreground)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-\[var\(--ring\)\]:focus-visible{--tw-ring-color:var(--ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-50:disabled{opacity:.5}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[state\=on\]\:bg-\[var\(--accent\)\][data-state=on]{background-color:var(--accent)}.data-\[state\=on\]\:bg-zinc-900[data-state=on]{background-color:var(--color-zinc-900)}.data-\[state\=on\]\:text-\[var\(--accent-foreground\)\][data-state=on]{color:var(--accent-foreground)}.data-\[state\=on\]\:text-white[data-state=on]{color:var(--color-white)}@media (prefers-color-scheme:dark){.dark\:border-zinc-600{border-color:var(--color-zinc-600)}.dark\:border-zinc-700{border-color:var(--color-zinc-700)}.dark\:bg-zinc-900{background-color:var(--color-zinc-900)}.dark\:text-zinc-300{color:var(--color-zinc-300)}@media (hover:hover){.dark\:hover\:bg-zinc-800:hover{background-color:var(--color-zinc-800)}}.dark\:data-\[state\=on\]\:bg-zinc-100[data-state=on]{background-color:var(--color-zinc-100)}.dark\:data-\[state\=on\]\:text-zinc-900[data-state=on]{color:var(--color-zinc-900)}}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}
3
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-100:oklch(93.6% .032 17.717);--color-red-300:oklch(80.8% .114 19.571);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-300:oklch(84.5% .143 164.978);--color-sky-100:oklch(95.1% .026 236.824);--color-sky-300:oklch(82.8% .111 230.318);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-white:#fff;--spacing:.25rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-mx-1{margin-inline:calc(var(--spacing)*-1)}.mx-1\.5{margin-inline:calc(var(--spacing)*1.5)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.block{display:block}.flex{display:flex}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-px{height:1px}.min-h-\[300px\]{min-height:300px}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-72{width:calc(var(--spacing)*72)}.w-full{width:100%}.w-px{width:1px}.max-w-7xl{max-width:var(--container-7xl)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\[8rem\]{min-width:8rem}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-default{cursor:default}.resize{resize:both}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-\[var\(--border\)\]{border-color:var(--border)}.border-amber-300{border-color:var(--color-amber-300)}.border-emerald-300{border-color:var(--color-emerald-300)}.border-red-300{border-color:var(--color-red-300)}.border-sky-300{border-color:var(--color-sky-300)}.border-zinc-200{border-color:var(--color-zinc-200)}.bg-\[var\(--border\)\]{background-color:var(--border)}.bg-\[var\(--popover\)\]{background-color:var(--popover)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-red-100{background-color:var(--color-red-100)}.bg-sky-100{background-color:var(--color-sky-100)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-zinc-900{background-color:var(--color-zinc-900)}.p-0{padding:calc(var(--spacing)*0)}.p-1{padding:calc(var(--spacing)*1)}.p-1\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-4{padding:calc(var(--spacing)*4)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-\[var\(--popover-foreground\)\]{color:var(--popover-foreground)}.text-zinc-700{color:var(--color-zinc-700)}.capitalize{text-transform:capitalize}.italic{font-style:italic}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:scale-110:hover{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x)var(--tw-scale-y)}.hover\:bg-\[var\(--accent\)\]:hover{background-color:var(--accent)}.hover\:bg-zinc-100:hover{background-color:var(--color-zinc-100)}.hover\:text-\[var\(--accent-foreground\)\]:hover{color:var(--accent-foreground)}}.focus\:bg-\[var\(--accent\)\]:focus{background-color:var(--accent)}.focus\:text-\[var\(--accent-foreground\)\]:focus{color:var(--accent-foreground)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-\[var\(--ring\)\]:focus-visible{--tw-ring-color:var(--ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-50:disabled{opacity:.5}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[state\=on\]\:bg-\[var\(--accent\)\][data-state=on]{background-color:var(--accent)}.data-\[state\=on\]\:bg-zinc-900[data-state=on]{background-color:var(--color-zinc-900)}.data-\[state\=on\]\:text-\[var\(--accent-foreground\)\][data-state=on]{color:var(--accent-foreground)}.data-\[state\=on\]\:text-white[data-state=on]{color:var(--color-white)}.dark\:border-zinc-700:where(.dark,.dark *){border-color:var(--color-zinc-700)}.dark\:text-zinc-300:where(.dark,.dark *){color:var(--color-zinc-300)}@media (hover:hover){.dark\:hover\:bg-zinc-800:where(.dark,.dark *):hover{background-color:var(--color-zinc-800)}}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}
4
4
 
5
5
  /* Editor styles */
6
6
  /* Editor CSS Variables (defaults) - on :root for Radix Portal compatibility */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elia-ori/editor",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "基於 TipTap 的富文字編輯器套件",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",