@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.mjs CHANGED
@@ -3616,6 +3616,7 @@ function installClip(host, entries, sources, box, absolute) {
3616
3616
 
3617
3617
  // src/masks/store.ts
3618
3618
  var CANVAS_MASK_TARGET = "canvas";
3619
+ var MAX_MASK_LAYERS = 10;
3619
3620
  var DEFAULT_ENTRY = {
3620
3621
  mode: "add",
3621
3622
  linked: true,
@@ -3834,13 +3835,16 @@ var LayerMaskManager = class extends MaskStackStore {
3834
3835
  if (!host) return null;
3835
3836
  const sources = this.unwrap(target, host);
3836
3837
  const entries = this.entriesFor(target, sources);
3838
+ if (entries.length >= MAX_MASK_LAYERS) return null;
3837
3839
  const entry = {
3838
3840
  ...DEFAULT_ENTRY,
3839
3841
  id: generateId(),
3840
3842
  name: options.name ?? "Mask",
3841
3843
  ...options.mode ? { mode: options.mode } : {},
3842
3844
  ...options.linked === void 0 ? {} : { linked: options.linked },
3843
- ...options.meta ? { meta: options.meta } : {}
3845
+ ...options.meta ? { meta: options.meta } : {},
3846
+ ...options.sourceLayer ? { sourceLayer: options.sourceLayer } : {},
3847
+ ...options.sourceObject ? { sourceObject: options.sourceObject } : {}
3844
3848
  };
3845
3849
  if (target === CANVAS_MASK_TARGET) entry.linked = false;
3846
3850
  if (options.fit !== false) {
@@ -3910,6 +3914,48 @@ var LayerMaskManager = class extends MaskStackStore {
3910
3914
  this.commit(target, host, [], []);
3911
3915
  return true;
3912
3916
  }
3917
+ /**
3918
+ * Remove one mask from its host and restore it as an ordinary canvas layer.
3919
+ * Its shape, text, paint and transform survive; only the mask relationship is
3920
+ * removed, so it can be edited through every normal layer property panel.
3921
+ */
3922
+ unmask(target, maskId) {
3923
+ const host = this.host(target);
3924
+ if (!host) return null;
3925
+ const entries = [...this.list(target)];
3926
+ const index = entries.findIndex((entry2) => entry2.id === maskId);
3927
+ if (index === -1) return null;
3928
+ const sources = this.unwrap(target, host);
3929
+ const source = sources[index];
3930
+ if (!source) return null;
3931
+ const entry = entries[index];
3932
+ this.history.beginTransaction();
3933
+ try {
3934
+ this.endEdit(false);
3935
+ entries.splice(index, 1);
3936
+ sources.splice(index, 1);
3937
+ if (!source.absolutePositioned && target !== CANVAS_MASK_TARGET) toCanvasSpace(source, host);
3938
+ source.set({
3939
+ absolutePositioned: false,
3940
+ opacity: entry.sourceObject?.opacity ?? 1,
3941
+ globalCompositeOperation: entry.sourceObject?.globalCompositeOperation ?? "source-over",
3942
+ objectCaching: entry.sourceObject?.objectCaching ?? true
3943
+ });
3944
+ if (this.selected?.maskId === maskId) this.select(null, null);
3945
+ this.commit(target, host, entries, sources, false);
3946
+ const saved = entry.sourceLayer;
3947
+ const restored = this.layers.add(saved?.type ?? layerTypeOf(source), source, saved?.name ?? entry.name);
3948
+ restored.meta = saved?.meta ? structuredClone(saved.meta) : {};
3949
+ this.layers.setVisibility(restored.id, saved?.visible ?? true);
3950
+ this.layers.setLocked(restored.id, saved?.locked ?? false);
3951
+ this.layers.setOpacity(restored.id, saved?.opacity ?? 1);
3952
+ this.layers.select(restored.id);
3953
+ this.history.save();
3954
+ return restored;
3955
+ } finally {
3956
+ this.history.endTransaction();
3957
+ }
3958
+ }
3913
3959
  reorder(target, maskId, index) {
3914
3960
  const host = this.host(target);
3915
3961
  if (!host) return false;
@@ -3984,7 +4030,21 @@ var LayerMaskManager = class extends MaskStackStore {
3984
4030
  const below = index > 0 ? ordered[index - 1] : void 0;
3985
4031
  const resolved = target ?? (below && !below.meta.canvasMask ? below.id : CANVAS_MASK_TARGET);
3986
4032
  if (resolved === layerId) return null;
4033
+ if (this.list(resolved).length >= MAX_MASK_LAYERS) return null;
3987
4034
  const object = layer.fabricObject;
4035
+ const sourceLayer = {
4036
+ type: layer.type,
4037
+ name: layer.name,
4038
+ visible: layer.visible,
4039
+ locked: layer.locked,
4040
+ opacity: layer.opacity,
4041
+ ...Object.keys(layer.meta).length > 0 ? { meta: structuredClone(layer.meta) } : {}
4042
+ };
4043
+ const sourceObject = {
4044
+ opacity: object.opacity ?? 1,
4045
+ globalCompositeOperation: object.globalCompositeOperation ?? "source-over",
4046
+ objectCaching: object.objectCaching
4047
+ };
3988
4048
  if (!object.fill && object.type !== "image") object.set({ fill: "#000000" });
3989
4049
  const stackHost = this.host(resolved);
3990
4050
  const absolute = resolved === CANVAS_MASK_TARGET || needsAbsoluteSpace(this.list(resolved));
@@ -3994,7 +4054,7 @@ var LayerMaskManager = class extends MaskStackStore {
3994
4054
  if (this.canvas.getActiveObject() === object) this.canvas.discardActiveObject();
3995
4055
  this.canvas.remove(object);
3996
4056
  this.layers.remove(layerId);
3997
- const entry = this.add(resolved, object, { name: layer.name, fit: false });
4057
+ const entry = this.add(resolved, object, { name: layer.name, fit: false, sourceLayer, sourceObject });
3998
4058
  return entry ? { target: resolved, entry } : null;
3999
4059
  } finally {
4000
4060
  this.history.endTransaction();
@@ -4072,6 +4132,11 @@ var LayerMaskManager = class extends MaskStackStore {
4072
4132
  return true;
4073
4133
  }
4074
4134
  };
4135
+ function layerTypeOf(object) {
4136
+ if (object.type === "image") return "image";
4137
+ if (object.type === "text" || object.type === "textbox" || object.type === "i-text") return "text";
4138
+ return "shape";
4139
+ }
4075
4140
 
4076
4141
  // src/gradient.ts
4077
4142
  import { Color, Gradient } from "fabric";
@@ -5317,6 +5382,7 @@ export {
5317
5382
  LayerManager,
5318
5383
  LayerMaskManager,
5319
5384
  LicenseManager,
5385
+ MAX_MASK_LAYERS,
5320
5386
  MaskController,
5321
5387
  MaskPresetManager,
5322
5388
  MaskRefinementError,