@opentiny/fluent-editor 4.1.0-alpha.4 → 4.1.1
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/es/config/editor.config.es.js +1 -1
- package/es/config/editor.config.es.js.map +1 -1
- package/es/config/i18n/en-us.es.js +4 -1
- package/es/config/i18n/en-us.es.js.map +1 -1
- package/es/config/i18n/zh-cn.es.js +4 -1
- package/es/config/i18n/zh-cn.es.js.map +1 -1
- package/es/core/fluent-editor.es.js +29 -4
- package/es/core/fluent-editor.es.js.map +1 -1
- package/es/fluent-editor.es.js +2 -11
- package/es/fluent-editor.es.js.map +1 -1
- package/es/formats/strike.es.js +1 -1
- package/es/formats/strike.es.js.map +1 -1
- package/es/index.es.js +3 -3
- package/es/index.es.js.map +1 -1
- package/es/modules/counter.es.js +2 -3
- package/es/modules/counter.es.js.map +1 -1
- package/es/modules/custom-clipboard.es.js +13 -1
- package/es/modules/custom-clipboard.es.js.map +1 -1
- package/es/modules/custom-image/blot-formatter.es.js +2 -2
- package/es/modules/custom-image/blot-formatter.es.js.map +1 -1
- package/es/modules/custom-image/index.es.js +1 -1
- package/es/modules/custom-image/preview/preview-modal.es.js +17 -6
- package/es/modules/custom-image/preview/preview-modal.es.js.map +1 -1
- package/es/modules/custom-image/specs/custom-image-spec.es.js.map +1 -1
- package/es/modules/custom-uploader.es.js.map +1 -1
- package/es/modules/file/modules/file-module.es.js.map +1 -1
- package/es/modules/flow-chart/i18n/index.es.js +3 -5
- package/es/modules/flow-chart/i18n/index.es.js.map +1 -1
- package/es/modules/flow-chart/modules/context-menu.es.js +10 -13
- package/es/modules/flow-chart/modules/context-menu.es.js.map +1 -1
- package/es/modules/flow-chart/modules/control-panel.es.js +13 -16
- package/es/modules/flow-chart/modules/control-panel.es.js.map +1 -1
- package/es/modules/index.es.js +2 -2
- package/es/modules/index.es.js.map +1 -1
- package/es/modules/link/modules/tooltip.es.js +42 -27
- package/es/modules/link/modules/tooltip.es.js.map +1 -1
- package/es/modules/mind-map/i18n/index.es.js +3 -5
- package/es/modules/mind-map/i18n/index.es.js.map +1 -1
- package/es/modules/mind-map/modules/context-menu.es.js +11 -11
- package/es/modules/mind-map/modules/context-menu.es.js.map +1 -1
- package/es/modules/mind-map/modules/control-panel.es.js +7 -9
- package/es/modules/mind-map/modules/control-panel.es.js.map +1 -1
- package/es/modules/shortcut-key/index.es.js +6 -6
- package/es/modules/shortcut-key/index.es.js.map +1 -1
- package/es/modules/table-up/index.es.js +23 -33
- package/es/modules/table-up/index.es.js.map +1 -1
- package/es/modules/toolbar/toolbar-tip.es.js +27 -5
- package/es/modules/toolbar/toolbar-tip.es.js.map +1 -1
- package/es/themes/snow.es.js +2 -2
- package/es/themes/snow.es.js.map +1 -1
- package/lib/config/editor.config.cjs.js +1 -1
- package/lib/config/editor.config.cjs.js.map +1 -1
- package/lib/config/i18n/en-us.cjs.js +4 -1
- package/lib/config/i18n/en-us.cjs.js.map +1 -1
- package/lib/config/i18n/zh-cn.cjs.js +4 -1
- package/lib/config/i18n/zh-cn.cjs.js.map +1 -1
- package/lib/core/fluent-editor.cjs.js +29 -4
- package/lib/core/fluent-editor.cjs.js.map +1 -1
- package/lib/fluent-editor.cjs.js +2 -11
- package/lib/fluent-editor.cjs.js.map +1 -1
- package/lib/formats/strike.cjs.js +1 -1
- package/lib/formats/strike.cjs.js.map +1 -1
- package/lib/index.cjs.js +16 -5
- package/lib/index.cjs.js.map +1 -1
- package/lib/modules/counter.cjs.js +2 -3
- package/lib/modules/counter.cjs.js.map +1 -1
- package/lib/modules/custom-clipboard.cjs.js +13 -1
- package/lib/modules/custom-clipboard.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/index.cjs.js +1 -1
- package/lib/modules/custom-image/preview/preview-modal.cjs.js +17 -6
- package/lib/modules/custom-image/preview/preview-modal.cjs.js.map +1 -1
- package/lib/modules/custom-image/specs/custom-image-spec.cjs.js.map +1 -1
- package/lib/modules/custom-uploader.cjs.js.map +1 -1
- package/lib/modules/file/modules/file-module.cjs.js.map +1 -1
- package/lib/modules/flow-chart/i18n/index.cjs.js +3 -5
- package/lib/modules/flow-chart/i18n/index.cjs.js.map +1 -1
- package/lib/modules/flow-chart/modules/context-menu.cjs.js +10 -13
- package/lib/modules/flow-chart/modules/context-menu.cjs.js.map +1 -1
- package/lib/modules/flow-chart/modules/control-panel.cjs.js +13 -16
- package/lib/modules/flow-chart/modules/control-panel.cjs.js.map +1 -1
- package/lib/modules/index.cjs.js +14 -2
- package/lib/modules/index.cjs.js.map +1 -1
- package/lib/modules/link/modules/tooltip.cjs.js +42 -27
- package/lib/modules/link/modules/tooltip.cjs.js.map +1 -1
- package/lib/modules/mind-map/i18n/index.cjs.js +3 -5
- package/lib/modules/mind-map/i18n/index.cjs.js.map +1 -1
- package/lib/modules/mind-map/modules/context-menu.cjs.js +11 -11
- package/lib/modules/mind-map/modules/context-menu.cjs.js.map +1 -1
- package/lib/modules/mind-map/modules/control-panel.cjs.js +7 -9
- package/lib/modules/mind-map/modules/control-panel.cjs.js.map +1 -1
- package/lib/modules/shortcut-key/index.cjs.js +4 -4
- package/lib/modules/shortcut-key/index.cjs.js.map +1 -1
- package/lib/modules/table-up/index.cjs.js +23 -33
- package/lib/modules/table-up/index.cjs.js.map +1 -1
- package/lib/modules/toolbar/toolbar-tip.cjs.js +26 -4
- package/lib/modules/toolbar/toolbar-tip.cjs.js.map +1 -1
- package/lib/themes/snow.cjs.js +2 -2
- package/lib/themes/snow.cjs.js.map +1 -1
- package/package.json +3 -2
- package/style.css +149 -144
- package/types/config/editor.config.d.ts +4 -2
- package/types/config/i18n/en-us.d.ts +4 -1
- package/types/config/i18n/zh-cn.d.ts +4 -1
- package/types/config/types/editor-modules.interface.d.ts +3 -2
- package/types/core/fluent-editor.d.ts +1 -1
- package/types/modules/custom-clipboard.d.ts +2 -0
- package/types/modules/custom-image/index.d.ts +1 -1
- package/types/modules/custom-image/preview/preview-modal.d.ts +1 -0
- package/types/modules/flow-chart/i18n/index.d.ts +1 -1
- package/types/modules/index.d.ts +2 -1
- package/types/modules/link/modules/tooltip.d.ts +1 -0
- package/types/modules/mind-map/i18n/index.d.ts +1 -1
- package/types/modules/table-up/index.d.ts +3 -26
- package/es/modules/i18n.es.js +0 -62
- package/es/modules/i18n.es.js.map +0 -1
- package/lib/modules/i18n.cjs.js +0 -62
- package/lib/modules/i18n.cjs.js.map +0 -1
- package/types/modules/i18n.d.ts +0 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blot-formatter.es.js","sources":["../../../../src/modules/custom-image/blot-formatter.ts"],"sourcesContent":["import type FluentEditor from '../../core/fluent-editor'\nimport type { Action } from './actions'\nimport type { BlotFormatterOptions } from './options'\nimport type { BlotSpec } from './specs'\nimport Quill from 'quill'\nimport { merge as deepmerge } from '../../utils/merge'\nimport { CustomImage } from './image'\nimport DefaultOptions from './options'\nimport { CustomImageSpec } from './specs'\n\nconst dontMerge = (_destination: Array<any>, source: Array<any>) => source\n\nexport class BlotFormatter {\n options: BlotFormatterOptions\n currentSpec: BlotSpec\n specs: BlotSpec[]\n overlay: HTMLElement\n actions: Action[]\n observer: MutationObserver\n\n static register() {\n Quill.register({\n 'formats/image': CustomImage,\n 'modules/image-spec': CustomImageSpec,\n }, true)\n }\n\n constructor(public quill: FluentEditor, options: Partial<BlotFormatterOptions> = {}) {\n this.options = deepmerge({}, DefaultOptions, options, { arrayMerge: dontMerge })\n if (options.allowInvalidUrl !== undefined) {\n this.options.allowInvalidUrl = options.allowInvalidUrl\n }\n CustomImage.setOptions(this.options.allowInvalidUrl)\n this.currentSpec = null\n this.actions = []\n this.overlay = document.createElement('div')\n this.overlay.classList.add(this.options.overlay.className)\n if (this.options.overlay.style) {\n Object.assign(this.overlay.style, this.options.overlay.style)\n }\n\n // disable native image resizing on firefox\n document.execCommand('enableObjectResizing', false, 'false') // eslint-disable-next-line-line no-undef\n this.quill.root.addEventListener('click', this.onClick)\n this.specs = this.options.specs.map((SpecClass: any) => new SpecClass(this))\n this.specs.forEach(spec => spec.init())\n }\n\n show(spec: BlotSpec) {\n this.currentSpec = spec\n this.currentSpec.setSelection()\n this.setUserSelect('none')\n this.quill.root.parentNode.appendChild(this.overlay)\n this.repositionOverlay()\n this.createActions(spec)\n\n // fix: 图片对齐之后,虚线外框应该跟随移动\n const imageDom = spec.getTargetElement()\n const win: any = window\n const MutationObserver: typeof window.MutationObserver = win.MutationObserver || win.WebKitMutationObserver || win.MozMutationObserver\n const element = imageDom.parentNode\n this.observer = new MutationObserver((mutationList) => {\n for (const mutation of mutationList) {\n const target = mutation.target as HTMLElement\n const image = target.querySelector('img')\n if (image) {\n this.repositionOverlay()\n }\n }\n })\n this.observer.observe(element, {\n attributes: true,\n attributeFilter: ['class'],\n attributeOldValue: true,\n subtree: true,\n })\n }\n\n hide() {\n if (!this.currentSpec) {\n return\n }\n\n const imgDom = this.currentSpec.getTargetElement()\n if (imgDom) {\n imgDom.classList.remove('current-select-img')\n }\n\n this.currentSpec.onHide()\n this.currentSpec = null\n this.quill.root.parentNode.removeChild(this.overlay)\n this.overlay.style.setProperty('display', 'none')\n this.setUserSelect('')\n this.destroyActions()\n }\n\n update() {\n this.repositionOverlay()\n this.actions.forEach(action => action.onUpdate())\n }\n\n createActions(spec: BlotSpec) {\n this.actions = spec.getActions().map((ActionClass: any) => {\n const action: Action = new ActionClass(this)\n action.onCreate()\n return action\n })\n }\n\n destroyActions() {\n this.actions.forEach((action: Action) => action.onDestroy())\n this.actions = []\n }\n\n repositionOverlay() {\n if (!this.currentSpec) {\n return\n }\n\n const overlayTarget = this.currentSpec.getOverlayElement()\n if (!overlayTarget) {\n return\n }\n\n const parent = this.quill.root.parentElement\n const specRect = overlayTarget.getBoundingClientRect()\n const parentRect = parent.getBoundingClientRect()\n\n Object.assign(this.overlay.style, {\n display: 'block',\n left: `${specRect.left - parentRect.left - 1 + parent.scrollLeft}px`,\n top: `${specRect.top - parentRect.top + parent.scrollTop}px`,\n width: `${specRect.width}px`,\n height: `${specRect.height}px`,\n })\n }\n\n setUserSelect(value: string) {\n const props: string[] = [\n 'userSelect',\n 'mozUserSelect',\n 'webkitUserSelect',\n 'msUserSelect',\n ]\n\n props.forEach((prop: string) => {\n // set on contenteditable element and <html>\n this.quill.root.style.setProperty(prop, value)\n if (document.documentElement) {\n document.documentElement.style.setProperty(prop, value)\n }\n })\n }\n\n onClick = () => {\n this.hide()\n }\n}\n"],"names":["deepmerge"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"blot-formatter.es.js","sources":["../../../../src/modules/custom-image/blot-formatter.ts"],"sourcesContent":["import type FluentEditor from '../../core/fluent-editor'\nimport type { Action } from './actions'\nimport type { BlotFormatterOptions } from './options'\nimport type { BlotSpec } from './specs'\nimport Quill from 'quill'\nimport { merge as deepmerge } from '../../utils/merge'\nimport { CustomImage } from './image'\nimport DefaultOptions from './options'\nimport { CustomImageSpec } from './specs'\n\nconst dontMerge = (_destination: Array<any>, source: Array<any>) => source\n\nexport class BlotFormatter {\n options: BlotFormatterOptions\n currentSpec: BlotSpec\n specs: BlotSpec[]\n overlay: HTMLElement\n actions: Action[]\n observer: MutationObserver\n\n static register() {\n Quill.register({\n 'formats/image': CustomImage,\n 'modules/image-spec': CustomImageSpec,\n }, true)\n }\n\n constructor(public quill: FluentEditor, options: Partial<BlotFormatterOptions> = {}) {\n this.options = deepmerge({}, DefaultOptions, options, { arrayMerge: dontMerge })\n if (options.allowInvalidUrl !== undefined) {\n this.options.allowInvalidUrl = options.allowInvalidUrl\n }\n CustomImage.setOptions(this.options.allowInvalidUrl)\n this.currentSpec = null\n this.actions = []\n this.overlay = document.createElement('div')\n this.overlay.classList.add(this.options.overlay.className)\n if (this.options.overlay.style) {\n Object.assign(this.overlay.style, this.options.overlay.style)\n }\n\n // disable native image resizing on firefox\n document.execCommand('enableObjectResizing', false, 'false') // eslint-disable-next-line-line no-undef\n this.quill.root.addEventListener('click', this.onClick)\n this.specs = this.options.specs.map((SpecClass: any) => new SpecClass(this))\n this.specs.forEach(spec => spec.init())\n }\n\n show(spec: BlotSpec) {\n this.currentSpec = spec\n this.currentSpec.setSelection()\n this.setUserSelect('none')\n this.quill.root.parentNode.appendChild(this.overlay)\n this.repositionOverlay()\n this.createActions(spec)\n\n // fix: 图片对齐之后,虚线外框应该跟随移动\n const imageDom = spec.getTargetElement()\n const win: any = window\n const MutationObserver: typeof window.MutationObserver = win.MutationObserver || win.WebKitMutationObserver || win.MozMutationObserver\n const element = imageDom.parentNode\n this.observer = new MutationObserver((mutationList) => {\n for (const mutation of mutationList) {\n const target = mutation.target as HTMLElement\n const image = target.querySelector('img')\n if (image) {\n this.repositionOverlay()\n }\n }\n })\n this.observer.observe(element, {\n attributes: true,\n attributeFilter: ['class'],\n attributeOldValue: true,\n subtree: true,\n })\n }\n\n hide() {\n if (!this.currentSpec) {\n return\n }\n\n const imgDom = this.currentSpec.getTargetElement()\n if (imgDom) {\n imgDom.classList.remove('current-select-img')\n }\n\n this.currentSpec.onHide()\n this.currentSpec = null\n this.quill.root.parentNode.removeChild(this.overlay)\n this.overlay.style.setProperty('display', 'none')\n this.setUserSelect('')\n this.destroyActions()\n }\n\n update() {\n this.repositionOverlay()\n this.actions.forEach(action => action.onUpdate())\n }\n\n createActions(spec: BlotSpec) {\n this.actions = spec.getActions().map((ActionClass: any) => {\n const action: Action = new ActionClass(this)\n action.onCreate()\n return action\n })\n }\n\n destroyActions() {\n this.actions.forEach((action: Action) => action.onDestroy())\n this.actions = []\n }\n\n repositionOverlay() {\n if (!this.currentSpec) {\n return\n }\n\n const overlayTarget = this.currentSpec.getOverlayElement()\n if (!overlayTarget) {\n return\n }\n\n const parent = this.quill.root.parentElement\n const specRect = overlayTarget.getBoundingClientRect()\n const parentRect = parent.getBoundingClientRect()\n\n Object.assign(this.overlay.style, {\n display: 'block',\n left: `${specRect.left - parentRect.left - 1 + parent.scrollLeft}px`,\n top: `${specRect.top - parentRect.top + parent.scrollTop}px`,\n width: `${Math.min(specRect.width, parentRect.width)}px`,\n height: `${Math.min(specRect.height, parentRect.height)}px`,\n })\n }\n\n setUserSelect(value: string) {\n const props: string[] = [\n 'userSelect',\n 'mozUserSelect',\n 'webkitUserSelect',\n 'msUserSelect',\n ]\n\n props.forEach((prop: string) => {\n // set on contenteditable element and <html>\n this.quill.root.style.setProperty(prop, value)\n if (document.documentElement) {\n document.documentElement.style.setProperty(prop, value)\n }\n })\n }\n\n onClick = () => {\n this.hide()\n }\n}\n"],"names":["deepmerge"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "./actions/index.es.js";
|
|
2
2
|
import { BlotFormatter } from "./blot-formatter.es.js";
|
|
3
3
|
import { CustomImage } from "./image.es.js";
|
|
4
|
-
import "./specs/index.es.js";
|
|
5
4
|
import "./preview/index.es.js";
|
|
5
|
+
import "./specs/index.es.js";
|
|
6
6
|
export {
|
|
7
7
|
BlotFormatter,
|
|
8
8
|
CustomImage
|
|
@@ -7,6 +7,7 @@ class ImagePreviewModal {
|
|
|
7
7
|
__publicField(this, "overlay", null);
|
|
8
8
|
__publicField(this, "previewImage", null);
|
|
9
9
|
__publicField(this, "scaleTooltip", null);
|
|
10
|
+
__publicField(this, "closeBtn", null);
|
|
10
11
|
__publicField(this, "currentScale", 1);
|
|
11
12
|
__publicField(this, "minScale", 0.5);
|
|
12
13
|
__publicField(this, "maxScale", 3);
|
|
@@ -65,10 +66,10 @@ class ImagePreviewModal {
|
|
|
65
66
|
transition: transform 0.2s ease-out;
|
|
66
67
|
cursor: grab;
|
|
67
68
|
`;
|
|
68
|
-
|
|
69
|
-
closeBtn.className = "tiny-editor-image-preview-close";
|
|
70
|
-
closeBtn.innerHTML = "×";
|
|
71
|
-
closeBtn.style.cssText = `
|
|
69
|
+
this.closeBtn = document.createElement("button");
|
|
70
|
+
this.closeBtn.className = "tiny-editor-image-preview-close";
|
|
71
|
+
this.closeBtn.innerHTML = "×";
|
|
72
|
+
this.closeBtn.style.cssText = `
|
|
72
73
|
position: fixed;
|
|
73
74
|
top: 20px;
|
|
74
75
|
right: 20px;
|
|
@@ -83,9 +84,9 @@ class ImagePreviewModal {
|
|
|
83
84
|
line-height: 1;
|
|
84
85
|
padding: 0;
|
|
85
86
|
`;
|
|
86
|
-
closeBtn.addEventListener("click", () => this.hide());
|
|
87
|
+
this.closeBtn.addEventListener("click", () => this.hide());
|
|
87
88
|
this.modal.appendChild(this.previewImage);
|
|
88
|
-
document.body.appendChild(closeBtn);
|
|
89
|
+
document.body.appendChild(this.closeBtn);
|
|
89
90
|
this.scaleTooltip = document.createElement("div");
|
|
90
91
|
this.scaleTooltip.className = "image-preview-scale-tooltip";
|
|
91
92
|
this.scaleTooltip.style.cssText = `
|
|
@@ -183,6 +184,9 @@ class ImagePreviewModal {
|
|
|
183
184
|
this.modal.style.alignItems = "center";
|
|
184
185
|
this.modal.style.justifyContent = "center";
|
|
185
186
|
this.overlay.style.display = "block";
|
|
187
|
+
if (this.closeBtn) {
|
|
188
|
+
this.closeBtn.style.display = "block";
|
|
189
|
+
}
|
|
186
190
|
document.body.style.overflow = "hidden";
|
|
187
191
|
}
|
|
188
192
|
/**
|
|
@@ -194,6 +198,9 @@ class ImagePreviewModal {
|
|
|
194
198
|
this.overlay.style.display = "none";
|
|
195
199
|
document.body.style.overflow = "";
|
|
196
200
|
this.resetScale();
|
|
201
|
+
if (this.closeBtn) {
|
|
202
|
+
this.closeBtn.style.display = "none";
|
|
203
|
+
}
|
|
197
204
|
}
|
|
198
205
|
}
|
|
199
206
|
/**
|
|
@@ -207,12 +214,16 @@ class ImagePreviewModal {
|
|
|
207
214
|
if (this.modal && this.modal.parentNode) {
|
|
208
215
|
this.modal.parentNode.removeChild(this.modal);
|
|
209
216
|
}
|
|
217
|
+
if (this.closeBtn && this.closeBtn.parentNode) {
|
|
218
|
+
this.closeBtn.parentNode.removeChild(this.closeBtn);
|
|
219
|
+
}
|
|
210
220
|
if (this.scaleTooltip && this.scaleTooltip.parentNode) {
|
|
211
221
|
this.scaleTooltip.parentNode.removeChild(this.scaleTooltip);
|
|
212
222
|
}
|
|
213
223
|
this.modal = null;
|
|
214
224
|
this.overlay = null;
|
|
215
225
|
this.previewImage = null;
|
|
226
|
+
this.closeBtn = null;
|
|
216
227
|
this.scaleTooltip = null;
|
|
217
228
|
}
|
|
218
229
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview-modal.es.js","sources":["../../../../../src/modules/custom-image/preview/preview-modal.ts"],"sourcesContent":["/**\n * 图片预览模态框\n * 提供图片双击时的预览功能,包括遮罩层和全屏预览\n */\n\nexport class ImagePreviewModal {\n private modal: HTMLElement | null = null\n private overlay: HTMLElement | null = null\n private previewImage: HTMLImageElement | null = null\n private scaleTooltip: HTMLElement | null = null\n private currentScale: number = 1\n private minScale: number = 0.5\n private maxScale: number = 3\n private scaleStep: number = 0.1\n private tooltipHideTimer: number | null = null\n\n constructor() {\n this.initModal()\n }\n\n private initModal() {\n // 创建遮罩层\n this.overlay = document.createElement('div')\n this.overlay.className = 'image-preview-overlay'\n this.overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.8);\n display: none;\n z-index: 9999;\n cursor: pointer;\n `\n\n // 创建预览容器\n this.modal = document.createElement('div')\n this.modal.className = 'image-preview-modal'\n this.modal.style.cssText = `\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background-color: transparent;\n display: none;\n z-index: 10000;\n max-width: 90vw;\n max-height: 90vh;\n cursor: auto;\n `\n\n // 创建预览图片\n this.previewImage = document.createElement('img')\n this.previewImage.className = 'image-preview-img'\n this.previewImage.style.cssText = `\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n border-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: transform 0.2s ease-out;\n cursor: grab;\n `\n\n // 创建关闭按钮\n const closeBtn = document.createElement('button')\n closeBtn.className = 'tiny-editor-image-preview-close'\n closeBtn.innerHTML = '×'\n closeBtn.style.cssText = `\n position: fixed;\n top: 20px;\n right: 20px;\n width: 40px;\n height: 40px;\n border: none;\n background-color: transparent;\n color: white;\n font-size: 32px;\n cursor: pointer;\n z-index: 10001;\n line-height: 1;\n padding: 0;\n `\n closeBtn.addEventListener('click', () => this.hide())\n\n this.modal.appendChild(this.previewImage)\n document.body.appendChild(closeBtn)\n\n // 创建缩放提示窗口\n this.scaleTooltip = document.createElement('div')\n this.scaleTooltip.className = 'image-preview-scale-tooltip'\n this.scaleTooltip.style.cssText = `\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background-color: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 12px 20px;\n border-radius: 6px;\n font-size: 14px;\n z-index: 10002;\n display: none;\n pointer-events: none;\n white-space: nowrap;\n font-weight: 500;\n `\n document.body.appendChild(this.scaleTooltip)\n\n // 绑定事件\n this.overlay.addEventListener('click', () => this.hide())\n document.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n this.hide()\n }\n })\n\n // 绑定滚轮缩放事件\n document.addEventListener('wheel', (e) => this.onMouseWheel(e), { passive: false })\n\n // 阻止模态框内的点击事件冒泡到遮罩层\n this.modal.addEventListener('click', (e) => {\n e.stopPropagation()\n })\n\n document.body.appendChild(this.overlay)\n document.body.appendChild(this.modal)\n }\n\n /**\n * 处理鼠标滚轮事件 - 缩放图片\n */\n private onMouseWheel = (event: WheelEvent) => {\n // 只在预览打开时处理\n if (!this.modal || this.modal.style.display === 'none') {\n return\n }\n\n event.preventDefault()\n\n // 根据滚轮方向调整缩放比例\n const delta = event.deltaY > 0 ? -this.scaleStep : this.scaleStep\n this.setScale(this.currentScale + delta)\n\n // 显示缩放提示\n this.showScaleTooltip()\n }\n\n /**\n * 设置缩放比例\n */\n private setScale(scale: number) {\n // 限制缩放范围\n this.currentScale = Math.max(this.minScale, Math.min(scale, this.maxScale))\n\n if (this.previewImage) {\n this.previewImage.style.transform = `scale(${this.currentScale})`\n }\n }\n\n /**\n * 显示缩放百分比提示\n */\n private showScaleTooltip() {\n if (!this.scaleTooltip) {\n return\n }\n\n // 清除之前的隐藏计时器\n if (this.tooltipHideTimer !== null) {\n clearTimeout(this.tooltipHideTimer)\n }\n\n // 更新提示文本\n const percentage = Math.round(this.currentScale * 100)\n this.scaleTooltip.textContent = `${percentage}%`\n this.scaleTooltip.style.display = 'block'\n\n // 1.5秒后隐藏提示\n this.tooltipHideTimer = window.setTimeout(() => {\n if (this.scaleTooltip) {\n this.scaleTooltip.style.display = 'none'\n }\n this.tooltipHideTimer = null\n }, 1500)\n }\n\n /**\n * 隐藏缩放提示\n */\n private hideScaleTooltip() {\n if (this.tooltipHideTimer !== null) {\n clearTimeout(this.tooltipHideTimer)\n this.tooltipHideTimer = null\n }\n if (this.scaleTooltip) {\n this.scaleTooltip.style.display = 'none'\n }\n }\n\n /**\n * 重置缩放比例\n */\n private resetScale() {\n this.currentScale = 1\n if (this.previewImage) {\n this.previewImage.style.transform = 'scale(1)'\n }\n this.hideScaleTooltip()\n }\n\n /**\n * 显示预览\n * @param imageUrl 图片URL\n */\n show(imageUrl: string) {\n if (!this.previewImage || !this.modal || !this.overlay) {\n return\n }\n\n this.resetScale()\n this.previewImage.src = imageUrl\n this.modal.style.display = 'flex'\n this.modal.style.alignItems = 'center'\n this.modal.style.justifyContent = 'center'\n this.overlay.style.display = 'block'\n\n // 防止页面滚动\n document.body.style.overflow = 'hidden'\n }\n\n /**\n * 隐藏预览\n */\n hide() {\n if (this.modal && this.overlay) {\n this.modal.style.display = 'none'\n this.overlay.style.display = 'none'\n document.body.style.overflow = ''\n this.resetScale()\n }\n }\n\n /**\n * 销毁预览模态框\n */\n destroy() {\n this.hideScaleTooltip()\n if (this.overlay && this.overlay.parentNode) {\n this.overlay.parentNode.removeChild(this.overlay)\n }\n if (this.modal && this.modal.parentNode) {\n this.modal.parentNode.removeChild(this.modal)\n }\n if (this.scaleTooltip && this.scaleTooltip.parentNode) {\n this.scaleTooltip.parentNode.removeChild(this.scaleTooltip)\n }\n this.modal = null\n this.overlay = null\n this.previewImage = null\n this.scaleTooltip = null\n }\n}\n\n// 全局单例实例\nlet globalPreviewModal: ImagePreviewModal | null = null\n\n/**\n * 获取或创建全局预览模态框实例\n */\nexport function getImagePreviewModal(): ImagePreviewModal {\n if (!globalPreviewModal) {\n globalPreviewModal = new ImagePreviewModal()\n }\n return globalPreviewModal\n}\n"],"names":[],"mappings":";;;AAKO,MAAM,kBAAkB;AAAA,EAW7B,cAAc;AAVN,iCAA4B;AAC5B,mCAA8B;AAC9B,wCAAwC;AACxC,wCAAmC;AACnC,wCAAuB;AACvB,oCAAmB;AACnB,oCAAmB;AACnB,qCAAoB;AACpB,4CAAkC;AAuHlC;AAAA;AAAA;AAAA,wCAAe,CAAC,UAAsB;AAE5C,UAAI,CAAC,KAAK,SAAS,KAAK,MAAM,MAAM,YAAY,QAAQ;AACtD;AAAA,MACF;AAEA,YAAM,eAAA;AAGN,YAAM,QAAQ,MAAM,SAAS,IAAI,CAAC,KAAK,YAAY,KAAK;AACxD,WAAK,SAAS,KAAK,eAAe,KAAK;AAGvC,WAAK,iBAAA;AAAA,IACP;AAlIE,SAAK,UAAA;AAAA,EACP;AAAA,EAEQ,YAAY;AAElB,SAAK,UAAU,SAAS,cAAc,KAAK;AAC3C,SAAK,QAAQ,YAAY;AACzB,SAAK,QAAQ,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAa7B,SAAK,QAAQ,SAAS,cAAc,KAAK;AACzC,SAAK,MAAM,YAAY;AACvB,SAAK,MAAM,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAc3B,SAAK,eAAe,SAAS,cAAc,KAAK;AAChD,SAAK,aAAa,YAAY;AAC9B,SAAK,aAAa,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWlC,UAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,aAAS,YAAY;AACrB,aAAS,YAAY;AACrB,aAAS,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAezB,aAAS,iBAAiB,SAAS,MAAM,KAAK,MAAM;AAEpD,SAAK,MAAM,YAAY,KAAK,YAAY;AACxC,aAAS,KAAK,YAAY,QAAQ;AAGlC,SAAK,eAAe,SAAS,cAAc,KAAK;AAChD,SAAK,aAAa,YAAY;AAC9B,SAAK,aAAa,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBlC,aAAS,KAAK,YAAY,KAAK,YAAY;AAG3C,SAAK,QAAQ,iBAAiB,SAAS,MAAM,KAAK,MAAM;AACxD,aAAS,iBAAiB,WAAW,CAAC,MAAM;AAC1C,UAAI,EAAE,QAAQ,UAAU;AACtB,aAAK,KAAA;AAAA,MACP;AAAA,IACF,CAAC;AAGD,aAAS,iBAAiB,SAAS,CAAC,MAAM,KAAK,aAAa,CAAC,GAAG,EAAE,SAAS,MAAA,CAAO;AAGlF,SAAK,MAAM,iBAAiB,SAAS,CAAC,MAAM;AAC1C,QAAE,gBAAA;AAAA,IACJ,CAAC;AAED,aAAS,KAAK,YAAY,KAAK,OAAO;AACtC,aAAS,KAAK,YAAY,KAAK,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAwBQ,SAAS,OAAe;AAE9B,SAAK,eAAe,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK,QAAQ,CAAC;AAE1E,QAAI,KAAK,cAAc;AACrB,WAAK,aAAa,MAAM,YAAY,SAAS,KAAK,YAAY;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB;AACzB,QAAI,CAAC,KAAK,cAAc;AACtB;AAAA,IACF;AAGA,QAAI,KAAK,qBAAqB,MAAM;AAClC,mBAAa,KAAK,gBAAgB;AAAA,IACpC;AAGA,UAAM,aAAa,KAAK,MAAM,KAAK,eAAe,GAAG;AACrD,SAAK,aAAa,cAAc,GAAG,UAAU;AAC7C,SAAK,aAAa,MAAM,UAAU;AAGlC,SAAK,mBAAmB,OAAO,WAAW,MAAM;AAC9C,UAAI,KAAK,cAAc;AACrB,aAAK,aAAa,MAAM,UAAU;AAAA,MACpC;AACA,WAAK,mBAAmB;AAAA,IAC1B,GAAG,IAAI;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB;AACzB,QAAI,KAAK,qBAAqB,MAAM;AAClC,mBAAa,KAAK,gBAAgB;AAClC,WAAK,mBAAmB;AAAA,IAC1B;AACA,QAAI,KAAK,cAAc;AACrB,WAAK,aAAa,MAAM,UAAU;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa;AACnB,SAAK,eAAe;AACpB,QAAI,KAAK,cAAc;AACrB,WAAK,aAAa,MAAM,YAAY;AAAA,IACtC;AACA,SAAK,iBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,UAAkB;AACrB,QAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,SAAS,CAAC,KAAK,SAAS;AACtD;AAAA,IACF;AAEA,SAAK,WAAA;AACL,SAAK,aAAa,MAAM;AACxB,SAAK,MAAM,MAAM,UAAU;AAC3B,SAAK,MAAM,MAAM,aAAa;AAC9B,SAAK,MAAM,MAAM,iBAAiB;AAClC,SAAK,QAAQ,MAAM,UAAU;AAG7B,aAAS,KAAK,MAAM,WAAW;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACL,QAAI,KAAK,SAAS,KAAK,SAAS;AAC9B,WAAK,MAAM,MAAM,UAAU;AAC3B,WAAK,QAAQ,MAAM,UAAU;AAC7B,eAAS,KAAK,MAAM,WAAW;AAC/B,WAAK,WAAA;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AACR,SAAK,iBAAA;AACL,QAAI,KAAK,WAAW,KAAK,QAAQ,YAAY;AAC3C,WAAK,QAAQ,WAAW,YAAY,KAAK,OAAO;AAAA,IAClD;AACA,QAAI,KAAK,SAAS,KAAK,MAAM,YAAY;AACvC,WAAK,MAAM,WAAW,YAAY,KAAK,KAAK;AAAA,IAC9C;AACA,QAAI,KAAK,gBAAgB,KAAK,aAAa,YAAY;AACrD,WAAK,aAAa,WAAW,YAAY,KAAK,YAAY;AAAA,IAC5D;AACA,SAAK,QAAQ;AACb,SAAK,UAAU;AACf,SAAK,eAAe;AACpB,SAAK,eAAe;AAAA,EACtB;AACF;AAGA,IAAI,qBAA+C;AAK5C,SAAS,uBAA0C;AACxD,MAAI,CAAC,oBAAoB;AACvB,yBAAqB,IAAI,kBAAA;AAAA,EAC3B;AACA,SAAO;AACT;"}
|
|
1
|
+
{"version":3,"file":"preview-modal.es.js","sources":["../../../../../src/modules/custom-image/preview/preview-modal.ts"],"sourcesContent":["/**\n * 图片预览模态框\n * 提供图片双击时的预览功能,包括遮罩层和全屏预览\n */\n\nexport class ImagePreviewModal {\n private modal: HTMLElement | null = null\n private overlay: HTMLElement | null = null\n private previewImage: HTMLImageElement | null = null\n private scaleTooltip: HTMLElement | null = null\n private closeBtn: HTMLButtonElement | null = null\n private currentScale: number = 1\n private minScale: number = 0.5\n private maxScale: number = 3\n private scaleStep: number = 0.1\n private tooltipHideTimer: number | null = null\n\n constructor() {\n this.initModal()\n }\n\n private initModal() {\n // 创建遮罩层\n this.overlay = document.createElement('div')\n this.overlay.className = 'image-preview-overlay'\n this.overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.8);\n display: none;\n z-index: 9999;\n cursor: pointer;\n `\n\n // 创建预览容器\n this.modal = document.createElement('div')\n this.modal.className = 'image-preview-modal'\n this.modal.style.cssText = `\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background-color: transparent;\n display: none;\n z-index: 10000;\n max-width: 90vw;\n max-height: 90vh;\n cursor: auto;\n `\n\n // 创建预览图片\n this.previewImage = document.createElement('img')\n this.previewImage.className = 'image-preview-img'\n this.previewImage.style.cssText = `\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n border-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: transform 0.2s ease-out;\n cursor: grab;\n `\n\n // 创建关闭按钮\n this.closeBtn = document.createElement('button')\n this.closeBtn.className = 'tiny-editor-image-preview-close'\n this.closeBtn.innerHTML = '×'\n this.closeBtn.style.cssText = `\n position: fixed;\n top: 20px;\n right: 20px;\n width: 40px;\n height: 40px;\n border: none;\n background-color: transparent;\n color: white;\n font-size: 32px;\n cursor: pointer;\n z-index: 10001;\n line-height: 1;\n padding: 0;\n `\n this.closeBtn.addEventListener('click', () => this.hide())\n\n this.modal.appendChild(this.previewImage)\n document.body.appendChild(this.closeBtn)\n\n // 创建缩放提示窗口\n this.scaleTooltip = document.createElement('div')\n this.scaleTooltip.className = 'image-preview-scale-tooltip'\n this.scaleTooltip.style.cssText = `\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background-color: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 12px 20px;\n border-radius: 6px;\n font-size: 14px;\n z-index: 10002;\n display: none;\n pointer-events: none;\n white-space: nowrap;\n font-weight: 500;\n `\n document.body.appendChild(this.scaleTooltip)\n\n // 绑定事件\n this.overlay.addEventListener('click', () => this.hide())\n document.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n this.hide()\n }\n })\n\n // 绑定滚轮缩放事件\n document.addEventListener('wheel', e => this.onMouseWheel(e), { passive: false })\n\n // 阻止模态框内的点击事件冒泡到遮罩层\n this.modal.addEventListener('click', (e) => {\n e.stopPropagation()\n })\n\n document.body.appendChild(this.overlay)\n document.body.appendChild(this.modal)\n }\n\n /**\n * 处理鼠标滚轮事件 - 缩放图片\n */\n private onMouseWheel = (event: WheelEvent) => {\n // 只在预览打开时处理\n if (!this.modal || this.modal.style.display === 'none') {\n return\n }\n\n event.preventDefault()\n\n // 根据滚轮方向调整缩放比例\n const delta = event.deltaY > 0 ? -this.scaleStep : this.scaleStep\n this.setScale(this.currentScale + delta)\n\n // 显示缩放提示\n this.showScaleTooltip()\n }\n\n /**\n * 设置缩放比例\n */\n private setScale(scale: number) {\n // 限制缩放范围\n this.currentScale = Math.max(this.minScale, Math.min(scale, this.maxScale))\n\n if (this.previewImage) {\n this.previewImage.style.transform = `scale(${this.currentScale})`\n }\n }\n\n /**\n * 显示缩放百分比提示\n */\n private showScaleTooltip() {\n if (!this.scaleTooltip) {\n return\n }\n\n // 清除之前的隐藏计时器\n if (this.tooltipHideTimer !== null) {\n clearTimeout(this.tooltipHideTimer)\n }\n\n // 更新提示文本\n const percentage = Math.round(this.currentScale * 100)\n this.scaleTooltip.textContent = `${percentage}%`\n this.scaleTooltip.style.display = 'block'\n\n // 1.5秒后隐藏提示\n this.tooltipHideTimer = window.setTimeout(() => {\n if (this.scaleTooltip) {\n this.scaleTooltip.style.display = 'none'\n }\n this.tooltipHideTimer = null\n }, 1500)\n }\n\n /**\n * 隐藏缩放提示\n */\n private hideScaleTooltip() {\n if (this.tooltipHideTimer !== null) {\n clearTimeout(this.tooltipHideTimer)\n this.tooltipHideTimer = null\n }\n if (this.scaleTooltip) {\n this.scaleTooltip.style.display = 'none'\n }\n }\n\n /**\n * 重置缩放比例\n */\n private resetScale() {\n this.currentScale = 1\n if (this.previewImage) {\n this.previewImage.style.transform = 'scale(1)'\n }\n this.hideScaleTooltip()\n }\n\n /**\n * 显示预览\n * @param imageUrl 图片URL\n */\n show(imageUrl: string) {\n if (!this.previewImage || !this.modal || !this.overlay) {\n return\n }\n\n this.resetScale()\n this.previewImage.src = imageUrl\n this.modal.style.display = 'flex'\n this.modal.style.alignItems = 'center'\n this.modal.style.justifyContent = 'center'\n this.overlay.style.display = 'block'\n\n if (this.closeBtn) {\n this.closeBtn.style.display = 'block'\n }\n\n // 防止页面滚动\n document.body.style.overflow = 'hidden'\n }\n\n /**\n * 隐藏预览\n */\n hide() {\n if (this.modal && this.overlay) {\n this.modal.style.display = 'none'\n this.overlay.style.display = 'none'\n document.body.style.overflow = ''\n this.resetScale()\n if (this.closeBtn) {\n this.closeBtn.style.display = 'none'\n }\n }\n }\n\n /**\n * 销毁预览模态框\n */\n destroy() {\n this.hideScaleTooltip()\n if (this.overlay && this.overlay.parentNode) {\n this.overlay.parentNode.removeChild(this.overlay)\n }\n if (this.modal && this.modal.parentNode) {\n this.modal.parentNode.removeChild(this.modal)\n }\n if (this.closeBtn && this.closeBtn.parentNode) {\n this.closeBtn.parentNode.removeChild(this.closeBtn)\n }\n if (this.scaleTooltip && this.scaleTooltip.parentNode) {\n this.scaleTooltip.parentNode.removeChild(this.scaleTooltip)\n }\n this.modal = null\n this.overlay = null\n this.previewImage = null\n this.closeBtn = null\n this.scaleTooltip = null\n }\n}\n\n// 全局单例实例\nlet globalPreviewModal: ImagePreviewModal | null = null\n\n/**\n * 获取或创建全局预览模态框实例\n */\nexport function getImagePreviewModal(): ImagePreviewModal {\n if (!globalPreviewModal) {\n globalPreviewModal = new ImagePreviewModal()\n }\n return globalPreviewModal\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-image-spec.es.js","sources":["../../../../../src/modules/custom-image/specs/custom-image-spec.ts"],"sourcesContent":["import type { BlotFormatter } from '../blot-formatter'\nimport { isInside } from '../../../config/editor.utils'\nimport { getImagePreviewModal } from '../preview'\nimport { ImageSpec } from './image-spec'\n\nexport class CustomImageSpec extends ImageSpec {\n editorElem: HTMLElement | undefined\n observer: any\n oldRootScrollTop: number\n\n constructor(formatter: BlotFormatter) {\n super(formatter)\n this.formatter = formatter\n this.oldRootScrollTop = this.formatter.quill.root.scrollTop\n this.editorElem = this.formatter.quill.container\n this.formatter.quill.root.addEventListener('scroll', this.handleQuillRootScroll.bind(this))\n }\n\n handleQuillRootScroll() {\n if (this.formatter.overlay) {\n this.formatter.overlay.style.marginTop = `${this.oldRootScrollTop - this.formatter.quill.root.scrollTop}px`\n }\n }\n\n init(): void {\n this.editorElem.addEventListener('mouseover', this.imageMouseOver.bind(this))\n this.editorElem.addEventListener('mouseout', this.imageMouseout)\n this.editorElem.addEventListener('dblclick', this.onImageDoubleClick.bind(this))\n\n super.init()\n }\n\n imageMouseOver(event) {\n const target = event.target\n const isBlotFormatter = target?.classList?.contains('blot-formatter__overlay')\n if (target.nodeName === 'IMG' || isBlotFormatter) {\n // this.addImagePreviewOverlay(event);\n }\n }\n\n imageMouseout = (event) => {\n if (event.target.nodeName === 'IMG'\n || event.target.classList.contains('blot-formatter__overlay')) {\n const imgDom = event.target\n if (!isInside(event, imgDom)) {\n this.removeImagePreviewOverlay()\n }\n }\n }\n\n addImagePreviewOverlay(event) {\n const target = event.target\n const {\n left: imgLeft,\n width: imgWidth,\n } = target.getBoundingClientRect()\n // fix: 解决 ql-container 容器设置 calc(100vh - 180px) 这样的视窗相对单位时,滚动视窗导致图片相对视窗的 top 相应改变,从而导致图片预览按钮的位置显示错误\n const imgTop = target.getBoundingClientRect().top + this.formatter.quill.container.scrollTop\n\n const {\n left: editorLeft,\n top: editorTop,\n } = event.currentTarget.getBoundingClientRect()\n\n const imgRelativeLeft = imgLeft - editorLeft\n const imgRelativeTop = imgTop - editorTop\n\n const maxmizeWidth = 24\n const maxmizePadding = 15\n const previewLeft = imgRelativeLeft + imgWidth - maxmizeWidth - maxmizePadding\n const previewTop = imgRelativeTop + maxmizePadding\n\n const previewStyle = `\n left: ${previewLeft}px;\n top: ${previewTop}px;\n width: ${maxmizeWidth}px;\n `\n const imageSrc = target.src || target.getAttribute('data-image')\n const imageId = target.getAttribute('data-image-id')\n\n const previewDom = event.currentTarget.querySelector('.image-preview__overlay')\n if (!previewDom) {\n event.currentTarget.insertAdjacentHTML('beforeend', `\n <div class=\"image-preview__overlay\" style=\"${previewStyle}\">\n <i class=\"icon-maxmize\" id=\"btn-image-preview\" data-image-id=\"${imageId}\"\n data-image=\"${imageSrc}\"></i>\n </div>\n `)\n }\n }\n\n removeImagePreviewOverlay() {\n const previewDom = this.editorElem.querySelector('.image-preview__overlay')\n if (previewDom) {\n previewDom.parentNode.removeChild(previewDom)\n }\n }\n\n onHide() {\n this.removeImagePreviewOverlay()\n super.onHide()\n }\n\n resetOverlayMarginTop() {\n if (this.formatter.overlay) {\n this.formatter.overlay.style.marginTop = '0px'\n }\n }\n\n onClick = (event: MouseEvent) => {\n const el = event.target\n const isReadonly = this.formatter.quill.options.readOnly\n if (!(el instanceof HTMLElement) || el.tagName !== 'IMG' || isReadonly) {\n return\n }\n\n this.img = el as HTMLImageElement\n this.oldRootScrollTop = this.formatter.quill.root.scrollTop\n this.resetOverlayMarginTop()\n this.formatter.show(this)\n\n // 通过图片dom获取图片选区用以复制,设置 current-select-img::selection 取消选区背景\n const imageDom = this.formatter.currentSpec?.getTargetElement()\n if (imageDom) {\n imageDom.classList.add('current-select-img')\n const quill = this.formatter.quill\n const imgBlot = quill.scroll.find(this.img)\n const index = quill.getIndex(imgBlot)\n const len = imgBlot.length()\n quill.setSelection(index, len)\n }\n }\n\n /**\n * 处理图片双击事件 - 显示预览\n */\n onImageDoubleClick = (event: MouseEvent) => {\n const target = event.target\n const imageSrc = target.getAttribute('src') || target.getAttribute('data-image')\n\n if (imageSrc) {\n const modal = getImagePreviewModal()\n modal.show(imageSrc)\n }\n }\n}\n"],"names":[],"mappings":";;;;;;;AAKO,MAAM,wBAAwB,UAAU;AAAA,EAK7C,YAAY,WAA0B;AACpC,UAAM,SAAS;AALjB;AACA;AACA;AAgCA,yCAAgB,CAAC,UAAU;AACzB,UAAI,MAAM,OAAO,aAAa,SACzB,MAAM,OAAO,UAAU,SAAS,yBAAyB,GAAG;AAC/D,cAAM,SAAS,MAAM;AACrB,YAAI,CAAC,SAAS,OAAO,MAAM,GAAG;AAC5B,eAAK,0BAAA;AAAA,QACP;AAAA,MACF;AAAA,IACF;AA6DA,mCAAU,CAAC,UAAsB;;AAC/B,YAAM,KAAK,MAAM;AACjB,YAAM,aAAa,KAAK,UAAU,MAAM,QAAQ;AAChD,UAAI,EAAE,cAAc,gBAAgB,GAAG,YAAY,SAAS,YAAY;AACtE;AAAA,MACF;AAEA,WAAK,MAAM;AACX,WAAK,mBAAmB,KAAK,UAAU,MAAM,KAAK;AAClD,WAAK,sBAAA;AACL,WAAK,UAAU,KAAK,IAAI;AAGxB,YAAM,YAAW,UAAK,UAAU,gBAAf,mBAA4B;AAC7C,UAAI,UAAU;AACZ,iBAAS,UAAU,IAAI,oBAAoB;AAC3C,cAAM,QAAQ,KAAK,UAAU;AAC7B,cAAM,UAAU,MAAM,OAAO,KAAK,KAAK,GAAG;AAC1C,cAAM,QAAQ,MAAM,SAAS,OAAO;AACpC,cAAM,MAAM,QAAQ,OAAA;AACpB,cAAM,aAAa,OAAO,GAAG;AAAA,MAC/B;AAAA,IACF;AAKA;AAAA;AAAA;AAAA,8CAAqB,CAAC,UAAsB;AAC1C,YAAM,SAAS,MAAM;AACrB,YAAM,
|
|
1
|
+
{"version":3,"file":"custom-image-spec.es.js","sources":["../../../../../src/modules/custom-image/specs/custom-image-spec.ts"],"sourcesContent":["import type { BlotFormatter } from '../blot-formatter'\nimport { isInside } from '../../../config/editor.utils'\nimport { getImagePreviewModal } from '../preview'\nimport { ImageSpec } from './image-spec'\n\nexport class CustomImageSpec extends ImageSpec {\n editorElem: HTMLElement | undefined\n observer: any\n oldRootScrollTop: number\n\n constructor(formatter: BlotFormatter) {\n super(formatter)\n this.formatter = formatter\n this.oldRootScrollTop = this.formatter.quill.root.scrollTop\n this.editorElem = this.formatter.quill.container\n this.formatter.quill.root.addEventListener('scroll', this.handleQuillRootScroll.bind(this))\n }\n\n handleQuillRootScroll() {\n if (this.formatter.overlay) {\n this.formatter.overlay.style.marginTop = `${this.oldRootScrollTop - this.formatter.quill.root.scrollTop}px`\n }\n }\n\n init(): void {\n this.editorElem.addEventListener('mouseover', this.imageMouseOver.bind(this))\n this.editorElem.addEventListener('mouseout', this.imageMouseout)\n this.editorElem.addEventListener('dblclick', this.onImageDoubleClick.bind(this))\n\n super.init()\n }\n\n imageMouseOver(event) {\n const target = event.target\n const isBlotFormatter = target?.classList?.contains('blot-formatter__overlay')\n if (target.nodeName === 'IMG' || isBlotFormatter) {\n // this.addImagePreviewOverlay(event);\n }\n }\n\n imageMouseout = (event) => {\n if (event.target.nodeName === 'IMG'\n || event.target.classList.contains('blot-formatter__overlay')) {\n const imgDom = event.target\n if (!isInside(event, imgDom)) {\n this.removeImagePreviewOverlay()\n }\n }\n }\n\n addImagePreviewOverlay(event) {\n const target = event.target\n const {\n left: imgLeft,\n width: imgWidth,\n } = target.getBoundingClientRect()\n // fix: 解决 ql-container 容器设置 calc(100vh - 180px) 这样的视窗相对单位时,滚动视窗导致图片相对视窗的 top 相应改变,从而导致图片预览按钮的位置显示错误\n const imgTop = target.getBoundingClientRect().top + this.formatter.quill.container.scrollTop\n\n const {\n left: editorLeft,\n top: editorTop,\n } = event.currentTarget.getBoundingClientRect()\n\n const imgRelativeLeft = imgLeft - editorLeft\n const imgRelativeTop = imgTop - editorTop\n\n const maxmizeWidth = 24\n const maxmizePadding = 15\n const previewLeft = imgRelativeLeft + imgWidth - maxmizeWidth - maxmizePadding\n const previewTop = imgRelativeTop + maxmizePadding\n\n const previewStyle = `\n left: ${previewLeft}px;\n top: ${previewTop}px;\n width: ${maxmizeWidth}px;\n `\n const imageSrc = target.src || target.getAttribute('data-image')\n const imageId = target.getAttribute('data-image-id')\n\n const previewDom = event.currentTarget.querySelector('.image-preview__overlay')\n if (!previewDom) {\n event.currentTarget.insertAdjacentHTML('beforeend', `\n <div class=\"image-preview__overlay\" style=\"${previewStyle}\">\n <i class=\"icon-maxmize\" id=\"btn-image-preview\" data-image-id=\"${imageId}\"\n data-image=\"${imageSrc}\"></i>\n </div>\n `)\n }\n }\n\n removeImagePreviewOverlay() {\n const previewDom = this.editorElem.querySelector('.image-preview__overlay')\n if (previewDom) {\n previewDom.parentNode.removeChild(previewDom)\n }\n }\n\n onHide() {\n this.removeImagePreviewOverlay()\n super.onHide()\n }\n\n resetOverlayMarginTop() {\n if (this.formatter.overlay) {\n this.formatter.overlay.style.marginTop = '0px'\n }\n }\n\n onClick = (event: MouseEvent) => {\n const el = event.target\n const isReadonly = this.formatter.quill.options.readOnly\n if (!(el instanceof HTMLElement) || el.tagName !== 'IMG' || isReadonly) {\n return\n }\n\n this.img = el as HTMLImageElement\n this.oldRootScrollTop = this.formatter.quill.root.scrollTop\n this.resetOverlayMarginTop()\n this.formatter.show(this)\n\n // 通过图片dom获取图片选区用以复制,设置 current-select-img::selection 取消选区背景\n const imageDom = this.formatter.currentSpec?.getTargetElement()\n if (imageDom) {\n imageDom.classList.add('current-select-img')\n const quill = this.formatter.quill\n const imgBlot = quill.scroll.find(this.img)\n const index = quill.getIndex(imgBlot)\n const len = imgBlot.length()\n quill.setSelection(index, len)\n }\n }\n\n /**\n * 处理图片双击事件 - 显示预览\n */\n onImageDoubleClick = (event: MouseEvent) => {\n const target = event.target\n const imageSrc = (target as HTMLElement).getAttribute('src') || (target as HTMLElement).getAttribute('data-image')\n\n if (imageSrc) {\n const modal = getImagePreviewModal()\n modal.show(imageSrc)\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-uploader.es.js","sources":["../../../src/modules/custom-uploader.ts"],"sourcesContent":["import type { Range } from 'quill'\r\nimport type TypeUploader from 'quill/modules/uploader'\r\nimport type FluentEditor from '../core/fluent-editor'\r\nimport Quill from 'quill'\r\nimport { isString } from '../utils/is'\r\n\r\nconst Uploader = Quill.import('modules/uploader') as typeof TypeUploader\r\nconst Delta = Quill.import('delta')\r\n\r\nexport type UploadKind = 'image' | 'video' | 'file'\r\nexport type MimeTypesConfig = string[] | Partial<Record<UploadKind, string[]>>\r\nexport type MaxSizeConfig = number | Partial<Record<UploadKind, number>>\r\nexport type MultipleConfig = boolean | Partial<Record<UploadKind, boolean>>\r\n\r\ninterface UploaderOptions {\r\n mimetypes: string[]\r\n handler: (this: { quill: Quill }, range: Range, files: File[]) => void\r\n}\r\nexport interface FileUploaderOptions {\r\n /**\r\n * 支持单个 MIME type、模糊匹配子类型和后缀名三种格式\r\n * - 全局配置:`string[]`\r\n * - 根据文件/图片/视频单独配置:`{ file?: string[]; image?: string[]; video?: string[] }`\r\n */\r\n mimetypes: MimeTypesConfig\r\n /**\r\n * 最大文件大小限制(字节)\r\n * - 全局配置:`number`\r\n * - 根据文件/图片/视频单独配置:`{ file?: number; image?: number; video?: number }`\r\n */\r\n maxSize: MaxSizeConfig\r\n /**\r\n * 是否允许多选文件\r\n * - 全局配置:`boolean`\r\n * - 根据文件/图片/视频单独配置:`{ file?: boolean; image?: boolean; video?: boolean }`\r\n */\r\n multiple: MultipleConfig\r\n handler: (this: { quill: FluentEditor }, range: Range, files: File[]) => Promise<(string | false)[]> | (string | false)[]\r\n success: (this: { quill: FluentEditor }, file: File, range: Range) => void\r\n fail: (this: { quill: FluentEditor }, file: File, range: Range) => void\r\n}\r\nexport class FileUploader extends Uploader {\r\n static DEFAULTS = {} as any\r\n // Partial<UploaderOptions> for ts type\r\n declare options: Partial<UploaderOptions> & FileUploaderOptions\r\n constructor(public quill: FluentEditor, options: Partial<FileUploaderOptions>) {\r\n super(quill, options as any)\r\n this.options = this.resolveOptions(options)\r\n // paste handle in clipboard\r\n }\r\n\r\n resolveOptions(options: Partial<FileUploaderOptions> = {}) {\r\n return Object.assign({\r\n mimetypes: ['*'],\r\n maxSize: Number.POSITIVE_INFINITY,\r\n multiple: true,\r\n handler(range: Range, files: File[]) {\r\n return files.map(file => URL.createObjectURL(file))\r\n },\r\n success() {},\r\n fail() {},\r\n }, options)\r\n }\r\n\r\n private inferKind(file: File): UploadKind {\r\n const type = file.type || ''\r\n if (type.startsWith('image/')) return 'image'\r\n if (type.startsWith('video/')) return 'video'\r\n return 'file'\r\n }\r\n\r\n private filterFromArray(types: string[], kind: UploadKind): string[] {\r\n if (kind === 'file') return types\r\n const prefix = `${kind}/`\r\n return types.filter((type) => {\r\n if (type === '*') return true\r\n if (type.includes('/')) return type.startsWith(prefix)\r\n return true\r\n })\r\n }\r\n\r\n getAccept(kind: UploadKind): string[] {\r\n const mimetypes = this.options.mimetypes\r\n if (Array.isArray(mimetypes)) {\r\n return this.filterFromArray(mimetypes, kind)\r\n }\r\n const map = mimetypes || {}\r\n const fromKind = map[kind]\r\n if (fromKind?.length) return fromKind\r\n if (map.file?.length && kind !== 'file') return map.file\r\n return []\r\n }\r\n\r\n getMaxSize(kind: UploadKind): number {\r\n const maxSize = this.options.maxSize\r\n if (typeof maxSize === 'number') {\r\n return maxSize\r\n }\r\n const map = maxSize || {}\r\n const fromKind = map[kind]\r\n if (typeof fromKind === 'number') return fromKind\r\n if (typeof map.file === 'number' && kind !== 'file') return map.file\r\n return Number.POSITIVE_INFINITY\r\n }\r\n\r\n getMultiple(kind: UploadKind): boolean {\r\n const multiple = this.options.multiple\r\n if (typeof multiple === 'boolean') {\r\n return multiple\r\n }\r\n const map = multiple || {}\r\n const fromKind = map[kind]\r\n if (typeof fromKind === 'boolean') return fromKind\r\n if (typeof map.file === 'boolean' && kind !== 'file') return map.file\r\n return true\r\n }\r\n\r\n validateFile(file: File, kind?: UploadKind) {\r\n const inferredKind = kind ?? this.inferKind(file)\r\n const accept = this.getAccept(inferredKind)\r\n const maxSize = this.getMaxSize(inferredKind)\r\n const mimeOk = accept.some((type) => {\r\n // 简单区分:带 '/' 的按 MIME,其他按后缀\r\n if (type.includes('/')) {\r\n return (file.type || 'text/plain').match(type.replaceAll('*', '.*'))\r\n }\r\n else {\r\n // 按文件名后缀匹配,例如 'png' / '.png'\r\n const ext = type.startsWith('.') ? type.toLowerCase() : `.${type.toLowerCase()}`\r\n return file.name.toLowerCase().endsWith(ext)\r\n }\r\n })\r\n return mimeOk && file.size < maxSize\r\n }\r\n\r\n async getFileUrls(files: File[], range: Range, kind?: UploadKind) {\r\n const uploads = files.filter(file => this.validateFile(file, kind))\r\n return this.options.handler.call(this, range, uploads)\r\n }\r\n\r\n async upload(range: Range, files: FileList | File[], kind?: UploadKind) {\r\n const uploads = []\r\n const fails = []\r\n\r\n for (const file of Array.from(files)) {\r\n if (this.validateFile(file, kind)) {\r\n uploads.push(file)\r\n }\r\n else {\r\n fails.push(file)\r\n }\r\n }\r\n\r\n const result = await this.options.handler.call(this, range, uploads)\r\n const updateDelta = result.reduce((delta, url, i) => {\r\n if (isString(url)) {\r\n const type = uploads[i].type\r\n if (type.startsWith('image/')) {\r\n delta.insert({ image: url })\r\n }\r\n else if (type.startsWith('video/')) {\r\n delta.insert({ video: { src: url } })\r\n }\r\n else {\r\n delta.insert({ file: { size: uploads[i].size, title: uploads[i].name, src: url } })\r\n }\r\n }\r\n else {\r\n delta.insert(' ')\r\n }\r\n return delta\r\n }, new Delta().retain(range.index).delete(range.length))\r\n\r\n this.quill.updateContents(updateDelta, Quill.sources.USER)\r\n this.quill.setSelection(range.index + result.length, Quill.sources.SILENT)\r\n\r\n for (const file of fails) {\r\n this.options.fail.call(this, file, range)\r\n }\r\n\r\n for (const [i, res] of result.entries()) {\r\n if (isString(res)) {\r\n this.options.success.call(this, files[i], { index: range.index + i, length: 0 })\r\n }\r\n else {\r\n this.options.fail.call(this, files[i], { index: range.index + i, length: 0 })\r\n }\r\n }\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"custom-uploader.es.js","sources":["../../../src/modules/custom-uploader.ts"],"sourcesContent":["import type { Range } from 'quill'\r\nimport type TypeUploader from 'quill/modules/uploader'\r\nimport type FluentEditor from '../core/fluent-editor'\r\nimport Quill from 'quill'\r\nimport { isString } from '../utils/is'\r\n\r\nconst Uploader = Quill.import('modules/uploader') as typeof TypeUploader\r\nconst Delta = Quill.import('delta')\r\n\r\nexport type UploadKind = 'image' | 'video' | 'file'\r\nexport type MimeTypesConfig = string[] | Partial<Record<UploadKind, string[]>>\r\nexport type MaxSizeConfig = number | Partial<Record<UploadKind, number>>\r\nexport type MultipleConfig = boolean | Partial<Record<UploadKind, boolean>>\r\n\r\ninterface UploaderOptions {\r\n mimetypes: string[]\r\n handler: (this: { quill: Quill }, range: Range, files: File[]) => void\r\n}\r\nexport interface FileUploaderOptions {\r\n /**\r\n * 支持单个 MIME type、模糊匹配子类型和后缀名三种格式\r\n * - 全局配置:`string[]`\r\n * - 根据文件/图片/视频单独配置:`{ file?: string[]; image?: string[]; video?: string[] }`\r\n */\r\n mimetypes: MimeTypesConfig\r\n /**\r\n * 最大文件大小限制(字节)\r\n * - 全局配置:`number`\r\n * - 根据文件/图片/视频单独配置:`{ file?: number; image?: number; video?: number }`\r\n */\r\n maxSize: MaxSizeConfig\r\n /**\r\n * 是否允许多选文件\r\n * - 全局配置:`boolean`\r\n * - 根据文件/图片/视频单独配置:`{ file?: boolean; image?: boolean; video?: boolean }`\r\n */\r\n multiple: MultipleConfig\r\n handler: (this: { quill: FluentEditor }, range: Range, files: File[]) => Promise<(string | false)[]> | (string | false)[]\r\n success: (this: { quill: FluentEditor }, file: File, range: Range) => void\r\n fail: (this: { quill: FluentEditor }, file: File, range: Range) => void\r\n}\r\nexport class FileUploader extends Uploader {\r\n static DEFAULTS = {} as any\r\n // Partial<UploaderOptions> for ts type\r\n declare options: Partial<UploaderOptions> & FileUploaderOptions\r\n constructor(public quill: FluentEditor, options: Partial<FileUploaderOptions>) {\r\n super(quill, options as any)\r\n this.options = this.resolveOptions(options)\r\n // paste handle in clipboard\r\n }\r\n\r\n resolveOptions(options: Partial<FileUploaderOptions> = {}) {\r\n return Object.assign({\r\n mimetypes: ['*'],\r\n maxSize: Number.POSITIVE_INFINITY,\r\n multiple: true,\r\n handler(range: Range, files: File[]) {\r\n return files.map(file => URL.createObjectURL(file))\r\n },\r\n success() {},\r\n fail() {},\r\n }, options)\r\n }\r\n\r\n private inferKind(file: File): UploadKind {\r\n const type = file.type || ''\r\n if (type.startsWith('image/')) return 'image'\r\n if (type.startsWith('video/')) return 'video'\r\n return 'file'\r\n }\r\n\r\n private filterFromArray(types: string[], kind: UploadKind): string[] {\r\n if (kind === 'file') return types\r\n const prefix = `${kind}/`\r\n return types.filter((type) => {\r\n if (type === '*') return true\r\n if (type.includes('/')) return type.startsWith(prefix)\r\n return true\r\n })\r\n }\r\n\r\n getAccept(kind: UploadKind): string[] {\r\n const mimetypes = this.options.mimetypes\r\n if (Array.isArray(mimetypes)) {\r\n return this.filterFromArray(mimetypes, kind)\r\n }\r\n const map = (mimetypes || {}) as any\r\n const fromKind = map[kind]\r\n if (fromKind?.length) return fromKind as string[]\r\n if (map.file?.length && kind !== 'file') return map.file as string[]\r\n return []\r\n }\r\n\r\n getMaxSize(kind: UploadKind): number {\r\n const maxSize = this.options.maxSize\r\n if (typeof maxSize === 'number') {\r\n return maxSize\r\n }\r\n const map = (maxSize || {}) as any\r\n const fromKind = map[kind]\r\n if (typeof fromKind === 'number') return fromKind\r\n if (typeof map.file === 'number' && kind !== 'file') return map.file\r\n return Number.POSITIVE_INFINITY\r\n }\r\n\r\n getMultiple(kind: UploadKind): boolean {\r\n const multiple = this.options.multiple\r\n if (typeof multiple === 'boolean') {\r\n return multiple\r\n }\r\n const map = (multiple || {}) as any\r\n const fromKind = map[kind]\r\n if (typeof fromKind === 'boolean') return fromKind\r\n if (typeof map.file === 'boolean' && kind !== 'file') return map.file\r\n return true\r\n }\r\n\r\n validateFile(file: File, kind?: UploadKind) {\r\n const inferredKind = kind ?? this.inferKind(file)\r\n const accept = this.getAccept(inferredKind)\r\n const maxSize = this.getMaxSize(inferredKind)\r\n const mimeOk = accept.some((type) => {\r\n // 简单区分:带 '/' 的按 MIME,其他按后缀\r\n if (type.includes('/')) {\r\n return (file.type || 'text/plain').match(type.replaceAll('*', '.*'))\r\n }\r\n else {\r\n // 按文件名后缀匹配,例如 'png' / '.png'\r\n const ext = type.startsWith('.') ? type.toLowerCase() : `.${type.toLowerCase()}`\r\n return file.name.toLowerCase().endsWith(ext)\r\n }\r\n })\r\n return mimeOk && file.size < maxSize\r\n }\r\n\r\n async getFileUrls(files: File[], range: Range, kind?: UploadKind) {\r\n const uploads = files.filter(file => this.validateFile(file, kind))\r\n return this.options.handler.call(this, range, uploads)\r\n }\r\n\r\n async upload(range: Range, files: FileList | File[], kind?: UploadKind) {\r\n const uploads = []\r\n const fails = []\r\n\r\n for (const file of Array.from(files)) {\r\n if (this.validateFile(file, kind)) {\r\n uploads.push(file)\r\n }\r\n else {\r\n fails.push(file)\r\n }\r\n }\r\n\r\n const result = await this.options.handler.call(this, range, uploads)\r\n const updateDelta = result.reduce((delta, url, i) => {\r\n if (isString(url)) {\r\n const type = uploads[i].type\r\n if (type.startsWith('image/')) {\r\n delta.insert({ image: url })\r\n }\r\n else if (type.startsWith('video/')) {\r\n delta.insert({ video: { src: url } })\r\n }\r\n else {\r\n delta.insert({ file: { size: uploads[i].size, title: uploads[i].name, src: url } })\r\n }\r\n }\r\n else {\r\n delta.insert(' ')\r\n }\r\n return delta\r\n }, new Delta().retain(range.index).delete(range.length))\r\n\r\n this.quill.updateContents(updateDelta, Quill.sources.USER)\r\n this.quill.setSelection(range.index + result.length, Quill.sources.SILENT)\r\n\r\n for (const file of fails) {\r\n this.options.fail.call(this, file, range)\r\n }\r\n\r\n for (const [i, res] of result.entries()) {\r\n if (isString(res)) {\r\n this.options.success.call(this, files[i], { index: range.index + i, length: 0 })\r\n }\r\n else {\r\n this.options.fail.call(this, files[i], { index: range.index + i, length: 0 })\r\n }\r\n }\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-module.es.js","sources":["../../../../../src/modules/file/modules/file-module.ts"],"sourcesContent":["import type FluentEditor from '../../../core/fluent-editor'\nimport Quill from 'quill'\nimport { File } from '../formats/file'\nimport { FileBar } from './file-bar'\n\nexport class FileModule {\n fileBar: FileBar\n\n static register() {\n Quill.register('formats/file', File, true)\n }\n\n constructor(public quill: FluentEditor) {\n this.quill = quill\n quill.root.addEventListener('click', event => this.clickEvent(event), false)\n }\n\n clickEvent(event: MouseEvent) {\n const target = event.target as HTMLElement\n const fileDom = target.closest('a.ql-file-item')\n const fileBar = target.closest('.ql-file-bar')\n\n if (fileDom) {\n event.preventDefault()\n // 在只读模式下直接下载文件\n if (!this.quill.isEnabled()) {\n this.downloadFile(fileDom)\n return\n }\n if (this.fileBar) {\n this.fileBar.destroy()\n }\n this.fileBar = new FileBar(this.quill, fileDom)\n }\n else if (this.fileBar && !fileBar) {\n event.preventDefault()\n this.fileBar.destroy()\n this.fileBar = null\n }\n }\n\n downloadFile(fileDom: HTMLElement) {\n const fileName = fileDom.dataset.title || ''\n const fileDownloadUrl = fileDom.getAttribute('href') || ''\n if (fileDownloadUrl) {\n const a = document.createElement('a')\n a.href = fileDownloadUrl\n a.target = '_blank'\n a.id = 'exppub'\n a.download = fileName\n document.body.appendChild(a)\n const alink = document.getElementById('exppub')\n alink?.click()\n alink?.parentNode?.removeChild(a)\n }\n }\n}\n"],"names":[],"mappings":";;;;;;AAKO,MAAM,WAAW;AAAA,EAOtB,YAAmB,OAAqB;AANxC;AAMmB,SAAA,QAAA;AACjB,SAAK,QAAQ;AACb,UAAM,KAAK,iBAAiB,SAAS,CAAA,UAAS,KAAK,WAAW,KAAK,GAAG,KAAK;AAAA,EAC7E;AAAA,EAPA,OAAO,WAAW;AAChB,UAAM,SAAS,gBAAgB,MAAM,IAAI;AAAA,EAC3C;AAAA,EAOA,WAAW,OAAmB;AAC5B,UAAM,SAAS,MAAM;AACrB,UAAM,UAAU,OAAO,QAAQ,gBAAgB;AAC/C,UAAM,UAAU,OAAO,QAAQ,cAAc;AAE7C,QAAI,SAAS;AACX,YAAM,eAAA;AAEN,UAAI,CAAC,KAAK,MAAM,aAAa;AAC3B,aAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"file-module.es.js","sources":["../../../../../src/modules/file/modules/file-module.ts"],"sourcesContent":["import type FluentEditor from '../../../core/fluent-editor'\nimport Quill from 'quill'\nimport { File } from '../formats/file'\nimport { FileBar } from './file-bar'\n\nexport class FileModule {\n fileBar: FileBar\n\n static register() {\n Quill.register('formats/file', File, true)\n }\n\n constructor(public quill: FluentEditor) {\n this.quill = quill\n quill.root.addEventListener('click', event => this.clickEvent(event), false)\n }\n\n clickEvent(event: MouseEvent) {\n const target = event.target as HTMLElement\n const fileDom = target.closest('a.ql-file-item')\n const fileBar = target.closest('.ql-file-bar')\n\n if (fileDom) {\n event.preventDefault()\n // 在只读模式下直接下载文件\n if (!this.quill.isEnabled()) {\n this.downloadFile(fileDom as HTMLElement)\n return\n }\n if (this.fileBar) {\n this.fileBar.destroy()\n }\n this.fileBar = new FileBar(this.quill, fileDom)\n }\n else if (this.fileBar && !fileBar) {\n event.preventDefault()\n this.fileBar.destroy()\n this.fileBar = null\n }\n }\n\n downloadFile(fileDom: HTMLElement) {\n const fileName = fileDom.dataset.title || ''\n const fileDownloadUrl = fileDom.getAttribute('href') || ''\n if (fileDownloadUrl) {\n const a = document.createElement('a')\n a.href = fileDownloadUrl\n a.target = '_blank'\n a.id = 'exppub'\n a.download = fileName\n document.body.appendChild(a)\n const alink = document.getElementById('exppub')\n alink?.click()\n alink?.parentNode?.removeChild(a)\n }\n }\n}\n"],"names":[],"mappings":";;;;;;AAKO,MAAM,WAAW;AAAA,EAOtB,YAAmB,OAAqB;AANxC;AAMmB,SAAA,QAAA;AACjB,SAAK,QAAQ;AACb,UAAM,KAAK,iBAAiB,SAAS,CAAA,UAAS,KAAK,WAAW,KAAK,GAAG,KAAK;AAAA,EAC7E;AAAA,EAPA,OAAO,WAAW;AAChB,UAAM,SAAS,gBAAgB,MAAM,IAAI;AAAA,EAC3C;AAAA,EAOA,WAAW,OAAmB;AAC5B,UAAM,SAAS,MAAM;AACrB,UAAM,UAAU,OAAO,QAAQ,gBAAgB;AAC/C,UAAM,UAAU,OAAO,QAAQ,cAAc;AAE7C,QAAI,SAAS;AACX,YAAM,eAAA;AAEN,UAAI,CAAC,KAAK,MAAM,aAAa;AAC3B,aAAK,aAAa,OAAsB;AACxC;AAAA,MACF;AACA,UAAI,KAAK,SAAS;AAChB,aAAK,QAAQ,QAAA;AAAA,MACf;AACA,WAAK,UAAU,IAAI,QAAQ,KAAK,OAAO,OAAO;AAAA,IAChD,WACS,KAAK,WAAW,CAAC,SAAS;AACjC,YAAM,eAAA;AACN,WAAK,QAAQ,QAAA;AACb,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,aAAa,SAAsB;;AACjC,UAAM,WAAW,QAAQ,QAAQ,SAAS;AAC1C,UAAM,kBAAkB,QAAQ,aAAa,MAAM,KAAK;AACxD,QAAI,iBAAiB;AACnB,YAAM,IAAI,SAAS,cAAc,GAAG;AACpC,QAAE,OAAO;AACT,QAAE,SAAS;AACX,QAAE,KAAK;AACP,QAAE,WAAW;AACb,eAAS,KAAK,YAAY,CAAC;AAC3B,YAAM,QAAQ,SAAS,eAAe,QAAQ;AAC9C,qCAAO;AACP,2CAAO,eAAP,mBAAmB,YAAY;AAAA,IACjC;AAAA,EACF;AACF;"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { FLOW_CHART_EN_US } from "./en-us.es.js";
|
|
2
2
|
import { FLOW_CHART_ZH_CN } from "./zh-cn.es.js";
|
|
3
|
-
function registerFlowChartI18N(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"zh-CN": FLOW_CHART_ZH_CN
|
|
7
|
-
}, false);
|
|
3
|
+
function registerFlowChartI18N(i18nModule) {
|
|
4
|
+
i18nModule.addMessages("en-US", FLOW_CHART_EN_US);
|
|
5
|
+
i18nModule.addMessages("zh-CN", FLOW_CHART_ZH_CN);
|
|
8
6
|
}
|
|
9
7
|
export {
|
|
10
8
|
registerFlowChartI18N
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../../../../../src/modules/flow-chart/i18n/index.ts"],"sourcesContent":["import { FLOW_CHART_EN_US } from './en-us'\nimport { FLOW_CHART_ZH_CN } from './zh-cn'\n\nexport function registerFlowChartI18N(
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../../../../../src/modules/flow-chart/i18n/index.ts"],"sourcesContent":["import { FLOW_CHART_EN_US } from './en-us'\nimport { FLOW_CHART_ZH_CN } from './zh-cn'\n\nexport function registerFlowChartI18N(i18nModule: any) {\n i18nModule.addMessages('en-US', FLOW_CHART_EN_US)\n i18nModule.addMessages('zh-CN', FLOW_CHART_ZH_CN)\n}\n"],"names":[],"mappings":";;AAGO,SAAS,sBAAsB,YAAiB;AACrD,aAAW,YAAY,SAAS,gBAAgB;AAChD,aAAW,YAAY,SAAS,gBAAgB;AAClD;"}
|
|
@@ -1,10 +1,7 @@
|
|
|
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 "../../../config/index.es.js";
|
|
5
|
-
import { I18N } from "../../i18n.es.js";
|
|
6
4
|
import { registerFlowChartI18N } from "../i18n/index.es.js";
|
|
7
|
-
import { CHANGE_LANGUAGE_EVENT } from "../../../config/editor.config.es.js";
|
|
8
5
|
class FlowChartContextMenuHandler {
|
|
9
6
|
constructor(quill, blot) {
|
|
10
7
|
__publicField(this, "texts");
|
|
@@ -12,11 +9,11 @@ class FlowChartContextMenuHandler {
|
|
|
12
9
|
this.quill = quill;
|
|
13
10
|
this.blot = blot;
|
|
14
11
|
const i18nModule = this.quill.getModule("i18n");
|
|
15
|
-
registerFlowChartI18N(
|
|
16
|
-
this.lang = i18nModule.
|
|
12
|
+
registerFlowChartI18N(i18nModule);
|
|
13
|
+
this.lang = i18nModule.getLocale();
|
|
17
14
|
this.texts = this.resolveTexts();
|
|
18
|
-
this.quill.
|
|
19
|
-
this.lang =
|
|
15
|
+
this.quill.on("i18n-locale-change", (event) => {
|
|
16
|
+
this.lang = event.locale;
|
|
20
17
|
this.texts = this.resolveTexts();
|
|
21
18
|
this.updateContextMenuItems();
|
|
22
19
|
});
|
|
@@ -26,12 +23,12 @@ class FlowChartContextMenuHandler {
|
|
|
26
23
|
}
|
|
27
24
|
resolveTexts() {
|
|
28
25
|
return {
|
|
29
|
-
copy:
|
|
30
|
-
cut:
|
|
31
|
-
paste:
|
|
32
|
-
deleteContent:
|
|
33
|
-
deleteNode:
|
|
34
|
-
deleteEdge:
|
|
26
|
+
copy: this.quill.getLangText("flowChart.contextMenu.copy"),
|
|
27
|
+
cut: this.quill.getLangText("flowChart.contextMenu.cut"),
|
|
28
|
+
paste: this.quill.getLangText("flowChart.contextMenu.paste"),
|
|
29
|
+
deleteContent: this.quill.getLangText("flowChart.contextMenu.deleteContent"),
|
|
30
|
+
deleteNode: this.quill.getLangText("flowChart.contextMenu.deleteNode"),
|
|
31
|
+
deleteEdge: this.quill.getLangText("flowChart.contextMenu.deleteEdge")
|
|
35
32
|
};
|
|
36
33
|
}
|
|
37
34
|
updateContextMenuItems() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-menu.es.js","sources":["../../../../../src/modules/flow-chart/modules/context-menu.ts"],"sourcesContent":["import type FluentEditor from '../../../core/fluent-editor'\nimport type FlowChartPlaceholderBlot from '../formats/flow-chart-blot'\nimport { CHANGE_LANGUAGE_EVENT } from '../../../config'\nimport { I18N } from '../../../modules/i18n'\nimport { registerFlowChartI18N } from '../i18n/index'\n\nclass FlowChartContextMenuHandler {\n private texts: Record<string, string>\n private lang: string\n getText(key: keyof Record<string, string>): string {\n return this.texts[key]\n }\n\n constructor(private quill: FluentEditor, private blot: FlowChartPlaceholderBlot) {\n const i18nModule = this.quill.getModule('i18n') as I18N\n registerFlowChartI18N(I18N)\n this.lang = i18nModule.options.lang\n this.texts = this.resolveTexts()\n this.quill.emitter.on(CHANGE_LANGUAGE_EVENT, (lang: string) => {\n this.lang = lang\n this.texts = this.resolveTexts()\n this.updateContextMenuItems()\n })\n }\n\n resolveTexts() {\n return {\n copy: I18N.parserText('flowChart.contextMenu.copy', this.lang),\n cut: I18N.parserText('flowChart.contextMenu.cut', this.lang),\n paste: I18N.parserText('flowChart.contextMenu.paste', this.lang),\n deleteContent: I18N.parserText('flowChart.contextMenu.deleteContent', this.lang),\n deleteNode: I18N.parserText('flowChart.contextMenu.deleteNode', this.lang),\n deleteEdge: I18N.parserText('flowChart.contextMenu.deleteEdge', this.lang),\n }\n }\n\n updateContextMenuItems() {\n if (!this.blot.contextMenu) return\n\n const menuItems = this.blot.contextMenu.querySelectorAll('.ql-flow-chart-context-menu-item')\n if (menuItems.length > 0) {\n Array.from(menuItems).forEach((item) => {\n const text = item.getAttribute('data-text-key')\n if (text && this.texts[text as keyof Record<string, string>]) {\n item.textContent = this.texts[text as keyof Record<string, string>]\n }\n })\n }\n }\n}\n\nconst contextMenuHandlers = new WeakMap<FlowChartPlaceholderBlot, FlowChartContextMenuHandler>()\n\nexport function initContextMenu(blot: FlowChartPlaceholderBlot, quill: FluentEditor): void {\n blot.contextMenu = document.createElement('div')\n blot.contextMenu.className = 'ql-flow-chart-context-menu'\n blot.contextMenu.style.position = 'fixed'\n blot.contextMenu.style.background = 'white'\n blot.contextMenu.style.borderRadius = '4px'\n blot.contextMenu.style.boxShadow = '0 2px 10px rgba(0,0,0,0.1)'\n blot.contextMenu.style.padding = '5px 0'\n blot.contextMenu.style.zIndex = '1000'\n blot.contextMenu.style.display = 'block'\n blot.contextMenu.style.visibility = 'visible'\n blot.contextMenu.style.opacity = '1'\n blot.contextMenu.style.width = '120px'\n blot.contextMenu.style.height = 'auto'\n blot.domNode.appendChild(blot.contextMenu)\n\n const handler = new FlowChartContextMenuHandler(quill, blot)\n contextMenuHandlers.set(blot, handler)\n\n if (blot.flowChart) {\n blot.flowChart.on('node:contextmenu', (event: any) => {\n const { data, e } = event\n e.preventDefault()\n e.stopPropagation()\n blot.currentElement = { type: 'node', data }\n showNodeContextMenu(blot, handler, e.clientX, e.clientY)\n })\n\n blot.flowChart.on('edge:contextmenu', (event: any) => {\n const { data, e } = event\n e.preventDefault()\n e.stopPropagation()\n blot.currentElement = { type: 'edge', data }\n showEdgeContextMenu(blot, handler, e.clientX, e.clientY)\n })\n }\n\n const hideMenu = () => {\n if (blot.contextMenu) {\n blot.contextMenu.style.display = 'none'\n blot.currentElement = null\n }\n }\n\n blot.flowChart.on('blank:click', hideMenu)\n document.addEventListener('click', (e) => {\n if (blot.contextMenu && !blot.contextMenu.contains(e.target as Node)) {\n hideMenu()\n }\n })\n}\n\nfunction showNodeContextMenu(blot: FlowChartPlaceholderBlot, handler: FlowChartContextMenuHandler, x: number, y: number): void {\n clearContextMenu(blot)\n\n addContextMenuItem(blot, handler.getText('copy'), 'copy', () => handleCopy(blot))\n addContextMenuItem(blot, handler.getText('deleteContent'), 'deleteContent', () => handleDeleteContent(blot))\n addContextMenuItem(blot, handler.getText('deleteNode'), 'deleteNode', () => handleDeleteNode(blot))\n\n showContextMenu(blot, x, y)\n}\n\nfunction showEdgeContextMenu(blot: FlowChartPlaceholderBlot, handler: FlowChartContextMenuHandler, x: number, y: number): void {\n clearContextMenu(blot)\n\n addContextMenuItem(blot, handler.getText('deleteContent'), 'deleteContent', () => handleDeleteContent(blot))\n addContextMenuItem(blot, handler.getText('deleteEdge'), 'deleteEdge', () => handleDeleteEdge(blot))\n\n showContextMenu(blot, x, y)\n}\n\nfunction clearContextMenu(blot: FlowChartPlaceholderBlot): void {\n if (blot.contextMenu) {\n blot.contextMenu.innerHTML = ''\n }\n}\n\nfunction showContextMenu(blot: FlowChartPlaceholderBlot, x: number, y: number): void {\n if (blot.contextMenu) {\n blot.contextMenu.style.display = 'block'\n blot.contextMenu.style.left = `${x}px`\n blot.contextMenu.style.top = `${y}px`\n }\n}\n\nfunction addContextMenuItem(blot: FlowChartPlaceholderBlot, text: string, textKey: string, onClick: () => void): void {\n const item = document.createElement('div')\n item.className = 'ql-flow-chart-context-menu-item'\n item.textContent = text\n item.setAttribute('data-text-key', textKey)\n item.style.padding = '5px 15px'\n item.style.cursor = 'pointer'\n item.style.whiteSpace = 'nowrap'\n item.addEventListener('click', onClick)\n item.addEventListener('mouseenter', () => {\n item.style.background = '#f5f5f5'\n })\n item.addEventListener('mouseleave', () => {\n item.style.background = 'white'\n })\n blot.contextMenu!.appendChild(item)\n}\n\nfunction handleCopy(blot: FlowChartPlaceholderBlot): void {\n if (blot.currentElement && blot.currentElement.type === 'node') {\n const nodeId = blot.currentElement.data.id\n blot.flowChart.cloneNode(nodeId)\n }\n hideContextMenu(blot)\n}\n\nfunction handleDeleteContent(blot: FlowChartPlaceholderBlot): void {\n if (blot.currentElement) {\n if (blot.currentElement.type === 'node') {\n const node = blot.currentElement.data\n blot.flowChart.updateText(node.id, '')\n }\n else if (blot.currentElement.type === 'edge') {\n const edge = blot.currentElement.data\n blot.flowChart.updateText(edge.id, '')\n }\n blot.data = blot.flowChart.getGraphData()\n blot.domNode.setAttribute('data-flow-chart', JSON.stringify(blot.data))\n }\n hideContextMenu(blot)\n}\n\nfunction handleDeleteNode(blot: FlowChartPlaceholderBlot): void {\n if (blot.currentElement && blot.currentElement.type === 'node') {\n blot.flowChart.deleteNode(blot.currentElement.data.id)\n blot.data = blot.flowChart.getGraphData()\n blot.domNode.setAttribute('data-flow-chart', JSON.stringify(blot.data))\n }\n hideContextMenu(blot)\n}\n\nfunction handleDeleteEdge(blot: FlowChartPlaceholderBlot): void {\n if (blot.currentElement && blot.currentElement.type === 'edge') {\n blot.flowChart.deleteEdge(blot.currentElement.data.id)\n blot.data = blot.flowChart.getGraphData()\n blot.domNode.setAttribute('data-flow-chart', JSON.stringify(blot.data))\n }\n hideContextMenu(blot)\n}\n\nfunction hideContextMenu(blot: FlowChartPlaceholderBlot): void {\n if (blot.contextMenu) {\n blot.contextMenu.style.display = 'none'\n }\n}\n"],"names":[],"mappings":";;;;;;;AAMA,MAAM,4BAA4B;AAAA,EAOhC,YAAoB,OAA6B,MAAgC;AANzE;AACA;AAKY,SAAA,QAAA;AAA6B,SAAA,OAAA;AAC/C,UAAM,aAAa,KAAK,MAAM,UAAU,MAAM;AAC9C,0BAAsB,IAAI;AAC1B,SAAK,OAAO,WAAW,QAAQ;AAC/B,SAAK,QAAQ,KAAK,aAAA;AAClB,SAAK,MAAM,QAAQ,GAAG,uBAAuB,CAAC,SAAiB;AAC7D,WAAK,OAAO;AACZ,WAAK,QAAQ,KAAK,aAAA;AAClB,WAAK,uBAAA;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAdA,QAAQ,KAA2C;AACjD,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB;AAAA,EAcA,eAAe;AACb,WAAO;AAAA,MACL,MAAM,KAAK,WAAW,8BAA8B,KAAK,IAAI;AAAA,MAC7D,KAAK,KAAK,WAAW,6BAA6B,KAAK,IAAI;AAAA,MAC3D,OAAO,KAAK,WAAW,+BAA+B,KAAK,IAAI;AAAA,MAC/D,eAAe,KAAK,WAAW,uCAAuC,KAAK,IAAI;AAAA,MAC/E,YAAY,KAAK,WAAW,oCAAoC,KAAK,IAAI;AAAA,MACzE,YAAY,KAAK,WAAW,oCAAoC,KAAK,IAAI;AAAA,IAAA;AAAA,EAE7E;AAAA,EAEA,yBAAyB;AACvB,QAAI,CAAC,KAAK,KAAK,YAAa;AAE5B,UAAM,YAAY,KAAK,KAAK,YAAY,iBAAiB,kCAAkC;AAC3F,QAAI,UAAU,SAAS,GAAG;AACxB,YAAM,KAAK,SAAS,EAAE,QAAQ,CAAC,SAAS;AACtC,cAAM,OAAO,KAAK,aAAa,eAAe;AAC9C,YAAI,QAAQ,KAAK,MAAM,IAAoC,GAAG;AAC5D,eAAK,cAAc,KAAK,MAAM,IAAoC;AAAA,QACpE;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,MAAM,0CAA0B,QAAA;AAEzB,SAAS,gBAAgB,MAAgC,OAA2B;AACzF,OAAK,cAAc,SAAS,cAAc,KAAK;AAC/C,OAAK,YAAY,YAAY;AAC7B,OAAK,YAAY,MAAM,WAAW;AAClC,OAAK,YAAY,MAAM,aAAa;AACpC,OAAK,YAAY,MAAM,eAAe;AACtC,OAAK,YAAY,MAAM,YAAY;AACnC,OAAK,YAAY,MAAM,UAAU;AACjC,OAAK,YAAY,MAAM,SAAS;AAChC,OAAK,YAAY,MAAM,UAAU;AACjC,OAAK,YAAY,MAAM,aAAa;AACpC,OAAK,YAAY,MAAM,UAAU;AACjC,OAAK,YAAY,MAAM,QAAQ;AAC/B,OAAK,YAAY,MAAM,SAAS;AAChC,OAAK,QAAQ,YAAY,KAAK,WAAW;AAEzC,QAAM,UAAU,IAAI,4BAA4B,OAAO,IAAI;AAC3D,sBAAoB,IAAI,MAAM,OAAO;AAErC,MAAI,KAAK,WAAW;AAClB,SAAK,UAAU,GAAG,oBAAoB,CAAC,UAAe;AACpD,YAAM,EAAE,MAAM,EAAA,IAAM;AACpB,QAAE,eAAA;AACF,QAAE,gBAAA;AACF,WAAK,iBAAiB,EAAE,MAAM,QAAQ,KAAA;AACtC,0BAAoB,MAAM,SAAS,EAAE,SAAS,EAAE,OAAO;AAAA,IACzD,CAAC;AAED,SAAK,UAAU,GAAG,oBAAoB,CAAC,UAAe;AACpD,YAAM,EAAE,MAAM,EAAA,IAAM;AACpB,QAAE,eAAA;AACF,QAAE,gBAAA;AACF,WAAK,iBAAiB,EAAE,MAAM,QAAQ,KAAA;AACtC,0BAAoB,MAAM,SAAS,EAAE,SAAS,EAAE,OAAO;AAAA,IACzD,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,MAAM;AACrB,QAAI,KAAK,aAAa;AACpB,WAAK,YAAY,MAAM,UAAU;AACjC,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAEA,OAAK,UAAU,GAAG,eAAe,QAAQ;AACzC,WAAS,iBAAiB,SAAS,CAAC,MAAM;AACxC,QAAI,KAAK,eAAe,CAAC,KAAK,YAAY,SAAS,EAAE,MAAc,GAAG;AACpE,eAAA;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,SAAS,oBAAoB,MAAgC,SAAsC,GAAW,GAAiB;AAC7H,mBAAiB,IAAI;AAErB,qBAAmB,MAAM,QAAQ,QAAQ,MAAM,GAAG,QAAQ,MAAM,WAAW,IAAI,CAAC;AAChF,qBAAmB,MAAM,QAAQ,QAAQ,eAAe,GAAG,iBAAiB,MAAM,oBAAoB,IAAI,CAAC;AAC3G,qBAAmB,MAAM,QAAQ,QAAQ,YAAY,GAAG,cAAc,MAAM,iBAAiB,IAAI,CAAC;AAElG,kBAAgB,MAAM,GAAG,CAAC;AAC5B;AAEA,SAAS,oBAAoB,MAAgC,SAAsC,GAAW,GAAiB;AAC7H,mBAAiB,IAAI;AAErB,qBAAmB,MAAM,QAAQ,QAAQ,eAAe,GAAG,iBAAiB,MAAM,oBAAoB,IAAI,CAAC;AAC3G,qBAAmB,MAAM,QAAQ,QAAQ,YAAY,GAAG,cAAc,MAAM,iBAAiB,IAAI,CAAC;AAElG,kBAAgB,MAAM,GAAG,CAAC;AAC5B;AAEA,SAAS,iBAAiB,MAAsC;AAC9D,MAAI,KAAK,aAAa;AACpB,SAAK,YAAY,YAAY;AAAA,EAC/B;AACF;AAEA,SAAS,gBAAgB,MAAgC,GAAW,GAAiB;AACnF,MAAI,KAAK,aAAa;AACpB,SAAK,YAAY,MAAM,UAAU;AACjC,SAAK,YAAY,MAAM,OAAO,GAAG,CAAC;AAClC,SAAK,YAAY,MAAM,MAAM,GAAG,CAAC;AAAA,EACnC;AACF;AAEA,SAAS,mBAAmB,MAAgC,MAAc,SAAiB,SAA2B;AACpH,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,YAAY;AACjB,OAAK,cAAc;AACnB,OAAK,aAAa,iBAAiB,OAAO;AAC1C,OAAK,MAAM,UAAU;AACrB,OAAK,MAAM,SAAS;AACpB,OAAK,MAAM,aAAa;AACxB,OAAK,iBAAiB,SAAS,OAAO;AACtC,OAAK,iBAAiB,cAAc,MAAM;AACxC,SAAK,MAAM,aAAa;AAAA,EAC1B,CAAC;AACD,OAAK,iBAAiB,cAAc,MAAM;AACxC,SAAK,MAAM,aAAa;AAAA,EAC1B,CAAC;AACD,OAAK,YAAa,YAAY,IAAI;AACpC;AAEA,SAAS,WAAW,MAAsC;AACxD,MAAI,KAAK,kBAAkB,KAAK,eAAe,SAAS,QAAQ;AAC9D,UAAM,SAAS,KAAK,eAAe,KAAK;AACxC,SAAK,UAAU,UAAU,MAAM;AAAA,EACjC;AACA,kBAAgB,IAAI;AACtB;AAEA,SAAS,oBAAoB,MAAsC;AACjE,MAAI,KAAK,gBAAgB;AACvB,QAAI,KAAK,eAAe,SAAS,QAAQ;AACvC,YAAM,OAAO,KAAK,eAAe;AACjC,WAAK,UAAU,WAAW,KAAK,IAAI,EAAE;AAAA,IACvC,WACS,KAAK,eAAe,SAAS,QAAQ;AAC5C,YAAM,OAAO,KAAK,eAAe;AACjC,WAAK,UAAU,WAAW,KAAK,IAAI,EAAE;AAAA,IACvC;AACA,SAAK,OAAO,KAAK,UAAU,aAAA;AAC3B,SAAK,QAAQ,aAAa,mBAAmB,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA,EACxE;AACA,kBAAgB,IAAI;AACtB;AAEA,SAAS,iBAAiB,MAAsC;AAC9D,MAAI,KAAK,kBAAkB,KAAK,eAAe,SAAS,QAAQ;AAC9D,SAAK,UAAU,WAAW,KAAK,eAAe,KAAK,EAAE;AACrD,SAAK,OAAO,KAAK,UAAU,aAAA;AAC3B,SAAK,QAAQ,aAAa,mBAAmB,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA,EACxE;AACA,kBAAgB,IAAI;AACtB;AAEA,SAAS,iBAAiB,MAAsC;AAC9D,MAAI,KAAK,kBAAkB,KAAK,eAAe,SAAS,QAAQ;AAC9D,SAAK,UAAU,WAAW,KAAK,eAAe,KAAK,EAAE;AACrD,SAAK,OAAO,KAAK,UAAU,aAAA;AAC3B,SAAK,QAAQ,aAAa,mBAAmB,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA,EACxE;AACA,kBAAgB,IAAI;AACtB;AAEA,SAAS,gBAAgB,MAAsC;AAC7D,MAAI,KAAK,aAAa;AACpB,SAAK,YAAY,MAAM,UAAU;AAAA,EACnC;AACF;"}
|
|
1
|
+
{"version":3,"file":"context-menu.es.js","sources":["../../../../../src/modules/flow-chart/modules/context-menu.ts"],"sourcesContent":["import type { I18n } from 'quill-i18n'\nimport type FluentEditor from '../../../core/fluent-editor'\nimport type FlowChartPlaceholderBlot from '../formats/flow-chart-blot'\nimport { registerFlowChartI18N } from '../i18n/index'\n\nclass FlowChartContextMenuHandler {\n private texts: Record<string, string>\n private lang: string\n getText(key: keyof Record<string, string>): string {\n return this.texts[key]\n }\n\n constructor(private quill: FluentEditor, private blot: FlowChartPlaceholderBlot) {\n const i18nModule = this.quill.getModule('i18n') as I18n\n registerFlowChartI18N(i18nModule)\n this.lang = i18nModule.getLocale()\n this.texts = this.resolveTexts()\n this.quill.on('i18n-locale-change', (event: { locale: string, oldLocale: string }) => {\n this.lang = event.locale\n this.texts = this.resolveTexts()\n this.updateContextMenuItems()\n })\n }\n\n resolveTexts() {\n return {\n copy: this.quill.getLangText('flowChart.contextMenu.copy'),\n cut: this.quill.getLangText('flowChart.contextMenu.cut'),\n paste: this.quill.getLangText('flowChart.contextMenu.paste'),\n deleteContent: this.quill.getLangText('flowChart.contextMenu.deleteContent'),\n deleteNode: this.quill.getLangText('flowChart.contextMenu.deleteNode'),\n deleteEdge: this.quill.getLangText('flowChart.contextMenu.deleteEdge'),\n }\n }\n\n updateContextMenuItems() {\n if (!this.blot.contextMenu) return\n\n const menuItems = this.blot.contextMenu.querySelectorAll('.ql-flow-chart-context-menu-item')\n if (menuItems.length > 0) {\n Array.from(menuItems).forEach((item) => {\n const text = item.getAttribute('data-text-key')\n if (text && this.texts[text as keyof Record<string, string>]) {\n item.textContent = this.texts[text as keyof Record<string, string>]\n }\n })\n }\n }\n}\n\nconst contextMenuHandlers = new WeakMap<FlowChartPlaceholderBlot, FlowChartContextMenuHandler>()\n\nexport function initContextMenu(blot: FlowChartPlaceholderBlot, quill: FluentEditor): void {\n blot.contextMenu = document.createElement('div')\n blot.contextMenu.className = 'ql-flow-chart-context-menu'\n blot.contextMenu.style.position = 'fixed'\n blot.contextMenu.style.background = 'white'\n blot.contextMenu.style.borderRadius = '4px'\n blot.contextMenu.style.boxShadow = '0 2px 10px rgba(0,0,0,0.1)'\n blot.contextMenu.style.padding = '5px 0'\n blot.contextMenu.style.zIndex = '1000'\n blot.contextMenu.style.display = 'block'\n blot.contextMenu.style.visibility = 'visible'\n blot.contextMenu.style.opacity = '1'\n blot.contextMenu.style.width = '120px'\n blot.contextMenu.style.height = 'auto'\n blot.domNode.appendChild(blot.contextMenu)\n\n const handler = new FlowChartContextMenuHandler(quill, blot)\n contextMenuHandlers.set(blot, handler)\n\n if (blot.flowChart) {\n blot.flowChart.on('node:contextmenu', (event: any) => {\n const { data, e } = event\n e.preventDefault()\n e.stopPropagation()\n blot.currentElement = { type: 'node', data }\n showNodeContextMenu(blot, handler, e.clientX, e.clientY)\n })\n\n blot.flowChart.on('edge:contextmenu', (event: any) => {\n const { data, e } = event\n e.preventDefault()\n e.stopPropagation()\n blot.currentElement = { type: 'edge', data }\n showEdgeContextMenu(blot, handler, e.clientX, e.clientY)\n })\n }\n\n const hideMenu = () => {\n if (blot.contextMenu) {\n blot.contextMenu.style.display = 'none'\n blot.currentElement = null\n }\n }\n\n blot.flowChart.on('blank:click', hideMenu)\n document.addEventListener('click', (e) => {\n if (blot.contextMenu && !blot.contextMenu.contains(e.target as Node)) {\n hideMenu()\n }\n })\n}\n\nfunction showNodeContextMenu(blot: FlowChartPlaceholderBlot, handler: FlowChartContextMenuHandler, x: number, y: number): void {\n clearContextMenu(blot)\n\n addContextMenuItem(blot, handler.getText('copy'), 'copy', () => handleCopy(blot))\n addContextMenuItem(blot, handler.getText('deleteContent'), 'deleteContent', () => handleDeleteContent(blot))\n addContextMenuItem(blot, handler.getText('deleteNode'), 'deleteNode', () => handleDeleteNode(blot))\n\n showContextMenu(blot, x, y)\n}\n\nfunction showEdgeContextMenu(blot: FlowChartPlaceholderBlot, handler: FlowChartContextMenuHandler, x: number, y: number): void {\n clearContextMenu(blot)\n\n addContextMenuItem(blot, handler.getText('deleteContent'), 'deleteContent', () => handleDeleteContent(blot))\n addContextMenuItem(blot, handler.getText('deleteEdge'), 'deleteEdge', () => handleDeleteEdge(blot))\n\n showContextMenu(blot, x, y)\n}\n\nfunction clearContextMenu(blot: FlowChartPlaceholderBlot): void {\n if (blot.contextMenu) {\n blot.contextMenu.innerHTML = ''\n }\n}\n\nfunction showContextMenu(blot: FlowChartPlaceholderBlot, x: number, y: number): void {\n if (blot.contextMenu) {\n blot.contextMenu.style.display = 'block'\n blot.contextMenu.style.left = `${x}px`\n blot.contextMenu.style.top = `${y}px`\n }\n}\n\nfunction addContextMenuItem(blot: FlowChartPlaceholderBlot, text: string, textKey: string, onClick: () => void): void {\n const item = document.createElement('div')\n item.className = 'ql-flow-chart-context-menu-item'\n item.textContent = text\n item.setAttribute('data-text-key', textKey)\n item.style.padding = '5px 15px'\n item.style.cursor = 'pointer'\n item.style.whiteSpace = 'nowrap'\n item.addEventListener('click', onClick)\n item.addEventListener('mouseenter', () => {\n item.style.background = '#f5f5f5'\n })\n item.addEventListener('mouseleave', () => {\n item.style.background = 'white'\n })\n blot.contextMenu!.appendChild(item)\n}\n\nfunction handleCopy(blot: FlowChartPlaceholderBlot): void {\n if (blot.currentElement && blot.currentElement.type === 'node') {\n const nodeId = blot.currentElement.data.id\n blot.flowChart.cloneNode(nodeId)\n }\n hideContextMenu(blot)\n}\n\nfunction handleDeleteContent(blot: FlowChartPlaceholderBlot): void {\n if (blot.currentElement) {\n if (blot.currentElement.type === 'node') {\n const node = blot.currentElement.data\n blot.flowChart.updateText(node.id, '')\n }\n else if (blot.currentElement.type === 'edge') {\n const edge = blot.currentElement.data\n blot.flowChart.updateText(edge.id, '')\n }\n blot.data = blot.flowChart.getGraphData()\n blot.domNode.setAttribute('data-flow-chart', JSON.stringify(blot.data))\n }\n hideContextMenu(blot)\n}\n\nfunction handleDeleteNode(blot: FlowChartPlaceholderBlot): void {\n if (blot.currentElement && blot.currentElement.type === 'node') {\n blot.flowChart.deleteNode(blot.currentElement.data.id)\n blot.data = blot.flowChart.getGraphData()\n blot.domNode.setAttribute('data-flow-chart', JSON.stringify(blot.data))\n }\n hideContextMenu(blot)\n}\n\nfunction handleDeleteEdge(blot: FlowChartPlaceholderBlot): void {\n if (blot.currentElement && blot.currentElement.type === 'edge') {\n blot.flowChart.deleteEdge(blot.currentElement.data.id)\n blot.data = blot.flowChart.getGraphData()\n blot.domNode.setAttribute('data-flow-chart', JSON.stringify(blot.data))\n }\n hideContextMenu(blot)\n}\n\nfunction hideContextMenu(blot: FlowChartPlaceholderBlot): void {\n if (blot.contextMenu) {\n blot.contextMenu.style.display = 'none'\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,8 @@
|
|
|
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 "../../../config/index.es.js";
|
|
5
|
-
import { I18N } from "../../i18n.es.js";
|
|
6
4
|
import { registerFlowChartI18N } from "../i18n/index.es.js";
|
|
7
5
|
import { lineIcon, contractIcon, screenTypeIcon, fitIcon, zoomInIcon, zoomOutIcon, forwardIcon, backIcon, polyLineIcon, bezierIcon, screenReduceIcon } from "../icons.es.js";
|
|
8
|
-
import { CHANGE_LANGUAGE_EVENT } from "../../../config/editor.config.es.js";
|
|
9
6
|
class FlowChartControlPanelHandler {
|
|
10
7
|
constructor(quill, blot) {
|
|
11
8
|
__publicField(this, "texts");
|
|
@@ -13,11 +10,11 @@ class FlowChartControlPanelHandler {
|
|
|
13
10
|
this.quill = quill;
|
|
14
11
|
this.blot = blot;
|
|
15
12
|
const i18nModule = this.quill.getModule("i18n");
|
|
16
|
-
registerFlowChartI18N(
|
|
17
|
-
this.lang = i18nModule.
|
|
13
|
+
registerFlowChartI18N(i18nModule);
|
|
14
|
+
this.lang = i18nModule.getLocale();
|
|
18
15
|
this.texts = this.resolveTexts();
|
|
19
|
-
this.quill.
|
|
20
|
-
this.lang =
|
|
16
|
+
this.quill.on("i18n-locale-change", (event) => {
|
|
17
|
+
this.lang = event.locale;
|
|
21
18
|
this.texts = this.resolveTexts();
|
|
22
19
|
this.updateControlPanelTexts();
|
|
23
20
|
});
|
|
@@ -27,15 +24,15 @@ class FlowChartControlPanelHandler {
|
|
|
27
24
|
}
|
|
28
25
|
resolveTexts() {
|
|
29
26
|
return {
|
|
30
|
-
exportTitle:
|
|
31
|
-
zoomOutTitle:
|
|
32
|
-
zoomInTitle:
|
|
33
|
-
fitTitle:
|
|
34
|
-
backTitle:
|
|
35
|
-
forwardTitle:
|
|
36
|
-
setEdgeTypeTitle:
|
|
37
|
-
panelStatusTitle:
|
|
38
|
-
screenTypeTitle:
|
|
27
|
+
exportTitle: this.quill.getLangText("flowChart.controlPanel.exportTitle"),
|
|
28
|
+
zoomOutTitle: this.quill.getLangText("flowChart.controlPanel.zoomOutTitle"),
|
|
29
|
+
zoomInTitle: this.quill.getLangText("flowChart.controlPanel.zoomInTitle"),
|
|
30
|
+
fitTitle: this.quill.getLangText("flowChart.controlPanel.fitTitle"),
|
|
31
|
+
backTitle: this.quill.getLangText("flowChart.controlPanel.backTitle"),
|
|
32
|
+
forwardTitle: this.quill.getLangText("flowChart.controlPanel.forwardTitle"),
|
|
33
|
+
setEdgeTypeTitle: this.quill.getLangText("flowChart.controlPanel.setEdgeTypeTitle"),
|
|
34
|
+
panelStatusTitle: this.quill.getLangText("flowChart.controlPanel.panelStatusTitle"),
|
|
35
|
+
screenTypeTitle: this.quill.getLangText("flowChart.controlPanel.screenTypeTitle")
|
|
39
36
|
};
|
|
40
37
|
}
|
|
41
38
|
updateControlPanelTexts() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-panel.es.js","sources":["../../../../../src/modules/flow-chart/modules/control-panel.ts"],"sourcesContent":["import type FluentEditor from '../../../core/fluent-editor'\nimport type FlowChartPlaceholderBlot from '../formats/flow-chart-blot'\nimport { CHANGE_LANGUAGE_EVENT } from '../../../config'\nimport { I18N } from '../../../modules/i18n'\nimport { registerFlowChartI18N } from '../i18n'\nimport { backIcon, bezierIcon, contractIcon, fitIcon, forwardIcon, lineIcon, polyLineIcon, screenReduceIcon, screenTypeIcon, zoomInIcon, zoomOutIcon } from '../icons'\n\nclass FlowChartControlPanelHandler {\n private texts: Record<string, string>\n private lang: string\n getText(key: keyof Record<string, string>): string {\n return this.texts[key]\n }\n\n constructor(private quill: FluentEditor, private blot: FlowChartPlaceholderBlot) {\n const i18nModule = this.quill.getModule('i18n') as I18N\n registerFlowChartI18N(I18N)\n this.lang = i18nModule.options.lang\n this.texts = this.resolveTexts()\n this.quill.emitter.on(CHANGE_LANGUAGE_EVENT, (lang: string) => {\n this.lang = lang\n this.texts = this.resolveTexts()\n this.updateControlPanelTexts()\n })\n }\n\n resolveTexts() {\n return {\n exportTitle: I18N.parserText('flowChart.controlPanel.exportTitle', this.lang),\n zoomOutTitle: I18N.parserText('flowChart.controlPanel.zoomOutTitle', this.lang),\n zoomInTitle: I18N.parserText('flowChart.controlPanel.zoomInTitle', this.lang),\n fitTitle: I18N.parserText('flowChart.controlPanel.fitTitle', this.lang),\n backTitle: I18N.parserText('flowChart.controlPanel.backTitle', this.lang),\n forwardTitle: I18N.parserText('flowChart.controlPanel.forwardTitle', this.lang),\n setEdgeTypeTitle: I18N.parserText('flowChart.controlPanel.setEdgeTypeTitle', this.lang),\n panelStatusTitle: I18N.parserText('flowChart.controlPanel.panelStatusTitle', this.lang),\n screenTypeTitle: I18N.parserText('flowChart.controlPanel.screenTypeTitle', this.lang),\n }\n }\n\n updateControlPanelTexts() {\n const controlItems = this.blot.domNode.querySelectorAll('.ql-flow-chart-control-item')\n\n const controlItemMap: Record<string, string> = {\n 'zoom-out': 'zoomOutTitle',\n 'zoom-in': 'zoomInTitle',\n 'fit': 'fitTitle',\n 'back': 'backTitle',\n 'forward': 'forwardTitle',\n 'set-edge-type': 'setEdgeTypeTitle',\n 'panel-status': 'panelStatusTitle',\n 'screen-type': 'screenTypeTitle',\n }\n\n controlItems.forEach((item) => {\n const controlType = (item as HTMLElement).dataset.controlType\n if (controlType && controlItemMap[controlType] && this.texts[controlItemMap[controlType]]) {\n (item as HTMLElement).title = this.texts[controlItemMap[controlType]]\n }\n })\n }\n}\n\nconst controlPanelHandlers = new WeakMap<FlowChartPlaceholderBlot, FlowChartControlPanelHandler>()\n\nconst DISABLED_OPACITY = '0.5'\nconst ENABLED_OPACITY = '1'\nexport function createControlPanel(blot: FlowChartPlaceholderBlot, quill: FluentEditor): void {\n // 中间的控制面板\n const controlPanel = document.createElement('div')\n controlPanel.className = 'ql-flow-chart-control'\n // 右上的控制面板\n const controlRightUpPanel = document.createElement('div')\n controlRightUpPanel.className = 'ql-flow-chart-right-up-control'\n\n const handler = new FlowChartControlPanelHandler(quill, blot)\n controlPanelHandlers.set(blot, handler)\n const zoomOutBtn = createControlItem('zoom-out', handler.getText('zoomOutTitle'), () => handleZoomOut(blot))\n const zoomInBtn = createControlItem('zoom-in', handler.getText('zoomInTitle'), () => handleZoomIn(blot))\n const resetBtn = createControlItem('fit', handler.getText('fitTitle'), () => handleResetZoom(blot))\n const backBtn = createControlItem('back', handler.getText('backTitle'), () => handleUndo(blot))\n const forwardBtn = createControlItem('forward', handler.getText('forwardTitle'), () => handleRedo(blot))\n const setEdgeTypeBtn = createControlItem('set-edge-type', handler.getText('setEdgeTypeTitle'), () => handleSetEdgeType(blot))\n const panelStatusBtn = createControlItem('panel-status', handler.getText('panelStatusTitle'))\n const screenTypeBtn = createControlItem('screen-type', handler.getText('screenTypeTitle'), () => handleScreenTypeBtn(blot))\n\n const updateButtonState = (historyData: any) => {\n if (!historyData.data) {\n backBtn.style.opacity = DISABLED_OPACITY\n backBtn.style.cursor = 'not-allowed'\n forwardBtn.style.opacity = DISABLED_OPACITY\n forwardBtn.style.cursor = 'not-allowed'\n return\n }\n const isUndoAvailable = historyData.data.undoAble || historyData.data.undos.length < 0\n const isRedoAvailable = historyData.data.redoAble || historyData.data.redos.length > 0\n\n if (backBtn) {\n backBtn.style.opacity = isUndoAvailable ? ENABLED_OPACITY : DISABLED_OPACITY\n backBtn.style.cursor = isUndoAvailable ? 'pointer' : 'not-allowed'\n }\n\n if (forwardBtn) {\n forwardBtn.style.opacity = isRedoAvailable ? ENABLED_OPACITY : DISABLED_OPACITY\n forwardBtn.style.cursor = isRedoAvailable ? 'pointer' : 'not-allowed'\n }\n }\n updateButtonState(blot.flowChart.history)\n blot.flowChart.on('history:change', (data: any) => {\n updateButtonState(data)\n })\n\n setTimeout(() => {\n const controlLeftUpPanel = blot.domNode.querySelector('.lf-dndpanel') as HTMLElement | null\n controlLeftUpPanel.append(setEdgeTypeBtn)\n }, 0)\n controlRightUpPanel.append(panelStatusBtn)\n blot.domNode.appendChild(controlRightUpPanel)\n controlPanel.append(zoomOutBtn, zoomInBtn, resetBtn, screenTypeBtn, backBtn, forwardBtn)\n blot.domNode.appendChild(controlPanel)\n}\n\nfunction handleUndo(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.undo()\n }\n}\n\nfunction handleRedo(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.redo()\n }\n}\n\nfunction handleZoomIn(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.zoom(true)\n }\n}\n\nfunction handleZoomOut(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.zoom(false)\n }\n}\n\nfunction handleResetZoom(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.resetZoom()\n }\n}\n\nfunction createControlItem(iconClass: string, title: string, onClick?: () => void, disabled = false) {\n const controlItem = document.createElement('div')\n controlItem.className = 'ql-flow-chart-control-item'\n controlItem.title = title\n controlItem.dataset.controlType = iconClass\n controlItem.style.cursor = disabled ? 'not-allowed' : 'pointer'\n\n const iconMap: Record<string, string> = {\n 'back': backIcon,\n 'forward': forwardIcon,\n 'zoom-out': zoomOutIcon,\n 'zoom-in': zoomInIcon,\n 'fit': fitIcon,\n 'screen-type': screenTypeIcon,\n 'panel-status': contractIcon,\n 'set-edge-type': lineIcon,\n }\n\n const icon = document.createElement('i')\n icon.innerHTML = iconMap[iconClass] || ''\n controlItem.appendChild(icon)\n\n if (!disabled) {\n controlItem.addEventListener('click', onClick)\n }\n\n return controlItem\n}\n\nfunction handleSetEdgeType(blot: FlowChartPlaceholderBlot): void {\n const controlLeftUpPanel = blot.domNode.querySelector('.lf-dndpanel') as HTMLElement | null\n if (!controlLeftUpPanel) return\n let edgeTypePanel = controlLeftUpPanel.querySelector('.ql-flow-chart-edge-panel') as HTMLElement\n if (!edgeTypePanel) {\n edgeTypePanel = document.createElement('div')\n edgeTypePanel.className = 'ql-flow-chart-edge-panel'\n edgeTypePanel.style.display = 'flex'\n edgeTypePanel.style.justifyContent = 'space-around'\n edgeTypePanel.style.flexWrap = 'nowrap'\n edgeTypePanel.style.width = 'auto'\n edgeTypePanel.style.minWidth = '100%'\n edgeTypePanel.style.padding = '8px'\n edgeTypePanel.style.boxSizing = 'border-box'\n edgeTypePanel.style.position = 'absolute'\n edgeTypePanel.style.top = '170px'\n controlLeftUpPanel.appendChild(edgeTypePanel)\n\n const edgeTypes = [\n {\n name: 'line',\n displayName: '直线',\n icon: lineIcon,\n },\n {\n name: 'polyline',\n displayName: '折线',\n icon: polyLineIcon,\n },\n {\n name: 'bezier',\n displayName: '贝塞尔曲线',\n icon: bezierIcon,\n },\n ]\n\n edgeTypes.forEach((edgeType) => {\n const edgeItem = document.createElement('div')\n edgeItem.className = 'ql-flow-chart-edge-item'\n edgeItem.style.padding = '8px'\n edgeItem.style.cursor = 'pointer'\n edgeItem.style.textAlign = 'center'\n\n const edgeIcon = document.createElement('div')\n edgeIcon.className = `ql-flow-chart-edge-type-icon`\n edgeIcon.style.width = '24px'\n edgeIcon.style.height = '24px'\n edgeIcon.style.margin = '0 auto'\n if (edgeType.icon) {\n edgeIcon.innerHTML = edgeType.icon\n }\n\n edgeItem.appendChild(edgeIcon)\n\n edgeItem.addEventListener('click', () => {\n const { edges = [] } = blot.flowChart.getSelectElements()\n if (edges.length > 0) {\n edges.forEach((edge) => {\n blot.flowChart.changeEdgeType(edge.id, edgeType.name)\n })\n blot.data = blot.flowChart.getGraphData()\n blot.domNode.setAttribute('data-flow-chart', JSON.stringify(blot.data))\n }\n\n edgeTypePanel.style.display = 'none'\n })\n edgeTypePanel.appendChild(edgeItem)\n })\n }\n else {\n edgeTypePanel.style.display = 'flex'\n edgeTypePanel.style.justifyContent = 'space-around'\n edgeTypePanel.style.flexWrap = 'nowrap'\n }\n\n const handleOutsideClick = (e: MouseEvent) => {\n let setEdgeTypeBtn: HTMLElement | null = null\n const controlItems = controlLeftUpPanel.querySelectorAll('.ql-flow-chart-control-item')\n controlItems.forEach((item) => {\n const iconEl = item.querySelector('i')\n if (iconEl && iconEl.className.includes('set-edge-type')) {\n setEdgeTypeBtn = item as HTMLElement\n }\n })\n if (!edgeTypePanel.contains(e.target as Node)\n && (!setEdgeTypeBtn || !setEdgeTypeBtn.contains(e.target as Node))) {\n edgeTypePanel.style.display = 'none'\n document.removeEventListener('click', handleOutsideClick)\n }\n }\n\n document.removeEventListener('click', handleOutsideClick)\n setTimeout(() => {\n document.addEventListener('click', handleOutsideClick)\n }, 0)\n}\n\nfunction handleScreenTypeBtn(blot: FlowChartPlaceholderBlot): void {\n const screenTypeBtn = blot.domNode.querySelector('[data-control-type=\"screen-type\"]') as HTMLElement | null\n if (!screenTypeBtn || !blot.domNode) return\n\n const flowChartContainer = blot.domNode\n const isFullscreen = flowChartContainer.style.position === 'fixed'\n\n if (isFullscreen) {\n const originalPosition = flowChartContainer.getAttribute('data-original-position')\n const originalWidth = flowChartContainer.getAttribute('data-original-width')\n const originalHeight = flowChartContainer.getAttribute('data-original-height')\n if (originalWidth && originalHeight) {\n flowChartContainer.style.position = originalPosition\n flowChartContainer.style.width = originalWidth\n flowChartContainer.style.height = originalHeight\n flowChartContainer.style.zIndex = '0'\n }\n const iconElement = screenTypeBtn.querySelector('i')\n if (iconElement) {\n iconElement.innerHTML = screenTypeIcon\n }\n }\n else {\n flowChartContainer.setAttribute('data-original-position', flowChartContainer.style.position || '')\n flowChartContainer.setAttribute('data-original-width', flowChartContainer.style.width || '')\n flowChartContainer.setAttribute('data-original-height', flowChartContainer.style.height || '')\n flowChartContainer.style.position = 'fixed'\n flowChartContainer.style.top = '0'\n flowChartContainer.style.left = '0'\n flowChartContainer.style.width = '100vw'\n flowChartContainer.style.height = '100vh'\n flowChartContainer.style.zIndex = '100'\n const iconElement = screenTypeBtn.querySelector('i')\n if (iconElement) {\n iconElement.innerHTML = screenReduceIcon\n }\n }\n blot.flowChart.resize()\n blot.flowChart.translateCenter()\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"control-panel.es.js","sources":["../../../../../src/modules/flow-chart/modules/control-panel.ts"],"sourcesContent":["import type { I18n } from 'quill-i18n'\nimport type FluentEditor from '../../../core/fluent-editor'\nimport type FlowChartPlaceholderBlot from '../formats/flow-chart-blot'\nimport { registerFlowChartI18N } from '../i18n'\nimport { backIcon, bezierIcon, contractIcon, fitIcon, forwardIcon, lineIcon, polyLineIcon, screenReduceIcon, screenTypeIcon, zoomInIcon, zoomOutIcon } from '../icons'\n\nclass FlowChartControlPanelHandler {\n private texts: Record<string, string>\n private lang: string\n getText(key: keyof Record<string, string>): string {\n return this.texts[key]\n }\n\n constructor(private quill: FluentEditor, private blot: FlowChartPlaceholderBlot) {\n const i18nModule = this.quill.getModule('i18n') as I18n\n registerFlowChartI18N(i18nModule)\n this.lang = i18nModule.getLocale()\n this.texts = this.resolveTexts()\n this.quill.on('i18n-locale-change', (event: { locale: string, oldLocale: string }) => {\n this.lang = event.locale\n this.texts = this.resolveTexts()\n this.updateControlPanelTexts()\n })\n }\n\n resolveTexts() {\n return {\n exportTitle: this.quill.getLangText('flowChart.controlPanel.exportTitle'),\n zoomOutTitle: this.quill.getLangText('flowChart.controlPanel.zoomOutTitle'),\n zoomInTitle: this.quill.getLangText('flowChart.controlPanel.zoomInTitle'),\n fitTitle: this.quill.getLangText('flowChart.controlPanel.fitTitle'),\n backTitle: this.quill.getLangText('flowChart.controlPanel.backTitle'),\n forwardTitle: this.quill.getLangText('flowChart.controlPanel.forwardTitle'),\n setEdgeTypeTitle: this.quill.getLangText('flowChart.controlPanel.setEdgeTypeTitle'),\n panelStatusTitle: this.quill.getLangText('flowChart.controlPanel.panelStatusTitle'),\n screenTypeTitle: this.quill.getLangText('flowChart.controlPanel.screenTypeTitle'),\n }\n }\n\n updateControlPanelTexts() {\n const controlItems = this.blot.domNode.querySelectorAll('.ql-flow-chart-control-item')\n\n const controlItemMap: Record<string, string> = {\n 'zoom-out': 'zoomOutTitle',\n 'zoom-in': 'zoomInTitle',\n 'fit': 'fitTitle',\n 'back': 'backTitle',\n 'forward': 'forwardTitle',\n 'set-edge-type': 'setEdgeTypeTitle',\n 'panel-status': 'panelStatusTitle',\n 'screen-type': 'screenTypeTitle',\n }\n\n controlItems.forEach((item) => {\n const controlType = (item as HTMLElement).dataset.controlType\n if (controlType && controlItemMap[controlType] && this.texts[controlItemMap[controlType]]) {\n (item as HTMLElement).title = this.texts[controlItemMap[controlType]]\n }\n })\n }\n}\n\nconst controlPanelHandlers = new WeakMap<FlowChartPlaceholderBlot, FlowChartControlPanelHandler>()\n\nconst DISABLED_OPACITY = '0.5'\nconst ENABLED_OPACITY = '1'\nexport function createControlPanel(blot: FlowChartPlaceholderBlot, quill: FluentEditor): void {\n // 中间的控制面板\n const controlPanel = document.createElement('div')\n controlPanel.className = 'ql-flow-chart-control'\n // 右上的控制面板\n const controlRightUpPanel = document.createElement('div')\n controlRightUpPanel.className = 'ql-flow-chart-right-up-control'\n\n const handler = new FlowChartControlPanelHandler(quill, blot)\n controlPanelHandlers.set(blot, handler)\n const zoomOutBtn = createControlItem('zoom-out', handler.getText('zoomOutTitle'), () => handleZoomOut(blot))\n const zoomInBtn = createControlItem('zoom-in', handler.getText('zoomInTitle'), () => handleZoomIn(blot))\n const resetBtn = createControlItem('fit', handler.getText('fitTitle'), () => handleResetZoom(blot))\n const backBtn = createControlItem('back', handler.getText('backTitle'), () => handleUndo(blot))\n const forwardBtn = createControlItem('forward', handler.getText('forwardTitle'), () => handleRedo(blot))\n const setEdgeTypeBtn = createControlItem('set-edge-type', handler.getText('setEdgeTypeTitle'), () => handleSetEdgeType(blot))\n const panelStatusBtn = createControlItem('panel-status', handler.getText('panelStatusTitle'))\n const screenTypeBtn = createControlItem('screen-type', handler.getText('screenTypeTitle'), () => handleScreenTypeBtn(blot))\n\n const updateButtonState = (historyData: any) => {\n if (!historyData.data) {\n backBtn.style.opacity = DISABLED_OPACITY\n backBtn.style.cursor = 'not-allowed'\n forwardBtn.style.opacity = DISABLED_OPACITY\n forwardBtn.style.cursor = 'not-allowed'\n return\n }\n const isUndoAvailable = historyData.data.undoAble || historyData.data.undos.length < 0\n const isRedoAvailable = historyData.data.redoAble || historyData.data.redos.length > 0\n\n if (backBtn) {\n backBtn.style.opacity = isUndoAvailable ? ENABLED_OPACITY : DISABLED_OPACITY\n backBtn.style.cursor = isUndoAvailable ? 'pointer' : 'not-allowed'\n }\n\n if (forwardBtn) {\n forwardBtn.style.opacity = isRedoAvailable ? ENABLED_OPACITY : DISABLED_OPACITY\n forwardBtn.style.cursor = isRedoAvailable ? 'pointer' : 'not-allowed'\n }\n }\n updateButtonState(blot.flowChart.history)\n blot.flowChart.on('history:change', (data: any) => {\n updateButtonState(data)\n })\n\n setTimeout(() => {\n const controlLeftUpPanel = blot.domNode.querySelector('.lf-dndpanel') as HTMLElement | null\n controlLeftUpPanel.append(setEdgeTypeBtn)\n }, 0)\n controlRightUpPanel.append(panelStatusBtn)\n blot.domNode.appendChild(controlRightUpPanel)\n controlPanel.append(zoomOutBtn, zoomInBtn, resetBtn, screenTypeBtn, backBtn, forwardBtn)\n blot.domNode.appendChild(controlPanel)\n}\n\nfunction handleUndo(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.undo()\n }\n}\n\nfunction handleRedo(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.redo()\n }\n}\n\nfunction handleZoomIn(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.zoom(true)\n }\n}\n\nfunction handleZoomOut(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.zoom(false)\n }\n}\n\nfunction handleResetZoom(blot: FlowChartPlaceholderBlot): void {\n if (blot.flowChart) {\n blot.flowChart.resetZoom()\n }\n}\n\nfunction createControlItem(iconClass: string, title: string, onClick?: () => void, disabled = false) {\n const controlItem = document.createElement('div')\n controlItem.className = 'ql-flow-chart-control-item'\n controlItem.title = title\n controlItem.dataset.controlType = iconClass\n controlItem.style.cursor = disabled ? 'not-allowed' : 'pointer'\n\n const iconMap: Record<string, string> = {\n 'back': backIcon,\n 'forward': forwardIcon,\n 'zoom-out': zoomOutIcon,\n 'zoom-in': zoomInIcon,\n 'fit': fitIcon,\n 'screen-type': screenTypeIcon,\n 'panel-status': contractIcon,\n 'set-edge-type': lineIcon,\n }\n\n const icon = document.createElement('i')\n icon.innerHTML = iconMap[iconClass] || ''\n controlItem.appendChild(icon)\n\n if (!disabled) {\n controlItem.addEventListener('click', onClick)\n }\n\n return controlItem\n}\n\nfunction handleSetEdgeType(blot: FlowChartPlaceholderBlot): void {\n const controlLeftUpPanel = blot.domNode.querySelector('.lf-dndpanel') as HTMLElement | null\n if (!controlLeftUpPanel) return\n let edgeTypePanel = controlLeftUpPanel.querySelector('.ql-flow-chart-edge-panel') as HTMLElement\n if (!edgeTypePanel) {\n edgeTypePanel = document.createElement('div')\n edgeTypePanel.className = 'ql-flow-chart-edge-panel'\n edgeTypePanel.style.display = 'flex'\n edgeTypePanel.style.justifyContent = 'space-around'\n edgeTypePanel.style.flexWrap = 'nowrap'\n edgeTypePanel.style.width = 'auto'\n edgeTypePanel.style.minWidth = '100%'\n edgeTypePanel.style.padding = '8px'\n edgeTypePanel.style.boxSizing = 'border-box'\n edgeTypePanel.style.position = 'absolute'\n edgeTypePanel.style.top = '170px'\n controlLeftUpPanel.appendChild(edgeTypePanel)\n\n const edgeTypes = [\n {\n name: 'line',\n displayName: '直线',\n icon: lineIcon,\n },\n {\n name: 'polyline',\n displayName: '折线',\n icon: polyLineIcon,\n },\n {\n name: 'bezier',\n displayName: '贝塞尔曲线',\n icon: bezierIcon,\n },\n ]\n\n edgeTypes.forEach((edgeType) => {\n const edgeItem = document.createElement('div')\n edgeItem.className = 'ql-flow-chart-edge-item'\n edgeItem.style.padding = '8px'\n edgeItem.style.cursor = 'pointer'\n edgeItem.style.textAlign = 'center'\n\n const edgeIcon = document.createElement('div')\n edgeIcon.className = `ql-flow-chart-edge-type-icon`\n edgeIcon.style.width = '24px'\n edgeIcon.style.height = '24px'\n edgeIcon.style.margin = '0 auto'\n if (edgeType.icon) {\n edgeIcon.innerHTML = edgeType.icon\n }\n\n edgeItem.appendChild(edgeIcon)\n\n edgeItem.addEventListener('click', () => {\n const { edges = [] } = blot.flowChart.getSelectElements()\n if (edges.length > 0) {\n edges.forEach((edge) => {\n blot.flowChart.changeEdgeType(edge.id, edgeType.name)\n })\n blot.data = blot.flowChart.getGraphData()\n blot.domNode.setAttribute('data-flow-chart', JSON.stringify(blot.data))\n }\n\n edgeTypePanel.style.display = 'none'\n })\n edgeTypePanel.appendChild(edgeItem)\n })\n }\n else {\n edgeTypePanel.style.display = 'flex'\n edgeTypePanel.style.justifyContent = 'space-around'\n edgeTypePanel.style.flexWrap = 'nowrap'\n }\n\n const handleOutsideClick = (e: MouseEvent) => {\n let setEdgeTypeBtn: HTMLElement | null = null\n const controlItems = controlLeftUpPanel.querySelectorAll('.ql-flow-chart-control-item')\n controlItems.forEach((item) => {\n const iconEl = item.querySelector('i')\n if (iconEl && iconEl.className.includes('set-edge-type')) {\n setEdgeTypeBtn = item as HTMLElement\n }\n })\n if (!edgeTypePanel.contains(e.target as Node)\n && (!setEdgeTypeBtn || !setEdgeTypeBtn.contains(e.target as Node))) {\n edgeTypePanel.style.display = 'none'\n document.removeEventListener('click', handleOutsideClick)\n }\n }\n\n document.removeEventListener('click', handleOutsideClick)\n setTimeout(() => {\n document.addEventListener('click', handleOutsideClick)\n }, 0)\n}\n\nfunction handleScreenTypeBtn(blot: FlowChartPlaceholderBlot): void {\n const screenTypeBtn = blot.domNode.querySelector('[data-control-type=\"screen-type\"]') as HTMLElement | null\n if (!screenTypeBtn || !blot.domNode) return\n\n const flowChartContainer = blot.domNode\n const isFullscreen = flowChartContainer.style.position === 'fixed'\n\n if (isFullscreen) {\n const originalPosition = flowChartContainer.getAttribute('data-original-position')\n const originalWidth = flowChartContainer.getAttribute('data-original-width')\n const originalHeight = flowChartContainer.getAttribute('data-original-height')\n if (originalWidth && originalHeight) {\n flowChartContainer.style.position = originalPosition\n flowChartContainer.style.width = originalWidth\n flowChartContainer.style.height = originalHeight\n flowChartContainer.style.zIndex = '0'\n }\n const iconElement = screenTypeBtn.querySelector('i')\n if (iconElement) {\n iconElement.innerHTML = screenTypeIcon\n }\n }\n else {\n flowChartContainer.setAttribute('data-original-position', flowChartContainer.style.position || '')\n flowChartContainer.setAttribute('data-original-width', flowChartContainer.style.width || '')\n flowChartContainer.setAttribute('data-original-height', flowChartContainer.style.height || '')\n flowChartContainer.style.position = 'fixed'\n flowChartContainer.style.top = '0'\n flowChartContainer.style.left = '0'\n flowChartContainer.style.width = '100vw'\n flowChartContainer.style.height = '100vh'\n flowChartContainer.style.zIndex = '100'\n const iconElement = screenTypeBtn.querySelector('i')\n if (iconElement) {\n iconElement.innerHTML = screenReduceIcon\n }\n }\n blot.flowChart.resize()\n blot.flowChart.translateCenter()\n}\n"],"names":[],"mappings":"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"}
|
package/es/modules/index.es.js
CHANGED
|
@@ -7,7 +7,6 @@ import { DividerBlot } from "./divider.es.js";
|
|
|
7
7
|
import { EmojiModule } from "./emoji.es.js";
|
|
8
8
|
import "./file/index.es.js";
|
|
9
9
|
import { FlowChartModule } from "./flow-chart/index.es.js";
|
|
10
|
-
import { I18N } from "./i18n.es.js";
|
|
11
10
|
import "./link/index.es.js";
|
|
12
11
|
import "./mathlive/index.es.js";
|
|
13
12
|
import "./mention/index.es.js";
|
|
@@ -16,13 +15,14 @@ import { ShortCutKey, shortKey } from "./shortcut-key/index.es.js";
|
|
|
16
15
|
import "./syntax.es.js";
|
|
17
16
|
import { generateTableUp } from "./table-up/index.es.js";
|
|
18
17
|
import "./toolbar/index.es.js";
|
|
18
|
+
export * from "quill-i18n";
|
|
19
|
+
export * from "quill-shortcut-key";
|
|
19
20
|
export {
|
|
20
21
|
CustomClipboard,
|
|
21
22
|
DividerBlot,
|
|
22
23
|
EmojiModule,
|
|
23
24
|
FileUploader,
|
|
24
25
|
FlowChartModule,
|
|
25
|
-
I18N,
|
|
26
26
|
MindMapModule,
|
|
27
27
|
ShortCutKey,
|
|
28
28
|
generateTableUp,
|