@pixerate/editor 0.187.0 → 0.188.0

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.
@@ -298,6 +298,8 @@ import {
298
298
  selectionArea,
299
299
  selectionFromCoverage,
300
300
  selectionFromPixels,
301
+ selectionFromRegion,
302
+ selectionFromTiles,
301
303
  selectionToCoverage,
302
304
  selectionToPixels,
303
305
  selectionValueAt,
@@ -370,7 +372,7 @@ import {
370
372
  writePsd,
371
373
  xyToTempTint,
372
374
  xyToUv
373
- } from "../chunk-FW7N64XK.js";
375
+ } from "../chunk-IGMNJM2H.js";
374
376
  import {
375
377
  parseCssColor
376
378
  } from "../chunk-3CI7FRMK.js";
@@ -2835,8 +2837,33 @@ var TypeToolGesture = class {
2835
2837
 
2836
2838
  // src/image-editor/selection/shapes.ts
2837
2839
  function polygonCoverage(points, width, height, antiAlias = true) {
2840
+ const { box, coverage } = polygonCoverageBox(points, width, height, antiAlias);
2841
+ if (!box || box.width === width && box.height === height) return box ? coverage : new Float32Array(width * height);
2838
2842
  const m = new Float32Array(width * height);
2839
- if (points.length < 3 || width <= 0 || height <= 0) return m;
2843
+ for (let y = 0; y < box.height; y++) m.set(coverage.subarray(y * box.width, (y + 1) * box.width), (box.y + y) * width + box.x);
2844
+ return m;
2845
+ }
2846
+ function polygonCoverageBox(points, width, height, antiAlias = true) {
2847
+ const none = { box: null, coverage: new Float32Array(0) };
2848
+ if (points.length < 3 || width <= 0 || height <= 0) return none;
2849
+ let minX = Infinity;
2850
+ let minY = Infinity;
2851
+ let maxX = -Infinity;
2852
+ let maxY = -Infinity;
2853
+ for (const p of points) {
2854
+ if (!Number.isFinite(p.x) || !Number.isFinite(p.y)) continue;
2855
+ minX = Math.min(minX, p.x);
2856
+ minY = Math.min(minY, p.y);
2857
+ maxX = Math.max(maxX, p.x);
2858
+ maxY = Math.max(maxY, p.y);
2859
+ }
2860
+ const bx0 = Math.max(0, Math.floor(minX));
2861
+ const by0 = Math.max(0, Math.floor(minY));
2862
+ const bx1 = Math.min(width, Math.ceil(maxX));
2863
+ const by1 = Math.min(height, Math.ceil(maxY));
2864
+ if (!(bx1 > bx0 && by1 > by0)) return none;
2865
+ const bw = bx1 - bx0;
2866
+ const m = new Float32Array(bw * (by1 - by0));
2840
2867
  const sub2 = antiAlias ? 4 : 1;
2841
2868
  const edges = [];
2842
2869
  for (let i = 0; i < points.length; i++) {
@@ -2850,8 +2877,8 @@ function polygonCoverage(points, width, height, antiAlias = true) {
2850
2877
  let next = 0;
2851
2878
  let active = [];
2852
2879
  const xs = [];
2853
- for (let py = 0; py < height; py++) {
2854
- const row = py * width;
2880
+ for (let py = by0; py < by1; py++) {
2881
+ const row = (py - by0) * bw - bx0;
2855
2882
  for (let s = 0; s < sub2; s++) {
2856
2883
  const y = py + (s + 0.5) / sub2;
2857
2884
  while (next < edges.length && edges[next].top <= y) active.push(edges[next++]);
@@ -2881,15 +2908,14 @@ function polygonCoverage(points, width, height, antiAlias = true) {
2881
2908
  }
2882
2909
  }
2883
2910
  for (let i = 0; i < m.length; i++) if (m[i] > 1) m[i] = 1;
2884
- return m;
2911
+ return { box: { x: bx0, y: by0, width: bw, height: by1 - by0 }, coverage: m };
2885
2912
  }
2886
- function toMask(width, height, coverage) {
2913
+ function polygonSelection(width, height, points, options = {}) {
2914
+ const { box, coverage } = polygonCoverageBox(points, width, height, options.antiAlias ?? true);
2915
+ if (!box) return createSelectionMask(width, height);
2887
2916
  const out = new Uint8Array(coverage.length);
2888
2917
  for (let i = 0; i < out.length; i++) out[i] = coverageToByte(coverage[i]);
2889
- return createSelectionMask(width, height, out);
2890
- }
2891
- function polygonSelection(width, height, points, options = {}) {
2892
- return toMask(width, height, polygonCoverage(points, width, height, options.antiAlias ?? true));
2918
+ return selectionFromRegion(width, height, box, out);
2893
2919
  }
2894
2920
  function normalizeRect(rect) {
2895
2921
  const x = rect.width < 0 ? rect.x + rect.width : rect.x;
@@ -3531,9 +3557,7 @@ function selectionRing(sel, width, location) {
3531
3557
  var DEFAULT_CHANNEL_COLOR = "#ff0000";
3532
3558
  function describeChannel(channel) {
3533
3559
  const { mask, ...rest } = channel;
3534
- let sum = 0;
3535
- for (let i = 0; i < mask.data.length; i++) sum += mask.data[i];
3536
- const percent = Math.round(sum / 255 / Math.max(1, mask.data.length) * 1e4) / 100;
3560
+ const percent = Math.round(selectionArea(mask) / Math.max(1, mask.width * mask.height) * 1e4) / 100;
3537
3561
  return { ...rest, bounds: mask.bounds, percent };
3538
3562
  }
3539
3563
  function serializeChannels(channels) {
@@ -4144,8 +4168,7 @@ var FreeTransformSession = class {
4144
4168
  const result = part.base ? compositeSurfaceOver(part.base, moved) : moved;
4145
4169
  if (part.what === "selection") {
4146
4170
  const { width, height } = this.host.canvas();
4147
- const data = new Uint8Array(readRegion(result, { x: 0, y: 0, width, height }).buffer);
4148
- const next = createSelectionMask(width, height, data);
4171
+ const next = selectionFromTiles(width, height, result);
4149
4172
  selection = next.bounds ? next : null;
4150
4173
  } else if (part.what === "pixels") {
4151
4174
  layers = mapLayer(layers, targetId, (l) => {
@@ -5471,14 +5494,18 @@ var ImageEditorController = class {
5471
5494
  this.trimHistoryBytes();
5472
5495
  }
5473
5496
  /**
5474
- * Bytes of pixel tiles held only by undo / redo steps (not by the current state). The oldest
5475
- * undo steps are dropped while it exceeds `maxHistoryBytes`.
5497
+ * Bytes of pixel, selection and channel tiles held only by undo / redo steps (not by the
5498
+ * current state). The oldest undo steps are dropped while it exceeds `maxHistoryBytes`.
5476
5499
  */
5477
5500
  get historyBytes() {
5478
5501
  const live = /* @__PURE__ */ new Set();
5479
5502
  collectStateTiles(this.state.layers, live);
5503
+ collectSelectionTiles(this.state.selection, this.state.channels, live);
5480
5504
  const held = /* @__PURE__ */ new Set();
5481
- for (const e of [...this.undoStack, ...this.redoStack]) collectStateTiles(e.layers, held);
5505
+ for (const e of [...this.undoStack, ...this.redoStack]) {
5506
+ collectStateTiles(e.layers, held);
5507
+ collectSelectionTiles(e.selection, e.channels, held);
5508
+ }
5482
5509
  let n = 0;
5483
5510
  for (const t of held) if (!live.has(t)) n += t.data.byteLength;
5484
5511
  return n;
@@ -7376,7 +7403,7 @@ var ImageEditorController = class {
7376
7403
  /** @internal Shows a stroke's live surface (no history). */
7377
7404
  _strokeUpdate(layerId, channel, surface, rects) {
7378
7405
  if (channel === "quick-mask") {
7379
- this.state.selection = this.selectionFromSurface(surface, this.state.selection ?? null, rects);
7406
+ this.state.selection = this.selectionFromSurface(surface);
7380
7407
  this.notify();
7381
7408
  return;
7382
7409
  }
@@ -8454,35 +8481,18 @@ var ImageEditorController = class {
8454
8481
  const { width, height } = this.naturalSize;
8455
8482
  const sel = this.state.selection;
8456
8483
  if (!sel?.bounds) return emptySurface(1, 0);
8457
- const sized = sel.width === width && sel.height === height ? sel : resizeSelection(sel, width, height);
8458
- return surfaceFromPixels({ width, height, data: sized.data }, 1, 0, 0, 0);
8484
+ return (sel.width === width && sel.height === height ? sel : resizeSelection(sel, width, height)).surface;
8459
8485
  }
8460
- /** The selection a painted Quick Mask surface stands for (`rects` changed since `base`). */
8461
- selectionFromSurface(surface, base = null, rects) {
8486
+ /** The selection a painted Quick Mask surface stands for (it shares the surface's tiles). */
8487
+ selectionFromSurface(surface) {
8462
8488
  const { width, height } = this.naturalSize;
8463
- let data;
8464
- if (base && rects && base.width === width && base.height === height) {
8465
- data = new Uint8Array(base.data);
8466
- for (const r of rects) {
8467
- const x0 = Math.max(0, Math.floor(r.x));
8468
- const y0 = Math.max(0, Math.floor(r.y));
8469
- const x1 = Math.min(width, Math.ceil(r.x + r.width));
8470
- const y1 = Math.min(height, Math.ceil(r.y + r.height));
8471
- if (x1 <= x0 || y1 <= y0) continue;
8472
- const part = readRegion(surface, { x: x0, y: y0, width: x1 - x0, height: y1 - y0 });
8473
- for (let y = y0; y < y1; y++) data.set(part.subarray((y - y0) * (x1 - x0), (y - y0 + 1) * (x1 - x0)), y * width + x0);
8474
- }
8475
- } else {
8476
- const all = readRegion(surface, { x: 0, y: 0, width, height });
8477
- data = new Uint8Array(all.buffer, all.byteOffset, all.length);
8478
- }
8479
- return normalizeSelection(createSelectionMask(width, height, data));
8489
+ return normalizeSelection(selectionFromTiles(width, height, surface));
8480
8490
  }
8481
8491
  // --- Layer masks ---
8482
8492
  maskFromSelection(sel, props = {}) {
8483
8493
  const { width, height } = this.naturalSize;
8484
8494
  const sized = sel.width === width && sel.height === height ? sel : resizeSelection(sel, width, height);
8485
- const mask = { surface: surfaceFromPixels({ width, height, data: sized.data }, 1, 0, 0, 0), defaultValue: 0 };
8495
+ const mask = { surface: sized.surface, defaultValue: 0 };
8486
8496
  return withMaskProps(mask, props);
8487
8497
  }
8488
8498
  /**
@@ -10154,6 +10164,10 @@ function isOpaqueInside(surface, width, height) {
10154
10164
  }
10155
10165
  return true;
10156
10166
  }
10167
+ function collectSelectionTiles(selection, channels, into) {
10168
+ if (selection) collectTiles(selection.surface, into);
10169
+ for (const c of channels ?? []) collectTiles(c.mask.surface, into);
10170
+ }
10157
10171
  function collectStateTiles(layers, into) {
10158
10172
  for (const l of flattenLayers(layers)) {
10159
10173
  if (l.type === "pixel" && l.source !== "document") collectTiles(l.surface, into);
@@ -11063,9 +11077,7 @@ var REFINE_EDGE_CONTROLS = [
11063
11077
  ];
11064
11078
  function describeSelection(mask) {
11065
11079
  if (!mask || !mask.bounds) return "No selection";
11066
- let sum = 0;
11067
- for (let i = 0; i < mask.data.length; i++) sum += mask.data[i];
11068
- const pct2 = sum / 255 / mask.data.length * 100;
11080
+ const pct2 = selectionArea(mask) / (mask.width * mask.height) * 100;
11069
11081
  const shown = pct2 >= 10 ? Math.round(pct2) : Math.round(pct2 * 10) / 10;
11070
11082
  return `${mask.bounds.width} \xD7 ${mask.bounds.height} px selected (${shown}% of the image)`;
11071
11083
  }
@@ -18410,6 +18422,7 @@ export {
18410
18422
  pointerStrokeSample,
18411
18423
  pointerStrokeSamples,
18412
18424
  polygonCoverage,
18425
+ polygonCoverageBox,
18413
18426
  polygonSelection,
18414
18427
  posterizeValue,
18415
18428
  presetWarp,
@@ -18509,6 +18522,8 @@ export {
18509
18522
  selectionArea,
18510
18523
  selectionFromCoverage,
18511
18524
  selectionFromPixels,
18525
+ selectionFromRegion,
18526
+ selectionFromTiles,
18512
18527
  selectionModeFromModifiers,
18513
18528
  selectionOutline,
18514
18529
  selectionRing,
@@ -1,11 +1,17 @@
1
1
  import type { CropBox } from '../types.cjs';
2
+ import { TiledSurface } from '../../raster/surface.cjs';
2
3
  /**
3
4
  * A selection: one 8-bit coverage value per image pixel (0 = not selected, 255 = fully
4
5
  * selected), row-major over the whole source image in natural pixels — the same space as the
5
6
  * crop box and annotations. Soft values are partial selection (feathered or anti-aliased edges).
6
7
  *
8
+ * The coverage is stored as 256 × 256 tiles (`surface`, one byte per pixel, missing tiles are 0
9
+ * and every pixel outside the image is 0), so an empty or fully selected area costs nothing and
10
+ * masks share the tiles an operation did not change. `data` is the same coverage as one array,
11
+ * built on first read and cached for the few masks read most recently.
12
+ *
7
13
  * Treat a mask as immutable: every operation returns a new one, so history entries can share
8
- * them without copying.
14
+ * them without copying. Never write to `data`.
9
15
  */
10
16
  export interface SelectionMask {
11
17
  readonly width: number;
@@ -13,6 +19,8 @@ export interface SelectionMask {
13
19
  readonly data: Uint8Array;
14
20
  /** Bounding box of the non-zero coverage, or `null` when nothing is selected. */
15
21
  readonly bounds: CropBox | null;
22
+ /** The coverage as tiles (1 channel, default 0), shared with other masks where equal. */
23
+ readonly surface: TiledSurface;
16
24
  }
17
25
  /** How a new selection combines with the current one. */
18
26
  export type SelectionMode = 'replace' | 'add' | 'subtract' | 'intersect';
@@ -35,8 +43,19 @@ export interface SerializedSelection {
35
43
  }
36
44
  /** Bounding box of non-zero bytes. */
37
45
  export declare function computeSelectionBounds(width: number, height: number, data: ArrayLike<number>): CropBox | null;
46
+ /**
47
+ * A selection over `width × height` from a 1-channel tiled surface in image space (Quick Mask
48
+ * paint, a mask): its tiles are shared, and coverage outside the image is dropped. A surface
49
+ * whose default is not 0 is read out instead.
50
+ */
51
+ export declare function selectionFromTiles(width: number, height: number, surface: TiledSurface): SelectionMask;
38
52
  /** Wraps coverage bytes (taken over, not copied) as a selection, computing its bounds. */
39
53
  export declare function createSelectionMask(width: number, height: number, data?: Uint8Array): SelectionMask;
54
+ /**
55
+ * A selection that is `data` (`rect.width × rect.height` coverage bytes) inside `rect` and
56
+ * nothing elsewhere, without allocating the whole image. `rect` must lie inside the image.
57
+ */
58
+ export declare function selectionFromRegion(width: number, height: number, rect: CropBox, data: ArrayLike<number>): SelectionMask;
40
59
  /** Select › All. */
41
60
  export declare function fullSelection(width: number, height: number): SelectionMask;
42
61
  export declare function isSelectionEmpty(mask: SelectionMask | null | undefined): boolean;
@@ -1,11 +1,17 @@
1
1
  import type { CropBox } from '../types.js';
2
+ import { TiledSurface } from '../../raster/surface.js';
2
3
  /**
3
4
  * A selection: one 8-bit coverage value per image pixel (0 = not selected, 255 = fully
4
5
  * selected), row-major over the whole source image in natural pixels — the same space as the
5
6
  * crop box and annotations. Soft values are partial selection (feathered or anti-aliased edges).
6
7
  *
8
+ * The coverage is stored as 256 × 256 tiles (`surface`, one byte per pixel, missing tiles are 0
9
+ * and every pixel outside the image is 0), so an empty or fully selected area costs nothing and
10
+ * masks share the tiles an operation did not change. `data` is the same coverage as one array,
11
+ * built on first read and cached for the few masks read most recently.
12
+ *
7
13
  * Treat a mask as immutable: every operation returns a new one, so history entries can share
8
- * them without copying.
14
+ * them without copying. Never write to `data`.
9
15
  */
10
16
  export interface SelectionMask {
11
17
  readonly width: number;
@@ -13,6 +19,8 @@ export interface SelectionMask {
13
19
  readonly data: Uint8Array;
14
20
  /** Bounding box of the non-zero coverage, or `null` when nothing is selected. */
15
21
  readonly bounds: CropBox | null;
22
+ /** The coverage as tiles (1 channel, default 0), shared with other masks where equal. */
23
+ readonly surface: TiledSurface;
16
24
  }
17
25
  /** How a new selection combines with the current one. */
18
26
  export type SelectionMode = 'replace' | 'add' | 'subtract' | 'intersect';
@@ -35,8 +43,19 @@ export interface SerializedSelection {
35
43
  }
36
44
  /** Bounding box of non-zero bytes. */
37
45
  export declare function computeSelectionBounds(width: number, height: number, data: ArrayLike<number>): CropBox | null;
46
+ /**
47
+ * A selection over `width × height` from a 1-channel tiled surface in image space (Quick Mask
48
+ * paint, a mask): its tiles are shared, and coverage outside the image is dropped. A surface
49
+ * whose default is not 0 is read out instead.
50
+ */
51
+ export declare function selectionFromTiles(width: number, height: number, surface: TiledSurface): SelectionMask;
38
52
  /** Wraps coverage bytes (taken over, not copied) as a selection, computing its bounds. */
39
53
  export declare function createSelectionMask(width: number, height: number, data?: Uint8Array): SelectionMask;
54
+ /**
55
+ * A selection that is `data` (`rect.width × rect.height` coverage bytes) inside `rect` and
56
+ * nothing elsewhere, without allocating the whole image. `rect` must lie inside the image.
57
+ */
58
+ export declare function selectionFromRegion(width: number, height: number, rect: CropBox, data: ArrayLike<number>): SelectionMask;
40
59
  /** Select › All. */
41
60
  export declare function fullSelection(width: number, height: number): SelectionMask;
42
61
  export declare function isSelectionEmpty(mask: SelectionMask | null | undefined): boolean;
@@ -11,6 +11,14 @@ export interface ShapeSelectionOptions {
11
11
  * their top), so the cost is about pixels + edges × rows they span.
12
12
  */
13
13
  export declare function polygonCoverage(points: readonly ImagePoint[], width: number, height: number, antiAlias?: boolean): Float32Array;
14
+ /**
15
+ * {@link polygonCoverage} over just the polygon's bounding box (clipped to the image): `coverage`
16
+ * is `box.width × box.height`; `box` is `null` when the polygon covers no pixel row or column.
17
+ */
18
+ export declare function polygonCoverageBox(points: readonly ImagePoint[], width: number, height: number, antiAlias?: boolean): {
19
+ box: CropBox | null;
20
+ coverage: Float32Array;
21
+ };
14
22
  /** Lasso / polygonal lasso: an even-odd polygon in natural image pixels. */
15
23
  export declare function polygonSelection(width: number, height: number, points: readonly ImagePoint[], options?: ShapeSelectionOptions): SelectionMask;
16
24
  /** Normalises a rectangle with a negative width or height. */
@@ -11,6 +11,14 @@ export interface ShapeSelectionOptions {
11
11
  * their top), so the cost is about pixels + edges × rows they span.
12
12
  */
13
13
  export declare function polygonCoverage(points: readonly ImagePoint[], width: number, height: number, antiAlias?: boolean): Float32Array;
14
+ /**
15
+ * {@link polygonCoverage} over just the polygon's bounding box (clipped to the image): `coverage`
16
+ * is `box.width × box.height`; `box` is `null` when the polygon covers no pixel row or column.
17
+ */
18
+ export declare function polygonCoverageBox(points: readonly ImagePoint[], width: number, height: number, antiAlias?: boolean): {
19
+ box: CropBox | null;
20
+ coverage: Float32Array;
21
+ };
14
22
  /** Lasso / polygonal lasso: an even-odd polygon in natural image pixels. */
15
23
  export declare function polygonSelection(width: number, height: number, points: readonly ImagePoint[], options?: ShapeSelectionOptions): SelectionMask;
16
24
  /** Normalises a rectangle with a negative width or height. */
@@ -1,4 +1,4 @@
1
- import type { SelectionMask, SelectionMode } from './mask.cjs';
1
+ import { type SelectionMask, type SelectionMode } from './mask.cjs';
2
2
  import type { ColorDistance, ColorRangePreset } from './wand.cjs';
3
3
  import type { RefineEdgeParams } from './refine.cjs';
4
4
  /** Selection tools of the image editor UI. */
@@ -1,4 +1,4 @@
1
- import type { SelectionMask, SelectionMode } from './mask.js';
1
+ import { type SelectionMask, type SelectionMode } from './mask.js';
2
2
  import type { ColorDistance, ColorRangePreset } from './wand.js';
3
3
  import type { RefineEdgeParams } from './refine.js';
4
4
  /** Selection tools of the image editor UI. */
@@ -7,7 +7,7 @@ var _chunkZ64NRDEHcjs = require('../chunk-Z64NRDEH.cjs');
7
7
 
8
8
 
9
9
 
10
- var _chunkX2KQQZBTcjs = require('../chunk-X2KQQZBT.cjs');
10
+ var _chunkJYV4R62Mcjs = require('../chunk-JYV4R62M.cjs');
11
11
  require('../chunk-A2IS7EHE.cjs');
12
12
 
13
13
 
@@ -1653,11 +1653,11 @@ function header(state, options) {
1653
1653
  return out;
1654
1654
  }
1655
1655
  function serializePaintDocument(state, options = {}) {
1656
- const { layers, assets } = _chunkX2KQQZBTcjs.serializeLayers.call(void 0, state.layers);
1656
+ const { layers, assets } = _chunkJYV4R62Mcjs.serializeLayers.call(void 0, state.layers);
1657
1657
  return { ...header(state, options), layers, assets };
1658
1658
  }
1659
1659
  async function serializePaintDocumentExternal(state, store, options = {}) {
1660
- const { layers, assets } = await _chunkX2KQQZBTcjs.serializeLayersExternal.call(void 0, state.layers, store);
1660
+ const { layers, assets } = await _chunkJYV4R62Mcjs.serializeLayersExternal.call(void 0, state.layers, store);
1661
1661
  return { ...header(state, options), layers, assets };
1662
1662
  }
1663
1663
  function paintLayersOnly(layers, problems) {
@@ -1694,7 +1694,7 @@ function deserializePaintDocument(raw) {
1694
1694
  const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
1695
1695
  const paper = _chunkYQ5C5BVKcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
1696
1696
  const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
1697
- const layers = paintLayersOnly(_chunkX2KQQZBTcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1697
+ const layers = paintLayersOnly(_chunkJYV4R62Mcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1698
1698
  const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
1699
1699
  const activeLayerId = wanted && _chunkHGTDMKNEcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.flattenLayers.call(void 0, layers), 'access', _70 => _70.filter, 'call', _71 => _71((l) => l.type === "pixel"), 'access', _72 => _72.pop, 'call', _73 => _73(), 'optionalAccess', _74 => _74.id]), () => ( null));
1700
1700
  const wetEvents = Array.isArray(r.wetEvents) ? r.wetEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.clock) && typeof e.kind === "string") : [];
@@ -1710,7 +1710,7 @@ async function deserializePaintDocumentAsync(raw, store) {
1710
1710
  if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
1711
1711
  const r = raw;
1712
1712
  const problems = [];
1713
- const assets = await _chunkX2KQQZBTcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1713
+ const assets = await _chunkJYV4R62Mcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1714
1714
  const loaded = deserializePaintDocument({ ...r, assets });
1715
1715
  return { ...loaded, problems: [...problems, ...loaded.problems] };
1716
1716
  }
@@ -5409,7 +5409,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5409
5409
  return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
5410
5410
  });
5411
5411
  const layers = toStandard(dried);
5412
- const result = _chunkX2KQQZBTcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
5412
+ const result = _chunkJYV4R62Mcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
5413
5413
  for (const [mode, names] of changed) {
5414
5414
  const label = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _271 => _271.find, 'call', _272 => _272((m) => m.id === mode), 'optionalAccess', _273 => _273.label]), () => ( mode));
5415
5415
  const std = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _274 => _274.find, 'call', _275 => _275((m) => m.id === _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _276 => _276.label]), () => ( _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)));
@@ -7,7 +7,7 @@ import {
7
7
  resolveExternalAssets,
8
8
  serializeLayers,
9
9
  serializeLayersExternal
10
- } from "../chunk-FW7N64XK.js";
10
+ } from "../chunk-IGMNJM2H.js";
11
11
  import "../chunk-3CI7FRMK.js";
12
12
  import {
13
13
  EffectRendererPool
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.187.0",
3
+ "version": "0.188.0",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",