@pixerate/editor 0.237.0 → 0.239.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 (94) hide show
  1. package/dist/agent/index.cjs +40 -39
  2. package/dist/agent/index.js +9 -8
  3. package/dist/animation/index.cjs +7 -6
  4. package/dist/animation/index.js +6 -5
  5. package/dist/animation-editor/index.cjs +66 -65
  6. package/dist/animation-editor/index.js +9 -8
  7. package/dist/{brushstrokeRender-WDTKD54B.cjs → brushstrokeRender-MPOM7BFW.cjs} +7 -5
  8. package/dist/{brushstrokeRender-MAHOXL7K.js → brushstrokeRender-WB67GMUP.js} +4 -2
  9. package/dist/canvas/index.cjs +55 -54
  10. package/dist/canvas/index.js +10 -9
  11. package/dist/chart/index.cjs +159 -158
  12. package/dist/chart/index.js +9 -8
  13. package/dist/{chunk-L6Y7TSQ4.js → chunk-36ZTV7WO.js} +1 -1
  14. package/dist/{chunk-JVNGCS26.js → chunk-3E36VDMJ.js} +1 -1
  15. package/dist/{chunk-WRZ6C4TU.cjs → chunk-3R5P3DVY.cjs} +6 -6
  16. package/dist/{chunk-RUONPPMC.cjs → chunk-44BMJJVA.cjs} +8 -8
  17. package/dist/{chunk-YBAPT7NL.js → chunk-6ADHGQ73.js} +4 -2
  18. package/dist/chunk-7AHBW2CQ.cjs +200 -0
  19. package/dist/{chunk-EUIDTZNQ.cjs → chunk-7PT4RJL5.cjs} +113 -111
  20. package/dist/{chunk-CU6ANS5L.js → chunk-7YGBSFC6.js} +2 -2
  21. package/dist/{chunk-ATKKG76G.cjs → chunk-AD7GA3TL.cjs} +23 -23
  22. package/dist/{chunk-FSLKBQU7.js → chunk-AIS56JOO.js} +3 -3
  23. package/dist/{chunk-5VQXSS2S.cjs → chunk-BBUE3UJL.cjs} +86 -86
  24. package/dist/{chunk-7272D3K2.js → chunk-BP6KSGVD.js} +6 -4
  25. package/dist/{chunk-F6R67I3A.js → chunk-CXXXAZ7H.js} +1 -1
  26. package/dist/{chunk-5DQPDXOM.cjs → chunk-D2SGV525.cjs} +76 -76
  27. package/dist/chunk-F67XMVDI.js +200 -0
  28. package/dist/{chunk-JVSX5QTS.js → chunk-FQVVO5YA.js} +3 -3
  29. package/dist/{chunk-UXETV2NC.cjs → chunk-GA4EU4P3.cjs} +4 -4
  30. package/dist/{chunk-UFEDHACQ.js → chunk-GXAK6Q5J.js} +2 -2
  31. package/dist/{chunk-MHLU6GRJ.js → chunk-JEGJP4OW.js} +7 -196
  32. package/dist/chunk-KMPM5JM5.js +936 -0
  33. package/dist/{chunk-GOBOCZZI.js → chunk-LEQKZGQI.js} +1 -1
  34. package/dist/{chunk-M5GLQQWG.cjs → chunk-LJZRHVZV.cjs} +2 -2
  35. package/dist/{chunk-N76AMOKE.cjs → chunk-MOW3JMNG.cjs} +42 -42
  36. package/dist/{chunk-WKMUBATU.js → chunk-N4DFDI73.js} +1 -1
  37. package/dist/{chunk-GNZI3KYK.cjs → chunk-NKTNLJUJ.cjs} +49 -9
  38. package/dist/{chunk-TQOL6CF7.js → chunk-PJYG6FCF.js} +49 -9
  39. package/dist/{chunk-V3L7U63N.cjs → chunk-PP6BXVRL.cjs} +1 -1
  40. package/dist/{chunk-TFF2GTGN.cjs → chunk-PPFJHTW5.cjs} +24 -22
  41. package/dist/{chunk-6ZZKRH7R.js → chunk-QARCM66V.js} +3 -3
  42. package/dist/{chunk-5UEFBM2M.cjs → chunk-RD7RX52G.cjs} +18 -207
  43. package/dist/{chunk-CDP2AKMA.js → chunk-RV5DKZHU.js} +1 -1
  44. package/dist/chunk-S6OT6CTS.cjs +936 -0
  45. package/dist/{chunk-HUAISCUX.cjs → chunk-T7KQEMAE.cjs} +18 -18
  46. package/dist/{chunk-BQE3Y6ZO.cjs → chunk-THXFU3JB.cjs} +5 -5
  47. package/dist/{chunk-4ZC5QJE2.cjs → chunk-UTI5IITZ.cjs} +3 -3
  48. package/dist/{chunk-XSVUNSDJ.js → chunk-UUBO6RB5.js} +1 -1
  49. package/dist/{chunk-CZWUDFR3.cjs → chunk-UZU6DIZA.cjs} +52 -52
  50. package/dist/{chunk-M2TPMYJE.js → chunk-V6DT2CDH.js} +1 -1
  51. package/dist/{chunk-WV5WTOC6.cjs → chunk-W7GRGGBH.cjs} +16 -16
  52. package/dist/{chunk-23E5GI2U.js → chunk-WGN7AUKB.js} +2 -2
  53. package/dist/{chunk-YMREOA67.js → chunk-XK4SST43.js} +2 -2
  54. package/dist/{chunk-SOSBOS5T.cjs → chunk-XWOLPNBW.cjs} +22 -22
  55. package/dist/{chunk-ILP77UD6.js → chunk-YGQVCQTG.js} +1 -1
  56. package/dist/{chunk-GXLZZVR5.cjs → chunk-ZXNO3ZOX.cjs} +37 -37
  57. package/dist/color/index.cjs +6 -4
  58. package/dist/color/index.js +9 -7
  59. package/dist/export/index.cjs +8 -7
  60. package/dist/export/index.js +7 -6
  61. package/dist/extensions/index.cjs +11 -10
  62. package/dist/extensions/index.js +10 -9
  63. package/dist/gradient/index.cjs +104 -813
  64. package/dist/gradient/index.d.cts +1 -0
  65. package/dist/gradient/index.d.ts +1 -0
  66. package/dist/gradient/index.js +87 -796
  67. package/dist/gradient/sample.d.cts +69 -0
  68. package/dist/gradient/sample.d.ts +69 -0
  69. package/dist/image-editor/index.cjs +826 -778
  70. package/dist/image-editor/index.js +57 -9
  71. package/dist/index.cjs +17 -16
  72. package/dist/index.js +11 -10
  73. package/dist/paint-editor/controller.d.cts +31 -1
  74. package/dist/paint-editor/controller.d.ts +31 -1
  75. package/dist/paint-editor/index.cjs +403 -195
  76. package/dist/paint-editor/index.js +231 -23
  77. package/dist/paint-editor/sticker-tools.d.cts +1 -1
  78. package/dist/paint-editor/sticker-tools.d.ts +1 -1
  79. package/dist/paint-editor/stickers.d.cts +10 -3
  80. package/dist/paint-editor/stickers.d.ts +10 -3
  81. package/dist/paint-editor/ui.d.cts +10 -3
  82. package/dist/paint-editor/ui.d.ts +10 -3
  83. package/dist/tokens/index.cjs +4 -3
  84. package/dist/tokens/index.js +3 -2
  85. package/dist/typography/index.cjs +8 -7
  86. package/dist/typography/index.js +3 -2
  87. package/dist/vector/index.cjs +967 -966
  88. package/dist/vector/index.js +9 -8
  89. package/dist/video-editor/index.cjs +7 -6
  90. package/dist/video-editor/index.js +6 -5
  91. package/package.json +1 -1
  92. package/skills/pixerate-color/SKILL.md +3 -0
  93. package/skills/pixerate-image-editor/SKILL.md +1 -0
  94. package/skills/pixerate-paint-editor/SKILL.md +6 -2
@@ -1,754 +1,41 @@
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 _chunkFJ2MSI43cjs = require('../chunk-FJ2MSI43.cjs');
4
3
 
5
4
 
6
5
 
7
6
 
8
7
 
9
8
 
10
- var _chunkEUIDTZNQcjs = require('../chunk-EUIDTZNQ.cjs');
11
9
 
12
10
 
13
11
 
14
- var _chunkTFF2GTGNcjs = require('../chunk-TFF2GTGN.cjs');
15
12
 
16
13
 
17
14
 
18
- var _chunk5UEFBM2Mcjs = require('../chunk-5UEFBM2M.cjs');
19
- require('../chunk-IPJ3TEYR.cjs');
20
15
 
21
- // src/gradient/model.ts
22
- function clamp(v, min, max) {
23
- return Math.max(min, Math.min(max, v));
24
- }
25
- function gradientMidpointRemap(u, m) {
26
- const mid = clamp(m, 0.05, 0.95);
27
- if (Math.abs(mid - 0.5) < 1e-6) return u;
28
- return u <= mid ? 0.5 * u / mid : 0.5 + 0.5 * (u - mid) / (1 - mid);
29
- }
30
- function normalizeGradient(input) {
31
- if (typeof input === "string") {
32
- const parsed = parseCssGradient(input);
33
- if (!parsed) {
34
- return { error: `Could not parse CSS gradient: "${input}".` };
35
- }
36
- return { gradient: parsed };
37
- }
38
- if (!input || typeof input !== "object") {
39
- return { error: "Gradient must be an object." };
40
- }
41
- const obj = input;
42
- const type = obj.type === "radial" || obj.type === "conic" ? obj.type : "linear";
43
- if (!Array.isArray(obj.stops)) {
44
- return { error: "Gradient stops must be an array." };
45
- }
46
- if (obj.stops.length < 2) {
47
- return { error: `A gradient needs at least 2 stops; it has ${obj.stops.length}.` };
48
- }
49
- const usedIds = /* @__PURE__ */ new Set();
50
- for (const s of obj.stops) {
51
- if (s && typeof s === "object" && typeof s.id === "string" && s.id.trim()) {
52
- usedIds.add(s.id.trim());
53
- }
54
- }
55
- let nextIdIndex = 1;
56
- const getNextId = () => {
57
- while (usedIds.has(`s${nextIdIndex}`)) {
58
- nextIdIndex++;
59
- }
60
- const id = `s${nextIdIndex}`;
61
- usedIds.add(id);
62
- nextIdIndex++;
63
- return id;
64
- };
65
- const stops = [];
66
- for (let i = 0; i < obj.stops.length; i++) {
67
- const s = obj.stops[i];
68
- if (!s || typeof s !== "object") {
69
- return { error: `Stop at index ${i} must be an object.` };
70
- }
71
- const rawStop = s;
72
- let normColor = null;
73
- if (typeof rawStop.color === "string" || rawStop.color && typeof rawStop.color === "object") {
74
- const dual = _chunkEUIDTZNQcjs.normalizeDualColor.call(void 0, rawStop.color);
75
- if (dual) {
76
- normColor = _chunkEUIDTZNQcjs.formatDualColor.call(void 0, dual);
77
- }
78
- }
79
- if (!normColor) {
80
- return { error: `Stop at index ${i} has an invalid colour.` };
81
- }
82
- let offset = Number(rawStop.offset);
83
- if (!Number.isFinite(offset)) {
84
- offset = obj.stops.length === 1 ? 0 : i / (obj.stops.length - 1);
85
- }
86
- offset = clamp(offset, 0, 1);
87
- const id = typeof rawStop.id === "string" && rawStop.id.trim() ? rawStop.id.trim() : getNextId();
88
- const stop = {
89
- id,
90
- offset,
91
- color: normColor
92
- };
93
- if (rawStop.midpoint !== void 0 && rawStop.midpoint !== null) {
94
- const m = Number(rawStop.midpoint);
95
- if (Number.isFinite(m)) {
96
- stop.midpoint = clamp(m, 0.05, 0.95);
97
- }
98
- }
99
- stops.push(stop);
100
- }
101
- stops.sort((a, b) => a.offset - b.offset);
102
- const gradient = {
103
- type,
104
- stops
105
- };
106
- if (type === "linear" || type === "conic") {
107
- if (obj.angle !== void 0 && Number.isFinite(Number(obj.angle))) {
108
- gradient.angle = (Number(obj.angle) % 360 + 360) % 360;
109
- } else {
110
- gradient.angle = type === "linear" ? 180 : 0;
111
- }
112
- }
113
- if (type === "radial" || type === "conic") {
114
- if (obj.center && typeof obj.center === "object") {
115
- const cx = Number(obj.center.x);
116
- const cy = Number(obj.center.y);
117
- gradient.center = {
118
- x: Number.isFinite(cx) ? clamp(cx, 0, 1) : 0.5,
119
- y: Number.isFinite(cy) ? clamp(cy, 0, 1) : 0.5
120
- };
121
- } else {
122
- gradient.center = { x: 0.5, y: 0.5 };
123
- }
124
- }
125
- if (type === "radial") {
126
- gradient.shape = obj.shape === "circle" ? "circle" : "ellipse";
127
- }
128
- const allowedInterp = ["srgb", "srgb-linear", "oklab", "oklch"];
129
- if (obj.interpolation && allowedInterp.includes(obj.interpolation)) {
130
- gradient.interpolation = obj.interpolation;
131
- } else {
132
- gradient.interpolation = "oklab";
133
- }
134
- if (obj.repeating) {
135
- gradient.repeating = true;
136
- }
137
- return { gradient };
138
- }
139
- function createGradient(colorsOrOptions, options) {
140
- if (Array.isArray(colorsOrOptions)) {
141
- const colors = colorsOrOptions;
142
- const resolvedColors = colors.length >= 2 ? colors : colors.length === 1 ? [colors[0], colors[0]] : ["#000000", "#ffffff"];
143
- const stops = resolvedColors.map((color, i) => ({
144
- id: `s${i + 1}`,
145
- offset: i / (resolvedColors.length - 1),
146
- color: _chunkEUIDTZNQcjs.formatDualColor.call(void 0, _nullishCoalesce(_chunkEUIDTZNQcjs.normalizeDualColor.call(void 0, color), () => ( { light: "#000000", dark: "#000000" })))
147
- }));
148
- const res2 = normalizeGradient({
149
- ...options,
150
- stops
151
- });
152
- if ("error" in res2) {
153
- throw new Error(res2.error);
154
- }
155
- return res2.gradient;
156
- }
157
- if (colorsOrOptions && typeof colorsOrOptions === "object" && !Array.isArray(colorsOrOptions)) {
158
- const raw = colorsOrOptions;
159
- let stops = raw.stops;
160
- if (!stops || stops.length === 0) {
161
- stops = [
162
- { id: "s1", offset: 0, color: "#000000" },
163
- { id: "s2", offset: 1, color: "#ffffff" }
164
- ];
165
- } else if (typeof stops[0] === "string") {
166
- const strStops = stops;
167
- stops = strStops.map((color, i) => ({
168
- id: `s${i + 1}`,
169
- offset: i / (strStops.length - 1),
170
- color
171
- }));
172
- }
173
- const res2 = normalizeGradient({
174
- ...raw,
175
- stops
176
- });
177
- if ("error" in res2) {
178
- throw new Error(res2.error);
179
- }
180
- return res2.gradient;
181
- }
182
- const res = normalizeGradient({
183
- ...options,
184
- stops: [
185
- { id: "s1", offset: 0, color: "#000000" },
186
- { id: "s2", offset: 1, color: "#ffffff" }
187
- ]
188
- });
189
- if ("error" in res) {
190
- throw new Error(res.error);
191
- }
192
- return res.gradient;
193
- }
194
- function isDualColorValue(val) {
195
- if (typeof val === "string") {
196
- return val.trim().toLowerCase().startsWith("light-dark(");
197
- }
198
- if (_chunkEUIDTZNQcjs.isDualColor.call(void 0, val)) {
199
- return val.light !== val.dark;
200
- }
201
- return false;
202
- }
203
- function isDualGradient(g) {
204
- return g.stops.some((s) => isDualColorValue(s.color));
205
- }
206
- function resolveGradient(g, scheme) {
207
- return {
208
- ...g,
209
- center: g.center ? { ...g.center } : void 0,
210
- stops: g.stops.map((s) => ({
211
- ...s,
212
- color: _nullishCoalesce(_chunkEUIDTZNQcjs.resolveColor.call(void 0, s.color, scheme), () => ( s.color))
213
- }))
214
- };
215
- }
216
- function sampleGradient(g, t, scheme = "light") {
217
- const resolved = resolveGradient(g, scheme);
218
- const clampedT = clamp(t, 0, 1);
219
- const stops = resolved.stops;
220
- if (clampedT <= stops[0].offset) {
221
- return stops[0].color;
222
- }
223
- if (clampedT >= stops[stops.length - 1].offset) {
224
- return stops[stops.length - 1].color;
225
- }
226
- let i = 0;
227
- while (i < stops.length - 1 && stops[i + 1].offset < clampedT) {
228
- i++;
229
- }
230
- const s0 = stops[i];
231
- const s1 = stops[i + 1];
232
- const span = s1.offset - s0.offset;
233
- if (span <= 1e-6) {
234
- return s1.color;
235
- }
236
- let u = (clampedT - s0.offset) / span;
237
- if (s0.midpoint !== void 0) {
238
- u = gradientMidpointRemap(u, s0.midpoint);
239
- }
240
- const mixed = _chunkEUIDTZNQcjs.mixColors.call(void 0, s0.color, s1.color, u, { space: _nullishCoalesce(g.interpolation, () => ( "oklab")) });
241
- return _nullishCoalesce(mixed, () => ( s0.color));
242
- }
243
- function insertGradientStop(g, offset, color) {
244
- const clampedOffset = clamp(offset, 0, 1);
245
- const stopColor = color !== void 0 ? color : sampleGradient(g, clampedOffset, "light");
246
- const used = new Set(g.stops.map((s) => s.id));
247
- let idx = 1;
248
- while (used.has(`s${idx}`)) idx++;
249
- const id = `s${idx}`;
250
- const newStop = {
251
- id,
252
- offset: clampedOffset,
253
- color: stopColor
254
- };
255
- const stops = [...g.stops, newStop];
256
- const res = normalizeGradient({ ...g, stops });
257
- if ("error" in res) throw new Error(res.error);
258
- const added = res.gradient.stops.find((s) => s.id === id);
259
- return { gradient: res.gradient, stop: added };
260
- }
261
- function listValidIds(g) {
262
- return g.stops.map((s) => `"${s.id}"`).join(", ");
263
- }
264
- function updateGradientStop(g, id, patch) {
265
- const index = g.stops.findIndex((s) => s.id === id);
266
- if (index === -1) {
267
- throw new Error(`Stop "${id}" not found. Valid stop IDs are: ${listValidIds(g)}.`);
268
- }
269
- const stops = g.stops.map((s, i) => i === index ? { ...s, ...patch } : s);
270
- const res = normalizeGradient({ ...g, stops });
271
- if ("error" in res) throw new Error(res.error);
272
- return res.gradient;
273
- }
274
- function removeGradientStop(g, id) {
275
- if (g.stops.length <= 2) {
276
- throw new Error("A gradient needs at least 2 stops; add one with add_gradient_stop before removing this one.");
277
- }
278
- const index = g.stops.findIndex((s) => s.id === id);
279
- if (index === -1) {
280
- throw new Error(`Stop "${id}" not found. Valid stop IDs are: ${listValidIds(g)}.`);
281
- }
282
- const stops = g.stops.filter((s) => s.id !== id);
283
- const res = normalizeGradient({ ...g, stops });
284
- if ("error" in res) throw new Error(res.error);
285
- return res.gradient;
286
- }
287
- function reverseGradient(g) {
288
- const reversedStops = g.stops.map((s) => ({
289
- ...s,
290
- offset: Math.round((1 - s.offset) * 1e4) / 1e4,
291
- midpoint: s.midpoint !== void 0 ? Math.round((1 - s.midpoint) * 1e4) / 1e4 : void 0
292
- }));
293
- reversedStops.sort((a, b) => a.offset - b.offset);
294
- return {
295
- ...g,
296
- center: g.center ? { ...g.center } : void 0,
297
- stops: reversedStops
298
- };
299
- }
300
- function distributeGradientStops(g) {
301
- const n = g.stops.length;
302
- const distributed = g.stops.map((s, i) => ({
303
- ...s,
304
- offset: Math.round(i / (n - 1) * 1e4) / 1e4
305
- }));
306
- return {
307
- ...g,
308
- center: g.center ? { ...g.center } : void 0,
309
- stops: distributed
310
- };
311
- }
312
- function formatPercent(fraction) {
313
- const pct = Math.round(fraction * 1e3) / 10;
314
- return `${pct}%`;
315
- }
316
- function gradientToCss(g) {
317
- const prefix = g.repeating ? `repeating-${g.type}-gradient` : `${g.type}-gradient`;
318
- const parts = [];
319
- const interpPrefix = g.interpolation && g.interpolation !== "srgb" ? `in ${g.interpolation} ` : "";
320
- if (g.type === "linear") {
321
- const angle = g.angle !== void 0 ? `${g.angle}deg` : "180deg";
322
- parts.push(`${interpPrefix}${angle}`.trim());
323
- } else if (g.type === "radial") {
324
- const shape = _nullishCoalesce(g.shape, () => ( "ellipse"));
325
- const cx = g.center ? formatPercent(g.center.x) : "50%";
326
- const cy = g.center ? formatPercent(g.center.y) : "50%";
327
- parts.push(`${interpPrefix}${shape} at ${cx} ${cy}`.trim());
328
- } else if (g.type === "conic") {
329
- const angle = g.angle !== void 0 ? `from ${g.angle}deg` : "from 0deg";
330
- const cx = g.center ? formatPercent(g.center.x) : "50%";
331
- const cy = g.center ? formatPercent(g.center.y) : "50%";
332
- parts.push(`${interpPrefix}${angle} at ${cx} ${cy}`.trim());
333
- }
334
- for (let i = 0; i < g.stops.length; i++) {
335
- const s = g.stops[i];
336
- parts.push(`${s.color} ${formatPercent(s.offset)}`);
337
- if (s.midpoint !== void 0 && i < g.stops.length - 1) {
338
- const next = g.stops[i + 1];
339
- const midOffset = s.offset + (next.offset - s.offset) * s.midpoint;
340
- parts.push(formatPercent(midOffset));
341
- }
342
- }
343
- return `${prefix}(${parts.join(", ")})`;
344
- }
345
- function gradientToCssFallback(g, steps = 16, scheme = "light") {
346
- const prefix = g.repeating ? `repeating-${g.type}-gradient` : `${g.type}-gradient`;
347
- const parts = [];
348
- if (g.type === "linear") {
349
- const angle = g.angle !== void 0 ? `${g.angle}deg` : "180deg";
350
- parts.push(angle);
351
- } else if (g.type === "radial") {
352
- const shape = _nullishCoalesce(g.shape, () => ( "ellipse"));
353
- const cx = g.center ? formatPercent(g.center.x) : "50%";
354
- const cy = g.center ? formatPercent(g.center.y) : "50%";
355
- parts.push(`${shape} at ${cx} ${cy}`);
356
- } else if (g.type === "conic") {
357
- const angle = g.angle !== void 0 ? `from ${g.angle}deg` : "from 0deg";
358
- const cx = g.center ? formatPercent(g.center.x) : "50%";
359
- const cy = g.center ? formatPercent(g.center.y) : "50%";
360
- parts.push(`${angle} at ${cx} ${cy}`);
361
- }
362
- for (let i = 0; i <= steps; i++) {
363
- const t = i / steps;
364
- const color = sampleGradient(g, t, scheme);
365
- parts.push(`${color} ${formatPercent(t)}`);
366
- }
367
- return `${prefix}(${parts.join(", ")})`;
368
- }
369
- function splitCssArgs(str) {
370
- const parts = [];
371
- let depth = 0;
372
- let current = "";
373
- for (let i = 0; i < str.length; i++) {
374
- const char = str[i];
375
- if (char === "(") depth++;
376
- else if (char === ")") depth = Math.max(0, depth - 1);
377
- if (char === "," && depth === 0) {
378
- if (current.trim()) parts.push(current.trim());
379
- current = "";
380
- } else {
381
- current += char;
382
- }
383
- }
384
- if (current.trim()) parts.push(current.trim());
385
- return parts;
386
- }
387
- function parseCssAngle(val) {
388
- const trimmed = val.trim().toLowerCase();
389
- if (trimmed.endsWith("deg")) return parseFloat(trimmed);
390
- if (trimmed.endsWith("turn")) return parseFloat(trimmed) * 360;
391
- if (trimmed.endsWith("rad")) return parseFloat(trimmed) * 180 / Math.PI;
392
- if (trimmed.startsWith("to ")) {
393
- const dir = trimmed.slice(3).trim();
394
- if (dir === "bottom") return 180;
395
- if (dir === "top") return 0;
396
- if (dir === "right") return 90;
397
- if (dir === "left") return 270;
398
- if (dir === "bottom right" || dir === "right bottom") return 135;
399
- if (dir === "bottom left" || dir === "left bottom") return 225;
400
- if (dir === "top right" || dir === "right top") return 45;
401
- if (dir === "top left" || dir === "left top") return 315;
402
- }
403
- const n = parseFloat(trimmed);
404
- return Number.isFinite(n) ? n : 180;
405
- }
406
- function parseCssGradient(css) {
407
- if (typeof css !== "string") return null;
408
- const trimmed = css.trim();
409
- const match = trimmed.match(/^(repeating-)?(linear|radial|conic)-gradient\s*\(([\s\S]*)\)$/i);
410
- if (!match) return null;
411
- const repeating = Boolean(match[1]);
412
- const type = match[2].toLowerCase();
413
- const body = match[3];
414
- const rawArgs = splitCssArgs(body);
415
- if (rawArgs.length === 0) return null;
416
- let angle = type === "linear" ? 180 : 0;
417
- let center = type !== "linear" ? { x: 0.5, y: 0.5 } : void 0;
418
- let shape = type === "radial" ? "ellipse" : void 0;
419
- let interpolation = "srgb";
420
- let stopStartIndex = 0;
421
- let first = rawArgs[0].trim();
422
- const inMatch = first.match(/^in\s+([a-z0-9-]+)\s*(.*)$/i);
423
- if (inMatch) {
424
- const space = inMatch[1].toLowerCase();
425
- if (space === "oklab" || space === "oklch" || space === "srgb" || space === "srgb-linear") {
426
- interpolation = space;
427
- }
428
- first = inMatch[2].trim();
429
- if (!first) {
430
- stopStartIndex = 1;
431
- first = _nullishCoalesce(_optionalChain([rawArgs, 'access', _ => _[1], 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()]), () => ( ""));
432
- }
433
- }
434
- if (first) {
435
- if (type === "linear") {
436
- if (first.endsWith("deg") || first.endsWith("turn") || first.endsWith("rad") || first.startsWith("to ")) {
437
- angle = parseCssAngle(first);
438
- stopStartIndex = stopStartIndex === 0 ? 1 : 2;
439
- }
440
- } else if (type === "radial") {
441
- if (first.includes("circle") || first.includes("ellipse") || first.includes("at ")) {
442
- if (first.includes("circle")) shape = "circle";
443
- if (first.includes("ellipse")) shape = "ellipse";
444
- const atIdx = first.indexOf("at ");
445
- if (atIdx !== -1) {
446
- const posParts = first.slice(atIdx + 3).trim().split(/\s+/);
447
- if (posParts[0]) center = { x: parsePos(posParts[0]), y: posParts[1] ? parsePos(posParts[1]) : parsePos(posParts[0]) };
448
- }
449
- stopStartIndex = stopStartIndex === 0 ? 1 : 2;
450
- }
451
- } else if (type === "conic") {
452
- if (first.includes("from ") || first.includes("at ")) {
453
- const fromMatch = first.match(/from\s+([0-9.]+(?:deg|turn|rad)?)/i);
454
- if (fromMatch) angle = parseCssAngle(fromMatch[1]);
455
- const atIdx = first.indexOf("at ");
456
- if (atIdx !== -1) {
457
- const posParts = first.slice(atIdx + 3).trim().split(/\s+/);
458
- if (posParts[0]) center = { x: parsePos(posParts[0]), y: posParts[1] ? parsePos(posParts[1]) : parsePos(posParts[0]) };
459
- }
460
- stopStartIndex = stopStartIndex === 0 ? 1 : 2;
461
- }
462
- }
463
- }
464
- const stopArgs = rawArgs.slice(stopStartIndex);
465
- if (stopArgs.length === 0) return null;
466
- const items = [];
467
- for (const str of stopArgs) {
468
- const s = str.trim();
469
- if (/^([0-9.]+)%$/.test(s)) {
470
- items.push({ kind: "hint", offset: parseFloat(s) / 100 });
471
- continue;
472
- }
473
- const posMatch = s.match(/\s+([0-9.]+)%$/);
474
- if (posMatch) {
475
- const colorStr = s.slice(0, posMatch.index).trim();
476
- const offset = parseFloat(posMatch[1]) / 100;
477
- items.push({ kind: "stop", color: colorStr, offset });
478
- } else {
479
- items.push({ kind: "stop", color: s });
480
- }
481
- }
482
- const rawStops = items.filter((it) => it.kind === "stop");
483
- if (rawStops.length < 2) return null;
484
- for (let i = 0; i < rawStops.length; i++) {
485
- if (rawStops[i].offset === void 0) {
486
- if (i === 0) rawStops[i].offset = 0;
487
- else if (i === rawStops.length - 1) rawStops[i].offset = 1;
488
- else {
489
- let nextIdx = i + 1;
490
- while (nextIdx < rawStops.length && rawStops[nextIdx].offset === void 0) {
491
- nextIdx++;
492
- }
493
- const nextOffset = nextIdx < rawStops.length ? rawStops[nextIdx].offset : 1;
494
- const prevOffset = _nullishCoalesce(rawStops[i - 1].offset, () => ( 0));
495
- const count = nextIdx - (i - 1);
496
- for (let k = i; k < nextIdx; k++) {
497
- rawStops[k].offset = prevOffset + (k - (i - 1)) / count * (nextOffset - prevOffset);
498
- }
499
- i = nextIdx - 1;
500
- }
501
- }
502
- }
503
- const finalStops = [];
504
- let stopIdx = 0;
505
- for (let i = 0; i < items.length; i++) {
506
- const it = items[i];
507
- if (it.kind === "stop") {
508
- const stop = {
509
- id: `s${stopIdx + 1}`,
510
- offset: clamp(_nullishCoalesce(it.offset, () => ( 0)), 0, 1),
511
- color: it.color
512
- };
513
- if (i + 1 < items.length && items[i + 1].kind === "hint") {
514
- const hintOffset = items[i + 1].offset;
515
- const nextStopItem = items.slice(i + 2).find((x) => x.kind === "stop");
516
- if (nextStopItem && nextStopItem.offset !== void 0) {
517
- const span = nextStopItem.offset - stop.offset;
518
- if (span > 0) {
519
- stop.midpoint = clamp((hintOffset - stop.offset) / span, 0.05, 0.95);
520
- }
521
- }
522
- }
523
- finalStops.push(stop);
524
- stopIdx++;
525
- }
526
- }
527
- const res = normalizeGradient({
528
- type,
529
- angle,
530
- center,
531
- shape,
532
- interpolation,
533
- repeating,
534
- stops: finalStops
535
- });
536
- return "gradient" in res ? res.gradient : null;
537
- }
538
- function parsePos(str) {
539
- const s = str.trim();
540
- if (s.endsWith("%")) return clamp(parseFloat(s) / 100, 0, 1);
541
- const val = parseFloat(s);
542
- return Number.isFinite(val) ? clamp(val, 0, 1) : 0.5;
543
- }
544
- function gradientToSvgDef(g, id, scheme = "light") {
545
- const steps = 32;
546
- const stopsXml = [];
547
- for (let i = 0; i <= steps; i++) {
548
- const t = i / steps;
549
- const color = sampleGradient(g, t, scheme);
550
- stopsXml.push(` <stop offset="${formatPercent(t)}" stop-color="${color}" />`);
551
- }
552
- if (g.type === "radial") {
553
- const cx = g.center ? formatPercent(g.center.x) : "50%";
554
- const cy = g.center ? formatPercent(g.center.y) : "50%";
555
- const r = g.shape === "circle" ? "50%" : "70.7%";
556
- return `<radialGradient id="${id}" cx="${cx}" cy="${cy}" r="${r}">
557
- ${stopsXml.join("\n")}
558
- </radialGradient>`;
559
- }
560
- if (g.type === "conic") {
561
- return `<!-- Note: SVG does not natively support conic gradients; rendering as linear fallback -->
562
- <linearGradient id="${id}" x1="0%" y1="0%" x2="100%" y2="0%">
563
- ${stopsXml.join("\n")}
564
- </linearGradient>`;
565
- }
566
- const angle = _nullishCoalesce(g.angle, () => ( 180));
567
- const rad = (90 - angle) * Math.PI / 180;
568
- const dx = Math.cos(rad);
569
- const dy = -Math.sin(rad);
570
- const x1 = formatPercent(0.5 - dx * 0.5);
571
- const y1 = formatPercent(0.5 - dy * 0.5);
572
- const x2 = formatPercent(0.5 + dx * 0.5);
573
- const y2 = formatPercent(0.5 + dy * 0.5);
574
- return `<linearGradient id="${id}" x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}">
575
- ${stopsXml.join("\n")}
576
- </linearGradient>`;
577
- }
578
- function checkGradient(g, options = {}) {
579
- const dual = isDualGradient(g) || _chunkEUIDTZNQcjs.isDualColor.call(void 0, options.surface) || _chunkEUIDTZNQcjs.isDualColor.call(void 0, options.text);
580
- if (dual) {
581
- const lightG = resolveGradient(g, "light");
582
- const darkG = resolveGradient(g, "dark");
583
- const lightText = options.text ? _nullishCoalesce(_chunkEUIDTZNQcjs.resolveColor.call(void 0, options.text, "light"), () => ( void 0)) : void 0;
584
- const darkText = options.text ? _nullishCoalesce(_chunkEUIDTZNQcjs.resolveColor.call(void 0, options.text, "dark"), () => ( void 0)) : void 0;
585
- const checkScheme = (grad, txt, schemeName) => {
586
- const issues2 = [];
587
- for (let i = 0; i < grad.stops.length - 1; i++) {
588
- const gap = grad.stops[i + 1].offset - grad.stops[i].offset;
589
- if (gap < 5e-3) {
590
- issues2.push(`[${schemeName}] Stops "${grad.stops[i].id}" and "${grad.stops[i + 1].id}" are too close (gap < 0.005).`);
591
- }
592
- const c1 = _chunk5UEFBM2Mcjs.parseColor.call(void 0, grad.stops[i].color);
593
- const c2 = _chunk5UEFBM2Mcjs.parseColor.call(void 0, grad.stops[i + 1].color);
594
- if (c1 && c2 && gap < 0.05) {
595
- const dE = _chunkTFF2GTGNcjs.deltaEOK.call(void 0, c1, c2);
596
- if (dE > 0.5) {
597
- issues2.push(
598
- `[${schemeName}] Banding risk between stops "${grad.stops[i].id}" and "${grad.stops[i + 1].id}" (\u0394EOK = ${dE.toFixed(2)} across gap ${gap.toFixed(3)}).`
599
- );
600
- }
601
- }
602
- }
603
- for (const s of grad.stops) {
604
- const c = _chunk5UEFBM2Mcjs.parseColor.call(void 0, s.color);
605
- if (c && !_chunkTFF2GTGNcjs.inSrgbGamut.call(void 0, c)) {
606
- issues2.push(`[${schemeName}] Stop "${s.id}" colour ${s.color} is outside standard sRGB gamut.`);
607
- }
608
- }
609
- let lowest;
610
- if (txt) {
611
- const parsedTxt = _chunk5UEFBM2Mcjs.parseColor.call(void 0, txt);
612
- if (parsedTxt) {
613
- let minRatio = Infinity;
614
- for (let step = 0; step <= 32; step++) {
615
- const sample = _chunk5UEFBM2Mcjs.parseColor.call(void 0, sampleGradient(grad, step / 32, schemeName));
616
- if (sample) {
617
- const r = _chunk5UEFBM2Mcjs.contrastRatio.call(void 0, parsedTxt, sample);
618
- if (r < minRatio) minRatio = r;
619
- }
620
- }
621
- lowest = Math.round(minRatio * 100) / 100;
622
- }
623
- }
624
- return { issues: issues2, lowest };
625
- };
626
- const lRes = checkScheme(lightG, lightText, "light");
627
- const dRes = checkScheme(darkG, darkText, "dark");
628
- return {
629
- issues: [...lRes.issues, ...dRes.issues],
630
- lowestTextContrast: lRes.lowest !== void 0 && dRes.lowest !== void 0 ? { light: lRes.lowest, dark: dRes.lowest } : void 0
631
- };
632
- }
633
- const issues = [];
634
- for (let i = 0; i < g.stops.length - 1; i++) {
635
- const gap = g.stops[i + 1].offset - g.stops[i].offset;
636
- if (gap < 5e-3) {
637
- issues.push(`Stops "${g.stops[i].id}" and "${g.stops[i + 1].id}" are too close (gap < 0.005).`);
638
- }
639
- const c1 = _chunk5UEFBM2Mcjs.parseColor.call(void 0, g.stops[i].color);
640
- const c2 = _chunk5UEFBM2Mcjs.parseColor.call(void 0, g.stops[i + 1].color);
641
- if (c1 && c2 && gap < 0.05) {
642
- const dE = _chunkTFF2GTGNcjs.deltaEOK.call(void 0, c1, c2);
643
- if (dE > 0.5) {
644
- issues.push(
645
- `Banding risk between stops "${g.stops[i].id}" and "${g.stops[i + 1].id}" (\u0394EOK = ${dE.toFixed(2)} across gap ${gap.toFixed(3)}).`
646
- );
647
- }
648
- }
649
- }
650
- for (const s of g.stops) {
651
- const c = _chunk5UEFBM2Mcjs.parseColor.call(void 0, s.color);
652
- if (c && !_chunkTFF2GTGNcjs.inSrgbGamut.call(void 0, c)) {
653
- issues.push(`Stop "${s.id}" colour ${s.color} is outside standard sRGB gamut.`);
654
- }
655
- }
656
- let lowestTextContrast;
657
- if (options.text) {
658
- const parsedTxt = _chunk5UEFBM2Mcjs.parseColor.call(void 0, options.text);
659
- if (parsedTxt) {
660
- let minRatio = Infinity;
661
- for (let step = 0; step <= 32; step++) {
662
- const sample = _chunk5UEFBM2Mcjs.parseColor.call(void 0, sampleGradient(g, step / 32, "light"));
663
- if (sample) {
664
- const r = _chunk5UEFBM2Mcjs.contrastRatio.call(void 0, parsedTxt, sample);
665
- if (r < minRatio) minRatio = r;
666
- }
667
- }
668
- lowestTextContrast = Math.round(minRatio * 100) / 100;
669
- }
670
- }
671
- return { issues, lowestTextContrast };
672
- }
673
- var GRADIENT_PRESETS = Object.freeze({
674
- sunset: {
675
- type: "linear",
676
- angle: 90,
677
- interpolation: "oklab",
678
- stops: [
679
- { id: "s1", offset: 0, color: "#f97316" },
680
- { id: "s2", offset: 1, color: "#ec4899" }
681
- ]
682
- },
683
- ocean: {
684
- type: "linear",
685
- angle: 180,
686
- interpolation: "oklab",
687
- stops: [
688
- { id: "s1", offset: 0, color: "#06b6d4" },
689
- { id: "s2", offset: 1, color: "#3b82f6" }
690
- ]
691
- },
692
- "mono-fade": {
693
- type: "linear",
694
- angle: 180,
695
- interpolation: "oklab",
696
- stops: [
697
- { id: "s1", offset: 0, color: "#ffffff" },
698
- { id: "s2", offset: 1, color: "#000000" }
699
- ]
700
- },
701
- "transparent-fade": {
702
- type: "linear",
703
- angle: 180,
704
- interpolation: "oklab",
705
- stops: [
706
- { id: "s1", offset: 0, color: "#000000ff" },
707
- { id: "s2", offset: 1, color: "#00000000" }
708
- ]
709
- },
710
- aurora: {
711
- type: "linear",
712
- angle: 135,
713
- interpolation: "oklab",
714
- stops: [
715
- { id: "s1", offset: 0, color: "#10b981" },
716
- { id: "s2", offset: 0.5, color: "#06b6d4" },
717
- { id: "s3", offset: 1, color: "#8b5cf6" }
718
- ]
719
- },
720
- neon: {
721
- type: "linear",
722
- angle: 90,
723
- interpolation: "oklab",
724
- stops: [
725
- { id: "s1", offset: 0, color: "#f43f5e" },
726
- { id: "s2", offset: 1, color: "#8b5cf6" }
727
- ]
728
- },
729
- radial: {
730
- type: "radial",
731
- shape: "ellipse",
732
- center: { x: 0.5, y: 0.5 },
733
- interpolation: "oklab",
734
- stops: [
735
- { id: "s1", offset: 0, color: "#ffffff" },
736
- { id: "s2", offset: 1, color: "#000000" }
737
- ]
738
- },
739
- conic: {
740
- type: "conic",
741
- angle: 0,
742
- center: { x: 0.5, y: 0.5 },
743
- interpolation: "oklab",
744
- stops: [
745
- { id: "s1", offset: 0, color: "#f43f5e" },
746
- { id: "s2", offset: 0.33, color: "#eab308" },
747
- { id: "s3", offset: 0.66, color: "#06b6d4" },
748
- { id: "s4", offset: 1, color: "#f43f5e" }
749
- ]
750
- }
751
- });
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+ var _chunkS6OT6CTScjs = require('../chunk-S6OT6CTS.cjs');
29
+
30
+
31
+ var _chunkFJ2MSI43cjs = require('../chunk-FJ2MSI43.cjs');
32
+ require('../chunk-7PT4RJL5.cjs');
33
+ require('../chunk-PPFJHTW5.cjs');
34
+
35
+
36
+ var _chunkRD7RX52Gcjs = require('../chunk-RD7RX52G.cjs');
37
+ require('../chunk-7AHBW2CQ.cjs');
38
+ require('../chunk-IPJ3TEYR.cjs');
752
39
 
753
40
  // src/gradient/controller.ts
754
41
  var GRADIENT_TYPES = ["linear", "radial", "conic"];
@@ -808,11 +95,11 @@ var GradientController = (_class = class {
808
95
  __init6() {this._cachedState = null}
809
96
  constructor(options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);
810
97
  if (options.value !== void 0) {
811
- const norm = normalizeGradient(options.value);
98
+ const norm = _chunkS6OT6CTScjs.normalizeGradient.call(void 0, options.value);
812
99
  if ("error" in norm) throw new Error(norm.error);
813
100
  this._gradient = norm.gradient;
814
101
  } else {
815
- this._gradient = createGradient(["#000000", "#ffffff"]);
102
+ this._gradient = _chunkS6OT6CTScjs.createGradient.call(void 0, ["#000000", "#ffffff"]);
816
103
  }
817
104
  this._history = _nullishCoalesce(options.history, () => ( new (0, _chunkFJ2MSI43cjs.HistoryManager)()));
818
105
  this._readOnlyOption = options.readOnly;
@@ -919,7 +206,7 @@ var GradientController = (_class = class {
919
206
  const ro = this._checkReadOnly();
920
207
  if (ro) return ro;
921
208
  if (newStopId !== null && !newGradient.stops.some((s) => s.id === newStopId)) {
922
- newStopId = _nullishCoalesce(_optionalChain([newGradient, 'access', _4 => _4.stops, 'access', _5 => _5[0], 'optionalAccess', _6 => _6.id]), () => ( null));
209
+ newStopId = _nullishCoalesce(_optionalChain([newGradient, 'access', _ => _.stops, 'access', _2 => _2[0], 'optionalAccess', _3 => _3.id]), () => ( null));
923
210
  }
924
211
  if (sameGradientJson(this._gradient, newGradient) && this._selectedStopId === newStopId) {
925
212
  return { ok: true };
@@ -952,10 +239,10 @@ var GradientController = (_class = class {
952
239
  if (this._selectedStopId === null) return null;
953
240
  if (next.stops.some((s) => s.id === this._selectedStopId)) return this._selectedStopId;
954
241
  const index = this._gradient.stops.findIndex((s) => s.id === this._selectedStopId);
955
- return _nullishCoalesce(_optionalChain([next, 'access', _7 => _7.stops, 'access', _8 => _8[Math.min(Math.max(index, 0), next.stops.length - 1)], 'optionalAccess', _9 => _9.id]), () => ( null));
242
+ return _nullishCoalesce(_optionalChain([next, 'access', _4 => _4.stops, 'access', _5 => _5[Math.min(Math.max(index, 0), next.stops.length - 1)], 'optionalAccess', _6 => _6.id]), () => ( null));
956
243
  }
957
244
  setGradient(value, label = "Set Gradient") {
958
- const norm = normalizeGradient(value);
245
+ const norm = _chunkS6OT6CTScjs.normalizeGradient.call(void 0, value);
959
246
  if ("error" in norm) {
960
247
  return { ok: false, message: norm.error };
961
248
  }
@@ -966,7 +253,7 @@ var GradientController = (_class = class {
966
253
  * host). Keeps the selection when the stop survives. Notifies subscribers and `onChange`.
967
254
  */
968
255
  load(value, options = {}) {
969
- const norm = normalizeGradient(value);
256
+ const norm = _chunkS6OT6CTScjs.normalizeGradient.call(void 0, value);
970
257
  if ("error" in norm) {
971
258
  return { ok: false, message: norm.error };
972
259
  }
@@ -1003,7 +290,7 @@ var GradientController = (_class = class {
1003
290
  if (patch.angle !== void 0 && merged.type === "radial") {
1004
291
  return { ok: false, message: "The angle applies to linear and conic gradients only; this one is radial." };
1005
292
  }
1006
- const norm = normalizeGradient(merged);
293
+ const norm = _chunkS6OT6CTScjs.normalizeGradient.call(void 0, merged);
1007
294
  if ("error" in norm) return { ok: false, message: norm.error };
1008
295
  return this._apply(norm.gradient, label);
1009
296
  }
@@ -1029,7 +316,7 @@ var GradientController = (_class = class {
1029
316
  const ro = this._checkReadOnly();
1030
317
  if (ro) return { ok: false, message: ro.message };
1031
318
  try {
1032
- const { gradient: next, stop } = insertGradientStop(this._gradient, offset, color);
319
+ const { gradient: next, stop } = _chunkS6OT6CTScjs.insertGradientStop.call(void 0, this._gradient, offset, color);
1033
320
  const res = this._apply(next, "Add Gradient Stop", stop.id);
1034
321
  if (!res.ok) return res;
1035
322
  return { ok: true, stop };
@@ -1041,7 +328,7 @@ var GradientController = (_class = class {
1041
328
  const ro = this._checkReadOnly();
1042
329
  if (ro) return ro;
1043
330
  try {
1044
- const next = updateGradientStop(this._gradient, id, patch);
331
+ const next = _chunkS6OT6CTScjs.updateGradientStop.call(void 0, this._gradient, id, patch);
1045
332
  return this._apply(next, "Update Gradient Stop");
1046
333
  } catch (e) {
1047
334
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
@@ -1051,7 +338,7 @@ var GradientController = (_class = class {
1051
338
  const ro = this._checkReadOnly();
1052
339
  if (ro) return ro;
1053
340
  try {
1054
- const next = removeGradientStop(this._gradient, id);
341
+ const next = _chunkS6OT6CTScjs.removeGradientStop.call(void 0, this._gradient, id);
1055
342
  return this._apply(next, "Remove Gradient Stop");
1056
343
  } catch (e) {
1057
344
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
@@ -1060,13 +347,13 @@ var GradientController = (_class = class {
1060
347
  reverse() {
1061
348
  const ro = this._checkReadOnly();
1062
349
  if (ro) return ro;
1063
- const next = reverseGradient(this._gradient);
350
+ const next = _chunkS6OT6CTScjs.reverseGradient.call(void 0, this._gradient);
1064
351
  return this._apply(next, "Reverse Gradient");
1065
352
  }
1066
353
  distribute() {
1067
354
  const ro = this._checkReadOnly();
1068
355
  if (ro) return ro;
1069
- const next = distributeGradientStops(this._gradient);
356
+ const next = _chunkS6OT6CTScjs.distributeGradientStops.call(void 0, this._gradient);
1070
357
  return this._apply(next, "Distribute Gradient Stops");
1071
358
  }
1072
359
  undo() {
@@ -1114,9 +401,9 @@ function createGradientToolProvider(controller, options = {}) {
1114
401
  const ro = readOnlyReason();
1115
402
  return {
1116
403
  gradient: g,
1117
- css: gradientToCss(g),
1118
- svgDef: gradientToSvgDef(g, "gradient-preview"),
1119
- isDual: isDualGradient(g),
404
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, g),
405
+ svgDef: _chunkS6OT6CTScjs.gradientToSvgDef.call(void 0, g, "gradient-preview"),
406
+ isDual: _chunkS6OT6CTScjs.isDualGradient.call(void 0, g),
1120
407
  selectedStopId: controller.getSelectedStopId(),
1121
408
  readOnly: ro !== null,
1122
409
  ...ro ? { readOnlyReason: ro } : {}
@@ -1155,7 +442,7 @@ function createGradientToolProvider(controller, options = {}) {
1155
442
  if (args.text !== void 0) checkOpts.text = args.text;
1156
443
  if (typeof args.fontSize === "number") checkOpts.fontSize = args.fontSize;
1157
444
  if (typeof args.bold === "boolean") checkOpts.bold = args.bold;
1158
- const res = checkGradient(g, checkOpts);
445
+ const res = _chunkS6OT6CTScjs.checkGradient.call(void 0, g, checkOpts);
1159
446
  return {
1160
447
  pass: res.issues.length === 0,
1161
448
  issueCount: res.issues.length,
@@ -1175,10 +462,10 @@ function createGradientToolProvider(controller, options = {}) {
1175
462
  annotations: readTool("List Gradient Presets"),
1176
463
  handler: async () => {
1177
464
  return {
1178
- presets: Object.entries(GRADIENT_PRESETS).map(([id, gradient]) => ({
465
+ presets: Object.entries(_chunkS6OT6CTScjs.GRADIENT_PRESETS).map(([id, gradient]) => ({
1179
466
  id,
1180
467
  name: id,
1181
- css: gradientToCss(gradient),
468
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, gradient),
1182
469
  gradient
1183
470
  }))
1184
471
  };
@@ -1223,7 +510,7 @@ function createGradientToolProvider(controller, options = {}) {
1223
510
  const current = controller.getGradient();
1224
511
  return {
1225
512
  gradient: current,
1226
- css: gradientToCss(current)
513
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, current)
1227
514
  };
1228
515
  }
1229
516
  },
@@ -1291,7 +578,7 @@ function createGradientToolProvider(controller, options = {}) {
1291
578
  const current = controller.getGradient();
1292
579
  return {
1293
580
  gradient: current,
1294
- css: gradientToCss(current)
581
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, current)
1295
582
  };
1296
583
  }
1297
584
  },
@@ -1321,7 +608,7 @@ function createGradientToolProvider(controller, options = {}) {
1321
608
  return {
1322
609
  stop: res.stop,
1323
610
  gradient: controller.getGradient(),
1324
- css: gradientToCss(controller.getGradient())
611
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, controller.getGradient())
1325
612
  };
1326
613
  }
1327
614
  },
@@ -1363,7 +650,7 @@ function createGradientToolProvider(controller, options = {}) {
1363
650
  return {
1364
651
  stop: controller.getGradient().stops.find((s) => s.id === args.id),
1365
652
  gradient: controller.getGradient(),
1366
- css: gradientToCss(controller.getGradient())
653
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, controller.getGradient())
1367
654
  };
1368
655
  }
1369
656
  },
@@ -1389,7 +676,7 @@ function createGradientToolProvider(controller, options = {}) {
1389
676
  return {
1390
677
  removedId: args.id,
1391
678
  gradient: controller.getGradient(),
1392
- css: gradientToCss(controller.getGradient())
679
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, controller.getGradient())
1393
680
  };
1394
681
  }
1395
682
  },
@@ -1408,7 +695,7 @@ function createGradientToolProvider(controller, options = {}) {
1408
695
  if (!res.ok) fail(res.message);
1409
696
  return {
1410
697
  gradient: controller.getGradient(),
1411
- css: gradientToCss(controller.getGradient())
698
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, controller.getGradient())
1412
699
  };
1413
700
  }
1414
701
  },
@@ -1427,10 +714,61 @@ function createGradientToolProvider(controller, options = {}) {
1427
714
  if (!res.ok) fail(res.message);
1428
715
  return {
1429
716
  gradient: controller.getGradient(),
1430
- css: gradientToCss(controller.getGradient())
717
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, controller.getGradient())
1431
718
  };
1432
719
  }
1433
720
  },
721
+ {
722
+ name: "set_gradient_from_samples",
723
+ title: "Set Gradient From Sampled Colours",
724
+ description: "Fits the fewest stops that reproduce colours sampled along a line (from a photo, painting or shape, e.g. image sample_gradient or your own picks) and makes them the gradient's stops, keeping its type, angle and centre and switching interpolation to oklab. Noise is smoothed first; stops are added where the colour turns most until every sample is within tolerance. One undo step. Returns the gradient, its CSS, the stop count and the largest error left (OKLab \u0394E).",
725
+ inputSchema: {
726
+ type: "object",
727
+ properties: {
728
+ samples: {
729
+ type: "array",
730
+ minItems: 2,
731
+ maxItems: 1024,
732
+ description: "Colours in order along the line.",
733
+ items: {
734
+ type: "object",
735
+ properties: {
736
+ offset: { type: "number", minimum: 0, maximum: 1, description: "Position along the line, 0..1." },
737
+ color: { type: "string", description: "Any CSS colour (hex, rgb(), oklch(), named\u2026)." }
738
+ },
739
+ required: ["offset", "color"],
740
+ additionalProperties: false
741
+ }
742
+ },
743
+ tolerance: { type: "number", exclusiveMinimum: 0, maximum: 1, description: "Largest error left, OKLab \u0394E (default 0.06; 0.02 is a just-noticeable step, lower keeps more stops)." },
744
+ minStops: { type: "integer", minimum: 2, maximum: 64, description: "Fewest stops (default 2)." },
745
+ maxStops: { type: "integer", minimum: 2, maximum: 64, description: "Most stops (default 5)." },
746
+ smoothing: { type: "integer", minimum: 0, maximum: 16, description: "Samples on each side averaged into each one to ignore grain and texture (default 2; 0 fits the raw colours)." }
747
+ },
748
+ required: ["samples"],
749
+ additionalProperties: false
750
+ },
751
+ annotations: writeIdempotentTool("Set Gradient From Sampled Colours"),
752
+ handler: async (args) => {
753
+ const unreadable = args.samples.findIndex((x) => !_chunkRD7RX52Gcjs.isColor.call(void 0, x.color));
754
+ if (unreadable >= 0) fail(`samples[${unreadable}].color ${JSON.stringify(args.samples[unreadable].color)} is not a CSS colour.`);
755
+ let fit;
756
+ try {
757
+ fit = _chunkS6OT6CTScjs.fitGradientStops.call(void 0, args.samples, {
758
+ tolerance: args.tolerance,
759
+ minStops: args.minStops,
760
+ maxStops: args.maxStops,
761
+ smoothing: args.smoothing
762
+ });
763
+ } catch (e) {
764
+ return fail(e.message);
765
+ }
766
+ const res = controller.setGradient({ ...controller.getGradient(), stops: fit.stops, interpolation: "oklab" }, "Gradient From Samples");
767
+ if (!res.ok) fail(res.message);
768
+ const gradient = controller.getGradient();
769
+ return { gradient, css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, gradient), stopCount: gradient.stops.length, maxError: fit.maxError };
770
+ }
771
+ },
1434
772
  {
1435
773
  name: "apply_gradient_preset",
1436
774
  title: "Apply Gradient Preset",
@@ -1448,7 +786,7 @@ function createGradientToolProvider(controller, options = {}) {
1448
786
  },
1449
787
  annotations: writeIdempotentTool("Apply Gradient Preset"),
1450
788
  handler: async (args) => {
1451
- const gradient = GRADIENT_PRESETS[args.id];
789
+ const gradient = _chunkS6OT6CTScjs.GRADIENT_PRESETS[args.id];
1452
790
  if (!gradient) {
1453
791
  fail(`Unknown gradient preset "${args.id}". Use list_gradient_presets to inspect available presets.`);
1454
792
  }
@@ -1457,7 +795,7 @@ function createGradientToolProvider(controller, options = {}) {
1457
795
  return {
1458
796
  preset: args.id,
1459
797
  gradient: controller.getGradient(),
1460
- css: gradientToCss(controller.getGradient())
798
+ css: _chunkS6OT6CTScjs.gradientToCss.call(void 0, controller.getGradient())
1461
799
  };
1462
800
  }
1463
801
  }
@@ -1473,55 +811,6 @@ function createGradientToolProvider(controller, options = {}) {
1473
811
  };
1474
812
  }
1475
813
 
1476
- // src/gradient/editor.ts
1477
- function stopFromTrackPosition(g, x) {
1478
- return Math.max(0, Math.min(1, Math.round(x * 1e3) / 1e3));
1479
- }
1480
- function trackPositionFromStop(stop) {
1481
- return Math.max(0, Math.min(1, stop.offset));
1482
- }
1483
- function gradientKeyStep(g, id, key, shift = false) {
1484
- const stop = g.stops.find((s) => s.id === id);
1485
- if (!stop) return null;
1486
- const step = shift ? 0.1 : 0.01;
1487
- switch (key) {
1488
- case "ArrowLeft":
1489
- case "ArrowDown": {
1490
- const offset = Math.max(0, Math.round((stop.offset - step) * 1e3) / 1e3);
1491
- return { stopId: id, offset };
1492
- }
1493
- case "ArrowRight":
1494
- case "ArrowUp": {
1495
- const offset = Math.min(1, Math.round((stop.offset + step) * 1e3) / 1e3);
1496
- return { stopId: id, offset };
1497
- }
1498
- case "Delete":
1499
- case "Backspace": {
1500
- return { stopId: id, remove: true };
1501
- }
1502
- default:
1503
- return null;
1504
- }
1505
- }
1506
- function angleFromPointer(center, point, snapStep) {
1507
- const dx = point.x - center.x;
1508
- const dy = point.y - center.y;
1509
- let deg = Math.atan2(dx, -dy) * 180 / Math.PI;
1510
- if (deg < 0) deg += 360;
1511
- if (snapStep && snapStep > 0) {
1512
- deg = Math.round(deg / snapStep) * snapStep;
1513
- if (deg >= 360) deg -= 360;
1514
- }
1515
- return Math.round(deg);
1516
- }
1517
- function gradientTrackBackground(g) {
1518
- const linearCopy = {
1519
- ...g,
1520
- type: "linear",
1521
- angle: 90
1522
- };
1523
- return gradientToCss(linearCopy);
1524
- }
1525
814
 
1526
815
 
1527
816
 
@@ -1550,4 +839,6 @@ function gradientTrackBackground(g) {
1550
839
 
1551
840
 
1552
841
 
1553
- exports.GRADIENT_INTERPOLATIONS = GRADIENT_INTERPOLATIONS; exports.GRADIENT_PRESETS = GRADIENT_PRESETS; exports.GRADIENT_TYPES = GRADIENT_TYPES; exports.GradientController = GradientController; exports.angleFromPointer = angleFromPointer; exports.checkGradient = checkGradient; exports.createGradient = createGradient; exports.createGradientToolProvider = createGradientToolProvider; exports.distributeGradientStops = distributeGradientStops; exports.gradientKeyStep = gradientKeyStep; exports.gradientMidpointRemap = gradientMidpointRemap; exports.gradientToCss = gradientToCss; exports.gradientToCssFallback = gradientToCssFallback; exports.gradientToSvgDef = gradientToSvgDef; exports.gradientTrackBackground = gradientTrackBackground; exports.insertGradientStop = insertGradientStop; exports.isDualColorValue = isDualColorValue; exports.isDualGradient = isDualGradient; exports.normalizeGradient = normalizeGradient; exports.parseCssGradient = parseCssGradient; exports.removeGradientStop = removeGradientStop; exports.resolveGradient = resolveGradient; exports.reverseGradient = reverseGradient; exports.sampleGradient = sampleGradient; exports.stopFromTrackPosition = stopFromTrackPosition; exports.trackPositionFromStop = trackPositionFromStop; exports.updateGradientStop = updateGradientStop;
842
+
843
+
844
+ exports.GRADIENT_INTERPOLATIONS = GRADIENT_INTERPOLATIONS; exports.GRADIENT_PRESETS = _chunkS6OT6CTScjs.GRADIENT_PRESETS; exports.GRADIENT_TYPES = GRADIENT_TYPES; exports.GradientController = GradientController; exports.angleFromPointer = _chunkS6OT6CTScjs.angleFromPointer; exports.checkGradient = _chunkS6OT6CTScjs.checkGradient; exports.createGradient = _chunkS6OT6CTScjs.createGradient; exports.createGradientToolProvider = createGradientToolProvider; exports.distributeGradientStops = _chunkS6OT6CTScjs.distributeGradientStops; exports.fitGradientStops = _chunkS6OT6CTScjs.fitGradientStops; exports.gradientKeyStep = _chunkS6OT6CTScjs.gradientKeyStep; exports.gradientMidpointRemap = _chunkS6OT6CTScjs.gradientMidpointRemap; exports.gradientToCss = _chunkS6OT6CTScjs.gradientToCss; exports.gradientToCssFallback = _chunkS6OT6CTScjs.gradientToCssFallback; exports.gradientToSvgDef = _chunkS6OT6CTScjs.gradientToSvgDef; exports.gradientTrackBackground = _chunkS6OT6CTScjs.gradientTrackBackground; exports.insertGradientStop = _chunkS6OT6CTScjs.insertGradientStop; exports.isDualColorValue = _chunkS6OT6CTScjs.isDualColorValue; exports.isDualGradient = _chunkS6OT6CTScjs.isDualGradient; exports.normalizeGradient = _chunkS6OT6CTScjs.normalizeGradient; exports.parseCssGradient = _chunkS6OT6CTScjs.parseCssGradient; exports.removeGradientStop = _chunkS6OT6CTScjs.removeGradientStop; exports.resolveGradient = _chunkS6OT6CTScjs.resolveGradient; exports.reverseGradient = _chunkS6OT6CTScjs.reverseGradient; exports.sampleGradient = _chunkS6OT6CTScjs.sampleGradient; exports.sampleGradientFromLine = _chunkS6OT6CTScjs.sampleGradientFromLine; exports.simplifyGradientStops = _chunkS6OT6CTScjs.simplifyGradientStops; exports.stopFromTrackPosition = _chunkS6OT6CTScjs.stopFromTrackPosition; exports.trackPositionFromStop = _chunkS6OT6CTScjs.trackPositionFromStop; exports.updateGradientStop = _chunkS6OT6CTScjs.updateGradientStop;