@pixerate/editor 0.259.0 → 0.260.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 (74) hide show
  1. package/dist/agent/index.cjs +2 -2
  2. package/dist/agent/index.js +1 -1
  3. package/dist/animation-editor/index.cjs +61 -59
  4. package/dist/animation-editor/index.js +5 -3
  5. package/dist/brushes/index.cjs +52 -52
  6. package/dist/brushes/index.js +6 -6
  7. package/dist/{brushstrokeRender-JI4W6F2G.js → brushstrokeRender-25Q5BEY6.js} +17 -7
  8. package/dist/{brushstrokeRender-MQ6PSDM5.cjs → brushstrokeRender-N6UPZSQS.cjs} +31 -21
  9. package/dist/canvas/brushTypes.d.cts +5 -0
  10. package/dist/canvas/brushTypes.d.ts +5 -0
  11. package/dist/canvas/drawController.d.cts +15 -1
  12. package/dist/canvas/drawController.d.ts +15 -1
  13. package/dist/canvas/index.cjs +136 -102
  14. package/dist/canvas/index.js +35 -1
  15. package/dist/{chunk-3PPJRMIG.js → chunk-3O47TPGX.js} +197 -18
  16. package/dist/{chunk-5Q5MLXAD.cjs → chunk-3TQW5MPW.cjs} +23 -23
  17. package/dist/{chunk-JBBJE76O.cjs → chunk-3ZRNK3RO.cjs} +1138 -85
  18. package/dist/{chunk-YSGW7VV4.cjs → chunk-43NT242D.cjs} +1401 -228
  19. package/dist/{chunk-SMTUQWGY.js → chunk-5IW65VQ6.js} +1 -1
  20. package/dist/{chunk-YQ4PQTBB.js → chunk-6NZL24W4.js} +9 -1
  21. package/dist/{chunk-O3ZVZSNJ.cjs → chunk-7AUQ2UJ3.cjs} +137 -129
  22. package/dist/{chunk-4M4E3N6X.js → chunk-CQVTGBQI.js} +1 -1
  23. package/dist/{chunk-SSFMWJDK.js → chunk-D4TE5JNW.js} +1192 -19
  24. package/dist/{chunk-AORZ5M5C.js → chunk-EHALWBBD.js} +1 -1
  25. package/dist/{chunk-6WCQ35GI.cjs → chunk-NHA26O5X.cjs} +2 -2
  26. package/dist/{chunk-DPYAO5U6.cjs → chunk-PVJMTLPJ.cjs} +197 -18
  27. package/dist/{chunk-MQGQTKVW.cjs → chunk-PYTJBVW5.cjs} +29 -29
  28. package/dist/{chunk-IXQZHCOF.js → chunk-QAR2N7HZ.js} +1 -1
  29. package/dist/{chunk-5P4JEOIV.js → chunk-TMDDMJCR.js} +2 -2
  30. package/dist/{chunk-RSIKDWOP.cjs → chunk-TZOX7KWV.cjs} +15 -15
  31. package/dist/{chunk-IPUTIUGQ.cjs → chunk-UVZ7RQOE.cjs} +1 -1
  32. package/dist/{chunk-A7GJ6BXI.js → chunk-WJ4WQJCC.js} +1062 -9
  33. package/dist/{chunk-ICTPLVSR.js → chunk-X2EXYY4J.js} +1 -1
  34. package/dist/{chunk-WQCNC4DK.js → chunk-XC6DPRYI.js} +695 -4
  35. package/dist/{chunk-KBYB7OWB.cjs → chunk-YHDHFJUC.cjs} +776 -85
  36. package/dist/{chunk-P3PZ63M3.cjs → chunk-YLUIFXSL.cjs} +35 -35
  37. package/dist/commands/index.cjs +2 -2
  38. package/dist/commands/index.js +1 -1
  39. package/dist/image-editor/index.cjs +1385 -2484
  40. package/dist/image-editor/index.js +139 -1238
  41. package/dist/image-editor/selection-worker.cjs +3 -4
  42. package/dist/image-editor/selection-worker.js +1 -2
  43. package/dist/paint/index.cjs +3 -5
  44. package/dist/paint/index.js +40 -42
  45. package/dist/paint-editor/contract.d.cts +29 -0
  46. package/dist/paint-editor/contract.d.ts +29 -0
  47. package/dist/paint-editor/dab-stroke.d.cts +5 -0
  48. package/dist/paint-editor/dab-stroke.d.ts +5 -0
  49. package/dist/paint-editor/index.cjs +402 -258
  50. package/dist/paint-editor/index.d.cts +1 -0
  51. package/dist/paint-editor/index.d.ts +1 -0
  52. package/dist/paint-editor/index.js +197 -53
  53. package/dist/paint-editor/stamp-tip.d.cts +17 -0
  54. package/dist/paint-editor/stamp-tip.d.ts +17 -0
  55. package/dist/paint-editor/ui.d.cts +21 -1
  56. package/dist/paint-editor/ui.d.ts +21 -1
  57. package/dist/raster/index.cjs +2 -4
  58. package/dist/raster/index.js +6 -8
  59. package/dist/vector/brushstroke.d.cts +6 -0
  60. package/dist/vector/brushstroke.d.ts +6 -0
  61. package/dist/vector/controller.d.cts +11 -2
  62. package/dist/vector/controller.d.ts +11 -2
  63. package/dist/vector/index.cjs +990 -973
  64. package/dist/vector/index.js +28 -11
  65. package/package.json +1 -1
  66. package/skills/pixerate-brushes/SKILL.md +1 -1
  67. package/skills/pixerate-canvas/SKILL.md +3 -1
  68. package/skills/pixerate-vector/SKILL.md +2 -2
  69. package/dist/chunk-2VJAVXLI.js +0 -192
  70. package/dist/chunk-62Z5WLRA.js +0 -700
  71. package/dist/chunk-BOHDJJ2O.cjs +0 -192
  72. package/dist/chunk-NKGB64CW.cjs +0 -700
  73. package/dist/chunk-SS53NNZO.cjs +0 -1066
  74. package/dist/chunk-ZNA3IQZF.js +0 -1066
@@ -8,12 +8,10 @@
8
8
 
9
9
 
10
10
 
11
- var _chunkMQGQTKVWcjs = require('../chunk-MQGQTKVW.cjs');
11
+ var _chunkPYTJBVW5cjs = require('../chunk-PYTJBVW5.cjs');
12
12
  require('../chunk-AVTPZO4Z.cjs');
13
13
 
14
14
 
15
- var _chunkLRTR4ASZcjs = require('../chunk-LRTR4ASZ.cjs');
16
- require('../chunk-A2IS7EHE.cjs');
17
15
 
18
16
 
19
17
 
@@ -60,12 +58,14 @@ require('../chunk-A2IS7EHE.cjs');
60
58
 
61
59
 
62
60
 
61
+ var _chunkTZOX7KWVcjs = require('../chunk-TZOX7KWV.cjs');
63
62
 
64
63
 
65
- var _chunkRSIKDWOPcjs = require('../chunk-RSIKDWOP.cjs');
64
+ var _chunkJSDND7DFcjs = require('../chunk-JSDND7DF.cjs');
66
65
 
67
66
 
68
- var _chunkJSDND7DFcjs = require('../chunk-JSDND7DF.cjs');
67
+ var _chunkLRTR4ASZcjs = require('../chunk-LRTR4ASZ.cjs');
68
+ require('../chunk-A2IS7EHE.cjs');
69
69
  require('../chunk-U67EN7GG.cjs');
70
70
  require('../chunk-WOFXZ3XU.cjs');
71
71
 
@@ -112,20 +112,20 @@ var ARIA = {
112
112
  "light.pressure": "Light follows pressure"
113
113
  };
114
114
  var aria = (path, label) => _nullishCoalesce(ARIA[path], () => ( `Brush ${label.toLowerCase()}`));
115
- function brushEditorSections(brush, profile = _chunkRSIKDWOPcjs.PAINT_PROFILE) {
116
- const resolved = _chunkRSIKDWOPcjs.resolveBrush.call(void 0, brush);
117
- const engine = _chunkRSIKDWOPcjs.resolveEngine.call(void 0, brush);
118
- const fieldOf = (facet) => _chunkRSIKDWOPcjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
119
- const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunkRSIKDWOPcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunkRSIKDWOPcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
115
+ function brushEditorSections(brush, profile = _chunkTZOX7KWVcjs.PAINT_PROFILE) {
116
+ const resolved = _chunkTZOX7KWVcjs.resolveBrush.call(void 0, brush);
117
+ const engine = _chunkTZOX7KWVcjs.resolveEngine.call(void 0, brush);
118
+ const fieldOf = (facet) => _chunkTZOX7KWVcjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
119
+ const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunkTZOX7KWVcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunkTZOX7KWVcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
120
120
  const value = (path) => {
121
- const own = _chunkRSIKDWOPcjs.getPath.call(void 0, brush, path);
121
+ const own = _chunkTZOX7KWVcjs.getPath.call(void 0, brush, path);
122
122
  if (own !== void 0) return own;
123
123
  const field = fieldOf(path);
124
124
  if (!field) return void 0;
125
- const v = _chunkRSIKDWOPcjs.getPath.call(void 0, resolved, field.engine);
125
+ const v = _chunkTZOX7KWVcjs.getPath.call(void 0, resolved, field.engine);
126
126
  return field.map ? field.map.toFacet(v) : v;
127
127
  };
128
- const warned = new Map(_chunkRSIKDWOPcjs.checkBrush.call(void 0, brush, profile).issues.filter((i) => i.severity === "warning").map((i) => [i.facet, i.reason]));
128
+ const warned = new Map(_chunkTZOX7KWVcjs.checkBrush.call(void 0, brush, profile).issues.filter((i) => i.severity === "warning").map((i) => [i.facet, i.reason]));
129
129
  const noteFor = (path) => _optionalChain([[...warned], 'access', _2 => _2.find, 'call', _3 => _3(([facet]) => path === facet || path.startsWith(`${facet}.`)), 'optionalAccess', _4 => _4[1]]);
130
130
  const withNote = (c) => {
131
131
  const note = noteFor(c.path);
@@ -149,18 +149,18 @@ function brushEditorSections(brush, profile = _chunkRSIKDWOPcjs.PAINT_PROFILE) {
149
149
  const marks = _nullishCoalesce(_optionalChain([brush, 'access', _7 => _7.marks, 'optionalAccess', _8 => _8.kind]), () => ( "continuous"));
150
150
  add("medium", "Medium", [
151
151
  profile.kinds.length > 1 && choice("kind", "Kind", options(profile.kinds, { mark: "Lays a material", tool: "Works on paint" })),
152
- !isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunkRSIKDWOPcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
152
+ !isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunkTZOX7KWVcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
153
153
  !isTool && withNote({ kind: "text", path: "variety", label: "Variety", ariaLabel: "Brush variety", value: _nullishCoalesce(brush.variety, () => ( "")), placeholder: "pencil, oil, highlighter\u2026" }),
154
154
  isTool && profile.tools.length > 0 && choice("tool", "Tool", options(profile.tools, TOOL_LABELS))
155
155
  ]);
156
- const engineControls = _chunkMQGQTKVWcjs.brushEngineControls.call(void 0, resolved);
157
- const tipSliders = _chunkMQGQTKVWcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
156
+ const engineControls = _chunkPYTJBVW5cjs.brushEngineControls.call(void 0, resolved);
157
+ const tipSliders = _chunkPYTJBVW5cjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
158
158
  add("shape", "Shape", [
159
159
  choice("tip.shape", "Tip", options(profile.tipShapes.filter((s) => !isTool || s !== "stamp"), SHAPE_LABELS)),
160
160
  ...tipSliders.map((c) => slider(c)),
161
161
  engine === "dab" && choice("tip.blend", "Blend", _chunk2VX55NFMcjs.BLEND_MODES.map((m) => ({ value: m.id, label: m.label })), "normal"),
162
162
  ...shape === "bristle" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("bristle.")).map((c) => slider(c)) : [],
163
- shape === "stamp" && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunkRSIKDWOPcjs.MAX_DOT_TEXTURES : _chunkRSIKDWOPcjs.MAX_STICKER_STAMPS, options: STAMP_OPTIONS })
163
+ shape === "stamp" && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunkTZOX7KWVcjs.MAX_DOT_TEXTURES : _chunkTZOX7KWVcjs.MAX_STICKER_STAMPS, options: STAMP_OPTIONS })
164
164
  ]);
165
165
  if (!isTool && profile.marks.length > 1) {
166
166
  const particles = marks === "particles" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("particle.") && c.path !== "particle.waveSpeed") : [];
@@ -168,21 +168,21 @@ function brushEditorSections(brush, profile = _chunkRSIKDWOPcjs.PAINT_PROFILE) {
168
168
  const render = value("marks.render");
169
169
  add("marks", "Marks", [
170
170
  choice("marks.kind", "Laid as", options(profile.marks, MARKS_LABELS), "continuous"),
171
- marks === "particles" && choice("marks.physics", "Particles", options(_chunkRSIKDWOPcjs.PARTICLE_KINDS, PHYSICS_LABELS)),
172
- marks === "particles" && choice("marks.render", "Drawn as", options(_chunkRSIKDWOPcjs.PARTICLE_RENDERS, RENDER_LABELS)),
173
- marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunkRSIKDWOPcjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
174
- marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunkRSIKDWOPcjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
175
- marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunkRSIKDWOPcjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
171
+ marks === "particles" && choice("marks.physics", "Particles", options(_chunkTZOX7KWVcjs.PARTICLE_KINDS, PHYSICS_LABELS)),
172
+ marks === "particles" && choice("marks.render", "Drawn as", options(_chunkTZOX7KWVcjs.PARTICLE_RENDERS, RENDER_LABELS)),
173
+ marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunkTZOX7KWVcjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
174
+ marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunkTZOX7KWVcjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
175
+ marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunkTZOX7KWVcjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
176
176
  ...particles.map((c) => slider(c)),
177
177
  ...objects.map((c) => slider(c))
178
178
  ]);
179
179
  }
180
- const feel = _chunkMQGQTKVWcjs.BRUSH_SLIDERS.filter((c) => ["tip.smoothing", "pressureSmoothing", "dynamics.minSize", "dynamics.tiltSize", "dynamics.velocitySize"].includes(c.path)).filter((c) => !(c.path === "dynamics.tiltSize" && profile.tilt === "none") && !(c.path === "dynamics.velocitySize" && profile.velocity === "none"));
180
+ const feel = _chunkPYTJBVW5cjs.BRUSH_SLIDERS.filter((c) => ["tip.smoothing", "pressureSmoothing", "dynamics.minSize", "dynamics.tiltSize", "dynamics.velocitySize"].includes(c.path)).filter((c) => !(c.path === "dynamics.tiltSize" && profile.tilt === "none") && !(c.path === "dynamics.velocitySize" && profile.velocity === "none"));
181
181
  add("feel", "Feel", [
182
182
  ...feel.map((c) => slider(c)),
183
183
  toggle("dynamics.pressureSize", "Pressure \u2192 size"),
184
184
  toggle("dynamics.pressureOpacity", "Pressure \u2192 opacity"),
185
- choice("dynamics.rotation", "Rotation", options(_chunkRSIKDWOPcjs.BRUSH_ROTATIONS, ROTATION_LABELS))
185
+ choice("dynamics.rotation", "Rotation", options(_chunkTZOX7KWVcjs.BRUSH_ROTATIONS, ROTATION_LABELS))
186
186
  ]);
187
187
  const surfaces = profile.surfaces;
188
188
  const engineSliders = (_nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _9 => _9.sliders]), () => ( []))).filter((c) => !/^(bristle|particle|sticker)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
@@ -190,8 +190,8 @@ function brushEditorSections(brush, profile = _chunkRSIKDWOPcjs.PAINT_PROFILE) {
190
190
  add("behaviour", _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _12 => _12.title]), () => ( "Behaviour")), [
191
191
  !isTool && surfaces.length > 1 && choice("behaviour.surface", "Surface", options(surfaces, SURFACE_LABELS), "dry"),
192
192
  profile.grain !== "none" && slider({ path: "grain", label: "Grain", min: 0, max: 1, step: 0.01 }, "behaviour.grain"),
193
- engine === "wet" && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunkRSIKDWOPcjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
194
- engine === "impasto" && choice("behaviour.thick.applicator", "Tool", options(_chunkRSIKDWOPcjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
193
+ engine === "wet" && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunkTZOX7KWVcjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
194
+ engine === "impasto" && choice("behaviour.thick.applicator", "Tool", options(_chunkTZOX7KWVcjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
195
195
  ...engineSliders.map((c) => exchangeOk(facetOf(c.path)) ? slider(c) : null),
196
196
  _optionalChain([engineControls, 'optionalAccess', _13 => _13.mixingPath]) && fieldOf("behaviour.mixing") && choice("behaviour.mixing", "Mixing", options(["pigment", "rgb"], { pigment: "Pigment", rgb: "RGB" })),
197
197
  _optionalChain([engineControls, 'optionalAccess', _14 => _14.dirty]) && profile.exchange !== "none" && fieldOf("behaviour.exchange.dirty") && toggle("behaviour.exchange.dirty", "Dirty brush"),
@@ -219,7 +219,7 @@ function brushEditorSections(brush, profile = _chunkRSIKDWOPcjs.PAINT_PROFILE) {
219
219
  label: "Palette",
220
220
  ariaLabel: "Brush palette",
221
221
  value: (_nullishCoalesce(_optionalChain([brush, 'access', _21 => _21.colour, 'optionalAccess', _22 => _22.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)] : []),
222
- max: _chunkRSIKDWOPcjs.MAX_BRUSH_PALETTE
222
+ max: _chunkTZOX7KWVcjs.MAX_BRUSH_PALETTE
223
223
  }),
224
224
  toggle("colour.own", "Always its own colour")
225
225
  ]);
@@ -248,13 +248,13 @@ function setBrushEditorValue(brush, path, value) {
248
248
  if (value !== "bristle") delete next.tip.bristle;
249
249
  } else if (value === void 0 || value === "") {
250
250
  const keys = path.split(".");
251
- const parent = _chunkRSIKDWOPcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
251
+ const parent = _chunkTZOX7KWVcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
252
252
  if (keys.length === 1) delete next[keys[0]];
253
253
  else if (parent) delete parent[keys[keys.length - 1]];
254
- } else _chunkRSIKDWOPcjs.setPath.call(void 0, next, path, value);
254
+ } else _chunkTZOX7KWVcjs.setPath.call(void 0, next, path, value);
255
255
  const problems = [];
256
256
  try {
257
- return { brush: _chunkRSIKDWOPcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
257
+ return { brush: _chunkTZOX7KWVcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
258
258
  } catch (e) {
259
259
  return { brush, problems: [e.message] };
260
260
  }
@@ -270,7 +270,7 @@ function brushLibraryGroups(entries, filter = {}) {
270
270
  const text = words([b.id, b.name, _nullishCoalesce(b.variety, () => ( "")), _nullishCoalesce(b.medium, () => ( "")), _nullishCoalesce(b.tool, () => ( "")), ..._nullishCoalesce(b.tags, () => ( []))].join(" "));
271
271
  if (!wanted.every((w) => text.some((t) => t.startsWith(w)))) continue;
272
272
  }
273
- if (filter.profile && !_chunkRSIKDWOPcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
273
+ if (filter.profile && !_chunkTZOX7KWVcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
274
274
  const id = b.kind === "tool" ? "tools" : _nullishCoalesce(b.medium, () => ( "other"));
275
275
  let g = groups.get(id);
276
276
  if (!g) groups.set(id, g = { id, title: id === "tools" ? "Tools" : id === "other" ? "Other" : MEDIUM_LABELS[id], varieties: [] });
@@ -292,11 +292,11 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
292
292
  properties: {
293
293
  id: { type: "string", description: "paint, image, canvas, vector\u2026" },
294
294
  name: { type: "string", description: "Display name, used in messages." },
295
- kinds: { type: "array", items: { type: "string", enum: [..._chunkRSIKDWOPcjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
296
- tools: { type: "array", items: { type: "string", enum: [..._chunkRSIKDWOPcjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
297
- tipShapes: { type: "array", items: { type: "string", enum: [..._chunkRSIKDWOPcjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
298
- marks: { type: "array", items: { type: "string", enum: [..._chunkRSIKDWOPcjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
299
- surfaces: { type: "array", items: { type: "string", enum: [..._chunkRSIKDWOPcjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
295
+ kinds: { type: "array", items: { type: "string", enum: [..._chunkTZOX7KWVcjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
296
+ tools: { type: "array", items: { type: "string", enum: [..._chunkTZOX7KWVcjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
297
+ tipShapes: { type: "array", items: { type: "string", enum: [..._chunkTZOX7KWVcjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
298
+ marks: { type: "array", items: { type: "string", enum: [..._chunkTZOX7KWVcjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
299
+ surfaces: { type: "array", items: { type: "string", enum: [..._chunkTZOX7KWVcjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
300
300
  exchange: { ...SUPPORT, description: "Picking paint up and mixing it in." },
301
301
  reservoir: { ...SUPPORT, description: "The Mixer Brush reservoir." },
302
302
  grain: { ...SUPPORT, description: "Paper grain response." },
@@ -321,7 +321,7 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
321
321
  additionalProperties: false
322
322
  };
323
323
  function migrationInputs() {
324
- const pick = (id) => _chunkRSIKDWOPcjs.brushToJSON.call(void 0, _chunkRSIKDWOPcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
324
+ const pick = (id) => _chunkTZOX7KWVcjs.brushToJSON.call(void 0, _chunkTZOX7KWVcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
325
325
  return [
326
326
  { id: "plain", name: "Plain" },
327
327
  pick("pencil-6b"),
@@ -343,34 +343,34 @@ function migrationInputs() {
343
343
  function editorSectionFixtures() {
344
344
  const ids = ["highlighter", "chalk", "watercolor-wash", "hair-strands", "mixer-brush", "blender", "spray-can"];
345
345
  return ids.flatMap(
346
- (id) => Object.keys(_chunkRSIKDWOPcjs.BRUSH_HOST_PROFILES).map((host) => {
347
- const brush = _chunkRSIKDWOPcjs.BRUSH_PRESETS.find((b) => b.id === id);
348
- return { brush: id, host, sections: brushEditorSections(brush, _chunkRSIKDWOPcjs.BRUSH_HOST_PROFILES[host]) };
346
+ (id) => Object.keys(_chunkTZOX7KWVcjs.BRUSH_HOST_PROFILES).map((host) => {
347
+ const brush = _chunkTZOX7KWVcjs.BRUSH_PRESETS.find((b) => b.id === id);
348
+ return { brush: id, host, sections: brushEditorSections(brush, _chunkTZOX7KWVcjs.BRUSH_HOST_PROFILES[host]) };
349
349
  })
350
350
  );
351
351
  }
352
352
  function toolDefinitions() {
353
- const library = _chunkRSIKDWOPcjs.createBrushLibrary.call(void 0, );
354
- const toolsFor = (host) => _chunkMQGQTKVWcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunkRSIKDWOPcjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
353
+ const library = _chunkTZOX7KWVcjs.createBrushLibrary.call(void 0, );
354
+ const toolsFor = (host) => _chunkPYTJBVW5cjs.createBrushLibraryTools.call(void 0, library, { profile: _chunkTZOX7KWVcjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
355
355
  return {
356
356
  tools: toolsFor("paint").map((t) => ({ name: t.name, title: t.title, description: t.description, inputSchema: t.inputSchema, annotations: t.annotations })),
357
- hosts: Object.fromEntries(Object.keys(_chunkRSIKDWOPcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
357
+ hosts: Object.fromEntries(Object.keys(_chunkTZOX7KWVcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
358
358
  };
359
359
  }
360
360
  function brushContracts() {
361
- const presets = _chunkRSIKDWOPcjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
362
- const resolved = _chunkRSIKDWOPcjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunkRSIKDWOPcjs.resolveEngine.call(void 0, b), category: _chunkRSIKDWOPcjs.resolveCategory.call(void 0, b), brush: _chunkRSIKDWOPcjs.brushToJSON.call(void 0, _chunkRSIKDWOPcjs.resolveBrush.call(void 0, b)) }));
363
- const profiles = Object.values(_chunkRSIKDWOPcjs.BRUSH_HOST_PROFILES);
364
- const checks = _chunkRSIKDWOPcjs.BRUSH_PRESETS.map((b) => ({
361
+ const presets = _chunkTZOX7KWVcjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
362
+ const resolved = _chunkTZOX7KWVcjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunkTZOX7KWVcjs.resolveEngine.call(void 0, b), category: _chunkTZOX7KWVcjs.resolveCategory.call(void 0, b), brush: _chunkTZOX7KWVcjs.brushToJSON.call(void 0, _chunkTZOX7KWVcjs.resolveBrush.call(void 0, b)) }));
363
+ const profiles = Object.values(_chunkTZOX7KWVcjs.BRUSH_HOST_PROFILES);
364
+ const checks = _chunkTZOX7KWVcjs.BRUSH_PRESETS.map((b) => ({
365
365
  id: b.id,
366
366
  hosts: Object.fromEntries(profiles.map((p) => {
367
- const c = _chunkRSIKDWOPcjs.checkBrush.call(void 0, b, p);
367
+ const c = _chunkTZOX7KWVcjs.checkBrush.call(void 0, b, p);
368
368
  return [p.id, { ok: c.ok, issues: c.issues.map(({ facet, severity }) => ({ facet, severity })) }];
369
369
  }))
370
370
  }));
371
- const migrations = migrationInputs().map((input) => ({ input, output: _chunkRSIKDWOPcjs.migrateBrushV1.call(void 0, input), resolved: _chunkRSIKDWOPcjs.brushToJSON.call(void 0, _chunkRSIKDWOPcjs.resolveBrush.call(void 0, _chunkRSIKDWOPcjs.migrateBrushV1.call(void 0, input))), engine: _chunkRSIKDWOPcjs.normalizePaintBrush.call(void 0, input).engine }));
371
+ const migrations = migrationInputs().map((input) => ({ input, output: _chunkTZOX7KWVcjs.migrateBrushV1.call(void 0, input), resolved: _chunkTZOX7KWVcjs.brushToJSON.call(void 0, _chunkTZOX7KWVcjs.resolveBrush.call(void 0, _chunkTZOX7KWVcjs.migrateBrushV1.call(void 0, input))), engine: _chunkTZOX7KWVcjs.normalizePaintBrush.call(void 0, input).engine }));
372
372
  const files = {
373
- "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkRSIKDWOPcjs.BRUSH_JSON_SCHEMA },
373
+ "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkTZOX7KWVcjs.BRUSH_JSON_SCHEMA },
374
374
  "profile.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "profile.schema.json", ...BRUSH_PROFILE_JSON_SCHEMA },
375
375
  "library-file.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "library-file.schema.json", ...BRUSH_LIBRARY_FILE_JSON_SCHEMA },
376
376
  "presets.json": presets,
@@ -384,7 +384,7 @@ function brushContracts() {
384
384
  files["manifest.json"] = {
385
385
  domain: "brushes",
386
386
  formatVersion: BRUSH_CONTRACT_FORMAT_VERSION,
387
- limits: { maxPalette: _chunkRSIKDWOPcjs.MAX_BRUSH_PALETTE },
387
+ limits: { maxPalette: _chunkTZOX7KWVcjs.MAX_BRUSH_PALETTE },
388
388
  counts: { presets: presets.length, profiles: profiles.length, migrations: migrations.length, editorSections: files["editor-sections.json"].length },
389
389
  files: Object.keys(files).sort()
390
390
  };
@@ -437,4 +437,4 @@ function brushContracts() {
437
437
 
438
438
 
439
439
 
440
- exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunkRSIKDWOPcjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_HOST_PROFILES = _chunkRSIKDWOPcjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunkRSIKDWOPcjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunkRSIKDWOPcjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunkRSIKDWOPcjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunkRSIKDWOPcjs.BRUSH_MEDIA; exports.BRUSH_PATCH_PROPERTIES = _chunkMQGQTKVWcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunkRSIKDWOPcjs.BRUSH_PRESETS; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SURFACES = _chunkRSIKDWOPcjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunkRSIKDWOPcjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunkRSIKDWOPcjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunkMQGQTKVWcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunkRSIKDWOPcjs.BRUSH_WORD; exports.BrushLibraryError = _chunkRSIKDWOPcjs.BrushLibraryError; exports.CANVAS_PROFILE = _chunkRSIKDWOPcjs.CANVAS_PROFILE; exports.IMAGE_PROFILE = _chunkRSIKDWOPcjs.IMAGE_PROFILE; exports.MAX_BRUSH_PALETTE = _chunkRSIKDWOPcjs.MAX_BRUSH_PALETTE; exports.PAINT_PROFILE = _chunkRSIKDWOPcjs.PAINT_PROFILE; exports.UNSETTABLE_BRUSH_FACETS = _chunkMQGQTKVWcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunkRSIKDWOPcjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunkRSIKDWOPcjs.WET_BRUSH_TOOLS; exports.brushColourHex = _chunkLRTR4ASZcjs.brushColourHex; exports.brushColourKind = _chunkRSIKDWOPcjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorSections = brushEditorSections; exports.brushLibraryGroups = brushLibraryGroups; exports.changedBrushPaths = _chunkMQGQTKVWcjs.changedBrushPaths; exports.checkBrush = _chunkRSIKDWOPcjs.checkBrush; exports.createBrushLibrary = _chunkRSIKDWOPcjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunkMQGQTKVWcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunkMQGQTKVWcjs.createBrushLibraryTools; exports.degrade = _chunkRSIKDWOPcjs.degrade; exports.listPresets = _chunkRSIKDWOPcjs.listPresets; exports.mergeBrushPatch = _chunkMQGQTKVWcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunkRSIKDWOPcjs.migrateBrushV1; exports.normalizeBrushSpec = _chunkRSIKDWOPcjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunkRSIKDWOPcjs.parseBrushLibrary2; exports.resolveBrush = _chunkRSIKDWOPcjs.resolveBrush; exports.resolveCategory = _chunkRSIKDWOPcjs.resolveCategory; exports.resolveEngine = _chunkRSIKDWOPcjs.resolveEngine; exports.resolveWetMedium = _chunkRSIKDWOPcjs.resolveWetMedium; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunkRSIKDWOPcjs.snapshotBrushLibrary;
440
+ exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunkTZOX7KWVcjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_HOST_PROFILES = _chunkTZOX7KWVcjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunkTZOX7KWVcjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunkTZOX7KWVcjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunkTZOX7KWVcjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunkTZOX7KWVcjs.BRUSH_MEDIA; exports.BRUSH_PATCH_PROPERTIES = _chunkPYTJBVW5cjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunkTZOX7KWVcjs.BRUSH_PRESETS; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SURFACES = _chunkTZOX7KWVcjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunkTZOX7KWVcjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunkTZOX7KWVcjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunkPYTJBVW5cjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunkTZOX7KWVcjs.BRUSH_WORD; exports.BrushLibraryError = _chunkTZOX7KWVcjs.BrushLibraryError; exports.CANVAS_PROFILE = _chunkTZOX7KWVcjs.CANVAS_PROFILE; exports.IMAGE_PROFILE = _chunkTZOX7KWVcjs.IMAGE_PROFILE; exports.MAX_BRUSH_PALETTE = _chunkTZOX7KWVcjs.MAX_BRUSH_PALETTE; exports.PAINT_PROFILE = _chunkTZOX7KWVcjs.PAINT_PROFILE; exports.UNSETTABLE_BRUSH_FACETS = _chunkPYTJBVW5cjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunkTZOX7KWVcjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunkTZOX7KWVcjs.WET_BRUSH_TOOLS; exports.brushColourHex = _chunkLRTR4ASZcjs.brushColourHex; exports.brushColourKind = _chunkTZOX7KWVcjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorSections = brushEditorSections; exports.brushLibraryGroups = brushLibraryGroups; exports.changedBrushPaths = _chunkPYTJBVW5cjs.changedBrushPaths; exports.checkBrush = _chunkTZOX7KWVcjs.checkBrush; exports.createBrushLibrary = _chunkTZOX7KWVcjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunkPYTJBVW5cjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunkPYTJBVW5cjs.createBrushLibraryTools; exports.degrade = _chunkTZOX7KWVcjs.degrade; exports.listPresets = _chunkTZOX7KWVcjs.listPresets; exports.mergeBrushPatch = _chunkPYTJBVW5cjs.mergeBrushPatch; exports.migrateBrushV1 = _chunkTZOX7KWVcjs.migrateBrushV1; exports.normalizeBrushSpec = _chunkTZOX7KWVcjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunkTZOX7KWVcjs.parseBrushLibrary2; exports.resolveBrush = _chunkTZOX7KWVcjs.resolveBrush; exports.resolveCategory = _chunkTZOX7KWVcjs.resolveCategory; exports.resolveEngine = _chunkTZOX7KWVcjs.resolveEngine; exports.resolveWetMedium = _chunkTZOX7KWVcjs.resolveWetMedium; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunkTZOX7KWVcjs.snapshotBrushLibrary;
@@ -8,12 +8,8 @@ import {
8
8
  createBrushLibraryToolProvider,
9
9
  createBrushLibraryTools,
10
10
  mergeBrushPatch
11
- } from "../chunk-ICTPLVSR.js";
11
+ } from "../chunk-X2EXYY4J.js";
12
12
  import "../chunk-J5UQHWVL.js";
13
- import {
14
- brushColourHex
15
- } from "../chunk-FJBQTZS4.js";
16
- import "../chunk-3CI7FRMK.js";
17
13
  import {
18
14
  BRUSH_FACET_SCHEMAS,
19
15
  BRUSH_FIELDS,
@@ -62,10 +58,14 @@ import {
62
58
  resolveWetMedium,
63
59
  setPath,
64
60
  snapshotBrushLibrary
65
- } from "../chunk-SMTUQWGY.js";
61
+ } from "../chunk-5IW65VQ6.js";
66
62
  import {
67
63
  STAMP_KINDS
68
64
  } from "../chunk-APX63ILU.js";
65
+ import {
66
+ brushColourHex
67
+ } from "../chunk-FJBQTZS4.js";
68
+ import "../chunk-3CI7FRMK.js";
69
69
  import "../chunk-SZTI6EER.js";
70
70
  import "../chunk-V2ZCJRDM.js";
71
71
  import {
@@ -1,9 +1,6 @@
1
1
  import {
2
2
  pathDataToPolyline
3
- } from "./chunk-AORZ5M5C.js";
4
- import {
5
- parseCssColor
6
- } from "./chunk-3CI7FRMK.js";
3
+ } from "./chunk-EHALWBBD.js";
7
4
  import {
8
5
  BRUSH_PRESETS,
9
6
  BUILTIN_BRUSHES,
@@ -14,13 +11,16 @@ import {
14
11
  normalizeBrushSpec,
15
12
  resolveBrush,
16
13
  resolveCategory
17
- } from "./chunk-SMTUQWGY.js";
14
+ } from "./chunk-5IW65VQ6.js";
18
15
  import "./chunk-APX63ILU.js";
19
16
  import {
20
17
  formatNumber,
21
18
  getShapeSvg,
22
19
  resolveCanvasGradient
23
20
  } from "./chunk-PWBZH3FK.js";
21
+ import {
22
+ parseCssColor
23
+ } from "./chunk-3CI7FRMK.js";
24
24
  import "./chunk-SZTI6EER.js";
25
25
  import "./chunk-V2ZCJRDM.js";
26
26
  import {
@@ -37,6 +37,12 @@ import "./chunk-OTTT5N3K.js";
37
37
  import "./chunk-IRSTHLQQ.js";
38
38
  import "./chunk-HVVR5PZW.js";
39
39
  import "./chunk-QGHEDC7B.js";
40
+ import {
41
+ isDualColor
42
+ } from "./chunk-VR6OGHU5.js";
43
+ import "./chunk-JC2SHA4A.js";
44
+ import "./chunk-MHLU6GRJ.js";
45
+ import "./chunk-6ONMQ6WF.js";
40
46
 
41
47
  // src/canvas/brushstrokeRender.ts
42
48
  var PRESETS = listPresets(CANVAS_PROFILE).map((spec) => BUILTIN_BRUSHES.find((b) => b.id === spec.id));
@@ -53,12 +59,16 @@ function readCanvasBrushSpec(spec) {
53
59
  return brush;
54
60
  }
55
61
  function listCanvasBrushes(user = []) {
56
- const out = PRESETS.map((b) => ({ id: b.id, name: b.name, category: b.category, size: b.tip.size, builtin: true }));
62
+ const colourOf = (spec) => {
63
+ const d = spec.colour?.default;
64
+ return typeof d === "string" || isDualColor(d) ? { defaultColor: d } : {};
65
+ };
66
+ const out = PRESETS.map((b) => ({ id: b.id, name: b.name, category: b.category, size: b.tip.size, builtin: true, ...colourOf(BRUSH_PRESETS.find((p) => p.id === b.id)) }));
57
67
  for (const raw of user) {
58
68
  try {
59
69
  const brush = readCanvasBrushSpec(raw);
60
70
  if (out.some((b) => b.id === brush.id)) continue;
61
- out.push({ id: brush.id, name: brush.name, category: resolveCategory(brush), size: resolveBrush(brush).tip.size, builtin: false, spec: brush });
71
+ out.push({ id: brush.id, name: brush.name, category: resolveCategory(brush), size: resolveBrush(brush).tip.size, builtin: false, spec: brush, ...colourOf(brush) });
62
72
  } catch {
63
73
  }
64
74
  }
@@ -1,9 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkIPUTIUGQcjs = require('./chunk-IPUTIUGQ.cjs');
4
-
5
-
6
- var _chunkA2IS7EHEcjs = require('./chunk-A2IS7EHE.cjs');
3
+ var _chunkUVZ7RQOEcjs = require('./chunk-UVZ7RQOE.cjs');
7
4
 
8
5
 
9
6
 
@@ -14,13 +11,16 @@ var _chunkA2IS7EHEcjs = require('./chunk-A2IS7EHE.cjs');
14
11
 
15
12
 
16
13
 
17
- var _chunkRSIKDWOPcjs = require('./chunk-RSIKDWOP.cjs');
14
+ var _chunkTZOX7KWVcjs = require('./chunk-TZOX7KWV.cjs');
18
15
  require('./chunk-JSDND7DF.cjs');
19
16
 
20
17
 
21
18
 
22
19
 
23
20
  var _chunkNM3G4VQTcjs = require('./chunk-NM3G4VQT.cjs');
21
+
22
+
23
+ var _chunkA2IS7EHEcjs = require('./chunk-A2IS7EHE.cjs');
24
24
  require('./chunk-U67EN7GG.cjs');
25
25
  require('./chunk-WOFXZ3XU.cjs');
26
26
 
@@ -38,27 +38,37 @@ require('./chunk-2VX55NFM.cjs');
38
38
  require('./chunk-474IQG74.cjs');
39
39
  require('./chunk-XFM3OCHU.cjs');
40
40
 
41
+
42
+ var _chunkMLLTWAXHcjs = require('./chunk-MLLTWAXH.cjs');
43
+ require('./chunk-SXQHWXEL.cjs');
44
+ require('./chunk-5UEFBM2M.cjs');
45
+ require('./chunk-IPJ3TEYR.cjs');
46
+
41
47
  // src/canvas/brushstrokeRender.ts
42
- var PRESETS = _chunkRSIKDWOPcjs.listPresets.call(void 0, _chunkRSIKDWOPcjs.CANVAS_PROFILE).map((spec) => _chunkRSIKDWOPcjs.BUILTIN_BRUSHES.find((b) => b.id === spec.id));
48
+ var PRESETS = _chunkTZOX7KWVcjs.listPresets.call(void 0, _chunkTZOX7KWVcjs.CANVAS_PROFILE).map((spec) => _chunkTZOX7KWVcjs.BUILTIN_BRUSHES.find((b) => b.id === spec.id));
43
49
  var presetIds = () => PRESETS.map((b) => b.id).join(", ");
44
- var refusal = (brush) => _chunkRSIKDWOPcjs.checkBrush.call(void 0, brush, _chunkRSIKDWOPcjs.CANVAS_PROFILE).issues.filter((i) => i.severity === "error").map((i) => `${i.reason} ${i.fix}`).join(" ");
50
+ var refusal = (brush) => _chunkTZOX7KWVcjs.checkBrush.call(void 0, brush, _chunkTZOX7KWVcjs.CANVAS_PROFILE).issues.filter((i) => i.severity === "error").map((i) => `${i.reason} ${i.fix}`).join(" ");
45
51
  function readCanvasBrushSpec(spec) {
46
52
  let brush;
47
53
  try {
48
- brush = _chunkRSIKDWOPcjs.normalizeBrushSpec.call(void 0, spec);
54
+ brush = _chunkTZOX7KWVcjs.normalizeBrushSpec.call(void 0, spec);
49
55
  } catch (e) {
50
56
  throw new Error(`Not a brush: ${e.message}`);
51
57
  }
52
- if (!_chunkRSIKDWOPcjs.checkBrush.call(void 0, brush, _chunkRSIKDWOPcjs.CANVAS_PROFILE).ok) throw new Error(`Brush '${brush.id}' (${brush.name}) can't brush a canvas stroke: ${refusal(brush)}`);
58
+ if (!_chunkTZOX7KWVcjs.checkBrush.call(void 0, brush, _chunkTZOX7KWVcjs.CANVAS_PROFILE).ok) throw new Error(`Brush '${brush.id}' (${brush.name}) can't brush a canvas stroke: ${refusal(brush)}`);
53
59
  return brush;
54
60
  }
55
61
  function listCanvasBrushes(user = []) {
56
- const out = PRESETS.map((b) => ({ id: b.id, name: b.name, category: b.category, size: b.tip.size, builtin: true }));
62
+ const colourOf = (spec) => {
63
+ const d = _optionalChain([spec, 'access', _2 => _2.colour, 'optionalAccess', _3 => _3.default]);
64
+ return typeof d === "string" || _chunkMLLTWAXHcjs.isDualColor.call(void 0, d) ? { defaultColor: d } : {};
65
+ };
66
+ const out = PRESETS.map((b) => ({ id: b.id, name: b.name, category: b.category, size: b.tip.size, builtin: true, ...colourOf(_chunkTZOX7KWVcjs.BRUSH_PRESETS.find((p) => p.id === b.id)) }));
57
67
  for (const raw of user) {
58
68
  try {
59
69
  const brush = readCanvasBrushSpec(raw);
60
70
  if (out.some((b) => b.id === brush.id)) continue;
61
- out.push({ id: brush.id, name: brush.name, category: _chunkRSIKDWOPcjs.resolveCategory.call(void 0, brush), size: _chunkRSIKDWOPcjs.resolveBrush.call(void 0, brush).tip.size, builtin: false, spec: brush });
71
+ out.push({ id: brush.id, name: brush.name, category: _chunkTZOX7KWVcjs.resolveCategory.call(void 0, brush), size: _chunkTZOX7KWVcjs.resolveBrush.call(void 0, brush).tip.size, builtin: false, spec: brush, ...colourOf(brush) });
62
72
  } catch (e2) {
63
73
  }
64
74
  }
@@ -69,15 +79,15 @@ function resolveCanvasBrush(brush, width, spec) {
69
79
  const sized = (b) => given === void 0 ? b : { ...b, tip: { ...b.tip, size: given } };
70
80
  if (typeof brush === "string") {
71
81
  if (spec !== void 0 && spec !== null) {
72
- const saved = _chunkRSIKDWOPcjs.resolveBrush.call(void 0, readCanvasBrushSpec(spec));
82
+ const saved = _chunkTZOX7KWVcjs.resolveBrush.call(void 0, readCanvasBrushSpec(spec));
73
83
  if (!_chunkPXDIAYB6cjs.isBrushstrokeBrush.call(void 0, saved)) throw new Error(`Brush '${saved.id}' (${saved.name}) can't brush a canvas stroke: it is not a dry dab brush.`);
74
84
  return sized(saved);
75
85
  }
76
86
  const preset = PRESETS.find((b) => b.id === brush);
77
87
  if (preset) return sized(preset);
78
- const other = _chunkRSIKDWOPcjs.BRUSH_PRESETS.find((b) => b.id === brush);
88
+ const other = _chunkTZOX7KWVcjs.BRUSH_PRESETS.find((b) => b.id === brush);
79
89
  if (other) throw new Error(`Brush '${brush}' (${other.name}) can't brush a canvas stroke: ${refusal(other)} Use one of: ${presetIds()}, or a saved brush the canvas can paint.`);
80
- throw new Error(`Unknown brush '${brush}'. ${_chunkRSIKDWOPcjs.closest.call(void 0, brush, PRESETS.map((b) => b.id))}Use one of the dry presets (${presetIds()}), a saved brush from the brush library, or tip settings ({ hardness, spacing, flow, \u2026 }).`);
90
+ throw new Error(`Unknown brush '${brush}'. ${_chunkTZOX7KWVcjs.closest.call(void 0, brush, PRESETS.map((b) => b.id))}Use one of the dry presets (${presetIds()}), a saved brush from the brush library, or tip settings ({ hardness, spacing, flow, \u2026 }).`);
81
91
  }
82
92
  if (!brush || typeof brush !== "object" || Array.isArray(brush)) {
83
93
  throw new Error("A brush is a preset or saved brush id (see listCanvasBrushes / canvas.listBrushes) or an object of tip settings.");
@@ -101,7 +111,7 @@ function shapePaint(shape) {
101
111
  }
102
112
  function strokeColor(shape) {
103
113
  const gradient = _chunkNM3G4VQTcjs.resolveCanvasGradient.call(void 0, _nullishCoalesce(shape.strokeGradient, () => ( shape.stroke)));
104
- const css = gradient ? _nullishCoalesce(_optionalChain([gradient, 'access', _2 => _2.stops, 'access', _3 => _3[0], 'optionalAccess', _4 => _4.color]), () => ( "#000")) : typeof shape.stroke === "string" && shape.stroke !== "none" ? shape.stroke : "#000";
114
+ const css = gradient ? _nullishCoalesce(_optionalChain([gradient, 'access', _4 => _4.stops, 'access', _5 => _5[0], 'optionalAccess', _6 => _6.color]), () => ( "#000")) : typeof shape.stroke === "string" && shape.stroke !== "none" ? shape.stroke : "#000";
105
115
  const parsed = _nullishCoalesce(_chunkA2IS7EHEcjs.parseCssColor.call(void 0, css), () => ( { hex: "#000000", alpha: 1 }));
106
116
  const n = parseInt(parsed.hex.slice(1), 16);
107
117
  return [n >> 16 & 255, n >> 8 & 255, n & 255, Math.round(parsed.alpha * 255)];
@@ -113,14 +123,14 @@ function renderShapeBrushstrokeNow(shape, scale, place = {}) {
113
123
  const textured = typeof seed === "number" && Number.isFinite(seed);
114
124
  const size = _nullishCoalesce(shape.brush.size, () => ( (textured ? void 0 : _nullishCoalesce(shape.strokeWidth, () => ( 3)))));
115
125
  const brush = resolveCanvasBrush(shape.brush.brush, size, shape.brush.spec);
116
- const points = _chunkIPUTIUGQcjs.pathDataToPolyline.call(void 0, shape.d);
126
+ const points = _chunkUVZ7RQOEcjs.pathDataToPolyline.call(void 0, shape.d);
117
127
  if (!points.length) return null;
118
128
  const { pressure, tiltX, tiltY } = shape.brush;
119
129
  const input = {
120
130
  points: points.map(([x, y]) => ({ x, y })),
121
- ..._optionalChain([pressure, 'optionalAccess', _5 => _5.length]) ? { pressure } : {},
122
- ..._optionalChain([tiltX, 'optionalAccess', _6 => _6.length]) ? { tiltX } : {},
123
- ..._optionalChain([tiltY, 'optionalAccess', _7 => _7.length]) ? { tiltY } : {}
131
+ ..._optionalChain([pressure, 'optionalAccess', _7 => _7.length]) ? { pressure } : {},
132
+ ..._optionalChain([tiltX, 'optionalAccess', _8 => _8.length]) ? { tiltX } : {},
133
+ ..._optionalChain([tiltY, 'optionalAccess', _9 => _9.length]) ? { tiltY } : {}
124
134
  };
125
135
  const paint = shapePaint(shape);
126
136
  const character = textured ? {
@@ -128,7 +138,7 @@ function renderShapeBrushstrokeNow(shape, scale, place = {}) {
128
138
  seed,
129
139
  ...shape.brush.paper !== void 0 ? { paper: shape.brush.paper } : {},
130
140
  // Whole canvas units: the grain stays put, and tiny drags do not re-render.
131
- origin: { x: Math.round(_nullishCoalesce(_optionalChain([place, 'access', _8 => _8.origin, 'optionalAccess', _9 => _9.x]), () => ( 0))), y: Math.round(_nullishCoalesce(_optionalChain([place, 'access', _10 => _10.origin, 'optionalAccess', _11 => _11.y]), () => ( 0))) },
141
+ origin: { x: Math.round(_nullishCoalesce(_optionalChain([place, 'access', _10 => _10.origin, 'optionalAccess', _11 => _11.x]), () => ( 0))), y: Math.round(_nullishCoalesce(_optionalChain([place, 'access', _12 => _12.origin, 'optionalAccess', _13 => _13.y]), () => ( 0))) },
132
142
  unit: place.unit && place.unit > 0 ? Math.round(place.unit * 1e3) / 1e3 : 1
133
143
  }
134
144
  } : {};
@@ -163,7 +173,7 @@ function brushSwatchNow(brush, options, spec) {
163
173
  { kind: "path", d, stroke: _nullishCoalesce(options.color, () => ( "#1f2937")), strokeWidth: size, brush: { brush, ...spec ? { spec } : {}, seed: 7, size, pressure: [0.35, 1, 0.5] } },
164
174
  options.scale && options.scale > 0 ? options.scale : 2
165
175
  );
166
- return _nullishCoalesce(_optionalChain([image, 'optionalAccess', _12 => _12.href]), () => ( ""));
176
+ return _nullishCoalesce(_optionalChain([image, 'optionalAccess', _14 => _14.href]), () => ( ""));
167
177
  }
168
178
 
169
179
 
@@ -145,6 +145,11 @@ export interface CanvasBrushPreset {
145
145
  builtin?: boolean;
146
146
  /** A saved brush's facets: set `brushSpec` to it with `brush` when picking it. */
147
147
  spec?: CanvasBrushSpec;
148
+ /** The brush's solid default colour, or its light / dark pair: what picking it makes the stroke colour (`selectBrush`). */
149
+ defaultColor?: string | {
150
+ light: string;
151
+ dark: string;
152
+ };
148
153
  /** The preset's own tip diameter in canvas units: a new brushed stroke's default size. */
149
154
  size: number;
150
155
  }
@@ -145,6 +145,11 @@ export interface CanvasBrushPreset {
145
145
  builtin?: boolean;
146
146
  /** A saved brush's facets: set `brushSpec` to it with `brush` when picking it. */
147
147
  spec?: CanvasBrushSpec;
148
+ /** The brush's solid default colour, or its light / dark pair: what picking it makes the stroke colour (`selectBrush`). */
149
+ defaultColor?: string | {
150
+ light: string;
151
+ dark: string;
152
+ };
148
153
  /** The preset's own tip diameter in canvas units: a new brushed stroke's default size. */
149
154
  size: number;
150
155
  }
@@ -7,6 +7,7 @@ import type { CanvasNode, Point } from './types.cjs';
7
7
  import { type FreehandDrawOptions, type FreehandPenSample, type FreehandStroke, type FreehandStrokeStyle, type FreehandTool } from './freehand.cjs';
8
8
  import { type CanvasBrush } from './brushstroke.cjs';
9
9
  import type { BrushLibrary } from '../brushes/library.cjs';
10
+ import type { CanvasBrushPreset } from './brushTypes.cjs';
10
11
  /** A stroke drawn by code or an agent (`drawStroke`). */
11
12
  export interface DrawStrokeInput {
12
13
  /** Points in canvas (flow) coordinates, at least one. */
@@ -42,6 +43,8 @@ export interface CanvasDrawControllerOptions<TNode extends CanvasNode = CanvasNo
42
43
  * profile decides which). Share one with the paint editor so a brush saved there draws here.
43
44
  */
44
45
  brushLibrary?: Pick<BrushLibrary, 'list' | 'get' | 'isBuiltin'>;
46
+ /** The host's colour scheme (default light): a brush's light / dark default colour resolves to its side. */
47
+ colorScheme?: 'light' | 'dark';
45
48
  getNodes: () => TNode[];
46
49
  setNodes: (nodes: TNode[]) => void;
47
50
  history?: ArrangeHistoryTarget;
@@ -75,7 +78,18 @@ export declare function createCanvasDrawController<TNode extends CanvasNode = Ca
75
78
  height: number;
76
79
  } | undefined;
77
80
  /** The presets and saved brushes (of `brushLibrary`) a stroke can be brushed with (loads the paint engine). */
78
- listBrushes: () => Promise<import("./brushTypes.cjs").CanvasBrushPreset[]>;
81
+ listBrushes: () => Promise<CanvasBrushPreset[]>;
82
+ /**
83
+ * A brush picker's choice: brushes the pen and highlighter with `id` (`null`: a plain vector
84
+ * stroke) at the brush's own size, embedding a saved brush, and makes its default colour
85
+ * (resolved for the colour scheme) the stroke colour unless `keepColour`. Throws for a brush
86
+ * the canvas can't paint. Resolves with the brush chosen.
87
+ */
88
+ selectBrush(id: string | null, choice?: {
89
+ keepColour?: boolean;
90
+ }): Promise<CanvasBrushPreset | null>;
91
+ /** The host's colour scheme, for brushes' light / dark default colours. */
92
+ setColorScheme(scheme: "light" | "dark"): void;
79
93
  /** The saved brush to embed for a brush id (undefined for presets and tip settings); for a brush picker. */
80
94
  brushSpec: (brush: CanvasBrush) => Promise<import("./brushTypes.cjs").CanvasBrushSpec | undefined>;
81
95
  };
@@ -7,6 +7,7 @@ import type { CanvasNode, Point } from './types.js';
7
7
  import { type FreehandDrawOptions, type FreehandPenSample, type FreehandStroke, type FreehandStrokeStyle, type FreehandTool } from './freehand.js';
8
8
  import { type CanvasBrush } from './brushstroke.js';
9
9
  import type { BrushLibrary } from '../brushes/library.js';
10
+ import type { CanvasBrushPreset } from './brushTypes.js';
10
11
  /** A stroke drawn by code or an agent (`drawStroke`). */
11
12
  export interface DrawStrokeInput {
12
13
  /** Points in canvas (flow) coordinates, at least one. */
@@ -42,6 +43,8 @@ export interface CanvasDrawControllerOptions<TNode extends CanvasNode = CanvasNo
42
43
  * profile decides which). Share one with the paint editor so a brush saved there draws here.
43
44
  */
44
45
  brushLibrary?: Pick<BrushLibrary, 'list' | 'get' | 'isBuiltin'>;
46
+ /** The host's colour scheme (default light): a brush's light / dark default colour resolves to its side. */
47
+ colorScheme?: 'light' | 'dark';
45
48
  getNodes: () => TNode[];
46
49
  setNodes: (nodes: TNode[]) => void;
47
50
  history?: ArrangeHistoryTarget;
@@ -75,7 +78,18 @@ export declare function createCanvasDrawController<TNode extends CanvasNode = Ca
75
78
  height: number;
76
79
  } | undefined;
77
80
  /** The presets and saved brushes (of `brushLibrary`) a stroke can be brushed with (loads the paint engine). */
78
- listBrushes: () => Promise<import("./brushTypes.js").CanvasBrushPreset[]>;
81
+ listBrushes: () => Promise<CanvasBrushPreset[]>;
82
+ /**
83
+ * A brush picker's choice: brushes the pen and highlighter with `id` (`null`: a plain vector
84
+ * stroke) at the brush's own size, embedding a saved brush, and makes its default colour
85
+ * (resolved for the colour scheme) the stroke colour unless `keepColour`. Throws for a brush
86
+ * the canvas can't paint. Resolves with the brush chosen.
87
+ */
88
+ selectBrush(id: string | null, choice?: {
89
+ keepColour?: boolean;
90
+ }): Promise<CanvasBrushPreset | null>;
91
+ /** The host's colour scheme, for brushes' light / dark default colours. */
92
+ setColorScheme(scheme: "light" | "dark"): void;
79
93
  /** The saved brush to embed for a brush id (undefined for presets and tip settings); for a brush picker. */
80
94
  brushSpec: (brush: CanvasBrush) => Promise<import("./brushTypes.js").CanvasBrushSpec | undefined>;
81
95
  };