@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.mjs
CHANGED
|
@@ -231,6 +231,38 @@ var LayerManager = class {
|
|
|
231
231
|
this.emitChanged();
|
|
232
232
|
this.onPropertyChanged?.();
|
|
233
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Patch a layer's host metadata. A key whose value is `undefined` is removed.
|
|
236
|
+
*
|
|
237
|
+
* `meta` is part of `LayerData` and is serialized, so a host that assigns
|
|
238
|
+
* `layer.meta.x` directly gets neither of the two things every other setter
|
|
239
|
+
* here provides: `layers:changed` (so `useLayers()` keeps returning the old
|
|
240
|
+
* meta) and the history checkpoint (so an undo silently reverts the write —
|
|
241
|
+
* the state IS versioned, it was just never committed at the moment it
|
|
242
|
+
* changed). Going through this method is what makes metadata behave like
|
|
243
|
+
* every other layer property.
|
|
244
|
+
*/
|
|
245
|
+
setMeta(id, patch) {
|
|
246
|
+
const layer = this.get(id);
|
|
247
|
+
if (!layer) return;
|
|
248
|
+
const next = { ...layer.meta };
|
|
249
|
+
let changed = false;
|
|
250
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
251
|
+
if (value === void 0) {
|
|
252
|
+
if (key in next) {
|
|
253
|
+
delete next[key];
|
|
254
|
+
changed = true;
|
|
255
|
+
}
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (next[key] !== value) changed = true;
|
|
259
|
+
next[key] = value;
|
|
260
|
+
}
|
|
261
|
+
if (!changed) return;
|
|
262
|
+
layer.meta = next;
|
|
263
|
+
this.emitChanged();
|
|
264
|
+
this.onPropertyChanged?.();
|
|
265
|
+
}
|
|
234
266
|
clear() {
|
|
235
267
|
for (const layer of this.layers) {
|
|
236
268
|
this.canvas.remove(layer.fabricObject);
|
|
@@ -1584,6 +1616,43 @@ function applyLayerShadow(object, config) {
|
|
|
1584
1616
|
});
|
|
1585
1617
|
}
|
|
1586
1618
|
|
|
1619
|
+
// src/selection-style.ts
|
|
1620
|
+
var DEFAULT_SELECTION_STYLE = {
|
|
1621
|
+
borderColor: "#c9a96e",
|
|
1622
|
+
cornerColor: "#c9a96e",
|
|
1623
|
+
cornerStrokeColor: "#101010",
|
|
1624
|
+
cornerSize: 11,
|
|
1625
|
+
cornerStyle: "circle",
|
|
1626
|
+
borderWidth: 1,
|
|
1627
|
+
borderDashArray: null,
|
|
1628
|
+
padding: 0,
|
|
1629
|
+
marqueeFill: "rgba(201, 169, 110, 0.12)"
|
|
1630
|
+
};
|
|
1631
|
+
function applyObjectSelectionStyle(object, style, zoom) {
|
|
1632
|
+
const scale = zoom > 0 ? 1 / zoom : 1;
|
|
1633
|
+
object.set({
|
|
1634
|
+
cornerSize: style.cornerSize * scale,
|
|
1635
|
+
cornerStyle: style.cornerStyle,
|
|
1636
|
+
cornerColor: style.cornerColor,
|
|
1637
|
+
cornerStrokeColor: style.cornerStrokeColor,
|
|
1638
|
+
// A filled handle is what makes the stroke colour visible at all.
|
|
1639
|
+
transparentCorners: false,
|
|
1640
|
+
borderColor: style.borderColor,
|
|
1641
|
+
borderScaleFactor: style.borderWidth * scale,
|
|
1642
|
+
borderDashArray: style.borderDashArray?.map((segment) => segment * scale) ?? null,
|
|
1643
|
+
padding: style.padding * scale
|
|
1644
|
+
});
|
|
1645
|
+
}
|
|
1646
|
+
function applySelectionStyle(canvas, style, zoom) {
|
|
1647
|
+
for (const object of canvas.getObjects()) applyObjectSelectionStyle(object, style, zoom);
|
|
1648
|
+
const active = canvas.getActiveObject();
|
|
1649
|
+
if (active) applyObjectSelectionStyle(active, style, zoom);
|
|
1650
|
+
canvas.selectionColor = style.marqueeFill;
|
|
1651
|
+
canvas.selectionBorderColor = style.borderColor;
|
|
1652
|
+
canvas.selectionLineWidth = style.borderWidth * (zoom > 0 ? 1 / zoom : 1);
|
|
1653
|
+
canvas.requestRenderAll();
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1587
1656
|
// src/transform.ts
|
|
1588
1657
|
var SIDE_CONTROLS = ["ml", "mr", "mt", "mb"];
|
|
1589
1658
|
function applyAspectLock(object, locked) {
|
|
@@ -2340,6 +2409,7 @@ var CanvasEditor = class {
|
|
|
2340
2409
|
fileAdapter;
|
|
2341
2410
|
imageProvider;
|
|
2342
2411
|
zoomLevel = 1;
|
|
2412
|
+
selectionStyle = { ...DEFAULT_SELECTION_STYLE };
|
|
2343
2413
|
mockup = null;
|
|
2344
2414
|
// The design's configured background. The live canvas background is forced
|
|
2345
2415
|
// transparent while a mockup preview is shown, so this is the source of truth
|
|
@@ -2387,6 +2457,7 @@ var CanvasEditor = class {
|
|
|
2387
2457
|
this.curves = new TextCurveManager(this.canvas, this.layers, this.history, this.events);
|
|
2388
2458
|
this.maskPresets = new MaskPresetManager(this.canvas, this.layers, this.history, this.events);
|
|
2389
2459
|
this.setupCanvasEvents();
|
|
2460
|
+
this.refreshSelectionStyle();
|
|
2390
2461
|
this.history.saveImmediate();
|
|
2391
2462
|
this.pages = new ProjectManager(this);
|
|
2392
2463
|
this.masks = new MaskController(this);
|
|
@@ -3057,6 +3128,7 @@ var CanvasEditor = class {
|
|
|
3057
3128
|
const next = clamp(round2(level), MIN_ZOOM, MAX_ZOOM);
|
|
3058
3129
|
if (next === this.zoomLevel) return;
|
|
3059
3130
|
this.zoomLevel = next;
|
|
3131
|
+
this.refreshSelectionStyle();
|
|
3060
3132
|
this.events.emit("zoom:changed", { zoom: next });
|
|
3061
3133
|
}
|
|
3062
3134
|
/** @deprecated use setZoom — kept for backward compatibility. */
|
|
@@ -3205,8 +3277,31 @@ var CanvasEditor = class {
|
|
|
3205
3277
|
this.events.removeAllListeners();
|
|
3206
3278
|
this.canvas.dispose();
|
|
3207
3279
|
}
|
|
3280
|
+
// ─── Selection style ────────────────────────────────
|
|
3281
|
+
/** Current look of the selection frame and its handles. */
|
|
3282
|
+
getSelectionStyle() {
|
|
3283
|
+
return { ...this.selectionStyle };
|
|
3284
|
+
}
|
|
3285
|
+
/**
|
|
3286
|
+
* Restyles the selection frame and resize handles. Sizes are in screen
|
|
3287
|
+
* pixels and stay constant across zoom levels (see `SelectionStyle`).
|
|
3288
|
+
*/
|
|
3289
|
+
setSelectionStyle(style) {
|
|
3290
|
+
this.selectionStyle = { ...this.selectionStyle, ...style };
|
|
3291
|
+
this.refreshSelectionStyle();
|
|
3292
|
+
}
|
|
3293
|
+
refreshSelectionStyle() {
|
|
3294
|
+
applySelectionStyle(this.canvas, this.selectionStyle, this.zoomLevel);
|
|
3295
|
+
}
|
|
3208
3296
|
// ─── Private ────────────────────────────────────────
|
|
3209
3297
|
setupCanvasEvents() {
|
|
3298
|
+
this.canvas.on("object:added", (e) => {
|
|
3299
|
+
if (e.target) applyObjectSelectionStyle(e.target, this.selectionStyle, this.zoomLevel);
|
|
3300
|
+
});
|
|
3301
|
+
const styleActive = () => {
|
|
3302
|
+
const active = this.canvas.getActiveObject();
|
|
3303
|
+
if (active) applyObjectSelectionStyle(active, this.selectionStyle, this.zoomLevel);
|
|
3304
|
+
};
|
|
3210
3305
|
this.canvas.on("object:modified", (e) => {
|
|
3211
3306
|
if (!e.target) return;
|
|
3212
3307
|
const layer = this.layers.findByObject(e.target);
|
|
@@ -3216,10 +3311,12 @@ var CanvasEditor = class {
|
|
|
3216
3311
|
}
|
|
3217
3312
|
});
|
|
3218
3313
|
this.canvas.on("selection:created", (e) => {
|
|
3314
|
+
styleActive();
|
|
3219
3315
|
const selected = (e.selected ?? []).map((obj) => this.layers.findByObject(obj)?.id).filter((id) => id !== void 0);
|
|
3220
3316
|
this.events.emit("selection:changed", { selected });
|
|
3221
3317
|
});
|
|
3222
3318
|
this.canvas.on("selection:updated", (e) => {
|
|
3319
|
+
styleActive();
|
|
3223
3320
|
const selected = (e.selected ?? []).map((obj) => this.layers.findByObject(obj)?.id).filter((id) => id !== void 0);
|
|
3224
3321
|
this.events.emit("selection:changed", { selected });
|
|
3225
3322
|
});
|
|
@@ -3300,6 +3397,7 @@ export {
|
|
|
3300
3397
|
CropController,
|
|
3301
3398
|
DEFAULT_LAYER_SHADOW,
|
|
3302
3399
|
DEFAULT_PATTERN_CONFIG,
|
|
3400
|
+
DEFAULT_SELECTION_STYLE,
|
|
3303
3401
|
DEFAULT_TEXT_CURVE,
|
|
3304
3402
|
EventEmitter,
|
|
3305
3403
|
FontRegistry,
|
|
@@ -3321,7 +3419,9 @@ export {
|
|
|
3321
3419
|
UnitConverter,
|
|
3322
3420
|
applyAspectLock,
|
|
3323
3421
|
applyLayerShadow,
|
|
3422
|
+
applyObjectSelectionStyle,
|
|
3324
3423
|
applyPatternLocks,
|
|
3424
|
+
applySelectionStyle,
|
|
3325
3425
|
buildCurvePathData,
|
|
3326
3426
|
buildPatternDataURL,
|
|
3327
3427
|
captureLocks,
|