@opentiny/fluent-editor 4.0.0-alpha.9 → 4.0.0-beta.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/README.md +88 -88
- package/es/attributors/line-height.es.js.map +1 -1
- package/es/config/base64-image.es.js.map +1 -1
- package/es/config/editor.config.es.js +27 -0
- package/es/config/editor.config.es.js.map +1 -1
- package/es/config/editor.utils.es.js.map +1 -1
- package/es/config/i18n/en-us.es.js +2 -0
- package/es/config/i18n/en-us.es.js.map +1 -1
- package/es/config/i18n/zh-cn.es.js +2 -0
- package/es/config/i18n/zh-cn.es.js.map +1 -1
- package/es/config/index.es.js +3 -1
- package/es/config/index.es.js.map +1 -1
- package/es/core/fluent-editor.es.js.map +1 -1
- package/es/fluent-editor.es.js +17 -13
- package/es/fluent-editor.es.js.map +1 -1
- package/es/formats/emoji.es.js.map +1 -1
- package/es/formats/soft-break.es.js.map +1 -1
- package/es/formats/strike.es.js.map +1 -1
- package/es/formats/video.es.js.map +1 -1
- package/es/index.es.js +35 -2
- package/es/index.es.js.map +1 -1
- package/es/modules/ai/constants.es.js.map +1 -1
- package/es/modules/ai/icons.es.js.map +1 -1
- package/es/modules/ai/index.es.js +1 -1
- package/es/modules/ai/index.es.js.map +1 -1
- package/es/modules/collaborative-editing/awareness/awareness.es.js +6 -7
- package/es/modules/collaborative-editing/awareness/awareness.es.js.map +1 -1
- package/es/modules/collaborative-editing/awareness/y-indexeddb.es.js +7 -3
- package/es/modules/collaborative-editing/awareness/y-indexeddb.es.js.map +1 -1
- package/es/modules/collaborative-editing/collaborative-editing.es.js +13 -8
- package/es/modules/collaborative-editing/collaborative-editing.es.js.map +1 -1
- package/es/modules/collaborative-editing/module.es.js.map +1 -1
- package/es/modules/collaborative-editing/provider/providerRegistry.es.js.map +1 -1
- package/es/modules/collaborative-editing/provider/webrtc.es.js +8 -4
- package/es/modules/collaborative-editing/provider/webrtc.es.js.map +1 -1
- package/es/modules/collaborative-editing/provider/websocket.es.js +6 -4
- package/es/modules/collaborative-editing/provider/websocket.es.js.map +1 -1
- package/es/modules/counter.es.js.map +1 -1
- package/es/modules/custom-clipboard.es.js.map +1 -1
- package/es/modules/custom-image/actions/action.es.js.map +1 -1
- package/es/modules/custom-image/actions/custom-resize-action.es.js.map +1 -1
- package/es/modules/custom-image/actions/delete-action.es.js.map +1 -1
- package/es/modules/custom-image/actions/image-toolbar-buttons.es.js +1 -1
- package/es/modules/custom-image/actions/image-toolbar-buttons.es.js.map +1 -1
- package/es/modules/custom-image/actions/toolbar-action.es.js.map +1 -1
- package/es/modules/custom-image/actions/toolbar.es.js.map +1 -1
- package/es/modules/custom-image/blot-formatter.es.js +1 -1
- package/es/modules/custom-image/blot-formatter.es.js.map +1 -1
- package/es/modules/custom-image/image.es.js.map +1 -1
- package/es/modules/custom-image/options.es.js.map +1 -1
- package/es/modules/custom-image/specs/blot-spec.es.js.map +1 -1
- package/es/modules/custom-image/specs/custom-image-spec.es.js.map +1 -1
- package/es/modules/custom-image/specs/image-spec.es.js.map +1 -1
- package/es/modules/custom-uploader.es.js.map +1 -1
- package/es/modules/divider.es.js.map +1 -1
- package/es/modules/emoji.es.js +1 -1
- package/es/modules/emoji.es.js.map +1 -1
- package/es/modules/file/formats/file.es.js.map +1 -1
- package/es/modules/file/modules/file-bar.es.js.map +1 -1
- package/es/modules/file/modules/file-module.es.js.map +1 -1
- package/es/modules/flow-chart/config-utils.es.js +102 -0
- package/es/modules/flow-chart/config-utils.es.js.map +1 -0
- package/es/modules/flow-chart/formats/flow-chart-blot.es.js +369 -0
- package/es/modules/flow-chart/formats/flow-chart-blot.es.js.map +1 -0
- package/es/modules/flow-chart/i18n/en-us.es.js +30 -0
- package/es/modules/flow-chart/i18n/en-us.es.js.map +1 -0
- package/es/modules/flow-chart/i18n/index.es.js +12 -0
- package/es/modules/flow-chart/i18n/index.es.js.map +1 -0
- package/es/modules/flow-chart/i18n/zh-cn.es.js +30 -0
- package/es/modules/flow-chart/i18n/zh-cn.es.js.map +1 -0
- package/es/modules/flow-chart/icons.es.js +27 -0
- package/es/modules/flow-chart/icons.es.js.map +1 -0
- package/es/modules/flow-chart/index.es.js +45 -0
- package/es/modules/flow-chart/index.es.js.map +1 -0
- package/es/modules/flow-chart/modules/context-menu.es.js +184 -0
- package/es/modules/flow-chart/modules/context-menu.es.js.map +1 -0
- package/es/modules/flow-chart/modules/control-panel.es.js +286 -0
- package/es/modules/flow-chart/modules/control-panel.es.js.map +1 -0
- package/es/modules/flow-chart/modules/custom-resize-action.es.js +150 -0
- package/es/modules/flow-chart/modules/custom-resize-action.es.js.map +1 -0
- package/es/modules/i18n.es.js.map +1 -1
- package/es/modules/index.es.js +4 -0
- package/es/modules/index.es.js.map +1 -1
- package/es/modules/link/formats/link.es.js.map +1 -1
- package/es/modules/link/modules/tooltip.es.js.map +1 -1
- package/es/modules/mathlive/formats.es.js.map +1 -1
- package/es/modules/mathlive/module.es.js.map +1 -1
- package/es/modules/mathlive/tooltip.es.js.map +1 -1
- package/es/modules/mention/constants.es.js.map +1 -1
- package/es/modules/mention/mention-link.es.js.map +1 -1
- package/es/modules/mention/mention.es.js.map +1 -1
- package/es/modules/mind-map/config-utils.es.js +108 -0
- package/es/modules/mind-map/config-utils.es.js.map +1 -0
- package/es/modules/mind-map/formats/mind-map-blot.es.js +356 -0
- package/es/modules/mind-map/formats/mind-map-blot.es.js.map +1 -0
- package/es/modules/mind-map/i18n/en-us.es.js +29 -0
- package/es/modules/mind-map/i18n/en-us.es.js.map +1 -0
- package/es/modules/mind-map/i18n/index.es.js +12 -0
- package/es/modules/mind-map/i18n/index.es.js.map +1 -0
- package/es/modules/mind-map/i18n/zh-cn.es.js +29 -0
- package/es/modules/mind-map/i18n/zh-cn.es.js.map +1 -0
- package/es/modules/mind-map/icons.es.js +45 -0
- package/es/modules/mind-map/icons.es.js.map +1 -0
- package/es/modules/mind-map/index.es.js +56 -0
- package/es/modules/mind-map/index.es.js.map +1 -0
- package/es/modules/mind-map/modules/context-menu.es.js +128 -0
- package/es/modules/mind-map/modules/context-menu.es.js.map +1 -0
- package/es/modules/mind-map/modules/control-panel.es.js +425 -0
- package/es/modules/mind-map/modules/control-panel.es.js.map +1 -0
- package/es/modules/mind-map/modules/custom-resize-action.es.js +161 -0
- package/es/modules/mind-map/modules/custom-resize-action.es.js.map +1 -0
- package/es/modules/shortcut-key/index.es.js +16 -0
- package/es/modules/shortcut-key/index.es.js.map +1 -1
- package/es/modules/syntax.es.js.map +1 -1
- package/es/modules/table-up/index.es.js.map +1 -1
- package/es/modules/toolbar/better-picker.es.js.map +1 -1
- package/es/modules/toolbar/better-toolbar.es.js.map +1 -1
- package/es/modules/toolbar/toolbar-tip.es.js.map +1 -1
- package/es/themes/snow.es.js.map +1 -1
- package/es/tools/format-painter.es.js.map +1 -1
- package/es/tools/fullscreen.es.js.map +1 -1
- package/es/tools/screenshot.es.js.map +1 -1
- package/es/ui/icons.config.es.js +4 -0
- package/es/ui/icons.config.es.js.map +1 -1
- package/es/ui/icons.es.js +4 -2
- package/es/ui/icons.es.js.map +1 -1
- package/es/utils/debounce.es.js.map +1 -1
- package/es/utils/image.es.js.map +1 -1
- package/es/utils/is.es.js.map +1 -1
- package/es/utils/merge.es.js +27 -0
- package/es/utils/merge.es.js.map +1 -0
- package/es/utils/method.es.js.map +1 -1
- package/es/utils/scroll-lock.es.js.map +1 -1
- package/flow-chart.css +185 -0
- package/lib/attributors/line-height.cjs.js.map +1 -1
- package/lib/config/base64-image.cjs.js.map +1 -1
- package/lib/config/editor.config.cjs.js +27 -0
- package/lib/config/editor.config.cjs.js.map +1 -1
- package/lib/config/editor.utils.cjs.js.map +1 -1
- package/lib/config/i18n/en-us.cjs.js +2 -0
- package/lib/config/i18n/en-us.cjs.js.map +1 -1
- package/lib/config/i18n/zh-cn.cjs.js +2 -0
- package/lib/config/i18n/zh-cn.cjs.js.map +1 -1
- package/lib/config/index.cjs.js +2 -0
- package/lib/config/index.cjs.js.map +1 -1
- package/lib/core/fluent-editor.cjs.js.map +1 -1
- package/lib/fluent-editor.cjs.js +23 -19
- package/lib/fluent-editor.cjs.js.map +1 -1
- package/lib/formats/emoji.cjs.js.map +1 -1
- package/lib/formats/soft-break.cjs.js.map +1 -1
- package/lib/formats/strike.cjs.js.map +1 -1
- package/lib/formats/video.cjs.js.map +1 -1
- package/lib/index.cjs.js +39 -6
- package/lib/index.cjs.js.map +1 -1
- package/lib/modules/ai/constants.cjs.js.map +1 -1
- package/lib/modules/ai/icons.cjs.js.map +1 -1
- package/lib/modules/ai/index.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/awareness/awareness.cjs.js +6 -24
- package/lib/modules/collaborative-editing/awareness/awareness.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/awareness/y-indexeddb.cjs.js +7 -3
- package/lib/modules/collaborative-editing/awareness/y-indexeddb.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/collaborative-editing.cjs.js +19 -31
- package/lib/modules/collaborative-editing/collaborative-editing.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/module.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/provider/providerRegistry.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/provider/webrtc.cjs.js +10 -23
- package/lib/modules/collaborative-editing/provider/webrtc.cjs.js.map +1 -1
- package/lib/modules/collaborative-editing/provider/websocket.cjs.js +10 -25
- package/lib/modules/collaborative-editing/provider/websocket.cjs.js.map +1 -1
- package/lib/modules/counter.cjs.js.map +1 -1
- package/lib/modules/custom-clipboard.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/action.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/custom-resize-action.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/delete-action.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/image-toolbar-buttons.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/toolbar-action.cjs.js.map +1 -1
- package/lib/modules/custom-image/actions/toolbar.cjs.js.map +1 -1
- package/lib/modules/custom-image/blot-formatter.cjs.js +2 -2
- package/lib/modules/custom-image/blot-formatter.cjs.js.map +1 -1
- package/lib/modules/custom-image/image.cjs.js.map +1 -1
- package/lib/modules/custom-image/options.cjs.js.map +1 -1
- package/lib/modules/custom-image/specs/blot-spec.cjs.js.map +1 -1
- package/lib/modules/custom-image/specs/custom-image-spec.cjs.js.map +1 -1
- package/lib/modules/custom-image/specs/image-spec.cjs.js.map +1 -1
- package/lib/modules/custom-uploader.cjs.js.map +1 -1
- package/lib/modules/divider.cjs.js.map +1 -1
- package/lib/modules/emoji.cjs.js +2 -2
- package/lib/modules/emoji.cjs.js.map +1 -1
- package/lib/modules/file/formats/file.cjs.js.map +1 -1
- package/lib/modules/file/modules/file-bar.cjs.js.map +1 -1
- package/lib/modules/file/modules/file-module.cjs.js.map +1 -1
- package/lib/modules/flow-chart/config-utils.cjs.js +102 -0
- package/lib/modules/flow-chart/config-utils.cjs.js.map +1 -0
- package/lib/modules/flow-chart/formats/flow-chart-blot.cjs.js +369 -0
- package/lib/modules/flow-chart/formats/flow-chart-blot.cjs.js.map +1 -0
- package/lib/modules/flow-chart/i18n/en-us.cjs.js +30 -0
- package/lib/modules/flow-chart/i18n/en-us.cjs.js.map +1 -0
- package/lib/modules/flow-chart/i18n/index.cjs.js +12 -0
- package/lib/modules/flow-chart/i18n/index.cjs.js.map +1 -0
- package/lib/modules/flow-chart/i18n/zh-cn.cjs.js +30 -0
- package/lib/modules/flow-chart/i18n/zh-cn.cjs.js.map +1 -0
- package/lib/modules/flow-chart/icons.cjs.js +27 -0
- package/lib/modules/flow-chart/icons.cjs.js.map +1 -0
- package/lib/modules/flow-chart/index.cjs.js +45 -0
- package/lib/modules/flow-chart/index.cjs.js.map +1 -0
- package/lib/modules/flow-chart/modules/context-menu.cjs.js +184 -0
- package/lib/modules/flow-chart/modules/context-menu.cjs.js.map +1 -0
- package/lib/modules/flow-chart/modules/control-panel.cjs.js +286 -0
- package/lib/modules/flow-chart/modules/control-panel.cjs.js.map +1 -0
- package/lib/modules/flow-chart/modules/custom-resize-action.cjs.js +150 -0
- package/lib/modules/flow-chart/modules/custom-resize-action.cjs.js.map +1 -0
- package/lib/modules/i18n.cjs.js.map +1 -1
- package/lib/modules/index.cjs.js +9 -5
- package/lib/modules/index.cjs.js.map +1 -1
- package/lib/modules/link/formats/link.cjs.js.map +1 -1
- package/lib/modules/link/modules/tooltip.cjs.js.map +1 -1
- package/lib/modules/mathlive/formats.cjs.js.map +1 -1
- package/lib/modules/mathlive/module.cjs.js.map +1 -1
- package/lib/modules/mathlive/tooltip.cjs.js.map +1 -1
- package/lib/modules/mention/constants.cjs.js.map +1 -1
- package/lib/modules/mention/mention-link.cjs.js.map +1 -1
- package/lib/modules/mention/mention.cjs.js.map +1 -1
- package/lib/modules/mind-map/config-utils.cjs.js +108 -0
- package/lib/modules/mind-map/config-utils.cjs.js.map +1 -0
- package/lib/modules/mind-map/formats/mind-map-blot.cjs.js +356 -0
- package/lib/modules/mind-map/formats/mind-map-blot.cjs.js.map +1 -0
- package/lib/modules/mind-map/i18n/en-us.cjs.js +29 -0
- package/lib/modules/mind-map/i18n/en-us.cjs.js.map +1 -0
- package/lib/modules/mind-map/i18n/index.cjs.js +12 -0
- package/lib/modules/mind-map/i18n/index.cjs.js.map +1 -0
- package/lib/modules/mind-map/i18n/zh-cn.cjs.js +29 -0
- package/lib/modules/mind-map/i18n/zh-cn.cjs.js.map +1 -0
- package/lib/modules/mind-map/icons.cjs.js +45 -0
- package/lib/modules/mind-map/icons.cjs.js.map +1 -0
- package/lib/modules/mind-map/index.cjs.js +56 -0
- package/lib/modules/mind-map/index.cjs.js.map +1 -0
- package/lib/modules/mind-map/modules/context-menu.cjs.js +128 -0
- package/lib/modules/mind-map/modules/context-menu.cjs.js.map +1 -0
- package/lib/modules/mind-map/modules/control-panel.cjs.js +425 -0
- package/lib/modules/mind-map/modules/control-panel.cjs.js.map +1 -0
- package/lib/modules/mind-map/modules/custom-resize-action.cjs.js +161 -0
- package/lib/modules/mind-map/modules/custom-resize-action.cjs.js.map +1 -0
- package/lib/modules/shortcut-key/index.cjs.js +16 -0
- package/lib/modules/shortcut-key/index.cjs.js.map +1 -1
- package/lib/modules/syntax.cjs.js.map +1 -1
- package/lib/modules/table-up/index.cjs.js.map +1 -1
- package/lib/modules/toolbar/better-picker.cjs.js.map +1 -1
- package/lib/modules/toolbar/better-toolbar.cjs.js.map +1 -1
- package/lib/modules/toolbar/toolbar-tip.cjs.js.map +1 -1
- package/lib/themes/snow.cjs.js.map +1 -1
- package/lib/tools/format-painter.cjs.js.map +1 -1
- package/lib/tools/fullscreen.cjs.js.map +1 -1
- package/lib/tools/screenshot.cjs.js.map +1 -1
- package/lib/ui/icons.cjs.js +3 -1
- package/lib/ui/icons.cjs.js.map +1 -1
- package/lib/ui/icons.config.cjs.js +4 -0
- package/lib/ui/icons.config.cjs.js.map +1 -1
- package/lib/utils/debounce.cjs.js.map +1 -1
- package/lib/utils/image.cjs.js.map +1 -1
- package/lib/utils/is.cjs.js.map +1 -1
- package/lib/utils/merge.cjs.js +27 -0
- package/lib/utils/merge.cjs.js.map +1 -0
- package/lib/utils/method.cjs.js.map +1 -1
- package/lib/utils/scroll-lock.cjs.js.map +1 -1
- package/mind-map.css +224 -0
- package/package.json +45 -67
- package/patches/quill@2.0.3.patch +33 -0
- package/scripts/apply-patches.cjs +248 -0
- package/style.css +4 -2
- package/types/attributors/font-size.d.ts +1 -1
- package/types/attributors/font-style.d.ts +1 -1
- package/types/attributors/index.d.ts +4 -4
- package/types/attributors/line-height.d.ts +1 -1
- package/types/attributors/text-indent.d.ts +1 -1
- package/types/config/base64-image.d.ts +2 -2
- package/types/config/editor.config.d.ts +55 -11
- package/types/config/editor.utils.d.ts +40 -40
- package/types/config/i18n/en-us.d.ts +125 -123
- package/types/config/i18n/zh-cn.d.ts +125 -123
- package/types/config/index.d.ts +7 -7
- package/types/config/types/editor-config.interface.d.ts +11 -12
- package/types/config/types/editor-modules.interface.d.ts +40 -37
- package/types/config/types/index.d.ts +3 -3
- package/types/config/types/type.d.ts +2 -2
- package/types/core/fluent-editor.d.ts +10 -11
- package/types/fluent-editor.d.ts +1 -2
- package/types/formats/emoji.d.ts +7 -8
- package/types/formats/index.d.ts +4 -4
- package/types/formats/soft-break.d.ts +11 -12
- package/types/formats/strike.d.ts +7 -8
- package/types/formats/video.d.ts +12 -13
- package/types/index.d.ts +7 -8
- package/types/modules/ai/constants.d.ts +30 -30
- package/types/modules/ai/icons.d.ts +21 -21
- package/types/modules/ai/index.d.ts +93 -94
- package/types/modules/ai/types.d.ts +16 -16
- package/types/modules/collaborative-editing/awareness/awareness.d.ts +25 -26
- package/types/modules/collaborative-editing/awareness/index.d.ts +2 -2
- package/types/modules/collaborative-editing/awareness/y-indexeddb.d.ts +3 -3
- package/types/modules/collaborative-editing/collaborative-editing.d.ts +22 -22
- package/types/modules/collaborative-editing/index.d.ts +2 -2
- package/types/modules/collaborative-editing/module.d.ts +10 -11
- package/types/modules/collaborative-editing/provider/index.d.ts +3 -3
- package/types/modules/collaborative-editing/provider/providerRegistry.d.ts +25 -25
- package/types/modules/collaborative-editing/provider/webrtc.d.ts +35 -35
- package/types/modules/collaborative-editing/provider/websocket.d.ts +39 -39
- package/types/modules/collaborative-editing/types.d.ts +51 -35
- package/types/modules/counter.d.ts +21 -22
- package/types/modules/custom-clipboard.d.ts +23 -24
- package/types/modules/custom-image/actions/action.d.ts +7 -8
- package/types/modules/custom-image/actions/custom-resize-action.d.ts +22 -23
- package/types/modules/custom-image/actions/delete-action.d.ts +5 -6
- package/types/modules/custom-image/actions/image-toolbar-buttons.d.ts +15 -16
- package/types/modules/custom-image/actions/index.d.ts +6 -6
- package/types/modules/custom-image/actions/toolbar-action.d.ts +7 -8
- package/types/modules/custom-image/actions/toolbar.d.ts +16 -17
- package/types/modules/custom-image/blot-formatter.d.ts +19 -20
- package/types/modules/custom-image/image.d.ts +26 -27
- package/types/modules/custom-image/index.d.ts +4 -4
- package/types/modules/custom-image/options.d.ts +45 -46
- package/types/modules/custom-image/specs/blot-spec.d.ts +10 -11
- package/types/modules/custom-image/specs/custom-image-spec.d.ts +15 -16
- package/types/modules/custom-image/specs/image-spec.d.ts +7 -8
- package/types/modules/custom-image/specs/index.d.ts +3 -3
- package/types/modules/custom-uploader.d.ts +37 -38
- package/types/modules/divider.d.ts +7 -8
- package/types/modules/emoji.d.ts +35 -36
- package/types/modules/file/formats/file.d.ts +17 -18
- package/types/modules/file/index.d.ts +3 -3
- package/types/modules/file/modules/file-bar.d.ts +14 -14
- package/types/modules/file/modules/file-module.d.ts +7 -8
- package/types/modules/flow-chart/config-utils.d.ts +10 -0
- package/types/modules/flow-chart/formats/flow-chart-blot.d.ts +43 -0
- package/types/modules/flow-chart/i18n/en-us.d.ts +26 -0
- package/types/modules/flow-chart/i18n/index.d.ts +1 -0
- package/types/modules/flow-chart/i18n/zh-cn.d.ts +26 -0
- package/types/modules/flow-chart/icons.d.ts +12 -0
- package/types/modules/flow-chart/index.d.ts +10 -0
- package/types/modules/flow-chart/modules/context-menu.d.ts +3 -0
- package/types/modules/flow-chart/modules/control-panel.d.ts +3 -0
- package/types/modules/flow-chart/modules/custom-resize-action.d.ts +22 -0
- package/types/modules/flow-chart/options.d.ts +29 -0
- package/types/modules/i18n.d.ts +13 -14
- package/types/modules/index.d.ts +18 -16
- package/types/modules/link/formats/link.d.ts +14 -15
- package/types/modules/link/index.d.ts +2 -2
- package/types/modules/link/modules/tooltip.d.ts +25 -26
- package/types/modules/mathlive/formats.d.ts +20 -21
- package/types/modules/mathlive/index.d.ts +3 -3
- package/types/modules/mathlive/module.d.ts +7 -8
- package/types/modules/mathlive/tooltip.d.ts +14 -15
- package/types/modules/mention/constants.d.ts +3 -3
- package/types/modules/mention/index.d.ts +2 -2
- package/types/modules/mention/mention-link.d.ts +14 -15
- package/types/modules/mention/mention.d.ts +52 -53
- package/types/modules/mind-map/config-utils.d.ts +12 -0
- package/types/modules/mind-map/formats/mind-map-blot.d.ts +44 -0
- package/types/modules/mind-map/i18n/en-us.d.ts +25 -0
- package/types/modules/mind-map/i18n/index.d.ts +1 -0
- package/types/modules/mind-map/i18n/zh-cn.d.ts +25 -0
- package/types/modules/mind-map/icons.d.ts +21 -0
- package/types/modules/mind-map/index.d.ts +10 -0
- package/types/modules/mind-map/modules/context-menu.d.ts +3 -0
- package/types/modules/mind-map/modules/control-panel.d.ts +3 -0
- package/types/modules/mind-map/modules/custom-resize-action.d.ts +23 -0
- package/types/modules/mind-map/options.d.ts +27 -0
- package/types/modules/shortcut-key/index.d.ts +67 -68
- package/types/modules/syntax.d.ts +12 -13
- package/types/modules/table-up/index.d.ts +32 -33
- package/types/modules/toolbar/better-picker.d.ts +13 -14
- package/types/modules/toolbar/better-toolbar.d.ts +6 -7
- package/types/modules/toolbar/index.d.ts +3 -3
- package/types/modules/toolbar/toolbar-tip.d.ts +7 -8
- package/types/themes/snow.d.ts +9 -10
- package/types/tools/format-painter.d.ts +12 -13
- package/types/tools/fullscreen.d.ts +4 -5
- package/types/tools/screenshot.d.ts +17 -18
- package/types/ui/icons.config.d.ts +40 -38
- package/types/ui/icons.d.ts +6 -6
- package/types/utils/debounce.d.ts +6 -6
- package/types/utils/image.d.ts +1 -1
- package/types/utils/is.d.ts +6 -6
- package/types/utils/merge.d.ts +7 -0
- package/types/utils/method.d.ts +6 -6
- package/types/utils/scroll-lock.d.ts +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../../../../src/modules/ai/index.ts"],"sourcesContent":["import type TypeToolbar from 'quill/modules/toolbar'\r\nimport type FluentEditor from '../../core/fluent-editor'\r\nimport type { AIOptions, OperationMenuItem, ResultMenuItem } from './types'\r\nimport {\r\n CLOSE,\r\n INPUT_PLACEHOLDER,\r\n INSERT_SUB_CONTENT_TEXT,\r\n INSERT_TEXT,\r\n MENU_ID_MAP,\r\n MENU_TITLE_DATA,\r\n REGENERATE,\r\n REPLACE_SELECT,\r\n RESULT_HEADER_TEXT,\r\n SELECT_PLACEHOLDER,\r\n STOP_ANSWER,\r\n THINK_TEXT,\r\n} from './constants'\r\nimport {\r\n ADJUST_ICON,\r\n AI_ICON,\r\n CALL_ICON,\r\n CLOSE_ICON,\r\n COPY_ICON,\r\n EDITOR_ICON,\r\n INSERT_ICON,\r\n MENU_CLOSE_ICON,\r\n REBUILD_ICON,\r\n REFRESH_ICON,\r\n REPLACE_SELECT_ICON,\r\n RIGHT_ARROW_ICON,\r\n SEND_BTN_ICON,\r\n STOP_ICON,\r\n THINK_ICON,\r\n} from './icons'\r\n\r\nexport class AI {\r\n toolbar: TypeToolbar\r\n host: string\r\n apiKey: string\r\n model: string\r\n message: string\r\n isBreak: boolean = false // 打断标记\r\n textNumber: number // 文本字数限制\r\n private _isSelectRangeMode: boolean = false // 选择/点击模式\r\n private _charCount: number = 0 // 文本字数\r\n private _debounceTimer = null\r\n private _inputPlaceholder: string = ''\r\n private _showOperationMenu: boolean = false\r\n private _isThinking: boolean = false // 思考中\r\n private _showResultPopupEl: boolean = false // 结果弹窗\r\n selectedText: string = '' // 选择的文本\r\n inputValue: string = '' // 存储输入框的值\r\n resultMenuList: ResultMenuItem[] = []\r\n operationMenuList: OperationMenuItem[] = []\r\n private _operationMenuItemList: OperationMenuItem[] = []\r\n\r\n private alertEl: HTMLDivElement | null = null\r\n private alertTimer: number | null = null\r\n private selectionBubbleEl: HTMLDivElement | null = null\r\n private selectionRange: any = null\r\n private dialogContainerEl: HTMLDivElement | null = null\r\n private wrapContainerEl: HTMLDivElement | null = null\r\n private aiIconEl: HTMLSpanElement | null = null\r\n private inputContainerEl: HTMLDivElement | null = null\r\n private inputEl: HTMLInputElement | null = null\r\n private menuContainerEl: HTMLDivElement | null = null\r\n private subMenuEl: HTMLDivElement | null = null\r\n private subMenuEditorEl: HTMLDivElement | null = null\r\n private subMenuToneEl: HTMLDivElement | null = null\r\n private subMenuAdjustEl: HTMLDivElement | null = null\r\n private inputRightEl: HTMLDivElement | null = null\r\n private inputSendBtnEl: HTMLSpanElement | null = null\r\n private inputCloseBtnEl: HTMLSpanElement | null = null\r\n private thinkContainerEl: HTMLDivElement | null = null // 思考元素\r\n private thinkBtnEl: HTMLDivElement | null = null\r\n private resultPopupEl: HTMLDivElement | null = null\r\n private resultPopupHeaderEl: HTMLDivElement | null = null\r\n private resultPopupContentEl: HTMLDivElement | null = null\r\n private resultPopupFooterEl: HTMLDivElement | null = null\r\n private resultPopupFooterTextEl: HTMLSpanElement | null = null\r\n private resultRefreshBtnEl: HTMLSpanElement | null = null\r\n private resultCopyBtnEl: HTMLSpanElement | null = null\r\n // 分享和朗读功能待放开\r\n // private resultShareBtnEl: HTMLSpanElement | null = null\r\n // private resultVoiceBtnEl: HTMLSpanElement | null = null\r\n private actionMenuEl: HTMLDivElement | null = null\r\n\r\n constructor(\r\n public quill: FluentEditor,\r\n public options: AIOptions,\r\n ) {\r\n this.quill = quill\r\n this.toolbar = quill.getModule('toolbar') as TypeToolbar\r\n // 添加AI按钮到工具栏\r\n if (typeof this.toolbar !== 'undefined') {\r\n this.toolbar.addHandler('ai', this.showAIInput.bind(this))\r\n }\r\n\r\n this.quill.on('selection-change', this.handleSelectionChange.bind(this))\r\n\r\n this.host = options.host || 'https://api.deepseek.com/v1'\r\n this.apiKey = options.apiKey\r\n this.model = options.model || 'deepseek-chat'\r\n this.textNumber = options.contentMaxLength || 5000\r\n\r\n this.resultMenuList = [\r\n { text: REPLACE_SELECT, icon: REPLACE_SELECT_ICON },\r\n { text: INSERT_TEXT, icon: INSERT_ICON, selectText: INSERT_SUB_CONTENT_TEXT },\r\n { text: REGENERATE, icon: REBUILD_ICON },\r\n { text: CLOSE, icon: MENU_CLOSE_ICON },\r\n ]\r\n\r\n this.operationMenuList = [\r\n { id: 'editor', text: '编辑调整内容', icon: EDITOR_ICON },\r\n { id: 'tone', text: '改写口吻', icon: CALL_ICON },\r\n { id: 'adjust', text: '整理选区内容', icon: ADJUST_ICON },\r\n ]\r\n }\r\n\r\n // 工具栏启动\r\n showAIInput() {\r\n // 创建输入框和结果弹窗\r\n this.create()\r\n\r\n this.selectionRange = this.quill.getSelection()\r\n if (this.selectionRange.length) {\r\n this.isSelectRangeMode = true\r\n }\r\n else {\r\n this.isSelectRangeMode = false\r\n }\r\n // 定位到编辑器焦点位置\r\n this.positionElements()\r\n\r\n // 添加ESC键监听\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') {\r\n this.closeAIPanel()\r\n this.quill.container.removeEventListener('keydown', handleKeyDown)\r\n }\r\n }\r\n this.quill.container.addEventListener('keydown', handleKeyDown)\r\n }\r\n\r\n // 气泡启动\r\n private selectTextEvent() {\r\n if (!this.selectionRange) return\r\n this.create()\r\n // 定位到编辑器焦点位置\r\n this.positionElements()\r\n\r\n this.isSelectRangeMode = true\r\n }\r\n\r\n private create() {\r\n this.createResultElement()\r\n this.createOperationMenuElements()\r\n this.createInputBoxElements()\r\n\r\n // 创建事件监听\r\n this.addInputEvent()\r\n this.addResultEvent()\r\n this.handleActionMenuDisplay()\r\n // 添加到编辑器\r\n this.quill.container.appendChild(this.dialogContainerEl)\r\n }\r\n\r\n // 创建结果弹窗\r\n private createResultElement() {\r\n if (!this.resultPopupEl) {\r\n this.resultPopupEl = document.createElement('div')\r\n this.resultPopupEl.className = 'ql-ai-result'\r\n this.resultPopupHeaderEl = document.createElement('div')\r\n this.resultPopupHeaderEl.className = 'ql-ai-result-header'\r\n this.resultPopupHeaderEl.textContent = RESULT_HEADER_TEXT\r\n this.resultPopupContentEl = document.createElement('div')\r\n this.resultPopupContentEl.className = 'ql-ai-result-content'\r\n this.resultPopupFooterEl = document.createElement('div')\r\n this.resultPopupFooterEl.className = 'ql-ai-result-footer'\r\n this.resultPopupFooterTextEl = document.createElement('span')\r\n this.resultPopupFooterTextEl.className = 'ql-ai-result-footer-text'\r\n this.resultPopupFooterTextEl.textContent = `0`\r\n this.resultRefreshBtnEl = document.createElement('span')\r\n this.resultRefreshBtnEl.className = 'ql-ai-result-footer-refresh'\r\n this.resultRefreshBtnEl.innerHTML = REFRESH_ICON\r\n this.resultCopyBtnEl = document.createElement('span')\r\n this.resultCopyBtnEl.className = 'ql-ai-result-footer-copy'\r\n this.resultCopyBtnEl.innerHTML = COPY_ICON\r\n\r\n // 分享和朗读功能待放开\r\n // this.resultShareBtnEl = document.createElement('span')\r\n // this.resultShareBtnEl.className = 'ql-ai-result-footer-share'\r\n // this.resultShareBtnEl.innerHTML = SHARE_ICON\r\n // this.resultVoiceBtnEl = document.createElement('span')\r\n // this.resultVoiceBtnEl.className = 'ql-ai-result-footer-voice'\r\n // this.resultVoiceBtnEl.innerHTML = VOICE_ICON\r\n const resultFooterRightEl: HTMLDivElement = document.createElement('div')\r\n resultFooterRightEl.className = 'ql-ai-result-footer-right'\r\n resultFooterRightEl.appendChild(this.resultRefreshBtnEl)\r\n resultFooterRightEl.appendChild(this.resultCopyBtnEl)\r\n // 分享和朗读功能待放开\r\n // resultFooterRightEl.appendChild(this.resultShareBtnEl)\r\n // resultFooterRightEl.appendChild(this.resultVoiceBtnEl)\r\n this.resultPopupFooterEl.appendChild(this.resultPopupFooterTextEl)\r\n this.resultPopupFooterEl.appendChild(resultFooterRightEl)\r\n this.resultPopupEl.appendChild(this.resultPopupHeaderEl)\r\n this.resultPopupEl.appendChild(this.resultPopupContentEl)\r\n this.resultPopupEl.appendChild(this.resultPopupFooterEl)\r\n }\r\n this.showResultPopupEl = false\r\n }\r\n\r\n private createOperationMenuElements() {\r\n if (!this.menuContainerEl) {\r\n // 创建操作菜单容器\r\n this.menuContainerEl = document.createElement('div')\r\n this.menuContainerEl.className = 'ql-ai-menu-container'\r\n\r\n // 创建主菜单\r\n const mainMenu = document.createElement('div')\r\n mainMenu.className = 'ql-ai-main-menu'\r\n this.operationMenuList.forEach(({ text, icon, id }) => {\r\n const menuItem = document.createElement('div')\r\n menuItem.className = 'ql-ai-menu-item'\r\n menuItem.innerHTML = `${icon}<span>${text}</span>${RIGHT_ARROW_ICON}`\r\n menuItem.addEventListener('mouseenter', (e) => {\r\n e.stopPropagation()\r\n this.subMenuEl.style.display = 'block'\r\n this.subMenuEl.className = `ql-ai-sub-menu ${id}`\r\n this.createOperationMenuItem(id)\r\n })\r\n mainMenu.appendChild(menuItem)\r\n })\r\n if (!this.subMenuEl) {\r\n // 创建子菜单\r\n this.subMenuEl = document.createElement('div')\r\n this.subMenuEl.className = 'ql-ai-sub-menu'\r\n this.subMenuEl.style.display = 'none'\r\n }\r\n\r\n this.menuContainerEl.appendChild(mainMenu)\r\n this.menuContainerEl.appendChild(this.subMenuEl)\r\n }\r\n this.showOperationMenu = false\r\n }\r\n\r\n private createOperationMenuItem(id: string) {\r\n let menuItemBox = this[MENU_ID_MAP[id]]\r\n if (!menuItemBox) {\r\n menuItemBox = document.createElement('div')\r\n }\r\n // 清除子菜单容器中的所有子元素\r\n while (this.subMenuEl.firstChild) {\r\n this.subMenuEl.removeChild(this.subMenuEl.firstChild)\r\n }\r\n\r\n MENU_TITLE_DATA[id].forEach(({ text, icon, id }) => {\r\n const menuItem = document.createElement('div')\r\n menuItem.className = 'ql-ai-menu-item'\r\n menuItem.innerHTML = `${icon || ''}<span>${text}</span>`\r\n menuItem.addEventListener('click', (e) => {\r\n e.stopPropagation()\r\n this.handleOperationMenuItemClick(text, id)\r\n })\r\n menuItemBox.appendChild(menuItem)\r\n })\r\n this.subMenuEl.appendChild(menuItemBox)\r\n }\r\n\r\n private createInputBoxElements() {\r\n if (!this.dialogContainerEl) {\r\n this.dialogContainerEl = document.createElement('div')\r\n this.dialogContainerEl.className = 'ql-ai-dialog'\r\n this.wrapContainerEl = document.createElement('div')\r\n this.wrapContainerEl.className = 'ql-ai-wrapper'\r\n this.wrapContainerEl.style.width = `${this.quill.container.clientWidth - 30}px`\r\n\r\n // 添加AI图标\r\n this.createAIInputIcon()\r\n\r\n // 增加输入框\r\n this.inputEl = document.createElement('input')\r\n this.inputEl.type = 'text'\r\n this.inputPlaceholder = this._isSelectRangeMode ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER\r\n // 添加发送按钮\r\n this.inputSendBtnEl = document.createElement('span')\r\n this.inputSendBtnEl.className = 'ql-ai-input-right-send'\r\n this.inputSendBtnEl.innerHTML = SEND_BTN_ICON\r\n this.inputCloseBtnEl = document.createElement('span')\r\n this.inputCloseBtnEl.className = 'ql-ai-input-right-close'\r\n this.inputCloseBtnEl.innerHTML = CLOSE_ICON\r\n this.inputRightEl = document.createElement('div')\r\n this.inputRightEl.className = 'ql-ai-input-right'\r\n\r\n // 创建输入框\r\n this.inputContainerEl = document.createElement('div')\r\n this.inputContainerEl.className = 'ql-ai-input'\r\n this.inputContainerEl.appendChild(this.aiIconEl)\r\n this.inputContainerEl.appendChild(this.inputEl)\r\n this.inputRightEl.appendChild(this.inputSendBtnEl)\r\n this.inputRightEl.appendChild(this.inputCloseBtnEl)\r\n this.inputContainerEl.appendChild(this.inputRightEl) // 添加发送按钮\r\n this.wrapContainerEl.appendChild(this.resultPopupEl)\r\n this.wrapContainerEl.appendChild(this.inputContainerEl)\r\n this.wrapContainerEl.appendChild(this.menuContainerEl) // 添加菜单容器\r\n this.dialogContainerEl.appendChild(this.wrapContainerEl)\r\n }\r\n else {\r\n this.dialogContainerEl.style.display = 'block'\r\n }\r\n this.hiddenInputSendBtnEl()\r\n }\r\n\r\n private hiddenInputSendBtnEl(display = 'none') {\r\n if (this.inputEl && this.inputSendBtnEl) {\r\n this.inputSendBtnEl.style.display = display\r\n }\r\n }\r\n\r\n private copyResult() {\r\n if (!this.resultPopupContentEl) return\r\n\r\n try {\r\n const textToCopy = this.resultPopupContentEl.textContent || ''\r\n navigator.clipboard\r\n .writeText(textToCopy)\r\n .then(() => {\r\n this.showAlert('内容已复制到剪贴板')\r\n // 可以在这里添加复制成功的提示\r\n })\r\n .catch((err) => {\r\n this.showAlert(`复制失败:${err}`)\r\n })\r\n }\r\n catch (err) {\r\n this.showAlert(`复制失败:${err}`)\r\n // 兼容不支持clipboard API的浏览器\r\n const textarea = document.createElement('textarea')\r\n textarea.value = this.resultPopupContentEl.textContent || ''\r\n document.body.appendChild(textarea)\r\n textarea.select()\r\n document.execCommand('copy')\r\n document.body.removeChild(textarea)\r\n }\r\n }\r\n\r\n // 分享和朗读功能待放开\r\n // private shareResult() {\r\n // if (!this.resultPopupContentEl) return\r\n\r\n // const textToShare = this.resultPopupContentEl.textContent || ''\r\n // const title = 'AI生成内容分享'\r\n\r\n // if (navigator.share) {\r\n // navigator.share({\r\n // title,\r\n // text: textToShare,\r\n // })\r\n // .catch((err) => {\r\n // this.showAlert(`分享失败:${err}`)\r\n // })\r\n // }\r\n // else {\r\n // // 兼容不支持Web Share API的浏览器\r\n // const shareUrl = `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(textToShare)}`\r\n // window.open(shareUrl, '_blank')\r\n // }\r\n // }\r\n // private voiceResult() {\r\n // if (!this.resultPopupContentEl) return\r\n\r\n // const textToSpeak = this.resultPopupContentEl.textContent || ''\r\n\r\n // if ('speechSynthesis' in window) {\r\n // const utterance = new SpeechSynthesisUtterance(textToSpeak)\r\n // utterance.lang = 'zh-CN' // 设置中文语音\r\n // speechSynthesis.speak(utterance)\r\n // }\r\n // else {\r\n // this.showAlert('当前浏览器不支持语音合成API')\r\n // // 可以在这里添加不支持语音的提示\r\n // }\r\n // }\r\n\r\n private addResultEvent() {\r\n if (this.resultRefreshBtnEl) {\r\n this.resultRefreshBtnEl.addEventListener('click', () => {\r\n this.regenerateResponse()\r\n })\r\n }\r\n\r\n if (this.resultCopyBtnEl) {\r\n this.resultCopyBtnEl.addEventListener('click', () => {\r\n this.copyResult()\r\n })\r\n }\r\n\r\n // 分享和朗读功能待放开\r\n // if (this.resultShareBtnEl) {\r\n // this.resultShareBtnEl.addEventListener('click', () => {\r\n // this.shareResult()\r\n // })\r\n // }\r\n // if (this.resultVoiceBtnEl) {\r\n // this.resultVoiceBtnEl.addEventListener('click', () => {\r\n // this.voiceResult()\r\n // })\r\n // }\r\n }\r\n\r\n // 显示选中文本的气泡\r\n private showSelectionBubble() {\r\n if (!this.selectionBubbleEl) {\r\n this.selectionBubbleEl = document.createElement('div')\r\n this.selectionBubbleEl.className = 'ql-ai-selection-bubble'\r\n const icon = AI_ICON.replaceAll('paint_linear_2', 'paint_linear_bubble')\r\n this.selectionBubbleEl.innerHTML = `${icon}<span>AI 智能</span>`\r\n this.selectionBubbleEl.addEventListener('click', () => this.selectTextEvent())\r\n document.body.appendChild(this.selectionBubbleEl)\r\n }\r\n\r\n const { left, top } = this.quill.getBounds(this.selectionRange.index)\r\n const { left: endLeft } = this.quill.getBounds(this.selectionRange.index + this.selectionRange.length)\r\n const width = (endLeft - left) / 2\r\n const editorRect = this.quill.container.getBoundingClientRect()\r\n\r\n this.selectionBubbleEl.style.display = 'flex'\r\n this.selectionBubbleEl.style.left = `${left + editorRect.left + width - 45}px`\r\n this.selectionBubbleEl.style.top = `${top + editorRect.top - 40}px`\r\n }\r\n\r\n // 隐藏选中文本的气泡\r\n private hideSelectionBubble() {\r\n if (this.selectionBubbleEl) {\r\n this.selectionBubbleEl.style.display = 'none'\r\n }\r\n }\r\n\r\n // 处理文本选中变化\r\n private handleSelectionChange(range: any) {\r\n if (range && range.length > 0) {\r\n this.selectionRange = range\r\n this.showSelectionBubble()\r\n this.selectedText = this.quill.getText(range.index, range.length)\r\n }\r\n else {\r\n if (range && range.index !== null) {\r\n this.selectedText = ''\r\n this.closeAIPanel()\r\n }\r\n else {\r\n this.hideSelectionBubble()\r\n }\r\n }\r\n }\r\n\r\n private addInputEvent() {\r\n if (this.inputContainerEl) {\r\n this.inputContainerEl.addEventListener('click', () => {})\r\n }\r\n\r\n // 监听输入事件\r\n if (this.inputEl) {\r\n this.inputEl.addEventListener('input', () => {\r\n this.hiddenInputSendBtnEl(this.inputEl.value.trim() ? 'flex' : 'none')\r\n if (this.menuContainerEl && this._isSelectRangeMode) {\r\n this.showOperationMenu = !this.inputEl.value.trim() && !this._showResultPopupEl\r\n }\r\n })\r\n }\r\n\r\n // 给发送按钮添加点击事件\r\n if (this.inputSendBtnEl) {\r\n this.inputSendBtnEl.addEventListener('click', async () => {\r\n await this.queryAI()\r\n })\r\n }\r\n // 监听发送事件\r\n this.inputEl.addEventListener('keydown', async (e) => {\r\n if (e.key === 'Enter') {\r\n await this.queryAI()\r\n }\r\n })\r\n\r\n // 给关闭按钮添加点击事件\r\n if (this.inputCloseBtnEl) {\r\n this.inputCloseBtnEl.addEventListener('click', () => {\r\n this.closeAIPanel()\r\n })\r\n }\r\n }\r\n\r\n private positionElements() {\r\n if (!this.dialogContainerEl) return\r\n const range = this.selectionRange\r\n if (range) {\r\n const bounds = this.quill.getBounds(range.index)\r\n this.dialogContainerEl.style.position = 'absolute'\r\n this.dialogContainerEl.style.top = `${bounds.top + bounds.height + 20}px`\r\n }\r\n }\r\n\r\n // 添加创建alert元素的方法\r\n private createAlertElement() {\r\n if (!this.alertEl) {\r\n this.alertEl = document.createElement('div')\r\n this.alertEl.className = 'ql-ai-alert'\r\n this.alertEl.style.display = 'none'\r\n document.body.appendChild(this.alertEl)\r\n }\r\n }\r\n\r\n // 添加显示alert的方法\r\n private showAlert(message: string, duration: number = 3000) {\r\n this.createAlertElement()\r\n if (!this.alertEl) return\r\n\r\n // 清除之前的定时器\r\n if (this.alertTimer) {\r\n clearTimeout(this.alertTimer)\r\n this.alertTimer = null\r\n }\r\n\r\n this.alertEl.textContent = message\r\n this.alertEl.style.display = 'block'\r\n\r\n // 自动隐藏\r\n this.alertTimer = setTimeout(() => {\r\n if (this.alertEl) {\r\n this.alertEl.style.display = 'none'\r\n }\r\n this.alertTimer = null\r\n }, duration) as unknown as number\r\n }\r\n\r\n private createAIInputIcon() {\r\n if (!this.aiIconEl) {\r\n this.aiIconEl = document.createElement('span')\r\n this.aiIconEl.className = 'ql-ai-input-pre-icon'\r\n const icon = AI_ICON.replaceAll('paint_linear_2', 'paint_linear_ai_input')\r\n this.aiIconEl.innerHTML = icon\r\n }\r\n }\r\n\r\n // 添加处理子菜单点击的方法\r\n private handleOperationMenuItemClick(text: string, id: string = '') {\r\n let quetion = ''\r\n if (id.startsWith('1-') || id.startsWith('3-')) {\r\n quetion = `将目标文字${text},目标文字为:${this.selectedText}`\r\n }\r\n else if (id.startsWith('2-')) {\r\n quetion = `改写目标文字的口吻,让其变得${text},目标文字为:${this.selectedText}`\r\n }\r\n this.showOperationMenu = false\r\n this.queryAI(quetion)\r\n }\r\n\r\n private createActionMenu() {\r\n if (!this.actionMenuEl) {\r\n this.actionMenuEl = document.createElement('div')\r\n this.actionMenuEl.className = 'ql-ai-actions'\r\n\r\n this.resultMenuList.forEach(({ text, icon }) => {\r\n const menuItem = document.createElement('div')\r\n menuItem.className = 'ql-ai-action-item'\r\n menuItem.innerHTML = `${icon}<span class=\"ql-ai-result-menu-text\">${text}</span>`\r\n menuItem.addEventListener('click', () => this.handleAction(text))\r\n this.actionMenuEl.appendChild(menuItem)\r\n })\r\n\r\n this.wrapContainerEl.appendChild(this.actionMenuEl)\r\n }\r\n const secondMenuItemText = this.actionMenuEl.children[1].querySelector('.ql-ai-result-menu-text') as HTMLDivElement\r\n\r\n const firstChild = this.actionMenuEl.firstChild\r\n\r\n if (!this._isSelectRangeMode) {\r\n if (firstChild instanceof Element) {\r\n firstChild.classList.add('hidden')\r\n }\r\n\r\n secondMenuItemText.textContent = INSERT_TEXT\r\n }\r\n else {\r\n if (firstChild instanceof Element) {\r\n firstChild.classList.remove('hidden')\r\n }\r\n\r\n secondMenuItemText.textContent = INSERT_SUB_CONTENT_TEXT\r\n }\r\n\r\n this.isThinking = false\r\n }\r\n\r\n private handleActionMenuDisplay(value: string = 'none') {\r\n if (this.actionMenuEl) {\r\n this.actionMenuEl.style.display = value\r\n }\r\n }\r\n\r\n private switchInputEl(showInput = true) {\r\n if (this.inputContainerEl) {\r\n this.inputContainerEl.style.display = showInput ? 'flex' : 'none'\r\n }\r\n\r\n this.handleActionMenuDisplay(showInput ? 'block' : 'none')\r\n\r\n if (this.thinkContainerEl) {\r\n this.thinkContainerEl.style.display = showInput ? 'none' : 'flex'\r\n }\r\n }\r\n\r\n // 创建思考元素\r\n private createThinkElements() {\r\n if (!this.thinkContainerEl) {\r\n this.thinkContainerEl = document.createElement('div')\r\n this.thinkContainerEl.className = 'ql-ai-input'\r\n this.thinkContainerEl.innerHTML = `<span class=\"ql-ai-input-pre-icon ql-ai-think-icon\">${THINK_ICON}</span><span class=\"ql-ai-think-text\">${THINK_TEXT}</span>`\r\n this.thinkBtnEl = document.createElement('div')\r\n this.thinkBtnEl.className = 'ql-ai-think-btn'\r\n this.thinkBtnEl.innerHTML = `${STOP_ICON}<span>${STOP_ANSWER}</span>`\r\n this.thinkContainerEl.appendChild(this.thinkBtnEl)\r\n this.wrapContainerEl.appendChild(this.thinkContainerEl) // 添加发送按钮\r\n this.thinkBtnEl.addEventListener('click', () => {\r\n this.isBreak = true\r\n this.isThinking = false\r\n })\r\n }\r\n\r\n this.isThinking = true\r\n }\r\n\r\n // AI查询\r\n private async queryAI(question?: string): Promise<string> {\r\n this.createThinkElements()\r\n this.inputValue = question || this.inputEl.value\r\n if (this.inputValue.trim() === '') {\r\n return\r\n }\r\n\r\n // 有信息\r\n this.isBreak = false // 重置打断标记,防止重复打断ai\r\n // 这里实现实际的AI查询逻辑\r\n try {\r\n const response = await fetch(`${this.host}`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: this.model,\r\n prompt: this.inputValue,\r\n stream: true,\r\n }),\r\n })\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`)\r\n }\r\n\r\n const reader = response.body.getReader()\r\n const decoder = new TextDecoder()\r\n let content = ''\r\n\r\n while (true) {\r\n if (this.isBreak) {\r\n this.isBreak = false\r\n break\r\n }\r\n\r\n const { done, value } = await reader.read()\r\n if (done) break\r\n\r\n const chunk = decoder.decode(value)\r\n const lines = chunk.split('\\n').filter(line => line.trim() !== '')\r\n\r\n for (const line of lines) {\r\n try {\r\n const data = JSON.parse(line)\r\n content += data.response || ''\r\n this.showAIResponse(content)\r\n }\r\n catch (e) {\r\n console.error('解析错误:', e)\r\n }\r\n }\r\n }\r\n\r\n // 创建操作菜单\r\n this.createActionMenu()\r\n this.inputEl.value = '' // 清空输入框\r\n this.hiddenInputSendBtnEl()\r\n return content\r\n }\r\n catch (error) {\r\n console.error('AI查询失败:', error)\r\n return 'AI查询失败,请重试'\r\n }\r\n }\r\n\r\n private showAIResponse(response: string) {\r\n if (!this.resultPopupEl) return\r\n\r\n // 显示结果\r\n if (this._charCount <= this.textNumber) {\r\n this.resultPopupContentEl.innerHTML = response\r\n this.charCount = this.resultPopupContentEl.textContent.replace(/\\s+/g, '').length\r\n }\r\n else {\r\n this.isBreak = true\r\n this.charCount = 0\r\n }\r\n this.showResultPopupEl = true\r\n }\r\n\r\n private handleAction(action: string) {\r\n switch (action) {\r\n case REPLACE_SELECT:\r\n this.replaceSelectText()\r\n break\r\n case INSERT_TEXT:\r\n this.insertAIResponse()\r\n break\r\n case REGENERATE:\r\n this.regenerateResponse()\r\n break\r\n case CLOSE:\r\n this.closeAIPanel()\r\n break\r\n }\r\n }\r\n\r\n private replaceSelectText() {\r\n if (!this.resultPopupContentEl) return\r\n const range = this.quill.getSelection(true)\r\n if (range && range.length > 0) {\r\n // 删除选中内容\r\n this.quill.deleteText(range.index, range.length)\r\n // 插入AI生成的内容\r\n this.quill.clipboard.dangerouslyPasteHTML(range.index, this.resultPopupContentEl.innerHTML)\r\n }\r\n this.closeAIPanel()\r\n }\r\n\r\n private insertAIResponse() {\r\n if (!this.resultPopupContentEl) return\r\n const range = this.quill.getSelection(true)\r\n if (range) {\r\n this.quill.clipboard.dangerouslyPasteHTML(range.index + range.length, this.resultPopupContentEl.innerHTML)\r\n }\r\n this.closeAIPanel()\r\n }\r\n\r\n private async regenerateResponse() {\r\n await this.queryAI(this.inputValue)\r\n }\r\n\r\n private closeAIPanel() {\r\n this.isBreak = true // 停止查询\r\n\r\n if (this.dialogContainerEl) {\r\n this.dialogContainerEl.style.display = 'none'\r\n }\r\n\r\n if (this.actionMenuEl) {\r\n this.actionMenuEl.style.display = 'none'\r\n }\r\n\r\n this.showResultPopupEl = false\r\n\r\n if (this.inputEl && this.inputEl.value.trim() !== '') {\r\n this.inputEl.value = '' // 清空输入框\r\n }\r\n this.hideSelectionBubble()\r\n }\r\n\r\n set charCount(value: number) {\r\n // 清除之前的定时器\r\n if (this._debounceTimer) {\r\n clearTimeout(this._debounceTimer)\r\n }\r\n\r\n this._debounceTimer = setTimeout(() => {\r\n this._charCount = value\r\n if (this.resultPopupFooterTextEl) {\r\n this.resultPopupFooterTextEl.textContent = `${this._charCount}/${this.textNumber}`\r\n }\r\n clearTimeout(this._debounceTimer)\r\n this._debounceTimer = null\r\n }, 210)\r\n }\r\n\r\n get charCount() {\r\n return this._charCount\r\n }\r\n\r\n set inputPlaceholder(value: string) {\r\n this._inputPlaceholder = value\r\n if (this.inputEl) {\r\n this.inputEl.placeholder = value\r\n }\r\n }\r\n\r\n get inputPlaceholder() {\r\n return this._inputPlaceholder\r\n }\r\n\r\n set showOperationMenu(value: boolean) {\r\n this._showOperationMenu = value\r\n if (this.menuContainerEl) {\r\n this.menuContainerEl.style.display = value ? 'flex' : 'none'\r\n }\r\n }\r\n\r\n get showOperationMenu() {\r\n return this._showOperationMenu\r\n }\r\n\r\n set isSelectRangeMode(value: boolean) {\r\n this._isSelectRangeMode = value\r\n this.showOperationMenu = value\r\n this.inputPlaceholder = value ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER\r\n this.hideSelectionBubble()\r\n }\r\n\r\n get isSelectRangeMode() {\r\n return this._isSelectRangeMode\r\n }\r\n\r\n set isThinking(value: boolean) {\r\n this._isThinking = value\r\n this.switchInputEl(!value)\r\n }\r\n\r\n get isThinking() {\r\n return this._isThinking\r\n }\r\n\r\n set showResultPopupEl(value: boolean) {\r\n this._showResultPopupEl = value\r\n if (this.resultPopupEl) {\r\n this.resultPopupEl.style.display = value ? 'block' : 'none'\r\n }\r\n }\r\n\r\n get showResultPopupEl() {\r\n return this._showResultPopupEl\r\n }\r\n}\r\n"],"names":["id"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../../../../src/modules/ai/index.ts"],"sourcesContent":["import type TypeToolbar from 'quill/modules/toolbar'\nimport type FluentEditor from '../../core/fluent-editor'\nimport type { AIOptions, OperationMenuItem, ResultMenuItem } from './types'\nimport {\n CLOSE,\n INPUT_PLACEHOLDER,\n INSERT_SUB_CONTENT_TEXT,\n INSERT_TEXT,\n MENU_ID_MAP,\n MENU_TITLE_DATA,\n REGENERATE,\n REPLACE_SELECT,\n RESULT_HEADER_TEXT,\n SELECT_PLACEHOLDER,\n STOP_ANSWER,\n THINK_TEXT,\n} from './constants'\nimport {\n ADJUST_ICON,\n AI_ICON,\n CALL_ICON,\n CLOSE_ICON,\n COPY_ICON,\n EDITOR_ICON,\n INSERT_ICON,\n MENU_CLOSE_ICON,\n REBUILD_ICON,\n REFRESH_ICON,\n REPLACE_SELECT_ICON,\n RIGHT_ARROW_ICON,\n SEND_BTN_ICON,\n STOP_ICON,\n THINK_ICON,\n} from './icons'\n\nexport class AI {\n toolbar: TypeToolbar\n host: string\n apiKey: string\n model: string\n message: string\n isBreak: boolean = false // 打断标记\n textNumber: number // 文本字数限制\n private _isSelectRangeMode: boolean = false // 选择/点击模式\n private _charCount: number = 0 // 文本字数\n private _debounceTimer = null\n private _inputPlaceholder: string = ''\n private _showOperationMenu: boolean = false\n private _isThinking: boolean = false // 思考中\n private _showResultPopupEl: boolean = false // 结果弹窗\n selectedText: string = '' // 选择的文本\n inputValue: string = '' // 存储输入框的值\n resultMenuList: ResultMenuItem[] = []\n operationMenuList: OperationMenuItem[] = []\n private _operationMenuItemList: OperationMenuItem[] = []\n\n private alertEl: HTMLDivElement | null = null\n private alertTimer: number | null = null\n private selectionBubbleEl: HTMLDivElement | null = null\n private selectionRange: any = null\n private dialogContainerEl: HTMLDivElement | null = null\n private wrapContainerEl: HTMLDivElement | null = null\n private aiIconEl: HTMLSpanElement | null = null\n private inputContainerEl: HTMLDivElement | null = null\n private inputEl: HTMLInputElement | null = null\n private menuContainerEl: HTMLDivElement | null = null\n private subMenuEl: HTMLDivElement | null = null\n private subMenuEditorEl: HTMLDivElement | null = null\n private subMenuToneEl: HTMLDivElement | null = null\n private subMenuAdjustEl: HTMLDivElement | null = null\n private inputRightEl: HTMLDivElement | null = null\n private inputSendBtnEl: HTMLSpanElement | null = null\n private inputCloseBtnEl: HTMLSpanElement | null = null\n private thinkContainerEl: HTMLDivElement | null = null // 思考元素\n private thinkBtnEl: HTMLDivElement | null = null\n private resultPopupEl: HTMLDivElement | null = null\n private resultPopupHeaderEl: HTMLDivElement | null = null\n private resultPopupContentEl: HTMLDivElement | null = null\n private resultPopupFooterEl: HTMLDivElement | null = null\n private resultPopupFooterTextEl: HTMLSpanElement | null = null\n private resultRefreshBtnEl: HTMLSpanElement | null = null\n private resultCopyBtnEl: HTMLSpanElement | null = null\n // 分享和朗读功能待放开\n // private resultShareBtnEl: HTMLSpanElement | null = null\n // private resultVoiceBtnEl: HTMLSpanElement | null = null\n private actionMenuEl: HTMLDivElement | null = null\n\n constructor(\n public quill: FluentEditor,\n public options: AIOptions,\n ) {\n this.quill = quill\n this.toolbar = quill.getModule('toolbar') as TypeToolbar\n // 添加AI按钮到工具栏\n if (typeof this.toolbar !== 'undefined') {\n this.toolbar.addHandler('ai', this.showAIInput.bind(this))\n }\n\n this.quill.on('selection-change', this.handleSelectionChange.bind(this))\n\n this.host = options.host || 'https://api.deepseek.com/v1'\n this.apiKey = options.apiKey\n this.model = options.model || 'deepseek-chat'\n this.textNumber = options.contentMaxLength || 5000\n\n this.resultMenuList = [\n { text: REPLACE_SELECT, icon: REPLACE_SELECT_ICON },\n { text: INSERT_TEXT, icon: INSERT_ICON, selectText: INSERT_SUB_CONTENT_TEXT },\n { text: REGENERATE, icon: REBUILD_ICON },\n { text: CLOSE, icon: MENU_CLOSE_ICON },\n ]\n\n this.operationMenuList = [\n { id: 'editor', text: '编辑调整内容', icon: EDITOR_ICON },\n { id: 'tone', text: '改写口吻', icon: CALL_ICON },\n { id: 'adjust', text: '整理选区内容', icon: ADJUST_ICON },\n ]\n }\n\n // 工具栏启动\n showAIInput() {\n // 创建输入框和结果弹窗\n this.create()\n\n this.selectionRange = this.quill.getSelection()\n if (this.selectionRange.length) {\n this.isSelectRangeMode = true\n }\n else {\n this.isSelectRangeMode = false\n }\n // 定位到编辑器焦点位置\n this.positionElements()\n\n // 添加ESC键监听\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n this.closeAIPanel()\n this.quill.container.removeEventListener('keydown', handleKeyDown)\n }\n }\n this.quill.container.addEventListener('keydown', handleKeyDown)\n }\n\n // 气泡启动\n private selectTextEvent() {\n if (!this.selectionRange) return\n this.create()\n // 定位到编辑器焦点位置\n this.positionElements()\n\n this.isSelectRangeMode = true\n }\n\n private create() {\n this.createResultElement()\n this.createOperationMenuElements()\n this.createInputBoxElements()\n\n // 创建事件监听\n this.addInputEvent()\n this.addResultEvent()\n this.handleActionMenuDisplay()\n // 添加到编辑器\n this.quill.container.appendChild(this.dialogContainerEl)\n }\n\n // 创建结果弹窗\n private createResultElement() {\n if (!this.resultPopupEl) {\n this.resultPopupEl = document.createElement('div')\n this.resultPopupEl.className = 'ql-ai-result'\n this.resultPopupHeaderEl = document.createElement('div')\n this.resultPopupHeaderEl.className = 'ql-ai-result-header'\n this.resultPopupHeaderEl.textContent = RESULT_HEADER_TEXT\n this.resultPopupContentEl = document.createElement('div')\n this.resultPopupContentEl.className = 'ql-ai-result-content'\n this.resultPopupFooterEl = document.createElement('div')\n this.resultPopupFooterEl.className = 'ql-ai-result-footer'\n this.resultPopupFooterTextEl = document.createElement('span')\n this.resultPopupFooterTextEl.className = 'ql-ai-result-footer-text'\n this.resultPopupFooterTextEl.textContent = `0`\n this.resultRefreshBtnEl = document.createElement('span')\n this.resultRefreshBtnEl.className = 'ql-ai-result-footer-refresh'\n this.resultRefreshBtnEl.innerHTML = REFRESH_ICON\n this.resultCopyBtnEl = document.createElement('span')\n this.resultCopyBtnEl.className = 'ql-ai-result-footer-copy'\n this.resultCopyBtnEl.innerHTML = COPY_ICON\n\n // 分享和朗读功能待放开\n // this.resultShareBtnEl = document.createElement('span')\n // this.resultShareBtnEl.className = 'ql-ai-result-footer-share'\n // this.resultShareBtnEl.innerHTML = SHARE_ICON\n // this.resultVoiceBtnEl = document.createElement('span')\n // this.resultVoiceBtnEl.className = 'ql-ai-result-footer-voice'\n // this.resultVoiceBtnEl.innerHTML = VOICE_ICON\n const resultFooterRightEl: HTMLDivElement = document.createElement('div')\n resultFooterRightEl.className = 'ql-ai-result-footer-right'\n resultFooterRightEl.appendChild(this.resultRefreshBtnEl)\n resultFooterRightEl.appendChild(this.resultCopyBtnEl)\n // 分享和朗读功能待放开\n // resultFooterRightEl.appendChild(this.resultShareBtnEl)\n // resultFooterRightEl.appendChild(this.resultVoiceBtnEl)\n this.resultPopupFooterEl.appendChild(this.resultPopupFooterTextEl)\n this.resultPopupFooterEl.appendChild(resultFooterRightEl)\n this.resultPopupEl.appendChild(this.resultPopupHeaderEl)\n this.resultPopupEl.appendChild(this.resultPopupContentEl)\n this.resultPopupEl.appendChild(this.resultPopupFooterEl)\n }\n this.showResultPopupEl = false\n }\n\n private createOperationMenuElements() {\n if (!this.menuContainerEl) {\n // 创建操作菜单容器\n this.menuContainerEl = document.createElement('div')\n this.menuContainerEl.className = 'ql-ai-menu-container'\n\n // 创建主菜单\n const mainMenu = document.createElement('div')\n mainMenu.className = 'ql-ai-main-menu'\n this.operationMenuList.forEach(({ text, icon, id }) => {\n const menuItem = document.createElement('div')\n menuItem.className = 'ql-ai-menu-item'\n menuItem.innerHTML = `${icon}<span>${text}</span>${RIGHT_ARROW_ICON}`\n menuItem.addEventListener('mouseenter', (e) => {\n e.stopPropagation()\n this.subMenuEl.style.display = 'block'\n this.subMenuEl.className = `ql-ai-sub-menu ${id}`\n this.createOperationMenuItem(id)\n })\n mainMenu.appendChild(menuItem)\n })\n if (!this.subMenuEl) {\n // 创建子菜单\n this.subMenuEl = document.createElement('div')\n this.subMenuEl.className = 'ql-ai-sub-menu'\n this.subMenuEl.style.display = 'none'\n }\n\n this.menuContainerEl.appendChild(mainMenu)\n this.menuContainerEl.appendChild(this.subMenuEl)\n }\n this.showOperationMenu = false\n }\n\n private createOperationMenuItem(id: string) {\n let menuItemBox = this[MENU_ID_MAP[id]]\n if (!menuItemBox) {\n menuItemBox = document.createElement('div')\n }\n // 清除子菜单容器中的所有子元素\n while (this.subMenuEl.firstChild) {\n this.subMenuEl.removeChild(this.subMenuEl.firstChild)\n }\n\n MENU_TITLE_DATA[id].forEach(({ text, icon, id }) => {\n const menuItem = document.createElement('div')\n menuItem.className = 'ql-ai-menu-item'\n menuItem.innerHTML = `${icon || ''}<span>${text}</span>`\n menuItem.addEventListener('click', (e) => {\n e.stopPropagation()\n this.handleOperationMenuItemClick(text, id)\n })\n menuItemBox.appendChild(menuItem)\n })\n this.subMenuEl.appendChild(menuItemBox)\n }\n\n private createInputBoxElements() {\n if (!this.dialogContainerEl) {\n this.dialogContainerEl = document.createElement('div')\n this.dialogContainerEl.className = 'ql-ai-dialog'\n this.wrapContainerEl = document.createElement('div')\n this.wrapContainerEl.className = 'ql-ai-wrapper'\n this.wrapContainerEl.style.width = `${this.quill.container.clientWidth - 30}px`\n\n // 添加AI图标\n this.createAIInputIcon()\n\n // 增加输入框\n this.inputEl = document.createElement('input')\n this.inputEl.type = 'text'\n this.inputPlaceholder = this._isSelectRangeMode ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER\n // 添加发送按钮\n this.inputSendBtnEl = document.createElement('span')\n this.inputSendBtnEl.className = 'ql-ai-input-right-send'\n this.inputSendBtnEl.innerHTML = SEND_BTN_ICON\n this.inputCloseBtnEl = document.createElement('span')\n this.inputCloseBtnEl.className = 'ql-ai-input-right-close'\n this.inputCloseBtnEl.innerHTML = CLOSE_ICON\n this.inputRightEl = document.createElement('div')\n this.inputRightEl.className = 'ql-ai-input-right'\n\n // 创建输入框\n this.inputContainerEl = document.createElement('div')\n this.inputContainerEl.className = 'ql-ai-input'\n this.inputContainerEl.appendChild(this.aiIconEl)\n this.inputContainerEl.appendChild(this.inputEl)\n this.inputRightEl.appendChild(this.inputSendBtnEl)\n this.inputRightEl.appendChild(this.inputCloseBtnEl)\n this.inputContainerEl.appendChild(this.inputRightEl) // 添加发送按钮\n this.wrapContainerEl.appendChild(this.resultPopupEl)\n this.wrapContainerEl.appendChild(this.inputContainerEl)\n this.wrapContainerEl.appendChild(this.menuContainerEl) // 添加菜单容器\n this.dialogContainerEl.appendChild(this.wrapContainerEl)\n }\n else {\n this.dialogContainerEl.style.display = 'block'\n }\n this.hiddenInputSendBtnEl()\n }\n\n private hiddenInputSendBtnEl(display = 'none') {\n if (this.inputEl && this.inputSendBtnEl) {\n this.inputSendBtnEl.style.display = display\n }\n }\n\n private copyResult() {\n if (!this.resultPopupContentEl) return\n\n try {\n const textToCopy = this.resultPopupContentEl.textContent || ''\n navigator.clipboard\n .writeText(textToCopy)\n .then(() => {\n this.showAlert('内容已复制到剪贴板')\n // 可以在这里添加复制成功的提示\n })\n .catch((err) => {\n this.showAlert(`复制失败:${err}`)\n })\n }\n catch (err) {\n this.showAlert(`复制失败:${err}`)\n // 兼容不支持clipboard API的浏览器\n const textarea = document.createElement('textarea')\n textarea.value = this.resultPopupContentEl.textContent || ''\n document.body.appendChild(textarea)\n textarea.select()\n document.execCommand('copy')\n document.body.removeChild(textarea)\n }\n }\n\n // 分享和朗读功能待放开\n // private shareResult() {\n // if (!this.resultPopupContentEl) return\n\n // const textToShare = this.resultPopupContentEl.textContent || ''\n // const title = 'AI生成内容分享'\n\n // if (navigator.share) {\n // navigator.share({\n // title,\n // text: textToShare,\n // })\n // .catch((err) => {\n // this.showAlert(`分享失败:${err}`)\n // })\n // }\n // else {\n // // 兼容不支持Web Share API的浏览器\n // const shareUrl = `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(textToShare)}`\n // window.open(shareUrl, '_blank')\n // }\n // }\n // private voiceResult() {\n // if (!this.resultPopupContentEl) return\n\n // const textToSpeak = this.resultPopupContentEl.textContent || ''\n\n // if ('speechSynthesis' in window) {\n // const utterance = new SpeechSynthesisUtterance(textToSpeak)\n // utterance.lang = 'zh-CN' // 设置中文语音\n // speechSynthesis.speak(utterance)\n // }\n // else {\n // this.showAlert('当前浏览器不支持语音合成API')\n // // 可以在这里添加不支持语音的提示\n // }\n // }\n\n private addResultEvent() {\n if (this.resultRefreshBtnEl) {\n this.resultRefreshBtnEl.addEventListener('click', () => {\n this.regenerateResponse()\n })\n }\n\n if (this.resultCopyBtnEl) {\n this.resultCopyBtnEl.addEventListener('click', () => {\n this.copyResult()\n })\n }\n\n // 分享和朗读功能待放开\n // if (this.resultShareBtnEl) {\n // this.resultShareBtnEl.addEventListener('click', () => {\n // this.shareResult()\n // })\n // }\n // if (this.resultVoiceBtnEl) {\n // this.resultVoiceBtnEl.addEventListener('click', () => {\n // this.voiceResult()\n // })\n // }\n }\n\n // 显示选中文本的气泡\n private showSelectionBubble() {\n if (!this.selectionBubbleEl) {\n this.selectionBubbleEl = document.createElement('div')\n this.selectionBubbleEl.className = 'ql-ai-selection-bubble'\n const icon = AI_ICON.replaceAll('paint_linear_2', 'paint_linear_bubble')\n this.selectionBubbleEl.innerHTML = `${icon}<span>AI 智能</span>`\n this.selectionBubbleEl.addEventListener('click', () => this.selectTextEvent())\n document.body.appendChild(this.selectionBubbleEl)\n }\n\n const { left, top } = this.quill.getBounds(this.selectionRange.index)\n const { left: endLeft } = this.quill.getBounds(this.selectionRange.index + this.selectionRange.length)\n const width = (endLeft - left) / 2\n const editorRect = this.quill.container.getBoundingClientRect()\n\n this.selectionBubbleEl.style.display = 'flex'\n this.selectionBubbleEl.style.left = `${left + editorRect.left + width - 45}px`\n this.selectionBubbleEl.style.top = `${top + editorRect.top - 40}px`\n }\n\n // 隐藏选中文本的气泡\n private hideSelectionBubble() {\n if (this.selectionBubbleEl) {\n this.selectionBubbleEl.style.display = 'none'\n }\n }\n\n // 处理文本选中变化\n private handleSelectionChange(range: any) {\n if (range && range.length > 0) {\n this.selectionRange = range\n this.showSelectionBubble()\n this.selectedText = this.quill.getText(range.index, range.length)\n }\n else {\n if (range && range.index !== null) {\n this.selectedText = ''\n this.closeAIPanel()\n }\n else {\n this.hideSelectionBubble()\n }\n }\n }\n\n private addInputEvent() {\n if (this.inputContainerEl) {\n this.inputContainerEl.addEventListener('click', () => {})\n }\n\n // 监听输入事件\n if (this.inputEl) {\n this.inputEl.addEventListener('input', () => {\n this.hiddenInputSendBtnEl(this.inputEl.value.trim() ? 'flex' : 'none')\n if (this.menuContainerEl && this._isSelectRangeMode) {\n this.showOperationMenu = !this.inputEl.value.trim() && !this._showResultPopupEl\n }\n })\n }\n\n // 给发送按钮添加点击事件\n if (this.inputSendBtnEl) {\n this.inputSendBtnEl.addEventListener('click', async () => {\n await this.queryAI()\n })\n }\n // 监听发送事件\n this.inputEl.addEventListener('keydown', async (e) => {\n if (e.key === 'Enter') {\n await this.queryAI()\n }\n })\n\n // 给关闭按钮添加点击事件\n if (this.inputCloseBtnEl) {\n this.inputCloseBtnEl.addEventListener('click', () => {\n this.closeAIPanel()\n })\n }\n }\n\n private positionElements() {\n if (!this.dialogContainerEl) return\n const range = this.selectionRange\n if (range) {\n const bounds = this.quill.getBounds(range.index)\n this.dialogContainerEl.style.position = 'absolute'\n this.dialogContainerEl.style.top = `${bounds.top + bounds.height + 20}px`\n }\n }\n\n // 添加创建alert元素的方法\n private createAlertElement() {\n if (!this.alertEl) {\n this.alertEl = document.createElement('div')\n this.alertEl.className = 'ql-ai-alert'\n this.alertEl.style.display = 'none'\n document.body.appendChild(this.alertEl)\n }\n }\n\n // 添加显示alert的方法\n private showAlert(message: string, duration: number = 3000) {\n this.createAlertElement()\n if (!this.alertEl) return\n\n // 清除之前的定时器\n if (this.alertTimer) {\n clearTimeout(this.alertTimer)\n this.alertTimer = null\n }\n\n this.alertEl.textContent = message\n this.alertEl.style.display = 'block'\n\n // 自动隐藏\n this.alertTimer = setTimeout(() => {\n if (this.alertEl) {\n this.alertEl.style.display = 'none'\n }\n this.alertTimer = null\n }, duration) as unknown as number\n }\n\n private createAIInputIcon() {\n if (!this.aiIconEl) {\n this.aiIconEl = document.createElement('span')\n this.aiIconEl.className = 'ql-ai-input-pre-icon'\n const icon = AI_ICON.replaceAll('paint_linear_2', 'paint_linear_ai_input')\n this.aiIconEl.innerHTML = icon\n }\n }\n\n // 添加处理子菜单点击的方法\n private handleOperationMenuItemClick(text: string, id: string = '') {\n let quetion = ''\n if (id.startsWith('1-') || id.startsWith('3-')) {\n quetion = `将目标文字${text},目标文字为:${this.selectedText}`\n }\n else if (id.startsWith('2-')) {\n quetion = `改写目标文字的口吻,让其变得${text},目标文字为:${this.selectedText}`\n }\n this.showOperationMenu = false\n this.queryAI(quetion)\n }\n\n private createActionMenu() {\n if (!this.actionMenuEl) {\n this.actionMenuEl = document.createElement('div')\n this.actionMenuEl.className = 'ql-ai-actions'\n\n this.resultMenuList.forEach(({ text, icon }) => {\n const menuItem = document.createElement('div')\n menuItem.className = 'ql-ai-action-item'\n menuItem.innerHTML = `${icon}<span class=\"ql-ai-result-menu-text\">${text}</span>`\n menuItem.addEventListener('click', () => this.handleAction(text))\n this.actionMenuEl.appendChild(menuItem)\n })\n\n this.wrapContainerEl.appendChild(this.actionMenuEl)\n }\n const secondMenuItemText = this.actionMenuEl.children[1].querySelector('.ql-ai-result-menu-text') as HTMLDivElement\n\n const firstChild = this.actionMenuEl.firstChild\n\n if (!this._isSelectRangeMode) {\n if (firstChild instanceof Element) {\n firstChild.classList.add('hidden')\n }\n\n secondMenuItemText.textContent = INSERT_TEXT\n }\n else {\n if (firstChild instanceof Element) {\n firstChild.classList.remove('hidden')\n }\n\n secondMenuItemText.textContent = INSERT_SUB_CONTENT_TEXT\n }\n\n this.isThinking = false\n }\n\n private handleActionMenuDisplay(value: string = 'none') {\n if (this.actionMenuEl) {\n this.actionMenuEl.style.display = value\n }\n }\n\n private switchInputEl(showInput = true) {\n if (this.inputContainerEl) {\n this.inputContainerEl.style.display = showInput ? 'flex' : 'none'\n }\n\n this.handleActionMenuDisplay(showInput ? 'block' : 'none')\n\n if (this.thinkContainerEl) {\n this.thinkContainerEl.style.display = showInput ? 'none' : 'flex'\n }\n }\n\n // 创建思考元素\n private createThinkElements() {\n if (!this.thinkContainerEl) {\n this.thinkContainerEl = document.createElement('div')\n this.thinkContainerEl.className = 'ql-ai-input'\n this.thinkContainerEl.innerHTML = `<span class=\"ql-ai-input-pre-icon ql-ai-think-icon\">${THINK_ICON}</span><span class=\"ql-ai-think-text\">${THINK_TEXT}</span>`\n this.thinkBtnEl = document.createElement('div')\n this.thinkBtnEl.className = 'ql-ai-think-btn'\n this.thinkBtnEl.innerHTML = `${STOP_ICON}<span>${STOP_ANSWER}</span>`\n this.thinkContainerEl.appendChild(this.thinkBtnEl)\n this.wrapContainerEl.appendChild(this.thinkContainerEl) // 添加发送按钮\n this.thinkBtnEl.addEventListener('click', () => {\n this.isBreak = true\n this.isThinking = false\n })\n }\n\n this.isThinking = true\n }\n\n // AI查询\n private async queryAI(question?: string): Promise<string> {\n this.createThinkElements()\n this.inputValue = question || this.inputEl.value\n if (this.inputValue.trim() === '') {\n return\n }\n\n // 有信息\n this.isBreak = false // 重置打断标记,防止重复打断ai\n // 这里实现实际的AI查询逻辑\n try {\n const response = await fetch(`${this.host}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n model: this.model,\n prompt: this.inputValue,\n stream: true,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let content = ''\n\n while (true) {\n if (this.isBreak) {\n this.isBreak = false\n break\n }\n\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value)\n const lines = chunk.split('\\n').filter(line => line.trim() !== '')\n\n for (const line of lines) {\n try {\n const data = JSON.parse(line)\n content += data.response || ''\n this.showAIResponse(content)\n }\n catch (e) {\n console.error('解析错误:', e)\n }\n }\n }\n\n // 创建操作菜单\n this.createActionMenu()\n this.inputEl.value = '' // 清空输入框\n this.hiddenInputSendBtnEl()\n return content\n }\n catch (error) {\n console.error('AI查询失败:', error)\n return 'AI查询失败,请重试'\n }\n }\n\n private showAIResponse(response: string) {\n if (!this.resultPopupEl) return\n\n // 显示结果\n if (this._charCount <= this.textNumber) {\n this.resultPopupContentEl.innerHTML = response\n this.charCount = this.resultPopupContentEl.textContent.replace(/\\s+/g, '').length\n }\n else {\n this.isBreak = true\n this.charCount = 0\n }\n this.showResultPopupEl = true\n }\n\n private handleAction(action: string) {\n switch (action) {\n case REPLACE_SELECT:\n this.replaceSelectText()\n break\n case INSERT_TEXT:\n this.insertAIResponse()\n break\n case REGENERATE:\n this.regenerateResponse()\n break\n case CLOSE:\n this.closeAIPanel()\n break\n }\n }\n\n private replaceSelectText() {\n if (!this.resultPopupContentEl) return\n const range = this.quill.getSelection(true)\n if (range && range.length > 0) {\n // 删除选中内容\n this.quill.deleteText(range.index, range.length)\n // 插入AI生成的内容\n this.quill.clipboard.dangerouslyPasteHTML(range.index, this.resultPopupContentEl.innerHTML)\n }\n this.closeAIPanel()\n }\n\n private insertAIResponse() {\n if (!this.resultPopupContentEl) return\n const range = this.quill.getSelection(true)\n if (range) {\n this.quill.clipboard.dangerouslyPasteHTML(range.index + range.length, this.resultPopupContentEl.innerHTML)\n }\n this.closeAIPanel()\n }\n\n private async regenerateResponse() {\n await this.queryAI(this.inputValue)\n }\n\n private closeAIPanel() {\n this.isBreak = true // 停止查询\n\n if (this.dialogContainerEl) {\n this.dialogContainerEl.style.display = 'none'\n }\n\n if (this.actionMenuEl) {\n this.actionMenuEl.style.display = 'none'\n }\n\n this.showResultPopupEl = false\n\n if (this.inputEl && this.inputEl.value.trim() !== '') {\n this.inputEl.value = '' // 清空输入框\n }\n this.hideSelectionBubble()\n }\n\n set charCount(value: number) {\n // 清除之前的定时器\n if (this._debounceTimer) {\n clearTimeout(this._debounceTimer)\n }\n\n this._debounceTimer = setTimeout(() => {\n this._charCount = value\n if (this.resultPopupFooterTextEl) {\n this.resultPopupFooterTextEl.textContent = `${this._charCount}/${this.textNumber}`\n }\n clearTimeout(this._debounceTimer)\n this._debounceTimer = null\n }, 210)\n }\n\n get charCount() {\n return this._charCount\n }\n\n set inputPlaceholder(value: string) {\n this._inputPlaceholder = value\n if (this.inputEl) {\n this.inputEl.placeholder = value\n }\n }\n\n get inputPlaceholder() {\n return this._inputPlaceholder\n }\n\n set showOperationMenu(value: boolean) {\n this._showOperationMenu = value\n if (this.menuContainerEl) {\n this.menuContainerEl.style.display = value ? 'flex' : 'none'\n }\n }\n\n get showOperationMenu() {\n return this._showOperationMenu\n }\n\n set isSelectRangeMode(value: boolean) {\n this._isSelectRangeMode = value\n this.showOperationMenu = value\n this.inputPlaceholder = value ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER\n this.hideSelectionBubble()\n }\n\n get isSelectRangeMode() {\n return this._isSelectRangeMode\n }\n\n set isThinking(value: boolean) {\n this._isThinking = value\n this.switchInputEl(!value)\n }\n\n get isThinking() {\n return this._isThinking\n }\n\n set showResultPopupEl(value: boolean) {\n this._showResultPopupEl = value\n if (this.resultPopupEl) {\n this.resultPopupEl.style.display = value ? 'block' : 'none'\n }\n }\n\n get showResultPopupEl() {\n return this._showResultPopupEl\n }\n}\n"],"names":["id"],"mappings":"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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as Y from "yjs";
|
|
2
1
|
function setupAwareness(options, defaultAwareness) {
|
|
3
2
|
if (!defaultAwareness) return null;
|
|
4
3
|
const awareness = defaultAwareness;
|
|
@@ -7,7 +6,7 @@ function setupAwareness(options, defaultAwareness) {
|
|
|
7
6
|
}
|
|
8
7
|
return awareness;
|
|
9
8
|
}
|
|
10
|
-
function bindAwarenessToCursors(awareness, cursorsModule, quill, yText) {
|
|
9
|
+
function bindAwarenessToCursors(awareness, cursorsModule, quill, yText, Yjs) {
|
|
11
10
|
if (!cursorsModule || !awareness) return;
|
|
12
11
|
const doc = yText.doc;
|
|
13
12
|
const updateCursor = (clientId, state) => {
|
|
@@ -17,8 +16,8 @@ function bindAwarenessToCursors(awareness, cursorsModule, quill, yText) {
|
|
|
17
16
|
const color = user.color || "#ff6b6b";
|
|
18
17
|
const name = user.name || `User ${clientId}`;
|
|
19
18
|
cursorsModule.createCursor(clientId.toString(), name, color);
|
|
20
|
-
const anchor =
|
|
21
|
-
const head =
|
|
19
|
+
const anchor = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.anchor), doc);
|
|
20
|
+
const head = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.head), doc);
|
|
22
21
|
if (anchor && head && anchor.type === yText && clientId) {
|
|
23
22
|
setTimeout(() => {
|
|
24
23
|
cursorsModule.moveCursor(clientId.toString(), {
|
|
@@ -38,10 +37,10 @@ function bindAwarenessToCursors(awareness, cursorsModule, quill, yText) {
|
|
|
38
37
|
setTimeout(() => {
|
|
39
38
|
var _a;
|
|
40
39
|
if (range) {
|
|
41
|
-
const anchor =
|
|
42
|
-
const head =
|
|
40
|
+
const anchor = Yjs.createRelativePositionFromTypeIndex(yText, range.index);
|
|
41
|
+
const head = Yjs.createRelativePositionFromTypeIndex(yText, range.index + range.length);
|
|
43
42
|
const currentState = awareness.getLocalState();
|
|
44
|
-
if (!(currentState == null ? void 0 : currentState.cursor) || !
|
|
43
|
+
if (!(currentState == null ? void 0 : currentState.cursor) || !Yjs.compareRelativePositions(anchor, currentState.cursor.anchor) || !Yjs.compareRelativePositions(head, currentState.cursor.head)) {
|
|
45
44
|
awareness.setLocalStateField("cursor", { anchor, head });
|
|
46
45
|
}
|
|
47
46
|
} else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"awareness.es.js","sources":["../../../../../src/modules/collaborative-editing/awareness/awareness.ts"],"sourcesContent":["import type QuillCursors from 'quill-cursors'\
|
|
1
|
+
{"version":3,"file":"awareness.es.js","sources":["../../../../../src/modules/collaborative-editing/awareness/awareness.ts"],"sourcesContent":["import type QuillCursors from 'quill-cursors'\nimport type { Awareness } from 'y-protocols/awareness'\nimport type * as Y from 'yjs'\nimport type FluentEditor from '../../../core/fluent-editor'\n\nexport interface AwarenessState {\n name?: string\n color?: string\n}\n\nexport interface AwarenessEvents {\n change?: (changes: { added: number[], updated: number[], removed: number[] }, transactionOrigin: any) => void\n update?: ({ added, updated, removed }: { added: number[], updated: number[], removed: number[] }, origin: any) => void\n destroy?: () => void\n}\n\nexport interface AwarenessOptions {\n state?: AwarenessState\n events?: AwarenessEvents\n timeout?: number | undefined\n}\n\nexport function setupAwareness(options?: AwarenessOptions, defaultAwareness?: Awareness): Awareness | null {\n if (!defaultAwareness) return null\n\n const awareness = defaultAwareness\n\n if (options?.state) {\n awareness.setLocalStateField('user', options.state)\n }\n\n return awareness\n}\n\nexport function bindAwarenessToCursors(\n awareness: Awareness,\n cursorsModule: QuillCursors,\n quill: FluentEditor,\n yText: Y.Text,\n Yjs: typeof Y,\n): (() => void) | void {\n if (!cursorsModule || !awareness) return\n\n const doc = yText.doc!\n\n const updateCursor = (clientId: number, state: any) => {\n try {\n if (state?.cursor && clientId !== awareness.clientID) {\n const user = state.user || {}\n const color = user.color || '#ff6b6b'\n const name = user.name || `User ${clientId}`\n\n cursorsModule.createCursor(clientId.toString(), name, color)\n\n const anchor = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.anchor), doc)\n const head = Yjs.createAbsolutePositionFromRelativePosition(Yjs.createRelativePositionFromJSON(state.cursor.head), doc)\n\n if (anchor && head && anchor.type === yText && clientId) {\n setTimeout(() => {\n cursorsModule.moveCursor(clientId.toString(), {\n index: anchor.index,\n length: head.index - anchor.index,\n })\n }, 0)\n }\n }\n else {\n cursorsModule.removeCursor(clientId.toString())\n }\n }\n catch (err) {\n console.error('Cursor update failed:', err)\n }\n }\n\n const selectionChangeHandler = (range: { index: number, length: number } | null) => {\n setTimeout(() => {\n if (range) {\n const anchor = Yjs.createRelativePositionFromTypeIndex(yText, range.index)\n const head = Yjs.createRelativePositionFromTypeIndex(yText, range.index + range.length)\n\n const currentState = awareness.getLocalState()\n if (!currentState?.cursor\n || !Yjs.compareRelativePositions(anchor, currentState.cursor.anchor)\n || !Yjs.compareRelativePositions(head, currentState.cursor.head)) {\n awareness.setLocalStateField('cursor', { anchor, head })\n }\n }\n else {\n if (awareness.getLocalState()?.cursor !== null) {\n awareness.setLocalStateField('cursor', null)\n }\n }\n }, 0)\n }\n\n const changeHandler = ({ added, updated, removed }: {\n added: number[]\n updated: number[]\n removed: number[]\n }) => {\n if (quill.composition.isComposing) return\n const states = awareness.getStates()\n\n added.forEach((id) => {\n updateCursor(id, states.get(id))\n })\n\n updated.forEach((id) => {\n updateCursor(id, states.get(id))\n })\n\n removed.forEach((id) => {\n cursorsModule.removeCursor(id.toString())\n })\n }\n\n awareness.on('change', changeHandler)\n quill.on('editor-change', (eventName, ...args) => {\n if (quill.composition.isComposing) return\n if (eventName === 'text-change') {\n if (args[2] === 'user') {\n const range = quill.getSelection()\n selectionChangeHandler(range)\n }\n }\n else if (eventName === 'selection-change') {\n if (args[2] === 'user') {\n selectionChangeHandler(args[0] as { index: number, length: number } | null)\n }\n }\n })\n\n awareness.getStates().forEach((state, clientId) => {\n updateCursor(clientId, state)\n })\n\n return () => {\n awareness.off('change', changeHandler)\n quill.off('editor-change', selectionChangeHandler)\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
function setupIndexedDB(doc, IndexeddbPersistenceClass) {
|
|
2
|
+
if (!IndexeddbPersistenceClass) {
|
|
3
|
+
console.warn("[yjs] IndexeddbPersistence not provided, offline support disabled");
|
|
4
|
+
return () => {
|
|
5
|
+
};
|
|
6
|
+
}
|
|
3
7
|
const fullDbName = `tiny-editor-${doc.guid}`;
|
|
4
|
-
new
|
|
8
|
+
new IndexeddbPersistenceClass(fullDbName, doc);
|
|
5
9
|
return () => {
|
|
6
10
|
indexedDB.deleteDatabase(fullDbName);
|
|
7
11
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"y-indexeddb.es.js","sources":["../../../../../src/modules/collaborative-editing/awareness/y-indexeddb.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"y-indexeddb.es.js","sources":["../../../../../src/modules/collaborative-editing/awareness/y-indexeddb.ts"],"sourcesContent":["import type { IndexeddbPersistence } from 'y-indexeddb'\nimport type * as Y from 'yjs'\n\nexport function setupIndexedDB(doc: Y.Doc, IndexeddbPersistenceClass?: typeof IndexeddbPersistence): () => void {\n if (!IndexeddbPersistenceClass) {\n console.warn('[yjs] IndexeddbPersistence not provided, offline support disabled')\n return () => {}\n }\n\n const fullDbName = `tiny-editor-${doc.guid}`\n\n new IndexeddbPersistenceClass(fullDbName, doc)\n\n return (): void => {\n indexedDB.deleteDatabase(fullDbName)\n }\n}\n"],"names":[],"mappings":"AAGO,SAAS,eAAe,KAAY,2BAAqE;AAC9G,MAAI,CAAC,2BAA2B;AAC9B,YAAQ,KAAK,mEAAmE;AAChF,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AAEA,QAAM,aAAa,eAAe,IAAI,IAAI;AAE1C,MAAI,0BAA0B,YAAY,GAAG;AAE7C,SAAO,MAAY;AACjB,cAAU,eAAe,UAAU;AAAA,EACrC;AACF;"}
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import QuillCursors from "quill-cursors";
|
|
5
|
-
import { Awareness } from "y-protocols/awareness";
|
|
6
|
-
import { QuillBinding } from "y-quill";
|
|
7
|
-
import * as Y from "yjs";
|
|
8
4
|
import "./awareness/index.es.js";
|
|
9
5
|
import { setupIndexedDB } from "./awareness/y-indexeddb.es.js";
|
|
10
6
|
import { createProvider } from "./provider/providerRegistry.es.js";
|
|
11
7
|
import { setupAwareness, bindAwarenessToCursors } from "./awareness/awareness.es.js";
|
|
12
8
|
class CollaborativeEditor {
|
|
13
9
|
constructor(quill, options) {
|
|
14
|
-
__publicField(this, "ydoc"
|
|
10
|
+
__publicField(this, "ydoc");
|
|
15
11
|
__publicField(this, "provider");
|
|
16
12
|
__publicField(this, "awareness");
|
|
17
13
|
__publicField(this, "cursors");
|
|
18
14
|
__publicField(this, "cleanupBindings", null);
|
|
19
15
|
__publicField(this, "clearIndexedDB", null);
|
|
16
|
+
__publicField(this, "deps");
|
|
20
17
|
this.quill = quill;
|
|
21
18
|
this.options = options;
|
|
19
|
+
this.deps = this.options.deps || window;
|
|
20
|
+
const { Y, Awareness, QuillBinding, QuillCursors } = this.deps;
|
|
21
|
+
if (!Y || !Awareness || !QuillBinding || !QuillCursors) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
"Missing required dependencies for collaborative editing. Please provide Y, Awareness, QuillBinding, and QuillCursors in the deps option."
|
|
24
|
+
);
|
|
25
|
+
}
|
|
22
26
|
this.ydoc = this.options.ydoc || new Y.Doc();
|
|
23
27
|
if (this.options.cursors !== false) {
|
|
24
28
|
const cursorsOptions = typeof this.options.cursors === "object" ? this.options.cursors : {};
|
|
@@ -44,7 +48,8 @@ class CollaborativeEditor {
|
|
|
44
48
|
onConnect: this.options.onConnect,
|
|
45
49
|
onDisconnect: this.options.onDisconnect,
|
|
46
50
|
onError: this.options.onError,
|
|
47
|
-
onSyncChange: this.options.onSyncChange
|
|
51
|
+
onSyncChange: this.options.onSyncChange,
|
|
52
|
+
deps: this.deps
|
|
48
53
|
});
|
|
49
54
|
this.provider = provider;
|
|
50
55
|
} catch (error) {
|
|
@@ -56,7 +61,7 @@ class CollaborativeEditor {
|
|
|
56
61
|
}
|
|
57
62
|
if (this.provider) {
|
|
58
63
|
const ytext = this.ydoc.getText("tiny-editor");
|
|
59
|
-
this.cleanupBindings = bindAwarenessToCursors(this.awareness, this.cursors, quill, ytext) || null;
|
|
64
|
+
this.cleanupBindings = bindAwarenessToCursors(this.awareness, this.cursors, quill, ytext, Y) || null;
|
|
60
65
|
new QuillBinding(
|
|
61
66
|
ytext,
|
|
62
67
|
this.quill,
|
|
@@ -66,7 +71,7 @@ class CollaborativeEditor {
|
|
|
66
71
|
console.error("Failed to initialize collaborative editor: no valid provider configured");
|
|
67
72
|
}
|
|
68
73
|
if (this.options.offline !== false) {
|
|
69
|
-
this.clearIndexedDB = setupIndexedDB(this.ydoc);
|
|
74
|
+
this.clearIndexedDB = setupIndexedDB(this.ydoc, this.deps.IndexeddbPersistence);
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
getAwareness() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collaborative-editing.es.js","sources":["../../../../src/modules/collaborative-editing/collaborative-editing.ts"],"sourcesContent":["import type
|
|
1
|
+
{"version":3,"file":"collaborative-editing.es.js","sources":["../../../../src/modules/collaborative-editing/collaborative-editing.ts"],"sourcesContent":["import type QuillCursors from 'quill-cursors'\nimport type { Awareness } from 'y-protocols/awareness'\nimport type * as Y from 'yjs'\nimport type FluentEditor from '../../fluent-editor'\nimport type { UnifiedProvider } from './provider/providerRegistry'\nimport type { CollaborativeEditingDeps, YjsOptions } from './types'\nimport { bindAwarenessToCursors, setupAwareness } from './awareness'\nimport { setupIndexedDB } from './awareness/y-indexeddb'\nimport { createProvider } from './provider/providerRegistry'\n\nexport class CollaborativeEditor {\n private ydoc: Y.Doc\n private provider: UnifiedProvider\n private awareness: Awareness\n private cursors: QuillCursors | null\n private cleanupBindings: (() => void) | null = null\n private clearIndexedDB: (() => void) | null = null\n private deps: CollaborativeEditingDeps\n\n constructor(\n public quill: FluentEditor,\n public options: YjsOptions,\n ) {\n this.deps = this.options.deps || (window as any)\n const { Y, Awareness, QuillBinding, QuillCursors } = this.deps\n\n if (!Y || !Awareness || !QuillBinding || !QuillCursors) {\n throw new Error(\n 'Missing required dependencies for collaborative editing. '\n + 'Please provide Y, Awareness, QuillBinding, and QuillCursors in the deps option.',\n )\n }\n\n this.ydoc = this.options.ydoc || new Y.Doc()\n\n if (this.options.cursors !== false) {\n const cursorsOptions = typeof this.options.cursors === 'object' ? this.options.cursors : {}\n this.cursors = new QuillCursors(quill, cursorsOptions)\n }\n\n if (this.options.awareness) {\n const awareness = setupAwareness(this.options.awareness, new Awareness(this.ydoc))\n if (!awareness) {\n throw new Error('Failed to initialize awareness')\n }\n this.awareness = awareness\n }\n else {\n this.awareness = new Awareness(this.ydoc)\n }\n\n if (this.options.provider) {\n const providerConfig = this.options.provider\n try {\n const provider = createProvider({\n doc: this.ydoc,\n options: providerConfig.options,\n type: providerConfig.type,\n awareness: this.awareness,\n onConnect: this.options.onConnect,\n onDisconnect: this.options.onDisconnect,\n onError: this.options.onError,\n onSyncChange: this.options.onSyncChange,\n deps: this.deps,\n })\n this.provider = provider\n }\n catch (error) {\n console.warn(\n `[yjs] Error creating provider of type ${providerConfig.type}:`,\n error,\n )\n }\n }\n\n if (this.provider) {\n const ytext = this.ydoc.getText('tiny-editor')\n this.cleanupBindings = bindAwarenessToCursors(this.awareness, this.cursors, quill, ytext, Y) || null\n new QuillBinding(\n ytext,\n this.quill,\n this.awareness,\n )\n }\n else {\n console.error('Failed to initialize collaborative editor: no valid provider configured')\n }\n\n if (this.options.offline !== false) {\n this.clearIndexedDB = setupIndexedDB(this.ydoc, this.deps.IndexeddbPersistence)\n }\n }\n\n public getAwareness() {\n return this.awareness\n }\n\n public getProvider() {\n return this.provider\n }\n\n public getYDoc() {\n return this.ydoc\n }\n\n get isConnected() {\n return this.provider?.isConnected ?? false\n }\n\n get isSynced() {\n return this.provider?.isSynced ?? false\n }\n\n public getCursors() {\n return this.cursors\n }\n\n public async destroy() {\n this.cleanupBindings?.()\n this.provider?.destroy?.()\n this.cursors?.clearCursors()\n this.awareness?.destroy?.()\n this.clearIndexedDB?.()\n this.ydoc?.destroy?.()\n }\n}\n"],"names":[],"mappings":";;;;;;;AAUO,MAAM,oBAAoB;AAAA,EAS/B,YACS,OACA,SACP;AAXM;AACA;AACA;AACA;AACA,2CAAuC;AACvC,0CAAsC;AACtC;AAGC,SAAA,QAAA;AACA,SAAA,UAAA;AAEP,SAAK,OAAO,KAAK,QAAQ,QAAS;AAClC,UAAM,EAAE,GAAG,WAAW,cAAc,aAAA,IAAiB,KAAK;AAE1D,QAAI,CAAC,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,cAAc;AACtD,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAGJ;AAEA,SAAK,OAAO,KAAK,QAAQ,QAAQ,IAAI,EAAE,IAAA;AAEvC,QAAI,KAAK,QAAQ,YAAY,OAAO;AAClC,YAAM,iBAAiB,OAAO,KAAK,QAAQ,YAAY,WAAW,KAAK,QAAQ,UAAU,CAAA;AACzF,WAAK,UAAU,IAAI,aAAa,OAAO,cAAc;AAAA,IACvD;AAEA,QAAI,KAAK,QAAQ,WAAW;AAC1B,YAAM,YAAY,eAAe,KAAK,QAAQ,WAAW,IAAI,UAAU,KAAK,IAAI,CAAC;AACjF,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AACA,WAAK,YAAY;AAAA,IACnB,OACK;AACH,WAAK,YAAY,IAAI,UAAU,KAAK,IAAI;AAAA,IAC1C;AAEA,QAAI,KAAK,QAAQ,UAAU;AACzB,YAAM,iBAAiB,KAAK,QAAQ;AACpC,UAAI;AACF,cAAM,WAAW,eAAe;AAAA,UAC9B,KAAK,KAAK;AAAA,UACV,SAAS,eAAe;AAAA,UACxB,MAAM,eAAe;AAAA,UACrB,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK,QAAQ;AAAA,UACxB,cAAc,KAAK,QAAQ;AAAA,UAC3B,SAAS,KAAK,QAAQ;AAAA,UACtB,cAAc,KAAK,QAAQ;AAAA,UAC3B,MAAM,KAAK;AAAA,QAAA,CACZ;AACD,aAAK,WAAW;AAAA,MAClB,SACO,OAAO;AACZ,gBAAQ;AAAA,UACN,yCAAyC,eAAe,IAAI;AAAA,UAC5D;AAAA,QAAA;AAAA,MAEJ;AAAA,IACF;AAEA,QAAI,KAAK,UAAU;AACjB,YAAM,QAAQ,KAAK,KAAK,QAAQ,aAAa;AAC7C,WAAK,kBAAkB,uBAAuB,KAAK,WAAW,KAAK,SAAS,OAAO,OAAO,CAAC,KAAK;AAChG,UAAI;AAAA,QACF;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MAAA;AAAA,IAET,OACK;AACH,cAAQ,MAAM,yEAAyE;AAAA,IACzF;AAEA,QAAI,KAAK,QAAQ,YAAY,OAAO;AAClC,WAAK,iBAAiB,eAAe,KAAK,MAAM,KAAK,KAAK,oBAAoB;AAAA,IAChF;AAAA,EACF;AAAA,EAEO,eAAe;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,cAAc;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,UAAU;AACf,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,cAAc;;AAChB,aAAO,UAAK,aAAL,mBAAe,gBAAe;AAAA,EACvC;AAAA,EAEA,IAAI,WAAW;;AACb,aAAO,UAAK,aAAL,mBAAe,aAAY;AAAA,EACpC;AAAA,EAEO,aAAa;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAa,UAAU;;AACrB,eAAK,oBAAL;AACA,qBAAK,aAAL,mBAAe,YAAf;AACA,eAAK,YAAL,mBAAc;AACd,qBAAK,cAAL,mBAAgB,YAAhB;AACA,eAAK,mBAAL;AACA,qBAAK,SAAL,mBAAW,YAAX;AAAA,EACF;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.es.js","sources":["../../../../src/modules/collaborative-editing/module.ts"],"sourcesContent":["import type FluentEditor from '../../fluent-editor'\
|
|
1
|
+
{"version":3,"file":"module.es.js","sources":["../../../../src/modules/collaborative-editing/module.ts"],"sourcesContent":["import type FluentEditor from '../../fluent-editor'\nimport { CollaborativeEditor } from './collaborative-editing'\n\nexport class CollaborationModule {\n private collaborativeEditor: CollaborativeEditor\n\n constructor(public quill: FluentEditor, public options: any) {\n this.collaborativeEditor = new CollaborativeEditor(quill, options)\n\n window.addEventListener(\n 'beforeunload',\n () => { void this.collaborativeEditor.destroy().catch(err => console.warn('[yjs] destroy failed:', err)) },\n { once: true },\n )\n }\n\n public getCursors() {\n return this.collaborativeEditor.getCursors()\n }\n\n public getAwareness() {\n return this.collaborativeEditor.getAwareness()\n }\n\n public getProvider() {\n return this.collaborativeEditor.getProvider()\n }\n\n public async destroy() {\n await this.collaborativeEditor.destroy()\n }\n}\n"],"names":[],"mappings":";;;;AAGO,MAAM,oBAAoB;AAAA,EAG/B,YAAmB,OAA4B,SAAc;AAFrD;AAEW,SAAA,QAAA;AAA4B,SAAA,UAAA;AAC7C,SAAK,sBAAsB,IAAI,oBAAoB,OAAO,OAAO;AAEjE,WAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAE,aAAK,KAAK,oBAAoB,QAAA,EAAU,MAAM,SAAO,QAAQ,KAAK,yBAAyB,GAAG,CAAC;AAAA,MAAE;AAAA,MACzG,EAAE,MAAM,KAAA;AAAA,IAAK;AAAA,EAEjB;AAAA,EAEO,aAAa;AAClB,WAAO,KAAK,oBAAoB,WAAA;AAAA,EAClC;AAAA,EAEO,eAAe;AACpB,WAAO,KAAK,oBAAoB,aAAA;AAAA,EAClC;AAAA,EAEO,cAAc;AACnB,WAAO,KAAK,oBAAoB,YAAA;AAAA,EAClC;AAAA,EAEA,MAAa,UAAU;AACrB,UAAM,KAAK,oBAAoB,QAAA;AAAA,EACjC;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providerRegistry.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/providerRegistry.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\
|
|
1
|
+
{"version":3,"file":"providerRegistry.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/providerRegistry.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\nimport type * as Y from 'yjs'\nimport type { CollaborativeEditingDeps, ProviderEventHandlers } from '../types'\nimport { WebRTCProviderWrapper } from './webrtc'\nimport { WebsocketProviderWrapper } from './websocket'\n\nexport type ProviderRegistry = Record<string, ProviderConstructor>\n\nexport type ProviderConstructor<T = any> = new (\n props: ProviderConstructorProps<T>\n) => UnifiedProvider\n\nexport type ProviderConstructorProps<T = any> = {\n options: T\n awareness?: Awareness\n doc?: Y.Doc\n deps?: CollaborativeEditingDeps\n} & ProviderEventHandlers\n\nexport interface UnifiedProvider extends ProviderEventHandlers {\n awareness: Awareness\n document: Y.Doc\n type: 'webrtc' | 'websocket' | string\n connect: () => void\n destroy: () => void\n disconnect: () => void\n isConnected: boolean\n isSynced: boolean\n}\n\nconst providerRegistry: ProviderRegistry = {\n websocket: WebsocketProviderWrapper,\n webrtc: WebRTCProviderWrapper,\n}\n\nexport function registerProviderType<T>(type: string, providerClass: ProviderConstructor<T>) {\n providerRegistry[type as string]\n = providerClass as ProviderConstructor\n}\n\nexport function getProviderClass(type: string): ProviderConstructor | undefined {\n return providerRegistry[type]\n}\n\nexport function createProvider({\n type,\n ...props\n}: ProviderConstructorProps & {\n type: string\n}) {\n const ProviderClass = getProviderClass(type)\n\n if (!ProviderClass) {\n throw new Error(`Provider type \"${type}\" not found in registry`)\n }\n\n return new ProviderClass(props)\n}\n"],"names":[],"mappings":";;AA8BA,MAAM,mBAAqC;AAAA,EACzC,WAAW;AAAA,EACX,QAAQ;AACV;AAEO,SAAS,qBAAwB,MAAc,eAAuC;AAC3F,mBAAiB,IAAc,IAC3B;AACN;AAEO,SAAS,iBAAiB,MAA+C;AAC9E,SAAO,iBAAiB,IAAI;AAC9B;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA,GAAG;AACL,GAEG;AACD,QAAM,gBAAgB,iBAAiB,IAAI;AAE3C,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,kBAAkB,IAAI,yBAAyB;AAAA,EACjE;AAEA,SAAO,IAAI,cAAc,KAAK;AAChC;"}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { WebrtcProvider } from "y-webrtc";
|
|
5
|
-
import * as Y from "yjs";
|
|
6
4
|
class WebRTCProviderWrapper {
|
|
7
5
|
constructor({
|
|
8
6
|
awareness,
|
|
@@ -11,7 +9,8 @@ class WebRTCProviderWrapper {
|
|
|
11
9
|
onConnect,
|
|
12
10
|
onDisconnect,
|
|
13
11
|
onError,
|
|
14
|
-
onSyncChange
|
|
12
|
+
onSyncChange,
|
|
13
|
+
deps
|
|
15
14
|
}) {
|
|
16
15
|
__publicField(this, "provider");
|
|
17
16
|
__publicField(this, "_isConnected", false);
|
|
@@ -50,10 +49,15 @@ class WebRTCProviderWrapper {
|
|
|
50
49
|
this.onDisconnect = onDisconnect;
|
|
51
50
|
this.onError = onError;
|
|
52
51
|
this.onSyncChange = onSyncChange;
|
|
52
|
+
const { Y, Awareness, WebrtcProvider } = deps || window;
|
|
53
|
+
if (!WebrtcProvider) {
|
|
54
|
+
throw new Error("WebrtcProvider dependency not provided");
|
|
55
|
+
}
|
|
53
56
|
this.document = doc || new Y.Doc();
|
|
57
|
+
this.awareness = awareness ?? new Awareness(this.document);
|
|
54
58
|
try {
|
|
55
59
|
this.provider = new WebrtcProvider(options.roomName, this.document, {
|
|
56
|
-
awareness,
|
|
60
|
+
awareness: this.awareness,
|
|
57
61
|
...options
|
|
58
62
|
});
|
|
59
63
|
this.provider.on("status", (status) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webrtc.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/webrtc.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\
|
|
1
|
+
{"version":3,"file":"webrtc.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/webrtc.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\nimport type { WebrtcProvider } from 'y-webrtc'\nimport type * as Y from 'yjs'\nimport type { CollaborativeEditingDeps, ProviderEventHandlers } from '../types'\nimport type { UnifiedProvider } from './providerRegistry'\n\nexport interface WebRTCProviderOptions {\n roomName: string\n filterBcConns?: boolean\n maxConns?: number\n password?: string\n peerOpts?: Record<string, unknown>\n signaling?: string[]\n}\n\nexport class WebRTCProviderWrapper implements UnifiedProvider {\n private provider: WebrtcProvider\n private _isConnected = false\n private _isSynced = false\n\n onConnect?: () => void\n onDisconnect?: () => void\n onError?: (error: Error) => void\n onSyncChange?: (isSynced: boolean) => void\n\n document: Y.Doc\n awareness: Awareness\n type: 'webrtc'\n\n connect = () => {\n try {\n this.provider.connect()\n }\n catch (error) {\n console.warn('[yjs] Error connecting WebRTC provider:', error)\n }\n }\n\n destroy = () => {\n try {\n this.provider.destroy()\n }\n catch (error) {\n console.warn('[yjs] Error destroying WebRTC provider:', error)\n }\n }\n\n disconnect = () => {\n try {\n this.provider.disconnect()\n this._isConnected = false\n this._isSynced = false\n }\n catch (error) {\n console.warn('[yjs] Error disconnecting WebRTC provider:', error)\n }\n }\n\n constructor({\n awareness,\n doc,\n options,\n onConnect,\n onDisconnect,\n onError,\n onSyncChange,\n deps,\n }: {\n options: WebRTCProviderOptions\n awareness?: Awareness\n doc?: Y.Doc\n deps?: CollaborativeEditingDeps\n } & ProviderEventHandlers) {\n this.onConnect = onConnect\n this.onDisconnect = onDisconnect\n this.onError = onError\n this.onSyncChange = onSyncChange\n\n const { Y, Awareness, WebrtcProvider } = deps || (window as any)\n\n if (!WebrtcProvider) {\n throw new Error('WebrtcProvider dependency not provided')\n }\n\n this.document = doc || new Y.Doc()\n this.awareness = awareness ?? new Awareness(this.document)\n try {\n this.provider = new WebrtcProvider(options.roomName, this.document, {\n awareness: this.awareness,\n ...options,\n })\n\n this.provider.on('status', (status: { connected: boolean }) => {\n const wasConnected = this._isConnected\n this._isConnected = status.connected\n if (status.connected) {\n if (!wasConnected) {\n this.onConnect?.()\n }\n if (!this._isSynced) {\n this._isSynced = true\n this.onSyncChange?.(true)\n }\n }\n else {\n if (wasConnected) {\n this.onDisconnect?.()\n\n if (this._isSynced) {\n this._isSynced = false\n this.onSyncChange?.(false)\n }\n }\n }\n })\n }\n catch (error) {\n console.warn('[yjs] Error creating WebRTC provider:', error)\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n get isConnected() {\n return this._isConnected\n }\n\n get isSynced() {\n return this._isSynced\n }\n\n getProvider() {\n return this.provider\n }\n}\n"],"names":[],"mappings":";;;AAeO,MAAM,sBAAiD;AAAA,EA2C5D,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GAMyB;AAxDnB;AACA,wCAAe;AACf,qCAAY;AAEpB;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,2CAA2C,KAAK;AAAA,MAC/D;AAAA,IACF;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,2CAA2C,KAAK;AAAA,MAC/D;AAAA,IACF;AAEA,sCAAa,MAAM;AACjB,UAAI;AACF,aAAK,SAAS,WAAA;AACd,aAAK,eAAe;AACpB,aAAK,YAAY;AAAA,MACnB,SACO,OAAO;AACZ,gBAAQ,KAAK,8CAA8C,KAAK;AAAA,MAClE;AAAA,IACF;AAiBE,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,eAAe;AAEpB,UAAM,EAAE,GAAG,WAAW,eAAA,IAAmB,QAAS;AAElD,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAEA,SAAK,WAAW,OAAO,IAAI,EAAE,IAAA;AAC7B,SAAK,YAAY,aAAa,IAAI,UAAU,KAAK,QAAQ;AACzD,QAAI;AACF,WAAK,WAAW,IAAI,eAAe,QAAQ,UAAU,KAAK,UAAU;AAAA,QAClE,WAAW,KAAK;AAAA,QAChB,GAAG;AAAA,MAAA,CACJ;AAED,WAAK,SAAS,GAAG,UAAU,CAAC,WAAmC;AA7E9D;AA8EC,cAAM,eAAe,KAAK;AAC1B,aAAK,eAAe,OAAO;AAC3B,YAAI,OAAO,WAAW;AACpB,cAAI,CAAC,cAAc;AACjB,uBAAK,cAAL;AAAA,UACF;AACA,cAAI,CAAC,KAAK,WAAW;AACnB,iBAAK,YAAY;AACjB,uBAAK,iBAAL,8BAAoB;AAAA,UACtB;AAAA,QACF,OACK;AACH,cAAI,cAAc;AAChB,uBAAK,iBAAL;AAEA,gBAAI,KAAK,WAAW;AAClB,mBAAK,YAAY;AACjB,yBAAK,iBAAL,8BAAoB;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SACO,OAAO;AACZ,cAAQ,KAAK,yCAAyC,KAAK;AAC3D,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAW;AACb,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,cAAc;AACZ,WAAO,KAAK;AAAA,EACd;AACF;"}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { Awareness } from "y-protocols/awareness";
|
|
5
|
-
import { WebsocketProvider } from "y-websocket";
|
|
6
|
-
import * as Y from "yjs";
|
|
7
4
|
class WebsocketProviderWrapper {
|
|
8
5
|
constructor({
|
|
9
6
|
awareness,
|
|
@@ -12,7 +9,8 @@ class WebsocketProviderWrapper {
|
|
|
12
9
|
onConnect,
|
|
13
10
|
onDisconnect,
|
|
14
11
|
onError,
|
|
15
|
-
onSyncChange
|
|
12
|
+
onSyncChange,
|
|
13
|
+
deps
|
|
16
14
|
}) {
|
|
17
15
|
__publicField(this, "provider");
|
|
18
16
|
__publicField(this, "_isConnected", false);
|
|
@@ -56,6 +54,10 @@ class WebsocketProviderWrapper {
|
|
|
56
54
|
this.onDisconnect = onDisconnect;
|
|
57
55
|
this.onError = onError;
|
|
58
56
|
this.onSyncChange = onSyncChange;
|
|
57
|
+
const { Y, Awareness, WebsocketProvider } = deps || window;
|
|
58
|
+
if (!WebsocketProvider) {
|
|
59
|
+
throw new Error("WebsocketProvider dependency not provided");
|
|
60
|
+
}
|
|
59
61
|
this.document = doc || new Y.Doc();
|
|
60
62
|
this.awareness = awareness ?? new Awareness(this.document);
|
|
61
63
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/websocket.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"websocket.es.js","sources":["../../../../../src/modules/collaborative-editing/provider/websocket.ts"],"sourcesContent":["import type { Awareness } from 'y-protocols/awareness'\nimport type { WebsocketProvider } from 'y-websocket'\nimport type * as Y from 'yjs'\nimport type { CollaborativeEditingDeps, ProviderEventHandlers } from '../types'\nimport type { UnifiedProvider } from './providerRegistry'\n\nexport interface WebsocketProviderOptions {\n serverUrl: string\n roomName: string\n connect?: boolean\n awareness?: Awareness\n params?: Record<string, string>\n protocols?: string[]\n WebSocketPolyfill?: typeof WebSocket\n resyncInterval?: number\n maxBackoffTime?: number\n disableBc?: boolean\n}\n\nexport class WebsocketProviderWrapper implements UnifiedProvider {\n private provider: WebsocketProvider\n\n private _isConnected = false\n private _isSynced = false\n\n onConnect?: () => void\n onDisconnect?: () => void\n onError?: (error: Error) => void\n onSyncChange?: (isSynced: boolean) => void\n\n document: Y.Doc\n awareness: Awareness\n type: 'websocket'\n\n connect = () => {\n try {\n this.provider.connect()\n }\n catch (error) {\n console.warn('[yjs] Error connecting WebSocket provider:', error)\n }\n }\n\n destroy = () => {\n try {\n this.provider.destroy()\n }\n catch (error) {\n console.warn('[yjs] Error destroying WebSocket provider:', error)\n }\n }\n\n disconnect = () => {\n try {\n this.provider.disconnect()\n const wasSynced = this._isSynced\n\n this._isConnected = false\n this._isSynced = false\n\n if (wasSynced) {\n this.onSyncChange?.(false)\n }\n }\n catch (error) {\n console.warn('[yjs] Error disconnecting WebSocket provider:', error)\n }\n }\n\n constructor({\n awareness,\n doc,\n options,\n onConnect,\n onDisconnect,\n onError,\n onSyncChange,\n deps,\n }: {\n options: WebsocketProviderOptions\n awareness?: Awareness\n doc?: Y.Doc\n deps?: CollaborativeEditingDeps\n } & ProviderEventHandlers) {\n this.onConnect = onConnect\n this.onDisconnect = onDisconnect\n this.onError = onError\n this.onSyncChange = onSyncChange\n\n const { Y, Awareness, WebsocketProvider } = deps || (window as any)\n\n if (!WebsocketProvider) {\n throw new Error('WebsocketProvider dependency not provided')\n }\n\n this.document = doc || new Y.Doc()\n this.awareness = awareness ?? new Awareness(this.document)\n try {\n this.provider = new WebsocketProvider(\n options.serverUrl,\n options.roomName,\n this.document,\n {\n awareness: this.awareness,\n ...options,\n },\n )\n\n this.provider.on('status', (event: { status: 'connected' | 'disconnected' | 'connecting' }) => {\n const wasConnected = this._isConnected\n this._isConnected = event.status === 'connected'\n\n if (event.status === 'connected') {\n if (!wasConnected) {\n this.onConnect?.()\n }\n if (!this._isSynced) {\n this._isSynced = true\n this.onSyncChange?.(true)\n }\n }\n else if (event.status === 'disconnected') {\n if (wasConnected) {\n this.onDisconnect?.()\n if (this._isSynced) {\n this._isSynced = false\n this.onSyncChange?.(false)\n }\n }\n }\n })\n }\n catch (error) {\n console.warn('[yjs] Error creating WebSocket provider:', error)\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n get isConnected() {\n return this._isConnected\n }\n\n get isSynced() {\n return this._isSynced\n }\n\n getProvider() {\n return this.provider\n }\n}\n"],"names":[],"mappings":";;;AAmBO,MAAM,yBAAoD;AAAA,EAkD/D,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GAMyB;AA/DnB;AAEA,wCAAe;AACf,qCAAY;AAEpB;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,8CAA8C,KAAK;AAAA,MAClE;AAAA,IACF;AAEA,mCAAU,MAAM;AACd,UAAI;AACF,aAAK,SAAS,QAAA;AAAA,MAChB,SACO,OAAO;AACZ,gBAAQ,KAAK,8CAA8C,KAAK;AAAA,MAClE;AAAA,IACF;AAEA,sCAAa,MAAM;AAjCd;AAkCH,UAAI;AACF,aAAK,SAAS,WAAA;AACd,cAAM,YAAY,KAAK;AAEvB,aAAK,eAAe;AACpB,aAAK,YAAY;AAEjB,YAAI,WAAW;AACb,qBAAK,iBAAL,8BAAoB;AAAA,QACtB;AAAA,MACF,SACO,OAAO;AACZ,gBAAQ,KAAK,iDAAiD,KAAK;AAAA,MACrE;AAAA,IACF;AAiBE,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,eAAe;AAEpB,UAAM,EAAE,GAAG,WAAW,kBAAA,IAAsB,QAAS;AAErD,QAAI,CAAC,mBAAmB;AACtB,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AAEA,SAAK,WAAW,OAAO,IAAI,EAAE,IAAA;AAC7B,SAAK,YAAY,aAAa,IAAI,UAAU,KAAK,QAAQ;AACzD,QAAI;AACF,WAAK,WAAW,IAAI;AAAA,QAClB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,KAAK;AAAA,QACL;AAAA,UACE,WAAW,KAAK;AAAA,UAChB,GAAG;AAAA,QAAA;AAAA,MACL;AAGF,WAAK,SAAS,GAAG,UAAU,CAAC,UAAmE;AAzF9F;AA0FC,cAAM,eAAe,KAAK;AAC1B,aAAK,eAAe,MAAM,WAAW;AAErC,YAAI,MAAM,WAAW,aAAa;AAChC,cAAI,CAAC,cAAc;AACjB,uBAAK,cAAL;AAAA,UACF;AACA,cAAI,CAAC,KAAK,WAAW;AACnB,iBAAK,YAAY;AACjB,uBAAK,iBAAL,8BAAoB;AAAA,UACtB;AAAA,QACF,WACS,MAAM,WAAW,gBAAgB;AACxC,cAAI,cAAc;AAChB,uBAAK,iBAAL;AACA,gBAAI,KAAK,WAAW;AAClB,mBAAK,YAAY;AACjB,yBAAK,iBAAL,8BAAoB;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SACO,OAAO;AACZ,cAAQ,KAAK,4CAA4C,KAAK;AAC9D,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAW;AACb,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,cAAc;AACZ,WAAO,KAAK;AAAA,EACd;AACF;"}
|