@hufe921/canvas-editor 0.9.36 → 0.9.38

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/CHANGELOG.md CHANGED
@@ -1,3 +1,48 @@
1
+ ## [0.9.38](https://github.com/Hufe921/canvas-editor/compare/v0.9.37...v0.9.38) (2023-07-12)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * limit word break element type #212 ([d7424f8](https://github.com/Hufe921/canvas-editor/commit/d7424f8b8798cc889df3b54748523c1367af2776)), closes [#212](https://github.com/Hufe921/canvas-editor/issues/212)
7
+
8
+
9
+ ### Chores
10
+
11
+ * add plugin tip ([8c6eee1](https://github.com/Hufe921/canvas-editor/commit/8c6eee1a57f5130919d1bdfa6a1067615f3a95e3))
12
+ * update README.md ([ccb1aa7](https://github.com/Hufe921/canvas-editor/commit/ccb1aa70abacd9398f9ff0e5b066ad51cfc27274))
13
+ * update release script ([4d1ad65](https://github.com/Hufe921/canvas-editor/commit/4d1ad650746ff2c4aa58dde2b725704ab9e7a639))
14
+
15
+
16
+ ### Features
17
+
18
+ * add word break option #212 ([d471165](https://github.com/Hufe921/canvas-editor/commit/d471165430e27e5322160e22da5a5f53fc969b0f)), closes [#212](https://github.com/Hufe921/canvas-editor/issues/212)
19
+ * get page value and append element api #211 ([85a9dcb](https://github.com/Hufe921/canvas-editor/commit/85a9dcbcf29a2fc0e1f89293c4f3ecbc976868b7)), closes [#211](https://github.com/Hufe921/canvas-editor/issues/211)
20
+
21
+
22
+
23
+ ## [0.9.37](https://github.com/Hufe921/canvas-editor/compare/v0.9.36...v0.9.37) (2023-07-02)
24
+
25
+
26
+ ### Chores
27
+
28
+ * add plugin demo ([107c4b8](https://github.com/Hufe921/canvas-editor/commit/107c4b86a8703bd1ab01ab7fc9d3cc8a1078591d))
29
+ * update next features roadmap ([ca28454](https://github.com/Hufe921/canvas-editor/commit/ca284540493b985081c86623b569eeef4bf9dcdc))
30
+
31
+
32
+ ### Documentation
33
+
34
+ * add plugin ([d0e1c9b](https://github.com/Hufe921/canvas-editor/commit/d0e1c9b5267e15c0afa94bbd400502735846050b))
35
+
36
+
37
+ ### Features
38
+
39
+ * add fallback placeholder image ([366374e](https://github.com/Hufe921/canvas-editor/commit/366374eb105a49360f7ddecfdb63420e48254698))
40
+ * add plugin interface ([ad0bb32](https://github.com/Hufe921/canvas-editor/commit/ad0bb32b70cd2a7b8cf2c25a83091e92cc13f53b))
41
+ * add setValue command api #210 ([193bd21](https://github.com/Hufe921/canvas-editor/commit/193bd21f7049a565abddd3ae9be761d95d49fea1)), closes [#210](https://github.com/Hufe921/canvas-editor/issues/210)
42
+ * smooth signature drawing ([c328778](https://github.com/Hufe921/canvas-editor/commit/c3287783abfb27670e3572db8c431f23cc04c6ce))
43
+
44
+
45
+
1
46
  ## [0.9.36](https://github.com/Hufe921/canvas-editor/compare/v0.9.35...v0.9.36) (2023-06-16)
2
47
 
3
48
 
package/README.md CHANGED
@@ -5,8 +5,9 @@
5
5
  ## tips
6
6
 
7
7
  1. [docs](https://hufe.club/canvas-editor-docs/)
8
- 2. The render layer by svg is under development, see [feature/svg](https://github.com/Hufe921/canvas-editor/tree/feature/svg)
9
- 3. The export pdf feature is available now, see [feature/pdf](https://github.com/Hufe921/canvas-editor/tree/feature/pdf)
8
+ 2. [canvas-editor-plugin](https://github.com/Hufe921/canvas-editor-plugin)
9
+ 3. The render layer by svg is under development, see [feature/svg](https://github.com/Hufe921/canvas-editor/tree/feature/svg)
10
+ 4. The export pdf feature is available now, see [feature/pdf](https://github.com/Hufe921/canvas-editor/tree/feature/pdf)
10
11
 
11
12
  ## usage
12
13
 
@@ -28,11 +29,10 @@ new Editor(document.querySelector(".canvas-editor"), [
28
29
 
29
30
  ## next features
30
31
 
31
- 1. improve list and title
32
- 2. improve performance
33
- 3. control rules
34
- 4. table paging
35
- 5. [CRDT](https://github.com/Hufe921/canvas-editor/tree/feature/CRDT)
32
+ 1. improve performance
33
+ 2. control rules
34
+ 3. table paging
35
+ 4. [CRDT](https://github.com/Hufe921/canvas-editor/tree/feature/CRDT)
36
36
 
37
37
  ## snapshot
38
38
 
@@ -23,7 +23,7 @@ var __publicField = (obj, key, value) => {
23
23
  return value;
24
24
  };
25
25
  var index = "";
26
- const version = "0.9.36";
26
+ const version = "0.9.38";
27
27
  var MaxHeightRatio;
28
28
  (function(MaxHeightRatio2) {
29
29
  MaxHeightRatio2["HALF"] = "half";
@@ -184,6 +184,13 @@ function cloneProperty(properties, sourceElement, targetElement) {
184
184
  }
185
185
  }
186
186
  }
187
+ function convertStringToBase64(input2) {
188
+ const encoder = new TextEncoder();
189
+ const data2 = encoder.encode(input2);
190
+ const charArray = Array.from(data2, (byte) => String.fromCharCode(byte));
191
+ const base64 = window.btoa(charArray.join(""));
192
+ return base64;
193
+ }
187
194
  const CURSOR_AGENT_HEIGHT = 12;
188
195
  const defaultCursorOption = {
189
196
  width: 1,
@@ -419,6 +426,23 @@ class ImageParticle {
419
426
  addImageObserver(promise) {
420
427
  this.draw.getImageObserver().add(promise);
421
428
  }
429
+ getFallbackImage(width, height) {
430
+ const tileSize = 8;
431
+ const x = (width - Math.ceil(width / tileSize) * tileSize) / 2;
432
+ const y = (height - Math.ceil(height / tileSize) * tileSize) / 2;
433
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
434
+ <rect width="${width}" height="${height}" fill="url(#mosaic)" />
435
+ <defs>
436
+ <pattern id="mosaic" x="${x}" y="${y}" width="${tileSize * 2}" height="${tileSize * 2}" patternUnits="userSpaceOnUse">
437
+ <rect width="${tileSize}" height="${tileSize}" fill="#cccccc" />
438
+ <rect width="${tileSize}" height="${tileSize}" fill="#cccccc" transform="translate(${tileSize}, ${tileSize})" />
439
+ </pattern>
440
+ </defs>
441
+ </svg>`;
442
+ const fallbackImage = new Image();
443
+ fallbackImage.src = `data:image/svg+xml;base64,${convertStringToBase64(svg)}`;
444
+ return fallbackImage;
445
+ }
422
446
  render(ctx, element, x, y) {
423
447
  const { scale } = this.options;
424
448
  const width = element.width * scale;
@@ -437,6 +461,11 @@ class ImageParticle {
437
461
  resolve(element);
438
462
  };
439
463
  img.onerror = (error) => {
464
+ const fallbackImage = this.getFallbackImage(width, height);
465
+ fallbackImage.onload = () => {
466
+ ctx.drawImage(fallbackImage, x, y, width, height);
467
+ this.imageCache.set(element.id, fallbackImage);
468
+ };
440
469
  reject(error);
441
470
  };
442
471
  });
@@ -5435,6 +5464,7 @@ function drop(evt, host) {
5435
5464
  }
5436
5465
  const LETTER_REG = /[a-zA-Z]/;
5437
5466
  const NUMBER_LIKE_REG = /[0-9.]/;
5467
+ const WORD_LIKE_REG = /[^a-zA-Z][a-zA-Z]/;
5438
5468
  function dblclick(host, evt) {
5439
5469
  const draw = host.getDraw();
5440
5470
  const position = draw.getPosition();
@@ -5887,6 +5917,10 @@ class HistoryManager {
5887
5917
  isCanRedo() {
5888
5918
  return !!this.redoStack.length;
5889
5919
  }
5920
+ recovery() {
5921
+ this.undoStack = [];
5922
+ this.redoStack = [];
5923
+ }
5890
5924
  }
5891
5925
  var EditorComponent;
5892
5926
  (function(EditorComponent2) {
@@ -5925,6 +5959,11 @@ var PaperDirection;
5925
5959
  PaperDirection2["VERTICAL"] = "vertical";
5926
5960
  PaperDirection2["HORIZONTAL"] = "horizontal";
5927
5961
  })(PaperDirection || (PaperDirection = {}));
5962
+ var WordBreak;
5963
+ (function(WordBreak2) {
5964
+ WordBreak2["BREAK_ALL"] = "break-all";
5965
+ WordBreak2["BREAK_WORD"] = "break-word";
5966
+ })(WordBreak || (WordBreak = {}));
5928
5967
  class Position {
5929
5968
  constructor(draw) {
5930
5969
  __publicField(this, "cursorPosition");
@@ -7032,6 +7071,24 @@ class TextParticle {
7032
7071
  this.curStyle = "";
7033
7072
  this.cacheMeasureText = new Map();
7034
7073
  }
7074
+ measureWord(ctx, elementList, curIndex) {
7075
+ let width = 0;
7076
+ let endElement = elementList[curIndex];
7077
+ let i = curIndex;
7078
+ while (i < elementList.length) {
7079
+ const element = elementList[i];
7080
+ if (!LETTER_REG.test(element.value)) {
7081
+ endElement = element;
7082
+ break;
7083
+ }
7084
+ width += this.measureText(ctx, element).width;
7085
+ i++;
7086
+ }
7087
+ return {
7088
+ width,
7089
+ endElement
7090
+ };
7091
+ }
7035
7092
  measurePunctuationWidth(ctx, element) {
7036
7093
  if (!element || !PUNCTUATION_LIST.includes(element.value))
7037
7094
  return 0;
@@ -10700,6 +10757,27 @@ class Draw {
10700
10757
  });
10701
10758
  }
10702
10759
  }
10760
+ appendElementList(elementList, options = {}) {
10761
+ if (!elementList.length)
10762
+ return;
10763
+ formatElementList(elementList, {
10764
+ isHandleFirstElement: false,
10765
+ editorOptions: this.options
10766
+ });
10767
+ let curIndex;
10768
+ const { isPrepend } = options;
10769
+ if (isPrepend) {
10770
+ this.elementList.splice(1, 0, ...elementList);
10771
+ curIndex = elementList.length;
10772
+ } else {
10773
+ this.elementList.push(...elementList);
10774
+ curIndex = this.elementList.length - 1;
10775
+ }
10776
+ this.range.setRange(curIndex, curIndex);
10777
+ this.render({
10778
+ curIndex
10779
+ });
10780
+ }
10703
10781
  spliceElementList(elementList, start, deleteCount, ...items) {
10704
10782
  var _a;
10705
10783
  if (deleteCount > 0) {
@@ -10914,11 +10992,16 @@ class Draw {
10914
10992
  isSetCursor: false
10915
10993
  });
10916
10994
  }
10917
- getValue() {
10995
+ getValue(options = {}) {
10918
10996
  const { width, height, margins, watermark } = this.options;
10997
+ const { pageNo } = options;
10998
+ let mainElementList = this.elementList;
10999
+ if (Number.isInteger(pageNo) && pageNo >= 0 && pageNo < this.pageRowList.length) {
11000
+ mainElementList = this.pageRowList[pageNo].flatMap((row) => row.elementList);
11001
+ }
10919
11002
  const data2 = {
10920
11003
  header: zipElementList(this.headerElementList),
10921
- main: zipElementList(this.elementList),
11004
+ main: zipElementList(mainElementList),
10922
11005
  footer: zipElementList(this.footerElementList)
10923
11006
  };
10924
11007
  return {
@@ -10930,6 +11013,33 @@ class Draw {
10930
11013
  data: data2
10931
11014
  };
10932
11015
  }
11016
+ setValue(payload) {
11017
+ const { header, main, footer } = payload;
11018
+ if (!header && !main && !footer)
11019
+ return;
11020
+ if (header) {
11021
+ formatElementList(header, {
11022
+ editorOptions: this.options
11023
+ });
11024
+ this.header.setElementList(header);
11025
+ }
11026
+ if (main) {
11027
+ formatElementList(main, {
11028
+ editorOptions: this.options
11029
+ });
11030
+ this.elementList = main;
11031
+ }
11032
+ if (footer) {
11033
+ formatElementList(footer, {
11034
+ editorOptions: this.options
11035
+ });
11036
+ this.footer.setElementList(footer);
11037
+ }
11038
+ this.historyManager.recovery();
11039
+ this.render({
11040
+ isSetCursor: false
11041
+ });
11042
+ }
10933
11043
  _wrapContainer(rootContainer) {
10934
11044
  const container = document.createElement("div");
10935
11045
  rootContainer.append(container);
@@ -11205,8 +11315,19 @@ class Draw {
11205
11315
  style: this._getFont(element, scale)
11206
11316
  });
11207
11317
  const preElement = elementList[i - 1];
11208
- const nextElement = elementList[i + 1];
11209
- const curRowWidth = curRow.width + metrics.width + this.textParticle.measurePunctuationWidth(ctx, nextElement);
11318
+ let nextElement = elementList[i + 1];
11319
+ let curRowWidth = curRow.width + metrics.width;
11320
+ if (this.options.wordBreak === WordBreak.BREAK_WORD) {
11321
+ if ((!(preElement == null ? void 0 : preElement.type) || (preElement == null ? void 0 : preElement.type) === ElementType.TEXT) && (!element.type || element.type === ElementType.TEXT)) {
11322
+ const word = `${(preElement == null ? void 0 : preElement.value) || ""}${element.value}`;
11323
+ if (WORD_LIKE_REG.test(word)) {
11324
+ const { width, endElement } = this.textParticle.measureWord(ctx, elementList, i);
11325
+ curRowWidth += width;
11326
+ nextElement = endElement;
11327
+ }
11328
+ curRowWidth += this.textParticle.measurePunctuationWidth(ctx, nextElement);
11329
+ }
11330
+ }
11210
11331
  if (element.listId) {
11211
11332
  if (element.listId !== listId) {
11212
11333
  listIndex = 0;
@@ -11692,6 +11813,8 @@ class Command {
11692
11813
  __publicField(this, "executePaperDirection");
11693
11814
  __publicField(this, "executeSetPaperMargin");
11694
11815
  __publicField(this, "executeInsertElementList");
11816
+ __publicField(this, "executeAppendElementList");
11817
+ __publicField(this, "executeSetValue");
11695
11818
  __publicField(this, "executeRemoveControl");
11696
11819
  __publicField(this, "executeSetLocale");
11697
11820
  __publicField(this, "executeLocationCatalog");
@@ -11769,6 +11892,8 @@ class Command {
11769
11892
  this.executePaperDirection = adapt.paperDirection.bind(adapt);
11770
11893
  this.executeSetPaperMargin = adapt.setPaperMargin.bind(adapt);
11771
11894
  this.executeInsertElementList = adapt.insertElementList.bind(adapt);
11895
+ this.executeAppendElementList = adapt.appendElementList.bind(adapt);
11896
+ this.executeSetValue = adapt.setValue.bind(adapt);
11772
11897
  this.executeRemoveControl = adapt.removeControl.bind(adapt);
11773
11898
  this.executeSetLocale = adapt.setLocale.bind(adapt);
11774
11899
  this.executeLocationCatalog = adapt.locationCatalog.bind(adapt);
@@ -13326,8 +13451,8 @@ class CommandAdapt {
13326
13451
  getImage() {
13327
13452
  return this.draw.getDataURL();
13328
13453
  }
13329
- getValue() {
13330
- return this.draw.getValue();
13454
+ getValue(options) {
13455
+ return this.draw.getValue(options);
13331
13456
  }
13332
13457
  getWordCount() {
13333
13458
  return this.workerManager.getWordCount();
@@ -13381,6 +13506,17 @@ class CommandAdapt {
13381
13506
  formatElementContext(elementList, payload, startIndex);
13382
13507
  this.draw.insertElementList(payload);
13383
13508
  }
13509
+ appendElementList(elementList, options) {
13510
+ if (!elementList.length)
13511
+ return;
13512
+ const isReadonly = this.draw.isReadonly();
13513
+ if (isReadonly)
13514
+ return;
13515
+ this.draw.appendElementList(elementList, options);
13516
+ }
13517
+ setValue(payload) {
13518
+ this.draw.setValue(payload);
13519
+ }
13384
13520
  removeControl() {
13385
13521
  const { startIndex, endIndex } = this.range.getRange();
13386
13522
  if (startIndex !== endIndex)
@@ -14274,12 +14410,22 @@ const defaultPlaceholderOption = {
14274
14410
  size: 16,
14275
14411
  font: "Yahei"
14276
14412
  };
14413
+ class Plugin {
14414
+ constructor(editor) {
14415
+ __publicField(this, "editor");
14416
+ this.editor = editor;
14417
+ }
14418
+ use(pluginFunction, options) {
14419
+ pluginFunction(this.editor, options);
14420
+ }
14421
+ }
14277
14422
  class Editor {
14278
14423
  constructor(container, data2, options = {}) {
14279
14424
  __publicField(this, "command");
14280
14425
  __publicField(this, "listener");
14281
14426
  __publicField(this, "register");
14282
14427
  __publicField(this, "destroy");
14428
+ __publicField(this, "use");
14283
14429
  const headerOptions = __spreadValues(__spreadValues({}, defaultHeaderOption), options.header);
14284
14430
  const footerOptions = __spreadValues(__spreadValues({}, defaultFooterOption), options.footer);
14285
14431
  const pageNumberOptions = __spreadValues(__spreadValues({}, defaultPageNumberOption), options.pageNumber);
@@ -14323,7 +14469,8 @@ class Editor {
14323
14469
  defaultHyperlinkColor: "#0000FF",
14324
14470
  paperDirection: PaperDirection.VERTICAL,
14325
14471
  inactiveAlpha: 0.6,
14326
- historyMaxRecordCount: 100
14472
+ historyMaxRecordCount: 100,
14473
+ wordBreak: WordBreak.BREAK_WORD
14327
14474
  }, options), {
14328
14475
  header: headerOptions,
14329
14476
  footer: footerOptions,
@@ -14369,7 +14516,9 @@ class Editor {
14369
14516
  shortcut.removeEvent();
14370
14517
  contextMenu.removeEvent();
14371
14518
  };
14519
+ const plugin = new Plugin(this);
14520
+ this.use = plugin.use.bind(plugin);
14372
14521
  }
14373
14522
  }
14374
- export { BlockType, Command, ControlType, EDITOR_COMPONENT, Editor, EditorComponent, EditorMode, EditorZone, ElementType, ImageDisplay, KeyMap, ListStyle, ListType, MaxHeightRatio, NumberType, PageMode, PaperDirection, RowFlex, TableBorder, TitleLevel, VerticalAlign, Editor as default };
14523
+ export { BlockType, Command, ControlType, EDITOR_COMPONENT, Editor, EditorComponent, EditorMode, EditorZone, ElementType, ImageDisplay, KeyMap, ListStyle, ListType, MaxHeightRatio, NumberType, PageMode, PaperDirection, RowFlex, TableBorder, TitleLevel, VerticalAlign, WordBreak, Editor as default };
14375
14524
  //# sourceMappingURL=canvas-editor.es.js.map