@overtone-art/canvas-editor-core 0.3.0 → 0.3.2
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.d.mts +63 -1
- package/dist/index.d.ts +63 -1
- package/dist/index.global.js +51 -51
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +103 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +100 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
CropController: () => CropController,
|
|
27
27
|
DEFAULT_LAYER_SHADOW: () => DEFAULT_LAYER_SHADOW,
|
|
28
28
|
DEFAULT_PATTERN_CONFIG: () => DEFAULT_PATTERN_CONFIG,
|
|
29
|
+
DEFAULT_SELECTION_STYLE: () => DEFAULT_SELECTION_STYLE,
|
|
29
30
|
DEFAULT_TEXT_CURVE: () => DEFAULT_TEXT_CURVE,
|
|
30
31
|
EventEmitter: () => EventEmitter,
|
|
31
32
|
FontRegistry: () => FontRegistry,
|
|
@@ -47,7 +48,9 @@ __export(index_exports, {
|
|
|
47
48
|
UnitConverter: () => UnitConverter,
|
|
48
49
|
applyAspectLock: () => applyAspectLock,
|
|
49
50
|
applyLayerShadow: () => applyLayerShadow,
|
|
51
|
+
applyObjectSelectionStyle: () => applyObjectSelectionStyle,
|
|
50
52
|
applyPatternLocks: () => applyPatternLocks,
|
|
53
|
+
applySelectionStyle: () => applySelectionStyle,
|
|
51
54
|
buildCurvePathData: () => buildCurvePathData,
|
|
52
55
|
buildPatternDataURL: () => buildPatternDataURL,
|
|
53
56
|
captureLocks: () => captureLocks,
|
|
@@ -304,6 +307,38 @@ var LayerManager = class {
|
|
|
304
307
|
this.emitChanged();
|
|
305
308
|
this.onPropertyChanged?.();
|
|
306
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* Patch a layer's host metadata. A key whose value is `undefined` is removed.
|
|
312
|
+
*
|
|
313
|
+
* `meta` is part of `LayerData` and is serialized, so a host that assigns
|
|
314
|
+
* `layer.meta.x` directly gets neither of the two things every other setter
|
|
315
|
+
* here provides: `layers:changed` (so `useLayers()` keeps returning the old
|
|
316
|
+
* meta) and the history checkpoint (so an undo silently reverts the write —
|
|
317
|
+
* the state IS versioned, it was just never committed at the moment it
|
|
318
|
+
* changed). Going through this method is what makes metadata behave like
|
|
319
|
+
* every other layer property.
|
|
320
|
+
*/
|
|
321
|
+
setMeta(id, patch) {
|
|
322
|
+
const layer = this.get(id);
|
|
323
|
+
if (!layer) return;
|
|
324
|
+
const next = { ...layer.meta };
|
|
325
|
+
let changed = false;
|
|
326
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
327
|
+
if (value === void 0) {
|
|
328
|
+
if (key in next) {
|
|
329
|
+
delete next[key];
|
|
330
|
+
changed = true;
|
|
331
|
+
}
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (next[key] !== value) changed = true;
|
|
335
|
+
next[key] = value;
|
|
336
|
+
}
|
|
337
|
+
if (!changed) return;
|
|
338
|
+
layer.meta = next;
|
|
339
|
+
this.emitChanged();
|
|
340
|
+
this.onPropertyChanged?.();
|
|
341
|
+
}
|
|
307
342
|
clear() {
|
|
308
343
|
for (const layer of this.layers) {
|
|
309
344
|
this.canvas.remove(layer.fabricObject);
|
|
@@ -1657,6 +1692,43 @@ function applyLayerShadow(object, config) {
|
|
|
1657
1692
|
});
|
|
1658
1693
|
}
|
|
1659
1694
|
|
|
1695
|
+
// src/selection-style.ts
|
|
1696
|
+
var DEFAULT_SELECTION_STYLE = {
|
|
1697
|
+
borderColor: "#c9a96e",
|
|
1698
|
+
cornerColor: "#c9a96e",
|
|
1699
|
+
cornerStrokeColor: "#101010",
|
|
1700
|
+
cornerSize: 11,
|
|
1701
|
+
cornerStyle: "circle",
|
|
1702
|
+
borderWidth: 1,
|
|
1703
|
+
borderDashArray: null,
|
|
1704
|
+
padding: 0,
|
|
1705
|
+
marqueeFill: "rgba(201, 169, 110, 0.12)"
|
|
1706
|
+
};
|
|
1707
|
+
function applyObjectSelectionStyle(object, style, zoom) {
|
|
1708
|
+
const scale = zoom > 0 ? 1 / zoom : 1;
|
|
1709
|
+
object.set({
|
|
1710
|
+
cornerSize: style.cornerSize * scale,
|
|
1711
|
+
cornerStyle: style.cornerStyle,
|
|
1712
|
+
cornerColor: style.cornerColor,
|
|
1713
|
+
cornerStrokeColor: style.cornerStrokeColor,
|
|
1714
|
+
// A filled handle is what makes the stroke colour visible at all.
|
|
1715
|
+
transparentCorners: false,
|
|
1716
|
+
borderColor: style.borderColor,
|
|
1717
|
+
borderScaleFactor: style.borderWidth * scale,
|
|
1718
|
+
borderDashArray: style.borderDashArray?.map((segment) => segment * scale) ?? null,
|
|
1719
|
+
padding: style.padding * scale
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
function applySelectionStyle(canvas, style, zoom) {
|
|
1723
|
+
for (const object of canvas.getObjects()) applyObjectSelectionStyle(object, style, zoom);
|
|
1724
|
+
const active = canvas.getActiveObject();
|
|
1725
|
+
if (active) applyObjectSelectionStyle(active, style, zoom);
|
|
1726
|
+
canvas.selectionColor = style.marqueeFill;
|
|
1727
|
+
canvas.selectionBorderColor = style.borderColor;
|
|
1728
|
+
canvas.selectionLineWidth = style.borderWidth * (zoom > 0 ? 1 / zoom : 1);
|
|
1729
|
+
canvas.requestRenderAll();
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1660
1732
|
// src/transform.ts
|
|
1661
1733
|
var SIDE_CONTROLS = ["ml", "mr", "mt", "mb"];
|
|
1662
1734
|
function applyAspectLock(object, locked) {
|
|
@@ -2664,6 +2736,7 @@ var CanvasEditor = class {
|
|
|
2664
2736
|
fileAdapter;
|
|
2665
2737
|
imageProvider;
|
|
2666
2738
|
zoomLevel = 1;
|
|
2739
|
+
selectionStyle = { ...DEFAULT_SELECTION_STYLE };
|
|
2667
2740
|
mockup = null;
|
|
2668
2741
|
// The design's configured background. The live canvas background is forced
|
|
2669
2742
|
// transparent while a mockup preview is shown, so this is the source of truth
|
|
@@ -2711,6 +2784,7 @@ var CanvasEditor = class {
|
|
|
2711
2784
|
this.curves = new TextCurveManager(this.canvas, this.layers, this.history, this.events);
|
|
2712
2785
|
this.maskPresets = new MaskPresetManager(this.canvas, this.layers, this.history, this.events);
|
|
2713
2786
|
this.setupCanvasEvents();
|
|
2787
|
+
this.refreshSelectionStyle();
|
|
2714
2788
|
this.history.saveImmediate();
|
|
2715
2789
|
this.pages = new ProjectManager(this);
|
|
2716
2790
|
this.masks = new MaskController(this);
|
|
@@ -3381,6 +3455,7 @@ var CanvasEditor = class {
|
|
|
3381
3455
|
const next = clamp(round2(level), MIN_ZOOM, MAX_ZOOM);
|
|
3382
3456
|
if (next === this.zoomLevel) return;
|
|
3383
3457
|
this.zoomLevel = next;
|
|
3458
|
+
this.refreshSelectionStyle();
|
|
3384
3459
|
this.events.emit("zoom:changed", { zoom: next });
|
|
3385
3460
|
}
|
|
3386
3461
|
/** @deprecated use setZoom — kept for backward compatibility. */
|
|
@@ -3529,8 +3604,31 @@ var CanvasEditor = class {
|
|
|
3529
3604
|
this.events.removeAllListeners();
|
|
3530
3605
|
this.canvas.dispose();
|
|
3531
3606
|
}
|
|
3607
|
+
// ─── Selection style ────────────────────────────────
|
|
3608
|
+
/** Current look of the selection frame and its handles. */
|
|
3609
|
+
getSelectionStyle() {
|
|
3610
|
+
return { ...this.selectionStyle };
|
|
3611
|
+
}
|
|
3612
|
+
/**
|
|
3613
|
+
* Restyles the selection frame and resize handles. Sizes are in screen
|
|
3614
|
+
* pixels and stay constant across zoom levels (see `SelectionStyle`).
|
|
3615
|
+
*/
|
|
3616
|
+
setSelectionStyle(style) {
|
|
3617
|
+
this.selectionStyle = { ...this.selectionStyle, ...style };
|
|
3618
|
+
this.refreshSelectionStyle();
|
|
3619
|
+
}
|
|
3620
|
+
refreshSelectionStyle() {
|
|
3621
|
+
applySelectionStyle(this.canvas, this.selectionStyle, this.zoomLevel);
|
|
3622
|
+
}
|
|
3532
3623
|
// ─── Private ────────────────────────────────────────
|
|
3533
3624
|
setupCanvasEvents() {
|
|
3625
|
+
this.canvas.on("object:added", (e) => {
|
|
3626
|
+
if (e.target) applyObjectSelectionStyle(e.target, this.selectionStyle, this.zoomLevel);
|
|
3627
|
+
});
|
|
3628
|
+
const styleActive = () => {
|
|
3629
|
+
const active = this.canvas.getActiveObject();
|
|
3630
|
+
if (active) applyObjectSelectionStyle(active, this.selectionStyle, this.zoomLevel);
|
|
3631
|
+
};
|
|
3534
3632
|
this.canvas.on("object:modified", (e) => {
|
|
3535
3633
|
if (!e.target) return;
|
|
3536
3634
|
const layer = this.layers.findByObject(e.target);
|
|
@@ -3540,10 +3638,12 @@ var CanvasEditor = class {
|
|
|
3540
3638
|
}
|
|
3541
3639
|
});
|
|
3542
3640
|
this.canvas.on("selection:created", (e) => {
|
|
3641
|
+
styleActive();
|
|
3543
3642
|
const selected = (e.selected ?? []).map((obj) => this.layers.findByObject(obj)?.id).filter((id) => id !== void 0);
|
|
3544
3643
|
this.events.emit("selection:changed", { selected });
|
|
3545
3644
|
});
|
|
3546
3645
|
this.canvas.on("selection:updated", (e) => {
|
|
3646
|
+
styleActive();
|
|
3547
3647
|
const selected = (e.selected ?? []).map((obj) => this.layers.findByObject(obj)?.id).filter((id) => id !== void 0);
|
|
3548
3648
|
this.events.emit("selection:changed", { selected });
|
|
3549
3649
|
});
|
|
@@ -3625,6 +3725,7 @@ var AnnotationOverlay = class {
|
|
|
3625
3725
|
CropController,
|
|
3626
3726
|
DEFAULT_LAYER_SHADOW,
|
|
3627
3727
|
DEFAULT_PATTERN_CONFIG,
|
|
3728
|
+
DEFAULT_SELECTION_STYLE,
|
|
3628
3729
|
DEFAULT_TEXT_CURVE,
|
|
3629
3730
|
EventEmitter,
|
|
3630
3731
|
FontRegistry,
|
|
@@ -3646,7 +3747,9 @@ var AnnotationOverlay = class {
|
|
|
3646
3747
|
UnitConverter,
|
|
3647
3748
|
applyAspectLock,
|
|
3648
3749
|
applyLayerShadow,
|
|
3750
|
+
applyObjectSelectionStyle,
|
|
3649
3751
|
applyPatternLocks,
|
|
3752
|
+
applySelectionStyle,
|
|
3650
3753
|
buildCurvePathData,
|
|
3651
3754
|
buildPatternDataURL,
|
|
3652
3755
|
captureLocks,
|