@overtone-art/canvas-editor-core 0.8.2 → 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,
@@ -4315,6 +4316,7 @@ function installClip(host, entries, sources, box, absolute) {
4315
4316
 
4316
4317
  // src/masks/store.ts
4317
4318
  var CANVAS_MASK_TARGET = "canvas";
4319
+ var MAX_MASK_LAYERS = 10;
4318
4320
  var DEFAULT_ENTRY = {
4319
4321
  mode: "add",
4320
4322
  linked: true,
@@ -4533,13 +4535,16 @@ var LayerMaskManager = class extends MaskStackStore {
4533
4535
  if (!host) return null;
4534
4536
  const sources = this.unwrap(target, host);
4535
4537
  const entries = this.entriesFor(target, sources);
4538
+ if (entries.length >= MAX_MASK_LAYERS) return null;
4536
4539
  const entry = {
4537
4540
  ...DEFAULT_ENTRY,
4538
4541
  id: generateId(),
4539
4542
  name: options.name ?? "Mask",
4540
4543
  ...options.mode ? { mode: options.mode } : {},
4541
4544
  ...options.linked === void 0 ? {} : { linked: options.linked },
4542
- ...options.meta ? { meta: options.meta } : {}
4545
+ ...options.meta ? { meta: options.meta } : {},
4546
+ ...options.sourceLayer ? { sourceLayer: options.sourceLayer } : {},
4547
+ ...options.sourceObject ? { sourceObject: options.sourceObject } : {}
4543
4548
  };
4544
4549
  if (target === CANVAS_MASK_TARGET) entry.linked = false;
4545
4550
  if (options.fit !== false) {
@@ -4609,6 +4614,48 @@ var LayerMaskManager = class extends MaskStackStore {
4609
4614
  this.commit(target, host, [], []);
4610
4615
  return true;
4611
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
+ }
4612
4659
  reorder(target, maskId, index) {
4613
4660
  const host = this.host(target);
4614
4661
  if (!host) return false;
@@ -4683,7 +4730,21 @@ var LayerMaskManager = class extends MaskStackStore {
4683
4730
  const below = index > 0 ? ordered[index - 1] : void 0;
4684
4731
  const resolved = target ?? (below && !below.meta.canvasMask ? below.id : CANVAS_MASK_TARGET);
4685
4732
  if (resolved === layerId) return null;
4733
+ if (this.list(resolved).length >= MAX_MASK_LAYERS) return null;
4686
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
+ };
4687
4748
  if (!object.fill && object.type !== "image") object.set({ fill: "#000000" });
4688
4749
  const stackHost = this.host(resolved);
4689
4750
  const absolute = resolved === CANVAS_MASK_TARGET || needsAbsoluteSpace(this.list(resolved));
@@ -4693,7 +4754,7 @@ var LayerMaskManager = class extends MaskStackStore {
4693
4754
  if (this.canvas.getActiveObject() === object) this.canvas.discardActiveObject();
4694
4755
  this.canvas.remove(object);
4695
4756
  this.layers.remove(layerId);
4696
- 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 });
4697
4758
  return entry ? { target: resolved, entry } : null;
4698
4759
  } finally {
4699
4760
  this.history.endTransaction();
@@ -4771,6 +4832,11 @@ var LayerMaskManager = class extends MaskStackStore {
4771
4832
  return true;
4772
4833
  }
4773
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
+ }
4774
4840
 
4775
4841
  // src/gradient.ts
4776
4842
  var import_fabric21 = require("fabric");
@@ -6017,6 +6083,7 @@ var AnnotationOverlay = class {
6017
6083
  LayerManager,
6018
6084
  LayerMaskManager,
6019
6085
  LicenseManager,
6086
+ MAX_MASK_LAYERS,
6020
6087
  MaskController,
6021
6088
  MaskPresetManager,
6022
6089
  MaskRefinementError,