@elia-ori/editor 0.1.7 → 0.1.8
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 +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -803,7 +803,7 @@ function EliaEditor({
|
|
|
803
803
|
editorClassName,
|
|
804
804
|
autofocus = false,
|
|
805
805
|
readOnly = false,
|
|
806
|
-
theme,
|
|
806
|
+
theme = "light",
|
|
807
807
|
onThemeToggle,
|
|
808
808
|
onImageUpload
|
|
809
809
|
}) {
|
|
@@ -881,7 +881,7 @@ function EliaEditor({
|
|
|
881
881
|
editor.setEditable(!readOnly);
|
|
882
882
|
}
|
|
883
883
|
}, [readOnly, editor]);
|
|
884
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("ori-editor", className), children: [
|
|
884
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("ori-editor", theme === "dark" && "dark", className), children: [
|
|
885
885
|
header && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ori-editor-header", children: header }),
|
|
886
886
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
887
887
|
Toolbar,
|
package/dist/index.cjs.map
CHANGED
|
@@ -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?: string;\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,\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', 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?: string;\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 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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -21,7 +21,7 @@ interface ToolbarProps {
|
|
|
21
21
|
config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';
|
|
22
22
|
toolbarStart?: React.ReactNode;
|
|
23
23
|
toolbarEnd?: React.ReactNode;
|
|
24
|
-
theme?:
|
|
24
|
+
theme?: 'light' | 'dark';
|
|
25
25
|
onThemeToggle?: () => void;
|
|
26
26
|
onImageUpload?: (file: File) => Promise<string> | void;
|
|
27
27
|
}
|
|
@@ -40,7 +40,7 @@ interface EliaEditorProps {
|
|
|
40
40
|
editorClassName?: string;
|
|
41
41
|
autofocus?: boolean;
|
|
42
42
|
readOnly?: boolean;
|
|
43
|
-
theme?:
|
|
43
|
+
theme?: 'light' | 'dark';
|
|
44
44
|
onThemeToggle?: () => void;
|
|
45
45
|
onImageUpload?: (file: File) => Promise<string> | void;
|
|
46
46
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ interface ToolbarProps {
|
|
|
21
21
|
config?: ToolbarItem[] | ToolbarItem[][] | 'all' | 'none';
|
|
22
22
|
toolbarStart?: React.ReactNode;
|
|
23
23
|
toolbarEnd?: React.ReactNode;
|
|
24
|
-
theme?:
|
|
24
|
+
theme?: 'light' | 'dark';
|
|
25
25
|
onThemeToggle?: () => void;
|
|
26
26
|
onImageUpload?: (file: File) => Promise<string> | void;
|
|
27
27
|
}
|
|
@@ -40,7 +40,7 @@ interface EliaEditorProps {
|
|
|
40
40
|
editorClassName?: string;
|
|
41
41
|
autofocus?: boolean;
|
|
42
42
|
readOnly?: boolean;
|
|
43
|
-
theme?:
|
|
43
|
+
theme?: 'light' | 'dark';
|
|
44
44
|
onThemeToggle?: () => void;
|
|
45
45
|
onImageUpload?: (file: File) => Promise<string> | void;
|
|
46
46
|
}
|
package/dist/index.js
CHANGED
|
@@ -764,7 +764,7 @@ function EliaEditor({
|
|
|
764
764
|
editorClassName,
|
|
765
765
|
autofocus = false,
|
|
766
766
|
readOnly = false,
|
|
767
|
-
theme,
|
|
767
|
+
theme = "light",
|
|
768
768
|
onThemeToggle,
|
|
769
769
|
onImageUpload
|
|
770
770
|
}) {
|
|
@@ -842,7 +842,7 @@ function EliaEditor({
|
|
|
842
842
|
editor.setEditable(!readOnly);
|
|
843
843
|
}
|
|
844
844
|
}, [readOnly, editor]);
|
|
845
|
-
return /* @__PURE__ */ jsxs7("div", { className: cn("ori-editor", className), children: [
|
|
845
|
+
return /* @__PURE__ */ jsxs7("div", { className: cn("ori-editor", theme === "dark" && "dark", className), children: [
|
|
846
846
|
header && /* @__PURE__ */ jsx12("div", { className: "ori-editor-header", children: header }),
|
|
847
847
|
/* @__PURE__ */ jsx12(
|
|
848
848
|
Toolbar,
|
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?: string;\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,\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', 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?: string;\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 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"]}
|