@overtone-art/canvas-editor-core 0.8.2 → 0.8.4

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,52 @@ 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(
3948
+ saved?.type ?? layerTypeOf(source),
3949
+ source,
3950
+ saved?.name ?? entry.name
3951
+ );
3952
+ restored.meta = saved?.meta ? structuredClone(saved.meta) : {};
3953
+ this.layers.setVisibility(restored.id, saved?.visible ?? true);
3954
+ this.layers.setLocked(restored.id, saved?.locked ?? false);
3955
+ this.layers.setOpacity(restored.id, saved?.opacity ?? 1);
3956
+ this.layers.select(restored.id);
3957
+ this.history.save();
3958
+ return restored;
3959
+ } finally {
3960
+ this.history.endTransaction();
3961
+ }
3962
+ }
3913
3963
  reorder(target, maskId, index) {
3914
3964
  const host = this.host(target);
3915
3965
  if (!host) return false;
@@ -3984,7 +4034,21 @@ var LayerMaskManager = class extends MaskStackStore {
3984
4034
  const below = index > 0 ? ordered[index - 1] : void 0;
3985
4035
  const resolved = target ?? (below && !below.meta.canvasMask ? below.id : CANVAS_MASK_TARGET);
3986
4036
  if (resolved === layerId) return null;
4037
+ if (this.list(resolved).length >= MAX_MASK_LAYERS) return null;
3987
4038
  const object = layer.fabricObject;
4039
+ const sourceLayer = {
4040
+ type: layer.type,
4041
+ name: layer.name,
4042
+ visible: layer.visible,
4043
+ locked: layer.locked,
4044
+ opacity: layer.opacity,
4045
+ ...Object.keys(layer.meta).length > 0 ? { meta: structuredClone(layer.meta) } : {}
4046
+ };
4047
+ const sourceObject = {
4048
+ opacity: object.opacity ?? 1,
4049
+ globalCompositeOperation: object.globalCompositeOperation ?? "source-over",
4050
+ objectCaching: object.objectCaching
4051
+ };
3988
4052
  if (!object.fill && object.type !== "image") object.set({ fill: "#000000" });
3989
4053
  const stackHost = this.host(resolved);
3990
4054
  const absolute = resolved === CANVAS_MASK_TARGET || needsAbsoluteSpace(this.list(resolved));
@@ -3994,7 +4058,12 @@ var LayerMaskManager = class extends MaskStackStore {
3994
4058
  if (this.canvas.getActiveObject() === object) this.canvas.discardActiveObject();
3995
4059
  this.canvas.remove(object);
3996
4060
  this.layers.remove(layerId);
3997
- const entry = this.add(resolved, object, { name: layer.name, fit: false });
4061
+ const entry = this.add(resolved, object, {
4062
+ name: layer.name,
4063
+ fit: false,
4064
+ sourceLayer,
4065
+ sourceObject
4066
+ });
3998
4067
  return entry ? { target: resolved, entry } : null;
3999
4068
  } finally {
4000
4069
  this.history.endTransaction();
@@ -4072,6 +4141,12 @@ var LayerMaskManager = class extends MaskStackStore {
4072
4141
  return true;
4073
4142
  }
4074
4143
  };
4144
+ function layerTypeOf(object) {
4145
+ if (object.type === "image") return "image";
4146
+ if (object.type === "text" || object.type === "textbox" || object.type === "i-text")
4147
+ return "text";
4148
+ return "shape";
4149
+ }
4075
4150
 
4076
4151
  // src/gradient.ts
4077
4152
  import { Color, Gradient } from "fabric";
@@ -4178,7 +4253,7 @@ function readGradientConfig(object) {
4178
4253
  }
4179
4254
 
4180
4255
  // src/editor.ts
4181
- var MIN_ZOOM = 0.1;
4256
+ var MIN_ZOOM = 0.01;
4182
4257
  var MAX_ZOOM = 8;
4183
4258
  function isTaintedCanvasError(error) {
4184
4259
  return error instanceof DOMException && error.name === "SecurityError" || error instanceof Error && /taint|cross-origin|insecure/i.test(error.message);
@@ -5317,6 +5392,7 @@ export {
5317
5392
  LayerManager,
5318
5393
  LayerMaskManager,
5319
5394
  LicenseManager,
5395
+ MAX_MASK_LAYERS,
5320
5396
  MaskController,
5321
5397
  MaskPresetManager,
5322
5398
  MaskRefinementError,