@pixerate/editor 0.246.0 → 0.249.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 (105) hide show
  1. package/README.md +1 -0
  2. package/dist/animation-editor/index.cjs +64 -61
  3. package/dist/animation-editor/index.js +8 -5
  4. package/dist/{brushstrokeRender-ZDHMXJAE.cjs → brushstrokeRender-GCKK7V2I.cjs} +14 -11
  5. package/dist/{brushstrokeRender-AKUI3SEJ.js → brushstrokeRender-T3JZST44.js} +7 -4
  6. package/dist/canvas/index.cjs +8 -8
  7. package/dist/canvas/index.js +1 -1
  8. package/dist/{chunk-UVPD55UZ.cjs → chunk-2SMMZDMG.cjs} +35 -35
  9. package/dist/chunk-2VJAVXLI.js +192 -0
  10. package/dist/{chunk-OLNIPTB3.cjs → chunk-2VX55NFM.cjs} +1 -320
  11. package/dist/chunk-3K6HWEXZ.cjs +92 -0
  12. package/dist/{chunk-UOOK7HTX.js → chunk-3PPJRMIG.js} +1 -1
  13. package/dist/chunk-4D6KP5BV.js +92 -0
  14. package/dist/chunk-5RH3VXAK.js +269 -0
  15. package/dist/{chunk-LDPLEZ5T.js → chunk-6BIDVPED.js} +1 -1
  16. package/dist/{chunk-2ONK3ERD.cjs → chunk-75K3W4D6.cjs} +20 -20
  17. package/dist/chunk-BOHDJJ2O.cjs +192 -0
  18. package/dist/{chunk-2PBZBRP5.js → chunk-D5KGAO4Z.js} +10 -92
  19. package/dist/{chunk-DQWPMGH2.js → chunk-DOIU7VJG.js} +1 -1
  20. package/dist/{chunk-HB4ICNNA.cjs → chunk-DPYAO5U6.cjs} +42 -42
  21. package/dist/chunk-EJLRBS5Q.js +301 -0
  22. package/dist/{chunk-Q2UYUWAZ.cjs → chunk-H4AOUUBE.cjs} +679 -164
  23. package/dist/{chunk-PQ3H2AAN.cjs → chunk-I7NJPHWV.cjs} +122 -204
  24. package/dist/{chunk-FK5LTDOO.cjs → chunk-IOFVM3L3.cjs} +7 -7
  25. package/dist/{chunk-42TWUPNJ.js → chunk-IRSTHLQQ.js} +1 -320
  26. package/dist/{chunk-VDAWA546.js → chunk-J7T5QZ45.js} +614 -99
  27. package/dist/{chunk-VMROIWLL.cjs → chunk-KBYB7OWB.cjs} +3 -3
  28. package/dist/{chunk-5MFDD7SP.cjs → chunk-KYX7NZ5V.cjs} +1 -1
  29. package/dist/chunk-LJRCU3BJ.cjs +301 -0
  30. package/dist/{chunk-XTWXBQD4.cjs → chunk-LP2MCSBE.cjs} +593 -236
  31. package/dist/{chunk-A23PSOBB.js → chunk-O75V4ZS3.js} +1 -1
  32. package/dist/chunk-OTTT5N3K.js +322 -0
  33. package/dist/{chunk-N6WUB3Y5.js → chunk-PZP2SZIZ.js} +2 -2
  34. package/dist/{chunk-4PMCMWQS.js → chunk-UBRJOIR5.js} +367 -10
  35. package/dist/chunk-W5M3J7PV.cjs +322 -0
  36. package/dist/{chunk-4P6H35HU.js → chunk-WA44NKPF.js} +2 -2
  37. package/dist/{chunk-CEPKXLBS.cjs → chunk-WLJZZHUZ.cjs} +23 -23
  38. package/dist/{chunk-P3NIPIKS.js → chunk-WQCNC4DK.js} +1 -1
  39. package/dist/chunk-ZEYMKDYS.cjs +269 -0
  40. package/dist/image-editor/effect-tools.d.cts +37 -4
  41. package/dist/image-editor/effect-tools.d.ts +37 -4
  42. package/dist/image-editor/index.cjs +1340 -1828
  43. package/dist/image-editor/index.d.cts +1 -1
  44. package/dist/image-editor/index.d.ts +1 -1
  45. package/dist/image-editor/index.js +298 -786
  46. package/dist/paint/index.cjs +8 -5
  47. package/dist/paint/index.js +13 -10
  48. package/dist/paint-editor/controller.d.cts +71 -2
  49. package/dist/paint-editor/controller.d.ts +71 -2
  50. package/dist/paint-editor/index.cjs +901 -589
  51. package/dist/paint-editor/index.d.cts +3 -0
  52. package/dist/paint-editor/index.d.ts +3 -0
  53. package/dist/paint-editor/index.js +365 -53
  54. package/dist/paint-editor/procedural.d.cts +82 -5
  55. package/dist/paint-editor/procedural.d.ts +82 -5
  56. package/dist/paint-editor/sticker-art.d.cts +55 -0
  57. package/dist/paint-editor/sticker-art.d.ts +55 -0
  58. package/dist/paint-editor/stickers.d.cts +30 -17
  59. package/dist/paint-editor/stickers.d.ts +30 -17
  60. package/dist/paint-editor/stroke.d.cts +4 -0
  61. package/dist/paint-editor/stroke.d.ts +4 -0
  62. package/dist/paint-editor/tools.d.cts +1 -1
  63. package/dist/paint-editor/tools.d.ts +1 -1
  64. package/dist/paint-editor/ui.d.cts +25 -4
  65. package/dist/paint-editor/ui.d.ts +25 -4
  66. package/dist/{image-editor/layers/effects-ui.d.cts → raster/effects/ui.d.cts} +32 -5
  67. package/dist/{image-editor/layers/effects-ui.d.ts → raster/effects/ui.d.ts} +32 -5
  68. package/dist/raster/index.cjs +17 -3
  69. package/dist/raster/index.d.cts +1 -0
  70. package/dist/raster/index.d.ts +1 -0
  71. package/dist/raster/index.js +23 -9
  72. package/dist/stickers/browser.d.cts +48 -0
  73. package/dist/stickers/browser.d.ts +48 -0
  74. package/dist/stickers/combine.d.cts +10 -0
  75. package/dist/stickers/combine.d.ts +10 -0
  76. package/dist/stickers/conformance.d.cts +18 -0
  77. package/dist/stickers/conformance.d.ts +18 -0
  78. package/dist/stickers/editor.d.cts +14 -0
  79. package/dist/stickers/editor.d.ts +14 -0
  80. package/dist/stickers/errors.d.cts +6 -0
  81. package/dist/stickers/errors.d.ts +6 -0
  82. package/dist/stickers/fake.d.cts +16 -0
  83. package/dist/stickers/fake.d.ts +16 -0
  84. package/dist/stickers/helpers.d.cts +51 -0
  85. package/dist/stickers/helpers.d.ts +51 -0
  86. package/dist/stickers/index.cjs +331 -0
  87. package/dist/stickers/index.d.cts +16 -0
  88. package/dist/stickers/index.d.ts +16 -0
  89. package/dist/stickers/index.js +331 -0
  90. package/dist/stickers/stamps.d.cts +13 -0
  91. package/dist/stickers/stamps.d.ts +13 -0
  92. package/dist/stickers/tools.d.cts +25 -0
  93. package/dist/stickers/tools.d.ts +25 -0
  94. package/dist/stickers/types.d.cts +123 -0
  95. package/dist/stickers/types.d.ts +123 -0
  96. package/dist/vector/index.cjs +978 -975
  97. package/dist/vector/index.js +9 -6
  98. package/package.json +11 -1
  99. package/skills/README.md +1 -0
  100. package/skills/pixerate-paint-editor/SKILL.md +26 -32
  101. package/skills/pixerate-paint-editor/references/gradient-paint.md +23 -0
  102. package/skills/pixerate-paint-editor/references/layer-effects.md +28 -0
  103. package/skills/pixerate-paint-editor/references/light-paint.md +10 -2
  104. package/skills/pixerate-paint-editor/references/particle-brushes.md +66 -0
  105. package/skills/pixerate-stickers/SKILL.md +45 -0
@@ -0,0 +1,269 @@
1
+ import {
2
+ hash2
3
+ } from "./chunk-4D6KP5BV.js";
4
+
5
+ // src/stickers/stamps.ts
6
+ var STAMP_KINDS = ["dot", "star", "heart", "leaf", "flower", "confetti", "splat", "sparkle", "ring"];
7
+ function stampCoverage(kind, u, v, t) {
8
+ const r = Math.hypot(u, v);
9
+ const a = Math.atan2(v, u);
10
+ const edge = (d) => Math.min(1, Math.max(0, d * 24 + 0.5));
11
+ switch (kind) {
12
+ case "dot":
13
+ return edge(0.95 - r);
14
+ case "ring":
15
+ return edge(Math.min(0.95 - r, r - 0.6));
16
+ case "star": {
17
+ const f = (a + Math.PI / 2) * 5 / (2 * Math.PI) % 1;
18
+ const notch = Math.min(f < 0 ? f + 1 : f, 1 - (f < 0 ? f + 1 : f)) * 2;
19
+ return edge(0.95 - 0.55 * notch - r);
20
+ }
21
+ case "sparkle": {
22
+ const q = Math.pow(Math.abs(u) / 0.95, 0.6) + Math.pow(Math.abs(v) / 0.95, 0.6);
23
+ return edge((1 - q) * 0.4);
24
+ }
25
+ case "heart": {
26
+ const x = u * 1.1;
27
+ const y = -v * 1.1 + 0.15;
28
+ const q = x * x + y * y - 0.55;
29
+ return edge(-(q * q * q - x * x * y * y * y) * 3);
30
+ }
31
+ case "leaf": {
32
+ const w = 0.42 * Math.sqrt(Math.max(0, 1 - u * u));
33
+ const inside = edge(w - Math.abs(v + 0.15 * u * u));
34
+ const rib = Math.abs(v + 0.15 * u * u) < 0.03 && Math.abs(u) < 0.85 ? 0.65 : 1;
35
+ return inside * rib;
36
+ }
37
+ case "flower": {
38
+ const petals = 0.6 + 0.35 * Math.abs(Math.cos(2.5 * a));
39
+ const body = edge(petals - r);
40
+ return r < 0.22 ? Math.max(body, 1) * 0.85 : body;
41
+ }
42
+ case "confetti": {
43
+ return edge(Math.min(0.9 - Math.abs(u), 0.35 - Math.abs(v)));
44
+ }
45
+ case "splat": {
46
+ let rr = 0.55;
47
+ for (let k = 1; k <= 3; k++) rr += 0.08 * Math.sin(a * (k + 2) + hash2(k, 1, t) * 6.28) / k;
48
+ let c = edge(rr - r);
49
+ for (let k = 0; k < 4; k++) {
50
+ const ang = hash2(k, 7, t) * Math.PI * 2;
51
+ const dist = 0.72 + 0.2 * hash2(k, 9, t);
52
+ const dx = u - Math.cos(ang) * dist;
53
+ const dy = v - Math.sin(ang) * dist;
54
+ c = Math.max(c, edge(0.08 + 0.06 * hash2(k, 11, t) - Math.hypot(dx, dy)));
55
+ }
56
+ return c;
57
+ }
58
+ }
59
+ }
60
+
61
+ // src/stickers/errors.ts
62
+ var StickerError = class extends Error {
63
+ constructor(code, message) {
64
+ super(message);
65
+ this.code = code;
66
+ this.name = "StickerError";
67
+ }
68
+ code;
69
+ };
70
+
71
+ // src/stickers/helpers.ts
72
+ var DEFAULT_STICKER_PAGE = 24;
73
+ var MAX_STICKER_PAGE = 100;
74
+ var EDITOR_STICKERS_ID = "editor";
75
+ function checkStickerSearchOptions(options = {}) {
76
+ if (options.limit !== void 0 && !(Number.isInteger(options.limit) && options.limit >= 1 && options.limit <= MAX_STICKER_PAGE)) {
77
+ throw new StickerError("invalid_argument", `limit must be a whole number from 1 to ${MAX_STICKER_PAGE}, got ${options.limit}.`);
78
+ }
79
+ if (options.after !== void 0 && !/^\d+$/.test(options.after)) throw new StickerError("invalid_argument", `after "${options.after}" is not a cursor from this provider; pass the next value of the previous page.`);
80
+ }
81
+ var words = (s) => s.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter(Boolean);
82
+ function stickerPage(items, options = {}, query = "") {
83
+ checkStickerSearchOptions(options);
84
+ const q = words(query);
85
+ const tags = (options.tags ?? []).map((t) => t.toLowerCase());
86
+ const matches = items.filter((s) => {
87
+ if (options.category && s.category !== options.category) return false;
88
+ if (tags.length && !tags.every((t) => (s.tags ?? []).some((x) => x.toLowerCase() === t))) return false;
89
+ if (options.licence?.commercial === true && !s.licence.commercial) return false;
90
+ if (!q.length) return true;
91
+ const text = new Set(words([s.name, s.category, s.description ?? "", ...s.tags ?? []].join(" ")));
92
+ return q.every((w) => [...text].some((t) => t.startsWith(w)));
93
+ });
94
+ const start = options.after ? Number(options.after) : 0;
95
+ const limit = options.limit ?? DEFAULT_STICKER_PAGE;
96
+ const page = matches.slice(start, start + limit);
97
+ return { items: page, total: matches.length, ...start + limit < matches.length ? { next: String(start + limit) } : {} };
98
+ }
99
+ function parseStickerRef(ref) {
100
+ if (typeof ref !== "string" || !ref) throw new StickerError("invalid_argument", 'A sticker ref is a "provider:id" string, e.g. "editor:star" (find_stickers lists them).');
101
+ const i = ref.indexOf(":");
102
+ if (i === -1) {
103
+ if (STAMP_KINDS.includes(ref)) return { provider: EDITOR_STICKERS_ID, id: ref };
104
+ throw new StickerError("invalid_argument", `"${ref}" is not a sticker ref; refs are "provider:id" (e.g. "editor:${STAMP_KINDS[1]}"); find_stickers lists them.`);
105
+ }
106
+ if (i === 0 || i === ref.length - 1) throw new StickerError("invalid_argument", `"${ref}" is not a sticker ref; refs are "provider:id".`);
107
+ return { provider: ref.slice(0, i), id: ref.slice(i + 1) };
108
+ }
109
+ function normalizeStickerRef(ref) {
110
+ const { provider, id } = parseStickerRef(ref);
111
+ return `${provider}:${id}`;
112
+ }
113
+ function editorStampOf(ref) {
114
+ const { provider, id } = parseStickerRef(ref);
115
+ return provider === EDITOR_STICKERS_ID && STAMP_KINDS.includes(id) ? id : null;
116
+ }
117
+ function stickerRefOf(provider, id) {
118
+ return provider.namespaced ? id : `${provider.id}:${id}`;
119
+ }
120
+ function stickerIdFor(provider, ref) {
121
+ const { provider: owner, id } = parseStickerRef(ref);
122
+ if (provider.namespaced) return `${owner}:${id}`;
123
+ return owner === provider.id ? id : null;
124
+ }
125
+ function closestStickerRefs(wanted, candidates, n = 3) {
126
+ const w = wanted.toLowerCase();
127
+ const dist = (a, b) => {
128
+ const d = Array.from({ length: b.length + 1 }, (_, j) => j);
129
+ for (let i = 1; i <= a.length; i++) {
130
+ let prev = d[0];
131
+ d[0] = i;
132
+ for (let j = 1; j <= b.length; j++) {
133
+ const tmp = d[j];
134
+ d[j] = Math.min(d[j] + 1, d[j - 1] + 1, prev + (a[i - 1] === b[j - 1] ? 0 : 1));
135
+ prev = tmp;
136
+ }
137
+ }
138
+ return d[b.length];
139
+ };
140
+ return [...candidates].sort((a, b) => dist(w, a.toLowerCase()) - dist(w, b.toLowerCase()) || a.localeCompare(b)).slice(0, n);
141
+ }
142
+ var StickersSlot = class {
143
+ constructor(fallback) {
144
+ this.fallback = fallback;
145
+ this.current = fallback;
146
+ }
147
+ fallback;
148
+ current;
149
+ listeners = /* @__PURE__ */ new Set();
150
+ get provider() {
151
+ return this.current;
152
+ }
153
+ set(provider) {
154
+ const next = provider ?? this.fallback;
155
+ if (next === this.current) return;
156
+ this.current = next;
157
+ for (const l of [...this.listeners]) l(next);
158
+ }
159
+ subscribe(listener) {
160
+ this.listeners.add(listener);
161
+ return () => this.listeners.delete(listener);
162
+ }
163
+ };
164
+
165
+ // src/stickers/tools.ts
166
+ var READ = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
167
+ function stickerForAgent(provider, s) {
168
+ const { id, thumbnail: _thumbnail, ...rest } = s;
169
+ return { ref: stickerRefOf(provider, id), ...rest };
170
+ }
171
+ async function knownRefs(provider, cap = 500) {
172
+ const refs = [];
173
+ let after;
174
+ while (refs.length < cap) {
175
+ const page = await provider.list({ limit: MAX_STICKER_PAGE, ...after ? { after } : {} });
176
+ refs.push(...page.items.map((s) => stickerRefOf(provider, s.id)));
177
+ if (!page.next || !page.items.length) break;
178
+ after = page.next;
179
+ }
180
+ return refs;
181
+ }
182
+ async function describeStickerRef(provider, ref) {
183
+ parseStickerRef(ref);
184
+ const id = stickerIdFor(provider, ref);
185
+ const found = id === null ? void 0 : await provider.describe(id);
186
+ if (found) return found;
187
+ const near = closestStickerRefs(ref, await knownRefs(provider));
188
+ const owner = parseStickerRef(ref).provider;
189
+ const where = id === null && !provider.namespaced ? ` The sticker library is "${provider.id}", not "${owner}".` : "";
190
+ throw new StickerError("unknown_sticker", `No sticker "${ref}".${where} Closest: ${near.join(", ") || "none"}; find_stickers lists them.`);
191
+ }
192
+ function createStickerTools(options) {
193
+ const find = {
194
+ name: "find_stickers",
195
+ title: "Find stickers",
196
+ description: "Searches the sticker library (the editor's own stamps unless the host plugged in its own): words in the name, tags, category or description, filtered by category, tags and commercial licence, a small page at a time. Returns each sticker's ref (provider:id, for the tools that spray or place stickers), name, category, tags, natural width and height, formats, whether it is tintable (recoloured to the paint colour) and its licence, plus total and next (pass as after for the next page) and the categories. Changes nothing.",
197
+ inputSchema: {
198
+ type: "object",
199
+ properties: {
200
+ query: { type: "string", maxLength: 200, description: "Words to match (default: list everything)." },
201
+ category: { type: "string", description: "Only this category (the result lists them)." },
202
+ tags: { type: "array", maxItems: 10, items: { type: "string", description: "A tag." }, description: "Only stickers with every one of these tags." },
203
+ commercial: { type: "boolean", description: "true: only stickers whose licence allows commercial use." },
204
+ limit: { type: "integer", minimum: 1, maximum: MAX_STICKER_PAGE, description: "Page size (default 24)." },
205
+ after: { type: "string", description: "next from the previous page." }
206
+ },
207
+ additionalProperties: false
208
+ },
209
+ annotations: { title: "Find stickers", ...READ },
210
+ handler: async ({ query, category, tags, commercial, limit, after }) => {
211
+ const p = options.provider();
212
+ const categories = await p.categories?.() ?? null;
213
+ if (category !== void 0 && categories && !categories.some((c) => c.id === category)) {
214
+ throw new StickerError("invalid_argument", `No category "${category}" in "${p.name}"; categories: ${categories.map((c) => c.id).join(", ")}.`);
215
+ }
216
+ const o = { ...category !== void 0 ? { category } : {}, ...tags ? { tags } : {}, ...commercial ? { licence: { commercial: true } } : {}, ...limit !== void 0 ? { limit } : {}, ...after !== void 0 ? { after } : {} };
217
+ const q = typeof query === "string" ? query.trim() : "";
218
+ if (q && !p.capabilities.supportsSearch) throw new StickerError("invalid_argument", `"${p.name}" can't search; leave query out and filter by category instead.`);
219
+ const page = q ? await p.search(q, o) : await p.list(o);
220
+ return { provider: p.id, items: page.items.map((s) => stickerForAgent(p, s)), total: page.total, ...page.next ? { next: page.next } : {}, ...categories ? { categories } : {} };
221
+ }
222
+ };
223
+ const describe = {
224
+ name: "describe_sticker",
225
+ title: "Describe a sticker",
226
+ description: "Everything about one sticker by ref (from find_stickers): name, category, tags, natural size, formats, tintable, licence (with any attribution it asks for), dominant colours, variants and its outline as SVG path data (silhouette). An unknown ref is refused with the closest refs. Changes nothing.",
227
+ inputSchema: { type: "object", properties: { ref: { type: "string", description: "Sticker ref provider:id from find_stickers (e.g. editor:star)." } }, required: ["ref"], additionalProperties: false },
228
+ annotations: { title: "Describe a sticker", ...READ },
229
+ handler: async ({ ref }) => {
230
+ const p = options.provider();
231
+ const d = await describeStickerRef(p, ref);
232
+ const { thumbnail: _thumbnail, id, ...rest } = d;
233
+ return { ref: stickerRefOf(p, id), ...rest };
234
+ }
235
+ };
236
+ return [find, describe];
237
+ }
238
+ function createStickerToolProvider(options) {
239
+ return {
240
+ id: options.id ?? "stickers",
241
+ namespace: options.namespace,
242
+ title: "Stickers",
243
+ description: "Find and describe stickers from the sticker library, by ref (provider:id), for the editors that spray or place them.",
244
+ skill: "pixerate-stickers",
245
+ tools: createStickerTools(options)
246
+ };
247
+ }
248
+
249
+ export {
250
+ STAMP_KINDS,
251
+ stampCoverage,
252
+ StickerError,
253
+ DEFAULT_STICKER_PAGE,
254
+ MAX_STICKER_PAGE,
255
+ EDITOR_STICKERS_ID,
256
+ checkStickerSearchOptions,
257
+ stickerPage,
258
+ parseStickerRef,
259
+ normalizeStickerRef,
260
+ editorStampOf,
261
+ stickerRefOf,
262
+ stickerIdFor,
263
+ closestStickerRefs,
264
+ StickersSlot,
265
+ stickerForAgent,
266
+ describeStickerRef,
267
+ createStickerTools,
268
+ createStickerToolProvider
269
+ };
@@ -74,7 +74,7 @@ function profileAlongPolyline(points, values, count = 32) {
74
74
  var round3 = (v) => Math.round(v * 1e3) / 1e3;
75
75
  var loading = null;
76
76
  function loadCanvasBrushstrokeRenderer() {
77
- loading ??= import("./brushstrokeRender-AKUI3SEJ.js").catch((error) => {
77
+ loading ??= import("./brushstrokeRender-T3JZST44.js").catch((error) => {
78
78
  loading = null;
79
79
  throw error;
80
80
  });
@@ -13,12 +13,12 @@ var _chunkBB6TR422cjs = require('./chunk-BB6TR422.cjs');
13
13
 
14
14
 
15
15
 
16
- var _chunkPQ3H2AANcjs = require('./chunk-PQ3H2AAN.cjs');
16
+ var _chunkI7NJPHWVcjs = require('./chunk-I7NJPHWV.cjs');
17
17
 
18
18
 
19
19
 
20
20
 
21
- var _chunkOLNIPTB3cjs = require('./chunk-OLNIPTB3.cjs');
21
+ var _chunk2VX55NFMcjs = require('./chunk-2VX55NFM.cjs');
22
22
 
23
23
 
24
24
 
@@ -367,9 +367,9 @@ function applyRetouchToTile(coverage, tileData, channels, tx, ty, paint, s, opti
367
367
  const g0 = rgb[1];
368
368
  const b0 = rgb[2];
369
369
  paint.tone(rgb);
370
- _chunkPQ3H2AANcjs.put255.call(void 0, out, i, r0 + (rgb[0] - r0) * k);
371
- _chunkPQ3H2AANcjs.put255.call(void 0, out, i + 1, g0 + (rgb[1] - g0) * k);
372
- _chunkPQ3H2AANcjs.put255.call(void 0, out, i + 2, b0 + (rgb[2] - b0) * k);
370
+ _chunkI7NJPHWVcjs.put255.call(void 0, out, i, r0 + (rgb[0] - r0) * k);
371
+ _chunkI7NJPHWVcjs.put255.call(void 0, out, i + 1, g0 + (rgb[1] - g0) * k);
372
+ _chunkI7NJPHWVcjs.put255.call(void 0, out, i + 2, b0 + (rgb[2] - b0) * k);
373
373
  continue;
374
374
  }
375
375
  if (s.lockTransparency && a === 0) continue;
@@ -383,11 +383,11 @@ function applyRetouchToTile(coverage, tileData, channels, tx, ty, paint, s, opti
383
383
  cb[ch] = out[i + ch] / 255;
384
384
  cs[ch] = src[ch] / 255;
385
385
  }
386
- const o = _chunkOLNIPTB3cjs.blendPixel.call(void 0, blend, cb, cs, k);
387
- _chunkPQ3H2AANcjs.put255.call(void 0, out, i, o[0]);
388
- _chunkPQ3H2AANcjs.put255.call(void 0, out, i + 1, o[1]);
389
- _chunkPQ3H2AANcjs.put255.call(void 0, out, i + 2, o[2]);
390
- if (!s.lockTransparency) _chunkPQ3H2AANcjs.put255.call(void 0, out, i + 3, o[3]);
386
+ const o = _chunk2VX55NFMcjs.blendPixel.call(void 0, blend, cb, cs, k);
387
+ _chunkI7NJPHWVcjs.put255.call(void 0, out, i, o[0]);
388
+ _chunkI7NJPHWVcjs.put255.call(void 0, out, i + 1, o[1]);
389
+ _chunkI7NJPHWVcjs.put255.call(void 0, out, i + 2, o[2]);
390
+ if (!s.lockTransparency) _chunkI7NJPHWVcjs.put255.call(void 0, out, i + 3, o[3]);
391
391
  }
392
392
  }
393
393
  return out;
@@ -443,14 +443,14 @@ function applyToneToDeepTile(coverage, samples, tx, ty, tone, s, options = {}) {
443
443
  const v = out[i + ch];
444
444
  if (linear) {
445
445
  excess[ch] = v > 1 ? v - 1 : 0;
446
- rgb[ch] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, v > 1 ? 1 : v < 0 ? 0 : v);
446
+ rgb[ch] = _chunk2VX55NFMcjs.srgbEncode.call(void 0, v > 1 ? 1 : v < 0 ? 0 : v);
447
447
  } else rgb[ch] = v / 65535;
448
448
  before[ch] = rgb[ch];
449
449
  }
450
450
  tone(rgb);
451
451
  for (let ch = 0; ch < 3; ch++) {
452
452
  const e = before[ch] + (rgb[ch] - before[ch]) * k;
453
- if (linear) out[i + ch] = _chunkOLNIPTB3cjs.srgbDecode.call(void 0, e) + excess[ch];
453
+ if (linear) out[i + ch] = _chunk2VX55NFMcjs.srgbDecode.call(void 0, e) + excess[ch];
454
454
  else out[i + ch] = e <= 0 ? 0 : e >= 1 ? 65535 : Math.round(e * 65535);
455
455
  }
456
456
  }
@@ -535,8 +535,8 @@ var RetouchDabStroke = (_class3 = class {
535
535
  constructor(brush, target, effect) {;_class3.prototype.__init5.call(this);_class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);
536
536
  this.brush = brush;
537
537
  this.effect = effect;
538
- this.walker = new (0, _chunkPQ3H2AANcjs.DabWalker)(brush);
539
- this.medium = new (0, _chunkPQ3H2AANcjs.TileMedium)(target);
538
+ this.walker = new (0, _chunkI7NJPHWVcjs.DabWalker)(brush);
539
+ this.medium = new (0, _chunkI7NJPHWVcjs.TileMedium)(target);
540
540
  }
541
541
 
542
542
 
@@ -567,11 +567,11 @@ var RetouchDabStroke = (_class3 = class {
567
567
  paint(dabs) {
568
568
  const rects = [];
569
569
  for (const d of dabs) {
570
- const rect = _chunkPQ3H2AANcjs.dabRect.call(void 0, d, this.brush.hardness);
570
+ const rect = _chunkI7NJPHWVcjs.dabRect.call(void 0, d, this.brush.hardness);
571
571
  const n = rect.width * rect.height;
572
572
  if (this.buf.length < n) this.buf = new Float32Array(n);
573
573
  const cov = this.buf.subarray(0, n);
574
- _chunkPQ3H2AANcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.brush.hardness, rect, cov);
574
+ _chunkI7NJPHWVcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.brush.hardness, rect, cov);
575
575
  this.medium.reset();
576
576
  this.effect(this.medium, d, rect, cov);
577
577
  rects.push(rect);
@@ -583,7 +583,7 @@ var RetouchDabStroke = (_class3 = class {
583
583
  }, _class3);
584
584
  function smudgeEffect(brush, strength, mixing = "rgb") {
585
585
  const s = Math.min(1, Math.max(0, strength));
586
- const tip = new (0, _chunkPQ3H2AANcjs.SmudgeTip)({ strength: s, length: s, mixing }, brush.size);
586
+ const tip = new (0, _chunkI7NJPHWVcjs.SmudgeTip)({ strength: s, length: s, mixing }, brush.size);
587
587
  return (medium, d, rect, cov) => tip.dab(medium, { x: d.x, y: d.y, radius: d.radius, opacity: d.opacity * d.alpha }, rect, cov);
588
588
  }
589
589
  function spongeEffect(brush, saturate, vibrance) {
@@ -606,9 +606,9 @@ function spongeEffect(brush, saturate, vibrance) {
606
606
  rgb[1] = px[i + 1] / 255;
607
607
  rgb[2] = px[i + 2] / 255;
608
608
  sponge(rgb, k, saturate, vibrance);
609
- _chunkPQ3H2AANcjs.put255.call(void 0, px, i, rgb[0]);
610
- _chunkPQ3H2AANcjs.put255.call(void 0, px, i + 1, rgb[1]);
611
- _chunkPQ3H2AANcjs.put255.call(void 0, px, i + 2, rgb[2]);
609
+ _chunkI7NJPHWVcjs.put255.call(void 0, px, i, rgb[0]);
610
+ _chunkI7NJPHWVcjs.put255.call(void 0, px, i + 1, rgb[1]);
611
+ _chunkI7NJPHWVcjs.put255.call(void 0, px, i + 2, rgb[2]);
612
612
  }
613
613
  }
614
614
  };
@@ -0,0 +1,192 @@
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; }
2
+
3
+
4
+
5
+
6
+
7
+
8
+ var _chunkDPYAO5U6cjs = require('./chunk-DPYAO5U6.cjs');
9
+
10
+
11
+ var _chunk2VX55NFMcjs = require('./chunk-2VX55NFM.cjs');
12
+
13
+ // src/raster/effects/ui.ts
14
+ function layerEffectsPanel(layer) {
15
+ const empty = { readOnly: true, enabled: true, scale: 1, rows: [] };
16
+ if (!layer) return { ...empty, available: false, reason: "Select a layer to add a layer style." };
17
+ if (layer.type === "adjustment") return { ...empty, available: false, reason: "Adjustment layers cannot have a layer style." };
18
+ const fx = layer.effects;
19
+ const readOnly = Boolean(_optionalChain([layer, 'access', _ => _.locks, 'optionalAccess', _2 => _2.all]));
20
+ return {
21
+ available: true,
22
+ readOnly,
23
+ reason: readOnly ? "The layer is locked; unlock it to change its layer style." : void 0,
24
+ enabled: _nullishCoalesce(_optionalChain([fx, 'optionalAccess', _3 => _3.enabled]), () => ( true)),
25
+ scale: _nullishCoalesce(_optionalChain([fx, 'optionalAccess', _4 => _4.scale]), () => ( 1)),
26
+ rows: (_nullishCoalesce(_optionalChain([fx, 'optionalAccess', _5 => _5.items]), () => ( []))).map((e) => ({ id: e.id, kind: e.kind, label: _chunkDPYAO5U6cjs.layerEffectLabel.call(void 0, e.kind), enabled: e.enabled }))
27
+ };
28
+ }
29
+ function layerEffectsBadge(layer) {
30
+ if (!_optionalChain([layer, 'access', _6 => _6.effects, 'optionalAccess', _7 => _7.items, 'access', _8 => _8.length])) return null;
31
+ return _chunkDPYAO5U6cjs.hasActiveEffects.call(void 0, layer.effects) ? "on" : "off";
32
+ }
33
+ var LAYER_EFFECT_MENU = _chunkDPYAO5U6cjs.LAYER_EFFECT_KINDS.map((kind) => ({ kind, label: _chunkDPYAO5U6cjs.layerEffectLabel.call(void 0, kind) }));
34
+ var BLENDS = _chunk2VX55NFMcjs.BLEND_MODES.filter((m) => m.id !== "pigment").map((m) => ({ value: m.id, label: m.label }));
35
+ var opt = (...pairs) => pairs.map(([value, label]) => ({ value, label }));
36
+ function patternOptions(patterns) {
37
+ return [...patterns.map((p) => ({ value: p.id, label: p.name || p.id })), ..._chunkDPYAO5U6cjs.builtinPatternIds.call(void 0, ).map((id) => ({ value: id, label: _chunkDPYAO5U6cjs.builtinPattern.call(void 0, id).name }))];
38
+ }
39
+ function getPath(o, path) {
40
+ let v = o;
41
+ for (const p of path.split(".")) {
42
+ if (v === null || v === void 0) return void 0;
43
+ if (Array.isArray(v)) v = p === "last" ? v[v.length - 1] : v[Number(p)];
44
+ else v = v[p];
45
+ }
46
+ return v;
47
+ }
48
+ function setPath(o, parts, value) {
49
+ if (!parts.length) return value;
50
+ const [p, ...rest] = parts;
51
+ if (Array.isArray(o)) {
52
+ const i = p === "last" ? o.length - 1 : Number(p);
53
+ const out = [...o];
54
+ out[i] = setPath(o[i], rest, value);
55
+ return out;
56
+ }
57
+ const r = _nullishCoalesce(o, () => ( {}));
58
+ return { ...r, [p]: setPath(r[p], rest, value) };
59
+ }
60
+ function fillControls(f, allowPattern, patterns) {
61
+ const types = allowPattern ? opt(["color", "Color"], ["gradient", "Gradient"], ["pattern", "Pattern"]) : opt(["color", "Color"], ["gradient", "Gradient"]);
62
+ const out = [{ key: "fill.type", label: "Fill", type: "select", value: f.type, options: types }];
63
+ if (f.type === "color") out.push({ key: "fill.color", label: "Color", type: "color", value: f.color });
64
+ else if (f.type === "gradient") out.push(...gradientControls("fill.gradient", f.gradient));
65
+ else {
66
+ out.push(
67
+ { key: "fill.patternId", label: "Pattern", type: "select", value: f.patternId, options: patternOptions(patterns) },
68
+ { key: "fill.scale", label: "Scale", type: "range", min: 0.01, max: 10, step: 0.01, value: f.scale, percent: true, unit: "%" }
69
+ );
70
+ }
71
+ return out;
72
+ }
73
+ function gradientControls(prefix, g) {
74
+ return [
75
+ { key: `${prefix}.stops.0.color`, label: "Start colour", type: "color", value: _nullishCoalesce(_optionalChain([g, 'access', _9 => _9.stops, 'access', _10 => _10[0], 'optionalAccess', _11 => _11.color]), () => ( "#000000")) },
76
+ { key: `${prefix}.stops.last.color`, label: "End colour", type: "color", value: _nullishCoalesce(_optionalChain([g, 'access', _12 => _12.stops, 'access', _13 => _13[g.stops.length - 1], 'optionalAccess', _14 => _14.color]), () => ( "#ffffff")) },
77
+ { key: `${prefix}.style`, label: "Style", type: "select", value: g.style, options: opt(["linear", "Linear"], ["radial", "Radial"], ["angle", "Angle"], ["reflected", "Reflected"], ["diamond", "Diamond"]) },
78
+ { key: `${prefix}.angle`, label: "Angle", type: "range", min: -180, max: 180, step: 1, value: g.angle, unit: "\xB0" },
79
+ { key: `${prefix}.scale`, label: "Scale", type: "range", min: 0.1, max: 1.5, step: 0.01, value: g.scale, percent: true, unit: "%" },
80
+ { key: `${prefix}.reverse`, label: "Reverse", type: "checkbox", value: g.reverse },
81
+ { key: `${prefix}.align`, label: "Align with layer", type: "checkbox", value: g.align }
82
+ ];
83
+ }
84
+ var px = (key, label, value, max = 250) => ({ key, label, type: "range", min: 0, max, step: 1, value, unit: "px" });
85
+ var pct = (key, label, value, min = 0, max = 1) => ({ key, label, type: "range", min, max, step: 0.01, value, percent: true, unit: "%" });
86
+ var deg = (key, label, value, min = -180, max = 180) => ({ key, label, type: "range", min, max, step: 1, value, unit: "\xB0" });
87
+ function layerEffectControls(e, patterns = []) {
88
+ const blended = e.kind === "bevel-emboss" ? [] : [
89
+ { key: "blend", label: "Blend mode", type: "select", value: e.blend, options: BLENDS },
90
+ pct("opacity", "Opacity", e.opacity)
91
+ ];
92
+ switch (e.kind) {
93
+ case "drop-shadow":
94
+ case "inner-shadow":
95
+ return [
96
+ ...blended,
97
+ { key: "color", label: "Color", type: "color", value: e.color },
98
+ { key: "useGlobalLight", label: "Use global light", type: "checkbox", value: e.useGlobalLight },
99
+ deg("angle", "Angle", e.angle),
100
+ px("distance", "Distance", e.distance, 500),
101
+ e.kind === "drop-shadow" ? pct("spread", "Spread", e.spread) : pct("choke", "Choke", e.choke),
102
+ px("size", "Size", e.size),
103
+ pct("noise", "Noise", e.noise),
104
+ ...e.kind === "drop-shadow" ? [{ key: "knocksOut", label: "Layer knocks out shadow", type: "checkbox", value: e.knocksOut }] : []
105
+ ];
106
+ case "outer-glow":
107
+ case "inner-glow":
108
+ return [
109
+ ...blended,
110
+ ...fillControls(e.fill, false, patterns),
111
+ { key: "technique", label: "Technique", type: "select", value: e.technique, options: opt(["softer", "Softer"], ["precise", "Precise"]) },
112
+ ...e.kind === "inner-glow" ? [{ key: "source", label: "Source", type: "select", value: e.source, options: opt(["edge", "Edge"], ["center", "Center"]) }] : [],
113
+ e.kind === "outer-glow" ? pct("spread", "Spread", e.spread) : pct("choke", "Choke", e.choke),
114
+ px("size", "Size", e.size),
115
+ pct("range", "Range", e.range, 0.01, 1),
116
+ pct("noise", "Noise", e.noise)
117
+ ];
118
+ case "bevel-emboss":
119
+ return [
120
+ { key: "style", label: "Style", type: "select", value: e.style, options: opt(["inner-bevel", "Inner Bevel"], ["outer-bevel", "Outer Bevel"], ["emboss", "Emboss"], ["pillow-emboss", "Pillow Emboss"], ["stroke-emboss", "Stroke Emboss"]) },
121
+ { key: "technique", label: "Technique", type: "select", value: e.technique, options: opt(["smooth", "Smooth"], ["chisel-hard", "Chisel Hard"], ["chisel-soft", "Chisel Soft"]) },
122
+ pct("depth", "Depth", e.depth, 0, 10),
123
+ { key: "direction", label: "Direction", type: "select", value: e.direction, options: opt(["up", "Up"], ["down", "Down"]) },
124
+ px("size", "Size", e.size),
125
+ px("soften", "Soften", e.soften, 16),
126
+ { key: "useGlobalLight", label: "Use global light", type: "checkbox", value: e.useGlobalLight },
127
+ deg("angle", "Angle", e.angle),
128
+ deg("altitude", "Altitude", e.altitude, 0, 90),
129
+ { key: "highlightColor", label: "Highlight", type: "color", value: e.highlightColor },
130
+ { key: "highlightBlend", label: "Highlight mode", type: "select", value: e.highlightBlend, options: BLENDS },
131
+ pct("highlightOpacity", "Highlight opacity", e.highlightOpacity),
132
+ { key: "shadowColor", label: "Shadow", type: "color", value: e.shadowColor },
133
+ { key: "shadowBlend", label: "Shadow mode", type: "select", value: e.shadowBlend, options: BLENDS },
134
+ pct("shadowOpacity", "Shadow opacity", e.shadowOpacity)
135
+ ];
136
+ case "satin":
137
+ return [
138
+ ...blended,
139
+ { key: "color", label: "Color", type: "color", value: e.color },
140
+ deg("angle", "Angle", e.angle),
141
+ px("distance", "Distance", e.distance),
142
+ px("size", "Size", e.size),
143
+ { key: "invert", label: "Invert", type: "checkbox", value: e.invert }
144
+ ];
145
+ case "color-overlay":
146
+ return [...blended, { key: "color", label: "Color", type: "color", value: e.color }];
147
+ case "gradient-overlay":
148
+ return [...blended, ...gradientControls("gradient", e.gradient)];
149
+ case "pattern-overlay":
150
+ return [
151
+ ...blended,
152
+ { key: "patternId", label: "Pattern", type: "select", value: e.patternId, options: patternOptions(patterns) },
153
+ pct("scale", "Scale", e.scale, 0.01, 10),
154
+ deg("angle", "Angle", _nullishCoalesce(e.angle, () => ( 0))),
155
+ { key: "link", label: "Link with layer", type: "checkbox", value: _nullishCoalesce(e.link, () => ( true)) }
156
+ ];
157
+ case "stroke":
158
+ return [
159
+ ...blended,
160
+ px("size", "Size", e.size),
161
+ { key: "position", label: "Position", type: "select", value: e.position, options: opt(["outside", "Outside"], ["inside", "Inside"], ["center", "Center"]) },
162
+ ...fillControls(e.fill, true, patterns)
163
+ ];
164
+ }
165
+ }
166
+ function fillOfType(current, type, patterns) {
167
+ if (type === "gradient") return { type: "gradient", gradient: _chunkDPYAO5U6cjs.defaultEffectGradient.call(void 0, ) };
168
+ if (type === "pattern") return { type: "pattern", patternId: _nullishCoalesce(_optionalChain([patterns, 'access', _15 => _15[0], 'optionalAccess', _16 => _16.id]), () => ( "checker")), scale: 1 };
169
+ return { type: "color", color: current.type === "color" ? current.color : "#000000" };
170
+ }
171
+ function effectControlChange(effect, key, value, patterns = []) {
172
+ const [top, ...rest] = key.split(".");
173
+ if (top === "fill" && rest[0] === "type") return { fill: fillOfType(effect.fill, String(value), patterns) };
174
+ if (top === "patternId" && !rest.length) {
175
+ const name = _optionalChain([patternOptions, 'call', _17 => _17(patterns), 'access', _18 => _18.find, 'call', _19 => _19((o) => o.value === value), 'optionalAccess', _20 => _20.label]);
176
+ return name ? { patternId: value, name } : { patternId: value };
177
+ }
178
+ if (!rest.length) return { [top]: value };
179
+ if (top === "fill" && rest[0] === "patternId") {
180
+ const name = _optionalChain([patternOptions, 'call', _21 => _21(patterns), 'access', _22 => _22.find, 'call', _23 => _23((o) => o.value === value), 'optionalAccess', _24 => _24.label]);
181
+ return { fill: { ...effect.fill, patternId: value, ...name ? { name } : {} } };
182
+ }
183
+ return { [top]: setPath(getPath(effect, top), rest, value) };
184
+ }
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+ exports.layerEffectsPanel = layerEffectsPanel; exports.layerEffectsBadge = layerEffectsBadge; exports.LAYER_EFFECT_MENU = LAYER_EFFECT_MENU; exports.layerEffectControls = layerEffectControls; exports.effectControlChange = effectControlChange;