mce 0.15.8 → 0.15.9

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.
@@ -41,7 +41,7 @@ export declare class Doc extends Model {
41
41
  set(source: Document): this;
42
42
  protected _proxyProps(obj: CoreObject, yMap: Y.Map<any>, isMeta?: boolean): void;
43
43
  protected _proxyChildren(node: Node, childrenIds: Y.Array<string>): void;
44
- protected _proxyNode(node: Node, yNode?: YNode, yChildrenIds?: Y.Array<string>): YNode;
44
+ protected _proxyNode(node: Node, yNode?: YNode, yChildrenIds?: Y.Array<string>): void;
45
45
  protected _initYNode(yNode: YNode): Node;
46
46
  toJSON(): Record<string, any>;
47
47
  }
package/dist/index.js CHANGED
@@ -688,7 +688,7 @@ class Doc extends Model {
688
688
  }
689
689
  _proxyChildren(node, childrenIds) {
690
690
  node.on("addChild", (child, newIndex) => {
691
- if (this._transacting === false) {
691
+ if (this._transacting === false || child.internalMode !== "default") {
692
692
  return;
693
693
  }
694
694
  this.transact(() => {
@@ -698,7 +698,7 @@ class Doc extends Model {
698
698
  });
699
699
  });
700
700
  node.on("removeChild", (child, oldIndex) => {
701
- if (this._transacting === false) {
701
+ if (this._transacting === false || child.internalMode !== "default") {
702
702
  return;
703
703
  }
704
704
  this.transact(() => {
@@ -715,7 +715,7 @@ class Doc extends Model {
715
715
  const cachedChildrenIds = childrenIds.toArray();
716
716
  const observeFn = (event, transaction) => {
717
717
  const skip = this._isSelfTransaction(transaction);
718
- this._debug(`yChildren ${node.id} changes`, event.changes.delta);
718
+ this._debug(`yChildren ${node.id} changes skip:${skip}`, event.changes.delta);
719
719
  let retain = 0;
720
720
  event.changes.delta.forEach((action) => {
721
721
  if (action.retain !== void 0) {
@@ -771,6 +771,9 @@ class Doc extends Model {
771
771
  childrenIds.observe(observeFn);
772
772
  }
773
773
  _proxyNode(node, yNode, yChildrenIds) {
774
+ if (node.internalMode !== "default") {
775
+ return;
776
+ }
774
777
  const id = node.id;
775
778
  if (!yNode) {
776
779
  yNode = this._yChildren.get(id);
@@ -839,7 +842,6 @@ class Doc extends Model {
839
842
  }
840
843
  this._proxyChildren(node, yChildrenIds);
841
844
  }
842
- return yNode;
843
845
  }
844
846
  _initYNode(yNode) {
845
847
  const id = yNode.get("id");
@@ -2245,6 +2247,13 @@ const _4_1_text = defineMixin((editor) => {
2245
2247
  elementSelection,
2246
2248
  textSelection
2247
2249
  } = editor;
2250
+ const element = computed(() => elementSelection.value[0]);
2251
+ const hasTextSelectionRange = computed(() => {
2252
+ return (textSelection.value?.length ?? 0) > 1 && textSelection.value[0] !== textSelection.value[1];
2253
+ });
2254
+ const isTextAllSelected = computed(() => {
2255
+ return textSelection.value?.[0].isFirst && textSelection.value?.[1].isLast && textSelection.value?.[1].isLastSelected;
2256
+ });
2248
2257
  function textFontSizeToFit(element2, scale) {
2249
2258
  function _handle(element3) {
2250
2259
  if (!scale) {
@@ -2320,13 +2329,22 @@ const _4_1_text = defineMixin((editor) => {
2320
2329
  if (!element3.text?.isValid?.() || typeof element3.text?.content !== "object") {
2321
2330
  return;
2322
2331
  }
2332
+ const isVertical = element3.text.base.isVertical;
2323
2333
  const style = element3.style.toJSON();
2324
2334
  switch (strategy) {
2325
2335
  case "autoWidth":
2326
- style.width = "auto";
2336
+ if (isVertical) {
2337
+ style.height = "auto";
2338
+ } else {
2339
+ style.width = "auto";
2340
+ }
2327
2341
  break;
2328
2342
  case "autoHeight":
2329
- style.height = "auto";
2343
+ if (isVertical) {
2344
+ style.width = "auto";
2345
+ } else {
2346
+ style.height = "auto";
2347
+ }
2330
2348
  break;
2331
2349
  }
2332
2350
  const { boundingBox } = measureText({
@@ -2347,10 +2365,6 @@ const _4_1_text = defineMixin((editor) => {
2347
2365
  return false;
2348
2366
  });
2349
2367
  }
2350
- const element = computed(() => elementSelection.value[0]);
2351
- const hasSelectionRange = computed(() => {
2352
- return (textSelection.value?.length ?? 0) > 1 && textSelection.value[0] !== textSelection.value[1];
2353
- });
2354
2368
  function handleSelection([start, end], cb) {
2355
2369
  let flag = true;
2356
2370
  element.value?.text?.content.forEach((p, pIndex, pItems) => {
@@ -2379,12 +2393,13 @@ const _4_1_text = defineMixin((editor) => {
2379
2393
  });
2380
2394
  }
2381
2395
  function getTextStyle(key) {
2382
- if (!element.value) {
2396
+ const el = element.value;
2397
+ if (!el) {
2383
2398
  return void 0;
2384
2399
  }
2385
- let value = element.value.style[key];
2386
- const content = element.value.text.content;
2387
- if (hasSelectionRange.value) {
2400
+ let value = el.style[key];
2401
+ const content = el.text.content;
2402
+ if (hasTextSelectionRange.value) {
2388
2403
  const selection = textSelection.value;
2389
2404
  if (selection && selection[0] && selection[1]) {
2390
2405
  handleSelection(selection, ({ selected, fStyle }) => {
@@ -2411,109 +2426,121 @@ const _4_1_text = defineMixin((editor) => {
2411
2426
  }
2412
2427
  return value;
2413
2428
  }
2414
- function setTextStyle(key, value) {
2415
- if (!element.value) {
2429
+ function setTextContentByEachFragment(handler) {
2430
+ const el = element.value;
2431
+ if (!el) {
2416
2432
  return;
2417
2433
  }
2418
- let isAllSelected = false;
2419
- if (hasSelectionRange.value) {
2420
- const selection = textSelection.value;
2421
- if (selection && selection[0] && selection[1]) {
2422
- if (selection[0].isFirst && selection[1].isLast && selection[1].isLastSelected) {
2423
- isAllSelected = true;
2434
+ const newContent = [];
2435
+ let newParagraph = { fragments: [] };
2436
+ let newFragment;
2437
+ handleSelection(textSelection.value, ({ selected, fIndex, fStyle, fLength, c, cIndex, cLength }) => {
2438
+ if (fIndex === 0 && cIndex === 0) {
2439
+ newParagraph = { fragments: [] };
2440
+ newFragment = void 0;
2441
+ }
2442
+ const style = { ...fStyle };
2443
+ if (selected) {
2444
+ handler(style);
2445
+ }
2446
+ if (newFragment) {
2447
+ const { content: _, ..._style } = newFragment;
2448
+ if (isEqualObject(style, _style)) {
2449
+ newFragment.content += c;
2424
2450
  } else {
2425
- const newContent = [];
2426
- let newParagraph = { fragments: [] };
2427
- let newFragment;
2428
- handleSelection(selection, ({ selected, fIndex, fStyle, fLength, c, cIndex, cLength }) => {
2429
- if (fIndex === 0 && cIndex === 0) {
2430
- newParagraph = { fragments: [] };
2431
- newFragment = void 0;
2432
- }
2433
- const style = { ...fStyle };
2434
- if (selected) {
2435
- style[key] = value;
2436
- }
2437
- if (newFragment) {
2438
- const { content: _, ..._style } = newFragment;
2439
- if (isEqualObject(style, _style)) {
2440
- newFragment.content += c;
2441
- } else {
2442
- newParagraph.fragments.push(newFragment);
2443
- newFragment = { ...style, content: c };
2444
- }
2445
- } else {
2446
- newFragment = { ...style, content: c };
2447
- }
2448
- if (fIndex === fLength - 1 && cIndex === cLength - 1) {
2449
- if (newFragment) {
2450
- newParagraph.fragments.push(newFragment);
2451
- }
2452
- if (newParagraph.fragments.length) {
2453
- newContent.push(newParagraph);
2454
- newParagraph = { fragments: [] };
2455
- }
2456
- }
2457
- return true;
2458
- });
2459
- if (newContent.length) {
2460
- element.value.text.content = newContent;
2461
- }
2451
+ newParagraph.fragments.push(newFragment);
2452
+ newFragment = { ...style, content: c };
2462
2453
  }
2454
+ } else {
2455
+ newFragment = { ...style, content: c };
2463
2456
  }
2464
- } else {
2465
- isAllSelected = true;
2457
+ if (fIndex === fLength - 1 && cIndex === cLength - 1) {
2458
+ if (newFragment) {
2459
+ newParagraph.fragments.push(newFragment);
2460
+ }
2461
+ if (newParagraph.fragments.length) {
2462
+ newContent.push(newParagraph);
2463
+ newParagraph = { fragments: [] };
2464
+ }
2465
+ }
2466
+ return true;
2467
+ });
2468
+ if (newContent.length) {
2469
+ el.text = { ...el.text.toJSON(), content: newContent };
2466
2470
  }
2467
- if (isAllSelected) {
2468
- const el = element.value;
2469
- switch (key) {
2470
- case "fill":
2471
- case "outline":
2472
- el.text[key] = value;
2473
- break;
2474
- default:
2471
+ }
2472
+ function setTextStyle(key, value) {
2473
+ const el = element.value;
2474
+ if (!el) {
2475
+ return;
2476
+ }
2477
+ switch (key) {
2478
+ case "writingMode": {
2479
+ if (el.style[key] !== value) {
2480
+ const { width, height } = el.style;
2481
+ el.style.width = height;
2482
+ el.style.height = width;
2475
2483
  el.style[key] = value;
2476
- break;
2484
+ }
2485
+ break;
2486
+ }
2487
+ default: {
2488
+ if (hasTextSelectionRange.value && !isTextAllSelected.value) {
2489
+ setTextContentByEachFragment((fragment) => {
2490
+ fragment[key] = value;
2491
+ });
2492
+ } else {
2493
+ switch (key) {
2494
+ case "fill":
2495
+ case "outline":
2496
+ el.text[key] = value;
2497
+ break;
2498
+ default:
2499
+ el.style[key] = value;
2500
+ break;
2501
+ }
2502
+ el.text.content.forEach((p) => {
2503
+ delete p[key];
2504
+ p.fragments.forEach((f) => {
2505
+ delete f[key];
2506
+ });
2507
+ });
2508
+ el.text = el.text.toJSON();
2509
+ }
2510
+ el.requestDraw();
2511
+ textToFit(el);
2512
+ break;
2477
2513
  }
2478
- const content = element.value.text.content;
2479
- content.forEach((p) => {
2480
- delete p[key];
2481
- p.fragments.forEach((f) => {
2482
- delete f[key];
2483
- });
2484
- });
2485
- el.text.content = content;
2486
2514
  }
2487
- element.value.requestRender();
2488
- textToFit(element.value);
2489
2515
  }
2490
2516
  function getTextFill() {
2491
- if (!element.value) {
2517
+ const el = element.value;
2518
+ if (!el) {
2492
2519
  return void 0;
2493
2520
  }
2494
2521
  let fill;
2495
- if (hasSelectionRange.value) {
2522
+ if (hasTextSelectionRange.value) {
2496
2523
  fill = getTextStyle("fill");
2497
2524
  if (!fill) {
2498
- const color = getTextStyle("color");
2499
- fill = { color };
2525
+ fill = { color: getTextStyle("color") };
2500
2526
  }
2501
2527
  }
2502
- fill = fill ?? element.value.text.fill ?? { color: element.value.style.color };
2528
+ fill = fill ?? el.text.fill ?? { color: el.style.color };
2503
2529
  return fill;
2504
2530
  }
2505
2531
  function setTextFill(value) {
2506
- if (!element.value) {
2507
- return;
2532
+ const el = element.value;
2533
+ if (!el) {
2534
+ return void 0;
2508
2535
  }
2509
- if (hasSelectionRange.value && value?.color) {
2536
+ if (hasTextSelectionRange.value && value?.color) {
2510
2537
  setTextStyle("fill", value);
2511
2538
  } else {
2512
- element.value.text.fill = value;
2539
+ el.text.fill = value;
2513
2540
  if (value?.color) {
2514
- element.value.style.color = value.color;
2541
+ el.style.color = value.color;
2515
2542
  }
2516
- element.value.text.content.forEach((p) => {
2543
+ el.text.content.forEach((p) => {
2517
2544
  delete p.fill;
2518
2545
  delete p.color;
2519
2546
  p.fragments.forEach((f) => {
@@ -2521,15 +2548,23 @@ const _4_1_text = defineMixin((editor) => {
2521
2548
  delete f.color;
2522
2549
  });
2523
2550
  });
2551
+ el.text = {
2552
+ ...el.text.toJSON(),
2553
+ fill: value
2554
+ };
2555
+ el.requestDraw();
2524
2556
  }
2525
2557
  }
2526
2558
  Object.assign(editor, {
2559
+ hasTextSelectionRange,
2560
+ isTextAllSelected,
2527
2561
  textFontSizeToFit,
2528
2562
  textToFit,
2529
2563
  setTextStyle,
2530
2564
  getTextStyle,
2531
2565
  getTextFill,
2532
- setTextFill
2566
+ setTextFill,
2567
+ setTextContentByEachFragment
2533
2568
  });
2534
2569
  return () => {
2535
2570
  TextEditor.register();
@@ -1,5 +1,5 @@
1
1
  import type { Cursor, Vector2, Vector2Like } from 'modern-canvas';
2
- import type { IndexCharacter } from 'modern-text/web-components';
2
+ import type { IndexCharacter as _IndexCharacter } from 'modern-text/web-components';
3
3
  import type { ComputedRef, Ref } from 'vue';
4
4
  import { Aabb2D, Camera2D, DrawboardEffect, Element2D, Engine, Node, Timeline } from 'modern-canvas';
5
5
  import { Fonts } from 'modern-font';
@@ -19,6 +19,7 @@ declare global {
19
19
  side: 'left' | 'right';
20
20
  align: Tblock | 'center';
21
21
  };
22
+ type IndexCharacter = _IndexCharacter;
22
23
  interface Editor {
23
24
  fonts: Fonts;
24
25
  renderEngine: Ref<Engine>;
@@ -1,14 +1,18 @@
1
1
  import type { Element2D } from 'modern-canvas';
2
- import type { NormalizedFill } from 'modern-idoc';
2
+ import type { NormalizedFill, NormalizedFragment } from 'modern-idoc';
3
+ import type { Ref } from 'vue';
3
4
  declare global {
4
5
  namespace Mce {
5
6
  interface Editor {
7
+ hasTextSelectionRange: Ref<boolean>;
8
+ isTextAllSelected: Ref<boolean>;
6
9
  textFontSizeToFit: (element: Element2D, scale?: number) => void;
7
10
  textToFit: (element: Element2D, typography?: Mce.TypographyStrategy) => void;
8
11
  getTextStyle: (key: string) => any;
9
12
  setTextStyle: (key: string, value: any) => void;
10
13
  getTextFill: () => NormalizedFill | undefined;
11
14
  setTextFill: (value: NormalizedFill | undefined) => void;
15
+ setTextContentByEachFragment: (handler: (fragment: NormalizedFragment) => void) => void;
12
16
  }
13
17
  }
14
18
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mce",
3
3
  "type": "module",
4
- "version": "0.15.8",
4
+ "version": "0.15.9",
5
5
  "description": "The headless canvas editor framework. only the ESM.",
6
6
  "author": "wxm",
7
7
  "license": "MIT",
@@ -61,7 +61,7 @@
61
61
  "diff": "^8.0.2",
62
62
  "file-saver": "^2.0.5",
63
63
  "lodash-es": "^4.17.22",
64
- "modern-canvas": "^0.14.23",
64
+ "modern-canvas": "^0.14.24",
65
65
  "modern-font": "^0.4.4",
66
66
  "modern-idoc": "^0.10.8",
67
67
  "modern-text": "^1.10.7",