@qxs-bns/components-wc 0.0.30 → 0.0.31

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.
Files changed (49) hide show
  1. package/es/editor/blocksuite-editor.mjs +166 -357
  2. package/es/editor/blocksuite-editor.mjs.map +1 -1
  3. package/es/editor/toolbar.mjs +2 -0
  4. package/es/editor/toolbar.mjs.map +1 -0
  5. package/es/subject/action.mjs +7 -8
  6. package/es/subject/action.mjs.map +1 -1
  7. package/es/subject/blank-fill.mjs +243 -132
  8. package/es/subject/blank-fill.mjs.map +1 -1
  9. package/es/subject/layout.mjs +4 -4
  10. package/es/subject/layout.mjs.map +1 -1
  11. package/es/subject/page-end.mjs +1 -1
  12. package/es/subject/page-end.mjs.map +1 -1
  13. package/es/subject/scale.mjs +165 -126
  14. package/es/subject/scale.mjs.map +1 -1
  15. package/es/subject/shared-methods.mjs +2 -0
  16. package/es/subject/shared-methods.mjs.map +1 -0
  17. package/es/subject/shared-styles.mjs +75 -0
  18. package/es/subject/shared-styles.mjs.map +1 -0
  19. package/es/subject/single.mjs +243 -187
  20. package/es/subject/single.mjs.map +1 -1
  21. package/es/subject/sortable.mjs +7 -7
  22. package/es/subject/sortable.mjs.map +1 -1
  23. package/es/subject/text-fill.mjs +273 -138
  24. package/es/subject/text-fill.mjs.map +1 -1
  25. package/lib/editor/blocksuite-editor.cjs +166 -357
  26. package/lib/editor/blocksuite-editor.cjs.map +1 -1
  27. package/lib/editor/toolbar.cjs +2 -0
  28. package/lib/editor/toolbar.cjs.map +1 -0
  29. package/lib/subject/action.cjs +33 -34
  30. package/lib/subject/action.cjs.map +1 -1
  31. package/lib/subject/blank-fill.cjs +247 -136
  32. package/lib/subject/blank-fill.cjs.map +1 -1
  33. package/lib/subject/layout.cjs +2 -2
  34. package/lib/subject/layout.cjs.map +1 -1
  35. package/lib/subject/page-end.cjs +2 -2
  36. package/lib/subject/page-end.cjs.map +1 -1
  37. package/lib/subject/scale.cjs +165 -126
  38. package/lib/subject/scale.cjs.map +1 -1
  39. package/lib/subject/shared-methods.cjs +2 -0
  40. package/lib/subject/shared-methods.cjs.map +1 -0
  41. package/lib/subject/shared-styles.cjs +75 -0
  42. package/lib/subject/shared-styles.cjs.map +1 -0
  43. package/lib/subject/single.cjs +243 -187
  44. package/lib/subject/single.cjs.map +1 -1
  45. package/lib/subject/sortable.cjs +1 -1
  46. package/lib/subject/sortable.cjs.map +1 -1
  47. package/lib/subject/text-fill.cjs +273 -138
  48. package/lib/subject/text-fill.cjs.map +1 -1
  49. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"blocksuite-editor.mjs","sources":["../../../../packages/components-wc/src/editor/blocksuite-editor.ts"],"sourcesContent":["import { Editor, Extension, mergeAttributes, Node as TiptapNode } from '@tiptap/core'\nimport Blockquote from '@tiptap/extension-blockquote'\nimport Bold from '@tiptap/extension-bold'\nimport BulletList from '@tiptap/extension-bullet-list'\nimport Code from '@tiptap/extension-code'\nimport Document from '@tiptap/extension-document'\nimport Heading from '@tiptap/extension-heading'\nimport History from '@tiptap/extension-history'\nimport HorizontalRule from '@tiptap/extension-horizontal-rule'\nimport Image from '@tiptap/extension-image'\nimport Italic from '@tiptap/extension-italic'\nimport Link from '@tiptap/extension-link'\nimport ListItem from '@tiptap/extension-list-item'\nimport OrderedList from '@tiptap/extension-ordered-list'\nimport Paragraph from '@tiptap/extension-paragraph'\nimport Placeholder from '@tiptap/extension-placeholder'\nimport Strike from '@tiptap/extension-strike'\nimport { Table } from '@tiptap/extension-table'\nimport { TableCell } from '@tiptap/extension-table-cell'\nimport { TableHeader } from '@tiptap/extension-table-header'\nimport { TableRow } from '@tiptap/extension-table-row'\nimport Text from '@tiptap/extension-text'\nimport TextAlign from '@tiptap/extension-text-align'\nimport Underline from '@tiptap/extension-underline'\nimport { css, html, LitElement } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport { safeCustomElement } from '../base/define'\n\ntype ToolbarMode = 'slash' | 'header'\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n taskList: {\n toggleTaskList: () => ReturnType\n }\n }\n}\n\nconst DEFAULT_IMAGE_WIDTH = 560\nconst MIN_IMAGE_WIDTH = 24\nconst DEFAULT_HEADER_PLACEHOLDER = '输入内容'\nconst DEFAULT_SLASH_PLACEHOLDER = '输入 / 唤出快捷命令'\n\nconst TaskList = TiptapNode.create({\n name: 'taskList',\n group: 'block list',\n content: 'taskItem+',\n defining: true,\n\n parseHTML() {\n return [{ tag: 'ul[data-type=\"taskList\"]' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['ul', mergeAttributes(HTMLAttributes, { 'data-type': 'taskList' }), 0]\n },\n\n addCommands() {\n return {\n toggleTaskList: () => ({ commands }) => commands.toggleList(this.name, 'taskItem'),\n }\n },\n})\n\nconst TaskItem = TiptapNode.create({\n name: 'taskItem',\n defining: true,\n content: 'paragraph block*',\n\n addAttributes() {\n return {\n checked: {\n default: false,\n parseHTML: element => element.getAttribute('data-checked') === 'true',\n renderHTML: attributes => ({ 'data-checked': String(Boolean(attributes.checked)) }),\n },\n }\n },\n\n parseHTML() {\n return [{ tag: 'li[data-type=\"taskItem\"]' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n const checked = Boolean(HTMLAttributes.checked)\n\n return [\n 'li',\n mergeAttributes(HTMLAttributes, { 'data-type': 'taskItem' }),\n [\n 'label',\n { contenteditable: 'false' },\n ['input', { type: 'checkbox', checked: checked ? 'checked' : null }],\n ['span'],\n ],\n ['div', 0],\n ]\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => this.editor.commands.splitListItem(this.name),\n Tab: () => this.editor.commands.sinkListItem(this.name),\n 'Shift-Tab': () => this.editor.commands.liftListItem(this.name),\n }\n },\n})\n\nconst ExtendedImage = Image.extend({\n addAttributes() {\n return {\n ...this.parent?.(),\n width: {\n default: null,\n parseHTML: (element) => {\n const attr = element.getAttribute('width')\n const value = Number(attr)\n return Number.isFinite(value) && value > 0 ? value : null\n },\n renderHTML: attributes => attributes.width ? { width: String(attributes.width) } : {},\n },\n align: {\n default: 'center',\n parseHTML: element => element.getAttribute('data-align') || 'center',\n renderHTML: attributes => attributes.align ? { 'data-align': String(attributes.align) } : {},\n },\n }\n },\n\n renderHTML({ HTMLAttributes }) {\n const width = Number(HTMLAttributes.width)\n\n const style = [\n 'max-width:100%',\n 'height:auto',\n Number.isFinite(width) && width > 0 ? `width:${width}px` : '',\n HTMLAttributes.style || '',\n ]\n .filter(Boolean)\n .join(';')\n\n return ['img', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { style })]\n },\n})\n\n@safeCustomElement('qxs-blocksuite-editor')\nexport class QxsBlocksuiteEditor extends LitElement {\n static styles = css`\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, sans-serif;\n }\n\n .editor-wrapper {\n border: 1px solid #e3e3e3;\n border-radius: 12px;\n background: #fff;\n overflow: visible;\n position: relative;\n min-height: 80px;\n }\n\n .editor-wrapper:focus-within {\n border-color: var(--qxs-color-primary, #3D61E3);\n }\n\n .editor-wrapper.preview {\n border: none;\n border-radius: 0;\n background: transparent;\n }\n\n .editor-wrapper.preview .editor-content {\n padding: 8px 12px;\n min-height: unset;\n }\n\n .editor-header {\n max-height: 0;\n opacity: 0;\n overflow: hidden;\n padding: 0 16px;\n border-bottom: 1px solid transparent;\n transition:\n max-height 0.24s ease,\n opacity 0.18s ease,\n padding 0.24s ease,\n border-color 0.24s ease;\n }\n\n .editor-header.is-visible {\n max-height: 132px;\n opacity: 1;\n overflow: visible;\n padding: 10px 12px;\n border-bottom-color: #eef1f5;\n }\n\n .editor-header__inner {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n overflow: visible;\n }\n\n .editor-content {\n padding: 12px 16px;\n min-height: 80px;\n cursor: text;\n }\n\n .editor-content:empty::before {\n content: attr(data-empty-hint);\n color: #c0c0c0;\n pointer-events: none;\n display: block;\n padding-top: 28px;\n text-align: center;\n }\n\n .editor-content .ProseMirror:empty {\n min-height: 80px;\n }\n\n .ProseMirror p.is-editor-empty:first-child::before {\n content: attr(data-placeholder);\n color: #c0c0c0;\n pointer-events: none;\n float: left;\n height: 0;\n }\n\n .ProseMirror p.is-empty:only-child::before,\n .ProseMirror p.is-empty:only-child > br:first-child + *::before {\n content: attr(data-placeholder);\n color: #c0c0c0;\n pointer-events: none;\n float: left;\n height: 0;\n }\n\n .editor-wrapper.loading {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n background: #fafafa;\n }\n\n .loading-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n color: #909399;\n font-size: 14px;\n }\n\n .loading-spinner {\n width: 24px;\n height: 24px;\n border: 2px solid #e3e3e3;\n border-top-color: var(--qxs-color-primary, #3D61E3);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n }\n\n @keyframes spin {\n to { transform: rotate(360deg); }\n }\n\n .ProseMirror {\n outline: none;\n line-height: 1.7;\n color: #37352f;\n font-size: 15px;\n }\n\n .ProseMirror > * + * {\n margin-top: 0.5em;\n }\n\n .ProseMirror > *:first-child {\n margin-top: 0 !important;\n }\n\n .ProseMirror p {\n margin: 0;\n }\n\n .ProseMirror h1 {\n font-size: 1.875em;\n font-weight: 700;\n margin: 0 0 0.25em;\n line-height: 1.3;\n }\n\n .ProseMirror > h1:first-child {\n margin-top: 0 !important;\n line-height: 1.15;\n }\n\n .ProseMirror > p:first-child {\n margin-top: 0 !important;\n }\n\n .ProseMirror h2 {\n font-size: 1.5em;\n font-weight: 600;\n margin: 0.5em 0 0.25em;\n line-height: 1.3;\n }\n\n .ProseMirror h3 {\n font-size: 1.25em;\n font-weight: 600;\n margin: 0.5em 0 0.25em;\n line-height: 1.3;\n }\n\n .ProseMirror ul,\n .ProseMirror ol {\n padding-left: 1.5em;\n margin: 0;\n }\n\n .ProseMirror ul[data-type=\"taskList\"] {\n padding-left: 0;\n list-style: none;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n list-style: none;\n margin: 0.2em 0;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] > label {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 28px;\n flex: 0 0 18px;\n cursor: pointer;\n user-select: none;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] > label > input {\n width: 14px;\n height: 14px;\n margin: 0;\n cursor: pointer;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] > label > span {\n display: none;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] > div {\n flex: 1;\n min-width: 0;\n }\n\n .ProseMirror li[data-type=\"taskItem\"][data-checked=\"true\"] > div p {\n color: #8a8f98;\n text-decoration: line-through;\n }\n\n .ProseMirror li {\n margin: 0.1em 0;\n }\n\n .ProseMirror li::marker {\n color: #37352f;\n }\n\n .ProseMirror strong {\n font-weight: 700;\n }\n\n .ProseMirror em {\n font-style: italic;\n font-synthesis: none;\n transform: skewX(-12deg);\n display: inline-block;\n }\n\n .ProseMirror u {\n text-decoration: underline;\n }\n\n .ProseMirror s {\n text-decoration: line-through;\n color: #787774;\n }\n\n .ProseMirror code {\n background: rgba(135, 131, 120, 0.14);\n color: #eb5757;\n padding: 2px 4px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', Menlo, Consolas, monospace;\n font-size: 85%;\n }\n\n .ProseMirror pre {\n background: #f6f6f7;\n border-radius: 8px;\n padding: 12px 16px;\n overflow-x: auto;\n }\n\n .ProseMirror pre code {\n background: none;\n padding: 0;\n color: #37352f;\n }\n\n .ProseMirror blockquote {\n border-left: 3px solid #e3e3e3;\n padding-left: 1em;\n margin: 0.75em 0;\n color: #787774;\n }\n\n .ProseMirror hr {\n border: none;\n border-top: 1px solid #e3e3e3;\n margin: 1.5em 0;\n }\n\n .ProseMirror img {\n max-width: 100%;\n height: auto;\n border-radius: 8px;\n }\n\n .ProseMirror img[data-align=\"left\"] {\n display: block !important;\n margin: 0 auto 0 0 !important;\n }\n\n .ProseMirror img[data-align=\"center\"] {\n display: block !important;\n margin: 0 auto !important;\n }\n\n .ProseMirror img[data-align=\"right\"] {\n display: block !important;\n margin: 0 0 0 auto !important;\n }\n\n .ProseMirror a {\n color: var(--qxs-color-primary, #3D61E3);\n text-decoration: underline;\n cursor: pointer;\n }\n\n .ProseMirror img.ProseMirror-selectednode {\n outline: 2px solid var(--qxs-color-primary, #3D61E3);\n }\n\n /* Table styles */\n .ProseMirror table {\n border-collapse: collapse;\n width: 100%;\n margin: 1em 0;\n border: 1px solid #e3e3e3;\n border-radius: 8px;\n overflow: hidden;\n }\n\n .ProseMirror th,\n .ProseMirror td {\n border: 1px solid #e3e3e3;\n padding: 8px 12px;\n text-align: left;\n vertical-align: top;\n }\n\n .ProseMirror th {\n background: #fafafa;\n font-weight: 600;\n }\n\n .ProseMirror .selectedCell {\n background: rgba(30, 150, 252, 0.1);\n }\n\n /* Table Cell Toolbar */\n .table-cell-toolbar {\n position: absolute;\n z-index: 50;\n display: flex;\n gap: 2px;\n padding: 4px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n\n .table-cell-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #606266;\n transition: all 0.15s;\n }\n\n .table-cell-toolbar-btn:hover {\n background: #ecf5ff;\n color: var(--qxs-color-primary, #3D61E3);\n }\n\n .table-cell-toolbar-btn.danger:hover {\n background: #fef0f0;\n color: #f56c6c;\n }\n\n /* Bubble Menu */\n .bubble-menu {\n position: absolute;\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 6px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n z-index: 100;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.15s, visibility 0.15s, transform 0.15s;\n transform: translateY(4px);\n max-width: calc(100vw - 40px);\n }\n\n .bubble-menu.is-visible {\n opacity: 1;\n visibility: visible;\n transform: translateY(0);\n }\n\n .bubble-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n color: #37352f;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s;\n position: relative;\n }\n\n .bubble-btn:hover {\n background: rgba(55, 53, 47, 0.08);\n }\n\n .bubble-btn.is-active {\n background: var(--qxs-color-primary, #3D61E3);\n color: #fff;\n }\n\n .bubble-btn.danger:hover {\n background: #fef0f0;\n color: #f56c6c;\n }\n\n .bubble-btn svg {\n width: 16px;\n height: 16px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n .bubble-divider {\n width: 1px;\n height: 16px;\n background: #e3e3e3;\n margin: 0 3px;\n }\n\n /* Dropdown */\n .bubble-dropdown {\n position: relative;\n }\n\n .bubble-dropdown-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 0 6px;\n height: 28px;\n border: none;\n background: transparent;\n color: #37352f;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n font-family: inherit;\n transition: all 0.15s;\n white-space: nowrap;\n }\n\n .bubble-dropdown-btn:hover {\n background: rgba(55, 53, 47, 0.08);\n }\n\n .bubble-dropdown-btn svg {\n width: 12px;\n height: 12px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n .bubble-dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 4px;\n min-width: 120px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n padding: 4px;\n opacity: 0;\n visibility: hidden;\n transform: translateY(-4px);\n transition: all 0.15s;\n z-index: 101;\n }\n\n .bubble-dropdown:hover .bubble-dropdown-menu,\n .bubble-dropdown.is-open .bubble-dropdown-menu {\n opacity: 1;\n visibility: visible;\n transform: translateY(0);\n }\n\n .bubble-dropdown-item {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 6px 8px;\n border: none;\n background: transparent;\n color: #37352f;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n font-family: inherit;\n text-align: left;\n transition: all 0.15s;\n }\n\n .bubble-dropdown-item:hover {\n background: rgba(55, 53, 47, 0.08);\n }\n\n .bubble-dropdown-item.is-active {\n background: var(--qxs-color-primary, #3D61E3);\n color: #fff;\n }\n\n .bubble-dropdown-item svg {\n width: 16px;\n height: 16px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n .image-input {\n display: none;\n }\n\n .table-grid-preview {\n display: grid;\n grid-template-columns: repeat(10, 18px);\n gap: 2px;\n padding: 8px;\n }\n\n .table-grid-preview .table-cell {\n width: 18px;\n height: 18px;\n border: 1px solid #e3e3e3;\n border-radius: 2px;\n background: #fff;\n cursor: pointer;\n transition: all 0.1s;\n }\n\n .table-grid-preview .table-cell:hover {\n background: rgba(30, 150, 252, 0.3);\n border-color: var(--qxs-color-primary, #3D61E3);\n }\n\n .table-grid-preview .table-cell.selected {\n background: rgba(30, 150, 252, 0.15);\n border-color: rgba(30, 150, 252, 0.5);\n }\n\n .table-size-hint {\n text-align: center;\n padding: 4px 8px 6px;\n font-size: 10px;\n color: #8c8c8c;\n }\n\n .image-size-control {\n display: flex;\n align-items: center;\n gap: 6px;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid #e3e3e3;\n white-space: nowrap;\n }\n\n .image-size-label {\n font-size: 12px;\n color: #7a7f88;\n }\n\n .image-size-range {\n width: 72px;\n height: 26px;\n padding: 0 8px;\n border: 1px solid #d8dde6;\n border-radius: 6px;\n font-size: 12px;\n color: #37352f;\n background: #fff;\n outline: none;\n }\n\n .image-size-range:focus {\n border-color: var(--qxs-color-primary, #3D61E3);\n }\n\n .link-editor {\n position: absolute;\n z-index: 120;\n display: grid;\n gap: 8px;\n min-width: 320px;\n padding: 10px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 10px;\n box-shadow: 0 12px 32px rgba(15, 23, 42, 0.14);\n }\n\n .link-editor__field {\n display: grid;\n gap: 4px;\n }\n\n .link-editor__label {\n font-size: 12px;\n color: #6b7280;\n line-height: 1;\n }\n\n .link-editor__input {\n min-width: 0;\n height: 32px;\n padding: 0 10px;\n border: 1px solid #d8dde6;\n border-radius: 8px;\n outline: none;\n font-size: 13px;\n color: #37352f;\n background: #fff;\n }\n\n .link-editor__input:focus {\n border-color: var(--qxs-color-primary, #3D61E3);\n }\n\n .link-editor__actions {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .link-editor__action {\n height: 32px;\n padding: 0 12px;\n border: 1px solid #d8dde6;\n border-radius: 8px;\n background: #fff;\n color: #4b5563;\n font-size: 12px;\n font-family: inherit;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n\n .link-editor__action:hover {\n border-color: #c3cad5;\n background: #f8fafc;\n }\n\n .link-editor__action.primary {\n border-color: var(--qxs-color-primary, #3D61E3);\n background: var(--qxs-color-primary, #3D61E3);\n color: #fff;\n }\n\n .link-editor__action.danger {\n color: #f56c6c;\n }\n\n /* Image Toolbar */\n .image-toolbar {\n position: absolute;\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 6px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n z-index: 100;\n transform: translateX(-50%);\n }\n\n .image-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #595959;\n transition: all 0.15s;\n }\n\n .image-toolbar-btn:hover {\n background: #f5f5f5;\n color: var(--qxs-color-primary, #3D61E3);\n }\n\n .image-toolbar-btn.danger:hover {\n background: #fff1f0;\n color: #ff4d4f;\n }\n\n .image-toolbar-btn svg {\n width: 16px;\n height: 16px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n .image-toolbar-divider {\n width: 1px;\n height: 20px;\n background: #e3e3e3;\n margin: 0 4px;\n }\n\n /* Image More Menu */\n .image-more-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n padding: 4px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n z-index: 101;\n min-width: 120px;\n }\n\n .image-more-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border: none;\n background: transparent;\n width: 100%;\n text-align: left;\n font-size: 13px;\n color: #595959;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .image-more-menu-item:hover {\n background: #f5f5f5;\n color: var(--qxs-color-primary, #3D61E3);\n }\n\n .image-more-menu-item svg {\n width: 14px;\n height: 14px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n /* Selected Image */\n .ProseMirror img.selected {\n outline: 2px solid var(--qxs-color-primary, #3D61E3);\n outline-offset: 2px;\n }\n `\n\n @property({ type: String, attribute: 'content' })\n content = ''\n\n @property({ type: String, attribute: 'model-value' })\n 'model-value' = ''\n\n @property({ type: String, attribute: 'placeholder' })\n placeholder = DEFAULT_HEADER_PLACEHOLDER\n\n @property({ type: String, attribute: 'toolbar-mode' })\n 'toolbar-mode': ToolbarMode = 'header'\n\n @property({ type: String, attribute: 'header-always-visible' })\n 'header-always-visible' = 'false'\n\n @property({ type: String, attribute: 'use-model' })\n 'use-model' = 'false'\n\n @property({ type: String, attribute: 'readonly' })\n readonly = 'false'\n\n @property({ type: String, attribute: 'preview' })\n preview = 'false'\n\n @property({ type: String, attribute: 'custom-styles' })\n 'custom-styles' = ''\n\n private _injectedStyleEl: HTMLStyleElement | null = null\n\n private _injectCustomStyles() {\n const shadow = this.shadowRoot\n if (!shadow) { return }\n\n if (this._injectedStyleEl) {\n this._injectedStyleEl.remove()\n this._injectedStyleEl = null\n }\n\n if (!this['custom-styles']) { return }\n\n const styleEl = document.createElement('style')\n styleEl.textContent = this['custom-styles']\n shadow.appendChild(styleEl)\n this._injectedStyleEl = styleEl\n }\n\n private get _useModelValue(): boolean {\n return this['use-model'] === true || this['use-model'] === 'true' || this['use-model'] === '' || this.hasAttribute('use-model')\n }\n\n private get _readonlyValue(): boolean {\n return this.readonly !== false && this.readonly !== 'false'\n }\n\n private get _previewValue(): boolean {\n return this.preview !== false && this.preview !== 'false'\n }\n\n private get _isEditable(): boolean {\n return !this._readonlyValue && !this._previewValue\n }\n\n private get _toolbarModeValue(): ToolbarMode {\n return this['toolbar-mode'] === 'header' ? 'header' : 'slash'\n }\n\n private get _headerAlwaysVisibleValue(): boolean {\n return this['header-always-visible'] === true\n || this['header-always-visible'] === 'true'\n || this['header-always-visible'] === ''\n || this.hasAttribute('header-always-visible')\n }\n\n private get _resolvedPlaceholder(): string {\n if (\n this.placeholder\n && this.placeholder !== DEFAULT_HEADER_PLACEHOLDER\n && this.placeholder !== DEFAULT_SLASH_PLACEHOLDER\n ) {\n return this.placeholder\n }\n return this._toolbarModeValue === 'header'\n ? DEFAULT_HEADER_PLACEHOLDER\n : DEFAULT_SLASH_PLACEHOLDER\n }\n\n @property({ type: Object, attribute: 'upload-image' })\n 'upload-image': (file: File) => Promise<string> = async (file: File) => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = e => resolve(e.target?.result as string)\n reader.onerror = reject\n reader.readAsDataURL(file)\n })\n }\n\n @state() private _editor: Editor | null = null\n @state() private _pendingContent: string | null = null\n private _tableRows = 3\n private _tableCols = 3\n @state() private _hoverRow = 0\n @state() private _hoverCol = 0\n @state() private _tableDropdownOpen = false\n @state() private _tableCellToolbar: { x: number, y: number, visible: boolean, cellRow: number, cellCol: number } = { x: 0, y: 0, visible: false, cellRow: 0, cellCol: 0 }\n @state() private _imageToolbar: { x: number, y: number, visible: boolean } = { x: 0, y: 0, visible: false }\n @state() private _linkEditor = { x: 0, y: 0, visible: false, url: '', label: '' }\n @state() private _isEditorFocused = false\n @state() private _selectedImage: { pos: number, width: number, align: string } | null = null\n private _hasSlashCommand = false\n private _slashCommandRange: { from: number, to: number } | null = null\n private _isUpdating = false\n private _pendingImageInsertPos: number | null = null\n private _linkSelection: { from: number, to: number } | null = null\n private _preserveFocusOnInternalClick = false\n\n private _initEditor() {\n if (this._editor) { return }\n\n const el = this.shadowRoot?.querySelector<HTMLElement>('.editor-content')\n if (!el) {\n requestAnimationFrame(() => this._initEditor())\n return\n }\n\n while (el.firstChild) {\n el.removeChild(el.firstChild)\n }\n\n const useModel = this._useModelValue\n const modelValue = this.getAttribute('model-value') ?? this['model-value']\n const contentValue = this.content\n\n const initialContent = useModel\n ? (this._pendingContent ?? modelValue) || '<p></p>'\n : (this._pendingContent ?? contentValue) || '<p></p>'\n\n const extensions: any[] = [\n Document,\n Paragraph,\n Text,\n Bold,\n Italic,\n Underline,\n Strike,\n Code,\n Heading.configure({ levels: [1, 2, 3] }),\n BulletList,\n OrderedList,\n TaskList,\n TaskItem,\n ListItem,\n Blockquote,\n HorizontalRule,\n History,\n ExtendedImage.configure({\n inline: false,\n allowBase64: true,\n }),\n Link.extend({\n inclusive: false,\n }).configure({\n openOnClick: false,\n HTMLAttributes: {\n rel: 'noopener noreferrer',\n },\n }),\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Table.configure({\n resizable: true,\n }),\n TableRow,\n TableCell,\n TableHeader,\n Placeholder.configure({\n placeholder: this._resolvedPlaceholder,\n }),\n ]\n\n this._editor = new Editor({\n element: el,\n extensions,\n editable: this._isEditable,\n content: initialContent,\n })\n\n this._pendingContent = null\n\n this._editor.on('selectionUpdate', () => {\n if (this._toolbarModeValue === 'slash') {\n this._updateBubbleMenuPosition()\n }\n if (this._editor?.isActive('table')) {\n this._showTableCellToolbar()\n }\n else {\n this._hideTableCellToolbar()\n }\n this._syncImageSelectionState()\n })\n\n this._editor.on('transaction', () => {\n if (this._editor?.isActive('table')) {\n this._showTableCellToolbar()\n }\n else {\n this._hideTableCellToolbar()\n }\n this._checkSlashCommand()\n this._setupTableEdgeDetection()\n this._syncImageSelectionState()\n })\n\n this._editor.on('update', () => {\n this._emitContentChange()\n })\n }\n\n private _tableEdgeDetectionSetup = false\n\n private _toggleTaskItemChecked(event: MouseEvent) {\n const target = event.target\n const editor = this._editor\n if (!(target instanceof HTMLInputElement) || target.type !== 'checkbox' || !editor) {\n return\n }\n\n const taskItem = target.closest('li[data-type=\"taskItem\"]')\n if (!taskItem) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n const basePos = editor.view.posAtDOM(taskItem, 0)\n const searchFrom = Math.max(0, basePos - 2)\n const searchTo = Math.min(editor.state.doc.content.size, basePos + 2)\n\n let taskItemPos: number | null = null\n editor.state.doc.nodesBetween(searchFrom, searchTo, (node, pos) => {\n if (node.type.name === 'taskItem') {\n taskItemPos = pos\n return false\n }\n return undefined\n })\n\n if (taskItemPos === null) {\n return\n }\n\n const node = editor.state.doc.nodeAt(taskItemPos)\n if (!node || node.type.name !== 'taskItem') {\n return\n }\n\n editor.view.dispatch(editor.state.tr.setNodeMarkup(taskItemPos, undefined, {\n ...node.attrs,\n checked: !node.attrs.checked,\n }))\n }\n\n private _emitContentChange() {\n if (!this._editor) { return }\n const html = this._editor.getHTML()\n\n this.dispatchEvent(new CustomEvent('content-change', {\n detail: html,\n bubbles: true,\n composed: true,\n }))\n }\n\n private _setupTableEdgeDetection() {\n const editorContent = this.shadowRoot?.querySelector('.editor-content')\n const editorWrapper = this.shadowRoot?.querySelector('.editor-wrapper')\n if (!editorContent || this._tableEdgeDetectionSetup) { return }\n\n this._tableEdgeDetectionSetup = true\n\n const handleEditorClick = (event: MouseEvent) => {\n this._toggleTaskItemChecked(event)\n\n const target = event.target\n if (\n target instanceof Element\n && target.closest('.editor-header, .bubble-menu, .table-cell-toolbar, .image-toolbar, .link-editor')\n ) {\n return\n }\n if (!this._isEditable) {\n return\n }\n this._editor?.chain().focus().run()\n }\n\n editorContent.addEventListener('click', handleEditorClick)\n editorWrapper?.addEventListener('click', handleEditorClick)\n }\n\n private _handleWrapperFocusIn() {\n this._preserveFocusOnInternalClick = false\n this._isEditorFocused = true\n }\n\n private _handleWrapperMouseDown(event: MouseEvent) {\n const target = event.target\n if (\n !this._isEditable\n || !(target instanceof Element)\n || target.closest('.editor-header, .bubble-menu, .table-cell-toolbar, .image-toolbar, .link-editor')\n ) {\n return\n }\n\n this._preserveFocusOnInternalClick = true\n requestAnimationFrame(() => {\n this._preserveFocusOnInternalClick = false\n })\n }\n\n private _handleWrapperFocusOut(event: FocusEvent) {\n const nextTarget = event.relatedTarget as Node | null\n const wrapper = this.shadowRoot?.querySelector('.editor-wrapper')\n if (this._preserveFocusOnInternalClick) {\n return\n }\n if (nextTarget && wrapper?.contains(nextTarget)) {\n return\n }\n this._isEditorFocused = false\n this._tableDropdownOpen = false\n this._closeLinkEditor()\n }\n\n private _isHeaderVisible(): boolean {\n return this._toolbarModeValue === 'header'\n && !this._previewValue\n && (\n this._headerAlwaysVisibleValue\n || this._isEditorFocused\n || this._tableDropdownOpen\n || Boolean(this._selectedImage)\n )\n }\n\n private _getImageSelection() {\n const editor = this._editor\n const selection: any = editor?.state.selection\n if (!editor || !selection?.node || selection.node.type?.name !== 'image') {\n return null\n }\n\n return {\n pos: selection.from,\n attrs: selection.node.attrs ?? {},\n }\n }\n\n private _getImageMaxWidth() {\n const editorContent = this.shadowRoot?.querySelector<HTMLElement>('.editor-content')\n const availableWidth = (editorContent?.clientWidth ?? DEFAULT_IMAGE_WIDTH) - 32\n return Math.max(MIN_IMAGE_WIDTH, Math.min(DEFAULT_IMAGE_WIDTH, availableWidth))\n }\n\n private async _getImageNaturalWidth(file: File) {\n return await new Promise<number | null>((resolve) => {\n const objectUrl = URL.createObjectURL(file)\n const image = new window.Image()\n\n image.onload = () => {\n const naturalWidth = image.naturalWidth\n URL.revokeObjectURL(objectUrl)\n resolve(Number.isFinite(naturalWidth) && naturalWidth > 0 ? naturalWidth : null)\n }\n\n image.onerror = () => {\n URL.revokeObjectURL(objectUrl)\n resolve(null)\n }\n\n image.src = objectUrl\n })\n }\n\n private _syncImageSelectionState() {\n const selection = this._getImageSelection()\n if (!selection) {\n this._selectedImage = null\n if (this._toolbarModeValue === 'slash') {\n this._hideImageToolbar()\n }\n return\n }\n\n const width = Number(selection.attrs.width)\n const align = String(selection.attrs.align || 'center')\n this._selectedImage = {\n pos: selection.pos,\n width: Number.isFinite(width) && width > 0 ? width : this._getImageMaxWidth(),\n align,\n }\n\n if (this._toolbarModeValue !== 'slash') {\n this._hideImageToolbar()\n return\n }\n\n const editor = this._editor\n const wrapperRect = this.shadowRoot?.querySelector('.editor-wrapper')?.getBoundingClientRect()\n if (!editor || !wrapperRect) { return }\n const coords = editor.view.coordsAtPos(selection.pos)\n const x = coords.left - wrapperRect.left + (coords.right - coords.left) / 2\n const y = coords.top - wrapperRect.top - 40\n this._showImageToolbar({ x, y })\n }\n\n private _clearSlashCommandText() {\n if (!this._editor || !this._slashCommandRange) { return }\n const { from, to } = this._slashCommandRange\n this._editor.chain().focus().deleteRange({ from, to }).run()\n this._hasSlashCommand = false\n this._slashCommandRange = null\n }\n\n private _checkSlashCommand() {\n if (!this._editor) { return }\n const { selection } = this._editor.state\n if (!selection.empty) {\n this._hasSlashCommand = false\n this._slashCommandRange = null\n return\n }\n\n const { $from } = selection as any\n const textBefore = $from.parent.textBetween(0, $from.parentOffset, ' ', ' ')\n const matched = /(?:^|\\s)(\\/\\S*)$/.exec(textBefore)\n\n if (!matched) {\n this._hasSlashCommand = false\n this._slashCommandRange = null\n return\n }\n\n const slashText = matched[1]\n this._hasSlashCommand = true\n this._slashCommandRange = {\n from: selection.from - slashText.length,\n to: selection.from,\n }\n }\n\n firstUpdated() {\n this._injectCustomStyles()\n this._initEditor()\n }\n\n updated(changed: Map<string, unknown>) {\n if (changed.has('custom-styles')) {\n this._injectCustomStyles()\n }\n\n if (this._editor) {\n if (changed.has('content') || (changed.has('model-value') && this._useModelValue)) {\n const newContent = this._useModelValue ? this['model-value'] : this.content\n if (newContent !== this._editor.getHTML()) {\n this._editor.commands.setContent(newContent || '<p></p>')\n }\n }\n if (changed.has('readonly') || changed.has('preview')) {\n this._editor.setEditable(this._isEditable)\n }\n return\n }\n\n // 编辑器未初始化时,只保存待处理内容,不重复初始化\n if (changed.has('content')) {\n this._pendingContent = this.content\n }\n\n if (changed.has('model-value') && this._useModelValue) {\n this._pendingContent = this['model-value']\n }\n\n // 只有在 firstUpdated 时才会初始化编辑器\n // 这里不再重复调用 _initEditor()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this._editor?.destroy()\n this._editor = null\n }\n\n getContent(): string {\n return this._editor?.getHTML() ?? ''\n }\n\n forceUpdate(): void {\n this.requestUpdate()\n if (this._editor) {\n const newContent = this._useModelValue ? this['model-value'] : this.content\n if (newContent !== this._editor.getHTML()) {\n this._editor.commands.setContent(newContent || '<p></p>')\n }\n }\n }\n\n private _applyFormat(command: () => void) {\n this._clearSlashCommandText()\n command()\n }\n\n private _getSlashCommandContext() {\n const editor = this._editor\n const range = this._slashCommandRange\n if (!editor || !range) { return null }\n\n const $from = editor.state.doc.resolve(range.from)\n return {\n lineFrom: $from.start(),\n lineTo: range.from,\n }\n }\n\n private _applySlashLineMark(\n applyMark: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n clearMark: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n ) {\n const editor = this._editor\n const context = this._getSlashCommandContext()\n if (!editor || !context) { return false }\n\n this._clearSlashCommandText()\n\n if (context.lineFrom < context.lineTo) {\n applyMark(\n editor.chain().focus().setTextSelection({ from: context.lineFrom, to: context.lineTo }),\n ).run()\n }\n\n clearMark(\n editor.chain().focus().setTextSelection({ from: context.lineTo, to: context.lineTo }),\n ).run()\n return true\n }\n\n private _applyToolbarLineMark(\n applyMark: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n clearMark: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n ) {\n const editor = this._editor\n if (!editor) { return false }\n\n const { selection } = editor.state\n const range = selection.empty\n ? (() => {\n const $from = editor.state.doc.resolve(selection.from)\n return { from: $from.start(), to: $from.end() }\n })()\n : { from: selection.from, to: selection.to }\n\n if (range.from >= range.to) {\n return false\n }\n\n applyMark(\n editor.chain().focus().setTextSelection(range),\n ).run()\n\n clearMark(\n editor.chain().focus().setTextSelection({ from: range.to, to: range.to }),\n ).run()\n\n return true\n }\n\n private _applySlashLineBlock(\n applyBlock: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n ) {\n const editor = this._editor\n const context = this._getSlashCommandContext()\n if (!editor || !context) { return false }\n\n this._clearSlashCommandText()\n applyBlock(\n editor.chain().focus().setTextSelection({ from: context.lineFrom, to: context.lineTo }),\n ).run()\n return true\n }\n\n private _toggleBold() {\n if (this._applySlashLineMark(chain => chain.setBold(), chain => chain.unsetBold())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleBold(), chain => chain.unsetBold())\n }\n\n private _toggleItalic() {\n if (this._applySlashLineMark(chain => chain.setItalic(), chain => chain.unsetItalic())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleItalic(), chain => chain.unsetItalic())\n }\n\n private _toggleUnderline() {\n if (this._applySlashLineMark(chain => chain.setUnderline(), chain => chain.unsetUnderline())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleUnderline(), chain => chain.unsetUnderline())\n }\n\n private _toggleStrike() {\n if (this._applySlashLineMark(chain => chain.setStrike(), chain => chain.unsetStrike())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleStrike(), chain => chain.unsetStrike())\n }\n\n private _toggleCode() {\n if (this._applySlashLineMark(chain => chain.setCode(), chain => chain.unsetCode())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleCode(), chain => chain.unsetCode())\n }\n\n private _setHeading(level: number) {\n if (this._applySlashLineBlock(chain => chain.setHeading({ level: level as 1 | 2 | 3 | 4 | 5 | 6 }))) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleHeading({ level: level as 1 | 2 | 3 | 4 | 5 | 6 }).run())\n }\n\n private _setParagraph() {\n if (this._applySlashLineBlock(chain => chain.setParagraph())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().setParagraph().run())\n }\n\n private _toggleBulletList() {\n if (this._applySlashLineBlock(chain => chain.toggleBulletList())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleBulletList().run())\n }\n\n private _toggleOrderedList() {\n if (this._applySlashLineBlock(chain => chain.toggleOrderedList())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleOrderedList().run())\n }\n\n private _toggleTaskList() {\n if (this._applySlashLineBlock(chain => chain.toggleTaskList())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleTaskList().run())\n }\n\n private _toggleBlockquote() {\n if (this._applySlashLineBlock(chain => chain.toggleBlockquote())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleBlockquote().run())\n }\n\n private _setTextAlign(align: string) {\n if (this._applySlashLineBlock(chain => chain.setTextAlign(align as any))) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().setTextAlign(align as any).run())\n }\n\n private _normalizeLinkUrl(url: string) {\n const trimmed = url.trim()\n if (!trimmed) { return '' }\n if (/^(https?:\\/\\/|mailto:|tel:|#|\\/)/i.test(trimmed)) {\n return trimmed\n }\n return `https://${trimmed}`\n }\n\n private _getLinkLabelFromRange(range: { from: number, to: number } | null) {\n const editor = this._editor\n if (!editor || !range || range.from >= range.to) {\n return ''\n }\n return editor.state.doc.textBetween(range.from, range.to, '')\n }\n\n private _getLinkTargetRange() {\n const editor = this._editor\n if (!editor) { return null }\n\n const { selection } = editor.state\n if (!selection.empty) {\n return { from: selection.from, to: selection.to }\n }\n\n if (editor.isActive('link')) {\n editor.chain().focus().extendMarkRange('link').run()\n return {\n from: editor.state.selection.from,\n to: editor.state.selection.to,\n }\n }\n\n const $from = editor.state.doc.resolve(selection.from)\n return {\n from: $from.start(),\n to: $from.end(),\n }\n }\n\n private _setLink(event: MouseEvent) {\n const editor = this._editor\n const wrapper = this.shadowRoot?.querySelector<HTMLElement>('.editor-wrapper')\n const trigger = event.currentTarget instanceof HTMLElement ? event.currentTarget : null\n if (!editor || !wrapper || !trigger) { return }\n\n const linkRange = this._getLinkTargetRange()\n this._linkSelection = linkRange\n\n const wrapperRect = wrapper.getBoundingClientRect()\n const triggerRect = trigger.getBoundingClientRect()\n const maxLeft = Math.max(12, wrapperRect.width - 332)\n const left = Math.min(Math.max(12, triggerRect.left - wrapperRect.left), maxLeft)\n const top = triggerRect.bottom - wrapperRect.top + 8\n const currentHref = String(editor.getAttributes('link').href || '')\n const currentLabel = this._getLinkLabelFromRange(linkRange)\n\n this._linkEditor = {\n x: left,\n y: top,\n visible: true,\n url: currentHref,\n label: currentLabel,\n }\n\n this.updateComplete.then(() => {\n const input = this.shadowRoot?.querySelector<HTMLInputElement>('.link-editor__input[data-field=\"url\"]')\n input?.focus()\n input?.select()\n })\n }\n\n private _closeLinkEditor() {\n this._linkEditor = { ...this._linkEditor, visible: false }\n }\n\n private _handleLinkEditorInput(event: Event) {\n const target = event.target as HTMLInputElement\n const field = target.dataset.field === 'label' ? 'label' : 'url'\n this._linkEditor = {\n ...this._linkEditor,\n [field]: target.value,\n }\n }\n\n private _applyLink() {\n const editor = this._editor\n const href = this._normalizeLinkUrl(this._linkEditor.url)\n const label = this._linkEditor.label.trim() || href\n if (!editor || !href) { return }\n\n this._clearSlashCommandText()\n\n const selection = this._linkSelection ?? this._getLinkTargetRange() ?? editor.state.selection\n const insertTo = selection.from + label.length\n\n editor\n .chain()\n .focus()\n .insertContentAt(\n { from: selection.from, to: selection.to },\n {\n type: 'text',\n text: label,\n marks: [{ type: 'link', attrs: { href } }],\n },\n )\n .setTextSelection({ from: insertTo, to: insertTo })\n .run()\n\n this._closeLinkEditor()\n }\n\n private _removeLink() {\n const editor = this._editor\n if (!editor) { return }\n\n const selection = this._linkSelection ?? editor.state.selection\n let chain = editor.chain().focus()\n if (selection.from !== selection.to) {\n chain = chain.setTextSelection(selection)\n }\n chain.extendMarkRange('link').unsetLink().run()\n this._closeLinkEditor()\n }\n\n private _handleLinkEditorKeydown(event: KeyboardEvent) {\n if (event.key === 'Enter') {\n event.preventDefault()\n this._applyLink()\n return\n }\n if (event.key === 'Escape') {\n event.preventDefault()\n this._closeLinkEditor()\n }\n }\n\n private _insertTable(rows?: number, cols?: number) {\n this._editor?.chain().focus().insertTable({ rows: rows ?? this._tableRows, cols: cols ?? this._tableCols, withHeaderRow: true }).run()\n }\n\n private async _handleImageUpload(e: Event) {\n const input = e.target as HTMLInputElement\n const file = input.files?.[0]\n if (file) {\n try {\n const naturalWidth = await this._getImageNaturalWidth(file)\n const src = await this['upload-image'](file)\n const initialWidth = naturalWidth\n ? Math.min(naturalWidth, this._getImageMaxWidth())\n : this._getImageMaxWidth()\n\n this._clearSlashCommandText()\n const pendingInsertPos = this._pendingImageInsertPos\n this._pendingImageInsertPos = null\n\n if (pendingInsertPos !== null) {\n this._insertImageAt(pendingInsertPos, {\n src,\n width: initialWidth,\n align: 'center',\n })\n }\n else {\n this._editor?.chain().focus().setImage({\n src,\n width: initialWidth,\n align: 'center',\n }).run()\n }\n }\n catch (err) {\n console.error('图片上传失败:', err)\n }\n }\n input.value = ''\n }\n\n private _triggerImageUpload() {\n this._clearSlashCommandText()\n const input = this.shadowRoot?.querySelector<HTMLInputElement>('.image-input')\n input?.click()\n }\n\n private _insertTableByClick(rows: number, cols: number) {\n this._clearSlashCommandText()\n this._tableRows = rows\n this._tableCols = cols\n this._insertTable(rows, cols)\n }\n\n private _showTableCellToolbar() {\n if (!this._editor?.isActive('table')) { return }\n const { state } = this._editor\n const { selection } = state\n const coords = this._editor.view.coordsAtPos(selection.from)\n const editorWrapper = this.shadowRoot?.querySelector<HTMLElement>('.editor-wrapper')\n if (!editorWrapper) { return }\n const wrapperRect = editorWrapper.getBoundingClientRect()\n\n const cellRow = this._getTableCellRow()\n const cellCol = this._getTableCellCol()\n const isTopRow = cellRow === 0\n const isLeftCol = cellCol === 0\n\n // Only show toolbar on top row or left column\n if (!isTopRow && !isLeftCol) { return }\n\n requestAnimationFrame(() => {\n this._tableCellToolbar = {\n x: coords.left - wrapperRect.left,\n y: coords.bottom - wrapperRect.top + 8,\n visible: true,\n cellRow,\n cellCol,\n }\n })\n }\n\n private _getTableCellRow(): number {\n if (!this._editor) { return 0 }\n const { selection } = this._editor.state\n const $pos = this._editor.state.doc.resolve(selection.from)\n for (let d = $pos.depth; d > 0; d--) {\n const node = $pos.node(d)\n if (node.type.name === 'tableCell') {\n return $pos.index(d - 1)\n }\n }\n return 0\n }\n\n private _getTableCellCol(): number {\n if (!this._editor) { return 0 }\n const { selection } = this._editor.state\n const $pos = this._editor.state.doc.resolve(selection.from)\n for (let d = $pos.depth; d > 0; d--) {\n const node = $pos.node(d)\n if (node.type.name === 'tableCell') {\n return $pos.index(d)\n }\n }\n return 0\n }\n\n private _hideTableCellToolbar() {\n requestAnimationFrame(() => {\n this._tableCellToolbar = { ...this._tableCellToolbar, visible: false }\n })\n }\n\n private _addTableRowAbove() {\n this._editor?.chain().focus().addRowBefore().run()\n this._hideTableCellToolbar()\n }\n\n private _addTableRowBelow() {\n this._editor?.chain().focus().addRowAfter().run()\n this._hideTableCellToolbar()\n }\n\n private _addTableColumnLeft() {\n this._editor?.chain().focus().addColumnBefore().run()\n this._hideTableCellToolbar()\n }\n\n private _addTableColumnRight() {\n this._editor?.chain().focus().addColumnAfter().run()\n this._hideTableCellToolbar()\n }\n\n private _deleteTableRow() {\n this._editor?.chain().focus().deleteRow().run()\n this._hideTableCellToolbar()\n }\n\n private _deleteTableColumn() {\n this._editor?.chain().focus().deleteColumn().run()\n this._hideTableCellToolbar()\n }\n\n private _deleteTable() {\n this._editor?.chain().focus().deleteTable().run()\n this._hideTableCellToolbar()\n }\n\n // Image Toolbar Methods\n private _showImageToolbar(pos: { x: number, y: number }) {\n requestAnimationFrame(() => {\n this._imageToolbar = { x: pos.x, y: pos.y, visible: true }\n })\n }\n\n private _hideImageToolbar() {\n requestAnimationFrame(() => {\n this._imageToolbar = { ...this._imageToolbar, visible: false }\n })\n }\n\n private _deleteImage() {\n const selectedImage = this._getSelectedImageNode()\n if (!selectedImage) { return }\n\n const { editor, pos, node } = selectedImage\n editor.view.dispatch(editor.state.tr.delete(pos, pos + node.nodeSize))\n this._selectedImage = null\n this._pendingImageInsertPos = null\n this._hideImageToolbar()\n }\n\n private _insertImageAfter() {\n const selectedImage = this._getSelectedImageNode()\n if (!selectedImage) {\n this._triggerImageUpload()\n return\n }\n\n this._pendingImageInsertPos = selectedImage.pos + selectedImage.node.nodeSize\n this._triggerImageUpload()\n }\n\n private _getSelectedImageNode() {\n const editor = this._editor\n const pos = this._selectedImage?.pos\n if (!editor || pos === undefined) { return null }\n\n const node = editor.state.doc.nodeAt(pos)\n if (!node || node.type.name !== 'image') { return null }\n\n return { editor, pos, node }\n }\n\n private _insertImageAt(pos: number, attrs: Record<string, unknown>) {\n const editor = this._editor\n if (!editor) { return }\n\n const insertPos = Math.max(0, Math.min(pos, editor.state.doc.content.size))\n editor\n .chain()\n .insertContentAt(insertPos, { type: 'image', attrs })\n .setNodeSelection(insertPos)\n .run()\n }\n\n private _updateSelectedImageAttributes(attrs: Record<string, unknown>) {\n const selectedImage = this._getSelectedImageNode()\n if (!selectedImage) { return }\n\n const { editor, pos, node } = selectedImage\n editor.view.dispatch(editor.state.tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n ...attrs,\n }))\n }\n\n private _setImageWidth(width: number) {\n const nextWidth = Math.max(MIN_IMAGE_WIDTH, Math.min(this._getImageMaxWidth(), Math.round(width)))\n this._updateSelectedImageAttributes({ width: nextWidth })\n }\n\n private _handleImageWidthInput(e: Event) {\n const rawValue = (e.target as HTMLInputElement).value.trim()\n if (!rawValue) { return }\n\n const value = Number(rawValue)\n if (!Number.isFinite(value)) { return }\n this._setImageWidth(value)\n }\n\n private _setImageAlignLeft() {\n this._updateSelectedImageAttributes({ align: 'left' })\n }\n\n private _setImageAlignCenter() {\n this._updateSelectedImageAttributes({ align: 'center' })\n }\n\n private _setImageAlignRight() {\n this._updateSelectedImageAttributes({ align: 'right' })\n }\n\n private _getTextLabel(): string {\n const editor = this._editor\n if (!editor) { return '正文' }\n if (editor.isActive('heading', { level: 1 })) { return '标题 1' }\n if (editor.isActive('heading', { level: 2 })) { return '标题 2' }\n if (editor.isActive('heading', { level: 3 })) { return '标题 3' }\n return '正文'\n }\n\n private _getAlignLabel(): string {\n const editor = this._editor\n if (!editor) { return '对齐' }\n if (editor.isActive({ textAlign: 'center' })) { return '居中' }\n if (editor.isActive({ textAlign: 'right' })) { return '右对齐' }\n return '左对齐'\n }\n\n private _renderImageControls() {\n const selectedImage = this._selectedImage\n if (!selectedImage) { return '' }\n\n return html`\n <button class=\"bubble-btn danger\" title=\"删除图片\" @click=${this._deleteImage}>\n <svg viewBox=\"0 0 24 24\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/></svg>\n </button>\n <button class=\"bubble-btn\" title=\"添加图片\" @click=${this._insertImageAfter}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/></svg>\n </button>\n <div class=\"bubble-divider\"></div>\n <button class=\"bubble-btn ${selectedImage.align === 'left' ? 'is-active' : ''}\" title=\"左对齐\" @click=${this._setImageAlignLeft}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"3\" y1=\"12\" x2=\"15\" y2=\"12\"/><line x1=\"3\" y1=\"18\" x2=\"18\" y2=\"18\"/></svg>\n </button>\n <button class=\"bubble-btn ${selectedImage.align === 'center' ? 'is-active' : ''}\" title=\"居中\" @click=${this._setImageAlignCenter}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"6\" y1=\"12\" x2=\"18\" y2=\"12\"/><line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\"/></svg>\n </button>\n <button class=\"bubble-btn ${selectedImage.align === 'right' ? 'is-active' : ''}\" title=\"右对齐\" @click=${this._setImageAlignRight}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"9\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"6\" y1=\"18\" x2=\"21\" y2=\"18\"/></svg>\n </button>\n <div class=\"image-size-control\">\n <span class=\"image-size-label\">宽度</span>\n <input\n class=\"image-size-range\"\n type=\"number\"\n min=\"${MIN_IMAGE_WIDTH}\"\n max=\"${this._getImageMaxWidth()}\"\n .value=${String(selectedImage.width)}\n @input=${this._handleImageWidthInput}\n />\n </div>\n `\n }\n\n private _updateBubbleMenuPosition() {\n if (this._toolbarModeValue !== 'slash') { return }\n requestAnimationFrame(() => {\n const bubbleMenu = this.shadowRoot?.querySelector<HTMLElement>('.bubble-menu')\n const proseMirror = this.shadowRoot?.querySelector<HTMLElement>('.ProseMirror')\n const editorWrapper = this.shadowRoot?.querySelector<HTMLElement>('.editor-wrapper')\n if (!bubbleMenu || !proseMirror || !editorWrapper) { return }\n\n const editor = this._editor\n const isInTable = editor?.isActive('table') ?? false\n const { selection } = editor?.state ?? { selection: null }\n\n // 如果选中了表格节点(而不只是单元格内的文字),隐藏菜单\n if (isInTable && selection && !selection.empty && editor) {\n const { from, to } = selection\n const $from = editor.state.doc.resolve(from)\n const $to = editor.state.doc.resolve(to)\n // 检查选区起点和终点之间是否有表格节点\n let hasTableInSelection = false\n for (let d = $from.depth; d >= 0; d--) {\n if ($from.node(d).type.name === 'table') {\n hasTableInSelection = true\n break\n }\n }\n // 如果选区起点在表格外但终点在表格内,或者选区跨越了表格\n const fromAncestor = $from.node($from.depth)\n const toAncestor = $to.node($to.depth)\n if (fromAncestor.type.name === 'table' || toAncestor.type.name === 'table') {\n hasTableInSelection = true\n }\n if (hasTableInSelection) {\n bubbleMenu.style.opacity = '0'\n bubbleMenu.style.visibility = 'hidden'\n return\n }\n }\n\n // 如果有选中文字,显示菜单\n if (selection && !selection.empty) {\n // continue to show menu\n }\n else if (!selection || (selection.empty && !this._hasSlashCommand)) {\n bubbleMenu.style.opacity = '0'\n bubbleMenu.style.visibility = 'hidden'\n return\n }\n\n const wrapperRect = editorWrapper.getBoundingClientRect()\n const menuRect = bubbleMenu.getBoundingClientRect()\n\n const { from } = selection!\n const coords = this._editor?.view.coordsAtPos(from)\n if (!coords) { return }\n\n let left = coords.left - wrapperRect.left\n let top = coords.top - wrapperRect.top - 40\n\n if (left + menuRect.width > wrapperRect.width) {\n left = wrapperRect.width - menuRect.width - 8\n }\n if (left < 0) {\n left = 8\n }\n\n if (top < 0) {\n top = coords.bottom - wrapperRect.top + 8\n }\n\n bubbleMenu.style.left = `${left}px`\n bubbleMenu.style.top = `${top}px`\n bubbleMenu.style.opacity = '1'\n bubbleMenu.style.visibility = 'visible'\n })\n }\n\n render() {\n const editor = this._editor\n\n return html`\n <div\n class=\"editor-wrapper ${!editor ? 'loading' : ''} ${this._previewValue ? 'preview' : ''}\"\n @mousedown=${this._handleWrapperMouseDown}\n @focusin=${this._handleWrapperFocusIn}\n @focusout=${this._handleWrapperFocusOut}\n >\n ${!editor\n ? html`\n <div class=\"loading-placeholder\">\n <div class=\"loading-spinner\"></div>\n <span>编辑器加载中...</span>\n </div>\n `\n : ''}\n <input\n type=\"file\"\n accept=\"image/*\"\n class=\"image-input\"\n @change=${this._handleImageUpload}\n />\n\n ${!this._previewValue && this._toolbarModeValue === 'header'\n ? html`\n <div class=\"editor-header ${this._isHeaderVisible() ? 'is-visible' : ''}\">\n <div class=\"editor-header__inner\">\n ${this._selectedImage\n ? this._renderImageControls()\n : html`\n <button\n class=\"bubble-btn ${editor?.isActive('bold') ? 'is-active' : ''}\"\n @click=${this._toggleBold}\n title=\"加粗\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/></svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('italic') ? 'is-active' : ''}\"\n @click=${this._toggleItalic}\n title=\"斜体\"\n >\n <svg viewBox=\"0 0 24 24\"><line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/></svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('underline') ? 'is-active' : ''}\"\n @click=${this._toggleUnderline}\n title=\"下划线\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"/><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"/></svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('strike') ? 'is-active' : ''}\"\n @click=${this._toggleStrike}\n title=\"删除线\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M17.3 4.9c-2.3-.6-4.4-1-6.2-.9-2.7 0-5.3.7-5.3 3.6 0 1.5 1.8 3.3 5.3 3.9h.2m8.2 3.2c.3.4.4.8.4 1.3 0 2.9-2.7 3.6-6.2 3.6-2.3 0-4.4-.3-6.2-.9M4 12h16\"/></svg>\n </button>\n\n <div class=\"bubble-divider\"></div>\n\n <div class=\"bubble-dropdown\">\n <button class=\"bubble-dropdown-btn\">\n ${this._getTextLabel()}\n <svg viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"/></svg>\n </button>\n <div class=\"bubble-dropdown-menu\">\n <button class=\"bubble-dropdown-item ${!editor?.isActive('heading') ? 'is-active' : ''}\" @click=${this._setParagraph}>正文</button>\n <button class=\"bubble-dropdown-item ${editor?.isActive('heading', { level: 1 }) ? 'is-active' : ''}\" @click=${() => this._setHeading(1)}>标题 1</button>\n <button class=\"bubble-dropdown-item ${editor?.isActive('heading', { level: 2 }) ? 'is-active' : ''}\" @click=${() => this._setHeading(2)}>标题 2</button>\n <button class=\"bubble-dropdown-item ${editor?.isActive('heading', { level: 3 }) ? 'is-active' : ''}\" @click=${() => this._setHeading(3)}>标题 3</button>\n </div>\n </div>\n\n <div class=\"bubble-divider\"></div>\n\n <div class=\"bubble-dropdown\">\n <button class=\"bubble-dropdown-btn\">\n ${this._getAlignLabel()}\n <svg viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"/></svg>\n </button>\n <div class=\"bubble-dropdown-menu\">\n <button class=\"bubble-dropdown-item ${editor?.isActive({ textAlign: 'left' }) ? 'is-active' : ''}\" @click=${() => this._setTextAlign('left')}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"3\" y1=\"12\" x2=\"15\" y2=\"12\"/><line x1=\"3\" y1=\"18\" x2=\"18\" y2=\"18\"/></svg>\n 左对齐\n </button>\n <button class=\"bubble-dropdown-item ${editor?.isActive({ textAlign: 'center' }) ? 'is-active' : ''}\" @click=${() => this._setTextAlign('center')}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"6\" y1=\"12\" x2=\"18\" y2=\"12\"/><line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\"/></svg>\n 居中\n </button>\n <button class=\"bubble-dropdown-item ${editor?.isActive({ textAlign: 'right' }) ? 'is-active' : ''}\" @click=${() => this._setTextAlign('right')}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"9\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"6\" y1=\"18\" x2=\"21\" y2=\"18\"/></svg>\n 右对齐\n </button>\n </div>\n </div>\n\n <div class=\"bubble-divider\"></div>\n\n <button class=\"bubble-btn ${editor?.isActive('code') ? 'is-active' : ''}\" @click=${this._toggleCode} title=\"行内代码\">\n <svg viewBox=\"0 0 24 24\"><polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/></svg>\n </button>\n <button class=\"bubble-btn ${editor?.isActive('link') ? 'is-active' : ''}\" @click=${this._setLink} title=\"链接\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>\n </button>\n <button class=\"bubble-btn\" @click=${this._triggerImageUpload} title=\"图片\">\n <svg viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/></svg>\n </button>\n\n <div class=\"bubble-divider\"></div>\n\n <button class=\"bubble-btn ${editor?.isActive('bulletList') ? 'is-active' : ''}\" @click=${this._toggleBulletList} title=\"无序列表\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"9\" y1=\"6\" x2=\"20\" y2=\"6\"/>\n <line x1=\"9\" y1=\"12\" x2=\"20\" y2=\"12\"/>\n <line x1=\"9\" y1=\"18\" x2=\"20\" y2=\"18\"/>\n <circle cx=\"4\" cy=\"6\" r=\"0.5\" fill=\"currentColor\" stroke=\"none\"/>\n <circle cx=\"4\" cy=\"12\" r=\"0.5\" fill=\"currentColor\" stroke=\"none\"/>\n <circle cx=\"4\" cy=\"18\" r=\"0.5\" fill=\"currentColor\" stroke=\"none\"/>\n </svg>\n </button>\n <button class=\"bubble-btn ${editor?.isActive('orderedList') ? 'is-active' : ''}\" @click=${this._toggleOrderedList} title=\"有序列表\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\"/>\n <line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\"/>\n <line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\"/>\n <path d=\"M4 6h1v4\"/>\n <path d=\"M4 10h2\"/>\n <path d=\"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1.5\"/>\n </svg>\n </button>\n <button class=\"bubble-btn ${editor?.isActive('taskList') ? 'is-active' : ''}\" @click=${this._toggleTaskList} title=\"待办列表\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"3\" y=\"5\" width=\"4\" height=\"4\" rx=\"1\"/>\n <polyline points=\"4 7 5 8 6.5 6.5\"/>\n <line x1=\"10\" y1=\"7\" x2=\"21\" y2=\"7\"/>\n <rect x=\"3\" y=\"15\" width=\"4\" height=\"4\" rx=\"1\"/>\n <line x1=\"10\" y1=\"17\" x2=\"21\" y2=\"17\"/>\n </svg>\n </button>\n <button class=\"bubble-btn ${editor?.isActive('blockquote') ? 'is-active' : ''}\" @click=${this._toggleBlockquote} title=\"引用\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V21z\"/><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\"/></svg>\n </button>\n\n <div class=\"bubble-divider\"></div>\n\n <div\n class=\"bubble-dropdown ${this._tableDropdownOpen ? 'is-open' : ''}\"\n @mouseenter=${() => {\n this._tableDropdownOpen = true\n this._hoverRow = 0\n this._hoverCol = 0\n }}\n @mouseleave=${() => this._tableDropdownOpen = false}\n >\n <button class=\"bubble-dropdown-btn\" title=\"表格\">\n <svg viewBox=\"0 0 24 24\" style=\"width:18px;height:18px;stroke:currentColor;stroke-width:2;fill:none;\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/></svg>\n </button>\n <div class=\"bubble-dropdown-menu\">\n <div class=\"table-grid-preview\">\n ${this._renderTableGrid()}\n </div>\n <div class=\"table-size-hint\">\n <span>${this._hoverRow > 0 ? `${this._hoverRow} × ${this._hoverCol}` : `${this._tableRows} × ${this._tableCols}`}</span>\n </div>\n </div>\n </div>\n `}\n </div>\n </div>\n `\n : ''}\n\n <!-- Bubble Menu (悬浮操作栏) -->\n ${!this._previewValue && this._toolbarModeValue === 'slash'\n ? html`\n <div class=\"bubble-menu\">\n <!-- 文本格式 -->\n <button\n class=\"bubble-btn ${editor?.isActive('bold') ? 'is-active' : ''}\"\n @click=${this._toggleBold}\n title=\"加粗\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/></svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('italic') ? 'is-active' : ''}\"\n @click=${this._toggleItalic}\n title=\"斜体\"\n >\n <svg viewBox=\"0 0 24 24\"><line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/></svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('underline') ? 'is-active' : ''}\"\n @click=${this._toggleUnderline}\n title=\"下划线\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"/><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"/></svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('strike') ? 'is-active' : ''}\"\n @click=${this._toggleStrike}\n title=\"删除线\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M17.3 4.9c-2.3-.6-4.4-1-6.2-.9-2.7 0-5.3.7-5.3 3.6 0 1.5 1.8 3.3 5.3 3.9h.2m8.2 3.2c.3.4.4.8.4 1.3 0 2.9-2.7 3.6-6.2 3.6-2.3 0-4.4-.3-6.2-.9M4 12h16\"/></svg>\n </button>\n\n <div class=\"bubble-divider\"></div>\n\n <!-- 文本类型下拉 -->\n <div class=\"bubble-dropdown\">\n <button class=\"bubble-dropdown-btn\">\n ${this._getTextLabel()}\n <svg viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"/></svg>\n </button>\n <div class=\"bubble-dropdown-menu\">\n <button\n class=\"bubble-dropdown-item ${!editor?.isActive('heading') ? 'is-active' : ''}\"\n @click=${this._setParagraph}\n >\n 正文\n </button>\n <button\n class=\"bubble-dropdown-item ${editor?.isActive('heading', { level: 1 }) ? 'is-active' : ''}\"\n @click=${() => this._setHeading(1)}\n >\n 标题 1\n </button>\n <button\n class=\"bubble-dropdown-item ${editor?.isActive('heading', { level: 2 }) ? 'is-active' : ''}\"\n @click=${() => this._setHeading(2)}\n >\n 标题 2\n </button>\n <button\n class=\"bubble-dropdown-item ${editor?.isActive('heading', { level: 3 }) ? 'is-active' : ''}\"\n @click=${() => this._setHeading(3)}\n >\n 标题 3\n </button>\n </div>\n </div>\n\n <div class=\"bubble-divider\"></div>\n\n <!-- 对齐下拉 -->\n <div class=\"bubble-dropdown\">\n <button class=\"bubble-dropdown-btn\">\n ${this._getAlignLabel()}\n <svg viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"/></svg>\n </button>\n <div class=\"bubble-dropdown-menu\">\n <button\n class=\"bubble-dropdown-item ${editor?.isActive({ textAlign: 'left' }) ? 'is-active' : ''}\"\n @click=${() => this._setTextAlign('left')}\n >\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"3\" y1=\"12\" x2=\"15\" y2=\"12\"/><line x1=\"3\" y1=\"18\" x2=\"18\" y2=\"18\"/></svg>\n 左对齐\n </button>\n <button\n class=\"bubble-dropdown-item ${editor?.isActive({ textAlign: 'center' }) ? 'is-active' : ''}\"\n @click=${() => this._setTextAlign('center')}\n >\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"6\" y1=\"12\" x2=\"18\" y2=\"12\"/><line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\"/></svg>\n 居中\n </button>\n <button\n class=\"bubble-dropdown-item ${editor?.isActive({ textAlign: 'right' }) ? 'is-active' : ''}\"\n @click=${() => this._setTextAlign('right')}\n >\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"9\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"6\" y1=\"18\" x2=\"21\" y2=\"18\"/></svg>\n 右对齐\n </button>\n </div>\n </div>\n\n <div class=\"bubble-divider\"></div>\n\n <!-- 行内代码 -->\n <button\n class=\"bubble-btn ${editor?.isActive('code') ? 'is-active' : ''}\"\n @click=${this._toggleCode}\n title=\"行内代码\"\n >\n <svg viewBox=\"0 0 24 24\"><polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/></svg>\n </button>\n\n <!-- 链接 -->\n <button\n class=\"bubble-btn ${editor?.isActive('link') ? 'is-active' : ''}\"\n @click=${this._setLink}\n title=\"链接\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>\n </button>\n\n <!-- 图片 -->\n <button\n class=\"bubble-btn\"\n @click=${this._triggerImageUpload}\n title=\"图片\"\n >\n <svg viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/></svg>\n </button>\n\n <div class=\"bubble-divider\"></div>\n\n <!-- 列表 -->\n <button\n class=\"bubble-btn ${editor?.isActive('bulletList') ? 'is-active' : ''}\"\n @click=${this._toggleBulletList}\n title=\"无序列表\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"9\" y1=\"6\" x2=\"20\" y2=\"6\"/>\n <line x1=\"9\" y1=\"12\" x2=\"20\" y2=\"12\"/>\n <line x1=\"9\" y1=\"18\" x2=\"20\" y2=\"18\"/>\n <circle cx=\"4\" cy=\"6\" r=\"0.5\" fill=\"currentColor\" stroke=\"none\"/>\n <circle cx=\"4\" cy=\"12\" r=\"0.5\" fill=\"currentColor\" stroke=\"none\"/>\n <circle cx=\"4\" cy=\"18\" r=\"0.5\" fill=\"currentColor\" stroke=\"none\"/>\n </svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('orderedList') ? 'is-active' : ''}\"\n @click=${this._toggleOrderedList}\n title=\"有序列表\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\"/>\n <line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\"/>\n <line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\"/>\n <path d=\"M4 6h1v4\"/>\n <path d=\"M4 10h2\"/>\n <path d=\"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1.5\"/>\n </svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('taskList') ? 'is-active' : ''}\"\n @click=${this._toggleTaskList}\n title=\"待办列表\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"3\" y=\"5\" width=\"4\" height=\"4\" rx=\"1\"/>\n <polyline points=\"4 7 5 8 6.5 6.5\"/>\n <line x1=\"10\" y1=\"7\" x2=\"21\" y2=\"7\"/>\n <rect x=\"3\" y=\"15\" width=\"4\" height=\"4\" rx=\"1\"/>\n <line x1=\"10\" y1=\"17\" x2=\"21\" y2=\"17\"/>\n </svg>\n </button>\n\n <!-- 引用 -->\n <button\n class=\"bubble-btn ${editor?.isActive('blockquote') ? 'is-active' : ''}\"\n @click=${this._toggleBlockquote}\n title=\"引用\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V21z\"/><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\"/></svg>\n </button>\n\n <div class=\"bubble-divider\"></div>\n\n <!-- 表格下拉 -->\n <div\n class=\"bubble-dropdown ${this._tableDropdownOpen ? 'is-open' : ''}\"\n @mouseenter=${() => {\n this._tableDropdownOpen = true\n this._hoverRow = 0\n this._hoverCol = 0\n }}\n @mouseleave=${() => this._tableDropdownOpen = false}\n >\n <button class=\"bubble-dropdown-btn\" title=\"表格\">\n <svg viewBox=\"0 0 24 24\" style=\"width:18px;height:18px;stroke:currentColor;stroke-width:2;fill:none;\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/></svg>\n </button>\n <div class=\"bubble-dropdown-menu\">\n <div class=\"table-grid-preview\">\n ${this._renderTableGrid()}\n </div>\n <div class=\"table-size-hint\">\n <span>${this._hoverRow > 0 ? `${this._hoverRow} × ${this._hoverCol}` : `${this._tableRows} × ${this._tableCols}`}</span>\n </div>\n </div>\n </div>\n </div>\n `\n : ''}\n\n <div class=\"editor-content\" data-empty-hint=${this._resolvedPlaceholder}></div>\n\n ${this._linkEditor.visible\n ? html`\n <div\n class=\"link-editor\"\n style=\"left: ${this._linkEditor.x}px; top: ${this._linkEditor.y}px;\"\n @mousedown=${(event: MouseEvent) => event.stopPropagation()}\n @click=${(event: MouseEvent) => event.stopPropagation()}\n >\n <div class=\"link-editor__field\">\n <span class=\"link-editor__label\">链接地址</span>\n <input\n class=\"link-editor__input\"\n data-field=\"url\"\n type=\"text\"\n placeholder=\"输入或粘贴链接\"\n .value=${this._linkEditor.url}\n @input=${this._handleLinkEditorInput}\n @keydown=${this._handleLinkEditorKeydown}\n />\n </div>\n <div class=\"link-editor__field\">\n <span class=\"link-editor__label\">链接名字</span>\n <input\n class=\"link-editor__input\"\n data-field=\"label\"\n type=\"text\"\n placeholder=\"输入展示名称\"\n .value=${this._linkEditor.label}\n @input=${this._handleLinkEditorInput}\n @keydown=${this._handleLinkEditorKeydown}\n />\n </div>\n <div class=\"link-editor__actions\">\n <button class=\"link-editor__action primary\" title=\"应用链接\" @click=${this._applyLink}>应用</button>\n <button class=\"link-editor__action\" title=\"取消链接编辑\" @click=${this._closeLinkEditor}>取消</button>\n ${(editor?.isActive('link') || this._linkEditor.url)\n ? html`<button class=\"link-editor__action danger\" title=\"移除链接\" @click=${this._removeLink}>移除</button>`\n : ''}\n </div>\n </div>\n `\n : ''}\n\n <!-- Table Cell Toolbar -->\n ${this._tableCellToolbar.visible && editor?.isActive('table')\n ? html`\n <div\n class=\"table-cell-toolbar\"\n style=\"left: ${this._tableCellToolbar.x}px; top: ${this._tableCellToolbar.y}px;\"\n @mousedown=${(e: Event) => e.preventDefault()}\n >\n ${this._tableCellToolbar.cellRow === 0\n ? html`\n <button class=\"table-cell-toolbar-btn\" title=\"上方添加行\" @click=${this._addTableRowAbove}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"7\"/><line x1=\"10\" y1=\"5\" x2=\"14\" y2=\"5\"/></svg>\n </button>\n <button class=\"table-cell-toolbar-btn\" title=\"下方添加行\" @click=${this._addTableRowBelow}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"17\"/><line x1=\"10\" y1=\"19\" x2=\"14\" y2=\"19\"/></svg>\n </button>\n <button class=\"table-cell-toolbar-btn danger\" title=\"删除行\" @click=${this._deleteTableRow}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"8\" rx=\"1\"/><line x1=\"9\" y1=\"10\" x2=\"9\" y2=\"14\"/><line x1=\"15\" y1=\"10\" x2=\"15\" y2=\"14\"/></svg>\n </button>\n `\n : ''}\n ${this._tableCellToolbar.cellCol === 0\n ? html`\n ${this._tableCellToolbar.cellRow !== 0 ? html`<div style=\"width:1px;height:20px;background:#e3e3e3;margin:0 4px;\"></div>` : ''}\n <button class=\"table-cell-toolbar-btn\" title=\"左侧添加列\" @click=${this._addTableColumnLeft}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"8\" y=\"4\" width=\"8\" height=\"16\" rx=\"1\"/><line x1=\"3\" y1=\"12\" x2=\"7\" y2=\"12\"/><line x1=\"5\" y1=\"10\" x2=\"5\" y2=\"14\"/></svg>\n </button>\n <button class=\"table-cell-toolbar-btn\" title=\"右侧添加列\" @click=${this._addTableColumnRight}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"8\" y=\"4\" width=\"8\" height=\"16\" rx=\"1\"/><line x1=\"21\" y1=\"12\" x2=\"17\" y2=\"12\"/><line x1=\"19\" y1=\"10\" x2=\"19\" y2=\"14\"/></svg>\n </button>\n <button class=\"table-cell-toolbar-btn danger\" title=\"删除列\" @click=${this._deleteTableColumn}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"8\" y=\"4\" width=\"8\" height=\"16\" rx=\"1\"/><line x1=\"10\" y1=\"9\" x2=\"14\" y2=\"9\"/><line x1=\"10\" y1=\"15\" x2=\"14\" y2=\"15\"/></svg>\n </button>\n `\n : ''}\n ${this._tableCellToolbar.cellRow === 0 && this._tableCellToolbar.cellCol === 0\n ? html`\n <div style=\"width:1px;height:20px;background:#e3e3e3;margin:0 4px;\"></div>\n <button class=\"table-cell-toolbar-btn danger\" title=\"删除表格\" @click=${this._deleteTable}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/></svg>\n </button>\n `\n : ''}\n </div>\n `\n : ''}\n\n <!-- Image Toolbar -->\n ${this._toolbarModeValue === 'slash' && this._imageToolbar.visible\n ? html`\n <div\n class=\"image-toolbar\"\n style=\"left: ${this._imageToolbar.x}px; top: ${this._imageToolbar.y}px;\"\n @mousedown=${(e: Event) => e.preventDefault()}\n >\n ${this._renderImageControls()}\n </div>\n `\n : ''}\n </div>\n `\n }\n\n private _renderTableGrid() {\n const cells = []\n for (let i = 0; i < 100; i++) {\n const row = Math.floor(i / 10) + 1\n const col = (i % 10) + 1\n const isHighlight = this._hoverRow > 0 && row <= this._hoverRow && col <= this._hoverCol\n cells.push(html`\n <div\n class=\"table-cell ${isHighlight ? 'selected' : ''}\"\n @click=${() => {\n this._insertTableByClick(row, col)\n this._tableDropdownOpen = false\n }}\n @mouseenter=${() => {\n this._hoverRow = row\n this._hoverCol = col\n }}\n @mouseleave=${() => {\n this._hoverRow = 0\n this._hoverCol = 0\n }}\n ></div>\n `)\n }\n return cells\n }\n}\n\nexport function register() {}\n"],"names":["DEFAULT_HEADER_PLACEHOLDER","DEFAULT_SLASH_PLACEHOLDER","TaskList","TiptapNode","create","name","group","content","defining","parseHTML","tag","renderHTML","_ref","HTMLAttributes","mergeAttributes","addCommands","toggleTaskList","_ref2","commands","toggleList","this","TaskItem","addAttributes","checked","default","element","getAttribute","String","Boolean","attributes","_ref3","contenteditable","type","addKeyboardShortcuts","Enter","editor","splitListItem","Tab","sinkListItem","Shift-Tab","liftListItem","ExtendedImage","Image","extend","parent","width","attr","value","Number","isFinite","align","_ref4","style","filter","join","options","QxsBlocksuiteEditor","LitElement","constructor","super","arguments","placeholder","readonly","preview","_injectedStyleEl","async","Promise","resolve","reject","reader","FileReader","onload","e","target","result","onerror","readAsDataURL","file","_editor","_pendingContent","_tableRows","_tableCols","_hoverRow","_hoverCol","_tableDropdownOpen","_tableCellToolbar","x","y","visible","cellRow","cellCol","_imageToolbar","_linkEditor","url","label","_isEditorFocused","_selectedImage","_hasSlashCommand","_slashCommandRange","_isUpdating","_pendingImageInsertPos","_linkSelection","_preserveFocusOnInternalClick","_tableEdgeDetectionSetup","_injectCustomStyles","shadow","shadowRoot","remove","styleEl","document","createElement","textContent","appendChild","_useModelValue","hasAttribute","_readonlyValue","_previewValue","_isEditable","_toolbarModeValue","_headerAlwaysVisibleValue","_resolvedPlaceholder","_initEditor","el","querySelector","requestAnimationFrame","firstChild","removeChild","useModel","modelValue","contentValue","initialContent","extensions","Document","Paragraph","Text","Bold","Italic","Underline","Strike","Code","Heading","configure","levels","BulletList","OrderedList","ListItem","Blockquote","HorizontalRule","History","inline","allowBase64","Link","inclusive","openOnClick","rel","TextAlign","types","Table","resizable","TableRow","TableCell","TableHeader","Placeholder","Editor","editable","on","_updateBubbleMenuPosition","isActive","_showTableCellToolbar","_hideTableCellToolbar","_syncImageSelectionState","_checkSlashCommand","_setupTableEdgeDetection","_emitContentChange","_toggleTaskItemChecked","event","HTMLInputElement","taskItem","closest","preventDefault","stopPropagation","basePos","view","posAtDOM","searchFrom","Math","max","searchTo","min","state","doc","size","taskItemPos","nodesBetween","node","pos","nodeAt","dispatch","tr","setNodeMarkup","attrs","html","getHTML","dispatchEvent","CustomEvent","detail","bubbles","composed","editorContent","editorWrapper","handleEditorClick","Element","chain","focus","run","addEventListener","_handleWrapperFocusIn","_handleWrapperMouseDown","_handleWrapperFocusOut","nextTarget","relatedTarget","wrapper","contains","_closeLinkEditor","_isHeaderVisible","_getImageSelection","selection","from","_getImageMaxWidth","availableWidth","clientWidth","_getImageNaturalWidth","objectUrl","URL","createObjectURL","image","window","naturalWidth","revokeObjectURL","src","_hideImageToolbar","wrapperRect","getBoundingClientRect","coords","coordsAtPos","left","right","top","_showImageToolbar","_clearSlashCommandText","to","deleteRange","empty","$from","textBefore","textBetween","parentOffset","matched","exec","slashText","length","firstUpdated","updated","changed","has","newContent","setContent","setEditable","disconnectedCallback","destroy","getContent","forceUpdate","requestUpdate","_applyFormat","command","_getSlashCommandContext","range","lineFrom","start","lineTo","_applySlashLineMark","applyMark","clearMark","context","setTextSelection","_applyToolbarLineMark","end","_applySlashLineBlock","applyBlock","_toggleBold","setBold","unsetBold","toggleBold","_toggleItalic","setItalic","unsetItalic","toggleItalic","_toggleUnderline","setUnderline","unsetUnderline","toggleUnderline","_toggleStrike","setStrike","unsetStrike","toggleStrike","_toggleCode","setCode","unsetCode","toggleCode","_setHeading","level","setHeading","toggleHeading","_setParagraph","setParagraph","_toggleBulletList","toggleBulletList","_toggleOrderedList","toggleOrderedList","_toggleTaskList","_toggleBlockquote","toggleBlockquote","_setTextAlign","setTextAlign","_normalizeLinkUrl","trimmed","trim","test","_getLinkLabelFromRange","_getLinkTargetRange","extendMarkRange","_setLink","trigger","currentTarget","HTMLElement","linkRange","triggerRect","maxLeft","bottom","currentHref","getAttributes","href","currentLabel","updateComplete","then","input","select","_handleLinkEditorInput","field","dataset","_applyLink","insertTo","insertContentAt","text","marks","_removeLink","unsetLink","_handleLinkEditorKeydown","key","_insertTable","rows","cols","insertTable","withHeaderRow","_handleImageUpload","files","initialWidth","pendingInsertPos","_insertImageAt","setImage","err","_triggerImageUpload","click","_insertTableByClick","_getTableCellRow","_getTableCellCol","$pos","d","depth","index","_addTableRowAbove","addRowBefore","_addTableRowBelow","addRowAfter","_addTableColumnLeft","addColumnBefore","_addTableColumnRight","addColumnAfter","_deleteTableRow","deleteRow","_deleteTableColumn","deleteColumn","_deleteTable","deleteTable","_deleteImage","selectedImage","_getSelectedImageNode","delete","nodeSize","_insertImageAfter","insertPos","setNodeSelection","_updateSelectedImageAttributes","_setImageWidth","nextWidth","round","_handleImageWidthInput","rawValue","_setImageAlignLeft","_setImageAlignCenter","_setImageAlignRight","_getTextLabel","_getAlignLabel","textAlign","_renderImageControls","bubbleMenu","proseMirror","isInTable","$to","hasTableInSelection","fromAncestor","toAncestor","opacity","visibility","menuRect","render","_renderTableGrid","cells","i","row","floor","col","isHighlight","push","styles","css","__decorateClass","property","attribute","prototype","Object","safeCustomElement"],"mappings":"k6CAsCA,MAEMA,EAA6B,OAC7BC,EAA4B,cAE5BC,EAAWC,EAAWC,OAAO,CACjCC,KAAM,WACNC,MAAO,aACPC,QAAS,YACTC,UAAU,EAEVC,UAAAA,IACS,CAAC,CAAEC,IAAK,6BAGjBC,UAAAA,CAAAC,GAA+B,IAApBC,eAAEA,GAAeD,EAC1B,MAAO,CAAC,KAAME,EAAgBD,EAAgB,CAAE,YAAa,aAAe,EAC9E,EAEAE,WAAAA,GACE,MAAO,CACLC,eAAgBA,IAAMC,IAAA,IAACC,SAAEA,YAAeA,EAASC,WAAWC,KAAKf,KAAM,aAE3E,IAGIgB,EAAWlB,EAAWC,OAAO,CACjCC,KAAM,WACNG,UAAU,EACVD,QAAS,mBAETe,cAAAA,KACS,CACLC,QAAS,CACPC,SAAS,EACTf,UAAWgB,GAAoD,SAAzCA,EAAQC,aAAa,gBAC3Cf,gBAA6B,eAAgBgB,OAAOC,QAAQC,EAAWN,eAK7Ed,UAAAA,IACS,CAAC,CAAEC,IAAK,6BAGjBC,UAAAA,CAAAmB,GAA+B,IAApBjB,eAAEA,GAAeiB,EAC1B,MAAMP,EAAUK,QAAQf,EAAeU,SAEvC,MAAO,CACL,KACAT,EAAgBD,EAAgB,CAAE,YAAa,aAC/C,CACE,QACA,CAAEkB,gBAAiB,SACnB,CAAC,QAAS,CAAEC,KAAM,WAAYT,QAASA,EAAU,UAAY,OAC7D,CAAC,SAEH,CAAC,MAAO,GAEZ,EAEAU,oBAAAA,GACE,MAAO,CACLC,MAAOA,IAAMd,KAAKe,OAAOjB,SAASkB,cAAchB,KAAKf,MACrDgC,IAAKA,IAAMjB,KAAKe,OAAOjB,SAASoB,aAAalB,KAAKf,MAClD,YAAakC,IAAMnB,KAAKe,OAAOjB,SAASsB,aAAapB,KAAKf,MAE9D,IAGIoC,EAAgBC,EAAMC,OAAO,CACjCrB,aAAAA,GACE,MAAO,IACFF,KAAKwB,WACRC,MAAO,CACLrB,QAAS,KACTf,UAAYgB,IACV,MAAMqB,EAAOrB,EAAQC,aAAa,SAC5BqB,EAAQC,OAAOF,GACrB,OAAOE,OAAOC,SAASF,IAAUA,EAAQ,EAAIA,EAAQ,MAEvDpC,WAAYkB,GAAcA,EAAWgB,MAAQ,CAAEA,MAAOlB,OAAOE,EAAWgB,QAAW,CAAA,GAErFK,MAAO,CACL1B,QAAS,SACTf,UAAWgB,GAAWA,EAAQC,aAAa,eAAiB,SAC5Df,WAAYkB,GAAcA,EAAWqB,MAAQ,CAAE,aAAcvB,OAAOE,EAAWqB,QAAW,CAAA,GAGhG,EAEAvC,UAAAA,CAAAwC,GAA+B,IAApBtC,eAAEA,GAAesC,EAC1B,MAAMN,EAAQG,OAAOnC,EAAegC,OAE9BO,EAAQ,CACZ,iBACA,cACAJ,OAAOC,SAASJ,IAAUA,EAAQ,EAAI,SAASA,MAAY,GAC3DhC,EAAeuC,OAAS,IAEvBC,OAAOzB,SACP0B,KAAK,KAER,MAAO,CAAC,MAAOxC,EAAgBM,KAAKmC,QAAQ1C,eAAgBA,EAAgB,CAAEuC,UAChF,IAIK,IAAMI,EAAN,cAAkCC,EAAlCC,WAAAA,GAAAC,SAAAC,WA6xBLxC,KAAAb,QAAU,GAGVa,KAAA,eAAgB,GAGhBA,KAAAyC,YAAc7D,EAGdoB,KAAA,gBAA8B,SAG9BA,KAAA,yBAA0B,QAG1BA,KAAA,aAAc,QAGdA,KAAA0C,SAAW,QAGX1C,KAAA2C,QAAU,QAGV3C,KAAA,iBAAkB,GAElBA,KAAQ4C,iBAA4C,KA4DpD5C,KAAA,gBAAkD6C,SACzC,IAAIC,QAAQ,CAACC,EAASC,KAC3B,MAAMC,EAAS,IAAIC,WACnBD,EAAOE,OAASC,GAAKL,EAAQK,EAAEC,QAAQC,QACvCL,EAAOM,QAAUP,EACjBC,EAAOO,cAAcC,KAIhBzD,KAAQ0D,QAAyB,KACjC1D,KAAQ2D,gBAAiC,KAClD3D,KAAQ4D,WAAa,EACrB5D,KAAQ6D,WAAa,EACZ7D,KAAQ8D,UAAY,EACpB9D,KAAQ+D,UAAY,EACpB/D,KAAQgE,oBAAqB,EAC7BhE,KAAQiE,kBAAkG,CAAEC,EAAG,EAAGC,EAAG,EAAGC,SAAS,EAAOC,QAAS,EAAGC,QAAS,GAC7JtE,KAAQuE,cAA4D,CAAEL,EAAG,EAAGC,EAAG,EAAGC,SAAS,GAC3FpE,KAAQwE,YAAc,CAAEN,EAAG,EAAGC,EAAG,EAAGC,SAAS,EAAOK,IAAK,GAAIC,MAAO,IACpE1E,KAAQ2E,kBAAmB,EAC3B3E,KAAQ4E,eAAuE,KACxF5E,KAAQ6E,kBAAmB,EAC3B7E,KAAQ8E,mBAA0D,KAClE9E,KAAQ+E,aAAc,EACtB/E,KAAQgF,uBAAwC,KAChDhF,KAAQiF,eAAsD,KAC9DjF,KAAQkF,+BAAgC,EA0GxClF,KAAQmF,0BAA2B,CAAA,CA9L3BC,mBAAAA,GACN,MAAMC,EAASrF,KAAKsF,WACpB,IAAKD,EAAU,OAOf,GALIrF,KAAK4C,mBACP5C,KAAK4C,iBAAiB2C,SACtBvF,KAAK4C,iBAAmB,OAGrB5C,KAAK,iBAAoB,OAE9B,MAAMwF,EAAUC,SAASC,cAAc,SACvCF,EAAQG,YAAc3F,KAAK,iBAC3BqF,EAAOO,YAAYJ,GACnBxF,KAAK4C,iBAAmB4C,CAC1B,CAEA,kBAAYK,GACV,OAA6B,IAAtB7F,KAAK,cAA+C,SAAtBA,KAAK,cAAiD,KAAtBA,KAAK,cAAuBA,KAAK8F,aAAa,YACrH,CAEA,kBAAYC,GACV,OAAyB,IAAlB/F,KAAK0C,UAAwC,UAAlB1C,KAAK0C,QACzC,CAEA,iBAAYsD,GACV,OAAwB,IAAjBhG,KAAK2C,SAAsC,UAAjB3C,KAAK2C,OACxC,CAEA,eAAYsD,GACV,OAAQjG,KAAK+F,iBAAmB/F,KAAKgG,aACvC,CAEA,qBAAYE,GACV,MAAgC,WAAzBlG,KAAK,gBAA+B,SAAW,OACxD,CAEA,6BAAYmG,GACV,OAAyC,IAAlCnG,KAAK,0BAC2B,SAAlCA,KAAK,0BAC6B,KAAlCA,KAAK,0BACLA,KAAK8F,aAAa,wBACzB,CAEA,wBAAYM,GACV,OACEpG,KAAKyC,aACFzC,KAAKyC,cAAgB7D,GACrBoB,KAAKyC,cAAgB5D,EAEjBmB,KAAKyC,YAEoB,WAA3BzC,KAAKkG,kBACRtH,EACAC,CACN,CA+BQwH,WAAAA,GACN,GAAIrG,KAAK0D,QAAW,OAEpB,MAAM4C,EAAKtG,KAAKsF,YAAYiB,cAA2B,mBACvD,IAAKD,EAEH,YADAE,sBAAsB,IAAMxG,KAAKqG,eAInC,KAAOC,EAAGG,YACRH,EAAGI,YAAYJ,EAAGG,YAGpB,MAAME,EAAW3G,KAAK6F,eAChBe,EAAa5G,KAAKM,aAAa,gBAAkBN,KAAK,eACtD6G,EAAe7G,KAAKb,QAEpB2H,EAAiBH,GAClB3G,KAAK2D,iBAAmBiD,IAAe,WACvC5G,KAAK2D,iBAAmBkD,IAAiB,UAExCE,EAAoB,CACxBC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EAAQC,UAAU,CAAEC,OAAQ,CAAC,EAAG,EAAG,KACnCC,EACAC,EACA9I,EACAmB,EACA4H,EACAC,EACAC,EACAC,EACA3G,EAAcoG,UAAU,CACtBQ,QAAQ,EACRC,aAAa,IAEfC,EAAK5G,OAAO,CACV6G,WAAW,IACVX,UAAU,CACXY,aAAa,EACb5I,eAAgB,CACd6I,IAAK,yBAGTC,EAAUd,UAAU,CAClBe,MAAO,CAAC,UAAW,eAErBC,EAAMhB,UAAU,CACdiB,WAAW,IAEbC,EACAC,EACAC,EACAC,EAAYrB,UAAU,CACpBhF,YAAazC,KAAKoG,wBAItBpG,KAAK0D,QAAU,IAAIqF,EAAO,CACxB1I,QAASiG,EACTS,aACAiC,SAAUhJ,KAAKiG,YACf9G,QAAS2H,IAGX9G,KAAK2D,gBAAkB,KAEvB3D,KAAK0D,QAAQuF,GAAG,kBAAmB,KACF,UAA3BjJ,KAAKkG,mBACPlG,KAAKkJ,4BAEHlJ,KAAK0D,SAASyF,SAAS,SACzBnJ,KAAKoJ,wBAGLpJ,KAAKqJ,wBAEPrJ,KAAKsJ,6BAGPtJ,KAAK0D,QAAQuF,GAAG,cAAe,KACzBjJ,KAAK0D,SAASyF,SAAS,SACzBnJ,KAAKoJ,wBAGLpJ,KAAKqJ,wBAEPrJ,KAAKuJ,qBACLvJ,KAAKwJ,2BACLxJ,KAAKsJ,6BAGPtJ,KAAK0D,QAAQuF,GAAG,SAAU,KACxBjJ,KAAKyJ,sBAET,CAIQC,sBAAAA,CAAuBC,GAC7B,MAAMtG,EAASsG,EAAMtG,OACftC,EAASf,KAAK0D,QACpB,KAAML,aAAkBuG,kBAAqC,aAAhBvG,EAAOzC,MAAwBG,GAC1E,OAGF,MAAM8I,EAAWxG,EAAOyG,QAAQ,4BAChC,IAAKD,EACH,OAGFF,EAAMI,iBACNJ,EAAMK,kBAEN,MAAMC,EAAUlJ,EAAOmJ,KAAKC,SAASN,EAAU,GACzCO,EAAaC,KAAKC,IAAI,EAAGL,EAAU,GACnCM,EAAWF,KAAKG,IAAIzJ,EAAO0J,MAAMC,IAAIvL,QAAQwL,KAAMV,EAAU,GAEnE,IAAIW,EAA6B,KASjC,GARA7J,EAAO0J,MAAMC,IAAIG,aAAaT,EAAYG,EAAU,CAACO,EAAMC,KACzD,GAAuB,aAAnBD,EAAKlK,KAAK3B,KAEZ,OADA2L,EAAcG,GACP,IAKS,OAAhBH,EACF,OAGF,MAAME,EAAO/J,EAAO0J,MAAMC,IAAIM,OAAOJ,GAChCE,GAA2B,aAAnBA,EAAKlK,KAAK3B,MAIvB8B,EAAOmJ,KAAKe,SAASlK,EAAO0J,MAAMS,GAAGC,cAAcP,OAAa,EAAW,IACtEE,EAAKM,MACRjL,SAAU2K,EAAKM,MAAMjL,UAEzB,CAEQsJ,kBAAAA,GACN,IAAKzJ,KAAK0D,QAAW,OACrB,MAAM2H,EAAOrL,KAAK0D,QAAQ4H,UAE1BtL,KAAKuL,cAAc,IAAIC,YAAY,iBAAkB,CACnDC,OAAQJ,EACRK,SAAS,EACTC,UAAU,IAEd,CAEQnC,wBAAAA,GACN,MAAMoC,EAAgB5L,KAAKsF,YAAYiB,cAAc,mBAC/CsF,EAAgB7L,KAAKsF,YAAYiB,cAAc,mBACrD,IAAKqF,GAAiB5L,KAAKmF,yBAA4B,OAEvDnF,KAAKmF,0BAA2B,EAEhC,MAAM2G,EAAqBnC,IACzB3J,KAAK0J,uBAAuBC,GAE5B,MAAMtG,EAASsG,EAAMtG,OAEnBA,aAAkB0I,SACf1I,EAAOyG,QAAQ,oFAIf9J,KAAKiG,aAGVjG,KAAK0D,SAASsI,QAAQC,QAAQC,OAGhCN,EAAcO,iBAAiB,QAASL,GACxCD,GAAeM,iBAAiB,QAASL,EAC3C,CAEQM,qBAAAA,GACNpM,KAAKkF,+BAAgC,EACrClF,KAAK2E,kBAAmB,CAC1B,CAEQ0H,uBAAAA,CAAwB1C,GAC9B,MAAMtG,EAASsG,EAAMtG,OAElBrD,KAAKiG,aACD5C,aAAkB0I,UACpB1I,EAAOyG,QAAQ,qFAKpB9J,KAAKkF,+BAAgC,EACrCsB,sBAAsB,KACpBxG,KAAKkF,+BAAgC,IAEzC,CAEQoH,sBAAAA,CAAuB3C,GAC7B,MAAM4C,EAAa5C,EAAM6C,cACnBC,EAAUzM,KAAKsF,YAAYiB,cAAc,mBAC3CvG,KAAKkF,+BAGLqH,GAAcE,GAASC,SAASH,KAGpCvM,KAAK2E,kBAAmB,EACxB3E,KAAKgE,oBAAqB,EAC1BhE,KAAK2M,mBACP,CAEQC,gBAAAA,GACN,MAAkC,WAA3B5M,KAAKkG,oBACNlG,KAAKgG,gBAEPhG,KAAKmG,2BACFnG,KAAK2E,kBACL3E,KAAKgE,oBACLxD,QAAQR,KAAK4E,gBAEtB,CAEQiI,kBAAAA,GACN,MAAM9L,EAASf,KAAK0D,QACdoJ,EAAiB/L,GAAQ0J,MAAMqC,UACrC,OAAK/L,GAAW+L,GAAWhC,MAAsC,UAA9BgC,EAAUhC,KAAKlK,MAAM3B,KAIjD,CACL8L,IAAK+B,EAAUC,KACf3B,MAAO0B,EAAUhC,KAAKM,OAAS,CAAA,GALxB,IAOX,CAEQ4B,iBAAAA,GACN,MAAMpB,EAAgB5L,KAAKsF,YAAYiB,cAA2B,mBAC5D0G,GAAkBrB,GAAesB,aAnvCf,KAmvCqD,GAC7E,OAAO7C,KAAKC,IAnvCQ,GAmvCaD,KAAKG,IApvCd,IAovCuCyC,GACjE,CAEA,2BAAcE,CAAsB1J,GAClC,aAAa,IAAIX,QAAwBC,IACvC,MAAMqK,EAAYC,IAAIC,gBAAgB7J,GAChC8J,EAAQ,IAAIC,OAAOlM,MAEzBiM,EAAMpK,OAAS,KACb,MAAMsK,EAAeF,EAAME,aAC3BJ,IAAIK,gBAAgBN,GACpBrK,EAAQnB,OAAOC,SAAS4L,IAAiBA,EAAe,EAAIA,EAAe,OAG7EF,EAAMhK,QAAU,KACd8J,IAAIK,gBAAgBN,GACpBrK,EAAQ,OAGVwK,EAAMI,IAAMP,GAEhB,CAEQ9D,wBAAAA,GACN,MAAMwD,EAAY9M,KAAK6M,qBACvB,IAAKC,EAKH,OAJA9M,KAAK4E,eAAiB,UACS,UAA3B5E,KAAKkG,mBACPlG,KAAK4N,qBAKT,MAAMnM,EAAQG,OAAOkL,EAAU1B,MAAM3J,OAC/BK,EAAQvB,OAAOuM,EAAU1B,MAAMtJ,OAAS,UAO9C,GANA9B,KAAK4E,eAAiB,CACpBmG,IAAK+B,EAAU/B,IACftJ,MAAOG,OAAOC,SAASJ,IAAUA,EAAQ,EAAIA,EAAQzB,KAAKgN,oBAC1DlL,SAG6B,UAA3B9B,KAAKkG,kBAEP,YADAlG,KAAK4N,oBAIP,MAAM7M,EAASf,KAAK0D,QACdmK,EAAc7N,KAAKsF,YAAYiB,cAAc,oBAAoBuH,wBACvE,IAAK/M,IAAW8M,EAAe,OAC/B,MAAME,EAAShN,EAAOmJ,KAAK8D,YAAYlB,EAAU/B,KAC3C7G,EAAI6J,EAAOE,KAAOJ,EAAYI,MAAQF,EAAOG,MAAQH,EAAOE,MAAQ,EACpE9J,EAAI4J,EAAOI,IAAMN,EAAYM,IAAM,GACzCnO,KAAKoO,kBAAkB,CAAElK,IAAGC,KAC9B,CAEQkK,sBAAAA,GACN,IAAKrO,KAAK0D,UAAY1D,KAAK8E,mBAAsB,OACjD,MAAMiI,KAAEA,EAAAuB,GAAMA,GAAOtO,KAAK8E,mBAC1B9E,KAAK0D,QAAQsI,QAAQC,QAAQsC,YAAY,CAAExB,OAAMuB,OAAMpC,MACvDlM,KAAK6E,kBAAmB,EACxB7E,KAAK8E,mBAAqB,IAC5B,CAEQyE,kBAAAA,GACN,IAAKvJ,KAAK0D,QAAW,OACrB,MAAMoJ,UAAEA,GAAc9M,KAAK0D,QAAQ+G,MACnC,IAAKqC,EAAU0B,MAGb,OAFAxO,KAAK6E,kBAAmB,OACxB7E,KAAK8E,mBAAqB,MAI5B,MAAM2J,MAAEA,GAAU3B,EACZ4B,EAAaD,EAAMjN,OAAOmN,YAAY,EAAGF,EAAMG,aAAc,IAAK,KAClEC,EAAU,mBAAmBC,KAAKJ,GAExC,IAAKG,EAGH,OAFA7O,KAAK6E,kBAAmB,OACxB7E,KAAK8E,mBAAqB,MAI5B,MAAMiK,EAAYF,EAAQ,GAC1B7O,KAAK6E,kBAAmB,EACxB7E,KAAK8E,mBAAqB,CACxBiI,KAAMD,EAAUC,KAAOgC,EAAUC,OACjCV,GAAIxB,EAAUC,KAElB,CAEAkC,YAAAA,GACEjP,KAAKoF,sBACLpF,KAAKqG,aACP,CAEA6I,OAAAA,CAAQC,GAKN,GAJIA,EAAQC,IAAI,kBACdpP,KAAKoF,sBAGHpF,KAAK0D,QAAT,CACE,GAAIyL,EAAQC,IAAI,YAAeD,EAAQC,IAAI,gBAAkBpP,KAAK6F,eAAiB,CACjF,MAAMwJ,EAAarP,KAAK6F,eAAiB7F,KAAK,eAAiBA,KAAKb,QAChEkQ,IAAerP,KAAK0D,QAAQ4H,WAC9BtL,KAAK0D,QAAQ5D,SAASwP,WAAWD,GAAc,UAEnD,EACIF,EAAQC,IAAI,aAAeD,EAAQC,IAAI,aACzCpP,KAAK0D,QAAQ6L,YAAYvP,KAAKiG,YAGlC,MAGIkJ,EAAQC,IAAI,aACdpP,KAAK2D,gBAAkB3D,KAAKb,SAG1BgQ,EAAQC,IAAI,gBAAkBpP,KAAK6F,iBACrC7F,KAAK2D,gBAAkB3D,KAAK,eAKhC,CAEAwP,oBAAAA,GACEjN,MAAMiN,uBACNxP,KAAK0D,SAAS+L,UACdzP,KAAK0D,QAAU,IACjB,CAEAgM,UAAAA,GACE,OAAO1P,KAAK0D,SAAS4H,WAAa,EACpC,CAEAqE,WAAAA,GAEE,GADA3P,KAAK4P,gBACD5P,KAAK0D,QAAS,CAChB,MAAM2L,EAAarP,KAAK6F,eAAiB7F,KAAK,eAAiBA,KAAKb,QAChEkQ,IAAerP,KAAK0D,QAAQ4H,WAC9BtL,KAAK0D,QAAQ5D,SAASwP,WAAWD,GAAc,UAEnD,CACF,CAEQQ,YAAAA,CAAaC,GACnB9P,KAAKqO,yBACLyB,GACF,CAEQC,uBAAAA,GACN,MAAMhP,EAASf,KAAK0D,QACdsM,EAAQhQ,KAAK8E,mBACnB,IAAK/D,IAAWiP,EAAS,OAAO,KAGhC,MAAO,CACLC,SAFYlP,EAAO0J,MAAMC,IAAI3H,QAAQiN,EAAMjD,MAE3BmD,QAChBC,OAAQH,EAAMjD,KAElB,CAEQqD,mBAAAA,CACNC,EACAC,GAEA,MAAMvP,EAASf,KAAK0D,QACd6M,EAAUvQ,KAAK+P,0BACrB,SAAKhP,IAAWwP,KAEhBvQ,KAAKqO,yBAEDkC,EAAQN,SAAWM,EAAQJ,QAC7BE,EACEtP,EAAOiL,QAAQC,QAAQuE,iBAAiB,CAAEzD,KAAMwD,EAAQN,SAAU3B,GAAIiC,EAAQJ,UAC9EjE,MAGJoE,EACEvP,EAAOiL,QAAQC,QAAQuE,iBAAiB,CAAEzD,KAAMwD,EAAQJ,OAAQ7B,GAAIiC,EAAQJ,UAC5EjE,OACK,EACT,CAEQuE,qBAAAA,CACNJ,EACAC,GAEA,MAAMvP,EAASf,KAAK0D,QACpB,IAAK3C,EAAU,OAAO,EAEtB,MAAM+L,UAAEA,GAAc/L,EAAO0J,MACvBuF,EAAQlD,EAAU0B,MAAA,MAElB,MAAMC,EAAQ1N,EAAO0J,MAAMC,IAAI3H,QAAQ+J,EAAUC,MACjD,MAAO,CAAEA,KAAM0B,EAAMyB,QAAS5B,GAAIG,EAAMiC,MAC1C,EAJoB,GAKpB,CAAE3D,KAAMD,EAAUC,KAAMuB,GAAIxB,EAAUwB,IAE1C,QAAI0B,EAAMjD,MAAQiD,EAAM1B,MAIxB+B,EACEtP,EAAOiL,QAAQC,QAAQuE,iBAAiBR,IACxC9D,MAEFoE,EACEvP,EAAOiL,QAAQC,QAAQuE,iBAAiB,CAAEzD,KAAMiD,EAAM1B,GAAIA,GAAI0B,EAAM1B,MACpEpC,OAEK,EACT,CAEQyE,oBAAAA,CACNC,GAEA,MAAM7P,EAASf,KAAK0D,QACd6M,EAAUvQ,KAAK+P,0BACrB,SAAKhP,IAAWwP,KAEhBvQ,KAAKqO,yBACLuC,EACE7P,EAAOiL,QAAQC,QAAQuE,iBAAiB,CAAEzD,KAAMwD,EAAQN,SAAU3B,GAAIiC,EAAQJ,UAC9EjE,OACK,EACT,CAEQ2E,WAAAA,GACF7Q,KAAKoQ,oBAAoBpE,GAASA,EAAM8E,UAAW9E,GAASA,EAAM+E,cAGtE/Q,KAAKyQ,yBAA+BzE,EAAMgF,aAAchF,GAASA,EAAM+E,YACzE,CAEQE,aAAAA,GACFjR,KAAKoQ,oBAAoBpE,GAASA,EAAMkF,YAAalF,GAASA,EAAMmF,gBAGxEnR,KAAKyQ,yBAA+BzE,EAAMoF,eAAgBpF,GAASA,EAAMmF,cAC3E,CAEQE,gBAAAA,GACFrR,KAAKoQ,oBAAoBpE,GAASA,EAAMsF,eAAgBtF,GAASA,EAAMuF,mBAG3EvR,KAAKyQ,yBAA+BzE,EAAMwF,kBAAmBxF,GAASA,EAAMuF,iBAC9E,CAEQE,aAAAA,GACFzR,KAAKoQ,oBAAoBpE,GAASA,EAAM0F,YAAa1F,GAASA,EAAM2F,gBAGxE3R,KAAKyQ,yBAA+BzE,EAAM4F,eAAgB5F,GAASA,EAAM2F,cAC3E,CAEQE,WAAAA,GACF7R,KAAKoQ,oBAAoBpE,GAASA,EAAM8F,UAAW9F,GAASA,EAAM+F,cAGtE/R,KAAKyQ,yBAA+BzE,EAAMgG,aAAchG,GAASA,EAAM+F,YACzE,CAEQE,WAAAA,CAAYC,GACdlS,KAAK2Q,qBAAqB3E,GAASA,EAAMmG,WAAW,CAAED,YAG1DlS,KAAK6P,aAAa,IAAM7P,KAAK0D,SAASsI,QAAQC,QAAQmG,cAAc,CAAEF,UAAyChG,MACjH,CAEQmG,aAAAA,GACFrS,KAAK2Q,qBAAqB3E,GAASA,EAAMsG,iBAG7CtS,KAAK6P,aAAa,IAAM7P,KAAK0D,SAASsI,QAAQC,QAAQqG,eAAepG,MACvE,CAEQqG,iBAAAA,GACFvS,KAAK2Q,qBAAqB3E,GAASA,EAAMwG,qBAG7CxS,KAAK6P,aAAa,IAAM7P,KAAK0D,SAASsI,QAAQC,QAAQuG,mBAAmBtG,MAC3E,CAEQuG,kBAAAA,GACFzS,KAAK2Q,qBAAqB3E,GAASA,EAAM0G,sBAG7C1S,KAAK6P,aAAa,IAAM7P,KAAK0D,SAASsI,QAAQC,QAAQyG,oBAAoBxG,MAC5E,CAEQyG,eAAAA,GACF3S,KAAK2Q,qBAAqB3E,GAASA,EAAMpM,mBAG7CI,KAAK6P,aAAa,IAAM7P,KAAK0D,SAASsI,QAAQC,QAAQrM,iBAAiBsM,MACzE,CAEQ0G,iBAAAA,GACF5S,KAAK2Q,qBAAqB3E,GAASA,EAAM6G,qBAG7C7S,KAAK6P,aAAa,IAAM7P,KAAK0D,SAASsI,QAAQC,QAAQ4G,mBAAmB3G,MAC3E,CAEQ4G,aAAAA,CAAchR,GAChB9B,KAAK2Q,qBAAqB3E,GAASA,EAAM+G,aAAajR,KAG1D9B,KAAK6P,aAAa,IAAM7P,KAAK0D,SAASsI,QAAQC,QAAQ8G,aAAajR,GAAcoK,MACnF,CAEQ8G,iBAAAA,CAAkBvO,GACxB,MAAMwO,EAAUxO,EAAIyO,OACpB,OAAKD,EACD,oCAAoCE,KAAKF,GACpCA,EAEF,WAAWA,IAJK,EAKzB,CAEQG,sBAAAA,CAAuBpD,GAC7B,MAAMjP,EAASf,KAAK0D,QACpB,OAAK3C,IAAWiP,GAASA,EAAMjD,MAAQiD,EAAM1B,GACpC,GAEFvN,EAAO0J,MAAMC,IAAIiE,YAAYqB,EAAMjD,KAAMiD,EAAM1B,GAAI,GAC5D,CAEQ+E,mBAAAA,GACN,MAAMtS,EAASf,KAAK0D,QACpB,IAAK3C,EAAU,OAAO,KAEtB,MAAM+L,UAAEA,GAAc/L,EAAO0J,MAC7B,IAAKqC,EAAU0B,MACb,MAAO,CAAEzB,KAAMD,EAAUC,KAAMuB,GAAIxB,EAAUwB,IAG/C,GAAIvN,EAAOoI,SAAS,QAElB,OADApI,EAAOiL,QAAQC,QAAQqH,gBAAgB,QAAQpH,MACxC,CACLa,KAAMhM,EAAO0J,MAAMqC,UAAUC,KAC7BuB,GAAIvN,EAAO0J,MAAMqC,UAAUwB,IAI/B,MAAMG,EAAQ1N,EAAO0J,MAAMC,IAAI3H,QAAQ+J,EAAUC,MACjD,MAAO,CACLA,KAAM0B,EAAMyB,QACZ5B,GAAIG,EAAMiC,MAEd,CAEQ6C,QAAAA,CAAS5J,GACf,MAAM5I,EAASf,KAAK0D,QACd+I,EAAUzM,KAAKsF,YAAYiB,cAA2B,mBACtDiN,EAAU7J,EAAM8J,yBAAyBC,YAAc/J,EAAM8J,cAAgB,KACnF,IAAK1S,IAAW0L,IAAY+G,EAAW,OAEvC,MAAMG,EAAY3T,KAAKqT,sBACvBrT,KAAKiF,eAAiB0O,EAEtB,MAAM9F,EAAcpB,EAAQqB,wBACtB8F,EAAcJ,EAAQ1F,wBACtB+F,EAAUxJ,KAAKC,IAAI,GAAIuD,EAAYpM,MAAQ,KAC3CwM,EAAO5D,KAAKG,IAAIH,KAAKC,IAAI,GAAIsJ,EAAY3F,KAAOJ,EAAYI,MAAO4F,GACnE1F,EAAMyF,EAAYE,OAASjG,EAAYM,IAAM,EAC7C4F,EAAcxT,OAAOQ,EAAOiT,cAAc,QAAQC,MAAQ,IAC1DC,EAAelU,KAAKoT,uBAAuBO,GAEjD3T,KAAKwE,YAAc,CACjBN,EAAG+J,EACH9J,EAAGgK,EACH/J,SAAS,EACTK,IAAKsP,EACLrP,MAAOwP,GAGTlU,KAAKmU,eAAeC,KAAK,KACvB,MAAMC,EAAQrU,KAAKsF,YAAYiB,cAAgC,yCAC/D8N,GAAOpI,QACPoI,GAAOC,UAEX,CAEQ3H,gBAAAA,GACN3M,KAAKwE,YAAc,IAAKxE,KAAKwE,YAAaJ,SAAS,EACrD,CAEQmQ,sBAAAA,CAAuB5K,GAC7B,MAAMtG,EAASsG,EAAMtG,OACfmR,EAAiC,UAAzBnR,EAAOoR,QAAQD,MAAoB,QAAU,MAC3DxU,KAAKwE,YAAc,IACdxE,KAAKwE,YACRgQ,CAACA,GAAQnR,EAAO1B,MAEpB,CAEQ+S,UAAAA,GACN,MAAM3T,EAASf,KAAK0D,QACduQ,EAAOjU,KAAKgT,kBAAkBhT,KAAKwE,YAAYC,KAC/CC,EAAQ1E,KAAKwE,YAAYE,MAAMwO,QAAUe,EAC/C,IAAKlT,IAAWkT,EAAQ,OAExBjU,KAAKqO,yBAEL,MAAMvB,EAAY9M,KAAKiF,gBAAkBjF,KAAKqT,uBAAyBtS,EAAO0J,MAAMqC,UAC9E6H,EAAW7H,EAAUC,KAAOrI,EAAMsK,OAExCjO,EACGiL,QACAC,QACA2I,gBACC,CAAE7H,KAAMD,EAAUC,KAAMuB,GAAIxB,EAAUwB,IACtC,CACE1N,KAAM,OACNiU,KAAMnQ,EACNoQ,MAAO,CAAC,CAAElU,KAAM,OAAQwK,MAAO,CAAE6I,YAGpCzD,iBAAiB,CAAEzD,KAAM4H,EAAUrG,GAAIqG,IACvCzI,MAEHlM,KAAK2M,kBACP,CAEQoI,WAAAA,GACN,MAAMhU,EAASf,KAAK0D,QACpB,IAAK3C,EAAU,OAEf,MAAM+L,EAAY9M,KAAKiF,gBAAkBlE,EAAO0J,MAAMqC,UACtD,IAAId,EAAQjL,EAAOiL,QAAQC,QACvBa,EAAUC,OAASD,EAAUwB,KAC/BtC,EAAQA,EAAMwE,iBAAiB1D,IAEjCd,EAAMsH,gBAAgB,QAAQ0B,YAAY9I,MAC1ClM,KAAK2M,kBACP,CAEQsI,wBAAAA,CAAyBtL,GAC/B,GAAkB,UAAdA,EAAMuL,IAGR,OAFAvL,EAAMI,sBACN/J,KAAK0U,aAGW,WAAd/K,EAAMuL,MACRvL,EAAMI,iBACN/J,KAAK2M,mBAET,CAEQwI,YAAAA,CAAaC,EAAeC,GAClCrV,KAAK0D,SAASsI,QAAQC,QAAQqJ,YAAY,CAAEF,KAAMA,GAAQpV,KAAK4D,WAAYyR,KAAMA,GAAQrV,KAAK6D,WAAY0R,eAAe,IAAQrJ,KACnI,CAEA,wBAAcsJ,CAAmBpS,GAC/B,MAAMiR,EAAQjR,EAAEC,OACVI,EAAO4Q,EAAMoB,QAAQ,GAC3B,GAAIhS,EACF,IACE,MAAMgK,QAAqBzN,KAAKmN,sBAAsB1J,GAChDkK,QAAY3N,KAAK,gBAAgByD,GACjCiS,EAAejI,EACjBpD,KAAKG,IAAIiD,EAAczN,KAAKgN,qBAC5BhN,KAAKgN,oBAEThN,KAAKqO,yBACL,MAAMsH,EAAmB3V,KAAKgF,uBAC9BhF,KAAKgF,uBAAyB,KAEL,OAArB2Q,EACF3V,KAAK4V,eAAeD,EAAkB,CACpChI,MACAlM,MAAOiU,EACP5T,MAAO,WAIT9B,KAAK0D,SAASsI,QAAQC,QAAQ4J,SAAS,CACrClI,MACAlM,MAAOiU,EACP5T,MAAO,WACNoK,KAEP,OACO4J,GAEP,CAEFzB,EAAM1S,MAAQ,EAChB,CAEQoU,mBAAAA,GACN/V,KAAKqO,yBACL,MAAMgG,EAAQrU,KAAKsF,YAAYiB,cAAgC,gBAC/D8N,GAAO2B,OACT,CAEQC,mBAAAA,CAAoBb,EAAcC,GACxCrV,KAAKqO,yBACLrO,KAAK4D,WAAawR,EAClBpV,KAAK6D,WAAawR,EAClBrV,KAAKmV,aAAaC,EAAMC,EAC1B,CAEQjM,qBAAAA,GACN,IAAKpJ,KAAK0D,SAASyF,SAAS,SAAY,OACxC,MAAQsB,MAAAA,GAAUzK,KAAK0D,SACjBoJ,UAAEA,GAAcrC,EAChBsD,EAAS/N,KAAK0D,QAAQwG,KAAK8D,YAAYlB,EAAUC,MACjDlB,EAAgB7L,KAAKsF,YAAYiB,cAA2B,mBAClE,IAAKsF,EAAiB,OACtB,MAAMgC,EAAchC,EAAciC,wBAE5BzJ,EAAUrE,KAAKkW,mBACf5R,EAAUtE,KAAKmW,oBACQ,IAAZ9R,GACa,IAAZC,IAKlBkC,sBAAsB,KACpBxG,KAAKiE,kBAAoB,CACvBC,EAAG6J,EAAOE,KAAOJ,EAAYI,KAC7B9J,EAAG4J,EAAO+F,OAASjG,EAAYM,IAAM,EACrC/J,SAAS,EACTC,UACAC,YAGN,CAEQ4R,gBAAAA,GACN,IAAKlW,KAAK0D,QAAW,OAAO,EAC5B,MAAMoJ,UAAEA,GAAc9M,KAAK0D,QAAQ+G,MAC7B2L,EAAOpW,KAAK0D,QAAQ+G,MAAMC,IAAI3H,QAAQ+J,EAAUC,MACtD,IAAA,IAASsJ,EAAID,EAAKE,MAAOD,EAAI,EAAGA,IAAK,CAEnC,GAAuB,cADVD,EAAKtL,KAAKuL,GACdzV,KAAK3B,KACZ,OAAOmX,EAAKG,MAAMF,EAAI,EAE1B,CACA,OAAO,CACT,CAEQF,gBAAAA,GACN,IAAKnW,KAAK0D,QAAW,OAAO,EAC5B,MAAMoJ,UAAEA,GAAc9M,KAAK0D,QAAQ+G,MAC7B2L,EAAOpW,KAAK0D,QAAQ+G,MAAMC,IAAI3H,QAAQ+J,EAAUC,MACtD,IAAA,IAASsJ,EAAID,EAAKE,MAAOD,EAAI,EAAGA,IAAK,CAEnC,GAAuB,cADVD,EAAKtL,KAAKuL,GACdzV,KAAK3B,KACZ,OAAOmX,EAAKG,MAAMF,EAEtB,CACA,OAAO,CACT,CAEQhN,qBAAAA,GACN7C,sBAAsB,KACpBxG,KAAKiE,kBAAoB,IAAKjE,KAAKiE,kBAAmBG,SAAS,IAEnE,CAEQoS,iBAAAA,GACNxW,KAAK0D,SAASsI,QAAQC,QAAQwK,eAAevK,MAC7ClM,KAAKqJ,uBACP,CAEQqN,iBAAAA,GACN1W,KAAK0D,SAASsI,QAAQC,QAAQ0K,cAAczK,MAC5ClM,KAAKqJ,uBACP,CAEQuN,mBAAAA,GACN5W,KAAK0D,SAASsI,QAAQC,QAAQ4K,kBAAkB3K,MAChDlM,KAAKqJ,uBACP,CAEQyN,oBAAAA,GACN9W,KAAK0D,SAASsI,QAAQC,QAAQ8K,iBAAiB7K,MAC/ClM,KAAKqJ,uBACP,CAEQ2N,eAAAA,GACNhX,KAAK0D,SAASsI,QAAQC,QAAQgL,YAAY/K,MAC1ClM,KAAKqJ,uBACP,CAEQ6N,kBAAAA,GACNlX,KAAK0D,SAASsI,QAAQC,QAAQkL,eAAejL,MAC7ClM,KAAKqJ,uBACP,CAEQ+N,YAAAA,GACNpX,KAAK0D,SAASsI,QAAQC,QAAQoL,cAAcnL,MAC5ClM,KAAKqJ,uBACP,CAGQ+E,iBAAAA,CAAkBrD,GACxBvE,sBAAsB,KACpBxG,KAAKuE,cAAgB,CAAEL,EAAG6G,EAAI7G,EAAGC,EAAG4G,EAAI5G,EAAGC,SAAS,IAExD,CAEQwJ,iBAAAA,GACNpH,sBAAsB,KACpBxG,KAAKuE,cAAgB,IAAKvE,KAAKuE,cAAeH,SAAS,IAE3D,CAEQkT,YAAAA,GACN,MAAMC,EAAgBvX,KAAKwX,wBAC3B,IAAKD,EAAiB,OAEtB,MAAMxW,OAAEA,EAAAgK,IAAQA,EAAAD,KAAKA,GAASyM,EAC9BxW,EAAOmJ,KAAKe,SAASlK,EAAO0J,MAAMS,GAAGuM,OAAO1M,EAAKA,EAAMD,EAAK4M,WAC5D1X,KAAK4E,eAAiB,KACtB5E,KAAKgF,uBAAyB,KAC9BhF,KAAK4N,mBACP,CAEQ+J,iBAAAA,GACN,MAAMJ,EAAgBvX,KAAKwX,wBACtBD,GAKLvX,KAAKgF,uBAAyBuS,EAAcxM,IAAMwM,EAAczM,KAAK4M,SACrE1X,KAAK+V,uBALH/V,KAAK+V,qBAMT,CAEQyB,qBAAAA,GACN,MAAMzW,EAASf,KAAK0D,QACdqH,EAAM/K,KAAK4E,gBAAgBmG,IACjC,IAAKhK,QAAkB,IAARgK,EAAqB,OAAO,KAE3C,MAAMD,EAAO/J,EAAO0J,MAAMC,IAAIM,OAAOD,GACrC,OAAKD,GAA2B,UAAnBA,EAAKlK,KAAK3B,KAEhB,CAAE8B,SAAQgK,MAAKD,QAF4B,IAGpD,CAEQ8K,cAAAA,CAAe7K,EAAaK,GAClC,MAAMrK,EAASf,KAAK0D,QACpB,IAAK3C,EAAU,OAEf,MAAM6W,EAAYvN,KAAKC,IAAI,EAAGD,KAAKG,IAAIO,EAAKhK,EAAO0J,MAAMC,IAAIvL,QAAQwL,OACrE5J,EACGiL,QACA4I,gBAAgBgD,EAAW,CAAEhX,KAAM,QAASwK,UAC5CyM,iBAAiBD,GACjB1L,KACL,CAEQ4L,8BAAAA,CAA+B1M,GACrC,MAAMmM,EAAgBvX,KAAKwX,wBAC3B,IAAKD,EAAiB,OAEtB,MAAMxW,OAAEA,EAAAgK,IAAQA,EAAAD,KAAKA,GAASyM,EAC9BxW,EAAOmJ,KAAKe,SAASlK,EAAO0J,MAAMS,GAAGC,cAAcJ,OAAK,EAAW,IAC9DD,EAAKM,SACLA,IAEP,CAEQ2M,cAAAA,CAAetW,GACrB,MAAMuW,EAAY3N,KAAKC,IAl5DH,GAk5DwBD,KAAKG,IAAIxK,KAAKgN,oBAAqB3C,KAAK4N,MAAMxW,KAC1FzB,KAAK8X,+BAA+B,CAAErW,MAAOuW,GAC/C,CAEQE,sBAAAA,CAAuB9U,GAC7B,MAAM+U,EAAY/U,EAAEC,OAA4B1B,MAAMuR,OACtD,IAAKiF,EAAY,OAEjB,MAAMxW,EAAQC,OAAOuW,GAChBvW,OAAOC,SAASF,IACrB3B,KAAK+X,eAAepW,EACtB,CAEQyW,kBAAAA,GACNpY,KAAK8X,+BAA+B,CAAEhW,MAAO,QAC/C,CAEQuW,oBAAAA,GACNrY,KAAK8X,+BAA+B,CAAEhW,MAAO,UAC/C,CAEQwW,mBAAAA,GACNtY,KAAK8X,+BAA+B,CAAEhW,MAAO,SAC/C,CAEQyW,aAAAA,GACN,MAAMxX,EAASf,KAAK0D,QACpB,OAAK3C,EACDA,EAAOoI,SAAS,UAAW,CAAE+I,MAAO,IAAe,OACnDnR,EAAOoI,SAAS,UAAW,CAAE+I,MAAO,IAAe,OACnDnR,EAAOoI,SAAS,UAAW,CAAE+I,MAAO,IAAe,OAChD,KAJe,IAKxB,CAEQsG,cAAAA,GACN,MAAMzX,EAASf,KAAK0D,QACpB,OAAK3C,EACDA,EAAOoI,SAAS,CAAEsP,UAAW,WAAsB,KACnD1X,EAAOoI,SAAS,CAAEsP,UAAW,UAAqB,MAC/C,MAHe,IAIxB,CAEQC,oBAAAA,GACN,MAAMnB,EAAgBvX,KAAK4E,eAC3B,OAAK2S,EAEElM,CAAA;8DACmDrL,KAAKsX;;;uDAGZtX,KAAK2X;;;;kCAIF,SAAxBJ,EAAczV,MAAmB,YAAc,0BAA0B9B,KAAKoY;;;kCAGtD,WAAxBb,EAAczV,MAAqB,YAAc,yBAAyB9B,KAAKqY;;;kCAGvD,UAAxBd,EAAczV,MAAoB,YAAc,0BAA0B9B,KAAKsY;;;;;;;;iBA98DzF;iBAu9DPtY,KAAKgN;mBACHzM,OAAOgX,EAAc9V;mBACrBzB,KAAKkY;;;MA3BS,EA+B/B,CAEQhP,yBAAAA,GACyB,UAA3BlJ,KAAKkG,mBACTM,sBAAsB,KACpB,MAAMmS,EAAa3Y,KAAKsF,YAAYiB,cAA2B,gBACzDqS,EAAc5Y,KAAKsF,YAAYiB,cAA2B,gBAC1DsF,EAAgB7L,KAAKsF,YAAYiB,cAA2B,mBAClE,IAAKoS,IAAeC,IAAgB/M,EAAiB,OAErD,MAAM9K,EAASf,KAAK0D,QACdmV,EAAY9X,GAAQoI,SAAS,WAAY,GACzC2D,UAAEA,GAAc/L,GAAQ0J,OAAS,CAAEqC,UAAW,MAGpD,GAAI+L,GAAa/L,IAAcA,EAAU0B,OAASzN,EAAQ,CACxD,MAAQgM,KAAAA,EAAAA,GAAMuB,GAAOxB,EACf2B,EAAQ1N,EAAO0J,MAAMC,IAAI3H,QAAQgK,GACjC+L,EAAM/X,EAAO0J,MAAMC,IAAI3H,QAAQuL,GAErC,IAAIyK,GAAsB,EAC1B,IAAA,IAAS1C,EAAI5H,EAAM6H,MAAOD,GAAK,EAAGA,IAChC,GAAgC,UAA5B5H,EAAM3D,KAAKuL,GAAGzV,KAAK3B,KAAkB,CACvC8Z,GAAsB,EACtB,KACF,CAGF,MAAMC,EAAevK,EAAM3D,KAAK2D,EAAM6H,OAChC2C,EAAaH,EAAIhO,KAAKgO,EAAIxC,OAIhC,GAH+B,UAA3B0C,EAAapY,KAAK3B,MAA6C,UAAzBga,EAAWrY,KAAK3B,OACxD8Z,GAAsB,GAEpBA,EAGF,OAFAJ,EAAW3W,MAAMkX,QAAU,SAC3BP,EAAW3W,MAAMmX,WAAa,SAGlC,CAGA,GAAIrM,IAAcA,EAAU0B,gBAGlB1B,GAAcA,EAAU0B,QAAUxO,KAAK6E,iBAG/C,OAFA8T,EAAW3W,MAAMkX,QAAU,SAC3BP,EAAW3W,MAAMmX,WAAa,UAIhC,MAAMtL,EAAchC,EAAciC,wBAC5BsL,EAAWT,EAAW7K,yBAEtBf,KAAEA,GAASD,EACXiB,EAAS/N,KAAK0D,SAASwG,KAAK8D,YAAYjB,GAC9C,IAAKgB,EAAU,OAEf,IAAIE,EAAOF,EAAOE,KAAOJ,EAAYI,KACjCE,EAAMJ,EAAOI,IAAMN,EAAYM,IAAM,GAErCF,EAAOmL,EAAS3X,MAAQoM,EAAYpM,QACtCwM,EAAOJ,EAAYpM,MAAQ2X,EAAS3X,MAAQ,GAE1CwM,EAAO,IACTA,EAAO,GAGLE,EAAM,IACRA,EAAMJ,EAAO+F,OAASjG,EAAYM,IAAM,GAG1CwK,EAAW3W,MAAMiM,KAAO,GAAGA,MAC3B0K,EAAW3W,MAAMmM,IAAM,GAAGA,MAC1BwK,EAAW3W,MAAMkX,QAAU,IAC3BP,EAAW3W,MAAMmX,WAAa,WAElC,CAEAE,MAAAA,GACE,MAAMtY,EAASf,KAAK0D,QAEpB,OAAO2H,CAAA;;gCAEsBtK,EAAqB,GAAZ,aAAkBf,KAAKgG,cAAgB,UAAY;qBACxEhG,KAAKqM;mBACPrM,KAAKoM;oBACJpM,KAAKsM;;UAEdvL,EAOC,GANAsK,CAAA;;;;;;;;;;oBAWQrL,KAAKwV;;;UAGdxV,KAAKgG,eAA4C,WAA3BhG,KAAKkG,kBAoJ1B,GAnJAmF,CAAA;oCACwBrL,KAAK4M,mBAAqB,aAAe;;cAE/D5M,KAAK4E,eACH5E,KAAK0Y,uBACLrN,CAAA;;sCAEsBtK,GAAQoI,SAAS,QAAU,YAAc;2BACpDnJ,KAAK6Q;;;;;;sCAMM9P,GAAQoI,SAAS,UAAY,YAAc;2BACtDnJ,KAAKiR;;;;;;sCAMMlQ,GAAQoI,SAAS,aAAe,YAAc;2BACzDnJ,KAAKqR;;;;;;sCAMMtQ,GAAQoI,SAAS,UAAY,YAAc;2BACtDnJ,KAAKyR;;;;;;;;;;sBAUVzR,KAAKuY;;;;0DAIgCxX,GAAQoI,SAAS,WAA2B,GAAd,uBAA4BnJ,KAAKqS;0DAChEtR,GAAQoI,SAAS,UAAW,CAAE+I,MAAO,IAAO,YAAc,cAAc,IAAMlS,KAAKiS,YAAY;0DAC/FlR,GAAQoI,SAAS,UAAW,CAAE+I,MAAO,IAAO,YAAc,cAAc,IAAMlS,KAAKiS,YAAY;0DAC/FlR,GAAQoI,SAAS,UAAW,CAAE+I,MAAO,IAAO,YAAc,cAAc,IAAMlS,KAAKiS,YAAY;;;;;;;;sBAQnIjS,KAAKwY;;;;0DAI+BzX,GAAQoI,SAAS,CAAEsP,UAAW,SAAY,YAAc,cAAc,IAAMzY,KAAK8S,cAAc;;;;0DAI/F/R,GAAQoI,SAAS,CAAEsP,UAAW,WAAc,YAAc,cAAc,IAAMzY,KAAK8S,cAAc;;;;0DAIjG/R,GAAQoI,SAAS,CAAEsP,UAAW,UAAa,YAAc,cAAc,IAAMzY,KAAK8S,cAAc;;;;;;;;;4CAS9G/R,GAAQoI,SAAS,QAAU,YAAc,cAAcnJ,KAAK6R;;;4CAG5D9Q,GAAQoI,SAAS,QAAU,YAAc,cAAcnJ,KAAKuT;;;oDAGpDvT,KAAK+V;;;;;;4CAMbhV,GAAQoI,SAAS,cAAgB,YAAc,cAAcnJ,KAAKuS;;;;;;;;;;4CAUlExR,GAAQoI,SAAS,eAAiB,YAAc,cAAcnJ,KAAKyS;;;;;;;;;;4CAUnE1R,GAAQoI,SAAS,YAAc,YAAc,cAAcnJ,KAAK2S;;;;;;;;;4CAShE5R,GAAQoI,SAAS,cAAgB,YAAc,cAAcnJ,KAAK4S;;;;;;;2CAOnE5S,KAAKgE,mBAAqB,UAAY;gCACjD,KACZhE,KAAKgE,oBAAqB,EAC1BhE,KAAK8D,UAAY,EACjB9D,KAAK+D,UAAY;gCAEL,IAAM/D,KAAKgE,oBAAqB;;;;;;;wBAOxChE,KAAKsZ;;;8BAGCtZ,KAAK8D,UAAY,EAAI,GAAG9D,KAAK8D,eAAe9D,KAAK+D,YAAc,GAAG/D,KAAK4D,gBAAgB5D,KAAK6D;;;;;;;;;;UAW/G7D,KAAKgG,eAA4C,UAA3BhG,KAAKkG,kBAmN1B,GAlNAmF,CAAA;;;;gCAIoBtK,GAAQoI,SAAS,QAAU,YAAc;qBACpDnJ,KAAK6Q;;;;;;gCAMM9P,GAAQoI,SAAS,UAAY,YAAc;qBACtDnJ,KAAKiR;;;;;;gCAMMlQ,GAAQoI,SAAS,aAAe,YAAc;qBACzDnJ,KAAKqR;;;;;;gCAMMtQ,GAAQoI,SAAS,UAAY,YAAc;qBACtDnJ,KAAKyR;;;;;;;;;;;gBAWVzR,KAAKuY;;;;;8CAK0BxX,GAAQoI,SAAS,WAA2B,GAAd;yBACpDnJ,KAAKqS;;;;;8CAKgBtR,GAAQoI,SAAS,UAAW,CAAE+I,MAAO,IAAO,YAAc;yBAC/E,IAAMlS,KAAKiS,YAAY;;;;;8CAKFlR,GAAQoI,SAAS,UAAW,CAAE+I,MAAO,IAAO,YAAc;yBAC/E,IAAMlS,KAAKiS,YAAY;;;;;8CAKFlR,GAAQoI,SAAS,UAAW,CAAE+I,MAAO,IAAO,YAAc;yBAC/E,IAAMlS,KAAKiS,YAAY;;;;;;;;;;;;gBAYhCjS,KAAKwY;;;;;8CAKyBzX,GAAQoI,SAAS,CAAEsP,UAAW,SAAY,YAAc;yBAC7E,IAAMzY,KAAK8S,cAAc;;;;;;8CAMJ/R,GAAQoI,SAAS,CAAEsP,UAAW,WAAc,YAAc;yBAC/E,IAAMzY,KAAK8S,cAAc;;;;;;8CAMJ/R,GAAQoI,SAAS,CAAEsP,UAAW,UAAa,YAAc;yBAC9E,IAAMzY,KAAK8S,cAAc;;;;;;;;;;;;gCAYlB/R,GAAQoI,SAAS,QAAU,YAAc;qBACpDnJ,KAAK6R;;;;;;;;gCAQM9Q,GAAQoI,SAAS,QAAU,YAAc;qBACpDnJ,KAAKuT;;;;;;;;;qBASLvT,KAAK+V;;;;;;;;;;gCAUMhV,GAAQoI,SAAS,cAAgB,YAAc;qBAC1DnJ,KAAKuS;;;;;;;;;;;;;gCAaMxR,GAAQoI,SAAS,eAAiB,YAAc;qBAC3DnJ,KAAKyS;;;;;;;;;;;;;gCAaM1R,GAAQoI,SAAS,YAAc,YAAc;qBACxDnJ,KAAK2S;;;;;;;;;;;;;;gCAcM5R,GAAQoI,SAAS,cAAgB,YAAc;qBAC1DnJ,KAAK4S;;;;;;;;;;qCAUW5S,KAAKgE,mBAAqB,UAAY;0BACjD,KACZhE,KAAKgE,oBAAqB,EAC1BhE,KAAK8D,UAAY,EACjB9D,KAAK+D,UAAY;0BAEL,IAAM/D,KAAKgE,oBAAqB;;;;;;;kBAOxChE,KAAKsZ;;;wBAGCtZ,KAAK8D,UAAY,EAAI,GAAG9D,KAAK8D,eAAe9D,KAAK+D,YAAc,GAAG/D,KAAK4D,gBAAgB5D,KAAK6D;;;;;;;sDAQ9D7D,KAAKoG;;UAEjDpG,KAAKwE,YAAYJ,QACfiH,CAAA;;;2BAGerL,KAAKwE,YAAYN,aAAalE,KAAKwE,YAAYL;yBAChDwF,GAAsBA,EAAMK;qBAChCL,GAAsBA,EAAMK;;;;;;;;;yBASzBhK,KAAKwE,YAAYC;yBACjBzE,KAAKuU;2BACHvU,KAAKiV;;;;;;;;;;yBAUPjV,KAAKwE,YAAYE;yBACjB1E,KAAKuU;2BACHvU,KAAKiV;;;;gFAIgDjV,KAAK0U;0EACX1U,KAAK2M;gBAC9D5L,GAAQoI,SAAS,SAAWnJ,KAAKwE,YAAYC,IAC5C4G,CAAA,kEAAsErL,KAAK+U,0BAC3E;;;YAIN;;;UAGF/U,KAAKiE,kBAAkBG,SAAWrD,GAAQoI,SAAS,SACjDkC,CAAA;;;2BAGerL,KAAKiE,kBAAkBC,aAAalE,KAAKiE,kBAAkBE;yBAC5Df,GAAaA,EAAE2G;;cAEQ,IAAnC/J,KAAKiE,kBAAkBI,QACrBgH,CAAA;4EAC4DrL,KAAKwW;;;4EAGLxW,KAAK0W;;;iFAGA1W,KAAKgX;;;cAItE;cACiC,IAAnChX,KAAKiE,kBAAkBK,QACrB+G,CAAA;gBACmC,IAAnCrL,KAAKiE,kBAAkBI,QAAgBgH,8EAAmF;4EAC9DrL,KAAK4W;;;4EAGL5W,KAAK8W;;;iFAGA9W,KAAKkX;;;cAItE;cACiC,IAAnClX,KAAKiE,kBAAkBI,SAAoD,IAAnCrE,KAAKiE,kBAAkBK,QAC7D+G,CAAA;;kFAEkErL,KAAKoX;;;cAIvE;;YAGJ;;;UAGyB,UAA3BpX,KAAKkG,mBAAiClG,KAAKuE,cAAcH,QACvDiH,CAAA;;;2BAGerL,KAAKuE,cAAcL,aAAalE,KAAKuE,cAAcJ;yBACpDf,GAAaA,EAAE2G;;cAE3B/J,KAAK0Y;;YAGP;;KAGV,CAEQY,gBAAAA,GACN,MAAMC,EAAQ,GACd,IAAA,IAASC,EAAI,EAAGA,EAAI,IAAKA,IAAK,CAC5B,MAAMC,EAAMpP,KAAKqP,MAAMF,EAAI,IAAM,EAC3BG,EAAOH,EAAI,GAAM,EACjBI,EAAc5Z,KAAK8D,UAAY,GAAK2V,GAAOzZ,KAAK8D,WAAa6V,GAAO3Z,KAAK+D,UAC/EwV,EAAMM,KAAKxO,CAAA;;8BAEauO,EAAc,WAAa;mBACtC,KACP5Z,KAAKiW,oBAAoBwD,EAAKE,GAC9B3Z,KAAKgE,oBAAqB;wBAEd,KACZhE,KAAK8D,UAAY2V,EACjBzZ,KAAK+D,UAAY4V;wBAEL,KACZ3Z,KAAK8D,UAAY,EACjB9D,KAAK+D,UAAY;;QAIzB,CACA,OAAOwV,CACT,GA18EWnX,EACJ0X,OAASC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4xBhBC,EAAA,CADCC,EAAS,CAAErZ,KAAML,OAAQ2Z,UAAW,aA5xB1B9X,EA6xBX+X,UAAA,UAAA,GAGAH,EAAA,CADCC,EAAS,CAAErZ,KAAML,OAAQ2Z,UAAW,iBA/xB1B9X,EAgyBX+X,UAAA,cAAA,GAGAH,EAAA,CADCC,EAAS,CAAErZ,KAAML,OAAQ2Z,UAAW,iBAlyB1B9X,EAmyBX+X,UAAA,cAAA,GAGAH,EAAA,CADCC,EAAS,CAAErZ,KAAML,OAAQ2Z,UAAW,kBAryB1B9X,EAsyBX+X,UAAA,eAAA,GAGAH,EAAA,CADCC,EAAS,CAAErZ,KAAML,OAAQ2Z,UAAW,2BAxyB1B9X,EAyyBX+X,UAAA,wBAAA,GAGAH,EAAA,CADCC,EAAS,CAAErZ,KAAML,OAAQ2Z,UAAW,eA3yB1B9X,EA4yBX+X,UAAA,YAAA,GAGAH,EAAA,CADCC,EAAS,CAAErZ,KAAML,OAAQ2Z,UAAW,cA9yB1B9X,EA+yBX+X,UAAA,WAAA,GAGAH,EAAA,CADCC,EAAS,CAAErZ,KAAML,OAAQ2Z,UAAW,aAjzB1B9X,EAkzBX+X,UAAA,UAAA,GAGAH,EAAA,CADCC,EAAS,CAAErZ,KAAML,OAAQ2Z,UAAW,mBApzB1B9X,EAqzBX+X,UAAA,gBAAA,GA8DAH,EAAA,CADCC,EAAS,CAAErZ,KAAMwZ,OAAQF,UAAW,kBAl3B1B9X,EAm3BX+X,UAAA,eAAA,GASiBH,EAAA,CAAhBvP,KA53BUrI,EA43BM+X,UAAA,UAAA,GACAH,EAAA,CAAhBvP,KA73BUrI,EA63BM+X,UAAA,kBAAA,GAGAH,EAAA,CAAhBvP,KAh4BUrI,EAg4BM+X,UAAA,YAAA,GACAH,EAAA,CAAhBvP,KAj4BUrI,EAi4BM+X,UAAA,YAAA,GACAH,EAAA,CAAhBvP,KAl4BUrI,EAk4BM+X,UAAA,qBAAA,GACAH,EAAA,CAAhBvP,KAn4BUrI,EAm4BM+X,UAAA,oBAAA,GACAH,EAAA,CAAhBvP,KAp4BUrI,EAo4BM+X,UAAA,gBAAA,GACAH,EAAA,CAAhBvP,KAr4BUrI,EAq4BM+X,UAAA,cAAA,GACAH,EAAA,CAAhBvP,KAt4BUrI,EAs4BM+X,UAAA,mBAAA,GACAH,EAAA,CAAhBvP,KAv4BUrI,EAu4BM+X,UAAA,iBAAA,GAv4BN/X,EAAN4X,EAAA,CADNK,EAAkB,0BACNjY"}
1
+ {"version":3,"file":"blocksuite-editor.mjs","sources":["../../../../packages/components-wc/src/editor/blocksuite-editor.ts"],"sourcesContent":["import { Editor, Extension, mergeAttributes, Node as TiptapNode } from '@tiptap/core'\nimport Blockquote from '@tiptap/extension-blockquote'\nimport Bold from '@tiptap/extension-bold'\nimport BulletList from '@tiptap/extension-bullet-list'\nimport Code from '@tiptap/extension-code'\nimport Document from '@tiptap/extension-document'\nimport Heading from '@tiptap/extension-heading'\nimport History from '@tiptap/extension-history'\nimport HorizontalRule from '@tiptap/extension-horizontal-rule'\nimport Image from '@tiptap/extension-image'\nimport Italic from '@tiptap/extension-italic'\nimport Link from '@tiptap/extension-link'\nimport ListItem from '@tiptap/extension-list-item'\nimport OrderedList from '@tiptap/extension-ordered-list'\nimport Paragraph from '@tiptap/extension-paragraph'\nimport Placeholder from '@tiptap/extension-placeholder'\nimport Strike from '@tiptap/extension-strike'\nimport { Table } from '@tiptap/extension-table'\nimport { TableCell } from '@tiptap/extension-table-cell'\nimport { TableHeader } from '@tiptap/extension-table-header'\nimport { TableRow } from '@tiptap/extension-table-row'\nimport Text from '@tiptap/extension-text'\nimport TextAlign from '@tiptap/extension-text-align'\nimport Underline from '@tiptap/extension-underline'\nimport { css, html, LitElement } from 'lit'\nimport type { EditorToolbarItem } from './toolbar'\nimport { property, state } from 'lit/decorators.js'\nimport { DEFAULT_EDITOR_TOOLBAR, parseEditorToolbarItems } from './toolbar'\nimport { safeCustomElement } from '../base/define'\n\ntype ToolbarMode = 'slash' | 'header'\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n taskList: {\n toggleTaskList: () => ReturnType\n }\n }\n}\n\nconst DEFAULT_IMAGE_WIDTH = 560\nconst MIN_IMAGE_WIDTH = 24\nconst DEFAULT_HEADER_PLACEHOLDER = '输入内容'\nconst DEFAULT_SLASH_PLACEHOLDER = '输入 / 唤出快捷命令'\n\nconst TaskList = TiptapNode.create({\n name: 'taskList',\n group: 'block list',\n content: 'taskItem+',\n defining: true,\n\n parseHTML() {\n return [{ tag: 'ul[data-type=\"taskList\"]' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['ul', mergeAttributes(HTMLAttributes, { 'data-type': 'taskList' }), 0]\n },\n\n addCommands() {\n return {\n toggleTaskList: () => ({ commands }) => commands.toggleList(this.name, 'taskItem'),\n }\n },\n})\n\nconst TaskItem = TiptapNode.create({\n name: 'taskItem',\n defining: true,\n content: 'paragraph block*',\n\n addAttributes() {\n return {\n checked: {\n default: false,\n parseHTML: element => element.getAttribute('data-checked') === 'true',\n renderHTML: attributes => ({ 'data-checked': String(Boolean(attributes.checked)) }),\n },\n }\n },\n\n parseHTML() {\n return [{ tag: 'li[data-type=\"taskItem\"]' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n const checked = Boolean(HTMLAttributes.checked)\n\n return [\n 'li',\n mergeAttributes(HTMLAttributes, { 'data-type': 'taskItem' }),\n [\n 'label',\n { contenteditable: 'false' },\n ['input', { type: 'checkbox', checked: checked ? 'checked' : null }],\n ['span'],\n ],\n ['div', 0],\n ]\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => this.editor.commands.splitListItem(this.name),\n Tab: () => this.editor.commands.sinkListItem(this.name),\n 'Shift-Tab': () => this.editor.commands.liftListItem(this.name),\n }\n },\n})\n\nconst ExtendedImage = Image.extend({\n addAttributes() {\n return {\n ...this.parent?.(),\n width: {\n default: null,\n parseHTML: (element) => {\n const attr = element.getAttribute('width')\n const value = Number(attr)\n return Number.isFinite(value) && value > 0 ? value : null\n },\n renderHTML: attributes => attributes.width ? { width: String(attributes.width) } : {},\n },\n align: {\n default: 'left',\n parseHTML: element => element.getAttribute('data-align') || 'left',\n renderHTML: attributes => attributes.align ? { 'data-align': String(attributes.align) } : {},\n },\n }\n },\n\n renderHTML({ HTMLAttributes }) {\n const width = Number(HTMLAttributes.width)\n\n const style = [\n 'max-width:100%',\n 'height:auto',\n Number.isFinite(width) && width > 0 ? `width:${width}px` : '',\n HTMLAttributes.style || '',\n ]\n .filter(Boolean)\n .join(';')\n\n return ['img', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { style })]\n },\n})\n\n@safeCustomElement('qxs-blocksuite-editor')\nexport class QxsBlocksuiteEditor extends LitElement {\n static styles = css`\n :host {\n display: block;\n font-family: inherit;\n }\n\n .editor-wrapper {\n border: 1px solid #e3e3e3;\n border-radius: 12px;\n background: #fff;\n overflow: visible;\n position: relative;\n min-height: 80px;\n }\n\n .editor-wrapper:focus-within {\n border-color: var(--qxs-color-primary, #3D61E3);\n }\n\n .editor-wrapper.preview {\n border: none;\n border-radius: 0;\n background: transparent;\n }\n\n .editor-wrapper.preview .editor-content {\n padding: 8px 12px;\n min-height: unset;\n }\n\n .editor-header {\n max-height: 0;\n opacity: 0;\n overflow: hidden;\n padding: 0 16px;\n border-bottom: 1px solid transparent;\n transition:\n max-height 0.24s ease,\n opacity 0.18s ease,\n padding 0.24s ease,\n border-color 0.24s ease;\n }\n\n .editor-header.is-visible {\n max-height: 132px;\n opacity: 1;\n overflow: visible;\n padding: 10px 12px;\n border-bottom-color: #eef1f5;\n }\n\n .editor-header__inner {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n overflow: visible;\n }\n\n .editor-content {\n padding: 12px 16px;\n min-height: 80px;\n cursor: text;\n }\n\n .editor-content:empty::before {\n content: attr(data-empty-hint);\n color: #c0c0c0;\n pointer-events: none;\n display: block;\n padding-top: 28px;\n text-align: center;\n }\n\n .editor-content .ProseMirror:empty {\n min-height: 80px;\n }\n\n .ProseMirror p.is-editor-empty:first-child::before {\n content: attr(data-placeholder);\n color: #c0c0c0;\n pointer-events: none;\n float: left;\n height: 0;\n }\n\n .ProseMirror p.is-empty:only-child::before,\n .ProseMirror p.is-empty:only-child > br:first-child + *::before {\n content: attr(data-placeholder);\n color: #c0c0c0;\n pointer-events: none;\n float: left;\n height: 0;\n }\n\n .editor-wrapper.loading {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n background: #fafafa;\n }\n\n .loading-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n color: #909399;\n font-size: 14px;\n }\n\n .loading-spinner {\n width: 24px;\n height: 24px;\n border: 2px solid #e3e3e3;\n border-top-color: var(--qxs-color-primary, #3D61E3);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n }\n\n @keyframes spin {\n to { transform: rotate(360deg); }\n }\n\n .ProseMirror {\n outline: none;\n line-height: 1.7;\n color: #37352f;\n font-size: 15px;\n }\n\n .ProseMirror > * + * {\n margin-top: 0.5em;\n }\n\n .ProseMirror > *:first-child {\n margin-top: 0 !important;\n }\n\n .ProseMirror p {\n margin: 0;\n }\n\n .ProseMirror h1 {\n font-size: 1.875em;\n font-weight: 700;\n margin: 0 0 0.25em;\n line-height: 1.3;\n }\n\n .ProseMirror > h1:first-child {\n margin-top: 0 !important;\n line-height: 1.15;\n }\n\n .ProseMirror > p:first-child {\n margin-top: 0 !important;\n }\n\n .ProseMirror h2 {\n font-size: 1.5em;\n font-weight: 600;\n margin: 0.5em 0 0.25em;\n line-height: 1.3;\n }\n\n .ProseMirror h3 {\n font-size: 1.25em;\n font-weight: 600;\n margin: 0.5em 0 0.25em;\n line-height: 1.3;\n }\n\n .ProseMirror ul,\n .ProseMirror ol {\n padding-left: 1.5em;\n margin: 0;\n }\n\n .ProseMirror ul[data-type=\"taskList\"] {\n padding-left: 0;\n list-style: none;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n list-style: none;\n margin: 0.2em 0;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] > label {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 28px;\n flex: 0 0 18px;\n cursor: pointer;\n user-select: none;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] > label > input {\n width: 14px;\n height: 14px;\n margin: 0;\n cursor: pointer;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] > label > span {\n display: none;\n }\n\n .ProseMirror li[data-type=\"taskItem\"] > div {\n flex: 1;\n min-width: 0;\n }\n\n .ProseMirror li[data-type=\"taskItem\"][data-checked=\"true\"] > div p {\n color: #8a8f98;\n text-decoration: line-through;\n }\n\n .ProseMirror li {\n margin: 0.1em 0;\n }\n\n .ProseMirror li::marker {\n color: #37352f;\n }\n\n .ProseMirror strong {\n font-weight: 700;\n }\n\n .ProseMirror em {\n font-style: italic;\n font-synthesis: none;\n transform: skewX(-12deg);\n display: inline-block;\n }\n\n .ProseMirror u {\n text-decoration: underline;\n }\n\n .ProseMirror s {\n text-decoration: line-through;\n color: #787774;\n }\n\n .ProseMirror code {\n background: rgba(135, 131, 120, 0.14);\n color: #eb5757;\n padding: 2px 4px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', Menlo, Consolas, monospace;\n font-size: 85%;\n }\n\n .ProseMirror pre {\n background: #f6f6f7;\n border-radius: 8px;\n padding: 12px 16px;\n overflow-x: auto;\n }\n\n .ProseMirror pre code {\n background: none;\n padding: 0;\n color: #37352f;\n }\n\n .ProseMirror blockquote {\n border-left: 3px solid #e3e3e3;\n padding-left: 1em;\n margin: 0.75em 0;\n color: #787774;\n }\n\n .ProseMirror hr {\n border: none;\n border-top: 1px solid #e3e3e3;\n margin: 1.5em 0;\n }\n\n .ProseMirror img {\n max-width: 100%;\n height: auto;\n border-radius: 8px;\n }\n\n .ProseMirror img[data-align=\"left\"] {\n display: block !important;\n margin: 16px auto 16px 0 !important;\n }\n\n .ProseMirror img[data-align=\"center\"] {\n display: block !important;\n margin: 16px auto !important;\n }\n\n .ProseMirror img[data-align=\"right\"] {\n display: block !important;\n margin: 16px 0 16px auto !important;\n }\n\n .ProseMirror a {\n color: var(--qxs-color-primary, #3D61E3);\n text-decoration: underline;\n cursor: pointer;\n }\n\n .ProseMirror img.ProseMirror-selectednode {\n outline: 2px solid var(--qxs-color-primary, #3D61E3);\n outline-offset: 2px;\n box-shadow: 0 0 0 4px rgba(61, 97, 227, 0.12);\n }\n\n /* Table styles */\n .ProseMirror table {\n border-collapse: collapse;\n width: 100%;\n margin: 1em 0;\n border: 1px solid #e3e3e3;\n border-radius: 8px;\n overflow: hidden;\n }\n\n .ProseMirror th,\n .ProseMirror td {\n border: 1px solid #e3e3e3;\n padding: 8px 12px;\n text-align: left;\n vertical-align: top;\n }\n\n .ProseMirror th {\n background: #fafafa;\n font-weight: 600;\n }\n\n .ProseMirror .selectedCell {\n background: rgba(30, 150, 252, 0.1);\n }\n\n /* Table Cell Toolbar */\n .table-cell-toolbar {\n position: absolute;\n z-index: 50;\n display: flex;\n gap: 2px;\n padding: 4px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n\n .table-cell-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #606266;\n transition: all 0.15s;\n }\n\n .table-cell-toolbar-btn:hover {\n background: #ecf5ff;\n color: var(--qxs-color-primary, #3D61E3);\n }\n\n .table-cell-toolbar-btn.danger:hover {\n background: #fef0f0;\n color: #f56c6c;\n }\n\n /* Bubble Menu */\n .bubble-menu {\n position: absolute;\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 6px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n z-index: 100;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.15s, visibility 0.15s, transform 0.15s;\n transform: translateY(4px);\n max-width: calc(100vw - 40px);\n }\n\n .bubble-menu.is-visible {\n opacity: 1;\n visibility: visible;\n transform: translateY(0);\n }\n\n .bubble-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n color: #37352f;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s;\n position: relative;\n }\n\n .bubble-btn:hover {\n background: rgba(55, 53, 47, 0.08);\n }\n\n .bubble-btn.is-active {\n background: var(--qxs-color-primary, #3D61E3);\n color: #fff;\n }\n\n .bubble-btn.danger:hover {\n background: #fef0f0;\n color: #f56c6c;\n }\n\n .bubble-btn svg {\n width: 16px;\n height: 16px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n .bubble-divider {\n width: 1px;\n height: 16px;\n background: #e3e3e3;\n margin: 0 3px;\n }\n\n /* Dropdown */\n .bubble-dropdown {\n position: relative;\n }\n\n .bubble-dropdown-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 0 6px;\n height: 28px;\n border: none;\n background: transparent;\n color: #37352f;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n font-family: inherit;\n transition: all 0.15s;\n white-space: nowrap;\n }\n\n .bubble-dropdown-btn:hover {\n background: rgba(55, 53, 47, 0.08);\n }\n\n .bubble-dropdown-btn svg {\n width: 12px;\n height: 12px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n .bubble-dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 4px;\n min-width: 120px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n padding: 4px;\n opacity: 0;\n visibility: hidden;\n transform: translateY(-4px);\n transition: all 0.15s;\n z-index: 101;\n }\n\n .bubble-dropdown:hover .bubble-dropdown-menu,\n .bubble-dropdown.is-open .bubble-dropdown-menu {\n opacity: 1;\n visibility: visible;\n transform: translateY(0);\n }\n\n .bubble-dropdown-item {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 6px 8px;\n border: none;\n background: transparent;\n color: #37352f;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n font-family: inherit;\n text-align: left;\n transition: all 0.15s;\n }\n\n .bubble-dropdown-item:hover {\n background: rgba(55, 53, 47, 0.08);\n }\n\n .bubble-dropdown-item.is-active {\n background: var(--qxs-color-primary, #3D61E3);\n color: #fff;\n }\n\n .bubble-dropdown-item svg {\n width: 16px;\n height: 16px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n .image-input {\n display: none;\n }\n\n .table-grid-preview {\n display: grid;\n grid-template-columns: repeat(10, 18px);\n gap: 2px;\n padding: 8px;\n }\n\n .table-grid-preview .table-cell {\n width: 18px;\n height: 18px;\n border: 1px solid #e3e3e3;\n border-radius: 2px;\n background: #fff;\n cursor: pointer;\n transition: all 0.1s;\n }\n\n .table-grid-preview .table-cell:hover {\n background: rgba(30, 150, 252, 0.3);\n border-color: var(--qxs-color-primary, #3D61E3);\n }\n\n .table-grid-preview .table-cell.selected {\n background: rgba(30, 150, 252, 0.15);\n border-color: rgba(30, 150, 252, 0.5);\n }\n\n .table-size-hint {\n text-align: center;\n padding: 4px 8px 6px;\n font-size: 10px;\n color: #8c8c8c;\n }\n\n .image-size-control {\n display: flex;\n align-items: center;\n gap: 6px;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid #e3e3e3;\n white-space: nowrap;\n }\n\n .image-size-label {\n font-size: 12px;\n color: #7a7f88;\n }\n\n .image-size-range {\n width: 72px;\n height: 26px;\n padding: 0 8px;\n border: 1px solid #d8dde6;\n border-radius: 6px;\n font-size: 12px;\n color: #37352f;\n background: #fff;\n outline: none;\n }\n\n .image-size-range:focus {\n border-color: var(--qxs-color-primary, #3D61E3);\n }\n\n .link-editor {\n position: absolute;\n z-index: 120;\n display: grid;\n gap: 8px;\n min-width: 320px;\n padding: 10px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 10px;\n box-shadow: 0 12px 32px rgba(15, 23, 42, 0.14);\n }\n\n .link-editor__field {\n display: grid;\n gap: 4px;\n }\n\n .link-editor__label {\n font-size: 12px;\n color: #6b7280;\n line-height: 1;\n }\n\n .link-editor__input {\n min-width: 0;\n height: 32px;\n padding: 0 10px;\n border: 1px solid #d8dde6;\n border-radius: 8px;\n outline: none;\n font-size: 13px;\n color: #37352f;\n background: #fff;\n }\n\n .link-editor__input:focus {\n border-color: var(--qxs-color-primary, #3D61E3);\n }\n\n .link-editor__actions {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .link-editor__action {\n height: 32px;\n padding: 0 12px;\n border: 1px solid #d8dde6;\n border-radius: 8px;\n background: #fff;\n color: #4b5563;\n font-size: 12px;\n font-family: inherit;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n\n .link-editor__action:hover {\n border-color: #c3cad5;\n background: #f8fafc;\n }\n\n .link-editor__action.primary {\n border-color: var(--qxs-color-primary, #3D61E3);\n background: var(--qxs-color-primary, #3D61E3);\n color: #fff;\n }\n\n .link-editor__action.danger {\n color: #f56c6c;\n }\n\n /* Image Toolbar */\n .image-toolbar {\n position: absolute;\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 6px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n z-index: 100;\n transform: translateX(-50%);\n }\n\n .image-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #595959;\n transition: all 0.15s;\n }\n\n .image-toolbar-btn:hover {\n background: #f5f5f5;\n color: var(--qxs-color-primary, #3D61E3);\n }\n\n .image-toolbar-btn.danger:hover {\n background: #fff1f0;\n color: #ff4d4f;\n }\n\n .image-toolbar-btn svg {\n width: 16px;\n height: 16px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n .image-toolbar-divider {\n width: 1px;\n height: 20px;\n background: #e3e3e3;\n margin: 0 4px;\n }\n\n .image-control-label {\n display: inline-flex;\n align-items: center;\n padding: 0 4px;\n font-size: 12px;\n color: #909399;\n user-select: none;\n white-space: nowrap;\n }\n\n /* Image More Menu */\n .image-more-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n padding: 4px;\n background: #fff;\n border: 1px solid #e3e3e3;\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n z-index: 101;\n min-width: 120px;\n }\n\n .image-more-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border: none;\n background: transparent;\n width: 100%;\n text-align: left;\n font-size: 13px;\n color: #595959;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .image-more-menu-item:hover {\n background: #f5f5f5;\n color: var(--qxs-color-primary, #3D61E3);\n }\n\n .image-more-menu-item svg {\n width: 14px;\n height: 14px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n }\n\n /* Selected Image */\n .ProseMirror img.selected {\n outline: 2px solid var(--qxs-color-primary, #3D61E3);\n outline-offset: 2px;\n }\n `\n\n @property({ type: String, attribute: 'content' })\n content = ''\n\n @property({ type: String, attribute: 'model-value' })\n 'model-value' = ''\n\n @property({ type: String, attribute: 'placeholder' })\n placeholder = DEFAULT_HEADER_PLACEHOLDER\n\n @property({ type: String, attribute: 'toolbar-mode' })\n 'toolbar-mode': ToolbarMode = 'header'\n\n @property({ attribute: 'toolbar' })\n toolbar: string | EditorToolbarItem[] = DEFAULT_EDITOR_TOOLBAR.join(' ')\n\n @property({ type: String, attribute: 'header-always-visible' })\n 'header-always-visible' = 'false'\n\n @property({ type: String, attribute: 'use-model' })\n 'use-model' = 'false'\n\n @property({ type: String, attribute: 'readonly' })\n readonly = 'false'\n\n @property({ type: String, attribute: 'preview' })\n preview = 'false'\n\n @property({ type: String, attribute: 'custom-styles' })\n 'custom-styles' = ''\n\n private _injectedStyleEl: HTMLStyleElement | null = null\n\n private _injectCustomStyles() {\n const shadow = this.shadowRoot\n if (!shadow) { return }\n\n if (this._injectedStyleEl) {\n this._injectedStyleEl.remove()\n this._injectedStyleEl = null\n }\n\n if (!this['custom-styles']) { return }\n\n const styleEl = document.createElement('style')\n styleEl.textContent = this['custom-styles']\n shadow.appendChild(styleEl)\n this._injectedStyleEl = styleEl\n }\n\n private get _useModelValue(): boolean {\n return this['use-model'] === true || this['use-model'] === 'true' || this['use-model'] === '' || this.hasAttribute('use-model')\n }\n\n private get _readonlyValue(): boolean {\n return this.readonly !== false && this.readonly !== 'false'\n }\n\n private get _previewValue(): boolean {\n return this.preview !== false && this.preview !== 'false'\n }\n\n private get _isEditable(): boolean {\n return !this._readonlyValue && !this._previewValue\n }\n\n private get _toolbarModeValue(): ToolbarMode {\n return this['toolbar-mode'] === 'header' ? 'header' : 'slash'\n }\n\n private get _headerAlwaysVisibleValue(): boolean {\n return this['header-always-visible'] === true\n || this['header-always-visible'] === 'true'\n || this['header-always-visible'] === ''\n || this.hasAttribute('header-always-visible')\n }\n\n private get _resolvedPlaceholder(): string {\n if (\n this.placeholder\n && this.placeholder !== DEFAULT_HEADER_PLACEHOLDER\n && this.placeholder !== DEFAULT_SLASH_PLACEHOLDER\n ) {\n return this.placeholder\n }\n return this._toolbarModeValue === 'header'\n ? DEFAULT_HEADER_PLACEHOLDER\n : DEFAULT_SLASH_PLACEHOLDER\n }\n\n private get _toolbarItemsValue(): EditorToolbarItem[] {\n return parseEditorToolbarItems(this.toolbar)\n }\n\n private _hasToolbarItem(item: EditorToolbarItem): boolean {\n return this._toolbarItemsValue.includes(item)\n }\n\n @property({ type: Object, attribute: 'upload-image' })\n 'upload-image': (file: File) => Promise<string> = async (file: File) => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = e => resolve(e.target?.result as string)\n reader.onerror = reject\n reader.readAsDataURL(file)\n })\n }\n\n @state() private _editor: Editor | null = null\n private _pendingContent: string | null = null\n private _tableRows = 3\n private _tableCols = 3\n @state() private _hoverRow = 0\n @state() private _hoverCol = 0\n @state() private _tableDropdownOpen = false\n @state() private _tableCellToolbar: { x: number, y: number, visible: boolean, cellRow: number, cellCol: number } = { x: 0, y: 0, visible: false, cellRow: 0, cellCol: 0 }\n @state() private _imageToolbar: { x: number, y: number, visible: boolean } = { x: 0, y: 0, visible: false }\n @state() private _linkEditor = { x: 0, y: 0, visible: false, url: '', label: '' }\n @state() private _isEditorFocused = false\n @state() private _selectedImage: { pos: number, width: number, align: string } | null = null\n private _hasSlashCommand = false\n private _slashCommandRange: { from: number, to: number } | null = null\n private _isUpdating = false\n private _pendingImageInsertPos: number | null = null\n private _linkSelection: { from: number, to: number } | null = null\n private _preserveFocusOnInternalClick = false\n\n private _initEditor() {\n if (this._editor) { return }\n\n const el = this.shadowRoot?.querySelector<HTMLElement>('.editor-content')\n if (!el) {\n requestAnimationFrame(() => this._initEditor())\n return\n }\n\n while (el.firstChild) {\n el.removeChild(el.firstChild)\n }\n\n const useModel = this._useModelValue\n const modelValue = this.getAttribute('model-value') ?? this['model-value']\n const contentValue = this.content\n\n const initialContent = useModel\n ? (this._pendingContent ?? modelValue) || '<p></p>'\n : (this._pendingContent ?? contentValue) || '<p></p>'\n\n const extensions: any[] = [\n Document,\n Paragraph,\n Text,\n Bold,\n Italic,\n Underline,\n Strike,\n Code,\n Heading.configure({ levels: [1, 2, 3] }),\n BulletList,\n OrderedList,\n TaskList,\n TaskItem,\n ListItem,\n Blockquote,\n HorizontalRule,\n History,\n ExtendedImage.configure({\n inline: false,\n allowBase64: true,\n }),\n Link.extend({\n inclusive: false,\n }).configure({\n openOnClick: false,\n HTMLAttributes: {\n rel: 'noopener noreferrer',\n },\n }),\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Table.configure({\n resizable: true,\n }),\n TableRow,\n TableCell,\n TableHeader,\n Placeholder.configure({\n placeholder: this._resolvedPlaceholder,\n }),\n ]\n\n this._editor = new Editor({\n element: el,\n extensions,\n editable: this._isEditable,\n content: initialContent,\n })\n\n this._pendingContent = null\n\n this._editor.on('selectionUpdate', () => {\n if (this._toolbarModeValue === 'slash') {\n this._updateBubbleMenuPosition()\n }\n if (this._editor?.isActive('table')) {\n this._showTableCellToolbar()\n }\n else {\n this._hideTableCellToolbar()\n }\n this._syncImageSelectionState()\n })\n\n this._editor.on('transaction', () => {\n if (this._editor?.isActive('table')) {\n this._showTableCellToolbar()\n }\n else {\n this._hideTableCellToolbar()\n }\n this._checkSlashCommand()\n this._setupTableEdgeDetection()\n this._syncImageSelectionState()\n })\n\n this._editor.on('update', () => {\n this._emitContentChange()\n })\n }\n\n private _tableEdgeDetectionSetup = false\n\n private _toggleTaskItemChecked(event: MouseEvent) {\n const target = event.target\n const editor = this._editor\n if (!(target instanceof HTMLInputElement) || target.type !== 'checkbox' || !editor) {\n return\n }\n\n const taskItem = target.closest('li[data-type=\"taskItem\"]')\n if (!taskItem) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n const basePos = editor.view.posAtDOM(taskItem, 0)\n const searchFrom = Math.max(0, basePos - 2)\n const searchTo = Math.min(editor.state.doc.content.size, basePos + 2)\n\n let taskItemPos: number | null = null\n editor.state.doc.nodesBetween(searchFrom, searchTo, (node, pos) => {\n if (node.type.name === 'taskItem') {\n taskItemPos = pos\n return false\n }\n return undefined\n })\n\n if (taskItemPos === null) {\n return\n }\n\n const node = editor.state.doc.nodeAt(taskItemPos)\n if (!node || node.type.name !== 'taskItem') {\n return\n }\n\n editor.view.dispatch(editor.state.tr.setNodeMarkup(taskItemPos, undefined, {\n ...node.attrs,\n checked: !node.attrs.checked,\n }))\n }\n\n private _emitContentChange() {\n if (!this._editor) { return }\n const html = this._editor.getHTML()\n\n this.dispatchEvent(new CustomEvent('content-change', {\n detail: html,\n bubbles: true,\n composed: true,\n }))\n }\n\n private _setupTableEdgeDetection() {\n const editorContent = this.shadowRoot?.querySelector('.editor-content')\n const editorWrapper = this.shadowRoot?.querySelector('.editor-wrapper')\n if (!editorContent || this._tableEdgeDetectionSetup) { return }\n\n this._tableEdgeDetectionSetup = true\n\n const handleEditorClick = (event: MouseEvent) => {\n this._toggleTaskItemChecked(event)\n\n const target = event.target\n if (\n target instanceof Element\n && target.closest('.editor-header, .bubble-menu, .table-cell-toolbar, .image-toolbar, .link-editor')\n ) {\n return\n }\n if (!this._isEditable) {\n return\n }\n this._editor?.chain().focus().run()\n }\n\n editorContent.addEventListener('click', handleEditorClick)\n editorWrapper?.addEventListener('click', handleEditorClick)\n }\n\n private _handleWrapperFocusIn() {\n this._preserveFocusOnInternalClick = false\n this._isEditorFocused = true\n }\n\n private _handleWrapperMouseDown(event: MouseEvent) {\n const target = event.target\n if (\n !this._isEditable\n || !(target instanceof Element)\n || target.closest('.editor-header, .bubble-menu, .table-cell-toolbar, .image-toolbar, .link-editor')\n ) {\n return\n }\n\n this._preserveFocusOnInternalClick = true\n requestAnimationFrame(() => {\n this._preserveFocusOnInternalClick = false\n })\n }\n\n private _handleWrapperFocusOut(event: FocusEvent) {\n const nextTarget = event.relatedTarget as Node | null\n const wrapper = this.shadowRoot?.querySelector('.editor-wrapper')\n if (this._preserveFocusOnInternalClick) {\n return\n }\n if (nextTarget && wrapper?.contains(nextTarget)) {\n return\n }\n this._isEditorFocused = false\n this._tableDropdownOpen = false\n this._closeLinkEditor()\n }\n\n private _isHeaderVisible(): boolean {\n return this._toolbarModeValue === 'header'\n && !this._previewValue\n && (\n this._headerAlwaysVisibleValue\n || this._isEditorFocused\n || this._tableDropdownOpen\n || Boolean(this._selectedImage)\n )\n }\n\n private _getImageSelection() {\n const editor = this._editor\n const selection: any = editor?.state.selection\n if (!editor || !selection?.node || selection.node.type?.name !== 'image') {\n return null\n }\n\n return {\n pos: selection.from,\n attrs: selection.node.attrs ?? {},\n }\n }\n\n private _getImageMaxWidth() {\n const editorContent = this.shadowRoot?.querySelector<HTMLElement>('.editor-content')\n const availableWidth = (editorContent?.clientWidth ?? DEFAULT_IMAGE_WIDTH) - 32\n return Math.max(MIN_IMAGE_WIDTH, Math.min(DEFAULT_IMAGE_WIDTH, availableWidth))\n }\n\n private async _getImageNaturalWidth(file: File) {\n return await new Promise<number | null>((resolve) => {\n const objectUrl = URL.createObjectURL(file)\n const image = new window.Image()\n\n image.onload = () => {\n const naturalWidth = image.naturalWidth\n URL.revokeObjectURL(objectUrl)\n resolve(Number.isFinite(naturalWidth) && naturalWidth > 0 ? naturalWidth : null)\n }\n\n image.onerror = () => {\n URL.revokeObjectURL(objectUrl)\n resolve(null)\n }\n\n image.src = objectUrl\n })\n }\n\n private _syncImageSelectionState() {\n const selection = this._getImageSelection()\n if (!selection) {\n this._selectedImage = null\n if (this._toolbarModeValue === 'slash') {\n this._hideImageToolbar()\n }\n return\n }\n\n const width = Number(selection.attrs.width)\n const align = String(selection.attrs.align || 'left')\n this._selectedImage = {\n pos: selection.pos,\n width: Number.isFinite(width) && width > 0 ? width : this._getImageMaxWidth(),\n align,\n }\n\n if (this._toolbarModeValue !== 'slash') {\n this._hideImageToolbar()\n return\n }\n\n const editor = this._editor\n const wrapperRect = this.shadowRoot?.querySelector('.editor-wrapper')?.getBoundingClientRect()\n if (!editor || !wrapperRect) { return }\n const coords = editor.view.coordsAtPos(selection.pos)\n const x = coords.left - wrapperRect.left + (coords.right - coords.left) / 2\n const y = coords.top - wrapperRect.top - 40\n this._showImageToolbar({ x, y })\n }\n\n private _clearSlashCommandText() {\n if (!this._editor || !this._slashCommandRange) { return }\n const { from, to } = this._slashCommandRange\n this._editor.chain().focus().deleteRange({ from, to }).run()\n this._hasSlashCommand = false\n this._slashCommandRange = null\n }\n\n private _checkSlashCommand() {\n if (!this._editor) { return }\n const { selection } = this._editor.state\n if (!selection.empty) {\n this._hasSlashCommand = false\n this._slashCommandRange = null\n return\n }\n\n const { $from } = selection as any\n const textBefore = $from.parent.textBetween(0, $from.parentOffset, ' ', ' ')\n const matched = /(?:^|\\s)(\\/\\S*)$/.exec(textBefore)\n\n if (!matched) {\n this._hasSlashCommand = false\n this._slashCommandRange = null\n return\n }\n\n const slashText = matched[1]\n this._hasSlashCommand = true\n this._slashCommandRange = {\n from: selection.from - slashText.length,\n to: selection.from,\n }\n }\n\n firstUpdated() {\n this._injectCustomStyles()\n queueMicrotask(() => {\n if (this.isConnected) {\n this._initEditor()\n }\n })\n }\n\n updated(changed: Map<string, unknown>) {\n if (changed.has('custom-styles')) {\n this._injectCustomStyles()\n }\n\n if (this._editor) {\n if (changed.has('content') || (changed.has('model-value') && this._useModelValue)) {\n const newContent = this._useModelValue ? this['model-value'] : this.content\n if (newContent !== this._editor.getHTML()) {\n this._editor.commands.setContent(newContent || '<p></p>')\n }\n }\n if (changed.has('readonly') || changed.has('preview')) {\n this._editor.setEditable(this._isEditable)\n }\n return\n }\n\n // 编辑器未初始化时,只保存待处理内容,不重复初始化\n if (changed.has('content')) {\n this._pendingContent = this.content\n }\n\n if (changed.has('model-value') && this._useModelValue) {\n this._pendingContent = this['model-value']\n }\n\n // 只有在 firstUpdated 时才会初始化编辑器\n // 这里不再重复调用 _initEditor()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this._editor?.destroy()\n this._editor = null\n }\n\n getContent(): string {\n return this._editor?.getHTML() ?? ''\n }\n\n forceUpdate(): void {\n this.requestUpdate()\n if (this._editor) {\n const newContent = this._useModelValue ? this['model-value'] : this.content\n if (newContent !== this._editor.getHTML()) {\n this._editor.commands.setContent(newContent || '<p></p>')\n }\n }\n }\n\n private _applyFormat(command: () => void) {\n this._clearSlashCommandText()\n command()\n }\n\n private _getSlashCommandContext() {\n const editor = this._editor\n const range = this._slashCommandRange\n if (!editor || !range) { return null }\n\n const $from = editor.state.doc.resolve(range.from)\n return {\n lineFrom: $from.start(),\n lineTo: range.from,\n }\n }\n\n private _applySlashLineMark(\n applyMark: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n clearMark: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n ) {\n const editor = this._editor\n const context = this._getSlashCommandContext()\n if (!editor || !context) { return false }\n\n this._clearSlashCommandText()\n\n if (context.lineFrom < context.lineTo) {\n applyMark(\n editor.chain().focus().setTextSelection({ from: context.lineFrom, to: context.lineTo }),\n ).run()\n }\n\n clearMark(\n editor.chain().focus().setTextSelection({ from: context.lineTo, to: context.lineTo }),\n ).run()\n return true\n }\n\n private _applyToolbarLineMark(\n applyMark: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n clearMark: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n ) {\n const editor = this._editor\n if (!editor) { return false }\n\n const { selection } = editor.state\n const range = selection.empty\n ? (() => {\n const $from = editor.state.doc.resolve(selection.from)\n return { from: $from.start(), to: $from.end() }\n })()\n : { from: selection.from, to: selection.to }\n\n if (range.from >= range.to) {\n return false\n }\n\n applyMark(\n editor.chain().focus().setTextSelection(range),\n ).run()\n\n clearMark(\n editor.chain().focus().setTextSelection({ from: range.to, to: range.to }),\n ).run()\n\n return true\n }\n\n private _applySlashLineBlock(\n applyBlock: (chain: ReturnType<Editor['chain']>) => ReturnType<Editor['chain']>,\n ) {\n const editor = this._editor\n const context = this._getSlashCommandContext()\n if (!editor || !context) { return false }\n\n this._clearSlashCommandText()\n applyBlock(\n editor.chain().focus().setTextSelection({ from: context.lineFrom, to: context.lineTo }),\n ).run()\n return true\n }\n\n private _toggleBold() {\n if (this._applySlashLineMark(chain => chain.setBold(), chain => chain.unsetBold())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleBold(), chain => chain.unsetBold())\n }\n\n private _toggleItalic() {\n if (this._applySlashLineMark(chain => chain.setItalic(), chain => chain.unsetItalic())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleItalic(), chain => chain.unsetItalic())\n }\n\n private _toggleUnderline() {\n if (this._applySlashLineMark(chain => chain.setUnderline(), chain => chain.unsetUnderline())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleUnderline(), chain => chain.unsetUnderline())\n }\n\n private _toggleStrike() {\n if (this._applySlashLineMark(chain => chain.setStrike(), chain => chain.unsetStrike())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleStrike(), chain => chain.unsetStrike())\n }\n\n private _toggleCode() {\n if (this._applySlashLineMark(chain => chain.setCode(), chain => chain.unsetCode())) {\n return\n }\n this._applyToolbarLineMark(chain => chain.toggleCode(), chain => chain.unsetCode())\n }\n\n private _setHeading(level: number) {\n if (this._applySlashLineBlock(chain => chain.setHeading({ level: level as 1 | 2 | 3 | 4 | 5 | 6 }))) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleHeading({ level: level as 1 | 2 | 3 | 4 | 5 | 6 }).run())\n }\n\n private _setParagraph() {\n if (this._applySlashLineBlock(chain => chain.setParagraph())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().setParagraph().run())\n }\n\n private _toggleBulletList() {\n if (this._applySlashLineBlock(chain => chain.toggleBulletList())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleBulletList().run())\n }\n\n private _toggleOrderedList() {\n if (this._applySlashLineBlock(chain => chain.toggleOrderedList())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleOrderedList().run())\n }\n\n private _toggleTaskList() {\n if (this._applySlashLineBlock(chain => chain.toggleTaskList())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleTaskList().run())\n }\n\n private _toggleBlockquote() {\n if (this._applySlashLineBlock(chain => chain.toggleBlockquote())) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().toggleBlockquote().run())\n }\n\n private _setTextAlign(align: string) {\n if (this._applySlashLineBlock(chain => chain.setTextAlign(align as any))) {\n return\n }\n this._applyFormat(() => this._editor?.chain().focus().setTextAlign(align as any).run())\n }\n\n private _normalizeLinkUrl(url: string) {\n const trimmed = url.trim()\n if (!trimmed) { return '' }\n if (/^(https?:\\/\\/|mailto:|tel:|#|\\/)/i.test(trimmed)) {\n return trimmed\n }\n return `https://${trimmed}`\n }\n\n private _getLinkLabelFromRange(range: { from: number, to: number } | null) {\n const editor = this._editor\n if (!editor || !range || range.from >= range.to) {\n return ''\n }\n return editor.state.doc.textBetween(range.from, range.to, '')\n }\n\n private _getLinkTargetRange() {\n const editor = this._editor\n if (!editor) { return null }\n\n const { selection } = editor.state\n if (!selection.empty) {\n return { from: selection.from, to: selection.to }\n }\n\n if (editor.isActive('link')) {\n editor.chain().focus().extendMarkRange('link').run()\n return {\n from: editor.state.selection.from,\n to: editor.state.selection.to,\n }\n }\n\n const $from = editor.state.doc.resolve(selection.from)\n return {\n from: $from.start(),\n to: $from.end(),\n }\n }\n\n private _setLink(event: MouseEvent) {\n const editor = this._editor\n const wrapper = this.shadowRoot?.querySelector<HTMLElement>('.editor-wrapper')\n const trigger = event.currentTarget instanceof HTMLElement ? event.currentTarget : null\n if (!editor || !wrapper || !trigger) { return }\n\n const linkRange = this._getLinkTargetRange()\n this._linkSelection = linkRange\n\n const wrapperRect = wrapper.getBoundingClientRect()\n const triggerRect = trigger.getBoundingClientRect()\n const maxLeft = Math.max(12, wrapperRect.width - 332)\n const left = Math.min(Math.max(12, triggerRect.left - wrapperRect.left), maxLeft)\n const top = triggerRect.bottom - wrapperRect.top + 8\n const currentHref = String(editor.getAttributes('link').href || '')\n const currentLabel = this._getLinkLabelFromRange(linkRange)\n\n this._linkEditor = {\n x: left,\n y: top,\n visible: true,\n url: currentHref,\n label: currentLabel,\n }\n\n this.updateComplete.then(() => {\n const input = this.shadowRoot?.querySelector<HTMLInputElement>('.link-editor__input[data-field=\"url\"]')\n input?.focus()\n input?.select()\n })\n }\n\n private _closeLinkEditor() {\n this._linkEditor = { ...this._linkEditor, visible: false }\n }\n\n private _handleLinkEditorInput(event: Event) {\n const target = event.target as HTMLInputElement\n const field = target.dataset.field === 'label' ? 'label' : 'url'\n this._linkEditor = {\n ...this._linkEditor,\n [field]: target.value,\n }\n }\n\n private _applyLink() {\n const editor = this._editor\n const href = this._normalizeLinkUrl(this._linkEditor.url)\n const label = this._linkEditor.label.trim() || href\n if (!editor || !href) { return }\n\n this._clearSlashCommandText()\n\n const selection = this._linkSelection ?? this._getLinkTargetRange() ?? editor.state.selection\n const insertTo = selection.from + label.length\n\n editor\n .chain()\n .focus()\n .insertContentAt(\n { from: selection.from, to: selection.to },\n {\n type: 'text',\n text: label,\n marks: [{ type: 'link', attrs: { href } }],\n },\n )\n .setTextSelection({ from: insertTo, to: insertTo })\n .run()\n\n this._closeLinkEditor()\n }\n\n private _removeLink() {\n const editor = this._editor\n if (!editor) { return }\n\n const selection = this._linkSelection ?? editor.state.selection\n let chain = editor.chain().focus()\n if (selection.from !== selection.to) {\n chain = chain.setTextSelection(selection)\n }\n chain.extendMarkRange('link').unsetLink().run()\n this._closeLinkEditor()\n }\n\n private _handleLinkEditorKeydown(event: KeyboardEvent) {\n if (event.key === 'Enter') {\n event.preventDefault()\n this._applyLink()\n return\n }\n if (event.key === 'Escape') {\n event.preventDefault()\n this._closeLinkEditor()\n }\n }\n\n private _insertTable(rows?: number, cols?: number) {\n this._editor?.chain().focus().insertTable({ rows: rows ?? this._tableRows, cols: cols ?? this._tableCols, withHeaderRow: true }).run()\n }\n\n private async _handleImageUpload(e: Event) {\n const input = e.target as HTMLInputElement\n const file = input.files?.[0]\n if (file) {\n try {\n const naturalWidth = await this._getImageNaturalWidth(file)\n const src = await this['upload-image'](file)\n const initialWidth = naturalWidth\n ? Math.min(naturalWidth, this._getImageMaxWidth())\n : this._getImageMaxWidth()\n\n this._clearSlashCommandText()\n const pendingInsertPos = this._pendingImageInsertPos\n this._pendingImageInsertPos = null\n\n if (pendingInsertPos !== null) {\n this._insertImageAt(pendingInsertPos, {\n src,\n width: initialWidth,\n align: 'left',\n })\n }\n else {\n this._editor?.chain().focus().setImage({\n src,\n width: initialWidth,\n align: 'left',\n }).run()\n }\n }\n catch (err) {\n console.error('图片上传失败:', err)\n }\n }\n input.value = ''\n }\n\n private _triggerImageUpload() {\n this._clearSlashCommandText()\n const input = this.shadowRoot?.querySelector<HTMLInputElement>('.image-input')\n input?.click()\n }\n\n private _insertTableByClick(rows: number, cols: number) {\n this._clearSlashCommandText()\n this._tableRows = rows\n this._tableCols = cols\n this._insertTable(rows, cols)\n }\n\n private _showTableCellToolbar() {\n if (!this._editor?.isActive('table')) { return }\n const { state } = this._editor\n const { selection } = state\n const coords = this._editor.view.coordsAtPos(selection.from)\n const editorWrapper = this.shadowRoot?.querySelector<HTMLElement>('.editor-wrapper')\n if (!editorWrapper) { return }\n const wrapperRect = editorWrapper.getBoundingClientRect()\n\n const cellRow = this._getTableCellRow()\n const cellCol = this._getTableCellCol()\n const isTopRow = cellRow === 0\n const isLeftCol = cellCol === 0\n\n // Only show toolbar on top row or left column\n if (!isTopRow && !isLeftCol) { return }\n\n requestAnimationFrame(() => {\n this._tableCellToolbar = {\n x: coords.left - wrapperRect.left,\n y: coords.bottom - wrapperRect.top + 8,\n visible: true,\n cellRow,\n cellCol,\n }\n })\n }\n\n private _getTableCellRow(): number {\n if (!this._editor) { return 0 }\n const { selection } = this._editor.state\n const $pos = this._editor.state.doc.resolve(selection.from)\n for (let d = $pos.depth; d > 0; d--) {\n const node = $pos.node(d)\n if (node.type.name === 'tableCell') {\n return $pos.index(d - 1)\n }\n }\n return 0\n }\n\n private _getTableCellCol(): number {\n if (!this._editor) { return 0 }\n const { selection } = this._editor.state\n const $pos = this._editor.state.doc.resolve(selection.from)\n for (let d = $pos.depth; d > 0; d--) {\n const node = $pos.node(d)\n if (node.type.name === 'tableCell') {\n return $pos.index(d)\n }\n }\n return 0\n }\n\n private _hideTableCellToolbar() {\n requestAnimationFrame(() => {\n this._tableCellToolbar = { ...this._tableCellToolbar, visible: false }\n })\n }\n\n private _addTableRowAbove() {\n this._editor?.chain().focus().addRowBefore().run()\n this._hideTableCellToolbar()\n }\n\n private _addTableRowBelow() {\n this._editor?.chain().focus().addRowAfter().run()\n this._hideTableCellToolbar()\n }\n\n private _addTableColumnLeft() {\n this._editor?.chain().focus().addColumnBefore().run()\n this._hideTableCellToolbar()\n }\n\n private _addTableColumnRight() {\n this._editor?.chain().focus().addColumnAfter().run()\n this._hideTableCellToolbar()\n }\n\n private _deleteTableRow() {\n this._editor?.chain().focus().deleteRow().run()\n this._hideTableCellToolbar()\n }\n\n private _deleteTableColumn() {\n this._editor?.chain().focus().deleteColumn().run()\n this._hideTableCellToolbar()\n }\n\n private _deleteTable() {\n this._editor?.chain().focus().deleteTable().run()\n this._hideTableCellToolbar()\n }\n\n // Image Toolbar Methods\n private _showImageToolbar(pos: { x: number, y: number }) {\n requestAnimationFrame(() => {\n this._imageToolbar = { x: pos.x, y: pos.y, visible: true }\n })\n }\n\n private _hideImageToolbar() {\n requestAnimationFrame(() => {\n this._imageToolbar = { ...this._imageToolbar, visible: false }\n })\n }\n\n private _deleteImage() {\n const selectedImage = this._getSelectedImageNode()\n if (!selectedImage) { return }\n\n const { editor, pos, node } = selectedImage\n editor.view.dispatch(editor.state.tr.delete(pos, pos + node.nodeSize))\n this._selectedImage = null\n this._pendingImageInsertPos = null\n this._hideImageToolbar()\n }\n\n private _insertImageAfter() {\n const selectedImage = this._getSelectedImageNode()\n if (!selectedImage) {\n this._triggerImageUpload()\n return\n }\n\n this._pendingImageInsertPos = selectedImage.pos + selectedImage.node.nodeSize\n this._triggerImageUpload()\n }\n\n private _getSelectedImageNode() {\n const editor = this._editor\n const pos = this._selectedImage?.pos\n if (!editor || pos === undefined) { return null }\n\n const node = editor.state.doc.nodeAt(pos)\n if (!node || node.type.name !== 'image') { return null }\n\n return { editor, pos, node }\n }\n\n private _insertImageAt(pos: number, attrs: Record<string, unknown>) {\n const editor = this._editor\n if (!editor) { return }\n\n const insertPos = Math.max(0, Math.min(pos, editor.state.doc.content.size))\n editor\n .chain()\n .insertContentAt(insertPos, { type: 'image', attrs })\n .setNodeSelection(insertPos)\n .run()\n }\n\n private _updateSelectedImageAttributes(attrs: Record<string, unknown>) {\n const selectedImage = this._getSelectedImageNode()\n if (!selectedImage) { return }\n\n const { editor, pos, node } = selectedImage\n editor.view.dispatch(editor.state.tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n ...attrs,\n }))\n }\n\n private _setImageWidth(width: number) {\n const nextWidth = Math.max(MIN_IMAGE_WIDTH, Math.min(this._getImageMaxWidth(), Math.round(width)))\n this._updateSelectedImageAttributes({ width: nextWidth })\n }\n\n private _handleImageWidthInput(e: Event) {\n const rawValue = (e.target as HTMLInputElement).value.trim()\n if (!rawValue) { return }\n\n const value = Number(rawValue)\n if (!Number.isFinite(value)) { return }\n this._setImageWidth(value)\n }\n\n private _setImageAlignLeft() {\n this._updateSelectedImageAttributes({ align: 'left' })\n }\n\n private _setImageAlignCenter() {\n this._updateSelectedImageAttributes({ align: 'center' })\n }\n\n private _setImageAlignRight() {\n this._updateSelectedImageAttributes({ align: 'right' })\n }\n\n private _getTextLabel(): string {\n const editor = this._editor\n if (!editor) { return '正文' }\n if (editor.isActive('heading', { level: 1 })) { return '标题 1' }\n if (editor.isActive('heading', { level: 2 })) { return '标题 2' }\n if (editor.isActive('heading', { level: 3 })) { return '标题 3' }\n return '正文'\n }\n\n private _getAlignLabel(): string {\n const editor = this._editor\n if (!editor) { return '对齐' }\n if (editor.isActive({ textAlign: 'center' })) { return '居中' }\n if (editor.isActive({ textAlign: 'right' })) { return '右对齐' }\n return '左对齐'\n }\n\n private _renderImageControls() {\n const selectedImage = this._selectedImage\n if (!selectedImage) { return '' }\n\n return html`\n <button class=\"bubble-btn danger\" title=\"删除图片\" @click=${this._deleteImage}>\n <svg viewBox=\"0 0 24 24\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/></svg>\n </button>\n <button class=\"bubble-btn\" title=\"添加图片\" @click=${this._insertImageAfter}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/></svg>\n </button>\n <div class=\"bubble-divider\"></div>\n <span class=\"image-control-label\">对齐</span>\n <button class=\"bubble-btn ${selectedImage.align === 'left' ? 'is-active' : ''}\" title=\"左对齐\" @click=${this._setImageAlignLeft}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"3\" y1=\"12\" x2=\"15\" y2=\"12\"/><line x1=\"3\" y1=\"18\" x2=\"18\" y2=\"18\"/></svg>\n </button>\n <button class=\"bubble-btn ${selectedImage.align === 'center' ? 'is-active' : ''}\" title=\"居中\" @click=${this._setImageAlignCenter}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"6\" y1=\"12\" x2=\"18\" y2=\"12\"/><line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\"/></svg>\n </button>\n <button class=\"bubble-btn ${selectedImage.align === 'right' ? 'is-active' : ''}\" title=\"右对齐\" @click=${this._setImageAlignRight}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"9\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"6\" y1=\"18\" x2=\"21\" y2=\"18\"/></svg>\n </button>\n <div class=\"image-size-control\">\n <span class=\"image-size-label\">宽度</span>\n <input\n class=\"image-size-range\"\n type=\"number\"\n min=\"${MIN_IMAGE_WIDTH}\"\n max=\"${this._getImageMaxWidth()}\"\n .value=${String(selectedImage.width)}\n @input=${this._handleImageWidthInput}\n />\n </div>\n `\n }\n\n private _joinToolbarGroups(groups: unknown[]) {\n return groups.flatMap((group, index) => index === 0\n ? [group]\n : [html`<div class=\"bubble-divider\"></div>`, group])\n }\n\n private _renderFormatToolbarGroup(editor: Editor | null) {\n return html`\n <button\n class=\"bubble-btn ${editor?.isActive('bold') ? 'is-active' : ''}\"\n @click=${this._toggleBold}\n title=\"加粗\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/></svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('italic') ? 'is-active' : ''}\"\n @click=${this._toggleItalic}\n title=\"斜体\"\n >\n <svg viewBox=\"0 0 24 24\"><line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/></svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('underline') ? 'is-active' : ''}\"\n @click=${this._toggleUnderline}\n title=\"下划线\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"/><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"/></svg>\n </button>\n <button\n class=\"bubble-btn ${editor?.isActive('strike') ? 'is-active' : ''}\"\n @click=${this._toggleStrike}\n title=\"删除线\"\n >\n <svg viewBox=\"0 0 24 24\"><path d=\"M17.3 4.9c-2.3-.6-4.4-1-6.2-.9-2.7 0-5.3.7-5.3 3.6 0 1.5 1.8 3.3 5.3 3.9h.2m8.2 3.2c.3.4.4.8.4 1.3 0 2.9-2.7 3.6-6.2 3.6-2.3 0-4.4-.3-6.2-.9M4 12h16\"/></svg>\n </button>\n `\n }\n\n private _renderHeadingToolbarGroup(editor: Editor | null) {\n return html`\n <div class=\"bubble-dropdown\">\n <button class=\"bubble-dropdown-btn\">\n ${this._getTextLabel()}\n <svg viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"/></svg>\n </button>\n <div class=\"bubble-dropdown-menu\">\n <button class=\"bubble-dropdown-item ${!editor?.isActive('heading') ? 'is-active' : ''}\" @click=${this._setParagraph}>正文</button>\n <button class=\"bubble-dropdown-item ${editor?.isActive('heading', { level: 1 }) ? 'is-active' : ''}\" @click=${() => this._setHeading(1)}>标题 1</button>\n <button class=\"bubble-dropdown-item ${editor?.isActive('heading', { level: 2 }) ? 'is-active' : ''}\" @click=${() => this._setHeading(2)}>标题 2</button>\n <button class=\"bubble-dropdown-item ${editor?.isActive('heading', { level: 3 }) ? 'is-active' : ''}\" @click=${() => this._setHeading(3)}>标题 3</button>\n </div>\n </div>\n `\n }\n\n private _renderAlignToolbarGroup(editor: Editor | null) {\n return html`\n <div class=\"bubble-dropdown\">\n <button class=\"bubble-dropdown-btn\">\n ${this._getAlignLabel()}\n <svg viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"/></svg>\n </button>\n <div class=\"bubble-dropdown-menu\">\n <button class=\"bubble-dropdown-item ${editor?.isActive({ textAlign: 'left' }) ? 'is-active' : ''}\" @click=${() => this._setTextAlign('left')}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"3\" y1=\"12\" x2=\"15\" y2=\"12\"/><line x1=\"3\" y1=\"18\" x2=\"18\" y2=\"18\"/></svg>\n 左对齐\n </button>\n <button class=\"bubble-dropdown-item ${editor?.isActive({ textAlign: 'center' }) ? 'is-active' : ''}\" @click=${() => this._setTextAlign('center')}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"6\" y1=\"12\" x2=\"18\" y2=\"12\"/><line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\"/></svg>\n 居中\n </button>\n <button class=\"bubble-dropdown-item ${editor?.isActive({ textAlign: 'right' }) ? 'is-active' : ''}\" @click=${() => this._setTextAlign('right')}>\n <svg viewBox=\"0 0 24 24\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"9\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"6\" y1=\"18\" x2=\"21\" y2=\"18\"/></svg>\n 右对齐\n </button>\n </div>\n </div>\n `\n }\n\n private _renderCodeLinkImageToolbarGroup(editor: Editor | null) {\n return html`\n ${this._hasToolbarItem('code')\n ? html`\n <button class=\"bubble-btn ${editor?.isActive('code') ? 'is-active' : ''}\" @click=${this._toggleCode} title=\"行内代码\">\n <svg viewBox=\"0 0 24 24\"><polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/></svg>\n </button>\n `\n : ''}\n ${this._hasToolbarItem('link')\n ? html`\n <button class=\"bubble-btn ${editor?.isActive('link') ? 'is-active' : ''}\" @click=${this._setLink} title=\"链接\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>\n </button>\n `\n : ''}\n ${this._hasToolbarItem('image')\n ? html`\n <button class=\"bubble-btn\" @click=${this._triggerImageUpload} title=\"图片\">\n <svg viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/></svg>\n </button>\n `\n : ''}\n `\n }\n\n private _renderListToolbarGroup(editor: Editor | null) {\n return html`\n <button class=\"bubble-btn ${editor?.isActive('bulletList') ? 'is-active' : ''}\" @click=${this._toggleBulletList} title=\"无序列表\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"9\" y1=\"6\" x2=\"20\" y2=\"6\"/>\n <line x1=\"9\" y1=\"12\" x2=\"20\" y2=\"12\"/>\n <line x1=\"9\" y1=\"18\" x2=\"20\" y2=\"18\"/>\n <circle cx=\"4\" cy=\"6\" r=\"0.5\" fill=\"currentColor\" stroke=\"none\"/>\n <circle cx=\"4\" cy=\"12\" r=\"0.5\" fill=\"currentColor\" stroke=\"none\"/>\n <circle cx=\"4\" cy=\"18\" r=\"0.5\" fill=\"currentColor\" stroke=\"none\"/>\n </svg>\n </button>\n <button class=\"bubble-btn ${editor?.isActive('orderedList') ? 'is-active' : ''}\" @click=${this._toggleOrderedList} title=\"有序列表\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\"/>\n <line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\"/>\n <line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\"/>\n <path d=\"M4 6h1v4\"/>\n <path d=\"M4 10h2\"/>\n <path d=\"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1.5\"/>\n </svg>\n </button>\n <button class=\"bubble-btn ${editor?.isActive('taskList') ? 'is-active' : ''}\" @click=${this._toggleTaskList} title=\"待办列表\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"3\" y=\"5\" width=\"4\" height=\"4\" rx=\"1\"/>\n <polyline points=\"4 7 5 8 6.5 6.5\"/>\n <line x1=\"10\" y1=\"7\" x2=\"21\" y2=\"7\"/>\n <rect x=\"3\" y=\"15\" width=\"4\" height=\"4\" rx=\"1\"/>\n <line x1=\"10\" y1=\"17\" x2=\"21\" y2=\"17\"/>\n </svg>\n </button>\n `\n }\n\n private _renderBlockquoteToolbarGroup(editor: Editor | null) {\n return html`\n <button class=\"bubble-btn ${editor?.isActive('blockquote') ? 'is-active' : ''}\" @click=${this._toggleBlockquote} title=\"引用\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V21z\"/><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\"/></svg>\n </button>\n `\n }\n\n private _renderTableToolbarGroup() {\n return html`\n <div\n class=\"bubble-dropdown ${this._tableDropdownOpen ? 'is-open' : ''}\"\n @mouseenter=${() => {\n this._tableDropdownOpen = true\n this._hoverRow = 0\n this._hoverCol = 0\n }}\n @mouseleave=${() => this._tableDropdownOpen = false}\n >\n <button class=\"bubble-dropdown-btn\" title=\"表格\">\n <svg viewBox=\"0 0 24 24\" style=\"width:18px;height:18px;stroke:currentColor;stroke-width:2;fill:none;\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/></svg>\n </button>\n <div class=\"bubble-dropdown-menu\">\n <div class=\"table-grid-preview\">\n ${this._renderTableGrid()}\n </div>\n <div class=\"table-size-hint\">\n <span>${this._hoverRow > 0 ? `${this._hoverRow} × ${this._hoverCol}` : `${this._tableRows} × ${this._tableCols}`}</span>\n </div>\n </div>\n </div>\n `\n }\n\n private _renderTextToolbar(editor: Editor | null) {\n const groups: unknown[] = []\n\n if (this._hasToolbarItem('format')) {\n groups.push(this._renderFormatToolbarGroup(editor))\n }\n if (this._hasToolbarItem('heading')) {\n groups.push(this._renderHeadingToolbarGroup(editor))\n }\n if (this._hasToolbarItem('align')) {\n groups.push(this._renderAlignToolbarGroup(editor))\n }\n if (this._hasToolbarItem('code') || this._hasToolbarItem('link') || this._hasToolbarItem('image')) {\n groups.push(this._renderCodeLinkImageToolbarGroup(editor))\n }\n if (this._hasToolbarItem('list')) {\n groups.push(this._renderListToolbarGroup(editor))\n }\n if (this._hasToolbarItem('blockquote')) {\n groups.push(this._renderBlockquoteToolbarGroup(editor))\n }\n if (this._hasToolbarItem('table')) {\n groups.push(this._renderTableToolbarGroup())\n }\n\n return this._joinToolbarGroups(groups)\n }\n\n private _updateBubbleMenuPosition() {\n if (this._toolbarModeValue !== 'slash') { return }\n requestAnimationFrame(() => {\n const bubbleMenu = this.shadowRoot?.querySelector<HTMLElement>('.bubble-menu')\n const proseMirror = this.shadowRoot?.querySelector<HTMLElement>('.ProseMirror')\n const editorWrapper = this.shadowRoot?.querySelector<HTMLElement>('.editor-wrapper')\n if (!bubbleMenu || !proseMirror || !editorWrapper) { return }\n\n const editor = this._editor\n const isInTable = editor?.isActive('table') ?? false\n const { selection } = editor?.state ?? { selection: null }\n\n // 如果选中了表格节点(而不只是单元格内的文字),隐藏菜单\n if (isInTable && selection && !selection.empty && editor) {\n const { from, to } = selection\n const $from = editor.state.doc.resolve(from)\n const $to = editor.state.doc.resolve(to)\n // 检查选区起点和终点之间是否有表格节点\n let hasTableInSelection = false\n for (let d = $from.depth; d >= 0; d--) {\n if ($from.node(d).type.name === 'table') {\n hasTableInSelection = true\n break\n }\n }\n // 如果选区起点在表格外但终点在表格内,或者选区跨越了表格\n const fromAncestor = $from.node($from.depth)\n const toAncestor = $to.node($to.depth)\n if (fromAncestor.type.name === 'table' || toAncestor.type.name === 'table') {\n hasTableInSelection = true\n }\n if (hasTableInSelection) {\n bubbleMenu.style.opacity = '0'\n bubbleMenu.style.visibility = 'hidden'\n return\n }\n }\n\n // 如果有选中文字,显示菜单\n if (selection && !selection.empty) {\n // continue to show menu\n }\n else if (!selection || (selection.empty && !this._hasSlashCommand)) {\n bubbleMenu.style.opacity = '0'\n bubbleMenu.style.visibility = 'hidden'\n return\n }\n\n const wrapperRect = editorWrapper.getBoundingClientRect()\n const menuRect = bubbleMenu.getBoundingClientRect()\n\n const { from } = selection!\n const coords = this._editor?.view.coordsAtPos(from)\n if (!coords) { return }\n\n let left = coords.left - wrapperRect.left\n let top = coords.top - wrapperRect.top - 40\n\n if (left + menuRect.width > wrapperRect.width) {\n left = wrapperRect.width - menuRect.width - 8\n }\n if (left < 0) {\n left = 8\n }\n\n if (top < 0) {\n top = coords.bottom - wrapperRect.top + 8\n }\n\n bubbleMenu.style.left = `${left}px`\n bubbleMenu.style.top = `${top}px`\n bubbleMenu.style.opacity = '1'\n bubbleMenu.style.visibility = 'visible'\n })\n }\n\n render() {\n const editor = this._editor\n\n return html`\n <div\n class=\"editor-wrapper ${!editor ? 'loading' : ''} ${this._previewValue ? 'preview' : ''}\"\n @mousedown=${this._handleWrapperMouseDown}\n @focusin=${this._handleWrapperFocusIn}\n @focusout=${this._handleWrapperFocusOut}\n >\n ${!editor\n ? html`\n <div class=\"loading-placeholder\">\n <div class=\"loading-spinner\"></div>\n <span>编辑器加载中...</span>\n </div>\n `\n : ''}\n <input\n type=\"file\"\n accept=\"image/*\"\n class=\"image-input\"\n @change=${this._handleImageUpload}\n />\n\n ${!this._previewValue && this._toolbarModeValue === 'header'\n ? html`\n <div class=\"editor-header ${this._isHeaderVisible() ? 'is-visible' : ''}\">\n <div class=\"editor-header__inner\">\n ${this._selectedImage\n ? this._renderImageControls()\n : this._renderTextToolbar(editor)}\n </div>\n </div>\n `\n : ''}\n\n <!-- Bubble Menu (悬浮操作栏) -->\n ${!this._previewValue && this._toolbarModeValue === 'slash'\n ? html`\n <div class=\"bubble-menu\">\n ${this._renderTextToolbar(editor)}\n </div>\n `\n : ''}\n\n <div class=\"editor-content\" data-empty-hint=${this._resolvedPlaceholder}></div>\n\n ${this._linkEditor.visible\n ? html`\n <div\n class=\"link-editor\"\n style=\"left: ${this._linkEditor.x}px; top: ${this._linkEditor.y}px;\"\n @mousedown=${(event: MouseEvent) => event.stopPropagation()}\n @click=${(event: MouseEvent) => event.stopPropagation()}\n >\n <div class=\"link-editor__field\">\n <span class=\"link-editor__label\">链接地址</span>\n <input\n class=\"link-editor__input\"\n data-field=\"url\"\n type=\"text\"\n placeholder=\"输入或粘贴链接\"\n .value=${this._linkEditor.url}\n @input=${this._handleLinkEditorInput}\n @keydown=${this._handleLinkEditorKeydown}\n />\n </div>\n <div class=\"link-editor__field\">\n <span class=\"link-editor__label\">链接名字</span>\n <input\n class=\"link-editor__input\"\n data-field=\"label\"\n type=\"text\"\n placeholder=\"输入展示名称\"\n .value=${this._linkEditor.label}\n @input=${this._handleLinkEditorInput}\n @keydown=${this._handleLinkEditorKeydown}\n />\n </div>\n <div class=\"link-editor__actions\">\n <button class=\"link-editor__action primary\" title=\"应用链接\" @click=${this._applyLink}>应用</button>\n <button class=\"link-editor__action\" title=\"取消链接编辑\" @click=${this._closeLinkEditor}>取消</button>\n ${(editor?.isActive('link') || this._linkEditor.url)\n ? html`<button class=\"link-editor__action danger\" title=\"移除链接\" @click=${this._removeLink}>移除</button>`\n : ''}\n </div>\n </div>\n `\n : ''}\n\n <!-- Table Cell Toolbar -->\n ${this._tableCellToolbar.visible && editor?.isActive('table')\n ? html`\n <div\n class=\"table-cell-toolbar\"\n style=\"left: ${this._tableCellToolbar.x}px; top: ${this._tableCellToolbar.y}px;\"\n @mousedown=${(e: Event) => e.preventDefault()}\n >\n ${this._tableCellToolbar.cellRow === 0\n ? html`\n <button class=\"table-cell-toolbar-btn\" title=\"上方添加行\" @click=${this._addTableRowAbove}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"7\"/><line x1=\"10\" y1=\"5\" x2=\"14\" y2=\"5\"/></svg>\n </button>\n <button class=\"table-cell-toolbar-btn\" title=\"下方添加行\" @click=${this._addTableRowBelow}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"17\"/><line x1=\"10\" y1=\"19\" x2=\"14\" y2=\"19\"/></svg>\n </button>\n <button class=\"table-cell-toolbar-btn danger\" title=\"删除行\" @click=${this._deleteTableRow}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"8\" rx=\"1\"/><line x1=\"9\" y1=\"10\" x2=\"9\" y2=\"14\"/><line x1=\"15\" y1=\"10\" x2=\"15\" y2=\"14\"/></svg>\n </button>\n `\n : ''}\n ${this._tableCellToolbar.cellCol === 0\n ? html`\n ${this._tableCellToolbar.cellRow !== 0 ? html`<div style=\"width:1px;height:20px;background:#e3e3e3;margin:0 4px;\"></div>` : ''}\n <button class=\"table-cell-toolbar-btn\" title=\"左侧添加列\" @click=${this._addTableColumnLeft}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"8\" y=\"4\" width=\"8\" height=\"16\" rx=\"1\"/><line x1=\"3\" y1=\"12\" x2=\"7\" y2=\"12\"/><line x1=\"5\" y1=\"10\" x2=\"5\" y2=\"14\"/></svg>\n </button>\n <button class=\"table-cell-toolbar-btn\" title=\"右侧添加列\" @click=${this._addTableColumnRight}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"8\" y=\"4\" width=\"8\" height=\"16\" rx=\"1\"/><line x1=\"21\" y1=\"12\" x2=\"17\" y2=\"12\"/><line x1=\"19\" y1=\"10\" x2=\"19\" y2=\"14\"/></svg>\n </button>\n <button class=\"table-cell-toolbar-btn danger\" title=\"删除列\" @click=${this._deleteTableColumn}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><rect x=\"8\" y=\"4\" width=\"8\" height=\"16\" rx=\"1\"/><line x1=\"10\" y1=\"9\" x2=\"14\" y2=\"9\"/><line x1=\"10\" y1=\"15\" x2=\"14\" y2=\"15\"/></svg>\n </button>\n `\n : ''}\n ${this._tableCellToolbar.cellRow === 0 && this._tableCellToolbar.cellCol === 0\n ? html`\n <div style=\"width:1px;height:20px;background:#e3e3e3;margin:0 4px;\"></div>\n <button class=\"table-cell-toolbar-btn danger\" title=\"删除表格\" @click=${this._deleteTable}>\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/></svg>\n </button>\n `\n : ''}\n </div>\n `\n : ''}\n\n <!-- Image Toolbar -->\n ${this._toolbarModeValue === 'slash' && this._imageToolbar.visible\n ? html`\n <div\n class=\"image-toolbar\"\n style=\"left: ${this._imageToolbar.x}px; top: ${this._imageToolbar.y}px;\"\n @mousedown=${(e: Event) => e.preventDefault()}\n >\n ${this._renderImageControls()}\n </div>\n `\n : ''}\n </div>\n `\n }\n\n private _renderTableGrid() {\n const cells = []\n for (let i = 0; i < 100; i++) {\n const row = Math.floor(i / 10) + 1\n const col = (i % 10) + 1\n const isHighlight = this._hoverRow > 0 && row <= this._hoverRow && col <= this._hoverCol\n cells.push(html`\n <div\n class=\"table-cell ${isHighlight ? 'selected' : ''}\"\n @click=${() => {\n this._insertTableByClick(row, col)\n this._tableDropdownOpen = false\n }}\n @mouseenter=${() => {\n this._hoverRow = row\n this._hoverCol = col\n }}\n @mouseleave=${() => {\n this._hoverRow = 0\n this._hoverCol = 0\n }}\n ></div>\n `)\n }\n return cells\n }\n}\n\nexport function register() {}\n"],"names":["DEFAULT_HEADER_PLACEHOLDER","DEFAULT_SLASH_PLACEHOLDER","TaskList","TiptapNode","create","name","group","content","defining","parseHTML","tag","renderHTML","_ref","HTMLAttributes","mergeAttributes","addCommands","toggleTaskList","_ref2","commands","toggleList","this","TaskItem","addAttributes","checked","default","element","getAttribute","String","Boolean","attributes","_ref3","contenteditable","type","addKeyboardShortcuts","Enter","editor","splitListItem","Tab","sinkListItem","Shift-Tab","liftListItem","ExtendedImage","Image","extend","parent","width","attr","value","Number","isFinite","align","_ref4","style","filter","join","options","QxsBlocksuiteEditor","LitElement","constructor","super","arguments","placeholder","toolbar","DEFAULT_EDITOR_TOOLBAR","readonly","preview","_injectedStyleEl","async","Promise","resolve","reject","reader","FileReader","onload","e","target","result","onerror","readAsDataURL","file","_editor","_pendingContent","_tableRows","_tableCols","_hoverRow","_hoverCol","_tableDropdownOpen","_tableCellToolbar","x","y","visible","cellRow","cellCol","_imageToolbar","_linkEditor","url","label","_isEditorFocused","_selectedImage","_hasSlashCommand","_slashCommandRange","_isUpdating","_pendingImageInsertPos","_linkSelection","_preserveFocusOnInternalClick","_tableEdgeDetectionSetup","_injectCustomStyles","shadow","shadowRoot","remove","styleEl","document","createElement","textContent","appendChild","_useModelValue","hasAttribute","_readonlyValue","_previewValue","_isEditable","_toolbarModeValue","_headerAlwaysVisibleValue","_resolvedPlaceholder","_toolbarItemsValue","parseEditorToolbarItems","_hasToolbarItem","item","includes","_initEditor","el","querySelector","requestAnimationFrame","firstChild","removeChild","useModel","modelValue","contentValue","initialContent","extensions","Document","Paragraph","Text","Bold","Italic","Underline","Strike","Code","Heading","configure","levels","BulletList","OrderedList","ListItem","Blockquote","HorizontalRule","History","inline","allowBase64","Link","inclusive","openOnClick","rel","TextAlign","types","Table","resizable","TableRow","TableCell","TableHeader","Placeholder","Editor","editable","on","_updateBubbleMenuPosition","isActive","_showTableCellToolbar","_hideTableCellToolbar","_syncImageSelectionState","_checkSlashCommand","_setupTableEdgeDetection","_emitContentChange","_toggleTaskItemChecked","event","HTMLInputElement","taskItem","closest","preventDefault","stopPropagation","basePos","view","posAtDOM","searchFrom","Math","max","searchTo","min","state","doc","size","taskItemPos","nodesBetween","node","pos","nodeAt","dispatch","tr","setNodeMarkup","attrs","html","getHTML","dispatchEvent","CustomEvent","detail","bubbles","composed","editorContent","editorWrapper","handleEditorClick","Element","chain","focus","run","addEventListener","_handleWrapperFocusIn","_handleWrapperMouseDown","_handleWrapperFocusOut","nextTarget","relatedTarget","wrapper","contains","_closeLinkEditor","_isHeaderVisible","_getImageSelection","selection","from","_getImageMaxWidth","availableWidth","clientWidth","_getImageNaturalWidth","objectUrl","URL","createObjectURL","image","window","naturalWidth","revokeObjectURL","src","_hideImageToolbar","wrapperRect","getBoundingClientRect","coords","coordsAtPos","left","right","top","_showImageToolbar","_clearSlashCommandText","to","deleteRange","empty","$from","textBefore","textBetween","parentOffset","matched","exec","slashText","length","firstUpdated","queueMicrotask","isConnected","updated","changed","has","newContent","setContent","setEditable","disconnectedCallback","destroy","getContent","forceUpdate","requestUpdate","_applyFormat","command","_getSlashCommandContext","range","lineFrom","start","lineTo","_applySlashLineMark","applyMark","clearMark","context","setTextSelection","_applyToolbarLineMark","end","_applySlashLineBlock","applyBlock","_toggleBold","setBold","unsetBold","toggleBold","_toggleItalic","setItalic","unsetItalic","toggleItalic","_toggleUnderline","setUnderline","unsetUnderline","toggleUnderline","_toggleStrike","setStrike","unsetStrike","toggleStrike","_toggleCode","setCode","unsetCode","toggleCode","_setHeading","level","setHeading","toggleHeading","_setParagraph","setParagraph","_toggleBulletList","toggleBulletList","_toggleOrderedList","toggleOrderedList","_toggleTaskList","_toggleBlockquote","toggleBlockquote","_setTextAlign","setTextAlign","_normalizeLinkUrl","trimmed","trim","test","_getLinkLabelFromRange","_getLinkTargetRange","extendMarkRange","_setLink","trigger","currentTarget","HTMLElement","linkRange","triggerRect","maxLeft","bottom","currentHref","getAttributes","href","currentLabel","updateComplete","then","input","select","_handleLinkEditorInput","field","dataset","_applyLink","insertTo","insertContentAt","text","marks","_removeLink","unsetLink","_handleLinkEditorKeydown","key","_insertTable","rows","cols","insertTable","withHeaderRow","_handleImageUpload","files","initialWidth","pendingInsertPos","_insertImageAt","setImage","err","_triggerImageUpload","click","_insertTableByClick","_getTableCellRow","_getTableCellCol","$pos","d","depth","index","_addTableRowAbove","addRowBefore","_addTableRowBelow","addRowAfter","_addTableColumnLeft","addColumnBefore","_addTableColumnRight","addColumnAfter","_deleteTableRow","deleteRow","_deleteTableColumn","deleteColumn","_deleteTable","deleteTable","_deleteImage","selectedImage","_getSelectedImageNode","delete","nodeSize","_insertImageAfter","insertPos","setNodeSelection","_updateSelectedImageAttributes","_setImageWidth","nextWidth","round","_handleImageWidthInput","rawValue","_setImageAlignLeft","_setImageAlignCenter","_setImageAlignRight","_getTextLabel","_getAlignLabel","textAlign","_renderImageControls","_joinToolbarGroups","groups","flatMap","_renderFormatToolbarGroup","_renderHeadingToolbarGroup","_renderAlignToolbarGroup","_renderCodeLinkImageToolbarGroup","_renderListToolbarGroup","_renderBlockquoteToolbarGroup","_renderTableToolbarGroup","_renderTableGrid","_renderTextToolbar","push","bubbleMenu","proseMirror","isInTable","$to","hasTableInSelection","fromAncestor","toAncestor","opacity","visibility","menuRect","render","cells","i","row","floor","col","isHighlight","styles","css","__decorateClass","property","attribute","prototype","Object","safeCustomElement"],"mappings":"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"}