@pixerate/editor 0.264.1 → 0.266.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 (60) hide show
  1. package/dist/agent/index.cjs +4 -3
  2. package/dist/agent/index.js +3 -2
  3. package/dist/animation-editor/index.cjs +60 -61
  4. package/dist/animation-editor/index.js +4 -5
  5. package/dist/brushes/index.cjs +73 -60
  6. package/dist/brushes/index.d.cts +1 -0
  7. package/dist/brushes/index.d.ts +1 -0
  8. package/dist/brushes/index.js +17 -4
  9. package/dist/brushes/preview.d.cts +59 -0
  10. package/dist/brushes/preview.d.ts +59 -0
  11. package/dist/brushes/tools.d.cts +12 -5
  12. package/dist/brushes/tools.d.ts +12 -5
  13. package/dist/{brushstrokeRender-3MOI7PH4.js → brushstrokeRender-4UB6NRJW.js} +11 -4
  14. package/dist/{brushstrokeRender-SMMPIJF2.cjs → brushstrokeRender-JQ2XQRUD.cjs} +22 -15
  15. package/dist/canvas/brushstroke.d.cts +6 -1
  16. package/dist/canvas/brushstroke.d.ts +6 -1
  17. package/dist/canvas/index.cjs +18 -18
  18. package/dist/canvas/index.js +4 -4
  19. package/dist/{chunk-TMDDMJCR.js → chunk-472INMWH.js} +4 -2
  20. package/dist/chunk-55ALHYJY.js +289 -0
  21. package/dist/{chunk-F3KKR6DD.cjs → chunk-5OE4ZZ6V.cjs} +30 -30
  22. package/dist/{chunk-BY5EBP26.cjs → chunk-677777GH.cjs} +3 -3
  23. package/dist/{chunk-NHA26O5X.cjs → chunk-7KNW3WXZ.cjs} +14 -12
  24. package/dist/{chunk-G5ADO47G.cjs → chunk-7NQOGWLM.cjs} +3 -2
  25. package/dist/{chunk-WWI6FLH2.js → chunk-7PW6VCNW.js} +2 -2
  26. package/dist/{chunk-CECCP2V7.js → chunk-BLR4KWYQ.js} +1 -1
  27. package/dist/chunk-DEBIFWY6.cjs +77 -0
  28. package/dist/{chunk-KXNZNOEF.cjs → chunk-DGXTEPCU.cjs} +94 -94
  29. package/dist/{chunk-3CI7FRMK.js → chunk-DVPQFMH6.js} +13 -1
  30. package/dist/chunk-E2Z4UARJ.cjs +289 -0
  31. package/dist/chunk-HAEB3MZD.js +664 -0
  32. package/dist/{chunk-EE7SAYBF.js → chunk-J4SGJCPW.js} +3 -3
  33. package/dist/{chunk-A2IS7EHE.cjs → chunk-JBZRVLXV.cjs} +14 -2
  34. package/dist/chunk-KIJIONZF.cjs +664 -0
  35. package/dist/{chunk-V7MJ4HIN.cjs → chunk-NOP4Y5AB.cjs} +23 -23
  36. package/dist/{chunk-FQC5TDB6.cjs → chunk-O53MOGXG.cjs} +35 -35
  37. package/dist/{chunk-LPFQHVCO.js → chunk-PXXXRCME.js} +1 -284
  38. package/dist/{chunk-4OJC4MCD.js → chunk-Q6RVVJW6.js} +1 -1
  39. package/dist/{chunk-T7QSEKDY.cjs → chunk-QJVOJUTD.cjs} +4 -287
  40. package/dist/{chunk-HAUDEVMC.js → chunk-WY23AUCA.js} +2 -2
  41. package/dist/{chunk-JEML4FSA.js → chunk-XDNWQMHY.js} +3 -2
  42. package/dist/{chunk-ROBSFJ6F.js → chunk-Z2Z2OHRM.js} +1 -1
  43. package/dist/{chunk-USJX5SW4.cjs → chunk-ZHRVCW3M.cjs} +12 -12
  44. package/dist/chunk-ZS7LB2MV.js +77 -0
  45. package/dist/commands/index.cjs +26 -656
  46. package/dist/commands/index.js +18 -648
  47. package/dist/image-editor/index.cjs +788 -790
  48. package/dist/image-editor/index.js +6 -8
  49. package/dist/paint-editor/index.cjs +88 -84
  50. package/dist/paint-editor/index.js +12 -8
  51. package/dist/vector/contract.d.cts +52 -0
  52. package/dist/vector/contract.d.ts +52 -0
  53. package/dist/vector/index.cjs +1168 -971
  54. package/dist/vector/index.d.cts +1 -0
  55. package/dist/vector/index.d.ts +1 -0
  56. package/dist/vector/index.js +204 -7
  57. package/package.json +1 -1
  58. package/skills/pixerate-brushes/SKILL.md +7 -2
  59. package/dist/chunk-FJBQTZS4.js +0 -17
  60. package/dist/chunk-LRTR4ASZ.cjs +0 -17
@@ -8,7 +8,7 @@
8
8
 
9
9
 
10
10
 
11
- var _chunkF3KKR6DDcjs = require('../chunk-F3KKR6DD.cjs');
11
+ var _chunk5OE4ZZ6Vcjs = require('../chunk-5OE4ZZ6V.cjs');
12
12
  require('../chunk-PE6YJMQT.cjs');
13
13
 
14
14
 
@@ -17,6 +17,7 @@ require('../chunk-PE6YJMQT.cjs');
17
17
 
18
18
 
19
19
 
20
+ var _chunkDEBIFWY6cjs = require('../chunk-DEBIFWY6.cjs');
20
21
 
21
22
 
22
23
 
@@ -61,14 +62,20 @@ require('../chunk-PE6YJMQT.cjs');
61
62
 
62
63
 
63
64
 
64
- var _chunkBY5EBP26cjs = require('../chunk-BY5EBP26.cjs');
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+ var _chunk677777GHcjs = require('../chunk-677777GH.cjs');
65
73
 
66
74
 
67
75
  var _chunkOTN6VB5Scjs = require('../chunk-OTN6VB5S.cjs');
68
76
 
69
77
 
70
- var _chunkLRTR4ASZcjs = require('../chunk-LRTR4ASZ.cjs');
71
- require('../chunk-A2IS7EHE.cjs');
78
+ var _chunkJBZRVLXVcjs = require('../chunk-JBZRVLXV.cjs');
72
79
  require('../chunk-U67EN7GG.cjs');
73
80
  require('../chunk-WOFXZ3XU.cjs');
74
81
 
@@ -115,20 +122,20 @@ var ARIA = {
115
122
  "light.pressure": "Light follows pressure"
116
123
  };
117
124
  var aria = (path, label) => _nullishCoalesce(ARIA[path], () => ( `Brush ${label.toLowerCase()}`));
118
- function brushEditorSections(brush, profile = _chunkBY5EBP26cjs.PAINT_PROFILE) {
119
- const resolved = _chunkBY5EBP26cjs.resolveBrush.call(void 0, brush);
120
- const engine = _chunkBY5EBP26cjs.resolveEngine.call(void 0, brush);
121
- const fieldOf = (facet) => _chunkBY5EBP26cjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
122
- const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunkBY5EBP26cjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunkBY5EBP26cjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
125
+ function brushEditorSections(brush, profile = _chunk677777GHcjs.PAINT_PROFILE) {
126
+ const resolved = _chunk677777GHcjs.resolveBrush.call(void 0, brush);
127
+ const engine = _chunk677777GHcjs.resolveEngine.call(void 0, brush);
128
+ const fieldOf = (facet) => _chunk677777GHcjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
129
+ const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunk677777GHcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunk677777GHcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
123
130
  const value = (path) => {
124
- const own = _chunkBY5EBP26cjs.getPath.call(void 0, brush, path);
131
+ const own = _chunk677777GHcjs.getPath.call(void 0, brush, path);
125
132
  if (own !== void 0) return own;
126
133
  const field = fieldOf(path);
127
134
  if (!field) return void 0;
128
- const v = _chunkBY5EBP26cjs.getPath.call(void 0, resolved, field.engine);
135
+ const v = _chunk677777GHcjs.getPath.call(void 0, resolved, field.engine);
129
136
  return field.map ? field.map.toFacet(v) : v;
130
137
  };
131
- const issues = _chunkBY5EBP26cjs.checkBrush.call(void 0, brush, profile).issues;
138
+ const issues = _chunk677777GHcjs.checkBrush.call(void 0, brush, profile).issues;
132
139
  const warned = new Map(issues.filter((i) => i.severity === "warning").map((i) => [i.facet, i.reason]));
133
140
  const refused = new Set(issues.filter((i) => i.severity === "error").map((i) => i.facet));
134
141
  const full = (s) => s === "full";
@@ -157,18 +164,18 @@ function brushEditorSections(brush, profile = _chunkBY5EBP26cjs.PAINT_PROFILE) {
157
164
  const exchangeFull = full(_optionalChain([brush, 'access', _9 => _9.behaviour, 'optionalAccess', _10 => _10.exchange, 'optionalAccess', _11 => _11.reservoir]) ? profile.reservoir : profile.exchange);
158
165
  add("medium", "Medium", [
159
166
  profile.kinds.length > 1 && profile.kinds.includes(brush.kind) && choice("kind", "Kind", options(profile.kinds, { mark: "Lays a material", tool: "Works on paint" })),
160
- !isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunkBY5EBP26cjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
167
+ !isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunk677777GHcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
161
168
  !isTool && withNote({ kind: "text", path: "variety", label: "Variety", ariaLabel: "Brush variety", value: _nullishCoalesce(brush.variety, () => ( "")), placeholder: "pencil, oil, highlighter\u2026" }),
162
169
  isTool && !!brush.tool && profile.tools.includes(brush.tool) && choice("tool", "Tool", options(profile.tools, TOOL_LABELS))
163
170
  ]);
164
- const engineControls = _chunkF3KKR6DDcjs.brushEngineControls.call(void 0, resolved);
165
- const tipSliders = _chunkF3KKR6DDcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
171
+ const engineControls = _chunk5OE4ZZ6Vcjs.brushEngineControls.call(void 0, resolved);
172
+ const tipSliders = _chunk5OE4ZZ6Vcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
166
173
  add("shape", "Shape", [
167
174
  !refused.has("tip.shape") && choice("tip.shape", "Tip", options(profile.tipShapes.filter((s) => !isTool || s !== "stamp"), SHAPE_LABELS)),
168
175
  ...tipSliders.map((c) => slider(c)),
169
176
  engine === "dab" && choice("tip.blend", "Blend", _chunk2VX55NFMcjs.BLEND_MODES.map((m) => ({ value: m.id, label: m.label })), "normal"),
170
177
  ...shape === "bristle" && engineOk && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("bristle.")).map((c) => slider(c)) : [],
171
- shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunkBY5EBP26cjs.MAX_DOT_TEXTURES : _chunkBY5EBP26cjs.MAX_STICKER_STAMPS, options: STAMP_OPTIONS })
178
+ shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunk677777GHcjs.MAX_DOT_TEXTURES : _chunk677777GHcjs.MAX_STICKER_STAMPS, options: STAMP_OPTIONS })
172
179
  ]);
173
180
  if (!isTool && profile.marks.length > 1 && engineOk) {
174
181
  const particles = marks === "particles" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("particle.") && c.path !== "particle.waveSpeed") : [];
@@ -176,21 +183,21 @@ function brushEditorSections(brush, profile = _chunkBY5EBP26cjs.PAINT_PROFILE) {
176
183
  const render = value("marks.render");
177
184
  add("marks", "Marks", [
178
185
  choice("marks.kind", "Laid as", options(profile.marks, MARKS_LABELS), "continuous"),
179
- marks === "particles" && choice("marks.physics", "Particles", options(_chunkBY5EBP26cjs.PARTICLE_KINDS, PHYSICS_LABELS)),
180
- marks === "particles" && choice("marks.render", "Drawn as", options(_chunkBY5EBP26cjs.PARTICLE_RENDERS, RENDER_LABELS)),
181
- marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunkBY5EBP26cjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
182
- marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunkBY5EBP26cjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
183
- marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunkBY5EBP26cjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
186
+ marks === "particles" && choice("marks.physics", "Particles", options(_chunk677777GHcjs.PARTICLE_KINDS, PHYSICS_LABELS)),
187
+ marks === "particles" && choice("marks.render", "Drawn as", options(_chunk677777GHcjs.PARTICLE_RENDERS, RENDER_LABELS)),
188
+ marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunk677777GHcjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
189
+ marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunk677777GHcjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
190
+ marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunk677777GHcjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
184
191
  ...particles.map((c) => slider(c)),
185
192
  ...objects.map((c) => slider(c))
186
193
  ]);
187
194
  }
188
- const feel = _chunkF3KKR6DDcjs.BRUSH_SLIDERS.filter((c) => ["tip.smoothing", "pressureSmoothing", "dynamics.minSize", "dynamics.tiltSize", "dynamics.velocitySize"].includes(c.path)).filter((c) => !(c.path === "dynamics.tiltSize" && !full(profile.tilt)) && !(c.path === "dynamics.velocitySize" && !full(profile.velocity)));
195
+ const feel = _chunk5OE4ZZ6Vcjs.BRUSH_SLIDERS.filter((c) => ["tip.smoothing", "pressureSmoothing", "dynamics.minSize", "dynamics.tiltSize", "dynamics.velocitySize"].includes(c.path)).filter((c) => !(c.path === "dynamics.tiltSize" && !full(profile.tilt)) && !(c.path === "dynamics.velocitySize" && !full(profile.velocity)));
189
196
  add("feel", "Feel", [
190
197
  ...feel.map((c) => slider(c)),
191
198
  toggle("dynamics.pressureSize", "Pressure \u2192 size"),
192
199
  toggle("dynamics.pressureOpacity", "Pressure \u2192 opacity"),
193
- choice("dynamics.rotation", "Rotation", options(_chunkBY5EBP26cjs.BRUSH_ROTATIONS, ROTATION_LABELS))
200
+ choice("dynamics.rotation", "Rotation", options(_chunk677777GHcjs.BRUSH_ROTATIONS, ROTATION_LABELS))
194
201
  ]);
195
202
  const surfaces = profile.surfaces;
196
203
  const engineSliders = (engineOk ? _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _12 => _12.sliders]), () => ( [])) : []).filter((c) => !/^(bristle|particle|sticker)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
@@ -198,8 +205,8 @@ function brushEditorSections(brush, profile = _chunkBY5EBP26cjs.PAINT_PROFILE) {
198
205
  add("behaviour", _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _15 => _15.title]), () => ( "Behaviour")), [
199
206
  !isTool && surfaces.length > 1 && !refused.has("behaviour.surface") && choice("behaviour.surface", "Surface", options(surfaces, SURFACE_LABELS), "dry"),
200
207
  full(profile.grain) && slider({ path: "grain", label: "Grain", min: 0, max: 1, step: 0.01 }, "behaviour.grain"),
201
- engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunkBY5EBP26cjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
202
- engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(_chunkBY5EBP26cjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
208
+ engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunk677777GHcjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
209
+ engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(_chunk677777GHcjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
203
210
  ...engineSliders.map((c) => exchangeOk(facetOf(c.path)) ? slider(c) : null),
204
211
  engineOk && _optionalChain([engineControls, 'optionalAccess', _16 => _16.mixingPath]) && (engine === "wet" || exchangeFull) && fieldOf("behaviour.mixing") && choice("behaviour.mixing", "Mixing", options(["pigment", "rgb"], { pigment: "Pigment", rgb: "RGB" })),
205
212
  engineOk && _optionalChain([engineControls, 'optionalAccess', _17 => _17.dirty]) && exchangeFull && fieldOf("behaviour.exchange.dirty") && toggle("behaviour.exchange.dirty", "Dirty brush"),
@@ -217,17 +224,17 @@ function brushEditorSections(brush, profile = _chunkBY5EBP26cjs.PAINT_PROFILE) {
217
224
  if (full(profile.motion) && engineOk && marks === "particles") add("motion", "Motion", [slider({ path: "particle.waveSpeed", label: "Wave speed", min: 0, max: 1, step: 0.01 })]);
218
225
  if (!isTool) {
219
226
  const own = _optionalChain([brush, 'access', _22 => _22.colour, 'optionalAccess', _23 => _23.default]);
220
- const hex = (c) => typeof c === "string" ? _nullishCoalesce(_chunkLRTR4ASZcjs.brushColourHex.call(void 0, c, "light"), () => ( null)) : null;
227
+ const hex = (c) => typeof c === "string" ? _nullishCoalesce(_chunkJBZRVLXVcjs.brushColourHex.call(void 0, c, "light"), () => ( null)) : null;
221
228
  const pair = _chunkMLLTWAXHcjs.isDualColor.call(void 0, own) ? own : null;
222
229
  add("colour", "Colour", [
223
- !refused.has("colour.default") && withNote({ kind: "colour", path: "colour.default", label: "Default colour", ariaLabel: "Brush default colour", value: pair ? _nullishCoalesce(_chunkLRTR4ASZcjs.brushColourHex.call(void 0, pair, "light"), () => ( null)) : hex(own), dark: pair ? _nullishCoalesce(_chunkLRTR4ASZcjs.brushColourHex.call(void 0, pair, "dark"), () => ( null)) : null, gradient: own !== void 0 && typeof own === "object" && !pair }),
230
+ !refused.has("colour.default") && withNote({ kind: "colour", path: "colour.default", label: "Default colour", ariaLabel: "Brush default colour", value: pair ? _nullishCoalesce(_chunkJBZRVLXVcjs.brushColourHex.call(void 0, pair, "light"), () => ( null)) : hex(own), dark: pair ? _nullishCoalesce(_chunkJBZRVLXVcjs.brushColourHex.call(void 0, pair, "dark"), () => ( null)) : null, gradient: own !== void 0 && typeof own === "object" && !pair }),
224
231
  withNote({
225
232
  kind: "palette",
226
233
  path: "colour.palette",
227
234
  label: "Palette",
228
235
  ariaLabel: "Brush palette",
229
- value: (_nullishCoalesce(_optionalChain([brush, 'access', _24 => _24.colour, 'optionalAccess', _25 => _25.palette]), () => ( []))).flatMap((c) => _chunkMLLTWAXHcjs.isDualColor.call(void 0, c) ? [{ light: _chunkLRTR4ASZcjs.brushColourHex.call(void 0, c, "light"), dark: _chunkLRTR4ASZcjs.brushColourHex.call(void 0, c, "dark") }] : hex(c) ? [hex(c)] : []),
230
- max: _chunkBY5EBP26cjs.MAX_BRUSH_PALETTE
236
+ value: (_nullishCoalesce(_optionalChain([brush, 'access', _24 => _24.colour, 'optionalAccess', _25 => _25.palette]), () => ( []))).flatMap((c) => _chunkMLLTWAXHcjs.isDualColor.call(void 0, c) ? [{ light: _chunkJBZRVLXVcjs.brushColourHex.call(void 0, c, "light"), dark: _chunkJBZRVLXVcjs.brushColourHex.call(void 0, c, "dark") }] : hex(c) ? [hex(c)] : []),
237
+ max: _chunk677777GHcjs.MAX_BRUSH_PALETTE
231
238
  }),
232
239
  toggle("colour.own", "Always its own colour")
233
240
  ]);
@@ -261,15 +268,15 @@ function hiddenLabel(issue, b) {
261
268
  case "dynamics.tilt":
262
269
  return "tilt dynamics";
263
270
  case "colour.default":
264
- return `a ${_chunkBY5EBP26cjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
271
+ return `a ${_chunk677777GHcjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
265
272
  default:
266
273
  return null;
267
274
  }
268
275
  }
269
276
  var sentence = (words) => words.length < 2 ? _nullishCoalesce(words[0], () => ( "")) : `${words.slice(0, -1).join(", ")} and ${words.at(-1)}`;
270
- function brushEditorScope(brush, profile = _chunkBY5EBP26cjs.PAINT_PROFILE) {
277
+ function brushEditorScope(brush, profile = _chunk677777GHcjs.PAINT_PROFILE) {
271
278
  const hidden = [];
272
- for (const issue of _chunkBY5EBP26cjs.checkBrush.call(void 0, brush, profile).issues) {
279
+ for (const issue of _chunk677777GHcjs.checkBrush.call(void 0, brush, profile).issues) {
273
280
  const label = hiddenLabel(issue, brush);
274
281
  if (label && !hidden.some((h) => h.label === label)) hidden.push({ facet: issue.facet, label });
275
282
  }
@@ -282,17 +289,17 @@ function newBrushFor(profile, from, name = "New brush") {
282
289
  const id = brushIdFromName(name);
283
290
  const base = { id, name, kind: profile.kinds.includes("mark") ? "mark" : profile.kinds[0], ...profile.kinds.includes("mark") ? {} : { tool: profile.tools[0] }, tip: { shape: profile.tipShapes.includes("round") ? "round" : profile.tipShapes[0] } };
284
291
  if (from) {
285
- const stripped = _chunkBY5EBP26cjs.degrade.call(void 0, from, profile, { ignored: true });
292
+ const stripped = _chunk677777GHcjs.degrade.call(void 0, from, profile, { ignored: true });
286
293
  if (!stripped.issues.length) return { ...stripped.brush, id, name };
287
294
  }
288
295
  return base;
289
296
  }
290
297
  async function saveBrushEdit(library, options2) {
291
298
  const { original, profile } = options2;
292
- const check = _chunkBY5EBP26cjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
299
+ const check = _chunk677777GHcjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
293
300
  if (!check.ok) {
294
301
  const errors = check.issues.filter((i) => i.severity === "error").map((i) => `${i.facet}: ${i.reason} ${i.fix}`);
295
- throw new (0, _chunkBY5EBP26cjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
302
+ throw new (0, _chunk677777GHcjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
296
303
  }
297
304
  const inPlace = !!original && options2.name === void 0 && !library.isBuiltin(original.id) && original.id === options2.brush.id && !!await library.get(original.id);
298
305
  let brush = options2.brush;
@@ -328,13 +335,13 @@ function setBrushEditorValue(brush, path, value) {
328
335
  if (value !== "bristle") delete next.tip.bristle;
329
336
  } else if (value === void 0 || value === "") {
330
337
  const keys = path.split(".");
331
- const parent = _chunkBY5EBP26cjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
338
+ const parent = _chunk677777GHcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
332
339
  if (keys.length === 1) delete next[keys[0]];
333
340
  else if (parent) delete parent[keys[keys.length - 1]];
334
- } else _chunkBY5EBP26cjs.setPath.call(void 0, next, path, value);
341
+ } else _chunk677777GHcjs.setPath.call(void 0, next, path, value);
335
342
  const problems = [];
336
343
  try {
337
- return { brush: _chunkBY5EBP26cjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
344
+ return { brush: _chunk677777GHcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
338
345
  } catch (e) {
339
346
  return { brush, problems: [e.message] };
340
347
  }
@@ -350,7 +357,7 @@ function brushLibraryGroups(entries, filter = {}) {
350
357
  const text = words([b.id, b.name, _nullishCoalesce(b.variety, () => ( "")), _nullishCoalesce(b.medium, () => ( "")), _nullishCoalesce(b.tool, () => ( "")), ..._nullishCoalesce(b.tags, () => ( []))].join(" "));
351
358
  if (!wanted.every((w) => text.some((t) => t.startsWith(w)))) continue;
352
359
  }
353
- if (filter.profile && !_chunkBY5EBP26cjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
360
+ if (filter.profile && !_chunk677777GHcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
354
361
  const id = b.kind === "tool" ? "tools" : _nullishCoalesce(b.medium, () => ( "other"));
355
362
  let g = groups.get(id);
356
363
  if (!g) groups.set(id, g = { id, title: id === "tools" ? "Tools" : id === "other" ? "Other" : MEDIUM_LABELS[id], varieties: [] });
@@ -372,11 +379,11 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
372
379
  properties: {
373
380
  id: { type: "string", description: "paint, image, canvas, vector\u2026" },
374
381
  name: { type: "string", description: "Display name, used in messages." },
375
- kinds: { type: "array", items: { type: "string", enum: [..._chunkBY5EBP26cjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
376
- tools: { type: "array", items: { type: "string", enum: [..._chunkBY5EBP26cjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
377
- tipShapes: { type: "array", items: { type: "string", enum: [..._chunkBY5EBP26cjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
378
- marks: { type: "array", items: { type: "string", enum: [..._chunkBY5EBP26cjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
379
- surfaces: { type: "array", items: { type: "string", enum: [..._chunkBY5EBP26cjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
382
+ kinds: { type: "array", items: { type: "string", enum: [..._chunk677777GHcjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
383
+ tools: { type: "array", items: { type: "string", enum: [..._chunk677777GHcjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
384
+ tipShapes: { type: "array", items: { type: "string", enum: [..._chunk677777GHcjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
385
+ marks: { type: "array", items: { type: "string", enum: [..._chunk677777GHcjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
386
+ surfaces: { type: "array", items: { type: "string", enum: [..._chunk677777GHcjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
380
387
  exchange: { ...SUPPORT, description: "Picking paint up and mixing it in." },
381
388
  reservoir: { ...SUPPORT, description: "The Mixer Brush reservoir." },
382
389
  grain: { ...SUPPORT, description: "Paper grain response." },
@@ -401,7 +408,7 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
401
408
  additionalProperties: false
402
409
  };
403
410
  function migrationInputs() {
404
- const pick = (id) => _chunkBY5EBP26cjs.brushToJSON.call(void 0, _chunkBY5EBP26cjs.BUILTIN_BRUSHES.find((b) => b.id === id));
411
+ const pick = (id) => _chunk677777GHcjs.brushToJSON.call(void 0, _chunk677777GHcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
405
412
  return [
406
413
  { id: "plain", name: "Plain" },
407
414
  pick("pencil-6b"),
@@ -423,34 +430,34 @@ function migrationInputs() {
423
430
  function editorSectionFixtures() {
424
431
  const ids = ["highlighter", "chalk", "watercolor-wash", "hair-strands", "mixer-brush", "blender", "spray-can"];
425
432
  return ids.flatMap(
426
- (id) => Object.keys(_chunkBY5EBP26cjs.BRUSH_HOST_PROFILES).map((host) => {
427
- const brush = _chunkBY5EBP26cjs.BRUSH_PRESETS.find((b) => b.id === id);
428
- return { brush: id, host, sections: brushEditorSections(brush, _chunkBY5EBP26cjs.BRUSH_HOST_PROFILES[host]) };
433
+ (id) => Object.keys(_chunk677777GHcjs.BRUSH_HOST_PROFILES).map((host) => {
434
+ const brush = _chunk677777GHcjs.BRUSH_PRESETS.find((b) => b.id === id);
435
+ return { brush: id, host, sections: brushEditorSections(brush, _chunk677777GHcjs.BRUSH_HOST_PROFILES[host]) };
429
436
  })
430
437
  );
431
438
  }
432
439
  function toolDefinitions() {
433
- const library = _chunkBY5EBP26cjs.createBrushLibrary.call(void 0, );
434
- const toolsFor = (host) => _chunkF3KKR6DDcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunkBY5EBP26cjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
440
+ const library = _chunk677777GHcjs.createBrushLibrary.call(void 0, );
441
+ const toolsFor = (host) => _chunk5OE4ZZ6Vcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunk677777GHcjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
435
442
  return {
436
443
  tools: toolsFor("paint").map((t) => ({ name: t.name, title: t.title, description: t.description, inputSchema: t.inputSchema, annotations: t.annotations })),
437
- hosts: Object.fromEntries(Object.keys(_chunkBY5EBP26cjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
444
+ hosts: Object.fromEntries(Object.keys(_chunk677777GHcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
438
445
  };
439
446
  }
440
447
  function brushContracts() {
441
- const presets = _chunkBY5EBP26cjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
442
- const resolved = _chunkBY5EBP26cjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunkBY5EBP26cjs.resolveEngine.call(void 0, b), category: _chunkBY5EBP26cjs.resolveCategory.call(void 0, b), brush: _chunkBY5EBP26cjs.brushToJSON.call(void 0, _chunkBY5EBP26cjs.resolveBrush.call(void 0, b)) }));
443
- const profiles = Object.values(_chunkBY5EBP26cjs.BRUSH_HOST_PROFILES);
444
- const checks = _chunkBY5EBP26cjs.BRUSH_PRESETS.map((b) => ({
448
+ const presets = _chunk677777GHcjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
449
+ const resolved = _chunk677777GHcjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunk677777GHcjs.resolveEngine.call(void 0, b), category: _chunk677777GHcjs.resolveCategory.call(void 0, b), brush: _chunk677777GHcjs.brushToJSON.call(void 0, _chunk677777GHcjs.resolveBrush.call(void 0, b)) }));
450
+ const profiles = Object.values(_chunk677777GHcjs.BRUSH_HOST_PROFILES);
451
+ const checks = _chunk677777GHcjs.BRUSH_PRESETS.map((b) => ({
445
452
  id: b.id,
446
453
  hosts: Object.fromEntries(profiles.map((p) => {
447
- const c = _chunkBY5EBP26cjs.checkBrush.call(void 0, b, p);
454
+ const c = _chunk677777GHcjs.checkBrush.call(void 0, b, p);
448
455
  return [p.id, { ok: c.ok, issues: c.issues.map(({ facet, severity }) => ({ facet, severity })) }];
449
456
  }))
450
457
  }));
451
- const migrations = migrationInputs().map((input) => ({ input, output: _chunkBY5EBP26cjs.migrateBrushV1.call(void 0, input), resolved: _chunkBY5EBP26cjs.brushToJSON.call(void 0, _chunkBY5EBP26cjs.resolveBrush.call(void 0, _chunkBY5EBP26cjs.migrateBrushV1.call(void 0, input))), engine: _chunkBY5EBP26cjs.normalizePaintBrush.call(void 0, input).engine }));
458
+ const migrations = migrationInputs().map((input) => ({ input, output: _chunk677777GHcjs.migrateBrushV1.call(void 0, input), resolved: _chunk677777GHcjs.brushToJSON.call(void 0, _chunk677777GHcjs.resolveBrush.call(void 0, _chunk677777GHcjs.migrateBrushV1.call(void 0, input))), engine: _chunk677777GHcjs.normalizePaintBrush.call(void 0, input).engine }));
452
459
  const files = {
453
- "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkBY5EBP26cjs.BRUSH_JSON_SCHEMA },
460
+ "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunk677777GHcjs.BRUSH_JSON_SCHEMA },
454
461
  "profile.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "profile.schema.json", ...BRUSH_PROFILE_JSON_SCHEMA },
455
462
  "library-file.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "library-file.schema.json", ...BRUSH_LIBRARY_FILE_JSON_SCHEMA },
456
463
  "presets.json": presets,
@@ -464,7 +471,7 @@ function brushContracts() {
464
471
  files["manifest.json"] = {
465
472
  domain: "brushes",
466
473
  formatVersion: BRUSH_CONTRACT_FORMAT_VERSION,
467
- limits: { maxPalette: _chunkBY5EBP26cjs.MAX_BRUSH_PALETTE },
474
+ limits: { maxPalette: _chunk677777GHcjs.MAX_BRUSH_PALETTE },
468
475
  counts: { presets: presets.length, profiles: profiles.length, migrations: migrations.length, editorSections: files["editor-sections.json"].length },
469
476
  files: Object.keys(files).sort()
470
477
  };
@@ -524,4 +531,10 @@ function brushContracts() {
524
531
 
525
532
 
526
533
 
527
- exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunkBY5EBP26cjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_HOST_PROFILES = _chunkBY5EBP26cjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunkBY5EBP26cjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunkBY5EBP26cjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunkBY5EBP26cjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunkBY5EBP26cjs.BRUSH_MEDIA; exports.BRUSH_PATCH_PROPERTIES = _chunkF3KKR6DDcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunkBY5EBP26cjs.BRUSH_PRESETS; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SURFACES = _chunkBY5EBP26cjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunkBY5EBP26cjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunkBY5EBP26cjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunkF3KKR6DDcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunkBY5EBP26cjs.BRUSH_WORD; exports.BrushLibraryError = _chunkBY5EBP26cjs.BrushLibraryError; exports.CANVAS_PROFILE = _chunkBY5EBP26cjs.CANVAS_PROFILE; exports.IMAGE_PROFILE = _chunkBY5EBP26cjs.IMAGE_PROFILE; exports.MAX_BRUSH_PALETTE = _chunkBY5EBP26cjs.MAX_BRUSH_PALETTE; exports.PAINT_PROFILE = _chunkBY5EBP26cjs.PAINT_PROFILE; exports.UNSETTABLE_BRUSH_FACETS = _chunkF3KKR6DDcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunkBY5EBP26cjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunkBY5EBP26cjs.WET_BRUSH_TOOLS; exports.brushColourHex = _chunkLRTR4ASZcjs.brushColourHex; exports.brushColourKind = _chunkBY5EBP26cjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorScope = brushEditorScope; exports.brushEditorSections = brushEditorSections; exports.brushIdFromName = brushIdFromName; exports.brushLibraryGroups = brushLibraryGroups; exports.changedBrushPaths = _chunkF3KKR6DDcjs.changedBrushPaths; exports.checkBrush = _chunkBY5EBP26cjs.checkBrush; exports.checkBrushEdit = _chunkBY5EBP26cjs.checkBrushEdit; exports.createBrushLibrary = _chunkBY5EBP26cjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunkF3KKR6DDcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunkF3KKR6DDcjs.createBrushLibraryTools; exports.degrade = _chunkBY5EBP26cjs.degrade; exports.isBrushLibrary = _chunkBY5EBP26cjs.isBrushLibrary; exports.listPresets = _chunkBY5EBP26cjs.listPresets; exports.mergeBrushPatch = _chunkF3KKR6DDcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunkBY5EBP26cjs.migrateBrushV1; exports.newBrushFor = newBrushFor; exports.normalizeBrushSpec = _chunkBY5EBP26cjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunkBY5EBP26cjs.parseBrushLibrary2; exports.resolveBrush = _chunkBY5EBP26cjs.resolveBrush; exports.resolveCategory = _chunkBY5EBP26cjs.resolveCategory; exports.resolveEngine = _chunkBY5EBP26cjs.resolveEngine; exports.resolveWetMedium = _chunkBY5EBP26cjs.resolveWetMedium; exports.saveBrushEdit = saveBrushEdit; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunkBY5EBP26cjs.snapshotBrushLibrary; exports.withKeptIssues = _chunkBY5EBP26cjs.withKeptIssues;
534
+
535
+
536
+
537
+
538
+
539
+
540
+ exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunk677777GHcjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_HOST_PROFILES = _chunk677777GHcjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunk677777GHcjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunk677777GHcjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunk677777GHcjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunk677777GHcjs.BRUSH_MEDIA; exports.BRUSH_PATCH_PROPERTIES = _chunk5OE4ZZ6Vcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunk677777GHcjs.BRUSH_PRESETS; exports.BRUSH_PREVIEW_DARK_PAPER = _chunkDEBIFWY6cjs.BRUSH_PREVIEW_DARK_PAPER; exports.BRUSH_PREVIEW_FALLBACKS = _chunkDEBIFWY6cjs.BRUSH_PREVIEW_FALLBACKS; exports.BRUSH_PREVIEW_MIN_CONTRAST = _chunkDEBIFWY6cjs.BRUSH_PREVIEW_MIN_CONTRAST; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SURFACES = _chunk677777GHcjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunk677777GHcjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunk677777GHcjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunk5OE4ZZ6Vcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunk677777GHcjs.BRUSH_WORD; exports.BrushLibraryError = _chunk677777GHcjs.BrushLibraryError; exports.CANVAS_PROFILE = _chunk677777GHcjs.CANVAS_PROFILE; exports.IMAGE_PROFILE = _chunk677777GHcjs.IMAGE_PROFILE; exports.MAX_BRUSH_PALETTE = _chunk677777GHcjs.MAX_BRUSH_PALETTE; exports.PAINT_PROFILE = _chunk677777GHcjs.PAINT_PROFILE; exports.UNSETTABLE_BRUSH_FACETS = _chunk5OE4ZZ6Vcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunk677777GHcjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunk677777GHcjs.WET_BRUSH_TOOLS; exports.brushColourHex = _chunkJBZRVLXVcjs.brushColourHex; exports.brushColourKind = _chunk677777GHcjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorScope = brushEditorScope; exports.brushEditorSections = brushEditorSections; exports.brushIdFromName = brushIdFromName; exports.brushLibraryGroups = brushLibraryGroups; exports.brushPreviewColours = _chunkDEBIFWY6cjs.brushPreviewColours; exports.brushPreviewStrength = _chunkDEBIFWY6cjs.brushPreviewStrength; exports.brushPreviewsOnDark = _chunkDEBIFWY6cjs.brushPreviewsOnDark; exports.changedBrushPaths = _chunk5OE4ZZ6Vcjs.changedBrushPaths; exports.checkBrush = _chunk677777GHcjs.checkBrush; exports.checkBrushEdit = _chunk677777GHcjs.checkBrushEdit; exports.createBrushLibrary = _chunk677777GHcjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunk5OE4ZZ6Vcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunk5OE4ZZ6Vcjs.createBrushLibraryTools; exports.degrade = _chunk677777GHcjs.degrade; exports.isBrushLibrary = _chunk677777GHcjs.isBrushLibrary; exports.listPresets = _chunk677777GHcjs.listPresets; exports.mergeBrushPatch = _chunk5OE4ZZ6Vcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunk677777GHcjs.migrateBrushV1; exports.newBrushFor = newBrushFor; exports.normalizeBrushSpec = _chunk677777GHcjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunk677777GHcjs.parseBrushLibrary2; exports.resolveBrush = _chunk677777GHcjs.resolveBrush; exports.resolveCategory = _chunk677777GHcjs.resolveCategory; exports.resolveEngine = _chunk677777GHcjs.resolveEngine; exports.resolveWetMedium = _chunk677777GHcjs.resolveWetMedium; exports.saveBrushEdit = saveBrushEdit; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunk677777GHcjs.snapshotBrushLibrary; exports.withKeptIssues = _chunk677777GHcjs.withKeptIssues;
@@ -15,6 +15,7 @@ export { resolveBrush, resolveCategory, resolveEngine, resolveWetMedium, type Re
15
15
  export { migrateBrushV1 } from './migrate.cjs';
16
16
  export { BRUSH_PRESETS } from './presets.cjs';
17
17
  export { brushColourHex } from './colour.cjs';
18
+ export { BRUSH_PREVIEW_DARK_PAPER, BRUSH_PREVIEW_FALLBACKS, BRUSH_PREVIEW_MIN_CONTRAST, brushPreviewColours, brushPreviewsOnDark, brushPreviewStrength, type BrushPreviewColours, type BrushPreviewColoursOptions } from './preview.cjs';
18
19
  export { BRUSH_CONTRACT_FORMAT_VERSION, BRUSH_LIBRARY_FILE_JSON_SCHEMA, BRUSH_PROFILE_JSON_SCHEMA, brushContracts } from './contract.cjs';
19
20
  export { BRUSH_HOST_PROFILES, brushColourKind, CANVAS_PROFILE, checkBrush, checkBrushEdit, degrade, withKeptIssues, IMAGE_PROFILE, listPresets, PAINT_PROFILE, VECTOR_PROFILE, type BrushCheck, type BrushEditCheck, type BrushColourKind, type BrushHostProfile, type BrushIssue, type BrushSupport, type DegradedBrush } from './profiles.cjs';
20
21
  export { BrushLibraryError, createBrushLibrary, isBrushLibrary, parseBrushLibrary, snapshotBrushLibrary, type BrushFilter, type BrushLibrary, type BrushLibraryEntry, type BrushLibraryErrorCode, type BrushLibraryFile, type BrushLibrarySnapshot, type BrushLibraryOptions, type ImportBrushesResult, type SaveBrushResult, } from './library.cjs';
@@ -15,6 +15,7 @@ export { resolveBrush, resolveCategory, resolveEngine, resolveWetMedium, type Re
15
15
  export { migrateBrushV1 } from './migrate.js';
16
16
  export { BRUSH_PRESETS } from './presets.js';
17
17
  export { brushColourHex } from './colour.js';
18
+ export { BRUSH_PREVIEW_DARK_PAPER, BRUSH_PREVIEW_FALLBACKS, BRUSH_PREVIEW_MIN_CONTRAST, brushPreviewColours, brushPreviewsOnDark, brushPreviewStrength, type BrushPreviewColours, type BrushPreviewColoursOptions } from './preview.js';
18
19
  export { BRUSH_CONTRACT_FORMAT_VERSION, BRUSH_LIBRARY_FILE_JSON_SCHEMA, BRUSH_PROFILE_JSON_SCHEMA, brushContracts } from './contract.js';
19
20
  export { BRUSH_HOST_PROFILES, brushColourKind, CANVAS_PROFILE, checkBrush, checkBrushEdit, degrade, withKeptIssues, IMAGE_PROFILE, listPresets, PAINT_PROFILE, VECTOR_PROFILE, type BrushCheck, type BrushEditCheck, type BrushColourKind, type BrushHostProfile, type BrushIssue, type BrushSupport, type DegradedBrush } from './profiles.js';
20
21
  export { BrushLibraryError, createBrushLibrary, isBrushLibrary, parseBrushLibrary, snapshotBrushLibrary, type BrushFilter, type BrushLibrary, type BrushLibraryEntry, type BrushLibraryErrorCode, type BrushLibraryFile, type BrushLibrarySnapshot, type BrushLibraryOptions, type ImportBrushesResult, type SaveBrushResult, } from './library.js';
@@ -8,8 +8,16 @@ import {
8
8
  createBrushLibraryToolProvider,
9
9
  createBrushLibraryTools,
10
10
  mergeBrushPatch
11
- } from "../chunk-4OJC4MCD.js";
11
+ } from "../chunk-Q6RVVJW6.js";
12
12
  import "../chunk-6JL2D5SG.js";
13
+ import {
14
+ BRUSH_PREVIEW_DARK_PAPER,
15
+ BRUSH_PREVIEW_FALLBACKS,
16
+ BRUSH_PREVIEW_MIN_CONTRAST,
17
+ brushPreviewColours,
18
+ brushPreviewStrength,
19
+ brushPreviewsOnDark
20
+ } from "../chunk-ZS7LB2MV.js";
13
21
  import {
14
22
  BRUSH_FACET_SCHEMAS,
15
23
  BRUSH_FIELDS,
@@ -61,14 +69,13 @@ import {
61
69
  setPath,
62
70
  snapshotBrushLibrary,
63
71
  withKeptIssues
64
- } from "../chunk-EE7SAYBF.js";
72
+ } from "../chunk-J4SGJCPW.js";
65
73
  import {
66
74
  STAMP_KINDS
67
75
  } from "../chunk-ACFSFUQH.js";
68
76
  import {
69
77
  brushColourHex
70
- } from "../chunk-FJBQTZS4.js";
71
- import "../chunk-3CI7FRMK.js";
78
+ } from "../chunk-DVPQFMH6.js";
72
79
  import "../chunk-SZTI6EER.js";
73
80
  import "../chunk-V2ZCJRDM.js";
74
81
  import {
@@ -481,6 +488,9 @@ export {
481
488
  BRUSH_MEDIA,
482
489
  BRUSH_PATCH_PROPERTIES,
483
490
  BRUSH_PRESETS,
491
+ BRUSH_PREVIEW_DARK_PAPER,
492
+ BRUSH_PREVIEW_FALLBACKS,
493
+ BRUSH_PREVIEW_MIN_CONTRAST,
484
494
  BRUSH_PROFILE_JSON_SCHEMA,
485
495
  BRUSH_SURFACES,
486
496
  BRUSH_TIP_SHAPES,
@@ -502,6 +512,9 @@ export {
502
512
  brushEditorSections,
503
513
  brushIdFromName,
504
514
  brushLibraryGroups,
515
+ brushPreviewColours,
516
+ brushPreviewStrength,
517
+ brushPreviewsOnDark,
505
518
  changedBrushPaths,
506
519
  checkBrush,
507
520
  checkBrushEdit,
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Preview colours for brushes: what a preview is drawn on and the colour that reads on it.
3
+ * `brushPreviewColours` picks the background (the renderer's paper, or dark paper for brushes
4
+ * that give off light) and a stroke colour with at least 3:1 contrast against it: the brush's
5
+ * default colour, resolved for that background (a light / dark pair takes its side), else a
6
+ * colour for the medium. Multiply brushes preview on white rather than a dark surface. Previews
7
+ * only: it never sets anyone's paint colour.
8
+ */
9
+ import { type ColorScheme, type DualColor } from '../color/dual.cjs';
10
+ import { type BrushHostProfile } from './profiles.cjs';
11
+ import type { Brush } from './types.cjs';
12
+ /** The paper behind brushes that give off light, so their glow reads. */
13
+ export declare const BRUSH_PREVIEW_DARK_PAPER = "#141414";
14
+ /** The contrast a preview colour keeps against its background (WCAG large-text / graphics). */
15
+ export declare const BRUSH_PREVIEW_MIN_CONTRAST = 3;
16
+ /** Preview colours for brushes with no solid default, by medium (`tools` for tool brushes). */
17
+ export declare const BRUSH_PREVIEW_FALLBACKS: Readonly<Record<string, DualColor>>;
18
+ /**
19
+ * Whether a brush that gives off `light` previews on dark paper: light paint glows on dark, but a
20
+ * multiply light brush (a highlighter) is a tint on paper and previews on light paper.
21
+ */
22
+ export declare function brushPreviewsOnDark(brush: {
23
+ light?: {
24
+ amount?: number;
25
+ };
26
+ tip?: {
27
+ blend?: string;
28
+ };
29
+ }): boolean;
30
+ export interface BrushPreviewColours {
31
+ /** The colour the preview is drawn on (#rrggbb): the renderer's paper, or dark paper for light paint. */
32
+ background: string;
33
+ /** The stroke colour (#rrggbb), at least `BRUSH_PREVIEW_MIN_CONTRAST` against `background`. */
34
+ color: string;
35
+ /** The background's scheme: which side of a light / dark colour was used. */
36
+ scheme: ColorScheme;
37
+ }
38
+ export interface BrushPreviewColoursOptions {
39
+ /**
40
+ * What the renderer draws on (#rrggbb, default white): the paper for the paint engine
41
+ * (`DEFAULT_PAPER.color`), or the surface behind a transparent preview (the canvas renderer's).
42
+ */
43
+ paper?: string;
44
+ /** The host (default the paint editor): only a host that renders light previews light brushes on dark paper. */
45
+ profile?: BrushHostProfile;
46
+ /** The preview can't change what is behind it (a swatch in a menu): `paper` is kept, even for multiply brushes. */
47
+ keepPaper?: boolean;
48
+ }
49
+ /**
50
+ * How much of its colour a brush lays in one pass, roughly: tip opacity, flow (soft brushes build
51
+ * up) and paper grain (dry media skip the paper's dips) all thin it.
52
+ */
53
+ export declare function brushPreviewStrength(brush: Brush): number;
54
+ /**
55
+ * The background and stroke colour for a preview of `brush` (see the module comment). A
56
+ * highlighter's own colour (a multiply brush that gives off light) is kept as it is: a tint reads
57
+ * by its colour, not its lightness.
58
+ */
59
+ export declare function brushPreviewColours(brush: Brush, options?: BrushPreviewColoursOptions): BrushPreviewColours;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Preview colours for brushes: what a preview is drawn on and the colour that reads on it.
3
+ * `brushPreviewColours` picks the background (the renderer's paper, or dark paper for brushes
4
+ * that give off light) and a stroke colour with at least 3:1 contrast against it: the brush's
5
+ * default colour, resolved for that background (a light / dark pair takes its side), else a
6
+ * colour for the medium. Multiply brushes preview on white rather than a dark surface. Previews
7
+ * only: it never sets anyone's paint colour.
8
+ */
9
+ import { type ColorScheme, type DualColor } from '../color/dual.js';
10
+ import { type BrushHostProfile } from './profiles.js';
11
+ import type { Brush } from './types.js';
12
+ /** The paper behind brushes that give off light, so their glow reads. */
13
+ export declare const BRUSH_PREVIEW_DARK_PAPER = "#141414";
14
+ /** The contrast a preview colour keeps against its background (WCAG large-text / graphics). */
15
+ export declare const BRUSH_PREVIEW_MIN_CONTRAST = 3;
16
+ /** Preview colours for brushes with no solid default, by medium (`tools` for tool brushes). */
17
+ export declare const BRUSH_PREVIEW_FALLBACKS: Readonly<Record<string, DualColor>>;
18
+ /**
19
+ * Whether a brush that gives off `light` previews on dark paper: light paint glows on dark, but a
20
+ * multiply light brush (a highlighter) is a tint on paper and previews on light paper.
21
+ */
22
+ export declare function brushPreviewsOnDark(brush: {
23
+ light?: {
24
+ amount?: number;
25
+ };
26
+ tip?: {
27
+ blend?: string;
28
+ };
29
+ }): boolean;
30
+ export interface BrushPreviewColours {
31
+ /** The colour the preview is drawn on (#rrggbb): the renderer's paper, or dark paper for light paint. */
32
+ background: string;
33
+ /** The stroke colour (#rrggbb), at least `BRUSH_PREVIEW_MIN_CONTRAST` against `background`. */
34
+ color: string;
35
+ /** The background's scheme: which side of a light / dark colour was used. */
36
+ scheme: ColorScheme;
37
+ }
38
+ export interface BrushPreviewColoursOptions {
39
+ /**
40
+ * What the renderer draws on (#rrggbb, default white): the paper for the paint engine
41
+ * (`DEFAULT_PAPER.color`), or the surface behind a transparent preview (the canvas renderer's).
42
+ */
43
+ paper?: string;
44
+ /** The host (default the paint editor): only a host that renders light previews light brushes on dark paper. */
45
+ profile?: BrushHostProfile;
46
+ /** The preview can't change what is behind it (a swatch in a menu): `paper` is kept, even for multiply brushes. */
47
+ keepPaper?: boolean;
48
+ }
49
+ /**
50
+ * How much of its colour a brush lays in one pass, roughly: tip opacity, flow (soft brushes build
51
+ * up) and paper grain (dry media skip the paper's dips) all thin it.
52
+ */
53
+ export declare function brushPreviewStrength(brush: Brush): number;
54
+ /**
55
+ * The background and stroke colour for a preview of `brush` (see the module comment). A
56
+ * highlighter's own colour (a multiply brush that gives off light) is kept as it is: a tint reads
57
+ * by its colour, not its lightness.
58
+ */
59
+ export declare function brushPreviewColours(brush: Brush, options?: BrushPreviewColoursOptions): BrushPreviewColours;
@@ -16,11 +16,18 @@ export interface BrushPreviewImage {
16
16
  mimeType: string;
17
17
  }
18
18
  /** Draws a sample stroke with a brush (the host's renderer: the paint engine, a canvas…). */
19
- export type BrushPreviewRenderer = (brush: Brush, options: {
20
- width: number;
21
- height: number;
22
- color: string;
23
- }) => BrushPreviewImage | Promise<BrushPreviewImage>;
19
+ export interface BrushPreviewRenderer {
20
+ (brush: Brush, options: {
21
+ width: number;
22
+ height: number;
23
+ color: string;
24
+ }): BrushPreviewImage | Promise<BrushPreviewImage>;
25
+ /**
26
+ * What it draws on (#rrggbb), for `brushPreviewColours`: the paint engine's paper. Unset for a
27
+ * transparent preview, which shows whatever the UI puts behind it.
28
+ */
29
+ readonly paper?: string;
30
+ }
24
31
  export interface BrushLibraryToolProviderOptions {
25
32
  /** What this host can render (default `PAINT_PROFILE`): lists are filtered by it and writes checked against it. */
26
33
  profile?: BrushHostProfile;
@@ -16,11 +16,18 @@ export interface BrushPreviewImage {
16
16
  mimeType: string;
17
17
  }
18
18
  /** Draws a sample stroke with a brush (the host's renderer: the paint engine, a canvas…). */
19
- export type BrushPreviewRenderer = (brush: Brush, options: {
20
- width: number;
21
- height: number;
22
- color: string;
23
- }) => BrushPreviewImage | Promise<BrushPreviewImage>;
19
+ export interface BrushPreviewRenderer {
20
+ (brush: Brush, options: {
21
+ width: number;
22
+ height: number;
23
+ color: string;
24
+ }): BrushPreviewImage | Promise<BrushPreviewImage>;
25
+ /**
26
+ * What it draws on (#rrggbb), for `brushPreviewColours`: the paint engine's paper. Unset for a
27
+ * transparent preview, which shows whatever the UI puts behind it.
28
+ */
29
+ readonly paper?: string;
30
+ }
24
31
  export interface BrushLibraryToolProviderOptions {
25
32
  /** What this host can render (default `PAINT_PROFILE`): lists are filtered by it and writes checked against it. */
26
33
  profile?: BrushHostProfile;
@@ -1,6 +1,9 @@
1
+ import {
2
+ brushPreviewColours
3
+ } from "./chunk-ZS7LB2MV.js";
1
4
  import {
2
5
  pathDataToPolyline
3
- } from "./chunk-JEML4FSA.js";
6
+ } from "./chunk-XDNWQMHY.js";
4
7
  import {
5
8
  BRUSH_PRESETS,
6
9
  BUILTIN_BRUSHES,
@@ -11,7 +14,7 @@ import {
11
14
  normalizeBrushSpec,
12
15
  resolveBrush,
13
16
  resolveCategory
14
- } from "./chunk-EE7SAYBF.js";
17
+ } from "./chunk-J4SGJCPW.js";
15
18
  import "./chunk-ACFSFUQH.js";
16
19
  import {
17
20
  formatNumber,
@@ -20,7 +23,7 @@ import {
20
23
  } from "./chunk-PWBZH3FK.js";
21
24
  import {
22
25
  parseCssColor
23
- } from "./chunk-3CI7FRMK.js";
26
+ } from "./chunk-DVPQFMH6.js";
24
27
  import "./chunk-SZTI6EER.js";
25
28
  import "./chunk-V2ZCJRDM.js";
26
29
  import {
@@ -160,6 +163,10 @@ function brushedShapeSvgNow(shape, size, scale, place = {}) {
160
163
  const content = svg.transform && body ? `<g transform="${svg.transform}">${body}</g>` : body;
161
164
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${f(size.width)}" height="${f(size.height)}" viewBox="0 0 ${f(size.width)} ${f(size.height)}">${content}</svg>`;
162
165
  }
166
+ function swatchColour(brush, background, spec) {
167
+ const facets = typeof brush !== "string" ? null : spec ? readCanvasBrushSpec(spec) : BRUSH_PRESETS.find((b) => b.id === brush);
168
+ return background && facets ? brushPreviewColours(facets, { paper: background, profile: CANVAS_PROFILE, keepPaper: true }).color : "#1f2937";
169
+ }
163
170
  function brushSwatchNow(brush, options, spec) {
164
171
  const w = options.width && options.width > 8 ? options.width : 96;
165
172
  const h = options.height && options.height > 4 ? options.height : 24;
@@ -170,7 +177,7 @@ function brushSwatchNow(brush, options, spec) {
170
177
  const pts = Array.from({ length: 9 }, (_, i) => [pad + (w - 2 * pad) * i / 8, h / 2 + Math.sin(i / 8 * Math.PI * 2) * (h / 2 - pad) * 0.6]);
171
178
  const d = pts.map(([x, y], i) => `${i ? "L" : "M"}${x.toFixed(2)} ${y.toFixed(2)}`).join(" ");
172
179
  const image = renderShapeBrushstrokeNow(
173
- { kind: "path", d, stroke: options.color ?? "#1f2937", strokeWidth: size, brush: { brush, ...spec ? { spec } : {}, seed: 7, size, pressure: [0.35, 1, 0.5] } },
180
+ { kind: "path", d, stroke: options.color ?? swatchColour(brush, options.background, spec), strokeWidth: size, brush: { brush, ...spec ? { spec } : {}, seed: 7, size, pressure: [0.35, 1, 0.5] } },
174
181
  options.scale && options.scale > 0 ? options.scale : 2
175
182
  );
176
183
  return image?.href ?? "";