@pixerate/editor 0.154.0 → 0.156.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.
Files changed (86) hide show
  1. package/dist/animation-editor/index.cjs +60 -61
  2. package/dist/animation-editor/index.js +5 -6
  3. package/dist/{brushstrokeRender-YAZVQUXY.cjs → brushstrokeRender-5WANQIG4.cjs} +10 -10
  4. package/dist/{brushstrokeRender-EUDQTDYS.js → brushstrokeRender-Q4LI22QV.js} +3 -3
  5. package/dist/canvas/index.cjs +23 -24
  6. package/dist/canvas/index.js +3 -4
  7. package/dist/chart/index.cjs +2 -3
  8. package/dist/chart/index.js +1 -2
  9. package/dist/{chunk-AGZ47XY2.js → chunk-2N2QPO3H.js} +6 -2
  10. package/dist/{chunk-NMXPOKF3.js → chunk-45XXVHVG.js} +1 -1
  11. package/dist/{chunk-FLOGD3QB.js → chunk-6UPGM3JB.js} +2 -2
  12. package/dist/{chunk-6FUAHCVI.cjs → chunk-7NW46N7I.cjs} +16 -16
  13. package/dist/{chunk-ORDXMBD4.js → chunk-A5UCR2TO.js} +10 -3
  14. package/dist/{chunk-PI45JMP7.cjs → chunk-CD7PLU77.cjs} +81 -81
  15. package/dist/{chunk-LRRCMRSL.cjs → chunk-EBDCRTZI.cjs} +20 -16
  16. package/dist/{chunk-OLCYQLFE.js → chunk-EL5PAHNP.js} +1 -1
  17. package/dist/{chunk-PUC43JPT.cjs → chunk-EYVVIZJ3.cjs} +1 -1
  18. package/dist/{chunk-BXMIBMVG.cjs → chunk-JGKCC5OF.cjs} +65 -58
  19. package/dist/chunk-M4MIZPQI.cjs +393 -0
  20. package/dist/{chunk-LIXLD433.cjs → chunk-MHEXLG3M.cjs} +35 -35
  21. package/dist/chunk-NHLYK3AX.js +393 -0
  22. package/dist/{chunk-RHXW4TA5.cjs → chunk-QMI5HZWA.cjs} +7 -7
  23. package/dist/{chunk-XFDQEAOS.cjs → chunk-RQCMSEM5.cjs} +2 -2
  24. package/dist/{chunk-BCY22GBH.js → chunk-SDHZG5TF.js} +1 -1
  25. package/dist/{chunk-HVX35M2I.cjs → chunk-WI7QJA7A.cjs} +2 -2
  26. package/dist/{chunk-UILRJQFD.js → chunk-WNAAWLZ5.js} +1 -1
  27. package/dist/{chunk-4J4MC3F5.js → chunk-YXOW456B.js} +1 -1
  28. package/dist/{chunk-Y64YPIFT.js → chunk-ZQWLWDZI.js} +1 -1
  29. package/dist/diagram/index.cjs +2 -3
  30. package/dist/diagram/index.js +1 -2
  31. package/dist/image-editor/controller.d.cts +8 -0
  32. package/dist/image-editor/controller.d.ts +8 -0
  33. package/dist/image-editor/editorDocument.d.cts +16 -0
  34. package/dist/image-editor/editorDocument.d.ts +16 -0
  35. package/dist/image-editor/index.cjs +787 -737
  36. package/dist/image-editor/index.d.cts +1 -0
  37. package/dist/image-editor/index.d.ts +1 -0
  38. package/dist/image-editor/index.js +56 -6
  39. package/dist/index.cjs +4 -5
  40. package/dist/index.js +2 -3
  41. package/dist/paint/grain.d.cts +7 -0
  42. package/dist/paint/grain.d.ts +7 -0
  43. package/dist/paint/index.cjs +3 -3
  44. package/dist/paint/index.js +2 -2
  45. package/dist/paint-editor/controller.d.cts +38 -0
  46. package/dist/paint-editor/controller.d.ts +38 -0
  47. package/dist/paint-editor/document.d.cts +8 -0
  48. package/dist/paint-editor/document.d.ts +8 -0
  49. package/dist/paint-editor/editorDocument.d.cts +17 -0
  50. package/dist/paint-editor/editorDocument.d.ts +17 -0
  51. package/dist/paint-editor/index.cjs +476 -273
  52. package/dist/paint-editor/index.d.cts +1 -0
  53. package/dist/paint-editor/index.d.ts +1 -0
  54. package/dist/paint-editor/index.js +216 -13
  55. package/dist/paint-editor/paper.d.cts +8 -0
  56. package/dist/paint-editor/paper.d.ts +8 -0
  57. package/dist/paint-editor/stencils.d.cts +2 -0
  58. package/dist/paint-editor/stencils.d.ts +2 -0
  59. package/dist/paint-editor/wet.d.cts +1 -0
  60. package/dist/paint-editor/wet.d.ts +1 -0
  61. package/dist/parameters/index.cjs +2 -3
  62. package/dist/parameters/index.js +1 -2
  63. package/dist/persistence/assets.d.cts +51 -0
  64. package/dist/persistence/assets.d.ts +51 -0
  65. package/dist/persistence/editorDocument.d.cts +12 -0
  66. package/dist/persistence/editorDocument.d.ts +12 -0
  67. package/dist/persistence/index.cjs +32 -8
  68. package/dist/persistence/index.d.cts +1 -0
  69. package/dist/persistence/index.d.ts +1 -0
  70. package/dist/persistence/index.js +34 -10
  71. package/dist/spreadsheet/index.cjs +3 -4
  72. package/dist/spreadsheet/index.js +2 -3
  73. package/dist/tokens/index.cjs +3 -4
  74. package/dist/tokens/index.js +2 -3
  75. package/dist/vector/index.cjs +952 -953
  76. package/dist/vector/index.js +5 -6
  77. package/dist/video-editor/index.cjs +2 -3
  78. package/dist/video-editor/index.js +1 -2
  79. package/package.json +1 -1
  80. package/skills/pixerate-image-editor/SKILL.md +16 -24
  81. package/skills/pixerate-image-editor/references/smart-objects.md +28 -0
  82. package/skills/pixerate-paint-editor/SKILL.md +26 -6
  83. package/dist/chunk-5H2C3QSF.cjs +0 -134
  84. package/dist/chunk-GNV54DLO.js +0 -134
  85. package/dist/chunk-L5OWG2NA.cjs +0 -135
  86. package/dist/chunk-WHKNYFM2.js +0 -135
@@ -0,0 +1,393 @@
1
+ import {
2
+ isUnsafeJsonKey,
3
+ stripPrototypeKeys
4
+ } from "./chunk-HF5QZS7Z.js";
5
+
6
+ // src/persistence/assets.ts
7
+ var EDITOR_ASSET_PREFIX = "pixerate-asset:";
8
+ var REF = /pixerate-asset:[0-9a-z]+-[0-9a-z]+(?:~[0-9]+)?/g;
9
+ var BASE64 = /^[A-Za-z0-9+/=\r\n]+$/;
10
+ function isInlineAsset(value) {
11
+ if (value.startsWith("data:")) return value.length >= 512;
12
+ return value.length >= 4096 && BASE64.test(value);
13
+ }
14
+ function hash53(text) {
15
+ let h1 = 3735928559;
16
+ let h2 = 1103547991;
17
+ for (let i = 0; i < text.length; i++) {
18
+ const c = text.charCodeAt(i);
19
+ h1 = Math.imul(h1 ^ c, 2654435761);
20
+ h2 = Math.imul(h2 ^ c, 1597334677);
21
+ }
22
+ h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
23
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
24
+ return 4294967296 * (2097151 & h2) + (h1 >>> 0);
25
+ }
26
+ function createEditorAssetRegistry() {
27
+ const byRef = /* @__PURE__ */ new Map();
28
+ const byData = /* @__PURE__ */ new Map();
29
+ return {
30
+ put(data) {
31
+ const known = byData.get(data);
32
+ if (known) return known;
33
+ const base = `${EDITOR_ASSET_PREFIX}${data.length.toString(36)}-${hash53(data).toString(36)}`;
34
+ let ref = base;
35
+ for (let n = 1; byRef.has(ref) && byRef.get(ref) !== data; n++) ref = `${base}~${n}`;
36
+ byRef.set(ref, data);
37
+ byData.set(data, ref);
38
+ return ref;
39
+ },
40
+ get: (ref) => byRef.get(ref),
41
+ has: (ref) => byRef.has(ref),
42
+ set(ref, data) {
43
+ byRef.set(ref, data);
44
+ byData.set(data, ref);
45
+ },
46
+ get size() {
47
+ return byRef.size;
48
+ }
49
+ };
50
+ }
51
+ function externalizeAssets(value, registry) {
52
+ const walk = (v) => {
53
+ if (typeof v === "string") return isInlineAsset(v) ? registry.put(v) : v;
54
+ if (Array.isArray(v)) return v.map(walk);
55
+ if (v && typeof v === "object") {
56
+ const out = {};
57
+ for (const [k, x] of Object.entries(v)) out[k] = walk(x);
58
+ return out;
59
+ }
60
+ return v;
61
+ };
62
+ return walk(value);
63
+ }
64
+ function collectAssetRefs(value) {
65
+ const text = typeof value === "string" ? value : JSON.stringify(value) ?? "";
66
+ return [...new Set(text.match(REF) ?? [])];
67
+ }
68
+ function internalizeAssets(value, registry) {
69
+ const missing = collectAssetRefs(value).filter((ref) => !registry.has(ref));
70
+ if (missing.length) {
71
+ throw new Error(
72
+ `The document refers to ${missing.length} asset${missing.length === 1 ? "" : "s"} that ${missing.length === 1 ? "is" : "are"} not loaded (${missing.slice(0, 3).join(", ")}${missing.length > 3 ? ", \u2026" : ""}). Pass a document from get_*_document in this session, or open it from storage so its assets are read first.`
73
+ );
74
+ }
75
+ const walk = (v) => {
76
+ if (typeof v === "string") return v.startsWith(EDITOR_ASSET_PREFIX) && registry.has(v) ? registry.get(v) : v;
77
+ if (Array.isArray(v)) return v.map(walk);
78
+ if (v && typeof v === "object") {
79
+ const out = {};
80
+ for (const [k, x] of Object.entries(v)) out[k] = walk(x);
81
+ return out;
82
+ }
83
+ return v;
84
+ };
85
+ return walk(value);
86
+ }
87
+ var persisted = /* @__PURE__ */ new WeakMap();
88
+ var assetKey = (ref, options) => `${options.prefix ?? "pixerate.assets:"}${ref.slice(EDITOR_ASSET_PREFIX.length)}`;
89
+ async function persistEditorAssets(storage, registry, document, options = {}) {
90
+ const written = persisted.get(storage) ?? /* @__PURE__ */ new Set();
91
+ persisted.set(storage, written);
92
+ for (const ref of collectAssetRefs(document)) {
93
+ const key = assetKey(ref, options);
94
+ if (written.has(key)) continue;
95
+ const data = registry.get(ref);
96
+ if (data === void 0) continue;
97
+ await storage.set(key, data);
98
+ written.add(key);
99
+ }
100
+ }
101
+ async function preloadEditorAssets(storage, registry, document, options = {}) {
102
+ const missing = [];
103
+ for (const ref of collectAssetRefs(document)) {
104
+ if (registry.has(ref)) continue;
105
+ const data = await storage.get(assetKey(ref, options));
106
+ if (data === null) missing.push(ref);
107
+ else registry.set(ref, data);
108
+ }
109
+ return missing;
110
+ }
111
+ function withEditorAssets(storage, registry, options = {}) {
112
+ return {
113
+ kind: storage.kind,
114
+ get available() {
115
+ return storage.available;
116
+ },
117
+ async get(key) {
118
+ const value = await storage.get(key);
119
+ if (value !== null && value.includes(EDITOR_ASSET_PREFIX)) await preloadEditorAssets(storage, registry, value, options);
120
+ return value;
121
+ },
122
+ async set(key, value) {
123
+ if (value.includes(EDITOR_ASSET_PREFIX)) await persistEditorAssets(storage, registry, value, options);
124
+ await storage.set(key, value);
125
+ },
126
+ remove: (key) => storage.remove(key)
127
+ };
128
+ }
129
+
130
+ // src/persistence/migrate.ts
131
+ function hasLoadProblems(report) {
132
+ return report.problems.length > 0 || report.readOnly !== null;
133
+ }
134
+ function createLoadReport(partial = {}) {
135
+ return {
136
+ migratedFrom: null,
137
+ version: null,
138
+ problems: [],
139
+ readOnly: null,
140
+ unknownKeys: [],
141
+ ...partial
142
+ };
143
+ }
144
+ var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
145
+ var deepClone = (value) => typeof structuredClone === "function" ? structuredClone(value) : JSON.parse(JSON.stringify(value));
146
+ function toObject(json) {
147
+ let value = json;
148
+ if (typeof json === "string") {
149
+ try {
150
+ value = JSON.parse(json);
151
+ } catch {
152
+ return void 0;
153
+ }
154
+ }
155
+ return isObject(value) ? stripPrototypeKeys(deepClone(value)) : void 0;
156
+ }
157
+ function migrateDocument(json, options) {
158
+ const versionKey = options.versionKey ?? "version";
159
+ const target = options.currentVersion;
160
+ const original = toObject(json);
161
+ if (!original) {
162
+ return {
163
+ doc: { [versionKey]: target },
164
+ report: createLoadReport({
165
+ readOnly: { kind: "invalid", message: "document is not a JSON object" }
166
+ })
167
+ };
168
+ }
169
+ const raw = original[versionKey];
170
+ const found = typeof raw === "number" && Number.isInteger(raw) && raw >= 0 ? raw : null;
171
+ const from = found ?? options.missingVersion ?? target;
172
+ const report = createLoadReport({ version: found });
173
+ if (from > target) {
174
+ report.readOnly = {
175
+ kind: "newerVersion",
176
+ version: from,
177
+ supported: target,
178
+ message: `document has version ${from}, newer than the supported ${target}`
179
+ };
180
+ return { doc: original, report };
181
+ }
182
+ if (from === target) {
183
+ original[versionKey] = target;
184
+ return { doc: original, report };
185
+ }
186
+ let doc = deepClone(original);
187
+ for (let step = from; step < target; step++) {
188
+ const fn = options.steps?.[step];
189
+ if (!fn) {
190
+ report.readOnly = {
191
+ kind: "migrationFailed",
192
+ from: step,
193
+ message: `no migration step from version ${step}`
194
+ };
195
+ return { doc: original, report };
196
+ }
197
+ try {
198
+ doc = fn(doc) ?? doc;
199
+ } catch (error) {
200
+ report.readOnly = {
201
+ kind: "migrationFailed",
202
+ from: step,
203
+ message: `migration from version ${step} failed: ${error instanceof Error ? error.message : String(error)}`
204
+ };
205
+ return { doc: original, report };
206
+ }
207
+ doc[versionKey] = step + 1;
208
+ }
209
+ report.migratedFrom = from;
210
+ return { doc, report };
211
+ }
212
+ function loadSections(doc, sections, options = {}) {
213
+ const source = isObject(doc) ? doc : {};
214
+ const ignore = new Set(options.ignore ?? ["version"]);
215
+ const value = {};
216
+ const problems = [];
217
+ for (const key of Object.keys(sections)) {
218
+ const spec = sections[key];
219
+ const fallback = () => typeof spec.defaults === "function" ? spec.defaults() : spec.defaults;
220
+ if (!Object.prototype.hasOwnProperty.call(source, key)) {
221
+ value[key] = fallback();
222
+ continue;
223
+ }
224
+ try {
225
+ const parsed = spec.parse(source[key]);
226
+ if (parsed === void 0) throw new Error("invalid value");
227
+ value[key] = parsed;
228
+ } catch (error) {
229
+ problems.push({
230
+ section: key,
231
+ message: error instanceof Error ? error.message : String(error)
232
+ });
233
+ value[key] = fallback();
234
+ }
235
+ }
236
+ const unknown = {};
237
+ for (const key of Object.keys(source)) {
238
+ if (!(key in sections) && !ignore.has(key) && !isUnsafeJsonKey(key)) unknown[key] = source[key];
239
+ }
240
+ return { value, problems, unknown };
241
+ }
242
+ function loadDocument(json, sections, options) {
243
+ const { doc, report } = migrateDocument(json, options);
244
+ const ignore = options.ignore ?? [options.versionKey ?? "version"];
245
+ const result = loadSections(report.readOnly?.kind === "invalid" ? {} : doc, sections, {
246
+ ignore
247
+ });
248
+ report.problems = result.problems;
249
+ report.unknownKeys = Object.keys(result.unknown);
250
+ return { ...result, report };
251
+ }
252
+
253
+ // src/persistence/editorDocument.ts
254
+ var EditorDocumentLoadError = class extends Error {
255
+ /** The `LoadReport` when the input was a file that could not be migrated. */
256
+ report;
257
+ constructor(message, report) {
258
+ super(message);
259
+ this.name = "EditorDocumentLoadError";
260
+ this.report = report;
261
+ }
262
+ };
263
+ var EDITOR_DOCUMENT_FORMAT = "pixerate.editor-document";
264
+ var KIND = /^[a-z][a-z0-9_]*$/;
265
+ function isEditorDocumentFile(value) {
266
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
267
+ const v = value;
268
+ return v.format === EDITOR_DOCUMENT_FORMAT && typeof v.kind === "string" && typeof v.formatVersion === "number" && "document" in v;
269
+ }
270
+ function toEditorDocumentFile(doc, name) {
271
+ return {
272
+ format: EDITOR_DOCUMENT_FORMAT,
273
+ kind: doc.kind,
274
+ formatVersion: doc.formatVersion,
275
+ ...name ? { name } : {},
276
+ document: doc.getDocument()
277
+ };
278
+ }
279
+ function serializeEditorDocument(doc, options = {}) {
280
+ return JSON.stringify(toEditorDocumentFile(doc, options.name), null, options.space);
281
+ }
282
+ function parseEditorDocument(text, options = {}) {
283
+ let value;
284
+ try {
285
+ value = stripPrototypeKeys(JSON.parse(text));
286
+ } catch (error) {
287
+ throw new EditorDocumentLoadError(`The file is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
288
+ }
289
+ if (!isEditorDocumentFile(value)) {
290
+ throw new EditorDocumentLoadError(`The file is not a saved editor document (expected "format": "${EDITOR_DOCUMENT_FORMAT}").`);
291
+ }
292
+ if (options.kind && value.kind !== options.kind) {
293
+ throw new EditorDocumentLoadError(`The file is a ${value.kind} document, not a ${options.kind} document.`);
294
+ }
295
+ return value;
296
+ }
297
+ function defineEditorDocument(spec) {
298
+ if (!KIND.test(spec.kind)) throw new Error(`Editor document kind "${spec.kind}" must match ${KIND}.`);
299
+ const formatVersion = spec.formatVersion ?? 1;
300
+ const listeners = /* @__PURE__ */ new Set();
301
+ let revision = 0;
302
+ let unsubscribe = null;
303
+ let connected = false;
304
+ const connect = () => {
305
+ if (unsubscribe) return;
306
+ if (connected) revision++;
307
+ connected = true;
308
+ unsubscribe = spec.subscribe(() => {
309
+ revision++;
310
+ listeners.forEach((listener) => {
311
+ try {
312
+ listener();
313
+ } catch (error) {
314
+ console.error(`[${spec.kind} document] Error in change listener:`, error);
315
+ }
316
+ });
317
+ });
318
+ };
319
+ connect();
320
+ const unwrap = (input) => {
321
+ if (!isEditorDocumentFile(input)) return { document: input, report: createLoadReport({ version: formatVersion }) };
322
+ if (input.kind !== spec.kind) throw new EditorDocumentLoadError(`This is a ${input.kind} document; it cannot be opened in the ${spec.kind} editor.`);
323
+ const steps = Object.fromEntries(
324
+ Object.entries(spec.migrations ?? {}).map(([v, step]) => [v, (w) => ({ ...w, document: step(w.document) })])
325
+ );
326
+ const { doc, report } = migrateDocument(
327
+ { formatVersion: input.formatVersion, document: input.document },
328
+ { currentVersion: formatVersion, versionKey: "formatVersion", steps }
329
+ );
330
+ if (report.readOnly) throw new EditorDocumentLoadError(`Cannot open the ${spec.kind} document: ${report.readOnly.message}.`, report);
331
+ return { document: doc.document, report };
332
+ };
333
+ return {
334
+ kind: spec.kind,
335
+ formatVersion,
336
+ recordsLoads: spec.recordsLoads !== false,
337
+ getDocument: () => spec.assets ? externalizeAssets(spec.get(), spec.assets) : spec.get(),
338
+ loadDocument(input, options = {}) {
339
+ const { document, report } = unwrap(input);
340
+ if (document === void 0 || document === null) throw new EditorDocumentLoadError(`No ${spec.kind} document was given.`);
341
+ try {
342
+ const result = spec.load(spec.assets ? internalizeAssets(document, spec.assets) : document, { history: options.history ?? "reset" });
343
+ if (result?.problems?.length) report.problems.push(...result.problems);
344
+ } catch (error) {
345
+ if (error instanceof EditorDocumentLoadError) throw error;
346
+ throw new EditorDocumentLoadError(error instanceof Error ? error.message : String(error));
347
+ }
348
+ return report;
349
+ },
350
+ revision: () => {
351
+ connect();
352
+ return revision;
353
+ },
354
+ subscribe(listener) {
355
+ connect();
356
+ listeners.add(listener);
357
+ return () => {
358
+ listeners.delete(listener);
359
+ };
360
+ },
361
+ history: spec.history,
362
+ ...spec.assets ? { assets: spec.assets } : {},
363
+ readOnly: () => spec.readOnly?.() ?? false,
364
+ destroy() {
365
+ unsubscribe?.();
366
+ unsubscribe = null;
367
+ }
368
+ };
369
+ }
370
+
371
+ export {
372
+ EDITOR_ASSET_PREFIX,
373
+ isInlineAsset,
374
+ createEditorAssetRegistry,
375
+ externalizeAssets,
376
+ collectAssetRefs,
377
+ internalizeAssets,
378
+ persistEditorAssets,
379
+ preloadEditorAssets,
380
+ withEditorAssets,
381
+ hasLoadProblems,
382
+ createLoadReport,
383
+ migrateDocument,
384
+ loadSections,
385
+ loadDocument,
386
+ EditorDocumentLoadError,
387
+ EDITOR_DOCUMENT_FORMAT,
388
+ isEditorDocumentFile,
389
+ toEditorDocumentFile,
390
+ serializeEditorDocument,
391
+ parseEditorDocument,
392
+ defineEditorDocument
393
+ };
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
2
2
 
3
- var _chunkBXMIBMVGcjs = require('./chunk-BXMIBMVG.cjs');
3
+ var _chunkJGKCC5OFcjs = require('./chunk-JGKCC5OF.cjs');
4
4
 
5
5
 
6
6
  var _chunkCVFAAZXEcjs = require('./chunk-CVFAAZXE.cjs');
@@ -47,7 +47,7 @@ var _chunkNM3G4VQTcjs = require('./chunk-NM3G4VQT.cjs');
47
47
 
48
48
 
49
49
 
50
- var _chunkLRRCMRSLcjs = require('./chunk-LRRCMRSL.cjs');
50
+ var _chunkEBDCRTZIcjs = require('./chunk-EBDCRTZI.cjs');
51
51
 
52
52
 
53
53
 
@@ -2527,7 +2527,7 @@ function vectorExtrudeFaces(path, params) {
2527
2527
  // src/vector/brushstroke.ts
2528
2528
  var VECTOR_BRUSHSTROKE_SCALE = 2;
2529
2529
  function vectorBrushstrokeBrushes() {
2530
- return _chunkBXMIBMVGcjs.BUILTIN_BRUSHES.filter((b) => _chunkLRRCMRSLcjs.isBrushstrokeBrush.call(void 0, b));
2530
+ return _chunkJGKCC5OFcjs.BUILTIN_BRUSHES.filter((b) => _chunkEBDCRTZIcjs.isBrushstrokeBrush.call(void 0, b));
2531
2531
  }
2532
2532
  function vectorBrushstrokeBrush(id) {
2533
2533
  return _nullishCoalesce(vectorBrushstrokeBrushes().find((b) => b.id === id), () => ( null));
@@ -2558,7 +2558,7 @@ function sanitizeVectorBrushstrokePaper(value) {
2558
2558
  if (!value || typeof value !== "object") return null;
2559
2559
  const r = value;
2560
2560
  const out = {};
2561
- if (typeof r.pattern === "string" && _chunkLRRCMRSLcjs.GRAIN_PATTERNS.includes(r.pattern)) out.pattern = r.pattern;
2561
+ if (typeof r.pattern === "string" && _chunkEBDCRTZIcjs.GRAIN_PATTERNS.includes(r.pattern)) out.pattern = r.pattern;
2562
2562
  const seed = sanitizeSeed(r.seed);
2563
2563
  if (seed !== void 0) out.seed = seed;
2564
2564
  if (finite2(r.scale) && r.scale > 0) out.scale = Math.min(8, Math.max(0.25, r.scale));
@@ -2573,7 +2573,7 @@ function vectorBrushstrokeCharacterError(brush) {
2573
2573
  const r = paper;
2574
2574
  const extra = Object.keys(r).filter((k) => !["pattern", "seed", "scale", "depth"].includes(k));
2575
2575
  if (extra.length) return `paper has unknown field ${extra.map((k) => `"${k}"`).join(", ")}: use pattern, seed, scale, depth.`;
2576
- if (r.pattern !== void 0 && !_chunkLRRCMRSLcjs.GRAIN_PATTERNS.includes(r.pattern)) return `Unknown paper pattern "${String(r.pattern)}": use one of ${_chunkLRRCMRSLcjs.GRAIN_PATTERNS.join(", ")}.`;
2576
+ if (r.pattern !== void 0 && !_chunkEBDCRTZIcjs.GRAIN_PATTERNS.includes(r.pattern)) return `Unknown paper pattern "${String(r.pattern)}": use one of ${_chunkEBDCRTZIcjs.GRAIN_PATTERNS.join(", ")}.`;
2577
2577
  if (r.seed !== void 0 && !(Number.isInteger(r.seed) && r.seed >= 0 && r.seed <= VECTOR_BRUSHSTROKE_MAX_SEED)) return `paper.seed must be an integer from 0 to ${VECTOR_BRUSHSTROKE_MAX_SEED}.`;
2578
2578
  if (r.scale !== void 0 && !(finite2(r.scale) && r.scale >= 0.25 && r.scale <= 8)) return "paper.scale must be from 0.25 to 8 (1 is the pattern's natural size).";
2579
2579
  if (r.depth !== void 0 && !(finite2(r.depth) && r.depth >= 0 && r.depth <= 1)) return "paper.depth must be from 0 to 1.";
@@ -2589,7 +2589,7 @@ function vectorBrushstrokeReach(layer) {
2589
2589
  if (!isVectorBrushstrokeLayer(layer)) return 0;
2590
2590
  return (_nullishCoalesce(layer.brush.size, () => ( vectorBrushstrokeBrush(layer.brush.brushId).tip.size))) / 2;
2591
2591
  }
2592
- var cache = new (0, _chunkLRRCMRSLcjs.BrushstrokeCache)(256);
2592
+ var cache = new (0, _chunkEBDCRTZIcjs.BrushstrokeCache)(256);
2593
2593
  var urls = /* @__PURE__ */ new WeakMap();
2594
2594
  var layerCache = /* @__PURE__ */ new WeakMap();
2595
2595
  function vectorBrushstrokeImages(node, layer) {
@@ -2614,7 +2614,7 @@ function vectorBrushstrokeImages(node, layer) {
2614
2614
  const stroke = cache.render({ points: ring.map(([x, y]) => ({ x, y })), ...layer.brush.pressure ? { pressure: layer.brush.pressure } : {} }, brush, { scale: VECTOR_BRUSHSTROKE_SCALE, color: color2, maxPixels: 2048 * 2048, ...character });
2615
2615
  if (!stroke.bounds) continue;
2616
2616
  let href = urls.get(stroke);
2617
- if (!href) urls.set(stroke, href = _chunkLRRCMRSLcjs.brushstrokeDataUrl.call(void 0, stroke));
2617
+ if (!href) urls.set(stroke, href = _chunkEBDCRTZIcjs.brushstrokeDataUrl.call(void 0, stroke));
2618
2618
  out.push({ href, ...stroke.bounds });
2619
2619
  }
2620
2620
  }
@@ -44,7 +44,7 @@ var _chunk55AKPTLMcjs = require('./chunk-55AKPTLM.cjs');
44
44
  var _chunkN3KJFGXTcjs = require('./chunk-N3KJFGXT.cjs');
45
45
 
46
46
 
47
- var _chunk5H2C3QSFcjs = require('./chunk-5H2C3QSF.cjs');
47
+ var _chunkM4MIZPQIcjs = require('./chunk-M4MIZPQI.cjs');
48
48
 
49
49
  // src/spreadsheet/formula/dependency-graph.ts
50
50
  function extractNameDependencies(node) {
@@ -6440,7 +6440,7 @@ function checkWorkbook(document) {
6440
6440
  if (document.names !== void 0 && !Array.isArray(document.names)) throw new Error(`names must be an array. ${hint}`);
6441
6441
  }
6442
6442
  function createSpreadsheetEditorDocument(controller) {
6443
- return _chunk5H2C3QSFcjs.defineEditorDocument.call(void 0, {
6443
+ return _chunkM4MIZPQIcjs.defineEditorDocument.call(void 0, {
6444
6444
  kind: "spreadsheet",
6445
6445
  get: () => controller.getWorkbook(),
6446
6446
  load: (document, { history }) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineEditorDocument
3
- } from "./chunk-GNV54DLO.js";
3
+ } from "./chunk-NHLYK3AX.js";
4
4
  import {
5
5
  hexToRgba,
6
6
  normalizeTokenColor
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
2
2
 
3
- var _chunk5H2C3QSFcjs = require('./chunk-5H2C3QSF.cjs');
3
+ var _chunkM4MIZPQIcjs = require('./chunk-M4MIZPQI.cjs');
4
4
 
5
5
 
6
6
 
@@ -1275,7 +1275,7 @@ function importW3CTokens(state, input, options = {}) {
1275
1275
 
1276
1276
  // src/tokens/editorDocument.ts
1277
1277
  function createTokensEditorDocument(store) {
1278
- return _chunk5H2C3QSFcjs.defineEditorDocument.call(void 0, {
1278
+ return _chunkM4MIZPQIcjs.defineEditorDocument.call(void 0, {
1279
1279
  kind: "tokens",
1280
1280
  get: () => store.toJSON(),
1281
1281
  load: (document, { history }) => {
@@ -18,7 +18,7 @@ import {
18
18
  unionBounds,
19
19
  vectorGradientPoints,
20
20
  widthProfileAt
21
- } from "./chunk-FLOGD3QB.js";
21
+ } from "./chunk-6UPGM3JB.js";
22
22
  import {
23
23
  segmentLength,
24
24
  segmentParamAtLength,
@@ -44,7 +44,7 @@ import {
44
44
  } from "./chunk-WJSD3MAZ.js";
45
45
  import {
46
46
  defineEditorDocument
47
- } from "./chunk-GNV54DLO.js";
47
+ } from "./chunk-NHLYK3AX.js";
48
48
 
49
49
  // src/spreadsheet/formula/dependency-graph.ts
50
50
  function extractNameDependencies(node) {
@@ -89,7 +89,7 @@ import {
89
89
  textRectPath,
90
90
  translateMatrix,
91
91
  warpPresetMesh
92
- } from "./chunk-FLOGD3QB.js";
92
+ } from "./chunk-6UPGM3JB.js";
93
93
  import {
94
94
  bezierPathBounds,
95
95
  outlineStroke,
@@ -126,8 +126,7 @@ var _chunkZVNAMTFOcjs = require('../chunk-ZVNAMTFO.cjs');
126
126
  var _chunkSWTUM32Hcjs = require('../chunk-SWTUM32H.cjs');
127
127
 
128
128
 
129
- var _chunk5H2C3QSFcjs = require('../chunk-5H2C3QSF.cjs');
130
- require('../chunk-L5OWG2NA.cjs');
129
+ var _chunkM4MIZPQIcjs = require('../chunk-M4MIZPQI.cjs');
131
130
  require('../chunk-2BSBFBOA.cjs');
132
131
 
133
132
 
@@ -138,7 +137,7 @@ var DIRECTIONS = ["TB", "TD", "BT", "LR", "RL"];
138
137
 
139
138
  // src/diagram/editorDocument.ts
140
139
  function createDiagramEditorDocument(controller) {
141
- return _chunk5H2C3QSFcjs.defineEditorDocument.call(void 0, {
140
+ return _chunkM4MIZPQIcjs.defineEditorDocument.call(void 0, {
142
141
  kind: "diagram",
143
142
  get: () => ({ source: controller.getSource() }),
144
143
  load: (document, { history }) => {
@@ -126,8 +126,7 @@ import {
126
126
  } from "../chunk-O2ANJFUF.js";
127
127
  import {
128
128
  defineEditorDocument
129
- } from "../chunk-GNV54DLO.js";
130
- import "../chunk-WHKNYFM2.js";
129
+ } from "../chunk-NHLYK3AX.js";
131
130
  import "../chunk-HF5QZS7Z.js";
132
131
  import {
133
132
  HistoryManager
@@ -646,6 +646,14 @@ export declare class ImageEditorController {
646
646
  get historyBytes(): number;
647
647
  private trimHistoryBytes;
648
648
  get canUndo(): boolean;
649
+ private docRevision;
650
+ /**
651
+ * Bumped on every change to the document (an undoable edit, a stroke, undo, redo), not on view
652
+ * or tool changes, nor on `loadImage` (the source image is the host's, not part of the document). `createImageEditorDocument` uses it to tell document changes apart.
653
+ */
654
+ get documentRevision(): number;
655
+ /** Drops the undo and redo steps (e.g. after opening a document). */
656
+ clearHistory(): void;
649
657
  get canRedo(): boolean;
650
658
  undo(): boolean;
651
659
  redo(): boolean;
@@ -646,6 +646,14 @@ export declare class ImageEditorController {
646
646
  get historyBytes(): number;
647
647
  private trimHistoryBytes;
648
648
  get canUndo(): boolean;
649
+ private docRevision;
650
+ /**
651
+ * Bumped on every change to the document (an undoable edit, a stroke, undo, redo), not on view
652
+ * or tool changes, nor on `loadImage` (the source image is the host's, not part of the document). `createImageEditorDocument` uses it to tell document changes apart.
653
+ */
654
+ get documentRevision(): number;
655
+ /** Drops the undo and redo steps (e.g. after opening a document). */
656
+ clearHistory(): void;
649
657
  get canRedo(): boolean;
650
658
  undo(): boolean;
651
659
  redo(): boolean;
@@ -0,0 +1,16 @@
1
+ import { type EditorAssetRegistry } from '../persistence/assets.cjs';
2
+ import { type EditorDocument } from '../persistence/editorDocument.cjs';
3
+ import type { ImageEditorController } from './controller.cjs';
4
+ import type { SerializedImageEditorState } from './types.cjs';
5
+ export interface ImageEditorDocumentOptions {
6
+ /** Where layer pixels are kept (default: a registry of its own). Share one between editors to share assets. */
7
+ assets?: EditorAssetRegistry;
8
+ }
9
+ /**
10
+ * The save / load / undo contract for an `ImageEditorController` (kind `image`, document: the
11
+ * saved state from `toJSON()`, with layer pixels, masks and other images as asset references kept
12
+ * in `assets`). The source image (`sourceUrl`) stays the host's, as in `toJSON()`. Agent loads are
13
+ * one undo step; opening (`history: "reset"`) clears the history. A document from a newer build is
14
+ * refused rather than opened read-only.
15
+ */
16
+ export declare function createImageEditorDocument(controller: ImageEditorController, options?: ImageEditorDocumentOptions): EditorDocument<SerializedImageEditorState>;
@@ -0,0 +1,16 @@
1
+ import { type EditorAssetRegistry } from '../persistence/assets.js';
2
+ import { type EditorDocument } from '../persistence/editorDocument.js';
3
+ import type { ImageEditorController } from './controller.js';
4
+ import type { SerializedImageEditorState } from './types.js';
5
+ export interface ImageEditorDocumentOptions {
6
+ /** Where layer pixels are kept (default: a registry of its own). Share one between editors to share assets. */
7
+ assets?: EditorAssetRegistry;
8
+ }
9
+ /**
10
+ * The save / load / undo contract for an `ImageEditorController` (kind `image`, document: the
11
+ * saved state from `toJSON()`, with layer pixels, masks and other images as asset references kept
12
+ * in `assets`). The source image (`sourceUrl`) stays the host's, as in `toJSON()`. Agent loads are
13
+ * one undo step; opening (`history: "reset"`) clears the history. A document from a newer build is
14
+ * refused rather than opened read-only.
15
+ */
16
+ export declare function createImageEditorDocument(controller: ImageEditorController, options?: ImageEditorDocumentOptions): EditorDocument<SerializedImageEditorState>;