@overtone-art/canvas-editor-core 0.8.1 → 0.8.3

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/dist/index.js CHANGED
@@ -39,6 +39,7 @@ __export(index_exports, {
39
39
  LayerManager: () => LayerManager,
40
40
  LayerMaskManager: () => LayerMaskManager,
41
41
  LicenseManager: () => LicenseManager,
42
+ MAX_MASK_LAYERS: () => MAX_MASK_LAYERS,
42
43
  MaskController: () => MaskController,
43
44
  MaskPresetManager: () => MaskPresetManager,
44
45
  MaskRefinementError: () => MaskRefinementError,
@@ -2716,8 +2717,10 @@ var TextWrapManager = class {
2716
2717
  text.dirty = true;
2717
2718
  text.setCoords();
2718
2719
  this.canvas.requestRenderAll();
2719
- this.events.emit("layer:modified", { layerId });
2720
- if (save) this.history.save();
2720
+ if (save) {
2721
+ this.events.emit("layer:modified", { layerId });
2722
+ this.history.save();
2723
+ }
2721
2724
  return true;
2722
2725
  }
2723
2726
  };
@@ -4313,6 +4316,7 @@ function installClip(host, entries, sources, box, absolute) {
4313
4316
 
4314
4317
  // src/masks/store.ts
4315
4318
  var CANVAS_MASK_TARGET = "canvas";
4319
+ var MAX_MASK_LAYERS = 10;
4316
4320
  var DEFAULT_ENTRY = {
4317
4321
  mode: "add",
4318
4322
  linked: true,
@@ -4531,13 +4535,16 @@ var LayerMaskManager = class extends MaskStackStore {
4531
4535
  if (!host) return null;
4532
4536
  const sources = this.unwrap(target, host);
4533
4537
  const entries = this.entriesFor(target, sources);
4538
+ if (entries.length >= MAX_MASK_LAYERS) return null;
4534
4539
  const entry = {
4535
4540
  ...DEFAULT_ENTRY,
4536
4541
  id: generateId(),
4537
4542
  name: options.name ?? "Mask",
4538
4543
  ...options.mode ? { mode: options.mode } : {},
4539
4544
  ...options.linked === void 0 ? {} : { linked: options.linked },
4540
- ...options.meta ? { meta: options.meta } : {}
4545
+ ...options.meta ? { meta: options.meta } : {},
4546
+ ...options.sourceLayer ? { sourceLayer: options.sourceLayer } : {},
4547
+ ...options.sourceObject ? { sourceObject: options.sourceObject } : {}
4541
4548
  };
4542
4549
  if (target === CANVAS_MASK_TARGET) entry.linked = false;
4543
4550
  if (options.fit !== false) {
@@ -4607,6 +4614,48 @@ var LayerMaskManager = class extends MaskStackStore {
4607
4614
  this.commit(target, host, [], []);
4608
4615
  return true;
4609
4616
  }
4617
+ /**
4618
+ * Remove one mask from its host and restore it as an ordinary canvas layer.
4619
+ * Its shape, text, paint and transform survive; only the mask relationship is
4620
+ * removed, so it can be edited through every normal layer property panel.
4621
+ */
4622
+ unmask(target, maskId) {
4623
+ const host = this.host(target);
4624
+ if (!host) return null;
4625
+ const entries = [...this.list(target)];
4626
+ const index = entries.findIndex((entry2) => entry2.id === maskId);
4627
+ if (index === -1) return null;
4628
+ const sources = this.unwrap(target, host);
4629
+ const source = sources[index];
4630
+ if (!source) return null;
4631
+ const entry = entries[index];
4632
+ this.history.beginTransaction();
4633
+ try {
4634
+ this.endEdit(false);
4635
+ entries.splice(index, 1);
4636
+ sources.splice(index, 1);
4637
+ if (!source.absolutePositioned && target !== CANVAS_MASK_TARGET) toCanvasSpace(source, host);
4638
+ source.set({
4639
+ absolutePositioned: false,
4640
+ opacity: entry.sourceObject?.opacity ?? 1,
4641
+ globalCompositeOperation: entry.sourceObject?.globalCompositeOperation ?? "source-over",
4642
+ objectCaching: entry.sourceObject?.objectCaching ?? true
4643
+ });
4644
+ if (this.selected?.maskId === maskId) this.select(null, null);
4645
+ this.commit(target, host, entries, sources, false);
4646
+ const saved = entry.sourceLayer;
4647
+ const restored = this.layers.add(saved?.type ?? layerTypeOf(source), source, saved?.name ?? entry.name);
4648
+ restored.meta = saved?.meta ? structuredClone(saved.meta) : {};
4649
+ this.layers.setVisibility(restored.id, saved?.visible ?? true);
4650
+ this.layers.setLocked(restored.id, saved?.locked ?? false);
4651
+ this.layers.setOpacity(restored.id, saved?.opacity ?? 1);
4652
+ this.layers.select(restored.id);
4653
+ this.history.save();
4654
+ return restored;
4655
+ } finally {
4656
+ this.history.endTransaction();
4657
+ }
4658
+ }
4610
4659
  reorder(target, maskId, index) {
4611
4660
  const host = this.host(target);
4612
4661
  if (!host) return false;
@@ -4681,7 +4730,21 @@ var LayerMaskManager = class extends MaskStackStore {
4681
4730
  const below = index > 0 ? ordered[index - 1] : void 0;
4682
4731
  const resolved = target ?? (below && !below.meta.canvasMask ? below.id : CANVAS_MASK_TARGET);
4683
4732
  if (resolved === layerId) return null;
4733
+ if (this.list(resolved).length >= MAX_MASK_LAYERS) return null;
4684
4734
  const object = layer.fabricObject;
4735
+ const sourceLayer = {
4736
+ type: layer.type,
4737
+ name: layer.name,
4738
+ visible: layer.visible,
4739
+ locked: layer.locked,
4740
+ opacity: layer.opacity,
4741
+ ...Object.keys(layer.meta).length > 0 ? { meta: structuredClone(layer.meta) } : {}
4742
+ };
4743
+ const sourceObject = {
4744
+ opacity: object.opacity ?? 1,
4745
+ globalCompositeOperation: object.globalCompositeOperation ?? "source-over",
4746
+ objectCaching: object.objectCaching
4747
+ };
4685
4748
  if (!object.fill && object.type !== "image") object.set({ fill: "#000000" });
4686
4749
  const stackHost = this.host(resolved);
4687
4750
  const absolute = resolved === CANVAS_MASK_TARGET || needsAbsoluteSpace(this.list(resolved));
@@ -4691,7 +4754,7 @@ var LayerMaskManager = class extends MaskStackStore {
4691
4754
  if (this.canvas.getActiveObject() === object) this.canvas.discardActiveObject();
4692
4755
  this.canvas.remove(object);
4693
4756
  this.layers.remove(layerId);
4694
- const entry = this.add(resolved, object, { name: layer.name, fit: false });
4757
+ const entry = this.add(resolved, object, { name: layer.name, fit: false, sourceLayer, sourceObject });
4695
4758
  return entry ? { target: resolved, entry } : null;
4696
4759
  } finally {
4697
4760
  this.history.endTransaction();
@@ -4769,6 +4832,11 @@ var LayerMaskManager = class extends MaskStackStore {
4769
4832
  return true;
4770
4833
  }
4771
4834
  };
4835
+ function layerTypeOf(object) {
4836
+ if (object.type === "image") return "image";
4837
+ if (object.type === "text" || object.type === "textbox" || object.type === "i-text") return "text";
4838
+ return "shape";
4839
+ }
4772
4840
 
4773
4841
  // src/gradient.ts
4774
4842
  var import_fabric21 = require("fabric");
@@ -6015,6 +6083,7 @@ var AnnotationOverlay = class {
6015
6083
  LayerManager,
6016
6084
  LayerMaskManager,
6017
6085
  LicenseManager,
6086
+ MAX_MASK_LAYERS,
6018
6087
  MaskController,
6019
6088
  MaskPresetManager,
6020
6089
  MaskRefinementError,