@opentiny/vue-renderless 3.16.1 → 3.17.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.
Files changed (103) hide show
  1. package/action-sheet/index.js +0 -1
  2. package/base-select/index.js +1510 -0
  3. package/base-select/vue.js +555 -0
  4. package/breadcrumb-item/vue.js +4 -2
  5. package/card/index.js +15 -0
  6. package/card/vue.js +6 -3
  7. package/carousel/index.js +89 -17
  8. package/carousel/vue.js +29 -24
  9. package/carousel-item/index.js +24 -9
  10. package/carousel-item/vue.js +10 -9
  11. package/cascader/vue.js +2 -1
  12. package/cascader-panel/index.js +8 -1
  13. package/cascader-panel/vue.js +1 -1
  14. package/cascader-select/column-index.js +11 -6
  15. package/cascader-select/column.js +8 -5
  16. package/cascader-select/usePicker.js +3 -2
  17. package/checkbox/index.js +0 -17
  18. package/checkbox/vue.js +4 -10
  19. package/collapse-item/vue.js +4 -2
  20. package/common/deps/clickoutside.js +15 -8
  21. package/common/deps/popper.js +15 -1
  22. package/common/deps/throttle.js +7 -0
  23. package/common/deps/touch-emulator.js +1 -1
  24. package/common/deps/tree-model/node.js +1 -0
  25. package/common/deps/tree-model/tree-store.js +4 -1
  26. package/common/deps/useEventListener.js +9 -2
  27. package/common/deps/useInstanceSlots.js +22 -0
  28. package/common/deps/useRelation.js +72 -0
  29. package/common/deps/vue-popper.js +1 -0
  30. package/common/function.js +28 -0
  31. package/common/index.js +1 -1
  32. package/common/runtime.js +1 -1
  33. package/common/type.js +2 -0
  34. package/dialog-box/index.js +0 -22
  35. package/dialog-box/vue.js +1 -4
  36. package/drawer/index.js +28 -29
  37. package/drawer/vue.js +7 -11
  38. package/file-upload/index.js +1 -1
  39. package/fluent-editor/index.js +679 -0
  40. package/fluent-editor/options.js +234 -0
  41. package/fluent-editor/vue.js +192 -0
  42. package/form/index.js +5 -1
  43. package/grid/utils/column.js +4 -2
  44. package/grid/utils/common.js +18 -29
  45. package/grid/utils/event.js +14 -9
  46. package/guide/index.js +6 -5
  47. package/guide/vue.js +2 -2
  48. package/input/index.js +32 -2
  49. package/input/vue.js +21 -2
  50. package/nav-menu/index.js +1 -1
  51. package/numeric/index.js +4 -1
  52. package/option/vue.js +6 -6
  53. package/package.json +1 -1
  54. package/picker/mb.js +6 -1
  55. package/picker/vue.js +2 -1
  56. package/select/index.js +65 -40
  57. package/select/vue.js +1 -1
  58. package/split/index.js +16 -9
  59. package/split/vue.js +7 -2
  60. package/statistic/index.js +7 -0
  61. package/tabs-mf/index.js +116 -13
  62. package/tabs-mf/vue-bar.js +6 -0
  63. package/tabs-mf/vue-nav-item.js +1 -1
  64. package/tabs-mf/vue.js +42 -7
  65. package/tag-group/vue.js +7 -1
  66. package/time/index.js +1 -1
  67. package/time-line/index.js +2 -2
  68. package/time-line/vue.js +4 -13
  69. package/timeline-item/index.js +5 -5
  70. package/timeline-item/vue.js +13 -6
  71. package/tree/index.js +29 -2
  72. package/tree/vue.js +5 -2
  73. package/tree-node/vue.js +2 -1
  74. package/types/cascader-menu.type.d.ts +1 -1
  75. package/types/cascader-node.type.d.ts +1 -1
  76. package/types/{cascader-panel.type-2bd03be3.d.ts → cascader-panel.type-8f58e628.d.ts} +1 -1
  77. package/types/cascader-panel.type.d.ts +1 -1
  78. package/types/cascader.type.d.ts +1 -1
  79. package/types/collapse-item.type.d.ts +3 -0
  80. package/types/dialog-box.type.d.ts +2 -6
  81. package/types/drawer.type.d.ts +29 -34
  82. package/types/file-upload.type.d.ts +1 -1
  83. package/types/form-item.type.d.ts +1 -1
  84. package/types/{form.type-8e30b25c.d.ts → form.type-33aa784a.d.ts} +4 -0
  85. package/types/form.type.d.ts +1 -1
  86. package/types/input.type.d.ts +5 -1
  87. package/types/ip-address.type.d.ts +1 -6
  88. package/types/numeric.type.d.ts +1 -0
  89. package/types/popover.type.d.ts +1 -1
  90. package/types/search.type.d.ts +1 -3
  91. package/types/{time-line.type-1b501c41.d.ts → time-line.type-9fb16096.d.ts} +7 -5
  92. package/types/time-line.type.d.ts +1 -1
  93. package/types/timeline-item.type.d.ts +1 -1
  94. package/types/transfer.type.d.ts +3 -3
  95. package/types/upload-dragger.type.d.ts +1 -1
  96. package/types/{upload-list.type-02a1effb.d.ts → upload-list.type-023fd6e9.d.ts} +3 -3
  97. package/types/upload-list.type.d.ts +1 -1
  98. package/types/upload.type.d.ts +1 -1
  99. package/user/index.js +10 -4
  100. package/year-table/index.js +5 -3
  101. package/year-table/vue.js +1 -1
  102. package/common/deps/letter-only.js +0 -19
  103. package/common/deps/number-only.js +0 -20
@@ -0,0 +1,679 @@
1
+ import "../chunk-G2ADBYYC.js";
2
+ import { extend } from "../common/object";
3
+ import { isNull } from "../common/type";
4
+ import { xss } from "../common/xss";
5
+ import { set } from "../chart-core/deps/utils";
6
+ import { on, off } from "../common/deps/dom";
7
+ import PopupManager from "../common/deps/popup-manager";
8
+ const init = ({ api, emit, props, service, state, FluentEditor, UploaderDfls, defaultOptions, vm }) => () => {
9
+ UploaderDfls.enableMultiUpload = { file: true, image: true };
10
+ UploaderDfls.handler = api.uploaderDflsHandler;
11
+ UploaderDfls.imagePasteFailCallback = props.imagePasteFailCallback;
12
+ defaultOptions.modules.toolbar.handlers = api.handlers();
13
+ state.innerOptions = extend(true, {}, defaultOptions, props.globalOptions, props.options);
14
+ if (props.imageUpload) {
15
+ state.innerOptions.imageUpload = props.imageUpload;
16
+ } else {
17
+ state.innerOptions.uploadOption.imageUploadToServer = false;
18
+ }
19
+ if (props.fileUpload) {
20
+ state.innerOptions.fileUpload = extend(
21
+ true,
22
+ {},
23
+ { httpRequest: service && service.network.request },
24
+ props.fileUpload,
25
+ { url: xss.filterUrl(state.fileUploadUrl) }
26
+ );
27
+ }
28
+ api.setToolbarTips();
29
+ const quill = new FluentEditor(vm.$refs.editor, state.innerOptions);
30
+ quill.emitter.on("file-change", api.fileOperationToSev);
31
+ state.quill = Object.freeze(quill);
32
+ setTimeout(api.setToolbarTitle);
33
+ let insertTableButton = vm.$el.querySelector(".ql-better-table");
34
+ const tableModule = state.quill.getModule("better-table");
35
+ insertTableButton && (insertTableButton.onclick = (event, row = 3, col = 3) => {
36
+ tableModule.insertTable(row, col);
37
+ });
38
+ let fullscreenButton = vm.$el.querySelector(".ql-fullscreen");
39
+ fullscreenButton && (fullscreenButton.onclick = api.keyDownHandler);
40
+ state.quill.enable(false);
41
+ state.quill.on("selection-change", api.selectionChange);
42
+ state.quill.on("text-change", api.textChange);
43
+ if (state.content) {
44
+ if (props.dataType) {
45
+ state.quill.setContents(api.stringToJson(state.content));
46
+ } else {
47
+ let temp = xss.filterHtml(state.content);
48
+ state.quill.clipboard.dangerouslyPasteHTML(temp);
49
+ }
50
+ api.textChange();
51
+ }
52
+ if (!props.disabled) {
53
+ state.quill.enable(true);
54
+ }
55
+ api.handleComposition();
56
+ emit("ready", state.quill);
57
+ };
58
+ const checkTableISEndElement = (element) => {
59
+ if (element.children.length > 1) {
60
+ return checkTableISEndElement(element.children[element.children.length - 1]);
61
+ } else {
62
+ return element.children[0] instanceof HTMLTableElement;
63
+ }
64
+ };
65
+ const setIcons = ({ api, vm, iconOption, FluentEditor, keys = [] }) => {
66
+ for (const key in iconOption) {
67
+ if (Object.hasOwnProperty.call(iconOption, key)) {
68
+ const option = iconOption[key];
69
+ if (typeof option === "object") {
70
+ setIcons({ api, vm, iconOption: option, FluentEditor, keys: [...keys, key] });
71
+ } else {
72
+ const iconElm = vm.$refs[option] && vm.$refs[option][0];
73
+ const outerHtml = api.getOuterHTML(iconElm);
74
+ if (option && outerHtml) {
75
+ const k = keys.length ? [...keys, key].join(".") : key;
76
+ set(FluentEditor.imports["ui/icons"], k.replace(/default/, ""), outerHtml);
77
+ }
78
+ }
79
+ }
80
+ }
81
+ };
82
+ const setToolbarTips = ({ api, vm, FluentEditor, iconOption }) => () => {
83
+ setIcons({ api, vm, iconOption, FluentEditor });
84
+ };
85
+ const getOuterHTML = () => (el) => el && el.outerHTML;
86
+ const keyDownHandler = ({ state }) => (e) => {
87
+ if (e.keyCode) {
88
+ if (e.keyCode === 27 && state.isFullscreen) {
89
+ state.isFullscreen = !state.isFullscreen;
90
+ }
91
+ } else {
92
+ state.isFullscreen = !state.isFullscreen;
93
+ }
94
+ };
95
+ const addFullscreenchange = ({ api }) => () => {
96
+ on(document, "keydown", api.keyDownHandler);
97
+ };
98
+ const removeFullscreenchange = ({ api }) => () => {
99
+ off(document, "keydown", api.keyDownHandler);
100
+ api.keyDownHandler = null;
101
+ };
102
+ const handleComposition = ({ state, api }) => () => {
103
+ on(state.quill.root, "compositionstart", api.handleCompositionstart);
104
+ on(state.quill.root, "compositionend", api.handleCompositionend);
105
+ };
106
+ const removeHandleComposition = ({ state, api }) => () => {
107
+ off(state.quill.root, "compositionstart", api.handleCompositionstart);
108
+ off(state.quill.root, "compositionend", api.handleCompositionend);
109
+ };
110
+ const handleCompositionstart = ({ state }) => () => {
111
+ state.quill.root.classList.remove("ql-blank");
112
+ };
113
+ const handleCompositionend = ({ state }) => (event) => {
114
+ if (state.quill.editor.isBlank()) {
115
+ if (state.quill.getLength() > 0 && event.data.length > 0) {
116
+ let data = event.data;
117
+ state.quill.setContents([{ insert: data }]);
118
+ state.quill.setSelection(data.length);
119
+ state.quill.root.classList.remove("ql-blank");
120
+ } else {
121
+ state.quill.root.classList.add("ql-blank");
122
+ }
123
+ } else {
124
+ let data = state.quill.container.innerHTML, range = state.quill.getSelection(true);
125
+ const [mentionItem, offset] = state.quill.getLeaf(range.index);
126
+ if (mentionItem.statics.blotName === "break" || mentionItem.statics.blotName === "text" && offset === 0) {
127
+ state.quill.clipboard.dangerouslyPasteHTML(data);
128
+ }
129
+ if (mentionItem.statics.blotName === "break") {
130
+ state.quill.setSelection(range.index + event.data.length);
131
+ } else {
132
+ let pattern = /[\u4E00-\u9FA5\uf900-\ufa2d]/, flag;
133
+ if (pattern.test(event.data)) {
134
+ flag = true;
135
+ }
136
+ if (flag) {
137
+ state.quill.setSelection(range.index);
138
+ } else {
139
+ if (offset !== 0) {
140
+ state.quill.setSelection(range.index);
141
+ } else {
142
+ if (event.data.length > 1) {
143
+ state.quill.setSelection(range.index + 1);
144
+ } else {
145
+ state.quill.setSelection(range.index);
146
+ }
147
+ }
148
+ }
149
+ }
150
+ state.quill.root.classList.remove("ql-blank");
151
+ }
152
+ };
153
+ const undoHandler = ({ state }) => () => {
154
+ const betterTableModule = state.quill.getModule("better-table");
155
+ if (betterTableModule && betterTableModule.table) {
156
+ betterTableModule.hideTableTools();
157
+ }
158
+ state.quill.history.undo();
159
+ };
160
+ const redoHandler = ({ state }) => () => {
161
+ const betterTableModule = state.quill.getModule("better-table");
162
+ if (betterTableModule && betterTableModule.table) {
163
+ betterTableModule.hideTableTools();
164
+ }
165
+ state.quill.history.redo();
166
+ };
167
+ const lineheightHandler = ({ state, FluentEditor }) => (value) => {
168
+ state.quill.format("lineheight", value, FluentEditor.sources.USER);
169
+ };
170
+ const fileHandler = ({ api, state }) => () => {
171
+ const option = state.quill.options.uploadOption;
172
+ const accept = option && option.fileAccept;
173
+ api.inputFileHandler("file", accept);
174
+ };
175
+ const imageHandler = ({ api, state }) => () => {
176
+ const option = state.quill.options.uploadOption;
177
+ const accept = option && option.imageAccept;
178
+ api.inputFileHandler("image", accept);
179
+ };
180
+ const inputFileHandler = ({ state, UploaderDfls }) => (type, accept) => {
181
+ const defaultMIMETypes = state.quill.uploader.options[type].join(", ");
182
+ const mimeTypes = accept || defaultMIMETypes;
183
+ const betterToolbar = state.quill.getModule("toolbar");
184
+ let fileInput = betterToolbar.container.querySelector(`input.ql-${type}[type=file]`);
185
+ if (isNull(fileInput)) {
186
+ fileInput = document.createElement("input");
187
+ fileInput.classList.add(`ql-${type}`);
188
+ fileInput.setAttribute("type", "file");
189
+ fileInput.setAttribute("accept", mimeTypes);
190
+ if (UploaderDfls.enableMultiUpload["file"] && type === "file" || UploaderDfls.enableMultiUpload["image"] && type === "image") {
191
+ fileInput.setAttribute("multiple", "");
192
+ }
193
+ fileInput.onchange = () => {
194
+ const range = state.quill.getSelection(true);
195
+ state.quill.uploader.upload(range, fileInput.files, type === "file");
196
+ fileInput.value = "";
197
+ };
198
+ betterToolbar.container.appendChild(fileInput);
199
+ }
200
+ fileInput.click();
201
+ };
202
+ const uploaderDflsHandler = ({ api, modules }) => (range, files, fileFlags, rejectFlags) => {
203
+ const fileArr = [];
204
+ const imgArr = [];
205
+ files.forEach((file, index) => fileFlags[index] ? fileArr.push(file) : imgArr.push(file));
206
+ if (modules.file && (fileArr.length || rejectFlags.file)) {
207
+ api.handleUploadFile(range, fileArr, rejectFlags.file);
208
+ }
209
+ if (imgArr.length || rejectFlags.image) {
210
+ api.handleUploadImage(range, { file: imgArr[0], files: imgArr }, rejectFlags.image);
211
+ }
212
+ };
213
+ const handleUploadFile = ({ api, UploaderDfls }) => (range, files, hasRejectedFile) => {
214
+ const fileEnableMultiUpload = UploaderDfls.enableMultiUpload === true || UploaderDfls.enableMultiUpload["file"];
215
+ api.fileOperationToSev({
216
+ operation: "upload",
217
+ data: fileEnableMultiUpload ? { files } : { file: files[0] },
218
+ hasRejectedFile,
219
+ callback: (res) => {
220
+ if (!res) {
221
+ return;
222
+ }
223
+ if (fileEnableMultiUpload && Array.isArray(res)) {
224
+ res.forEach((value, index) => api.insertFileToEditor(range, files[index], value));
225
+ } else {
226
+ api.insertFileToEditor(range, files[0], res);
227
+ }
228
+ }
229
+ });
230
+ };
231
+ const getOption = (url, headers, method, fd, callbackOK, callbackKO, callback) => {
232
+ url = xss.filterUrl(url);
233
+ return {
234
+ url,
235
+ headers,
236
+ method,
237
+ data: fd,
238
+ onSuccess(res) {
239
+ res = res.data;
240
+ let resData = {};
241
+ for (let key in res) {
242
+ resData = res[key];
243
+ break;
244
+ }
245
+ callbackOK(res, ({ name, url: url2 }) => {
246
+ callback({
247
+ data: {
248
+ id: resData.attachmentId,
249
+ size: resData.fileSize,
250
+ title: name,
251
+ src: url2
252
+ }
253
+ });
254
+ });
255
+ },
256
+ onError(error) {
257
+ callbackKO(error);
258
+ }
259
+ };
260
+ };
261
+ const getOnloadOfFileOperToSev = ({ xmlhr, callbackOK, callback, callbackKO }) => () => {
262
+ if (xmlhr.status === 200) {
263
+ let res = JSON.parse(xmlhr.responseText);
264
+ let resData = {};
265
+ for (let key in res) {
266
+ resData = res[key];
267
+ break;
268
+ }
269
+ callbackOK(res, ({ name, url }) => {
270
+ callback({ data: { id: resData.attachmentId, size: resData.fileSize, title: name, src: url } });
271
+ });
272
+ } else {
273
+ callbackKO({ code: xmlhr.status, type: xmlhr.statusText, body: xmlhr.responseText });
274
+ }
275
+ };
276
+ const fileOperationToSev = ({ state }) => (event) => {
277
+ const { operation, hasRejectedFile, callback } = event;
278
+ const { files, fileDownloadUrl } = event.data;
279
+ switch (operation) {
280
+ case "upload": {
281
+ if (hasRejectedFile || !files || !files.length) {
282
+ return;
283
+ }
284
+ const options = state.innerOptions.fileUpload;
285
+ let { url, method = "POST", name = "file", headers = {} } = options;
286
+ let { success: callbackOK, fail: callbackKO } = options;
287
+ url = xss.filterUrl(url);
288
+ if (!url) {
289
+ return;
290
+ }
291
+ let fd = new FormData();
292
+ fd.append(name, files[0], files[0].name);
293
+ options.csrf && fd.append(options.csrf.token, options.csrf.hash);
294
+ if (options.httpRequest) {
295
+ let reqOptions = getOption(url, headers, method, fd, callbackOK, callbackKO, callback);
296
+ let req = options.httpRequest(reqOptions);
297
+ req && req.then && req.then(reqOptions.onSuccess, reqOptions.onError);
298
+ } else {
299
+ let xmlhr = new XMLHttpRequest();
300
+ xmlhr.withCredentials = options.withCredentials !== false;
301
+ xmlhr.open(method, url, true);
302
+ for (let index in headers) {
303
+ xmlhr.setRequestHeader(index, headers[index]);
304
+ }
305
+ xmlhr.onload = getOnloadOfFileOperToSev({ xmlhr, callbackOK, callback, callbackKO });
306
+ xmlhr.send(fd);
307
+ }
308
+ break;
309
+ }
310
+ case "download":
311
+ window.open(xss.filterUrl(fileDownloadUrl)).opener = null;
312
+ break;
313
+ default: {
314
+ break;
315
+ }
316
+ }
317
+ };
318
+ const handleUploadImage = ({ state, api, FluentEditor, Delta, UploaderDfls }) => (range, { file, files }, hasRejectedImage) => {
319
+ if (state.quill.options.uploadOption.imageUploadToServer) {
320
+ const index = state.promisesData.length;
321
+ const imageEnableMultiUpload = UploaderDfls.enableMultiUpload["image"];
322
+ const result = {
323
+ file,
324
+ data: { files: [file] },
325
+ hasRejectedImage,
326
+ callback: (res) => {
327
+ if (!res) {
328
+ return;
329
+ }
330
+ state.cbNum += 1;
331
+ state.promisesData[index].range = range;
332
+ state.promisesData[index].imgUrlData = res;
333
+ if (state.cbNum === state.promises.length) {
334
+ Promise.all(state.promises).then((arr) => {
335
+ arr.forEach((data, index2) => {
336
+ const { imageEnableMultiUpload: imageEnableMultiUpload2, imgUrlData, range: range2 } = state.promisesData[index2];
337
+ if (imgUrlData) {
338
+ if (imageEnableMultiUpload2 && Array.isArray(imgUrlData)) {
339
+ imgUrlData.forEach(function(value) {
340
+ return api.insertImageToEditor(range2, value);
341
+ });
342
+ } else {
343
+ api.insertImageToEditor(range2, imgUrlData);
344
+ }
345
+ }
346
+ });
347
+ state.promises = [];
348
+ state.promisesData = [];
349
+ state.cbNum = 0;
350
+ });
351
+ }
352
+ }
353
+ };
354
+ if (imageEnableMultiUpload) {
355
+ result["data"] = { files };
356
+ }
357
+ state.promisesData.push({
358
+ imageEnableMultiUpload
359
+ });
360
+ state.promises.push(api.uploadImageToSev(result));
361
+ } else {
362
+ const promises = files.map((fileItem) => {
363
+ return new Promise((resolve) => {
364
+ const reader = new FileReader();
365
+ reader.onload = (e) => {
366
+ resolve(e.target.result);
367
+ };
368
+ reader.readAsDataURL(fileItem);
369
+ });
370
+ });
371
+ Promise.all(promises).then((images) => {
372
+ const update = images.reduce((delta, image) => {
373
+ return delta.insert({ image });
374
+ }, new Delta().retain(range.index).delete(range.length));
375
+ state.quill.updateContents(update, FluentEditor.sources.USER);
376
+ state.quill.setSelection(range.index + images.length, FluentEditor.sources.SILENT);
377
+ });
378
+ }
379
+ };
380
+ const insertFileToEditor = ({ state, FluentEditor, Delta }) => (range, file, { data }) => {
381
+ const oldContent = new Delta().retain(range.index).delete(range.length);
382
+ const videoFlag = state.quill.options.uploadOption && state.quill.options.uploadOption.isVideoPlay && /^video\/[-\w.]+$/.test(file.type);
383
+ const insertObj = videoFlag ? { video: data } : { file: data };
384
+ const currentContent = new Delta([{ insert: insertObj }]);
385
+ const newContent = oldContent.concat(currentContent);
386
+ state.quill.updateContents(newContent, FluentEditor.sources.USER);
387
+ };
388
+ const insertImageToEditor = ({ state, FluentEditor, Delta }) => (range, { data }) => {
389
+ const { imageId, imageUrl } = data;
390
+ const oldContent = new Delta().retain(range.index).delete(range.length);
391
+ const currentContent = new Delta([
392
+ {
393
+ insert: { image: xss.filterUrl(imageUrl) },
394
+ attributes: { "image-id": imageId }
395
+ }
396
+ ]);
397
+ const newContent = oldContent.concat(currentContent);
398
+ state.quill.updateContents(newContent, FluentEditor.sources.USER);
399
+ };
400
+ const uploadImageToSev = ({ state }) => (event) => {
401
+ const { file, hasRejectedImage, callback } = event;
402
+ const { files } = event.data;
403
+ if (hasRejectedImage) {
404
+ return;
405
+ }
406
+ if (!files || !files.length) {
407
+ return;
408
+ }
409
+ const options = state.innerOptions.imageUpload;
410
+ let { url, method = "POST", name = "image", headers = {} } = options;
411
+ let { success: callbackOK, fail: callbackKO } = options;
412
+ url = xss.filterUrl(url);
413
+ if (!url) {
414
+ return;
415
+ }
416
+ let { fd = new FormData(), xhr = new XMLHttpRequest() } = {};
417
+ fd.append(name, file, file.name);
418
+ options.csrf && fd.append(options.csrf.token, options.csrf.hash);
419
+ xhr.withCredentials = options.withCredentials !== false;
420
+ xhr.open(method, url, true);
421
+ for (let index in headers) {
422
+ xhr.setRequestHeader(index, headers[index]);
423
+ }
424
+ xhr.onload = () => {
425
+ if (xhr.status === 200) {
426
+ let { res = JSON.parse(xhr.responseText), resData = {} } = {};
427
+ for (let key in res) {
428
+ resData = res[key];
429
+ break;
430
+ }
431
+ callbackOK(res, (imageUrl) => {
432
+ callback({ data: { imageId: resData.attachmentId, imageUrl } });
433
+ });
434
+ } else {
435
+ callbackKO({ code: xhr.status, type: xhr.statusText, body: xhr.responseText });
436
+ }
437
+ };
438
+ xhr.send(fd);
439
+ };
440
+ const handlers = ({ api }) => () => {
441
+ return {
442
+ undo: api.undoHandler,
443
+ redo: api.redoHandler,
444
+ lineheight: api.lineheightHandler,
445
+ file: api.fileHandler,
446
+ image: api.imageHandler,
447
+ inputFile: api.inputFileHandler
448
+ };
449
+ };
450
+ const getFileUploadUrl = ({ service }) => () => {
451
+ return service ? service.common.getFileUploadUrl() : Promise.resolve("");
452
+ };
453
+ const selectionChange = ({ state, emit }) => (range) => {
454
+ if (!range) {
455
+ emit("blur", state.quill);
456
+ } else {
457
+ emit("focus", state.quill);
458
+ }
459
+ };
460
+ const stringToJson = () => (str) => {
461
+ let contents = "";
462
+ try {
463
+ contents = JSON.parse(str);
464
+ } catch (e) {
465
+ contents = {};
466
+ }
467
+ return contents;
468
+ };
469
+ const initContent = ({ state, props, api, nextTick }) => () => {
470
+ if (state.quill) {
471
+ const flag = state.quill.selection.hasFocus();
472
+ if (state.content && state.content !== state.innerContent) {
473
+ state.innerContent = state.content;
474
+ if (props.dataType) {
475
+ state.quill.setContents(api.stringToJson(state.content));
476
+ } else {
477
+ state.quill.clipboard.dangerouslyPasteHTML(xss.filterHtml(state.content));
478
+ }
479
+ } else if (!state.content) {
480
+ state.quill.setText("");
481
+ }
482
+ nextTick(() => {
483
+ if (!props.disabled) {
484
+ state.quill.enable(true);
485
+ }
486
+ flag ? state.quill.selection.focus() : state.quill.blur();
487
+ });
488
+ }
489
+ };
490
+ const textChange = ({ emit, vm, state, props }) => () => {
491
+ let contents = "";
492
+ const quill = state.quill;
493
+ const text = state.quill.getText();
494
+ if (props.dataType || props.dataUpgrade) {
495
+ contents = JSON.stringify(state.quill.getContents());
496
+ if (contents === '{"ops":[{"insert":"\\n"}]}') {
497
+ contents = "";
498
+ }
499
+ } else {
500
+ contents = xss.filterHtml(vm.$refs.editor.children[0].innerHTML);
501
+ if (contents === "<p><br></p>" || contents === "<p><img></p>") {
502
+ contents = "";
503
+ }
504
+ }
505
+ state.innerContent = contents;
506
+ emit("update:modelValue", contents);
507
+ emit("change", { contents, text, quill });
508
+ };
509
+ const mounted = ({ api, props, state }) => () => {
510
+ if (props.fileUpload && !props.fileUpload.url) {
511
+ api.getFileUploadUrl().then((url) => {
512
+ url = xss.filterUrl(url);
513
+ state.fileUploadUrl = url;
514
+ api.init();
515
+ });
516
+ } else {
517
+ api.init();
518
+ }
519
+ api.addFullscreenchange();
520
+ };
521
+ const beforeUnmount = ({ state, api, vm }) => () => {
522
+ const toolbar = state.quill.getModule("toolbar");
523
+ state.quill.uploader.options && (state.quill.uploader.options.handler = null);
524
+ state.quill.uploader.options && (state.quill.uploader.options.imagePasteFailCallback = null);
525
+ toolbar.options && (toolbar.options.handlers = null);
526
+ toolbar.handlers = null;
527
+ state.quill.emitter.off("file-change", api.fileOperationToSev);
528
+ if (state.quill.options.imageUpload) {
529
+ state.quill.options.imageUpload.fail = null;
530
+ state.quill.options.imageUpload.success = null;
531
+ }
532
+ if (state.quill.options.fileUpload) {
533
+ state.quill.options.fileUpload.fail = null;
534
+ state.quill.options.fileUpload.success = null;
535
+ }
536
+ const fileInput = toolbar.container.querySelector(`input.ql-file[type=file]`);
537
+ const imageInput = toolbar.container.querySelector(`input.ql-image[type=file]`);
538
+ let insertTableButton = vm.$el.querySelector(".ql-better-table");
539
+ let fullscreenButton = vm.$el.querySelector(".ql-fullscreen");
540
+ fileInput && (fileInput.onchange = null);
541
+ imageInput && (imageInput.onchange = null);
542
+ insertTableButton && (insertTableButton.onclick = null);
543
+ fullscreenButton && (fullscreenButton.onclick = null);
544
+ api.removeFullscreenchange();
545
+ api.removeHandleComposition();
546
+ state.quill.off("selection-change", api.selectionChange);
547
+ state.quill.off("text-change", api.textChange);
548
+ state.quill = null;
549
+ delete state.quill;
550
+ };
551
+ const computePreviewOptions = ({ props, state, constants, api }) => () => {
552
+ if (props.picPreview && state.previewImgUrl) {
553
+ let previewOptions = typeof props.picPreview === "boolean" ? constants.PIC_PREVIEW_OPTIONS : props.picPreview;
554
+ previewOptions = extend(true, {}, previewOptions, {
555
+ urlList: [state.previewImgUrl]
556
+ });
557
+ let onClose = previewOptions.onClose;
558
+ if (typeof onClose !== "function") {
559
+ previewOptions.onClose = () => {
560
+ api.doPreview();
561
+ };
562
+ } else {
563
+ previewOptions.onClose = (...args) => {
564
+ onClose(...args);
565
+ api.doPreview();
566
+ };
567
+ }
568
+ return previewOptions;
569
+ }
570
+ return {};
571
+ };
572
+ const doPreview = ({ props, state, nextTick }) => (elem) => {
573
+ state.showPreview = false;
574
+ state.previewImgUrl = elem && elem.nodeType ? elem.dataset.image || elem.src : "";
575
+ state.previewImgUrl = /^data:image\/.{2,8};base64,\//.test(state.previewImgUrl) ? state.previewImgUrl : xss.filterUrl(state.previewImgUrl);
576
+ if (props.picPreview && state.previewImgUrl) {
577
+ nextTick(() => {
578
+ state.showPreview = true;
579
+ });
580
+ }
581
+ };
582
+ const handleDblclick = ({ props, api }) => (e) => {
583
+ if (props.picPreview && e && e.type === "dblclick" && [...e.target.classList].indexOf("blot-formatter__overlay") > -1 && e.target.dataset.image) {
584
+ api.doPreview(e.target);
585
+ }
586
+ };
587
+ const getToolbarTitle = (t) => {
588
+ return [
589
+ { selector: ".ql-undo", title: t("ui.fluentEditor.undo") },
590
+ { selector: ".ql-redo", title: t("ui.fluentEditor.redo") },
591
+ { selector: ".ql-clean", title: t("ui.richText.clean") },
592
+ { selector: ".ql-font", title: t("ui.richText.font") },
593
+ { selector: ".ql-size", title: t("ui.richText.size") },
594
+ { selector: ".ql-lineheight", title: t("ui.fluentEditor.lineheight") },
595
+ { selector: ".ql-header.ql-picker", title: t("ui.richText.pickerLabel") },
596
+ { selector: '.ql-header .ql-picker-item[data-value="1"]', title: t("ui.richText.headerPicker1") },
597
+ { selector: '.ql-header .ql-picker-item[data-value="2"]', title: t("ui.richText.headerPicker2") },
598
+ { selector: '.ql-header .ql-picker-item[data-value="3"]', title: t("ui.richText.headerPicker3") },
599
+ { selector: '.ql-header .ql-picker-item[data-value="4"]', title: t("ui.richText.headerPicker4") },
600
+ { selector: '.ql-header .ql-picker-item[data-value="5"]', title: t("ui.richText.headerPicker5") },
601
+ { selector: '.ql-header .ql-picker-item[data-value="6"]', title: t("ui.richText.headerPicker6") },
602
+ { selector: ".ql-header .ql-picker-item:not([data-value])", title: t("ui.richText.normal") },
603
+ { selector: ".ql-bold", title: t("ui.richText.bold") },
604
+ { selector: ".ql-italic", title: t("ui.richText.italic") },
605
+ { selector: ".ql-underline", title: t("ui.richText.underline") },
606
+ { selector: ".ql-strike", title: t("ui.richText.strike") },
607
+ { selector: ".ql-blockquote", title: t("ui.richText.blockquote") },
608
+ { selector: ".ql-code-block", title: t("ui.richText.codeBlock") },
609
+ { selector: '.ql-header[value="1"]', title: t("ui.richText.header1") },
610
+ { selector: '.ql-header[value="2"]', title: t("ui.richText.header2") },
611
+ { selector: '.ql-list[value="ordered"]', title: t("ui.richText.listOrdered") },
612
+ { selector: '.ql-list[value="bullet"]', title: t("ui.richText.listBullet") },
613
+ { selector: '.ql-script[value="sub"]', title: t("ui.richText.subScript") },
614
+ { selector: '.ql-script[value="super"]', title: t("ui.richText.superScript") },
615
+ { selector: '.ql-indent[value="-1"]', title: t("ui.richText.indent1") },
616
+ { selector: '.ql-indent[value="+1"]', title: t("ui.richText.indent2") },
617
+ { selector: '.ql-direction[value="rtl"]', title: t("ui.richText.directionRTL") },
618
+ { selector: ".ql-color", title: t("ui.richText.color") },
619
+ { selector: ".ql-background", title: t("ui.richText.background") },
620
+ { selector: ".ql-align", title: t("ui.richText.align") },
621
+ { selector: ".ql-align .ql-picker-item", title: t("ui.richText.alignPicker1") },
622
+ { selector: '.ql-align .ql-picker-item[data-value="center"]', title: t("ui.richText.alignPicker2") },
623
+ { selector: '.ql-align .ql-picker-item[data-value="right"]', title: t("ui.richText.alignPicker3") },
624
+ { selector: ".ql-link", title: t("ui.richText.link") },
625
+ { selector: ".ql-image", title: t("ui.richText.image") },
626
+ { selector: ".ql-video", title: t("ui.richText.video") },
627
+ { selector: ".ql-file", title: t("ui.richText.file") },
628
+ { selector: ".ql-better-table", title: t("ui.richText.betterTable") },
629
+ { selector: ".ql-fullscreen", title: t("ui.richText.fullscreen") }
630
+ ];
631
+ };
632
+ const setToolbarTitle = ({ state, t }) => () => {
633
+ const tips = getToolbarTitle(t);
634
+ const container = state.quill.container.parentNode;
635
+ for (let i = 0, l = tips.length; i < l; i++) {
636
+ const targetDom = container.querySelector(`.ql-formats ${tips[i].selector}`);
637
+ targetDom && targetDom.setAttribute("title", tips[i].title);
638
+ }
639
+ };
640
+ const computeZIndex = ({ constants, props }) => () => props.zIndex === constants.EDITOR_FULLSCREEN_OPTIONS || props.zIndex < 1 ? PopupManager.nextZIndex() : props.zIndex;
641
+ export {
642
+ addFullscreenchange,
643
+ beforeUnmount,
644
+ checkTableISEndElement,
645
+ computePreviewOptions,
646
+ computeZIndex,
647
+ doPreview,
648
+ fileHandler,
649
+ fileOperationToSev,
650
+ getFileUploadUrl,
651
+ getOuterHTML,
652
+ handleComposition,
653
+ handleCompositionend,
654
+ handleCompositionstart,
655
+ handleDblclick,
656
+ handleUploadFile,
657
+ handleUploadImage,
658
+ handlers,
659
+ imageHandler,
660
+ init,
661
+ initContent,
662
+ inputFileHandler,
663
+ insertFileToEditor,
664
+ insertImageToEditor,
665
+ keyDownHandler,
666
+ lineheightHandler,
667
+ mounted,
668
+ redoHandler,
669
+ removeFullscreenchange,
670
+ removeHandleComposition,
671
+ selectionChange,
672
+ setToolbarTips,
673
+ setToolbarTitle,
674
+ stringToJson,
675
+ textChange,
676
+ undoHandler,
677
+ uploadImageToSev,
678
+ uploaderDflsHandler
679
+ };