lakelib 0.1.8 → 0.1.10

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/lib/lake.js CHANGED
@@ -37,8 +37,12 @@ var checkCircle = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height
37
37
 
38
38
  var warningCircle = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z\"></path></svg>";
39
39
 
40
+ var file$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z\"></path></svg>";
41
+
40
42
  var open = "<svg width=\"24\" height=\"24\" fill=\"none\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.25 4.5A1.75 1.75 0 0 0 4.5 6.25v11.5c0 .966.783 1.75 1.75 1.75h11.5a1.75 1.75 0 0 0 1.75-1.75v-4a.75.75 0 0 1 1.5 0v4A3.25 3.25 0 0 1 17.75 21H6.25A3.25 3.25 0 0 1 3 17.75V6.25A3.25 3.25 0 0 1 6.25 3h4a.75.75 0 0 1 0 1.5h-4ZM13 3.75a.75.75 0 0 1 .75-.75h6.5a.75.75 0 0 1 .75.75v6.5a.75.75 0 0 1-1.5 0V5.56l-5.22 5.22a.75.75 0 0 1-1.06-1.06l5.22-5.22h-4.69a.75.75 0 0 1-.75-.75Z\" fill=\"#000000\"/></svg>";
41
43
 
44
+ var download = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0Zm-101.66,5.66a8,8,0,0,0,11.32,0l40-40a8,8,0,0,0-11.32-11.32L136,124.69V32a8,8,0,0,0-16,0v92.69L93.66,98.34a8,8,0,0,0-11.32,11.32Z\"></path></svg>";
45
+
42
46
  var copy$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\"></path></svg>";
43
47
 
44
48
  var remove = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z\"></path></svg>";
@@ -133,6 +137,8 @@ var hr$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\"
133
137
 
134
138
  var image$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,16V158.75l-26.07-26.06a16,16,0,0,0-22.63,0l-20,20-44-44a16,16,0,0,0-22.62,0L40,149.37V56ZM40,172l52-52,80,80H40Zm176,28H194.63l-36-36,20-20L216,181.38V200ZM144,100a12,12,0,1,1,12,12A12,12,0,0,1,144,100Z\"></path></svg>";
135
139
 
140
+ var attachment = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M209.66,122.34a8,8,0,0,1,0,11.32l-82.05,82a56,56,0,0,1-79.2-79.21L147.67,35.73a40,40,0,1,1,56.61,56.55L105,193A24,24,0,1,1,71,159L154.3,74.38A8,8,0,1,1,165.7,85.6L82.39,170.31a8,8,0,1,0,11.27,11.36L192.93,81A24,24,0,1,0,159,47L59.76,147.68a40,40,0,1,0,56.53,56.62l82.06-82A8,8,0,0,1,209.66,122.34Z\"></path></svg>";
141
+
136
142
  var codeBlock$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M58.34,101.66l-32-32a8,8,0,0,1,0-11.32l32-32A8,8,0,0,1,69.66,37.66L43.31,64,69.66,90.34a8,8,0,0,1-11.32,11.32Zm40,0a8,8,0,0,0,11.32,0l32-32a8,8,0,0,0,0-11.32l-32-32A8,8,0,0,0,98.34,37.66L124.69,64,98.34,90.34A8,8,0,0,0,98.34,101.66ZM200,40H176a8,8,0,0,0,0,16h24V200H56V136a8,8,0,0,0-16,0v64a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Z\"></path></svg>";
137
143
 
138
144
  var table = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM40,112H80v32H40Zm56,0H216v32H96ZM216,64V96H40V64ZM40,160H80v32H40Zm176,32H96V160H216v32Z\"></path></svg>";
@@ -160,7 +166,9 @@ const icons = new Map([
160
166
  ['check', check],
161
167
  ['checkCircle', checkCircle],
162
168
  ['warningCircle', warningCircle],
169
+ ['file', file$1],
163
170
  ['open', open],
171
+ ['download', download],
164
172
  ['copy', copy$1],
165
173
  ['remove', remove],
166
174
  ['maximize', maximize],
@@ -208,6 +216,7 @@ const icons = new Map([
208
216
  ['unlink', unlink],
209
217
  ['hr', hr$1],
210
218
  ['image', image$1],
219
+ ['attachment', attachment],
211
220
  ['codeBlock', codeBlock$1],
212
221
  ['table', table],
213
222
  ]);
@@ -324,12 +333,29 @@ function denormalizeValue(value) {
324
333
  // Mac: mod+Z returns ⌘+Z
325
334
  // Windows / Linux: mod+Z returns Ctrl+Z
326
335
  function modifierText(value, userAgent) {
336
+ // for generating i18n files
337
+ if (typeof window === 'undefined') {
338
+ return value;
339
+ }
327
340
  userAgent = userAgent !== null && userAgent !== void 0 ? userAgent : navigator.userAgent;
328
341
  const isMac = userAgent.indexOf('Mac OS X') >= 0;
329
342
  const modText = isMac ? '⌘' : 'Ctrl';
330
343
  return value.replace(/(^|\+|\s)mod(\+|\s|$)/g, `$1${modText}$2`);
331
344
  }
332
345
 
346
+ // Returns a human-readable file size string from a number.
347
+ function fileSize(size) {
348
+ const units = ['KB', 'MB', 'GB'];
349
+ let i = 0;
350
+ size /= 1024;
351
+ while (size > 1024 && i < 2) {
352
+ size /= 1024;
353
+ i++;
354
+ }
355
+ const sizeString = size > 0 ? Math.max(size, 0.1).toFixed(1) : 0;
356
+ return `${sizeString} ${units[i]}`;
357
+ }
358
+
333
359
  // Returns a property value of all CSS properties of an element
334
360
  function getCSS(element, propertyName) {
335
361
  const camelPropertyName = camelCase(propertyName);
@@ -2678,184 +2704,42 @@ function morph(node, otherNode, config = {}) {
2678
2704
  morphNormalizedContent(node.get(0), normalizedContent, ctx);
2679
2705
  }
2680
2706
 
2681
- /**
2682
- The MIT License (MIT)
2683
-
2684
- Copyright (c) 2016-present react-component
2685
-
2686
- Permission is hereby granted, free of charge, to any person obtaining a copy
2687
- of this software and associated documentation files (the "Software"), to deal
2688
- in the Software without restriction, including without limitation the rights
2689
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2690
- copies of the Software, and to permit persons to whom the Software is
2691
- furnished to do so, subject to the following conditions:
2692
-
2693
- The above copyright notice and this permission notice shall be included in
2694
- all copies or substantial portions of the Software.
2695
-
2696
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2697
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2698
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2699
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2700
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2701
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2702
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2703
-
2704
- Repository: https://github.com/react-component/upload
2705
- */
2706
- function getError(option, xhr) {
2707
- const msg = `Cannot ${option.method} ${option.action} ${xhr.status}'`;
2708
- const err = new Error(msg);
2709
- err.status = xhr.status;
2710
- err.method = option.method;
2711
- err.url = option.action;
2712
- return err;
2713
- }
2714
- function getBody(xhr) {
2715
- const text = xhr.responseText || xhr.response;
2716
- if (!text) {
2717
- return text;
2718
- }
2719
- try {
2720
- return JSON.parse(text);
2721
- }
2722
- catch (e) {
2723
- return text;
2724
- }
2725
- }
2726
- function request(option) {
2727
- const xhr = new XMLHttpRequest();
2728
- if (option.onProgress && xhr.upload) {
2729
- xhr.upload.onprogress = (e) => {
2730
- if (e.total > 0) {
2731
- e.percent = (e.loaded / e.total) * 100;
2732
- }
2733
- if (option.onProgress) {
2734
- option.onProgress(e);
2735
- }
2736
- };
2737
- }
2738
- const formData = new FormData();
2739
- const data = option.data || {};
2740
- Object.keys(data).forEach(key => {
2741
- const value = data[key];
2742
- // support key-value array data
2743
- if (Array.isArray(value)) {
2744
- value.forEach(item => {
2745
- // { list: [ 11, 22 ] }
2746
- // formData.append('list[]', 11);
2747
- formData.append(`${key}[]`, item);
2748
- });
2749
- return;
2707
+ // Returns an object that indicates the specified node's position relative to the viewport.
2708
+ function nodeAndView(node) {
2709
+ const nativeNode = node.get(0);
2710
+ const rect = nativeNode.getBoundingClientRect();
2711
+ let left = rect.left;
2712
+ let right = rect.right;
2713
+ let top = rect.top;
2714
+ let bottom = rect.bottom;
2715
+ let viewportWidth = window.innerWidth;
2716
+ let viewportHeight = window.innerHeight;
2717
+ const container = node.closestContainer();
2718
+ if (container.length > 0) {
2719
+ const viewport = container.closestScroller();
2720
+ if (viewport.length > 0) {
2721
+ const nativeViewport = viewport.get(0);
2722
+ const viewportRect = nativeViewport.getBoundingClientRect();
2723
+ const offsetLeft = viewportRect.x;
2724
+ const offsetTop = viewportRect.y;
2725
+ left -= offsetLeft;
2726
+ right -= offsetLeft;
2727
+ top -= offsetTop;
2728
+ bottom -= offsetTop;
2729
+ viewportWidth = viewportRect.width;
2730
+ viewportHeight = viewportRect.height;
2750
2731
  }
2751
- formData.append(key, value);
2752
- });
2753
- const filename = option.filename || 'file';
2754
- if (option.file instanceof Blob) {
2755
- formData.append(filename, option.file, option.file.name);
2756
- }
2757
- else {
2758
- formData.append(filename, option.file);
2759
2732
  }
2760
- xhr.onerror = (e) => {
2761
- if (option.onError) {
2762
- option.onError(e);
2763
- }
2733
+ const position = {
2734
+ left,
2735
+ right: viewportWidth - right,
2736
+ top,
2737
+ bottom: viewportHeight - bottom,
2764
2738
  };
2765
- xhr.onload = () => {
2766
- // allow success when 2xx status
2767
- // see https://github.com/react-component/upload/issues/34
2768
- if (xhr.status < 200 || xhr.status >= 300) {
2769
- if (!option.onError) {
2770
- return;
2771
- }
2772
- return option.onError(getError(option, xhr), getBody(xhr));
2773
- }
2774
- if (!option.onSuccess) {
2775
- return;
2776
- }
2777
- return option.onSuccess(getBody(xhr), xhr);
2778
- };
2779
- xhr.open(option.method, option.action, true);
2780
- // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
2781
- if (option.withCredentials && 'withCredentials' in xhr) {
2782
- xhr.withCredentials = true;
2783
- }
2784
- const headers = option.headers || {};
2785
- // when set headers['X-Requested-With'] = null , can close default XHR header
2786
- // see https://github.com/react-component/upload/issues/33
2787
- if (headers['X-Requested-With'] !== null) {
2788
- xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
2789
- }
2790
- Object.keys(headers).forEach(h => {
2791
- if (headers[h] !== null) {
2792
- xhr.setRequestHeader(h, headers[h]);
2793
- }
2794
- });
2795
- xhr.send(formData);
2796
- return xhr;
2739
+ return position;
2797
2740
  }
2798
2741
 
2799
- // String
2800
-
2801
- var index = /*#__PURE__*/Object.freeze({
2802
- __proto__: null,
2803
- appendDeepest: appendDeepest,
2804
- camelCase: camelCase,
2805
- changeTagName: changeTagName,
2806
- debug: debug,
2807
- denormalizeValue: denormalizeValue,
2808
- encode: encode,
2809
- fixNumberedList: fixNumberedList,
2810
- getCSS: getCSS,
2811
- getDeepest: getDeepest,
2812
- inString: inString,
2813
- mergeNodes: mergeNodes,
2814
- modifierText: modifierText,
2815
- morph: morph,
2816
- normalizeValue: normalizeValue,
2817
- parseStyle: parseStyle,
2818
- query: query,
2819
- removeBr: removeBr,
2820
- removeZWS: removeZWS,
2821
- request: request,
2822
- safeTemplate: safeTemplate,
2823
- setBlockIndent: setBlockIndent,
2824
- splitNodes: splitNodes,
2825
- template: template,
2826
- toHex: toHex,
2827
- toNodeList: toNodeList,
2828
- wrapNodeList: wrapNodeList
2829
- });
2830
-
2831
- class Fragment {
2832
- constructor(fragment) {
2833
- this.fragment = fragment !== null && fragment !== void 0 ? fragment : document.createDocumentFragment();
2834
- }
2835
- // Returns the descendants of the fragment which are selected by the specified CSS selector.
2836
- find(selector) {
2837
- const nodeList = [];
2838
- let child = new Nodes(this.fragment.firstChild);
2839
- while (child.length > 0) {
2840
- if (child.matches(selector)) {
2841
- nodeList.push(child.get(0));
2842
- }
2843
- else if (child.isElement) {
2844
- child.find(selector).each(node => {
2845
- nodeList.push(node);
2846
- });
2847
- }
2848
- child = child.next();
2849
- }
2850
- return new Nodes(nodeList);
2851
- }
2852
- // Inserts the specified node as the last child.
2853
- append(node) {
2854
- node.each(nativeNode => {
2855
- this.fragment.appendChild(nativeNode);
2856
- });
2857
- }
2858
- }
2742
+ const boxInstances = new Map();
2859
2743
 
2860
2744
  const boxes = new Map();
2861
2745
 
@@ -2867,7 +2751,7 @@ const boxData = {};
2867
2751
  const effectData = {};
2868
2752
  const framework = safeTemplate `
2869
2753
  <span class="lake-box-strip"><br /></span>
2870
- <div class="lake-box-container" contenteditable="false" draggable="true"></div>
2754
+ <div class="lake-box-container" contenteditable="false"></div>
2871
2755
  <span class="lake-box-strip"><br /></span>
2872
2756
  `;
2873
2757
  class Box {
@@ -2932,6 +2816,9 @@ class Box {
2932
2816
  debug(`Box '${this.name}' (id = ${this.node.id}) value:`);
2933
2817
  debug(this.value);
2934
2818
  });
2819
+ if (this.type === 'block') {
2820
+ container.attr('draggable', 'true');
2821
+ }
2935
2822
  }
2936
2823
  // Returns the type of the box.
2937
2824
  get type() {
@@ -3009,28 +2896,235 @@ class Box {
3009
2896
  }
3010
2897
  debug(`Box '${this.name}' (id = ${this.node.id}) rendered`);
3011
2898
  }
3012
- // Destroys a rendered box.
3013
- unmount() {
3014
- for (const cleanup of effectData[this.node.id].cleanup) {
3015
- cleanup();
2899
+ // Destroys a rendered box.
2900
+ unmount() {
2901
+ this.event.emit('blur');
2902
+ for (const cleanup of effectData[this.node.id].cleanup) {
2903
+ cleanup();
2904
+ }
2905
+ boxData[this.node.id] = {};
2906
+ effectData[this.node.id].setup = [];
2907
+ effectData[this.node.id].cleanup = [];
2908
+ this.event.removeAllListeners();
2909
+ this.node.empty();
2910
+ debug(`Box '${this.name}' (id = ${this.node.id}) unmounted`);
2911
+ }
2912
+ // Returns a HTML string of the box.
2913
+ getHTML() {
2914
+ const component = boxes.get(this.name);
2915
+ if (component === undefined) {
2916
+ return '';
2917
+ }
2918
+ if (component.html === undefined) {
2919
+ return this.node.outerHTML();
2920
+ }
2921
+ return component.html(this);
2922
+ }
2923
+ }
2924
+
2925
+ // Returns an already generated box instance or generates a new instance if it does not exist.
2926
+ function getBox(boxNode) {
2927
+ if (typeof boxNode === 'string') {
2928
+ return new Box(boxNode);
2929
+ }
2930
+ boxNode = query(boxNode);
2931
+ const container = boxNode.closestContainer();
2932
+ if (container.length === 0) {
2933
+ return new Box(boxNode);
2934
+ }
2935
+ let instanceMap = boxInstances.get(container.id);
2936
+ if (!instanceMap) {
2937
+ instanceMap = new Map();
2938
+ boxInstances.set(container.id, instanceMap);
2939
+ }
2940
+ let box = instanceMap.get(boxNode.id);
2941
+ if (box) {
2942
+ return box;
2943
+ }
2944
+ box = new Box(boxNode);
2945
+ instanceMap.set(box.node.id, box);
2946
+ return box;
2947
+ }
2948
+
2949
+ /**
2950
+ The MIT License (MIT)
2951
+
2952
+ Copyright (c) 2016-present react-component
2953
+
2954
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2955
+ of this software and associated documentation files (the "Software"), to deal
2956
+ in the Software without restriction, including without limitation the rights
2957
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2958
+ copies of the Software, and to permit persons to whom the Software is
2959
+ furnished to do so, subject to the following conditions:
2960
+
2961
+ The above copyright notice and this permission notice shall be included in
2962
+ all copies or substantial portions of the Software.
2963
+
2964
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2965
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2966
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2967
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2968
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2969
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2970
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2971
+
2972
+ Repository: https://github.com/react-component/upload
2973
+ */
2974
+ function getError(option, xhr) {
2975
+ const msg = `Cannot ${option.method} ${option.action} ${xhr.status}'`;
2976
+ const err = new Error(msg);
2977
+ err.status = xhr.status;
2978
+ err.method = option.method;
2979
+ err.url = option.action;
2980
+ return err;
2981
+ }
2982
+ function getBody(xhr) {
2983
+ const text = xhr.responseText || xhr.response;
2984
+ if (!text) {
2985
+ return text;
2986
+ }
2987
+ try {
2988
+ return JSON.parse(text);
2989
+ }
2990
+ catch (e) {
2991
+ return text;
2992
+ }
2993
+ }
2994
+ function request(option) {
2995
+ const xhr = new XMLHttpRequest();
2996
+ if (option.onProgress && xhr.upload) {
2997
+ xhr.upload.onprogress = (e) => {
2998
+ if (e.total > 0) {
2999
+ e.percent = (e.loaded / e.total) * 100;
3000
+ }
3001
+ if (option.onProgress) {
3002
+ option.onProgress(e);
3003
+ }
3004
+ };
3005
+ }
3006
+ const formData = new FormData();
3007
+ const data = option.data || {};
3008
+ Object.keys(data).forEach(key => {
3009
+ const value = data[key];
3010
+ // support key-value array data
3011
+ if (Array.isArray(value)) {
3012
+ value.forEach(item => {
3013
+ // { list: [ 11, 22 ] }
3014
+ // formData.append('list[]', 11);
3015
+ formData.append(`${key}[]`, item);
3016
+ });
3017
+ return;
3018
+ }
3019
+ formData.append(key, value);
3020
+ });
3021
+ const filename = option.filename || 'file';
3022
+ if (option.file instanceof Blob) {
3023
+ formData.append(filename, option.file, option.file.name);
3024
+ }
3025
+ else {
3026
+ formData.append(filename, option.file);
3027
+ }
3028
+ xhr.onerror = (e) => {
3029
+ if (option.onError) {
3030
+ option.onError(e);
3031
+ }
3032
+ };
3033
+ xhr.onload = () => {
3034
+ // allow success when 2xx status
3035
+ // see https://github.com/react-component/upload/issues/34
3036
+ if (xhr.status < 200 || xhr.status >= 300) {
3037
+ if (!option.onError) {
3038
+ return;
3039
+ }
3040
+ return option.onError(getError(option, xhr), getBody(xhr));
3041
+ }
3042
+ if (!option.onSuccess) {
3043
+ return;
3044
+ }
3045
+ return option.onSuccess(getBody(xhr), xhr);
3046
+ };
3047
+ xhr.open(option.method, option.action, true);
3048
+ // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
3049
+ if (option.withCredentials && 'withCredentials' in xhr) {
3050
+ xhr.withCredentials = true;
3051
+ }
3052
+ const headers = option.headers || {};
3053
+ // when set headers['X-Requested-With'] = null , can close default XHR header
3054
+ // see https://github.com/react-component/upload/issues/33
3055
+ if (headers['X-Requested-With'] !== null) {
3056
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
3057
+ }
3058
+ Object.keys(headers).forEach(h => {
3059
+ if (headers[h] !== null) {
3060
+ xhr.setRequestHeader(h, headers[h]);
3061
+ }
3062
+ });
3063
+ xhr.send(formData);
3064
+ return xhr;
3065
+ }
3066
+
3067
+ // String
3068
+
3069
+ var index = /*#__PURE__*/Object.freeze({
3070
+ __proto__: null,
3071
+ appendDeepest: appendDeepest,
3072
+ camelCase: camelCase,
3073
+ changeTagName: changeTagName,
3074
+ debug: debug,
3075
+ denormalizeValue: denormalizeValue,
3076
+ encode: encode,
3077
+ fileSize: fileSize,
3078
+ fixNumberedList: fixNumberedList,
3079
+ getBox: getBox,
3080
+ getCSS: getCSS,
3081
+ getDeepest: getDeepest,
3082
+ inString: inString,
3083
+ mergeNodes: mergeNodes,
3084
+ modifierText: modifierText,
3085
+ morph: morph,
3086
+ nodeAndView: nodeAndView,
3087
+ normalizeValue: normalizeValue,
3088
+ parseStyle: parseStyle,
3089
+ query: query,
3090
+ removeBr: removeBr,
3091
+ removeZWS: removeZWS,
3092
+ request: request,
3093
+ safeTemplate: safeTemplate,
3094
+ setBlockIndent: setBlockIndent,
3095
+ splitNodes: splitNodes,
3096
+ template: template,
3097
+ toHex: toHex,
3098
+ toNodeList: toNodeList,
3099
+ wrapNodeList: wrapNodeList
3100
+ });
3101
+
3102
+ class Fragment {
3103
+ constructor(fragment) {
3104
+ this.fragment = fragment !== null && fragment !== void 0 ? fragment : document.createDocumentFragment();
3105
+ }
3106
+ // Returns the descendants of the fragment which are selected by the specified CSS selector.
3107
+ find(selector) {
3108
+ const nodeList = [];
3109
+ let child = new Nodes(this.fragment.firstChild);
3110
+ while (child.length > 0) {
3111
+ if (child.matches(selector)) {
3112
+ nodeList.push(child.get(0));
3113
+ }
3114
+ else if (child.isElement) {
3115
+ child.find(selector).each(node => {
3116
+ nodeList.push(node);
3117
+ });
3118
+ }
3119
+ child = child.next();
3016
3120
  }
3017
- boxData[this.node.id] = {};
3018
- effectData[this.node.id].setup = [];
3019
- effectData[this.node.id].cleanup = [];
3020
- this.event.removeAllListeners();
3021
- this.node.empty();
3022
- debug(`Box '${this.name}' (id = ${this.node.id}) unmounted`);
3121
+ return new Nodes(nodeList);
3023
3122
  }
3024
- // Returns a HTML string of the box.
3025
- getHTML() {
3026
- const component = boxes.get(this.name);
3027
- if (component === undefined) {
3028
- return '';
3029
- }
3030
- if (component.html === undefined) {
3031
- return this.node.outerHTML();
3032
- }
3033
- return component.html(this);
3123
+ // Inserts the specified node as the last child.
3124
+ append(node) {
3125
+ node.each(nativeNode => {
3126
+ this.fragment.appendChild(nativeNode);
3127
+ });
3034
3128
  }
3035
3129
  }
3036
3130
 
@@ -3440,7 +3534,7 @@ function toBookmark(range, bookmark) {
3440
3534
  }
3441
3535
  if (focus.length > 0 && anchor.length === 0) {
3442
3536
  if (focus.isBox) {
3443
- const box = new Box(focus);
3537
+ const box = getBox(focus);
3444
3538
  if (box.getContainer().length === 0) {
3445
3539
  box.render();
3446
3540
  }
@@ -3861,7 +3955,7 @@ function addMark(range, value) {
3861
3955
  if (range.isCollapsed) {
3862
3956
  if (range.isBox) {
3863
3957
  const boxNode = range.startNode.closest('lake-box');
3864
- const box = new Box(boxNode);
3958
+ const box = getBox(boxNode);
3865
3959
  if (box.type === 'block') {
3866
3960
  const newBlock = query('<p><br /></p>');
3867
3961
  if (range.isBoxStart) {
@@ -4160,6 +4254,7 @@ var enUS = {
4160
4254
  fontColor: 'Font color',
4161
4255
  highlight: 'Highlight',
4162
4256
  image: 'Image',
4257
+ file: 'File',
4163
4258
  removeColor: 'Remove color',
4164
4259
  },
4165
4260
  link: {
@@ -4181,6 +4276,10 @@ var enUS = {
4181
4276
  zoomOut: 'Zoom out',
4182
4277
  zoomIn: 'Zoom in',
4183
4278
  },
4279
+ file: {
4280
+ download: 'Download',
4281
+ remove: 'Delete',
4282
+ },
4184
4283
  codeBlock: {
4185
4284
  langType: 'Select language',
4186
4285
  },
@@ -4230,6 +4329,7 @@ var zhCN = {
4230
4329
  fontColor: '文字颜色',
4231
4330
  highlight: '文字背景',
4232
4331
  image: '图片',
4332
+ file: '文件',
4233
4333
  removeColor: '默认',
4234
4334
  },
4235
4335
  link: {
@@ -4251,6 +4351,10 @@ var zhCN = {
4251
4351
  zoomOut: '缩小',
4252
4352
  zoomIn: '放大',
4253
4353
  },
4354
+ file: {
4355
+ download: '下载',
4356
+ remove: '删除',
4357
+ },
4254
4358
  codeBlock: {
4255
4359
  langType: '选择代码语言',
4256
4360
  },
@@ -4300,6 +4404,7 @@ var ja = {
4300
4404
  fontColor: '文字色',
4301
4405
  highlight: '文字の背景',
4302
4406
  image: '画像',
4407
+ file: 'ファイル',
4303
4408
  removeColor: 'デフォルト',
4304
4409
  },
4305
4410
  link: {
@@ -4321,6 +4426,10 @@ var ja = {
4321
4426
  zoomOut: '縮小',
4322
4427
  zoomIn: '拡大',
4323
4428
  },
4429
+ file: {
4430
+ download: 'ダウンロード',
4431
+ remove: '削除',
4432
+ },
4324
4433
  codeBlock: {
4325
4434
  langType: 'コード言語を選択',
4326
4435
  },
@@ -4370,6 +4479,7 @@ var ko = {
4370
4479
  fontColor: '글자 색상',
4371
4480
  highlight: '글자 배경',
4372
4481
  image: '이미지',
4482
+ file: '파일',
4373
4483
  removeColor: '기본색',
4374
4484
  },
4375
4485
  link: {
@@ -4391,6 +4501,10 @@ var ko = {
4391
4501
  zoomOut: '축소',
4392
4502
  zoomIn: '확대',
4393
4503
  },
4504
+ file: {
4505
+ download: '다운로드',
4506
+ remove: '삭제',
4507
+ },
4394
4508
  codeBlock: {
4395
4509
  langType: '코드언어 선택',
4396
4510
  },
@@ -4673,14 +4787,14 @@ class Dropdown {
4673
4787
  }
4674
4788
  }
4675
4789
 
4676
- var version = "0.1.8";
4790
+ var version = "0.1.10";
4677
4791
 
4678
4792
  // Inserts a box into the specified range.
4679
4793
  function insertBox(range, boxName, boxValue) {
4680
4794
  if (range.commonAncestor.isOutside) {
4681
4795
  return null;
4682
4796
  }
4683
- const box = new Box(boxName);
4797
+ const box = getBox(boxName);
4684
4798
  if (boxValue) {
4685
4799
  box.value = boxValue;
4686
4800
  }
@@ -4719,7 +4833,7 @@ function removeBox(range) {
4719
4833
  if (boxNode.length === 0) {
4720
4834
  return null;
4721
4835
  }
4722
- const box = new Box(boxNode);
4836
+ const box = getBox(boxNode);
4723
4837
  if (box.type === 'block') {
4724
4838
  const paragraph = query('<p><br /></p>');
4725
4839
  boxNode.before(paragraph);
@@ -4823,20 +4937,20 @@ class Selection {
4823
4937
  return new Range();
4824
4938
  }
4825
4939
  // Adds the saved range to the native selection.
4826
- addRangeToNativeSelection() {
4940
+ sync() {
4827
4941
  this.selection.removeAllRanges();
4828
4942
  this.selection.addRange(this.range.get());
4829
4943
  }
4830
- // Synchronizes the saved range with the range of the native selection.
4831
- syncByRange() {
4944
+ // Updates the saved range with the range of the native selection.
4945
+ updateByRange() {
4832
4946
  const newRange = this.getRangeFromNativeSelection();
4833
4947
  if (this.range.get() === newRange.get()) {
4834
4948
  return;
4835
4949
  }
4836
4950
  this.range = newRange;
4837
4951
  }
4838
- // Synchronizes the saved range with the range represented by the bookmark.
4839
- synByBookmark() {
4952
+ // Updates the saved range with the range represented by the bookmark.
4953
+ updateByBookmark() {
4840
4954
  const range = this.range;
4841
4955
  const container = this.container;
4842
4956
  const boxFocus = container.find('lake-box[focus]');
@@ -4845,7 +4959,7 @@ class Selection {
4845
4959
  anchor: new Nodes(),
4846
4960
  focus: boxFocus,
4847
4961
  });
4848
- this.addRangeToNativeSelection();
4962
+ this.sync();
4849
4963
  return;
4850
4964
  }
4851
4965
  const anchor = container.find('lake-bookmark[type="anchor"]');
@@ -4854,7 +4968,7 @@ class Selection {
4854
4968
  anchor,
4855
4969
  focus,
4856
4970
  });
4857
- this.addRangeToNativeSelection();
4971
+ this.sync();
4858
4972
  }
4859
4973
  getAppliedItems() {
4860
4974
  const appliedItems = [];
@@ -4961,8 +5075,6 @@ class Command {
4961
5075
  }
4962
5076
  }
4963
5077
 
4964
- const boxInstances = new Map();
4965
-
4966
5078
  // Saves and controls the history of the value of the editor.
4967
5079
  // Example:
4968
5080
  // before initialization: value: 'a', list: [], index: 0, canUndo: false
@@ -5040,7 +5152,7 @@ class History {
5040
5152
  const range = this.selection.range;
5041
5153
  const newContainer = this.container.clone(true);
5042
5154
  newContainer.find('lake-box').each(nativeNode => {
5043
- const box = new Box(nativeNode);
5155
+ const box = getBox(nativeNode);
5044
5156
  box.getContainer().empty();
5045
5157
  });
5046
5158
  if (range.commonAncestor.isOutside) {
@@ -5090,7 +5202,7 @@ class History {
5090
5202
  }
5091
5203
  this.index--;
5092
5204
  }
5093
- this.selection.synByBookmark();
5205
+ this.selection.updateByBookmark();
5094
5206
  debug(`History undone, the last index is ${this.index}`);
5095
5207
  }
5096
5208
  redo() {
@@ -5112,7 +5224,7 @@ class History {
5112
5224
  break;
5113
5225
  }
5114
5226
  }
5115
- this.selection.synByBookmark();
5227
+ this.selection.updateByBookmark();
5116
5228
  debug(`History redone, the last index is ${this.index}`);
5117
5229
  }
5118
5230
  continue() {
@@ -5219,17 +5331,17 @@ class BoxManager {
5219
5331
  getNames() {
5220
5332
  return Array.from(boxes.keys());
5221
5333
  }
5222
- getInstances(editor) {
5223
- let instanceMap = boxInstances.get(editor.container.id);
5334
+ getInstances(container) {
5335
+ let instanceMap = boxInstances.get(container.id);
5224
5336
  if (!instanceMap) {
5225
5337
  instanceMap = new Map();
5226
- boxInstances.set(editor.container.id, instanceMap);
5338
+ boxInstances.set(container.id, instanceMap);
5227
5339
  return instanceMap;
5228
5340
  }
5229
5341
  return instanceMap;
5230
5342
  }
5231
- rectifyInstances(editor) {
5232
- const instanceMap = this.getInstances(editor);
5343
+ rectifyInstances(container) {
5344
+ const instanceMap = this.getInstances(container);
5233
5345
  for (const box of instanceMap.values()) {
5234
5346
  if (!box.node.get(0).isConnected) {
5235
5347
  box.unmount();
@@ -5237,20 +5349,16 @@ class BoxManager {
5237
5349
  }
5238
5350
  }
5239
5351
  }
5240
- findAll(editor) {
5241
- return editor.container.find('lake-box');
5242
- }
5243
- renderAll(editor) {
5244
- this.rectifyInstances(editor);
5245
- const instanceMap = this.getInstances(editor);
5246
- this.findAll(editor).each(boxNativeNode => {
5247
- const boxNode = new Nodes(boxNativeNode);
5352
+ renderAll(container) {
5353
+ this.rectifyInstances(container);
5354
+ const instanceMap = this.getInstances(container);
5355
+ container.find('lake-box').each(boxNativeNode => {
5356
+ const boxNode = query(boxNativeNode);
5248
5357
  if (instanceMap.get(boxNode.id)) {
5249
5358
  return;
5250
5359
  }
5251
- const box = new Box(boxNode);
5360
+ const box = getBox(boxNode);
5252
5361
  box.render();
5253
- instanceMap.set(box.node.id, box);
5254
5362
  });
5255
5363
  }
5256
5364
  }
@@ -5278,6 +5386,22 @@ const defaultConfig = {
5278
5386
  indentWithTab: true,
5279
5387
  lang: 'en-US',
5280
5388
  minChangeSize: 5,
5389
+ onMessage: (type, message) => {
5390
+ if (type === 'success') {
5391
+ // eslint-disable-next-line no-console
5392
+ console.log(message);
5393
+ return;
5394
+ }
5395
+ if (type === 'warning') {
5396
+ // eslint-disable-next-line no-console
5397
+ console.warn(message);
5398
+ return;
5399
+ }
5400
+ if (type === 'error') {
5401
+ // eslint-disable-next-line no-console
5402
+ console.error(message);
5403
+ }
5404
+ },
5281
5405
  };
5282
5406
  class Editor {
5283
5407
  constructor(config) {
@@ -5316,13 +5440,13 @@ class Editor {
5316
5440
  this.history.save();
5317
5441
  };
5318
5442
  this.selectionchangeListener = () => {
5319
- this.selection.syncByRange();
5443
+ this.selection.updateByRange();
5320
5444
  this.updateBoxSelectionStyle();
5321
5445
  this.emitStateChangeEvent();
5322
5446
  };
5323
5447
  this.clickListener = event => {
5324
5448
  const targetNode = new Nodes(event.target);
5325
- if (targetNode.closest('.lake-popup').length > 0) {
5449
+ if (!targetNode.get(0).isConnected || targetNode.closest('.lake-popup').length > 0) {
5326
5450
  return;
5327
5451
  }
5328
5452
  this.event.emit('click', targetNode);
@@ -5338,8 +5462,8 @@ class Editor {
5338
5462
  const range = this.selection.range;
5339
5463
  const clonedRange = range.clone();
5340
5464
  clonedRange.adaptBox();
5341
- this.box.findAll(this).each(boxNode => {
5342
- const box = new Box(boxNode);
5465
+ this.container.find('lake-box').each(boxNativeNode => {
5466
+ const box = getBox(boxNativeNode);
5343
5467
  const boxContainer = box.getContainer();
5344
5468
  if (boxContainer.length === 0) {
5345
5469
  return;
@@ -5350,6 +5474,7 @@ class Editor {
5350
5474
  boxContainer.removeClass('lake-box-selected');
5351
5475
  boxContainer.removeClass('lake-box-focused');
5352
5476
  boxContainer.addClass('lake-box-activated');
5477
+ box.event.emit('focus');
5353
5478
  return;
5354
5479
  }
5355
5480
  }
@@ -5359,16 +5484,19 @@ class Editor {
5359
5484
  boxContainer.removeClass('lake-box-hovered');
5360
5485
  boxContainer.removeClass('lake-box-selected');
5361
5486
  boxContainer.addClass('lake-box-focused');
5487
+ box.event.emit('focus');
5362
5488
  }
5363
5489
  else {
5364
5490
  boxContainer.removeClass('lake-box-focused');
5365
5491
  boxContainer.addClass('lake-box-selected');
5492
+ box.event.emit('blur');
5366
5493
  }
5367
5494
  return;
5368
5495
  }
5369
5496
  boxContainer.removeClass('lake-box-activated');
5370
5497
  boxContainer.removeClass('lake-box-focused');
5371
5498
  boxContainer.removeClass('lake-box-selected');
5499
+ box.event.emit('blur');
5372
5500
  });
5373
5501
  this.event.emit('boxselectionstylechange');
5374
5502
  }, 50, {
@@ -5473,7 +5601,7 @@ class Editor {
5473
5601
  const range = selection.range;
5474
5602
  const stripNode = range.startNode.closest('.lake-box-strip');
5475
5603
  const boxNode = stripNode.closest('lake-box');
5476
- const box = new Box(boxNode);
5604
+ const box = getBox(boxNode);
5477
5605
  if (box.type === 'inline') {
5478
5606
  if (range.isBoxStart) {
5479
5607
  range.setStartBefore(boxNode);
@@ -5555,15 +5683,15 @@ class Editor {
5555
5683
  }
5556
5684
  bindHistoryEvents() {
5557
5685
  this.history.event.on('undo', value => {
5558
- this.box.renderAll(this);
5686
+ this.box.renderAll(this.container);
5559
5687
  this.emitChangeEvent(value);
5560
5688
  });
5561
5689
  this.history.event.on('redo', value => {
5562
- this.box.renderAll(this);
5690
+ this.box.renderAll(this.container);
5563
5691
  this.emitChangeEvent(value);
5564
5692
  });
5565
5693
  this.history.event.on('save', value => {
5566
- this.box.rectifyInstances(this);
5694
+ this.box.rectifyInstances(this.container);
5567
5695
  this.emitChangeEvent(value);
5568
5696
  });
5569
5697
  }
@@ -5710,8 +5838,8 @@ class Editor {
5710
5838
  this.container.empty();
5711
5839
  this.togglePlaceholderClass(htmlParser.getHTML());
5712
5840
  this.container.append(fragment);
5713
- Editor.box.renderAll(this);
5714
- this.selection.synByBookmark();
5841
+ Editor.box.renderAll(this.container);
5842
+ this.selection.updateByBookmark();
5715
5843
  }
5716
5844
  // Returns the contents from the editor.
5717
5845
  getValue() {
@@ -5721,21 +5849,35 @@ class Editor {
5721
5849
  this.selection.toBookmark(bookmark);
5722
5850
  return value;
5723
5851
  }
5852
+ // Sets the current range to the center position of the box.
5853
+ selectBox(box) {
5854
+ let boxNode = box;
5855
+ if (box instanceof Box) {
5856
+ boxNode = box.node;
5857
+ }
5858
+ else {
5859
+ boxNode = box;
5860
+ }
5861
+ this.selection.range.selectBox(boxNode);
5862
+ }
5724
5863
  // Inserts a box into the position of the selection.
5725
5864
  insertBox(boxName, boxValue) {
5726
5865
  const box = insertBox(this.selection.range, boxName, boxValue);
5727
5866
  if (!box) {
5728
5867
  throw new Error(`Box '${boxName}' cannot be inserted outside the editor.`);
5729
5868
  }
5730
- const instanceMap = this.box.getInstances(this);
5869
+ const instanceMap = this.box.getInstances(this.container);
5731
5870
  instanceMap.set(box.node.id, box);
5732
5871
  return box;
5733
5872
  }
5734
5873
  // Removes the selected box.
5735
- removeBox() {
5736
- const box = removeBox(this.selection.range);
5874
+ removeBox(box = null) {
5875
+ if (box) {
5876
+ this.selectBox(box);
5877
+ }
5878
+ box = removeBox(this.selection.range);
5737
5879
  if (box) {
5738
- const instanceMap = this.box.getInstances(this);
5880
+ const instanceMap = this.box.getInstances(this.container);
5739
5881
  instanceMap.delete(box.node.id);
5740
5882
  }
5741
5883
  return box;
@@ -5754,10 +5896,10 @@ class Editor {
5754
5896
  this.container.append(fragment);
5755
5897
  Editor.plugin.loadAll(this);
5756
5898
  if (!this.readonly) {
5757
- this.selection.synByBookmark();
5899
+ this.selection.updateByBookmark();
5758
5900
  this.history.save();
5759
5901
  }
5760
- Editor.box.renderAll(this);
5902
+ Editor.box.renderAll(this.container);
5761
5903
  if (this.toolbar) {
5762
5904
  this.toolbar.render(this);
5763
5905
  }
@@ -6414,15 +6556,26 @@ const toolbarItems = [
6414
6556
  accept: 'image/*',
6415
6557
  multiple: true,
6416
6558
  },
6559
+ {
6560
+ name: 'file',
6561
+ type: 'upload',
6562
+ icon: icons.get('attachment'),
6563
+ tooltip: locale => locale.toolbar.file(),
6564
+ accept: '*',
6565
+ multiple: true,
6566
+ },
6417
6567
  ];
6418
6568
 
6419
- function uploadImage(config) {
6420
- const { editor, file, onError, onSuccess } = config;
6421
- const { requestMethod, requestAction, requestTypes } = editor.config.image;
6569
+ function uploadFile(config) {
6570
+ const { editor, name, file, onError, onSuccess } = config;
6571
+ const { requestMethod, requestAction, requestTypes } = editor.config[name];
6422
6572
  if (requestTypes.indexOf(file.type) < 0) {
6423
- throw new Error(`Cannot upload file because its type '${file.type}' is not found in ['${requestTypes.join('\', \'')}'].`);
6573
+ if (onError) {
6574
+ onError(`File '${file.name}' is not allowed for uploading.`);
6575
+ }
6576
+ throw new Error(`Cannot upload file '${file.name}' because its type '${file.type}' is not found in ['${requestTypes.join('\', \'')}'].`);
6424
6577
  }
6425
- const box = editor.insertBox('image', {
6578
+ const box = editor.insertBox(name, {
6426
6579
  url: URL.createObjectURL(file),
6427
6580
  status: 'uploading',
6428
6581
  name: file.name,
@@ -6441,7 +6594,7 @@ function uploadImage(config) {
6441
6594
  box.updateValue('status', 'error');
6442
6595
  box.render();
6443
6596
  if (onError) {
6444
- onError();
6597
+ onError(error.toString());
6445
6598
  }
6446
6599
  },
6447
6600
  onSuccess: body => {
@@ -6449,7 +6602,7 @@ function uploadImage(config) {
6449
6602
  box.updateValue('status', 'error');
6450
6603
  box.render();
6451
6604
  if (onError) {
6452
- onError();
6605
+ onError('Cannot find the url field.');
6453
6606
  }
6454
6607
  return;
6455
6608
  }
@@ -6492,9 +6645,9 @@ const defaultItems = [
6492
6645
  'blockQuote',
6493
6646
  'hr',
6494
6647
  ];
6495
- const toolbarItemMap = new Map();
6648
+ const toolbarItemMap$1 = new Map();
6496
6649
  toolbarItems.forEach(item => {
6497
- toolbarItemMap.set(item.name, item);
6650
+ toolbarItemMap$1.set(item.name, item);
6498
6651
  });
6499
6652
  class Toolbar {
6500
6653
  constructor(config) {
@@ -6581,9 +6734,11 @@ class Toolbar {
6581
6734
  const target = event.target;
6582
6735
  const files = target.files || [];
6583
6736
  for (const file of files) {
6584
- uploadImage({
6737
+ uploadFile({
6585
6738
  editor,
6739
+ name: item.name,
6586
6740
  file,
6741
+ onError: error => editor.config.onMessage('error', error),
6587
6742
  });
6588
6743
  }
6589
6744
  });
@@ -6658,7 +6813,7 @@ class Toolbar {
6658
6813
  }
6659
6814
  let item;
6660
6815
  if (typeof name === 'string') {
6661
- item = toolbarItemMap.get(name);
6816
+ item = toolbarItemMap$1.get(name);
6662
6817
  if (!item) {
6663
6818
  return;
6664
6819
  }
@@ -6695,7 +6850,7 @@ const hrBox = {
6695
6850
  box.useEffect(() => {
6696
6851
  const hrNode = box.getContainer().find('.lake-hr');
6697
6852
  hrNode.on('click', () => {
6698
- editor.selection.range.selectBox(box.node);
6853
+ editor.selectBox(box);
6699
6854
  });
6700
6855
  });
6701
6856
  return '<div class="lake-hr"><hr /></div>';
@@ -6839,7 +6994,7 @@ function openFullScreen(box) {
6839
6994
  let currentIndex = 0;
6840
6995
  const allImageBox = editor.container.find('lake-box[name="image"]');
6841
6996
  allImageBox.each((node, index) => {
6842
- const imageBox = new Box(node);
6997
+ const imageBox = getBox(node);
6843
6998
  const imageValue = imageBox.value;
6844
6999
  if (imageValue.status !== 'done') {
6845
7000
  return;
@@ -6922,7 +7077,7 @@ function openFullScreen(box) {
6922
7077
  if (savedRange) {
6923
7078
  // fix(image): lose focus when zooming in the iOS
6924
7079
  editor.selection.range = savedRange;
6925
- editor.selection.addRangeToNativeSelection();
7080
+ editor.selection.sync();
6926
7081
  }
6927
7082
  box.event.emit('closefullscreen');
6928
7083
  }, 0);
@@ -6930,20 +7085,6 @@ function openFullScreen(box) {
6930
7085
  lightbox.init();
6931
7086
  lightbox.loadAndOpen(currentIndex);
6932
7087
  }
6933
- // Removes current box.
6934
- function removeImageBox(box) {
6935
- const editor = box.getEditor();
6936
- if (!editor) {
6937
- return;
6938
- }
6939
- const xhr = box.getData('xhr');
6940
- if (xhr) {
6941
- xhr.abort();
6942
- }
6943
- editor.selection.range.selectBox(box.node);
6944
- editor.removeBox();
6945
- editor.history.save();
6946
- }
6947
7088
  // Displays error icon and filename.
6948
7089
  function renderError(imageNode, box) {
6949
7090
  return __awaiter(this, void 0, void 0, function* () {
@@ -7167,13 +7308,19 @@ const imageBox = {
7167
7308
  else {
7168
7309
  imageNode.find('.lake-button-remove').on('click', event => {
7169
7310
  event.stopPropagation();
7170
- removeImageBox(box);
7311
+ const xhr = box.getData('xhr');
7312
+ if (xhr) {
7313
+ xhr.abort();
7314
+ }
7315
+ editor.removeBox(box);
7316
+ editor.history.save();
7317
+ editor.selection.sync();
7171
7318
  });
7172
7319
  }
7173
7320
  box.event.emit('render');
7174
7321
  });
7175
7322
  imageNode.on('click', () => {
7176
- editor.selection.range.selectBox(box.node);
7323
+ editor.selectBox(box);
7177
7324
  });
7178
7325
  },
7179
7326
  html: box => {
@@ -7182,6 +7329,232 @@ const imageBox = {
7182
7329
  },
7183
7330
  };
7184
7331
 
7332
+ const toolbarItemMap = new Map();
7333
+ class BoxToolbar {
7334
+ constructor(config) {
7335
+ this.placement = 'top';
7336
+ this.buttonItemList = [];
7337
+ this.dropdownItemList = [];
7338
+ this.root = query(config.root);
7339
+ this.editor = config.editor;
7340
+ this.box = config.box;
7341
+ this.items = config.items;
7342
+ if (config.placement) {
7343
+ this.placement = config.placement;
7344
+ }
7345
+ this.container = query('<div class="lake-box-toolbar" />');
7346
+ this.root.addClass('lake-custom-properties');
7347
+ }
7348
+ appendDivider() {
7349
+ this.container.append('<div class="lake-box-toolbar-divider" />');
7350
+ }
7351
+ appendButton(item) {
7352
+ const button = new Button({
7353
+ root: this.container,
7354
+ name: item.name,
7355
+ icon: item.icon,
7356
+ tooltip: typeof item.tooltip === 'string' ? item.tooltip : item.tooltip(this.editor.locale),
7357
+ tabIndex: -1,
7358
+ onClick: () => {
7359
+ item.onClick(this.box, item.name);
7360
+ },
7361
+ });
7362
+ button.render();
7363
+ }
7364
+ appendDropdown(item) {
7365
+ const dropdown = new Dropdown({
7366
+ root: this.container,
7367
+ locale: this.editor.locale,
7368
+ name: item.name,
7369
+ icon: item.icon,
7370
+ accentIcon: item.accentIcon,
7371
+ downIcon: item.downIcon,
7372
+ defaultValue: item.defaultValue,
7373
+ tooltip: item.tooltip,
7374
+ width: item.width,
7375
+ menuType: item.menuType,
7376
+ menuItems: item.menuItems,
7377
+ tabIndex: -1,
7378
+ placement: this.placement === 'top' ? 'bottom' : 'top',
7379
+ onSelect: value => {
7380
+ item.onSelect(this.box, value);
7381
+ },
7382
+ });
7383
+ dropdown.render();
7384
+ }
7385
+ updatePosition() {
7386
+ const boxNode = this.box.node;
7387
+ const position = nodeAndView(boxNode);
7388
+ if (position.left < 0 || position.right < 0 || position.top < 0 || position.bottom < 0) {
7389
+ this.container.hide();
7390
+ return;
7391
+ }
7392
+ this.container.show('flex');
7393
+ const boxNativeNode = this.box.node.get(0);
7394
+ const boxRect = boxNativeNode.getBoundingClientRect();
7395
+ const boxX = boxRect.x + window.scrollX;
7396
+ const boxY = boxRect.y + window.scrollY;
7397
+ const left = (boxX + boxRect.width / 2 - this.container.width() / 2).toFixed(1);
7398
+ const top = (boxY - this.container.height() - 6).toFixed(1);
7399
+ this.container.css({
7400
+ left: `${left}px`,
7401
+ top: `${top}px`,
7402
+ });
7403
+ }
7404
+ // Renders a toolbar for the specified box.
7405
+ render() {
7406
+ this.root.empty();
7407
+ this.root.append(this.container);
7408
+ this.items.forEach(name => {
7409
+ if (name === '|') {
7410
+ this.appendDivider();
7411
+ return;
7412
+ }
7413
+ let item;
7414
+ if (typeof name === 'string') {
7415
+ item = toolbarItemMap.get(name);
7416
+ if (!item) {
7417
+ return;
7418
+ }
7419
+ }
7420
+ else {
7421
+ item = name;
7422
+ }
7423
+ if (item.type === 'button') {
7424
+ this.buttonItemList.push(item);
7425
+ this.appendButton(item);
7426
+ return;
7427
+ }
7428
+ if (item.type === 'dropdown') {
7429
+ this.dropdownItemList.push(item);
7430
+ this.appendDropdown(item);
7431
+ }
7432
+ });
7433
+ this.updatePosition();
7434
+ }
7435
+ unmount() {
7436
+ this.container.remove();
7437
+ }
7438
+ }
7439
+
7440
+ const boxToolbarItems = [
7441
+ {
7442
+ name: 'download',
7443
+ type: 'button',
7444
+ icon: icons.get('download'),
7445
+ tooltip: locale => locale.file.download(),
7446
+ onClick: box => {
7447
+ window.open(box.value.url);
7448
+ },
7449
+ },
7450
+ {
7451
+ name: 'remove',
7452
+ type: 'button',
7453
+ icon: icons.get('remove'),
7454
+ tooltip: locale => locale.file.remove(),
7455
+ onClick: box => {
7456
+ const editor = box.getEditor();
7457
+ if (!editor) {
7458
+ return;
7459
+ }
7460
+ editor.removeBox(box);
7461
+ editor.history.save();
7462
+ editor.selection.sync();
7463
+ },
7464
+ },
7465
+ ];
7466
+ function appendContent(fileNode, box) {
7467
+ return __awaiter(this, void 0, void 0, function* () {
7468
+ const editor = box.getEditor();
7469
+ if (!editor) {
7470
+ return;
7471
+ }
7472
+ const value = box.value;
7473
+ const infoNode = query(safeTemplate `
7474
+ <div class="lake-file-info">
7475
+ <div class="lake-file-type"></div>
7476
+ <div class="lake-file-name">${value.name} (${fileSize(value.size)})</div>
7477
+ </div>
7478
+ `);
7479
+ const typeNode = infoNode.find('.lake-file-type');
7480
+ if (value.status === 'uploading') {
7481
+ const percent = Math.round(value.percent || 0);
7482
+ const progressNode = query(safeTemplate `
7483
+ <div class="lake-progress">
7484
+ <div class="lake-percent">${percent} %</div>
7485
+ </div>
7486
+ `);
7487
+ const circleNotchIcon = icons.get('circleNotch');
7488
+ if (circleNotchIcon) {
7489
+ progressNode.prepend(circleNotchIcon);
7490
+ }
7491
+ typeNode.replaceWith(progressNode);
7492
+ }
7493
+ else {
7494
+ const fileIcon = value.status === 'error' ? icons.get('warningCircle') : icons.get('file');
7495
+ if (fileIcon) {
7496
+ typeNode.append(fileIcon);
7497
+ }
7498
+ }
7499
+ fileNode.append(infoNode);
7500
+ });
7501
+ }
7502
+ const fileBox = {
7503
+ type: 'inline',
7504
+ name: 'file',
7505
+ render: box => {
7506
+ const editor = box.getEditor();
7507
+ if (!editor) {
7508
+ return;
7509
+ }
7510
+ const value = box.value;
7511
+ const container = box.getContainer();
7512
+ const fileNode = query('<div class="lake-file" />');
7513
+ fileNode.addClass(`lake-file-${value.status}`);
7514
+ if (editor.readonly) {
7515
+ fileNode.addClass('lake-file-readonly');
7516
+ }
7517
+ appendContent(fileNode, box);
7518
+ container.empty();
7519
+ container.append(fileNode);
7520
+ if (!editor.readonly) {
7521
+ fileNode.on('click', () => {
7522
+ editor.selectBox(box);
7523
+ });
7524
+ let toolbar = null;
7525
+ const scrollListener = () => {
7526
+ if (toolbar) {
7527
+ toolbar.updatePosition();
7528
+ }
7529
+ };
7530
+ box.event.on('focus', () => {
7531
+ const items = value.status === 'done' ? boxToolbarItems : boxToolbarItems.filter(item => item.name === 'remove');
7532
+ toolbar = new BoxToolbar({
7533
+ root: editor.popupContainer,
7534
+ editor,
7535
+ box,
7536
+ items,
7537
+ });
7538
+ toolbar.render();
7539
+ editor.root.on('scroll', scrollListener);
7540
+ });
7541
+ box.event.on('blur', () => {
7542
+ if (toolbar) {
7543
+ toolbar.unmount();
7544
+ toolbar = null;
7545
+ }
7546
+ editor.root.off('scroll', scrollListener);
7547
+ });
7548
+ }
7549
+ else {
7550
+ fileNode.on('click', () => {
7551
+ window.open(value.url);
7552
+ });
7553
+ }
7554
+ box.event.emit('render');
7555
+ },
7556
+ };
7557
+
7185
7558
  const config = {
7186
7559
  comment: '#57606a',
7187
7560
  name: '#444d56',
@@ -7286,7 +7659,7 @@ const codeBlockBox = {
7286
7659
  Please check if the "lake-codemirror" library is added to this page.
7287
7660
  `.trim());
7288
7661
  codeBlockNode.on('click', () => {
7289
- editor.selection.range.selectBox(box.node);
7662
+ editor.selectBox(box);
7290
7663
  });
7291
7664
  return;
7292
7665
  }
@@ -7391,7 +7764,7 @@ var copy = (editor) => {
7391
7764
  if (!dataTransfer) {
7392
7765
  return;
7393
7766
  }
7394
- const box = new Box(boxNode);
7767
+ const box = getBox(boxNode);
7395
7768
  const content = box.getHTML();
7396
7769
  dataTransfer.setData('text/html', content);
7397
7770
  });
@@ -7418,7 +7791,7 @@ var cut = (editor) => {
7418
7791
  if (!dataTransfer) {
7419
7792
  return;
7420
7793
  }
7421
- const box = new Box(boxNode);
7794
+ const box = getBox(boxNode);
7422
7795
  const content = box.getHTML();
7423
7796
  dataTransfer.setData('text/html', content);
7424
7797
  editor.removeBox();
@@ -7484,7 +7857,7 @@ function insertFirstNode(editor, otherNode) {
7484
7857
  const range = editor.selection.range;
7485
7858
  const boxNode = range.startNode.closest('lake-box');
7486
7859
  if (boxNode.length > 0) {
7487
- const box = new Box(boxNode);
7860
+ const box = getBox(boxNode);
7488
7861
  if (box.type === 'inline') {
7489
7862
  if (range.isBoxStart) {
7490
7863
  range.setStartBefore(boxNode);
@@ -7515,7 +7888,7 @@ function insertFirstNode(editor, otherNode) {
7515
7888
  }
7516
7889
  const block = range.startNode.closestBlock();
7517
7890
  if (otherNode.isBlockBox) {
7518
- const box = new Box(otherNode);
7891
+ const box = getBox(otherNode);
7519
7892
  const value = otherNode.attr('value') !== '' ? box.value : undefined;
7520
7893
  editor.insertBox(box.name, value);
7521
7894
  otherNode.remove();
@@ -7527,7 +7900,7 @@ function insertFirstNode(editor, otherNode) {
7527
7900
  if (block.isEmpty && block.name === 'p') {
7528
7901
  block.replaceWith(otherNode);
7529
7902
  otherNode.find('lake-box').each(node => {
7530
- new Box(node).render();
7903
+ getBox(node).render();
7531
7904
  });
7532
7905
  range.shrinkAfter(otherNode);
7533
7906
  return;
@@ -7601,9 +7974,11 @@ var paste = (editor) => {
7601
7974
  if (dataTransfer.files.length > 0) {
7602
7975
  for (const file of dataTransfer.files) {
7603
7976
  if (requestTypes.indexOf(file.type) >= 0) {
7604
- uploadImage({
7977
+ uploadFile({
7605
7978
  editor,
7979
+ name: file.type.indexOf('image/') === 0 ? 'image' : 'file',
7606
7980
  file,
7981
+ onError: error => editor.config.onMessage('error', error),
7607
7982
  });
7608
7983
  }
7609
7984
  }
@@ -7626,7 +8001,7 @@ var paste = (editor) => {
7626
8001
  editor.event.emit('beforepaste', fragment);
7627
8002
  fixClipboardData(fragment);
7628
8003
  pasteFragment(editor, fragment);
7629
- editor.box.renderAll(editor);
8004
+ editor.box.renderAll(editor.container);
7630
8005
  });
7631
8006
  };
7632
8007
 
@@ -7654,7 +8029,7 @@ var drop = (editor) => {
7654
8029
  dragEvent.preventDefault();
7655
8030
  return;
7656
8031
  }
7657
- const box = new Box(boxNode);
8032
+ const box = getBox(boxNode);
7658
8033
  if (box.type === 'inline') {
7659
8034
  dragEvent.preventDefault();
7660
8035
  return;
@@ -7752,7 +8127,7 @@ var drop = (editor) => {
7752
8127
  return;
7753
8128
  }
7754
8129
  dragEvent.preventDefault();
7755
- const draggedBox = new Box(draggedNode);
8130
+ const draggedBox = getBox(draggedNode);
7756
8131
  const range = editor.selection.range;
7757
8132
  if (targetBlock.isBox) {
7758
8133
  if (dropPosition === 'top') {
@@ -8494,15 +8869,17 @@ class LinkPopup {
8494
8869
  if (!this.linkNode) {
8495
8870
  return;
8496
8871
  }
8872
+ const position = nodeAndView(this.linkNode);
8873
+ if (position.left < 0 || position.right < 0 || position.top < 0 || position.bottom < 0) {
8874
+ this.container.css('visibility', 'hidden');
8875
+ return;
8876
+ }
8877
+ this.container.css('visibility', '');
8497
8878
  const linkNativeNode = this.linkNode.get(0);
8498
8879
  // Returns a DOMRect object providing information about the size of an element and its position relative to the viewport.
8499
8880
  const linkRect = linkNativeNode.getBoundingClientRect();
8500
8881
  const linkX = linkRect.x + window.scrollX;
8501
8882
  const linkY = linkRect.y + window.scrollY;
8502
- if (linkX < 0 || linkY < 0) {
8503
- this.hide();
8504
- return;
8505
- }
8506
8883
  // link.x + popup.width > window.width
8507
8884
  if (linkRect.x + this.container.width() > window.innerWidth) {
8508
8885
  // link.x + window.scrollX - (popup.width - link.width)
@@ -8564,14 +8941,14 @@ var link = (editor) => {
8564
8941
  const range = editor.selection.range;
8565
8942
  range.setStartAfter(node);
8566
8943
  range.collapseToStart();
8567
- editor.selection.addRangeToNativeSelection();
8944
+ editor.selection.sync();
8568
8945
  editor.history.save();
8569
8946
  },
8570
8947
  onRemove: node => {
8571
8948
  const range = editor.selection.range;
8572
8949
  range.setStartAfter(node);
8573
8950
  range.collapseToStart();
8574
- editor.selection.addRangeToNativeSelection();
8951
+ editor.selection.sync();
8575
8952
  editor.history.save();
8576
8953
  },
8577
8954
  });
@@ -8618,7 +8995,7 @@ var hr = (editor) => {
8618
8995
  const fragment = new Fragment(nativeFragment);
8619
8996
  fragment.find('hr').each(nativeNode => {
8620
8997
  const node = query(nativeNode);
8621
- const box = new Box('hr');
8998
+ const box = getBox('hr');
8622
8999
  node.replaceWith(box.node);
8623
9000
  });
8624
9001
  });
@@ -8642,7 +9019,7 @@ var image = (editor) => {
8642
9019
  const fragment = new Fragment(nativeFragment);
8643
9020
  fragment.find('img').each(nativeNode => {
8644
9021
  const node = query(nativeNode);
8645
- const box = new Box('image');
9022
+ const box = getBox('image');
8646
9023
  const value = node.attr('data-lake-value');
8647
9024
  if (value === '') {
8648
9025
  box.value = {
@@ -8664,6 +9041,39 @@ var image = (editor) => {
8664
9041
  });
8665
9042
  };
8666
9043
 
9044
+ var file = (editor) => {
9045
+ editor.setPluginConfig('file', {
9046
+ requestMethod: 'POST',
9047
+ requestTypes: [
9048
+ 'application/zip',
9049
+ 'application/x-zip-compressed',
9050
+ 'application/vnd.rar',
9051
+ 'image/gif',
9052
+ 'image/jpeg',
9053
+ 'image/png',
9054
+ 'image/svg+xml',
9055
+ 'text/plain',
9056
+ 'text/html',
9057
+ 'application/pdf',
9058
+ 'application/msword',
9059
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
9060
+ 'application/vnd.ms-excel',
9061
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
9062
+ 'application/vnd.ms-powerpoint',
9063
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
9064
+ ],
9065
+ });
9066
+ if (editor.readonly) {
9067
+ return;
9068
+ }
9069
+ editor.command.add('file', {
9070
+ execute: (value) => {
9071
+ editor.insertBox('file', value);
9072
+ editor.history.save();
9073
+ },
9074
+ });
9075
+ };
9076
+
8667
9077
  const langList = [
8668
9078
  'text',
8669
9079
  'c',
@@ -9288,8 +9698,7 @@ var backspaceKey = (editor) => {
9288
9698
  const prevNode = range.getPrevNode();
9289
9699
  if (prevNode.isBox) {
9290
9700
  event.preventDefault();
9291
- range.selectBox(prevNode);
9292
- editor.removeBox();
9701
+ editor.removeBox(prevNode);
9293
9702
  editor.history.save();
9294
9703
  return;
9295
9704
  }
@@ -9408,8 +9817,7 @@ var deleteKey = (editor) => {
9408
9817
  const nextNode = range.getNextNode();
9409
9818
  if (nextNode.isBox) {
9410
9819
  event.preventDefault();
9411
- range.selectBox(nextNode);
9412
- editor.removeBox();
9820
+ editor.removeBox(nextNode);
9413
9821
  editor.history.save();
9414
9822
  return;
9415
9823
  }
@@ -9590,7 +9998,7 @@ var escapeKey = (editor) => {
9590
9998
  event.preventDefault();
9591
9999
  const boxNode = range.commonAncestor.closest('lake-box');
9592
10000
  range.selectBoxEnd(boxNode);
9593
- selection.addRangeToNativeSelection();
10001
+ selection.sync();
9594
10002
  return;
9595
10003
  }
9596
10004
  if (editor.hasFocus) {
@@ -9602,6 +10010,7 @@ var escapeKey = (editor) => {
9602
10010
 
9603
10011
  Editor.box.add(hrBox);
9604
10012
  Editor.box.add(imageBox);
10013
+ Editor.box.add(fileBox);
9605
10014
  Editor.box.add(codeBlockBox);
9606
10015
  Editor.plugin.add(copy);
9607
10016
  Editor.plugin.add(cut);
@@ -9631,6 +10040,7 @@ Editor.plugin.add(formatPainter);
9631
10040
  Editor.plugin.add(link);
9632
10041
  Editor.plugin.add(hr);
9633
10042
  Editor.plugin.add(image);
10043
+ Editor.plugin.add(file);
9634
10044
  Editor.plugin.add(codeBlock);
9635
10045
  Editor.plugin.add(markdown);
9636
10046
  Editor.plugin.add(enterKey);