@meta-1/editor 0.0.29 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +52 -67
- package/src/components/notion-like/notion-like-editor-toolbar-floating.tsx +181 -0
- package/src/components/tiptap-extension/list-normalization-extension.ts +112 -0
- package/src/components/tiptap-extension/node-alignment-extension.ts +285 -0
- package/src/components/tiptap-extension/node-background-extension.ts +150 -0
- package/src/components/tiptap-extension/ui-state-extension.ts +97 -0
- package/src/components/tiptap-icons/add-col-left-icon.tsx +30 -0
- package/src/components/tiptap-icons/add-col-right-icon.tsx +30 -0
- package/src/components/tiptap-icons/add-row-bottom-icon.tsx +30 -0
- package/src/components/tiptap-icons/add-row-top-icon.tsx +30 -0
- package/src/components/tiptap-icons/ai-sparkles-icon.tsx +32 -0
- package/src/components/tiptap-icons/align-bottom-icon.tsx +28 -0
- package/src/components/tiptap-icons/align-center-icon.tsx +38 -0
- package/src/components/tiptap-icons/align-center-vertical-icon.tsx +34 -0
- package/src/components/tiptap-icons/align-end-vertical-icon.tsx +34 -0
- package/src/components/tiptap-icons/align-justify-icon.tsx +38 -0
- package/src/components/tiptap-icons/align-left-icon.tsx +38 -0
- package/src/components/tiptap-icons/align-middle-icon.tsx +55 -0
- package/src/components/tiptap-icons/align-right-icon.tsx +38 -0
- package/src/components/tiptap-icons/align-start-vertical-icon.tsx +32 -0
- package/src/components/tiptap-icons/align-top-icon.tsx +28 -0
- package/src/components/tiptap-icons/alignment-icon.tsx +72 -0
- package/src/components/tiptap-icons/arrow-down-a-z-icon.tsx +34 -0
- package/src/components/tiptap-icons/arrow-down-icon.tsx +24 -0
- package/src/components/tiptap-icons/arrow-down-to-line-icon.tsx +28 -0
- package/src/components/tiptap-icons/arrow-down-z-a-icon.tsx +34 -0
- package/src/components/tiptap-icons/arrow-left-icon.tsx +24 -0
- package/src/components/tiptap-icons/arrow-right-icon.tsx +26 -0
- package/src/components/tiptap-icons/arrow-up-icon.tsx +26 -0
- package/src/components/tiptap-icons/at-sign-icon.tsx +26 -0
- package/src/components/tiptap-icons/ban-icon.tsx +26 -0
- package/src/components/tiptap-icons/blockquote-icon.tsx +44 -0
- package/src/components/tiptap-icons/bold-icon.tsx +26 -0
- package/src/components/tiptap-icons/check-ai-icon.tsx +32 -0
- package/src/components/tiptap-icons/check-icon.tsx +26 -0
- package/src/components/tiptap-icons/chevron-down-icon.tsx +26 -0
- package/src/components/tiptap-icons/chevron-right-icon.tsx +26 -0
- package/src/components/tiptap-icons/clipboard-icon.tsx +24 -0
- package/src/components/tiptap-icons/close-icon.tsx +24 -0
- package/src/components/tiptap-icons/code-block-icon.tsx +38 -0
- package/src/components/tiptap-icons/code2-icon.tsx +32 -0
- package/src/components/tiptap-icons/complete-sentence-icon.tsx +44 -0
- package/src/components/tiptap-icons/copy-icon.tsx +32 -0
- package/src/components/tiptap-icons/corner-down-left-icon.tsx +26 -0
- package/src/components/tiptap-icons/external-link-icon.tsx +28 -0
- package/src/components/tiptap-icons/grip-4-icon.tsx +24 -0
- package/src/components/tiptap-icons/grip-vertical-icon.tsx +44 -0
- package/src/components/tiptap-icons/heading-five-icon.tsx +28 -0
- package/src/components/tiptap-icons/heading-four-icon.tsx +28 -0
- package/src/components/tiptap-icons/heading-one-icon.tsx +28 -0
- package/src/components/tiptap-icons/heading-six-icon.tsx +30 -0
- package/src/components/tiptap-icons/heading-three-icon.tsx +36 -0
- package/src/components/tiptap-icons/heading-two-icon.tsx +28 -0
- package/src/components/tiptap-icons/highlighter-icon.tsx +26 -0
- package/src/components/tiptap-icons/image-caption-icon.tsx +38 -0
- package/src/components/tiptap-icons/image-icon.tsx +26 -0
- package/src/components/tiptap-icons/image-plus-icon.tsx +26 -0
- package/src/components/tiptap-icons/italic-icon.tsx +24 -0
- package/src/components/tiptap-icons/languages-icon.tsx +34 -0
- package/src/components/tiptap-icons/link-icon.tsx +28 -0
- package/src/components/tiptap-icons/list-icon.tsx +56 -0
- package/src/components/tiptap-icons/list-ordered-icon.tsx +56 -0
- package/src/components/tiptap-icons/list-todo-icon.tsx +50 -0
- package/src/components/tiptap-icons/message-square-icon.tsx +26 -0
- package/src/components/tiptap-icons/message-square-plus-icon.tsx +32 -0
- package/src/components/tiptap-icons/mic-ai-icon.tsx +34 -0
- package/src/components/tiptap-icons/minus-icon.tsx +26 -0
- package/src/components/tiptap-icons/moon-star-icon.tsx +30 -0
- package/src/components/tiptap-icons/more-vertical-icon.tsx +38 -0
- package/src/components/tiptap-icons/move-horizontal-icon.tsx +24 -0
- package/src/components/tiptap-icons/paint-bucket-icon.tsx +32 -0
- package/src/components/tiptap-icons/plus-icon.tsx +24 -0
- package/src/components/tiptap-icons/plus-small-icon.tsx +24 -0
- package/src/components/tiptap-icons/redo2-icon.tsx +26 -0
- package/src/components/tiptap-icons/refresh-ai-icon.tsx +34 -0
- package/src/components/tiptap-icons/refresh-ccw-icon.tsx +28 -0
- package/src/components/tiptap-icons/repeat-2-icon.tsx +26 -0
- package/src/components/tiptap-icons/rotate-ccw-icon.tsx +24 -0
- package/src/components/tiptap-icons/simplify-2-icon.tsx +24 -0
- package/src/components/tiptap-icons/smile-ai-icon.tsx +38 -0
- package/src/components/tiptap-icons/smile-plus-icon.tsx +26 -0
- package/src/components/tiptap-icons/square-x-icon.tsx +26 -0
- package/src/components/tiptap-icons/stop-circle-2-icon.tsx +26 -0
- package/src/components/tiptap-icons/strike-icon.tsx +28 -0
- package/src/components/tiptap-icons/subscript-icon.tsx +38 -0
- package/src/components/tiptap-icons/summarize-text-icon.tsx +36 -0
- package/src/components/tiptap-icons/sun-icon.tsx +58 -0
- package/src/components/tiptap-icons/superscript-icon.tsx +38 -0
- package/src/components/tiptap-icons/table-cell-merge-icon.tsx +44 -0
- package/src/components/tiptap-icons/table-cell-split-icon.tsx +44 -0
- package/src/components/tiptap-icons/table-column-icon.tsx +26 -0
- package/src/components/tiptap-icons/table-header-column-icon.tsx +28 -0
- package/src/components/tiptap-icons/table-header-row-icon.tsx +26 -0
- package/src/components/tiptap-icons/table-icon.tsx +26 -0
- package/src/components/tiptap-icons/table-row-icon.tsx +26 -0
- package/src/components/tiptap-icons/text-color-small-icon.tsx +26 -0
- package/src/components/tiptap-icons/text-extend-icon.tsx +36 -0
- package/src/components/tiptap-icons/text-reduce-icon.tsx +32 -0
- package/src/components/tiptap-icons/trash-icon.tsx +26 -0
- package/src/components/tiptap-icons/type-icon.tsx +24 -0
- package/src/components/tiptap-icons/underline-icon.tsx +26 -0
- package/src/components/tiptap-icons/undo2-icon.tsx +26 -0
- package/src/components/tiptap-icons/x-icon.tsx +24 -0
- package/src/components/tiptap-node/blockquote-node/blockquote-node.css +18 -0
- package/src/components/tiptap-node/code-block-node/code-block-node.css +24 -0
- package/src/components/tiptap-node/heading-node/heading-node.css +33 -0
- package/src/components/tiptap-node/horizontal-rule-node/horizontal-rule-node-extension.ts +11 -0
- package/src/components/tiptap-node/horizontal-rule-node/horizontal-rule-node.css +12 -0
- package/src/components/tiptap-node/image-node/image-node-extension.ts +169 -0
- package/src/components/tiptap-node/image-node/image-node-floating.tsx +41 -0
- package/src/components/tiptap-node/image-node/image-node-view.css +60 -0
- package/src/components/tiptap-node/image-node/image-node-view.tsx +316 -0
- package/src/components/tiptap-node/image-node/image-node.css +28 -0
- package/src/components/tiptap-node/image-upload-node/image-upload-node-extension.ts +155 -0
- package/src/components/tiptap-node/image-upload-node/image-upload-node.css +141 -0
- package/src/components/tiptap-node/image-upload-node/image-upload-node.tsx +513 -0
- package/src/components/tiptap-node/image-upload-node/index.tsx +1 -0
- package/src/components/tiptap-node/list-node/list-node.css +127 -0
- package/src/components/tiptap-node/paragraph-node/paragraph-node.css +198 -0
- package/src/components/tiptap-node/table-node/extensions/table-handle/helpers/create-image.ts +273 -0
- package/src/components/tiptap-node/table-node/extensions/table-handle/index.ts +2 -0
- package/src/components/tiptap-node/table-node/extensions/table-handle/table-handle-plugin.ts +718 -0
- package/src/components/tiptap-node/table-node/extensions/table-handle/table-handle.ts +48 -0
- package/src/components/tiptap-node/table-node/extensions/table-node-extension.ts +226 -0
- package/src/components/tiptap-node/table-node/hooks/use-table-handle-state.ts +66 -0
- package/src/components/tiptap-node/table-node/lib/tiptap-table-utils.ts +1289 -0
- package/src/components/tiptap-node/table-node/styles/prosemirror-table.css +35 -0
- package/src/components/tiptap-node/table-node/styles/table-node.css +158 -0
- package/src/components/tiptap-node/table-node/ui/table-add-row-column-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-add-row-column-button/table-add-row-column-button.tsx +94 -0
- package/src/components/tiptap-node/table-node/ui/table-add-row-column-button/use-table-add-row-column.ts +325 -0
- package/src/components/tiptap-node/table-node/ui/table-align-cell-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-align-cell-button/table-align-cell-button.tsx +129 -0
- package/src/components/tiptap-node/table-node/ui/table-align-cell-button/use-table-align-cell.ts +528 -0
- package/src/components/tiptap-node/table-node/ui/table-alignment-menu/index.tsx +1 -0
- package/src/components/tiptap-node/table-node/ui/table-alignment-menu/table-alignment-menu.tsx +154 -0
- package/src/components/tiptap-node/table-node/ui/table-cell-handle-menu/index.tsx +1 -0
- package/src/components/tiptap-node/table-node/ui/table-cell-handle-menu/table-cell-handle-menu.css +62 -0
- package/src/components/tiptap-node/table-node/ui/table-cell-handle-menu/table-cell-handle-menu.tsx +212 -0
- package/src/components/tiptap-node/table-node/ui/table-clear-row-column-content-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-clear-row-column-content-button/table-clear-row-column-content-button.tsx +101 -0
- package/src/components/tiptap-node/table-node/ui/table-clear-row-column-content-button/use-table-clear-row-column-content.ts +423 -0
- package/src/components/tiptap-node/table-node/ui/table-delete-row-column-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-delete-row-column-button/table-delete-row-column-button.tsx +100 -0
- package/src/components/tiptap-node/table-node/ui/table-delete-row-column-button/use-table-delete-row-column.ts +243 -0
- package/src/components/tiptap-node/table-node/ui/table-duplicate-row-column-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-duplicate-row-column-button/table-duplicate-row-column-button.tsx +92 -0
- package/src/components/tiptap-node/table-node/ui/table-duplicate-row-column-button/use-table-duplicate-row-column.ts +357 -0
- package/src/components/tiptap-node/table-node/ui/table-extend-row-column-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-extend-row-column-button/table-extend-row-column-button.css +17 -0
- package/src/components/tiptap-node/table-node/ui/table-extend-row-column-button/table-extend-row-column-button.tsx +240 -0
- package/src/components/tiptap-node/table-node/ui/table-extend-row-column-button/use-table-extend-row-column.ts +118 -0
- package/src/components/tiptap-node/table-node/ui/table-fit-to-width-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-fit-to-width-button/table-fit-to-width-button.tsx +98 -0
- package/src/components/tiptap-node/table-node/ui/table-fit-to-width-button/use-table-fit-to-width.ts +223 -0
- package/src/components/tiptap-node/table-node/ui/table-handle/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-handle/table-handle.tsx +163 -0
- package/src/components/tiptap-node/table-node/ui/table-handle/use-table-handle-positioning.ts +255 -0
- package/src/components/tiptap-node/table-node/ui/table-handle-menu/index.tsx +1 -0
- package/src/components/tiptap-node/table-node/ui/table-handle-menu/table-handle-menu.css +39 -0
- package/src/components/tiptap-node/table-node/ui/table-handle-menu/table-handle-menu.tsx +681 -0
- package/src/components/tiptap-node/table-node/ui/table-header-row-column-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-header-row-column-button/table-header-row-column-button.tsx +99 -0
- package/src/components/tiptap-node/table-node/ui/table-header-row-column-button/use-table-header-row-column.ts +227 -0
- package/src/components/tiptap-node/table-node/ui/table-merge-split-cell-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-merge-split-cell-button/table-merge-split-cell-button.tsx +125 -0
- package/src/components/tiptap-node/table-node/ui/table-merge-split-cell-button/use-table-merge-split-cell.ts +267 -0
- package/src/components/tiptap-node/table-node/ui/table-move-row-column-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-move-row-column-button/table-move-row-column-button.tsx +123 -0
- package/src/components/tiptap-node/table-node/ui/table-move-row-column-button/use-table-move-row-column.ts +431 -0
- package/src/components/tiptap-node/table-node/ui/table-selection-overlay/index.tsx +1 -0
- package/src/components/tiptap-node/table-node/ui/table-selection-overlay/table-selection-overlay.tsx +483 -0
- package/src/components/tiptap-node/table-node/ui/table-selection-overlay/use-resize-overlay.ts +78 -0
- package/src/components/tiptap-node/table-node/ui/table-sort-row-column-button/index.tsx +2 -0
- package/src/components/tiptap-node/table-node/ui/table-sort-row-column-button/table-sort-row-column-button.tsx +100 -0
- package/src/components/tiptap-node/table-node/ui/table-sort-row-column-button/use-table-sort-row-column.ts +444 -0
- package/src/components/tiptap-node/table-node/ui/table-trigger-button/index.tsx +3 -0
- package/src/components/tiptap-node/table-node/ui/table-trigger-button/table-grid-selector.css +39 -0
- package/src/components/tiptap-node/table-node/ui/table-trigger-button/table-grid-selector.tsx +219 -0
- package/src/components/tiptap-node/table-node/ui/table-trigger-button/table-trigger-button.tsx +132 -0
- package/src/components/tiptap-node/table-node/ui/table-trigger-button/use-table-trigger.ts +166 -0
- package/src/components/tiptap-ui/blockquote-button/blockquote-button.tsx +125 -0
- package/src/components/tiptap-ui/blockquote-button/index.tsx +2 -0
- package/src/components/tiptap-ui/blockquote-button/use-blockquote.ts +246 -0
- package/src/components/tiptap-ui/code-block-button/code-block-button.tsx +100 -0
- package/src/components/tiptap-ui/code-block-button/index.tsx +2 -0
- package/src/components/tiptap-ui/code-block-button/use-code-block.ts +256 -0
- package/src/components/tiptap-ui/color-highlight-button/color-highlight-button.css +32 -0
- package/src/components/tiptap-ui/color-highlight-button/color-highlight-button.tsx +171 -0
- package/src/components/tiptap-ui/color-highlight-button/index.tsx +2 -0
- package/src/components/tiptap-ui/color-highlight-button/use-color-highlight.ts +296 -0
- package/src/components/tiptap-ui/color-highlight-popover/color-highlight-popover.tsx +211 -0
- package/src/components/tiptap-ui/color-highlight-popover/index.tsx +1 -0
- package/src/components/tiptap-ui/color-menu/color-menu.tsx +178 -0
- package/src/components/tiptap-ui/color-menu/index.tsx +1 -0
- package/src/components/tiptap-ui/color-text-button/color-text-button.css +31 -0
- package/src/components/tiptap-ui/color-text-button/color-text-button.tsx +150 -0
- package/src/components/tiptap-ui/color-text-button/index.tsx +2 -0
- package/src/components/tiptap-ui/color-text-button/use-color-text.ts +251 -0
- package/src/components/tiptap-ui/color-text-popover/color-text-popover.css +25 -0
- package/src/components/tiptap-ui/color-text-popover/color-text-popover.tsx +360 -0
- package/src/components/tiptap-ui/color-text-popover/index.tsx +2 -0
- package/src/components/tiptap-ui/color-text-popover/use-color-text-popover.ts +229 -0
- package/src/components/tiptap-ui/copy-anchor-link-button/copy-anchor-link-button.tsx +118 -0
- package/src/components/tiptap-ui/copy-anchor-link-button/index.tsx +3 -0
- package/src/components/tiptap-ui/copy-anchor-link-button/use-copy-anchor-link.ts +252 -0
- package/src/components/tiptap-ui/copy-anchor-link-button/use-scroll-to-hash.ts +128 -0
- package/src/components/tiptap-ui/copy-to-clipboard-button/copy-to-clipboard-button.tsx +116 -0
- package/src/components/tiptap-ui/copy-to-clipboard-button/index.tsx +2 -0
- package/src/components/tiptap-ui/copy-to-clipboard-button/use-copy-to-clipboard.ts +234 -0
- package/src/components/tiptap-ui/delete-node-button/delete-node-button.tsx +98 -0
- package/src/components/tiptap-ui/delete-node-button/index.tsx +2 -0
- package/src/components/tiptap-ui/delete-node-button/use-delete-node.ts +236 -0
- package/src/components/tiptap-ui/drag-context-menu/drag-context-menu-types.ts +28 -0
- package/src/components/tiptap-ui/drag-context-menu/drag-context-menu.css +17 -0
- package/src/components/tiptap-ui/drag-context-menu/drag-context-menu.tsx +413 -0
- package/src/components/tiptap-ui/drag-context-menu/index.tsx +2 -0
- package/src/components/tiptap-ui/duplicate-button/duplicate-button.tsx +114 -0
- package/src/components/tiptap-ui/duplicate-button/index.tsx +2 -0
- package/src/components/tiptap-ui/duplicate-button/use-duplicate.ts +208 -0
- package/src/components/tiptap-ui/emoji-dropdown-menu/emoji-dropdown-menu.tsx +103 -0
- package/src/components/tiptap-ui/emoji-dropdown-menu/index.tsx +1 -0
- package/src/components/tiptap-ui/emoji-menu/emoji-menu-utils.ts +36 -0
- package/src/components/tiptap-ui/emoji-menu/emoji-menu.css +30 -0
- package/src/components/tiptap-ui/emoji-menu/emoji-menu.tsx +142 -0
- package/src/components/tiptap-ui/emoji-menu/index.tsx +2 -0
- package/src/components/tiptap-ui/emoji-trigger-button/emoji-trigger-button.tsx +128 -0
- package/src/components/tiptap-ui/emoji-trigger-button/index.tsx +2 -0
- package/src/components/tiptap-ui/emoji-trigger-button/use-emoji-trigger.ts +315 -0
- package/src/components/tiptap-ui/heading-button/heading-button.tsx +127 -0
- package/src/components/tiptap-ui/heading-button/index.tsx +2 -0
- package/src/components/tiptap-ui/heading-button/use-heading.ts +321 -0
- package/src/components/tiptap-ui/image-align-button/image-align-button.tsx +114 -0
- package/src/components/tiptap-ui/image-align-button/index.tsx +2 -0
- package/src/components/tiptap-ui/image-align-button/use-image-align.ts +295 -0
- package/src/components/tiptap-ui/image-caption-button/image-caption-button.tsx +77 -0
- package/src/components/tiptap-ui/image-caption-button/index.tsx +2 -0
- package/src/components/tiptap-ui/image-caption-button/use-image-caption.ts +212 -0
- package/src/components/tiptap-ui/image-download-button/image-download-button.tsx +104 -0
- package/src/components/tiptap-ui/image-download-button/index.tsx +2 -0
- package/src/components/tiptap-ui/image-download-button/use-image-download.ts +364 -0
- package/src/components/tiptap-ui/image-upload-button/image-upload-button.tsx +133 -0
- package/src/components/tiptap-ui/image-upload-button/index.tsx +2 -0
- package/src/components/tiptap-ui/image-upload-button/use-image-upload.ts +192 -0
- package/src/components/tiptap-ui/link-popover/index.tsx +2 -0
- package/src/components/tiptap-ui/link-popover/link-popover.tsx +271 -0
- package/src/components/tiptap-ui/link-popover/use-link-popover.ts +286 -0
- package/src/components/tiptap-ui/list-button/index.tsx +2 -0
- package/src/components/tiptap-ui/list-button/list-button.tsx +123 -0
- package/src/components/tiptap-ui/list-button/use-list.ts +326 -0
- package/src/components/tiptap-ui/mark-button/index.tsx +2 -0
- package/src/components/tiptap-ui/mark-button/mark-button.tsx +110 -0
- package/src/components/tiptap-ui/mark-button/use-mark.ts +195 -0
- package/src/components/tiptap-ui/mention-dropdown-menu/index.tsx +1 -0
- package/src/components/tiptap-ui/mention-dropdown-menu/mention-dropdown-menu.tsx +212 -0
- package/src/components/tiptap-ui/mention-trigger-button/index.tsx +2 -0
- package/src/components/tiptap-ui/mention-trigger-button/mention-trigger-button.tsx +122 -0
- package/src/components/tiptap-ui/mention-trigger-button/use-mention-trigger.ts +339 -0
- package/src/components/tiptap-ui/move-node-button/index.tsx +2 -0
- package/src/components/tiptap-ui/move-node-button/move-node-button.tsx +120 -0
- package/src/components/tiptap-ui/move-node-button/use-move-node.ts +207 -0
- package/src/components/tiptap-ui/reset-all-formatting-button/index.tsx +2 -0
- package/src/components/tiptap-ui/reset-all-formatting-button/reset-all-formatting-button.tsx +126 -0
- package/src/components/tiptap-ui/reset-all-formatting-button/use-reset-all-formatting.ts +250 -0
- package/src/components/tiptap-ui/slash-command-trigger-button/index.tsx +2 -0
- package/src/components/tiptap-ui/slash-command-trigger-button/slash-command-trigger-button.tsx +128 -0
- package/src/components/tiptap-ui/slash-command-trigger-button/use-slash-command-trigger.ts +255 -0
- package/src/components/tiptap-ui/slash-dropdown-menu/index.tsx +2 -0
- package/src/components/tiptap-ui/slash-dropdown-menu/slash-dropdown-menu.css +33 -0
- package/src/components/tiptap-ui/slash-dropdown-menu/slash-dropdown-menu.tsx +159 -0
- package/src/components/tiptap-ui/slash-dropdown-menu/use-slash-dropdown-menu.ts +317 -0
- package/src/components/tiptap-ui/text-align-button/index.tsx +2 -0
- package/src/components/tiptap-ui/text-align-button/text-align-button.tsx +120 -0
- package/src/components/tiptap-ui/text-align-button/use-text-align.ts +224 -0
- package/src/components/tiptap-ui/text-button/index.tsx +2 -0
- package/src/components/tiptap-ui/text-button/text-button.tsx +117 -0
- package/src/components/tiptap-ui/text-button/use-text.ts +264 -0
- package/src/components/tiptap-ui/turn-into-dropdown/index.tsx +2 -0
- package/src/components/tiptap-ui/turn-into-dropdown/turn-into-dropdown.tsx +192 -0
- package/src/components/tiptap-ui/turn-into-dropdown/use-turn-into-dropdown.ts +260 -0
- package/src/components/tiptap-ui/undo-redo-button/index.tsx +2 -0
- package/src/components/tiptap-ui/undo-redo-button/undo-redo-button.tsx +126 -0
- package/src/components/tiptap-ui/undo-redo-button/use-undo-redo.ts +184 -0
- package/src/components/tiptap-ui-primitive/avatar/avatar.css +83 -0
- package/src/components/tiptap-ui-primitive/avatar/avatar.tsx +239 -0
- package/src/components/tiptap-ui-primitive/avatar/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/badge/badge-colors.css +358 -0
- package/src/components/tiptap-ui-primitive/badge/badge-group.css +18 -0
- package/src/components/tiptap-ui-primitive/badge/badge.css +93 -0
- package/src/components/tiptap-ui-primitive/badge/badge.tsx +46 -0
- package/src/components/tiptap-ui-primitive/badge/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/button/button-colors.css +6 -0
- package/src/components/tiptap-ui-primitive/button/button-group.css +17 -0
- package/src/components/tiptap-ui-primitive/button/button.css +428 -0
- package/src/components/tiptap-ui-primitive/button/button.tsx +116 -0
- package/src/components/tiptap-ui-primitive/button/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/card/card.css +42 -0
- package/src/components/tiptap-ui-primitive/card/card.tsx +79 -0
- package/src/components/tiptap-ui-primitive/card/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/combobox/combobox.css +15 -0
- package/src/components/tiptap-ui-primitive/combobox/combobox.tsx +73 -0
- package/src/components/tiptap-ui-primitive/combobox/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/dropdown-menu/dropdown-menu.css +49 -0
- package/src/components/tiptap-ui-primitive/dropdown-menu/dropdown-menu.tsx +98 -0
- package/src/components/tiptap-ui-primitive/dropdown-menu/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/input/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/input/input.css +26 -0
- package/src/components/tiptap-ui-primitive/input/input.tsx +24 -0
- package/src/components/tiptap-ui-primitive/label/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/label/label.css +9 -0
- package/src/components/tiptap-ui-primitive/label/label.tsx +42 -0
- package/src/components/tiptap-ui-primitive/menu/index.tsx +5 -0
- package/src/components/tiptap-ui-primitive/menu/menu-context.ts +19 -0
- package/src/components/tiptap-ui-primitive/menu/menu-hooks.ts +102 -0
- package/src/components/tiptap-ui-primitive/menu/menu-types.ts +56 -0
- package/src/components/tiptap-ui-primitive/menu/menu-utils.ts +64 -0
- package/src/components/tiptap-ui-primitive/menu/menu.css +49 -0
- package/src/components/tiptap-ui-primitive/menu/menu.tsx +235 -0
- package/src/components/tiptap-ui-primitive/popover/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/popover/popover.css +49 -0
- package/src/components/tiptap-ui-primitive/popover/popover.tsx +37 -0
- package/src/components/tiptap-ui-primitive/separator/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/separator/separator.css +19 -0
- package/src/components/tiptap-ui-primitive/separator/separator.tsx +33 -0
- package/src/components/tiptap-ui-primitive/sidebar/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/sidebar/sidebar.css +140 -0
- package/src/components/tiptap-ui-primitive/sidebar/sidebar.tsx +299 -0
- package/src/components/tiptap-ui-primitive/spacer/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/spacer/spacer.tsx +26 -0
- package/src/components/tiptap-ui-primitive/textarea-autosize/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/textarea-autosize/textarea-autosize.tsx +18 -0
- package/src/components/tiptap-ui-primitive/toolbar/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/toolbar/toolbar.css +65 -0
- package/src/components/tiptap-ui-primitive/toolbar/toolbar.tsx +123 -0
- package/src/components/tiptap-ui-primitive/tooltip/index.tsx +1 -0
- package/src/components/tiptap-ui-primitive/tooltip/tooltip.css +21 -0
- package/src/components/tiptap-ui-primitive/tooltip/tooltip.tsx +237 -0
- package/src/components/tiptap-ui-utils/floating-element/floating-element-utils.ts +23 -0
- package/src/components/tiptap-ui-utils/floating-element/floating-element.tsx +343 -0
- package/src/components/tiptap-ui-utils/floating-element/index.tsx +2 -0
- package/src/components/tiptap-ui-utils/suggestion-menu/index.tsx +3 -0
- package/src/components/tiptap-ui-utils/suggestion-menu/suggestion-menu-types.ts +91 -0
- package/src/components/tiptap-ui-utils/suggestion-menu/suggestion-menu-utils.ts +87 -0
- package/src/components/tiptap-ui-utils/suggestion-menu/suggestion-menu.tsx +240 -0
- package/src/content/index.tsx +27 -0
- package/src/content/style.css +12 -0
- package/src/contexts/ai-context.tsx +65 -0
- package/src/contexts/app-context.tsx +159 -0
- package/src/contexts/user-context.tsx +138 -0
- package/src/editor/collaboration/index.tsx +64 -0
- package/src/editor/index.tsx +144 -42
- package/src/hooks/use-composed-ref.ts +47 -0
- package/src/hooks/use-cursor-visibility.ts +69 -0
- package/src/hooks/use-editor.ts +237 -0
- package/src/hooks/use-element-rect.ts +165 -0
- package/src/hooks/use-floating-element.ts +101 -0
- package/src/hooks/use-floating-toolbar-visibility.ts +123 -0
- package/src/hooks/use-is-breakpoint.ts +37 -0
- package/src/hooks/use-isomorphic-layout-effect.ts +11 -0
- package/src/hooks/use-menu-navigation.ts +182 -0
- package/src/hooks/use-on-click-outside.ts +135 -0
- package/src/hooks/use-scrolling.ts +75 -0
- package/src/hooks/use-throttled-callback.ts +48 -0
- package/src/hooks/use-tiptap-editor.ts +49 -0
- package/src/hooks/use-ui-editor-state.ts +29 -0
- package/src/hooks/use-unmount.ts +21 -0
- package/src/hooks/use-window-size.ts +88 -0
- package/src/index.ts +4 -7
- package/src/lib/tiptap-advanced-utils.ts +362 -0
- package/src/lib/tiptap-collab-utils.ts +289 -0
- package/src/lib/tiptap-utils.ts +612 -0
- package/src/locales/en.json +123 -0
- package/src/locales/zh-CN.json +123 -0
- package/src/locales/zh-TW.json +123 -0
- package/src/styles/variables.css +92 -0
- package/README.md +0 -458
- package/src/editor/constants.tsx +0 -66
- package/src/editor/container.css +0 -46
- package/src/editor/control/character-count/index.tsx +0 -39
- package/src/editor/control/drag-handle/index.tsx +0 -85
- package/src/editor/control/drag-handle/use.content.actions.ts +0 -71
- package/src/editor/control/drag-handle/use.data.ts +0 -29
- package/src/editor/control/drag-handle/use.handle.id.ts +0 -6
- package/src/editor/control/index.tsx +0 -35
- package/src/editor/editor.css +0 -626
- package/src/editor/extension/block-quote-figure/BlockquoteFigure.ts +0 -73
- package/src/editor/extension/block-quote-figure/Quote/Quote.ts +0 -31
- package/src/editor/extension/block-quote-figure/Quote/index.ts +0 -1
- package/src/editor/extension/block-quote-figure/QuoteCaption/QuoteCaption.ts +0 -54
- package/src/editor/extension/block-quote-figure/QuoteCaption/index.ts +0 -1
- package/src/editor/extension/block-quote-figure/index.ts +0 -1
- package/src/editor/extension/document/index.ts +0 -5
- package/src/editor/extension/figcaption/Figcaption.ts +0 -90
- package/src/editor/extension/figcaption/index.ts +0 -1
- package/src/editor/extension/figure/Figure.ts +0 -62
- package/src/editor/extension/figure/index.ts +0 -1
- package/src/editor/extension/font-size/FontSize.ts +0 -64
- package/src/editor/extension/font-size/index.ts +0 -1
- package/src/editor/extension/global-drag-handle/clipboard-serializer.ts +0 -28
- package/src/editor/extension/global-drag-handle/index.ts +0 -377
- package/src/editor/extension/heading/index.ts +0 -13
- package/src/editor/extension/horizontal-rule/HorizontalRule.ts +0 -10
- package/src/editor/extension/horizontal-rule/index.ts +0 -1
- package/src/editor/extension/image/index.ts +0 -5
- package/src/editor/extension/image-block/ImageBlock.ts +0 -103
- package/src/editor/extension/image-block/components/ImageBlockMenu.tsx +0 -100
- package/src/editor/extension/image-block/components/ImageBlockView.tsx +0 -47
- package/src/editor/extension/image-block/components/ImageBlockWidth.tsx +0 -40
- package/src/editor/extension/image-block/index.ts +0 -1
- package/src/editor/extension/image-upload/ImageUpload.ts +0 -58
- package/src/editor/extension/image-upload/index.ts +0 -1
- package/src/editor/extension/image-upload/view/ImageUpload.tsx +0 -27
- package/src/editor/extension/image-upload/view/ImageUploader.tsx +0 -64
- package/src/editor/extension/image-upload/view/hooks.ts +0 -109
- package/src/editor/extension/image-upload/view/index.tsx +0 -1
- package/src/editor/extension/index.ts +0 -30
- package/src/editor/extension/link/Link.ts +0 -39
- package/src/editor/extension/link/index.ts +0 -1
- package/src/editor/extension/multi-column/Column.ts +0 -33
- package/src/editor/extension/multi-column/Columns.ts +0 -65
- package/src/editor/extension/multi-column/index.ts +0 -2
- package/src/editor/extension/multi-column/menus/ColumnsMenu.tsx +0 -82
- package/src/editor/extension/multi-column/menus/index.ts +0 -1
- package/src/editor/extension/selection/Selection.ts +0 -36
- package/src/editor/extension/selection/index.ts +0 -1
- package/src/editor/extension/slash-command/MenuList.tsx +0 -145
- package/src/editor/extension/slash-command/groups.ts +0 -153
- package/src/editor/extension/slash-command/index.ts +0 -277
- package/src/editor/extension/slash-command/types.ts +0 -25
- package/src/editor/extension/table/Cell.ts +0 -126
- package/src/editor/extension/table/Header.ts +0 -89
- package/src/editor/extension/table/Row.ts +0 -8
- package/src/editor/extension/table/Table.ts +0 -9
- package/src/editor/extension/table/index.ts +0 -4
- package/src/editor/extension/table/menus/TableColumn/index.tsx +0 -73
- package/src/editor/extension/table/menus/TableColumn/utils.ts +0 -38
- package/src/editor/extension/table/menus/TableRow/index.tsx +0 -74
- package/src/editor/extension/table/menus/TableRow/utils.ts +0 -38
- package/src/editor/extension/table/menus/index.tsx +0 -2
- package/src/editor/extension/table/utils.ts +0 -258
- package/src/editor/extension/task-item/index.ts +0 -1
- package/src/editor/extension/task-item/task-item.ts +0 -225
- package/src/editor/extension/task-list/index.ts +0 -1
- package/src/editor/extension/task-list/task-list.ts +0 -81
- package/src/editor/extension/trailing-node/index.ts +0 -1
- package/src/editor/extension/trailing-node/trailing-node.ts +0 -70
- package/src/editor/extension/unique-id/index.ts +0 -1
- package/src/editor/extension/unique-id/uniqueId.ts +0 -123
- package/src/editor/hooks.ts +0 -264
- package/src/editor/menus/LinkMenu/LinkMenu.tsx +0 -75
- package/src/editor/menus/LinkMenu/index.tsx +0 -1
- package/src/editor/menus/TextMenu/TextMenu.tsx +0 -193
- package/src/editor/menus/TextMenu/components/AIDropdown.tsx +0 -140
- package/src/editor/menus/TextMenu/components/ContentTypePicker.tsx +0 -76
- package/src/editor/menus/TextMenu/components/EditLinkPopover.tsx +0 -25
- package/src/editor/menus/TextMenu/components/FontFamilyPicker.tsx +0 -84
- package/src/editor/menus/TextMenu/components/FontSizePicker.tsx +0 -56
- package/src/editor/menus/TextMenu/hooks/useTextmenuCommands.ts +0 -96
- package/src/editor/menus/TextMenu/hooks/useTextmenuContentTypes.ts +0 -86
- package/src/editor/menus/TextMenu/hooks/useTextmenuStates.ts +0 -50
- package/src/editor/menus/TextMenu/index.tsx +0 -2
- package/src/editor/menus/types.ts +0 -21
- package/src/editor/panels/Colorpicker/ColorButton.tsx +0 -35
- package/src/editor/panels/Colorpicker/Colorpicker.tsx +0 -67
- package/src/editor/panels/Colorpicker/index.tsx +0 -2
- package/src/editor/panels/LinkEditorPanel/LinkEditorPanel.tsx +0 -76
- package/src/editor/panels/LinkEditorPanel/index.tsx +0 -1
- package/src/editor/panels/LinkPreviewPanel/LinkPreviewPanel.tsx +0 -32
- package/src/editor/panels/LinkPreviewPanel/index.tsx +0 -1
- package/src/editor/panels/index.tsx +0 -3
- package/src/editor/types.tsx +0 -38
- package/src/editor/ui/Button/Button.tsx +0 -70
- package/src/editor/ui/Button/index.tsx +0 -2
- package/src/editor/ui/Dropdown/Dropdown.tsx +0 -39
- package/src/editor/ui/Dropdown/index.tsx +0 -1
- package/src/editor/ui/Icon.tsx +0 -21
- package/src/editor/ui/Loader/Loader.tsx +0 -39
- package/src/editor/ui/Loader/index.ts +0 -1
- package/src/editor/ui/Loader/types.ts +0 -7
- package/src/editor/ui/Panel/index.tsx +0 -109
- package/src/editor/ui/PopoverMenu.tsx +0 -127
- package/src/editor/ui/Spinner/Spinner.tsx +0 -10
- package/src/editor/ui/Spinner/index.tsx +0 -1
- package/src/editor/ui/Surface.tsx +0 -27
- package/src/editor/ui/Textarea/Textarea.tsx +0 -20
- package/src/editor/ui/Textarea/index.tsx +0 -1
- package/src/editor/ui/Toggle/Toggle.tsx +0 -39
- package/src/editor/ui/Toggle/index.tsx +0 -1
- package/src/editor/ui/Toolbar.tsx +0 -107
- package/src/editor/ui/Tooltip/index.tsx +0 -77
- package/src/editor/ui/Tooltip/types.ts +0 -17
- package/src/editor/utils/cssVar.ts +0 -14
- package/src/editor/utils/getRenderContainer.ts +0 -39
- package/src/editor/utils/index.ts +0 -16
- package/src/editor/utils/isCustomNodeSelected.ts +0 -47
- package/src/editor/utils/isTextSelected.ts +0 -25
- package/src/editor/utils/locale.ts +0 -5
- package/src/editor/viewer/index.tsx +0 -26
- package/src/globals.css +0 -1
- package/src/locales/en-us.ts +0 -133
- package/src/locales/zh-cn.ts +0 -133
- package/src/locales/zh-tw.ts +0 -133
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import type { Attrs, Node } from "@tiptap/pm/model"
|
|
2
|
+
import { type Editor } from "@tiptap/react"
|
|
3
|
+
import { NodeSelection, TextSelection } from "@tiptap/pm/state"
|
|
4
|
+
import { findNodePosition, isValidPosition } from "./tiptap-utils"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Splits an array into chunks of specified size
|
|
8
|
+
*/
|
|
9
|
+
export function chunkArray<T>(array: Array<T>, size: number): Array<Array<T>> {
|
|
10
|
+
return Array.from({ length: Math.ceil(array.length / size) }, (_, index) =>
|
|
11
|
+
array.slice(index * size, index * size + size)
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Helper function to check if there's content above the current position
|
|
17
|
+
*/
|
|
18
|
+
export function hasContentAbove(editor: Editor | null): {
|
|
19
|
+
hasContent: boolean
|
|
20
|
+
content: string
|
|
21
|
+
} {
|
|
22
|
+
if (!editor) return { hasContent: false, content: "" }
|
|
23
|
+
|
|
24
|
+
const { state } = editor
|
|
25
|
+
const { $from } = state.selection
|
|
26
|
+
|
|
27
|
+
for (let i = $from.index(0) - 1; i >= 0; i--) {
|
|
28
|
+
const node = state.doc.child(i)
|
|
29
|
+
const content = node.textContent.trim()
|
|
30
|
+
|
|
31
|
+
if (content) {
|
|
32
|
+
return { hasContent: true, content }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return { hasContent: false, content: "" }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Gets the active attributes of a specific mark in the current editor selection.
|
|
41
|
+
*
|
|
42
|
+
* @param editor - The Tiptap editor instance.
|
|
43
|
+
* @param markName - The name of the mark to look for (e.g., "highlight", "link").
|
|
44
|
+
* @returns The attributes of the active mark, or `null` if the mark is not active.
|
|
45
|
+
*/
|
|
46
|
+
export function getActiveMarkAttrs(
|
|
47
|
+
editor: Editor | null,
|
|
48
|
+
markName: string
|
|
49
|
+
): Attrs | null {
|
|
50
|
+
if (!editor) return null
|
|
51
|
+
|
|
52
|
+
const { state } = editor
|
|
53
|
+
const { from, to, empty, $from } = state.selection
|
|
54
|
+
|
|
55
|
+
if (empty) {
|
|
56
|
+
const mark = $from.marks().find((m) => m.type.name === markName)
|
|
57
|
+
return mark?.attrs ?? null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const seen = new Set<string>()
|
|
61
|
+
let foundAttrs: Attrs | null = null
|
|
62
|
+
|
|
63
|
+
state.doc.nodesBetween(from, to, (node) => {
|
|
64
|
+
if (!node.isText) return
|
|
65
|
+
|
|
66
|
+
for (const mark of node.marks) {
|
|
67
|
+
if (mark.type.name === markName && !seen.has(mark.type.name)) {
|
|
68
|
+
seen.add(mark.type.name)
|
|
69
|
+
foundAttrs = mark.attrs
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
return foundAttrs
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Finds the position of a node in the editor selection
|
|
79
|
+
* @param params Object containing editor, node (optional), and nodePos (optional)
|
|
80
|
+
* @returns The position of the node in the selection or null if not found
|
|
81
|
+
*/
|
|
82
|
+
export function findSelectionPosition(params: {
|
|
83
|
+
editor: Editor
|
|
84
|
+
node?: Node | null
|
|
85
|
+
nodePos?: number | null
|
|
86
|
+
}): number | null {
|
|
87
|
+
const { editor, node, nodePos } = params
|
|
88
|
+
|
|
89
|
+
if (isValidPosition(nodePos)) return nodePos
|
|
90
|
+
|
|
91
|
+
if (node) {
|
|
92
|
+
const found = findNodePosition({ editor, node })
|
|
93
|
+
if (found) return found.pos
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const { selection } = editor.state
|
|
97
|
+
if (!selection.empty) return null
|
|
98
|
+
|
|
99
|
+
const resolvedPos = selection.$anchor
|
|
100
|
+
const nodeDepth = 1
|
|
101
|
+
const selectedNode = resolvedPos.node(nodeDepth)
|
|
102
|
+
|
|
103
|
+
return selectedNode ? resolvedPos.before(nodeDepth) : null
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Gets the currently selected DOM element in the editor
|
|
108
|
+
* @param editor The Tiptap editor instance
|
|
109
|
+
* @returns The selected DOM element or null if no selection is present
|
|
110
|
+
*/
|
|
111
|
+
export function getSelectedDOMElement(editor: Editor): HTMLElement | null {
|
|
112
|
+
const { state, view } = editor
|
|
113
|
+
const { selection } = state
|
|
114
|
+
|
|
115
|
+
if (selection instanceof NodeSelection) {
|
|
116
|
+
return view.nodeDOM(selection.from) as HTMLElement | null
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (selection instanceof TextSelection) {
|
|
120
|
+
const $anchor = selection.$anchor
|
|
121
|
+
|
|
122
|
+
// Ensure the depth is sufficient to avoid errors
|
|
123
|
+
if ($anchor.depth >= 1) {
|
|
124
|
+
const dom = view.nodeDOM($anchor.before(1))
|
|
125
|
+
if (dom instanceof HTMLElement) {
|
|
126
|
+
return dom
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return null
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Gets the closest node from the current selection in the editor based on criteria
|
|
136
|
+
* @param editor The Tiptap editor instance
|
|
137
|
+
* @param options Configuration options for finding the node
|
|
138
|
+
* @returns An object containing the closest matching node, its position, and depth, or null if not found
|
|
139
|
+
*/
|
|
140
|
+
export function getClosestNode(
|
|
141
|
+
editor: Editor | null,
|
|
142
|
+
options?: {
|
|
143
|
+
nodeName?: string
|
|
144
|
+
isBlock?: boolean
|
|
145
|
+
predicate?: (node: Node) => boolean
|
|
146
|
+
}
|
|
147
|
+
) {
|
|
148
|
+
if (!editor) return null
|
|
149
|
+
|
|
150
|
+
const { selection } = editor.state
|
|
151
|
+
const { $from } = selection
|
|
152
|
+
const { nodeName, isBlock = true, predicate } = options || {} // Default to block nodes
|
|
153
|
+
|
|
154
|
+
let depth = $from.depth
|
|
155
|
+
while (depth > 0) {
|
|
156
|
+
const node = $from.node(depth)
|
|
157
|
+
|
|
158
|
+
// Check all conditions
|
|
159
|
+
const matchesName = !nodeName || node.type.name === nodeName
|
|
160
|
+
const matchesBlock = node.type.isBlock === isBlock
|
|
161
|
+
const matchesPredicate = !predicate || predicate(node)
|
|
162
|
+
|
|
163
|
+
if (matchesName && matchesBlock && matchesPredicate) {
|
|
164
|
+
const pos = $from.before(depth)
|
|
165
|
+
return { node, pos, depth }
|
|
166
|
+
}
|
|
167
|
+
depth--
|
|
168
|
+
}
|
|
169
|
+
return null
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Gets the closest node from a specific position in the document
|
|
174
|
+
* @param editor The Tiptap editor instance
|
|
175
|
+
* @param pos The position to search from
|
|
176
|
+
* @param options Configuration options for finding the node
|
|
177
|
+
* @returns An object containing the closest matching node, its position, and depth, or null if not found
|
|
178
|
+
*/
|
|
179
|
+
export function getClosestNodeByPos(
|
|
180
|
+
editor: Editor | null,
|
|
181
|
+
pos: number,
|
|
182
|
+
options?: {
|
|
183
|
+
nodeName?: string
|
|
184
|
+
isBlock?: boolean
|
|
185
|
+
predicate?: (node: Node) => boolean
|
|
186
|
+
}
|
|
187
|
+
) {
|
|
188
|
+
if (!editor) return null
|
|
189
|
+
|
|
190
|
+
const docSize = editor.state.doc.content.size
|
|
191
|
+
if (pos < 0 || pos > docSize) {
|
|
192
|
+
console.warn(`Position ${pos} is out of bounds (doc size: ${docSize})`)
|
|
193
|
+
return null
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const $pos = editor.state.doc.resolve(pos)
|
|
198
|
+
const { nodeName, isBlock = true, predicate } = options || {}
|
|
199
|
+
|
|
200
|
+
let depth = $pos.depth
|
|
201
|
+
while (depth > 0) {
|
|
202
|
+
const node = $pos.node(depth)
|
|
203
|
+
|
|
204
|
+
const matchesName = !nodeName || node.type.name === nodeName
|
|
205
|
+
const matchesBlock = node.type.isBlock === isBlock
|
|
206
|
+
const matchesPredicate = !predicate || predicate(node)
|
|
207
|
+
|
|
208
|
+
if (matchesName && matchesBlock && matchesPredicate) {
|
|
209
|
+
const nodePos = $pos.before(depth)
|
|
210
|
+
return { node, pos: nodePos, depth }
|
|
211
|
+
}
|
|
212
|
+
depth--
|
|
213
|
+
}
|
|
214
|
+
return null
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.error("Error resolving position:", error)
|
|
217
|
+
return null
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Convenience function to find closest block node (maintains backward compatibility)
|
|
223
|
+
*/
|
|
224
|
+
export function getClosestBlockNode(editor: Editor | null) {
|
|
225
|
+
return getClosestNode(editor, { isBlock: true })
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Convenience function to find closest node by name
|
|
230
|
+
*/
|
|
231
|
+
export function getClosestNodeByName(editor: Editor | null, nodeName: string) {
|
|
232
|
+
return getClosestNode(editor, { nodeName })
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Find multiple matching nodes up the tree
|
|
237
|
+
*/
|
|
238
|
+
export function getAllMatchingNodes(
|
|
239
|
+
editor: Editor | null,
|
|
240
|
+
options?: {
|
|
241
|
+
nodeName?: string
|
|
242
|
+
isBlock?: boolean
|
|
243
|
+
predicate?: (node: Node) => boolean
|
|
244
|
+
}
|
|
245
|
+
) {
|
|
246
|
+
if (!editor) return []
|
|
247
|
+
|
|
248
|
+
const { selection } = editor.state
|
|
249
|
+
const { nodeName, isBlock = true, predicate } = options || {}
|
|
250
|
+
const matches = []
|
|
251
|
+
|
|
252
|
+
const nodeMatches = (node: Node) => {
|
|
253
|
+
const matchesName = !nodeName || node.type.name === nodeName
|
|
254
|
+
const matchesBlock = node.type.isBlock === isBlock
|
|
255
|
+
const matchesPredicate = !predicate || predicate(node)
|
|
256
|
+
return matchesName && matchesBlock && matchesPredicate
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (selection instanceof NodeSelection) {
|
|
260
|
+
const selectedNode = selection.node
|
|
261
|
+
if (nodeMatches(selectedNode)) {
|
|
262
|
+
matches.push({
|
|
263
|
+
node: selectedNode,
|
|
264
|
+
pos: selection.from,
|
|
265
|
+
depth: 0,
|
|
266
|
+
})
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const { $from } = selection
|
|
271
|
+
let depth = $from.depth
|
|
272
|
+
|
|
273
|
+
while (depth > 0) {
|
|
274
|
+
const node = $from.node(depth)
|
|
275
|
+
|
|
276
|
+
if (nodeMatches(node)) {
|
|
277
|
+
const pos = $from.before(depth)
|
|
278
|
+
matches.push({ node, pos, depth })
|
|
279
|
+
}
|
|
280
|
+
depth--
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return matches
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Gets the anchor node and its position in the editor.
|
|
288
|
+
* @param editor The Tiptap editor instance
|
|
289
|
+
* @param allowEmptySelection If true, still returns the node at the cursor position even if selection is empty
|
|
290
|
+
* @returns An object containing the anchor node and its position, or null if not found
|
|
291
|
+
*/
|
|
292
|
+
export function getAnchorNodeAndPos(
|
|
293
|
+
editor: Editor | null,
|
|
294
|
+
allowEmptySelection: boolean = true
|
|
295
|
+
): { node: Node; pos: number } | null {
|
|
296
|
+
if (!editor) return null
|
|
297
|
+
|
|
298
|
+
const { state } = editor
|
|
299
|
+
const { selection } = state
|
|
300
|
+
|
|
301
|
+
if (selection instanceof NodeSelection) {
|
|
302
|
+
const node = selection.node
|
|
303
|
+
const pos = selection.from
|
|
304
|
+
|
|
305
|
+
if (node && isValidPosition(pos)) {
|
|
306
|
+
return { node, pos }
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (selection.empty && !allowEmptySelection) return null
|
|
311
|
+
|
|
312
|
+
const $anchor = selection.$anchor
|
|
313
|
+
const depth = 1 // explicitly use depth 1
|
|
314
|
+
const node = $anchor.node(depth)
|
|
315
|
+
const pos = $anchor.before(depth)
|
|
316
|
+
|
|
317
|
+
return { node, pos }
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Checks if the current selection in the editor contains any text.
|
|
322
|
+
*
|
|
323
|
+
* @param editor - The Tiptap editor instance.
|
|
324
|
+
* @returns `true` if the selection contains text, `false` otherwise.
|
|
325
|
+
*/
|
|
326
|
+
export function selectionHasText(editor: Editor | null): boolean {
|
|
327
|
+
if (!editor) return false
|
|
328
|
+
|
|
329
|
+
const { state } = editor
|
|
330
|
+
const { selection, doc } = state
|
|
331
|
+
|
|
332
|
+
if (selection.empty) return false
|
|
333
|
+
|
|
334
|
+
const text = doc.textBetween(selection.from, selection.to, "\n", "\0")
|
|
335
|
+
return text.trim().length > 0
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Retrieves a specific extension by name from the Tiptap editor.
|
|
340
|
+
* @param editor - The Tiptap editor instance
|
|
341
|
+
* @param extensionName - The name of the extension to retrieve
|
|
342
|
+
* @returns The extension instance if found, otherwise null
|
|
343
|
+
*/
|
|
344
|
+
export function getEditorExtension(
|
|
345
|
+
editor: Editor | null,
|
|
346
|
+
extensionName: string
|
|
347
|
+
) {
|
|
348
|
+
if (!editor) return null
|
|
349
|
+
|
|
350
|
+
const extension = editor.extensionManager.extensions.find(
|
|
351
|
+
(ext) => ext.name === extensionName
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
if (!extension) {
|
|
355
|
+
console.warn(
|
|
356
|
+
`Extension "${extensionName}" not found in the editor schema. Ensure it is included in the editor configuration.`
|
|
357
|
+
)
|
|
358
|
+
return null
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return extension
|
|
362
|
+
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { NodeSelection, type Selection } from "@tiptap/pm/state"
|
|
2
|
+
import { CellSelection } from "@tiptap/pm/tables"
|
|
3
|
+
import type { JSONContent, Editor } from "@tiptap/react"
|
|
4
|
+
import { isTextSelection, isNodeSelection, posToDOMRect } from "@tiptap/react"
|
|
5
|
+
|
|
6
|
+
// TipTap Collaboration
|
|
7
|
+
export const TIPTAP_COLLAB_DOC_PREFIX =
|
|
8
|
+
process.env.NEXT_PUBLIC_TIPTAP_COLLAB_DOC_PREFIX || ""
|
|
9
|
+
export const TIPTAP_COLLAB_APP_ID =
|
|
10
|
+
process.env.NEXT_PUBLIC_TIPTAP_COLLAB_APP_ID || ""
|
|
11
|
+
export const TIPTAP_COLLAB_TOKEN =
|
|
12
|
+
process.env.NEXT_PUBLIC_TIPTAP_COLLAB_TOKEN || ""
|
|
13
|
+
|
|
14
|
+
// TipTap AI
|
|
15
|
+
export const TIPTAP_AI_APP_ID = process.env.NEXT_PUBLIC_TIPTAP_AI_APP_ID || ""
|
|
16
|
+
export const TIPTAP_AI_TOKEN = process.env.NEXT_PUBLIC_TIPTAP_AI_TOKEN || ""
|
|
17
|
+
|
|
18
|
+
export const USE_JWT_TOKEN_API_ENDPOINT =
|
|
19
|
+
process.env.NEXT_PUBLIC_USE_JWT_TOKEN_API_ENDPOINT || ""
|
|
20
|
+
|
|
21
|
+
const NODE_TYPE_LABELS: Record<string, string> = {
|
|
22
|
+
paragraph: "Text",
|
|
23
|
+
heading: "Heading",
|
|
24
|
+
blockquote: "Blockquote",
|
|
25
|
+
listItem: "List Item",
|
|
26
|
+
codeBlock: "Code Block",
|
|
27
|
+
table: "Table",
|
|
28
|
+
}
|
|
29
|
+
export type OverflowPosition = "none" | "top" | "bottom" | "both"
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Utility function to get URL parameters
|
|
33
|
+
*/
|
|
34
|
+
export const getUrlParam = (param: string): string | null => {
|
|
35
|
+
if (typeof window === "undefined") return null
|
|
36
|
+
const params = new URLSearchParams(window.location.search)
|
|
37
|
+
return params.get(param)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns a display name for the current node in the editor
|
|
42
|
+
* @param editor The Tiptap editor instance
|
|
43
|
+
* @returns The display name of the current node
|
|
44
|
+
*/
|
|
45
|
+
export const getNodeDisplayName = (editor: Editor | null): string => {
|
|
46
|
+
if (!editor) return "Node"
|
|
47
|
+
|
|
48
|
+
const { selection } = editor.state
|
|
49
|
+
|
|
50
|
+
if (selection instanceof NodeSelection) {
|
|
51
|
+
const nodeType = selection.node.type.name
|
|
52
|
+
return NODE_TYPE_LABELS[nodeType] || nodeType.toLowerCase()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (selection instanceof CellSelection) {
|
|
56
|
+
return "Table"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const { $anchor } = selection
|
|
60
|
+
const nodeType = $anchor.parent.type.name
|
|
61
|
+
return NODE_TYPE_LABELS[nodeType] || nodeType.toLowerCase()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Removes empty paragraph nodes from content
|
|
66
|
+
*/
|
|
67
|
+
export const removeEmptyParagraphs = (content: JSONContent) => ({
|
|
68
|
+
...content,
|
|
69
|
+
content: content.content?.filter(
|
|
70
|
+
(node) =>
|
|
71
|
+
node.type !== "paragraph" ||
|
|
72
|
+
node.content?.some((child) => child.text?.trim() || child.type !== "text")
|
|
73
|
+
),
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Determines how a target element overflows relative to a container element
|
|
78
|
+
*/
|
|
79
|
+
export function getElementOverflowPosition(
|
|
80
|
+
targetElement: Element,
|
|
81
|
+
containerElement: HTMLElement
|
|
82
|
+
): OverflowPosition {
|
|
83
|
+
const targetBounds = targetElement.getBoundingClientRect()
|
|
84
|
+
const containerBounds = containerElement.getBoundingClientRect()
|
|
85
|
+
|
|
86
|
+
const isOverflowingTop = targetBounds.top < containerBounds.top
|
|
87
|
+
const isOverflowingBottom = targetBounds.bottom > containerBounds.bottom
|
|
88
|
+
|
|
89
|
+
if (isOverflowingTop && isOverflowingBottom) return "both"
|
|
90
|
+
if (isOverflowingTop) return "top"
|
|
91
|
+
if (isOverflowingBottom) return "bottom"
|
|
92
|
+
return "none"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Checks if the current selection is valid for a given editor
|
|
97
|
+
*/
|
|
98
|
+
export const isSelectionValid = (
|
|
99
|
+
editor: Editor | null,
|
|
100
|
+
selection?: Selection,
|
|
101
|
+
excludedNodeTypes: string[] = ["imageUpload", "horizontalRule"]
|
|
102
|
+
): boolean => {
|
|
103
|
+
if (!editor) return false
|
|
104
|
+
if (!selection) selection = editor.state.selection
|
|
105
|
+
|
|
106
|
+
const { state } = editor
|
|
107
|
+
const { doc } = state
|
|
108
|
+
const { empty, from, to } = selection
|
|
109
|
+
|
|
110
|
+
const isEmptyTextBlock =
|
|
111
|
+
!doc.textBetween(from, to).length && isTextSelection(selection)
|
|
112
|
+
const isCodeBlock =
|
|
113
|
+
selection.$from.parent.type.spec.code ||
|
|
114
|
+
(isNodeSelection(selection) && selection.node.type.spec.code)
|
|
115
|
+
const isExcludedNode =
|
|
116
|
+
isNodeSelection(selection) &&
|
|
117
|
+
excludedNodeTypes.includes(selection.node.type.name)
|
|
118
|
+
const isTableCell = selection instanceof CellSelection
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
!empty &&
|
|
122
|
+
!isEmptyTextBlock &&
|
|
123
|
+
!isCodeBlock &&
|
|
124
|
+
!isExcludedNode &&
|
|
125
|
+
!isTableCell
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Checks if the current text selection is valid for editing
|
|
131
|
+
* - Not empty
|
|
132
|
+
* - Not a code block
|
|
133
|
+
* - Not a node selection
|
|
134
|
+
*/
|
|
135
|
+
export const isTextSelectionValid = (editor: Editor | null): boolean => {
|
|
136
|
+
if (!editor) return false
|
|
137
|
+
const { state } = editor
|
|
138
|
+
const { selection } = state
|
|
139
|
+
const isValid =
|
|
140
|
+
isTextSelection(selection) &&
|
|
141
|
+
!selection.empty &&
|
|
142
|
+
!selection.$from.parent.type.spec.code &&
|
|
143
|
+
!isNodeSelection(selection)
|
|
144
|
+
|
|
145
|
+
return isValid
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Gets the bounding rect of the current selection in the editor.
|
|
150
|
+
*/
|
|
151
|
+
export const getSelectionBoundingRect = (editor: Editor): DOMRect | null => {
|
|
152
|
+
const { state } = editor.view
|
|
153
|
+
const { selection } = state
|
|
154
|
+
const { ranges } = selection
|
|
155
|
+
|
|
156
|
+
const from = Math.min(...ranges.map((range) => range.$from.pos))
|
|
157
|
+
const to = Math.max(...ranges.map((range) => range.$to.pos))
|
|
158
|
+
|
|
159
|
+
if (isNodeSelection(selection)) {
|
|
160
|
+
const node = editor.view.nodeDOM(from) as HTMLElement
|
|
161
|
+
if (node) {
|
|
162
|
+
return node.getBoundingClientRect()
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return posToDOMRect(editor.view, from, to)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Generates a deterministic avatar URL from a user name
|
|
171
|
+
*/
|
|
172
|
+
export const getAvatar = (name: string) => {
|
|
173
|
+
if (!name) {
|
|
174
|
+
return "/avatars/memoji_01.png"
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let hash = 0
|
|
178
|
+
for (let i = 0; i < name.length; i++) {
|
|
179
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash)
|
|
180
|
+
hash = hash & hash
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const randomFraction = (Math.abs(hash) % 1000000) / 1000000
|
|
184
|
+
const id = 1 + Math.floor(randomFraction * 20)
|
|
185
|
+
const idString = id.toString().padStart(2, "0")
|
|
186
|
+
return `/avatars/memoji_${idString}.png`
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Fetch collaboration JWT token from the API
|
|
191
|
+
*/
|
|
192
|
+
export const fetchCollabToken = async () => {
|
|
193
|
+
if (USE_JWT_TOKEN_API_ENDPOINT) {
|
|
194
|
+
try {
|
|
195
|
+
// Example API endpoint that returns a JWT token.
|
|
196
|
+
// TODO: implement this API endpoint in your app
|
|
197
|
+
const response = await fetch(`/api/collaboration`, {
|
|
198
|
+
method: "POST",
|
|
199
|
+
headers: {
|
|
200
|
+
"Content-Type": "application/json",
|
|
201
|
+
},
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
if (!response.ok) {
|
|
205
|
+
throw new Error(`Failed to fetch token: ${response.status}`)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const data = await response.json()
|
|
209
|
+
return data.token
|
|
210
|
+
} catch (error) {
|
|
211
|
+
console.error("Failed to fetch collaboration token:", error)
|
|
212
|
+
return null
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// TODO: as a developer, use the example JWT token provided in the Tiptap
|
|
217
|
+
// Cloud dashboard for local development only. In production, implement an API
|
|
218
|
+
// endpoint that generates a new JWT token in the server. Then, call that API
|
|
219
|
+
// endpoint from this function.
|
|
220
|
+
// When you've implemented the API endpoint, remove the code below.
|
|
221
|
+
if (!TIPTAP_COLLAB_TOKEN) {
|
|
222
|
+
alert(`Set up your environment variables to connect to Tiptap Cloud:
|
|
223
|
+
- NEXT_PUBLIC_TIPTAP_COLLAB_DOC_PREFIX - Prefix for identifying collaborative documents
|
|
224
|
+
- NEXT_PUBLIC_TIPTAP_COLLAB_APP_ID - Your Document Server App ID
|
|
225
|
+
- NEXT_PUBLIC_TIPTAP_COLLAB_TOKEN - JWT token for accessing Collaboration services (do not use in production)
|
|
226
|
+
- NEXT_PUBLIC_TIPTAP_AI_APP_ID - Your AI App ID
|
|
227
|
+
- NEXT_PUBLIC_TIPTAP_AI_TOKEN - JWT token for accessing AI services (do not use in production)
|
|
228
|
+
Follow this guide: https://tiptap.dev/docs/ui-components/templates/notion-like-editor`)
|
|
229
|
+
} else {
|
|
230
|
+
console.warn(
|
|
231
|
+
"You are using the example JWT token provided in the Tiptap Cloud dashboard. This is only for local development and should not be used in production. In production, implement an API endpoint that generates a new JWT token in the server, and call that API endpoint from the fetchCollabToken function. More info in the docs: https://tiptap.dev/docs/ui-components/templates/notion-like-editor"
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// A hardcoded token for demonstration purposes.
|
|
236
|
+
// TODO: remove this in production and use the API endpoint instead
|
|
237
|
+
return TIPTAP_COLLAB_TOKEN
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Fetch AI JWT token from the API
|
|
242
|
+
*/
|
|
243
|
+
export const fetchAiToken = async () => {
|
|
244
|
+
if (USE_JWT_TOKEN_API_ENDPOINT) {
|
|
245
|
+
try {
|
|
246
|
+
// Example API endpoint that returns a JWT token.
|
|
247
|
+
// TODO: implement this API endpoint in your app
|
|
248
|
+
const response = await fetch(`/api/ai`, {
|
|
249
|
+
method: "POST",
|
|
250
|
+
headers: {
|
|
251
|
+
"Content-Type": "application/json",
|
|
252
|
+
},
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
if (!response.ok) {
|
|
256
|
+
throw new Error(`Failed to fetch token: ${response.status}`)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const data = await response.json()
|
|
260
|
+
return data.token
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error("Failed to fetch AI token:", error)
|
|
263
|
+
return null
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// TODO: as a developer, use the example JWT token provided in the Tiptap
|
|
268
|
+
// Cloud dashboard for local development only. In production, implement an API
|
|
269
|
+
// endpoint that generates a new JWT token in the server. Then, call that API
|
|
270
|
+
// endpoint from this function.
|
|
271
|
+
// When you've implemented the API endpoint, remove the code below.
|
|
272
|
+
if (!TIPTAP_AI_TOKEN) {
|
|
273
|
+
alert(`Set up your environment variables to connect to Tiptap Cloud:
|
|
274
|
+
- NEXT_PUBLIC_TIPTAP_COLLAB_DOC_PREFIX - Prefix for identifying collaborative documents
|
|
275
|
+
- NEXT_PUBLIC_TIPTAP_COLLAB_APP_ID - Your Document Server App ID
|
|
276
|
+
- NEXT_PUBLIC_TIPTAP_COLLAB_TOKEN - JWT token for accessing Collaboration services (do not use in production)
|
|
277
|
+
- NEXT_PUBLIC_TIPTAP_AI_APP_ID - Your AI App ID
|
|
278
|
+
- NEXT_PUBLIC_TIPTAP_AI_TOKEN - JWT token for accessing AI services (do not use in production)
|
|
279
|
+
Follow this guide: https://tiptap.dev/docs/ui-components/templates/notion-like-editor`)
|
|
280
|
+
} else {
|
|
281
|
+
console.warn(
|
|
282
|
+
"You are using the example JWT token provided in the Tiptap Cloud dashboard. This is only for local development and should not be used in production. In production, implement an API endpoint that generates a new JWT token in the server, and call that API endpoint from the fetchAiToken function. More info in the docs: https://tiptap.dev/docs/ui-components/templates/notion-like-editor"
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// A hardcoded token for demonstration purposes.
|
|
287
|
+
// TODO: remove this in production and use the API endpoint instead
|
|
288
|
+
return TIPTAP_AI_TOKEN
|
|
289
|
+
}
|