@pixerate/editor 0.274.0 → 0.275.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 (79) hide show
  1. package/dist/animation-editor/index.cjs +60 -60
  2. package/dist/animation-editor/index.js +4 -4
  3. package/dist/brushes/index.cjs +102 -74
  4. package/dist/brushes/index.js +34 -6
  5. package/dist/brushes/patch.d.cts +1 -1
  6. package/dist/brushes/patch.d.ts +1 -1
  7. package/dist/brushes/preview.d.cts +3 -0
  8. package/dist/brushes/preview.d.ts +3 -0
  9. package/dist/brushes/profiles.d.cts +2 -0
  10. package/dist/brushes/profiles.d.ts +2 -0
  11. package/dist/brushes/schema.d.cts +4 -0
  12. package/dist/brushes/schema.d.ts +4 -0
  13. package/dist/brushes/types.d.cts +47 -0
  14. package/dist/brushes/types.d.ts +47 -0
  15. package/dist/{brushstrokeRender-5YBCLFDQ.cjs → brushstrokeRender-2RQL46WB.cjs} +15 -15
  16. package/dist/{brushstrokeRender-DZGFU3J4.js → brushstrokeRender-WGY4DZHF.js} +3 -3
  17. package/dist/canvas/index.cjs +13 -13
  18. package/dist/canvas/index.js +1 -1
  19. package/dist/{chunk-2XDNF73E.js → chunk-43XJC3PP.js} +1 -1
  20. package/dist/{chunk-GHGBIAWQ.cjs → chunk-6QNDGMK7.cjs} +263 -45
  21. package/dist/{chunk-2F3YDXCN.js → chunk-75SYKUOT.js} +1 -1
  22. package/dist/{chunk-M3RZOF3G.cjs → chunk-C6VB7CPY.cjs} +1 -1
  23. package/dist/{chunk-N5IMDAHM.cjs → chunk-DHC4E2DU.cjs} +89 -37
  24. package/dist/{chunk-NAHJV3O6.js → chunk-G5TCMKX5.js} +28 -11
  25. package/dist/{chunk-DZVRH63Y.js → chunk-IEEY5RJV.js} +1 -1
  26. package/dist/{chunk-7W2EQQBP.cjs → chunk-JDXWLCXF.cjs} +6 -6
  27. package/dist/{chunk-N3SKPQEH.js → chunk-LMG57L5A.js} +62 -10
  28. package/dist/{chunk-5HP2VSAS.js → chunk-MSWLJI4G.js} +1 -1
  29. package/dist/{chunk-SNAFFCAX.cjs → chunk-OLZXXAER.cjs} +221 -196
  30. package/dist/{chunk-YJANF2BL.cjs → chunk-RAPNRK4R.cjs} +86 -86
  31. package/dist/{chunk-CLB2I2FU.js → chunk-RJGW3RQS.js} +2 -2
  32. package/dist/{chunk-FXVCB6YG.cjs → chunk-T6KNJVBP.cjs} +35 -35
  33. package/dist/{chunk-ZEI7ZEA4.js → chunk-Y2ISSVPH.js} +34 -9
  34. package/dist/{chunk-3JKCREEU.cjs → chunk-Y354ETAE.cjs} +76 -59
  35. package/dist/{chunk-TNLKFW7D.cjs → chunk-YYZC2EQO.cjs} +23 -23
  36. package/dist/{chunk-UXYCY3HP.js → chunk-ZM7IKQ4X.js} +239 -21
  37. package/dist/image-editor/index.cjs +789 -789
  38. package/dist/image-editor/index.js +5 -5
  39. package/dist/paint/index.cjs +2 -2
  40. package/dist/paint/index.js +1 -1
  41. package/dist/paint/wet/world.d.cts +15 -2
  42. package/dist/paint/wet/world.d.ts +15 -2
  43. package/dist/paint-editor/brush-controls.d.cts +7 -0
  44. package/dist/paint-editor/brush-controls.d.ts +7 -0
  45. package/dist/paint-editor/brush-model.d.cts +59 -1
  46. package/dist/paint-editor/brush-model.d.ts +59 -1
  47. package/dist/paint-editor/controller.d.cts +168 -1
  48. package/dist/paint-editor/controller.d.ts +168 -1
  49. package/dist/paint-editor/dab-stroke.d.cts +3 -0
  50. package/dist/paint-editor/dab-stroke.d.ts +3 -0
  51. package/dist/paint-editor/document.d.cts +13 -3
  52. package/dist/paint-editor/document.d.ts +13 -3
  53. package/dist/paint-editor/engine.d.cts +3 -0
  54. package/dist/paint-editor/engine.d.ts +3 -0
  55. package/dist/paint-editor/heat.d.cts +156 -0
  56. package/dist/paint-editor/heat.d.ts +156 -0
  57. package/dist/paint-editor/index.cjs +3386 -855
  58. package/dist/paint-editor/index.d.cts +3 -0
  59. package/dist/paint-editor/index.d.ts +3 -0
  60. package/dist/paint-editor/index.js +2731 -200
  61. package/dist/paint-editor/mutation-tools.d.cts +13 -0
  62. package/dist/paint-editor/mutation-tools.d.ts +13 -0
  63. package/dist/paint-editor/mutation.d.cts +67 -0
  64. package/dist/paint-editor/mutation.d.ts +67 -0
  65. package/dist/paint-editor/presence.d.cts +7 -1
  66. package/dist/paint-editor/presence.d.ts +7 -1
  67. package/dist/paint-editor/procedural.d.cts +3 -0
  68. package/dist/paint-editor/procedural.d.ts +3 -0
  69. package/dist/paint-editor/stroke.d.cts +32 -2
  70. package/dist/paint-editor/stroke.d.ts +32 -2
  71. package/dist/paint-editor/thick.d.cts +48 -7
  72. package/dist/paint-editor/thick.d.ts +48 -7
  73. package/dist/paint-editor/ui.d.cts +34 -1
  74. package/dist/paint-editor/ui.d.ts +34 -1
  75. package/dist/paint-editor/wet.d.cts +8 -1
  76. package/dist/paint-editor/wet.d.ts +8 -1
  77. package/dist/vector/index.cjs +999 -999
  78. package/dist/vector/index.js +5 -5
  79. package/package.json +1 -1
@@ -18,7 +18,7 @@
18
18
 
19
19
 
20
20
 
21
- var _chunk3JKCREEUcjs = require('../chunk-3JKCREEU.cjs');
21
+ var _chunkY354ETAEcjs = require('../chunk-Y354ETAE.cjs');
22
22
  require('../chunk-PFHJS4HE.cjs');
23
23
 
24
24
 
@@ -27,7 +27,7 @@ require('../chunk-PFHJS4HE.cjs');
27
27
 
28
28
 
29
29
 
30
- var _chunk7W2EQQBPcjs = require('../chunk-7W2EQQBP.cjs');
30
+ var _chunkJDXWLCXFcjs = require('../chunk-JDXWLCXF.cjs');
31
31
 
32
32
 
33
33
 
@@ -101,7 +101,8 @@ var _chunk7W2EQQBPcjs = require('../chunk-7W2EQQBP.cjs');
101
101
 
102
102
 
103
103
 
104
- var _chunkGHGBIAWQcjs = require('../chunk-GHGBIAWQ.cjs');
104
+
105
+ var _chunk6QNDGMK7cjs = require('../chunk-6QNDGMK7.cjs');
105
106
 
106
107
 
107
108
  var _chunkRDFHWAHLcjs = require('../chunk-RDFHWAHL.cjs');
@@ -164,20 +165,20 @@ var ARIA = {
164
165
  "dynamics.angleJitter": "Brush rotation jitter"
165
166
  };
166
167
  var aria = (path, label) => _nullishCoalesce(ARIA[path], () => ( `Brush ${label.toLowerCase()}`));
167
- function brushEditorSections(brush, profile = _chunkGHGBIAWQcjs.PAINT_PROFILE, context = {}) {
168
- const resolved = _chunkGHGBIAWQcjs.resolveBrush.call(void 0, brush);
169
- const engine = _chunkGHGBIAWQcjs.resolveEngine.call(void 0, brush);
170
- const fieldOf = (facet) => _chunkGHGBIAWQcjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
171
- const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunkGHGBIAWQcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunkGHGBIAWQcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
168
+ function brushEditorSections(brush, profile = _chunk6QNDGMK7cjs.PAINT_PROFILE, context = {}) {
169
+ const resolved = _chunk6QNDGMK7cjs.resolveBrush.call(void 0, brush);
170
+ const engine = _chunk6QNDGMK7cjs.resolveEngine.call(void 0, brush);
171
+ const fieldOf = (facet) => _chunk6QNDGMK7cjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
172
+ const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunk6QNDGMK7cjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunk6QNDGMK7cjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
172
173
  const value = (path) => {
173
- const own = _chunkGHGBIAWQcjs.getPath.call(void 0, brush, path);
174
+ const own = _chunk6QNDGMK7cjs.getPath.call(void 0, brush, path);
174
175
  if (own !== void 0) return own;
175
176
  const field = fieldOf(path);
176
177
  if (!field) return void 0;
177
- const v = _chunkGHGBIAWQcjs.getPath.call(void 0, resolved, field.engine);
178
+ const v = _chunk6QNDGMK7cjs.getPath.call(void 0, resolved, field.engine);
178
179
  return field.map ? field.map.toFacet(v) : v;
179
180
  };
180
- const issues = _chunkGHGBIAWQcjs.checkBrush.call(void 0, brush, profile).issues;
181
+ const issues = _chunk6QNDGMK7cjs.checkBrush.call(void 0, brush, profile).issues;
181
182
  const warned = new Map(issues.filter((i) => i.severity === "warning").map((i) => [i.facet, i.reason]));
182
183
  const refused = new Set(issues.filter((i) => i.severity === "error").map((i) => i.facet));
183
184
  const full = (s) => s === "full";
@@ -202,30 +203,30 @@ function brushEditorSections(brush, profile = _chunkGHGBIAWQcjs.PAINT_PROFILE, c
202
203
  };
203
204
  const isTool = brush.kind === "tool";
204
205
  const shape = brush.tip.shape;
205
- const sourceOptions = (_nullishCoalesce(context.sources, () => ( []))).map((x) => ({ value: _chunkGHGBIAWQcjs.brushSourceRef.call(void 0, x.id), label: x.name }));
206
+ const sourceOptions = (_nullishCoalesce(context.sources, () => ( []))).map((x) => ({ value: _chunk6QNDGMK7cjs.brushSourceRef.call(void 0, x.id), label: x.name }));
206
207
  const marks = _nullishCoalesce(_optionalChain([brush, 'access', _7 => _7.marks, 'optionalAccess', _8 => _8.kind]), () => ( "continuous"));
207
208
  const exchangeFull = full(_optionalChain([brush, 'access', _9 => _9.behaviour, 'optionalAccess', _10 => _10.exchange, 'optionalAccess', _11 => _11.reservoir]) ? profile.reservoir : profile.exchange);
208
209
  add("medium", "Medium", [
209
210
  profile.kinds.length > 1 && profile.kinds.includes(brush.kind) && choice("kind", "Kind", options(profile.kinds, { mark: "Lays a material", tool: "Works on paint" })),
210
- !isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunkGHGBIAWQcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
211
+ !isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunk6QNDGMK7cjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
211
212
  !isTool && withNote({ kind: "text", path: "variety", label: "Variety", ariaLabel: "Brush variety", value: _nullishCoalesce(brush.variety, () => ( "")), placeholder: "pencil, oil, highlighter\u2026" }),
212
213
  isTool && !!brush.tool && profile.tools.includes(brush.tool) && choice("tool", "Tool", options(profile.tools, TOOL_LABELS))
213
214
  ]);
214
- const engineControls = _chunk3JKCREEUcjs.brushEngineControls.call(void 0, resolved);
215
- const tipSliders = _chunk3JKCREEUcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
215
+ const engineControls = _chunkY354ETAEcjs.brushEngineControls.call(void 0, resolved);
216
+ const tipSliders = _chunkY354ETAEcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
216
217
  add("shape", "Shape", [
217
218
  !refused.has("tip.shape") && choice("tip.shape", "Tip", options(profile.tipShapes.filter((s) => !isTool || s !== "stamp"), SHAPE_LABELS)),
218
219
  ...tipSliders.map((c) => slider(c)),
219
220
  engine === "dab" && choice("tip.blend", "Blend", _chunk2VX55NFMcjs.BLEND_MODES.map((m) => ({ value: m.id, label: m.label })), "normal"),
220
221
  ...shape === "bristle" && engineOk && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("bristle.")).map((c) => slider(c)) : [],
221
- shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunkGHGBIAWQcjs.MAX_DOT_TEXTURES : _chunkGHGBIAWQcjs.MAX_STICKER_STAMPS, options: marks === "objects" ? STAMP_OPTIONS : [...STAMP_OPTIONS, ...sourceOptions] })
222
+ shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunk6QNDGMK7cjs.MAX_DOT_TEXTURES : _chunk6QNDGMK7cjs.MAX_STICKER_STAMPS, options: marks === "objects" ? STAMP_OPTIONS : [...STAMP_OPTIONS, ...sourceOptions] })
222
223
  ]);
223
224
  const dabs = DAB_ENGINES.has(engine) && engineOk && shape !== "bristle" && marks !== "particles" && marks !== "objects";
224
225
  const grain = brush.tip.grain;
225
226
  if (dabs && full(_nullishCoalesce(profile.tipGrain, () => ( "none")))) {
226
227
  add("grain", "Tip grain", [
227
- choice("tip.grain.source", "Texture", [{ value: "", label: "None" }, ...options(_chunkGHGBIAWQcjs.TIP_GRAIN_PATTERNS), ...sourceOptions], ""),
228
- !!grain && choice("tip.grain.mode", "Grain moves", options(_chunkGHGBIAWQcjs.BRUSH_GRAIN_MODES, GRAIN_MODE_LABELS), "texturised"),
228
+ choice("tip.grain.source", "Texture", [{ value: "", label: "None" }, ...options(_chunk6QNDGMK7cjs.TIP_GRAIN_PATTERNS), ...sourceOptions], ""),
229
+ !!grain && choice("tip.grain.mode", "Grain moves", options(_chunk6QNDGMK7cjs.BRUSH_GRAIN_MODES, GRAIN_MODE_LABELS), "texturised"),
229
230
  !!grain && withNote({ kind: "slider", path: "tip.grain.scale", label: "Grain scale", ariaLabel: "Brush grain scale", min: 0.1, max: 8, step: 0.05, value: _nullishCoalesce(grain.scale, () => ( 1)) }),
230
231
  !!grain && withNote({ kind: "slider", path: "tip.grain.depth", label: "Grain depth", ariaLabel: "Brush grain depth", min: 0, max: 1, step: 0.01, value: _nullishCoalesce(grain.depth, () => ( 0.6)) }),
231
232
  !!grain && withNote({ kind: "slider", path: "tip.grain.contrast", label: "Grain contrast", ariaLabel: "Brush grain contrast", min: 0, max: 3, step: 0.05, value: _nullishCoalesce(grain.contrast, () => ( 1)) }),
@@ -238,37 +239,37 @@ function brushEditorSections(brush, profile = _chunkGHGBIAWQcjs.PAINT_PROFILE, c
238
239
  const render = value("marks.render");
239
240
  add("marks", "Marks", [
240
241
  choice("marks.kind", "Laid as", options(profile.marks, MARKS_LABELS), "continuous"),
241
- marks === "particles" && choice("marks.physics", "Particles", options(_chunkGHGBIAWQcjs.PARTICLE_KINDS, PHYSICS_LABELS)),
242
- marks === "particles" && choice("marks.render", "Drawn as", options(_chunkGHGBIAWQcjs.PARTICLE_RENDERS, RENDER_LABELS)),
243
- marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunkGHGBIAWQcjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
244
- marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunkGHGBIAWQcjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
245
- marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunkGHGBIAWQcjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
242
+ marks === "particles" && choice("marks.physics", "Particles", options(_chunk6QNDGMK7cjs.PARTICLE_KINDS, PHYSICS_LABELS)),
243
+ marks === "particles" && choice("marks.render", "Drawn as", options(_chunk6QNDGMK7cjs.PARTICLE_RENDERS, RENDER_LABELS)),
244
+ marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunk6QNDGMK7cjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
245
+ marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunk6QNDGMK7cjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
246
+ marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunk6QNDGMK7cjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
246
247
  ...particles.map((c) => slider(c)),
247
248
  ...objects.map((c) => slider(c))
248
249
  ]);
249
250
  }
250
- const feel = _chunk3JKCREEUcjs.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)));
251
+ const feel = _chunkY354ETAEcjs.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)));
251
252
  const stampDabs = dabs && shape === "stamp";
252
253
  const jitter = (path, label, max = 1, step = 0.01) => withNote({ kind: "slider", path, label, ariaLabel: aria(path, label), min: 0, max, step, value: Number(_nullishCoalesce(value(path), () => ( 0))) });
253
254
  add("feel", "Feel", [
254
255
  ...feel.map((c) => slider(c)),
255
256
  toggle("dynamics.pressureSize", "Pressure \u2192 size"),
256
257
  toggle("dynamics.pressureOpacity", "Pressure \u2192 opacity"),
257
- choice("dynamics.rotation", "Rotation", options(_chunkGHGBIAWQcjs.BRUSH_ROTATIONS, ROTATION_LABELS)),
258
+ choice("dynamics.rotation", "Rotation", options(_chunk6QNDGMK7cjs.BRUSH_ROTATIONS, ROTATION_LABELS)),
258
259
  stampDabs && full(_nullishCoalesce(profile.dabCount, () => ( "none"))) && withNote({ kind: "slider", path: "dynamics.count", label: "Count", ariaLabel: "Brush dab count", min: 1, max: 16, step: 1, value: _nullishCoalesce(_optionalChain([brush, 'access', _12 => _12.dynamics, 'optionalAccess', _13 => _13.count]), () => ( 1)) }),
259
260
  stampDabs && jitter("dynamics.scatter", "Scatter", 4),
260
261
  stampDabs && jitter("dynamics.angleJitter", "Rotation jitter"),
261
262
  stampDabs && jitter("dynamics.sizeJitter", "Size jitter"),
262
- stampDabs && choice("dynamics.flip", "Flip", options(_chunkGHGBIAWQcjs.BRUSH_FLIPS, FLIP_LABELS), "none")
263
+ stampDabs && choice("dynamics.flip", "Flip", options(_chunk6QNDGMK7cjs.BRUSH_FLIPS, FLIP_LABELS), "none")
263
264
  ]);
264
265
  const surfaces = profile.surfaces;
265
- const engineSliders = (engineOk ? _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _14 => _14.sliders]), () => ( [])) : []).filter((c) => !/^(bristle|particle|sticker)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
266
+ const engineSliders = (engineOk ? _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _14 => _14.sliders]), () => ( [])) : []).filter((c) => !/^(bristle|particle|sticker|iridescence)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
266
267
  const exchangeOk = (path) => !_optionalChain([path, 'optionalAccess', _15 => _15.startsWith, 'call', _16 => _16("behaviour.exchange")]) || (path.startsWith("behaviour.exchange.reservoir") ? full(profile.reservoir) : exchangeFull);
267
268
  add("behaviour", _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _17 => _17.title]), () => ( "Behaviour")), [
268
269
  !isTool && surfaces.length > 1 && !refused.has("behaviour.surface") && choice("behaviour.surface", "Surface", options(surfaces, SURFACE_LABELS), "dry"),
269
270
  full(profile.grain) && slider({ path: "grain", label: "Grain", min: 0, max: 1, step: 0.01 }, "behaviour.grain"),
270
- engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunkGHGBIAWQcjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
271
- engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(_chunkGHGBIAWQcjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
271
+ engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunk6QNDGMK7cjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
272
+ engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(_chunk6QNDGMK7cjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
272
273
  ...engineSliders.map((c) => exchangeOk(facetOf(c.path)) ? slider(c) : null),
273
274
  engineOk && _optionalChain([engineControls, 'optionalAccess', _18 => _18.mixingPath]) && (engine === "wet" || exchangeFull) && fieldOf("behaviour.mixing") && choice("behaviour.mixing", "Mixing", options(["pigment", "rgb"], { pigment: "Pigment", rgb: "RGB" })),
274
275
  engineOk && _optionalChain([engineControls, 'optionalAccess', _19 => _19.dirty]) && exchangeFull && fieldOf("behaviour.exchange.dirty") && toggle("behaviour.exchange.dirty", "Dirty brush"),
@@ -280,12 +281,22 @@ function brushEditorSections(brush, profile = _chunkGHGBIAWQcjs.PAINT_PROFILE, c
280
281
  toggle("light.pressure", "Light follows pressure"),
281
282
  ...engine === "impasto" ? [slider({ path: "impasto.rim", label: "Rim", min: 0, max: 1, step: 0.01 }), slider({ path: "impasto.clarity", label: "Clarity", min: 0, max: 1, step: 0.01 })] : [],
282
283
  withNote({ kind: "slider", path: "light.spill.radius", label: "Spill", ariaLabel: "Brush light spill", min: 0, max: 128, step: 1, value: _nullishCoalesce(_optionalChain([brush, 'access', _21 => _21.light, 'optionalAccess', _22 => _22.spill, 'optionalAccess', _23 => _23.radius]), () => ( 24)) }),
283
- toggle("light.glow", "Suggest a glow")
284
+ toggle("light.glow", "Suggest a glow"),
285
+ withNote({ kind: "slider", path: "fluorescence.amount", label: "UV fluorescence", ariaLabel: "Brush fluorescence amount", min: 0, max: 1, step: 0.01, value: _nullishCoalesce(_optionalChain([brush, 'access', _24 => _24.fluorescence, 'optionalAccess', _25 => _25.amount]), () => ( 0)) }),
286
+ toggle("fluorescence.invisible", "Invisible in daylight"),
287
+ withNote({ kind: "colour", path: "thermochromic.hotColor", label: "Hot colour", ariaLabel: "Brush thermochromic hot colour", value: _nullishCoalesce(_optionalChain([brush, 'access', _26 => _26.thermochromic, 'optionalAccess', _27 => _27.hotColor]), () => ( null)), dark: null, gradient: false }),
288
+ withNote({ kind: "slider", path: "thermochromic.threshold", label: "Heat threshold", ariaLabel: "Brush thermochromic threshold", min: 0.05, max: 0.95, step: 0.01, value: _nullishCoalesce(_optionalChain([brush, 'access', _28 => _28.thermochromic, 'optionalAccess', _29 => _29.threshold]), () => ( 0.5)) }),
289
+ full(_nullishCoalesce(profile.iridescence, () => ( "none"))) && marks !== "objects" && withNote({ kind: "toggle", path: "iridescence", label: "Thin-film iridescence", ariaLabel: "Brush thin-film iridescence", value: Boolean(brush.iridescence) }),
290
+ ...brush.iridescence && full(_nullishCoalesce(profile.iridescence, () => ( "none"))) ? [
291
+ slider({ path: "iridescence.thickness", label: "Film (nm)", min: 100, max: 1e3, step: 5 }),
292
+ slider({ path: "iridescence.pressureToThickness", label: "Pressure \u2192 film", min: 0, max: 1, step: 0.01 }),
293
+ slider({ path: "iridescence.ior", label: "Film IOR", min: 1.2, max: 2, step: 0.01 })
294
+ ] : []
284
295
  ]);
285
296
  }
286
297
  if (full(profile.motion) && engineOk && marks === "particles") add("motion", "Motion", [slider({ path: "particle.waveSpeed", label: "Wave speed", min: 0, max: 1, step: 0.01 })]);
287
298
  if (!isTool) {
288
- const own = _optionalChain([brush, 'access', _24 => _24.colour, 'optionalAccess', _25 => _25.default]);
299
+ const own = _optionalChain([brush, 'access', _30 => _30.colour, 'optionalAccess', _31 => _31.default]);
289
300
  const hex = (c) => typeof c === "string" ? _nullishCoalesce(_chunkJBZRVLXVcjs.brushColourHex.call(void 0, c, "light"), () => ( null)) : null;
290
301
  const pair = _chunkMLLTWAXHcjs.isDualColor.call(void 0, own) ? own : null;
291
302
  add("colour", "Colour", [
@@ -295,8 +306,8 @@ function brushEditorSections(brush, profile = _chunkGHGBIAWQcjs.PAINT_PROFILE, c
295
306
  path: "colour.palette",
296
307
  label: "Palette",
297
308
  ariaLabel: "Brush palette",
298
- value: (_nullishCoalesce(_optionalChain([brush, 'access', _26 => _26.colour, 'optionalAccess', _27 => _27.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)] : []),
299
- max: _chunkGHGBIAWQcjs.MAX_BRUSH_PALETTE
309
+ value: (_nullishCoalesce(_optionalChain([brush, 'access', _32 => _32.colour, 'optionalAccess', _33 => _33.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)] : []),
310
+ max: _chunk6QNDGMK7cjs.MAX_BRUSH_PALETTE
300
311
  }),
301
312
  toggle("colour.own", "Always its own colour")
302
313
  ]);
@@ -312,9 +323,9 @@ function hiddenLabel(issue, b) {
312
323
  case "tip.shape":
313
324
  return `a ${b.tip.shape} tip`;
314
325
  case "marks":
315
- return _nullishCoalesce(MARKS_WORDS[_nullishCoalesce(_optionalChain([b, 'access', _28 => _28.marks, 'optionalAccess', _29 => _29.kind]), () => ( "continuous"))], () => ( "its marks"));
326
+ return _nullishCoalesce(MARKS_WORDS[_nullishCoalesce(_optionalChain([b, 'access', _34 => _34.marks, 'optionalAccess', _35 => _35.kind]), () => ( "continuous"))], () => ( "its marks"));
316
327
  case "behaviour.surface":
317
- return `${_nullishCoalesce(_optionalChain([b, 'access', _30 => _30.behaviour, 'optionalAccess', _31 => _31.surface]), () => ( "dry"))} behaviour`;
328
+ return `${_nullishCoalesce(_optionalChain([b, 'access', _36 => _36.behaviour, 'optionalAccess', _37 => _37.surface]), () => ( "dry"))} behaviour`;
318
329
  case "behaviour.exchange.reservoir":
319
330
  return "a Mixer Brush reservoir";
320
331
  case "behaviour.exchange":
@@ -327,8 +338,16 @@ function hiddenLabel(issue, b) {
327
338
  return "several dabs per step";
328
339
  case "light":
329
340
  return "light";
341
+ case "fluorescence":
342
+ return "UV-fluorescent ink";
343
+ case "thermochromic":
344
+ return "thermochromic ink";
345
+ case "iridescence":
346
+ return "iridescence";
330
347
  case "ghost":
331
348
  return "ghost paint";
349
+ case "mutation":
350
+ return "mutation paint";
332
351
  case "motion":
333
352
  return "motion";
334
353
  case "dynamics.velocity":
@@ -336,15 +355,15 @@ function hiddenLabel(issue, b) {
336
355
  case "dynamics.tilt":
337
356
  return "tilt dynamics";
338
357
  case "colour.default":
339
- return `a ${_chunkGHGBIAWQcjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
358
+ return `a ${_chunk6QNDGMK7cjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
340
359
  default:
341
360
  return null;
342
361
  }
343
362
  }
344
363
  var sentence = (words) => words.length < 2 ? _nullishCoalesce(words[0], () => ( "")) : `${words.slice(0, -1).join(", ")} and ${words.at(-1)}`;
345
- function brushEditorScope(brush, profile = _chunkGHGBIAWQcjs.PAINT_PROFILE) {
364
+ function brushEditorScope(brush, profile = _chunk6QNDGMK7cjs.PAINT_PROFILE) {
346
365
  const hidden = [];
347
- for (const issue of _chunkGHGBIAWQcjs.checkBrush.call(void 0, brush, profile).issues) {
366
+ for (const issue of _chunk6QNDGMK7cjs.checkBrush.call(void 0, brush, profile).issues) {
348
367
  const label = hiddenLabel(issue, brush);
349
368
  if (label && !hidden.some((h) => h.label === label)) hidden.push({ facet: issue.facet, label });
350
369
  }
@@ -357,17 +376,17 @@ function newBrushFor(profile, from, name = "New brush") {
357
376
  const id = brushIdFromName(name);
358
377
  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] } };
359
378
  if (from) {
360
- const stripped = _chunkGHGBIAWQcjs.degrade.call(void 0, from, profile, { ignored: true });
379
+ const stripped = _chunk6QNDGMK7cjs.degrade.call(void 0, from, profile, { ignored: true });
361
380
  if (!stripped.issues.length) return { ...stripped.brush, id, name };
362
381
  }
363
382
  return base;
364
383
  }
365
384
  async function saveBrushEdit(library, options2) {
366
385
  const { original, profile } = options2;
367
- const check = _chunkGHGBIAWQcjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
386
+ const check = _chunk6QNDGMK7cjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
368
387
  if (!check.ok) {
369
388
  const errors = check.issues.filter((i) => i.severity === "error").map((i) => `${i.facet}: ${i.reason} ${i.fix}`);
370
- throw new (0, _chunkGHGBIAWQcjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
389
+ throw new (0, _chunk6QNDGMK7cjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
371
390
  }
372
391
  const inPlace = !!original && options2.name === void 0 && !library.isBuiltin(original.id) && original.id === options2.brush.id && !!await library.get(original.id);
373
392
  let brush = options2.brush;
@@ -389,7 +408,11 @@ function setBrushEditorValue(brush, path, value) {
389
408
  delete next.variety;
390
409
  delete next.marks;
391
410
  delete next.light;
411
+ delete next.fluorescence;
412
+ delete next.thermochromic;
413
+ delete next.iridescence;
392
414
  delete next.ghost;
415
+ delete next.mutation;
393
416
  delete next.colour;
394
417
  next.tool = _nullishCoalesce(next.tool, () => ( "eraser"));
395
418
  if (next.tip.shape === "stamp") next.tip = { shape: "round", ...next.tip.size !== void 0 ? { size: next.tip.size } : {} };
@@ -399,6 +422,9 @@ function setBrushEditorValue(brush, path, value) {
399
422
  next.marks = value === "continuous" ? void 0 : { kind: value };
400
423
  if (value !== "continuous" && next.tip.shape === "bristle") next.tip = { ...next.tip, shape: "round", bristle: void 0 };
401
424
  if (value === "objects") next.tip = { ...next.tip, shape: "stamp" };
425
+ } else if (path === "iridescence") {
426
+ if (value) next.iridescence = _nullishCoalesce(next.iridescence, () => ( { thickness: 400 }));
427
+ else delete next.iridescence;
402
428
  } else if (path === "tip.grain.source" && (value === void 0 || value === "")) {
403
429
  delete next.tip.grain;
404
430
  } else if (path === "tip.shape" && value !== "stamp") {
@@ -406,13 +432,13 @@ function setBrushEditorValue(brush, path, value) {
406
432
  if (value !== "bristle") delete next.tip.bristle;
407
433
  } else if (value === void 0 || value === "") {
408
434
  const keys = path.split(".");
409
- const parent = _chunkGHGBIAWQcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
435
+ const parent = _chunk6QNDGMK7cjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
410
436
  if (keys.length === 1) delete next[keys[0]];
411
437
  else if (parent) delete parent[keys[keys.length - 1]];
412
- } else _chunkGHGBIAWQcjs.setPath.call(void 0, next, path, value);
438
+ } else _chunk6QNDGMK7cjs.setPath.call(void 0, next, path, value);
413
439
  const problems = [];
414
440
  try {
415
- return { brush: _chunkGHGBIAWQcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
441
+ return { brush: _chunk6QNDGMK7cjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
416
442
  } catch (e) {
417
443
  return { brush, problems: [e.message] };
418
444
  }
@@ -428,7 +454,7 @@ function brushLibraryGroups(entries, filter = {}) {
428
454
  const text = words([b.id, b.name, _nullishCoalesce(b.variety, () => ( "")), _nullishCoalesce(b.medium, () => ( "")), _nullishCoalesce(b.tool, () => ( "")), ..._nullishCoalesce(b.tags, () => ( []))].join(" "));
429
455
  if (!wanted.every((w) => text.some((t) => t.startsWith(w)))) continue;
430
456
  }
431
- if (filter.profile && !_chunkGHGBIAWQcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
457
+ if (filter.profile && !_chunk6QNDGMK7cjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
432
458
  const id = b.kind === "tool" ? "tools" : _nullishCoalesce(b.medium, () => ( "other"));
433
459
  let g = groups.get(id);
434
460
  if (!g) groups.set(id, g = { id, title: id === "tools" ? "Tools" : id === "other" ? "Other" : MEDIUM_LABELS[id], varieties: [] });
@@ -444,7 +470,7 @@ async function imageFileToPngDataUrl(file) {
444
470
  const bytes = new Uint8Array(await file.arrayBuffer());
445
471
  if (_chunkW5M3J7PVcjs.isPng.call(void 0, bytes)) return `data:image/png;base64,${_chunkW5M3J7PVcjs.bytesToBase64.call(void 0, bytes)}`;
446
472
  const g = globalThis;
447
- if (!g.createImageBitmap || !g.OffscreenCanvas) throw new (0, _chunkGHGBIAWQcjs.BrushSourceError)("Only PNG images can be read here; convert the image to PNG.");
473
+ if (!g.createImageBitmap || !g.OffscreenCanvas) throw new (0, _chunk6QNDGMK7cjs.BrushSourceError)("Only PNG images can be read here; convert the image to PNG.");
448
474
  const bitmap = await g.createImageBitmap(file);
449
475
  const canvas = new g.OffscreenCanvas(bitmap.width, bitmap.height);
450
476
  canvas.getContext("2d").drawImage(bitmap, 0, 0);
@@ -452,9 +478,9 @@ async function imageFileToPngDataUrl(file) {
452
478
  return `data:image/png;base64,${_chunkW5M3J7PVcjs.bytesToBase64.call(void 0, png)}`;
453
479
  }
454
480
  async function addBrushSourceFromFile(library, file, options2 = {}) {
455
- const name = (_nullishCoalesce(_nullishCoalesce(options2.name, () => ( _optionalChain([file, 'access', _32 => _32.name, 'optionalAccess', _33 => _33.replace, 'call', _34 => _34(/\.[a-z0-9]+$/i, "")]))), () => ( "Image"))).trim() || "Image";
481
+ const name = (_nullishCoalesce(_nullishCoalesce(options2.name, () => ( _optionalChain([file, 'access', _38 => _38.name, 'optionalAccess', _39 => _39.replace, 'call', _40 => _40(/\.[a-z0-9]+$/i, "")]))), () => ( "Image"))).trim() || "Image";
456
482
  const result = await library.addSource({ name, image: await imageFileToPngDataUrl(file), origin: file.name, ...options2.channel ? { channel: options2.channel } : {} });
457
- return { ...result, ref: _chunkGHGBIAWQcjs.brushSourceRef.call(void 0, result.source.id) };
483
+ return { ...result, ref: _chunk6QNDGMK7cjs.brushSourceRef.call(void 0, result.source.id) };
458
484
  }
459
485
  function withBrushSource(brush, ref, as) {
460
486
  if (as === "grain") return setBrushEditorValue(brush, "tip.grain.source", ref);
@@ -472,11 +498,11 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
472
498
  properties: {
473
499
  id: { type: "string", description: "paint, image, canvas, vector\u2026" },
474
500
  name: { type: "string", description: "Display name, used in messages." },
475
- kinds: { type: "array", items: { type: "string", enum: [..._chunkGHGBIAWQcjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
476
- tools: { type: "array", items: { type: "string", enum: [..._chunkGHGBIAWQcjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
477
- tipShapes: { type: "array", items: { type: "string", enum: [..._chunkGHGBIAWQcjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
478
- marks: { type: "array", items: { type: "string", enum: [..._chunkGHGBIAWQcjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
479
- surfaces: { type: "array", items: { type: "string", enum: [..._chunkGHGBIAWQcjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
501
+ kinds: { type: "array", items: { type: "string", enum: [..._chunk6QNDGMK7cjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
502
+ tools: { type: "array", items: { type: "string", enum: [..._chunk6QNDGMK7cjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
503
+ tipShapes: { type: "array", items: { type: "string", enum: [..._chunk6QNDGMK7cjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
504
+ marks: { type: "array", items: { type: "string", enum: [..._chunk6QNDGMK7cjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
505
+ surfaces: { type: "array", items: { type: "string", enum: [..._chunk6QNDGMK7cjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
480
506
  exchange: { ...SUPPORT, description: "Picking paint up and mixing it in." },
481
507
  reservoir: { ...SUPPORT, description: "The Mixer Brush reservoir." },
482
508
  grain: { ...SUPPORT, description: "Paper grain response." },
@@ -486,7 +512,8 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
486
512
  velocity: { ...SUPPORT, description: "Velocity dynamics." },
487
513
  tilt: { ...SUPPORT, description: "Tilt dynamics." },
488
514
  tipGrain: { ...SUPPORT, description: "Texture inside the tip (tip.grain); missing: none." },
489
- dabCount: { ...SUPPORT, description: "Several dabs per spacing step (dynamics.count); missing: none." }
515
+ dabCount: { ...SUPPORT, description: "Several dabs per spacing step (dynamics.count); missing: none." },
516
+ iridescence: { ...SUPPORT, description: "Thin-film iridescence (iridescence); missing: none." }
490
517
  },
491
518
  required: ["id", "name", "kinds", "tools", "tipShapes", "marks", "surfaces", "exchange", "reservoir", "grain", "light", "motion", "colours", "velocity", "tilt"],
492
519
  additionalProperties: false
@@ -500,16 +527,16 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
500
527
  brushes: { type: "array", items: { $ref: "brush.schema.json" }, description: "The brushes, each a facet brush (brush.schema.json)." },
501
528
  sources: {
502
529
  type: "array",
503
- maxItems: _chunkGHGBIAWQcjs.MAX_BRUSH_SOURCES,
530
+ maxItems: _chunk6QNDGMK7cjs.MAX_BRUSH_SOURCES,
504
531
  description: "The image sources the brushes name (source:<id> in tip.stamps or tip.grain.source), bytes included.",
505
532
  items: {
506
533
  type: "object",
507
534
  description: "An image source: a grey mask, 255 paints (or is a grain peak).",
508
535
  properties: {
509
- id: { type: "string", pattern: _chunkGHGBIAWQcjs.BRUSH_ID.source, description: "Source id." },
536
+ id: { type: "string", pattern: _chunk6QNDGMK7cjs.BRUSH_ID.source, description: "Source id." },
510
537
  name: { type: "string", maxLength: 80, description: "Display name." },
511
- width: { type: "integer", minimum: 1, maximum: _chunkGHGBIAWQcjs.MAX_BRUSH_SOURCE_SIZE, description: "Width in px." },
512
- height: { type: "integer", minimum: 1, maximum: _chunkGHGBIAWQcjs.MAX_BRUSH_SOURCE_SIZE, description: "Height in px." },
538
+ width: { type: "integer", minimum: 1, maximum: _chunk6QNDGMK7cjs.MAX_BRUSH_SOURCE_SIZE, description: "Width in px." },
539
+ height: { type: "integer", minimum: 1, maximum: _chunk6QNDGMK7cjs.MAX_BRUSH_SOURCE_SIZE, description: "Height in px." },
513
540
  image: { type: "string", pattern: "^data:image/png;base64,", description: "The mask as a greyscale PNG data: URL." },
514
541
  licence: { type: "string", maxLength: 2e3, description: "The licence or terms it came with." },
515
542
  origin: { type: "string", maxLength: 200, description: "Where it came from (a file or pack name)." }
@@ -523,7 +550,7 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
523
550
  additionalProperties: false
524
551
  };
525
552
  function migrationInputs() {
526
- const pick = (id) => _chunkGHGBIAWQcjs.brushToJSON.call(void 0, _chunkGHGBIAWQcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
553
+ const pick = (id) => _chunk6QNDGMK7cjs.brushToJSON.call(void 0, _chunk6QNDGMK7cjs.BUILTIN_BRUSHES.find((b) => b.id === id));
527
554
  return [
528
555
  { id: "plain", name: "Plain" },
529
556
  pick("pencil-6b"),
@@ -545,34 +572,34 @@ function migrationInputs() {
545
572
  function editorSectionFixtures() {
546
573
  const ids = ["highlighter", "chalk", "watercolor-wash", "hair-strands", "mixer-brush", "blender", "spray-can"];
547
574
  return ids.flatMap(
548
- (id) => Object.keys(_chunkGHGBIAWQcjs.BRUSH_HOST_PROFILES).map((host) => {
549
- const brush = _chunkGHGBIAWQcjs.BRUSH_PRESETS.find((b) => b.id === id);
550
- return { brush: id, host, sections: brushEditorSections(brush, _chunkGHGBIAWQcjs.BRUSH_HOST_PROFILES[host]) };
575
+ (id) => Object.keys(_chunk6QNDGMK7cjs.BRUSH_HOST_PROFILES).map((host) => {
576
+ const brush = _chunk6QNDGMK7cjs.BRUSH_PRESETS.find((b) => b.id === id);
577
+ return { brush: id, host, sections: brushEditorSections(brush, _chunk6QNDGMK7cjs.BRUSH_HOST_PROFILES[host]) };
551
578
  })
552
579
  );
553
580
  }
554
581
  function toolDefinitions() {
555
- const library = _chunkGHGBIAWQcjs.createBrushLibrary.call(void 0, );
556
- const toolsFor = (host) => _chunk3JKCREEUcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunkGHGBIAWQcjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
582
+ const library = _chunk6QNDGMK7cjs.createBrushLibrary.call(void 0, );
583
+ const toolsFor = (host) => _chunkY354ETAEcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunk6QNDGMK7cjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
557
584
  return {
558
585
  tools: toolsFor("paint").map((t) => ({ name: t.name, title: t.title, description: t.description, inputSchema: t.inputSchema, annotations: t.annotations })),
559
- hosts: Object.fromEntries(Object.keys(_chunkGHGBIAWQcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
586
+ hosts: Object.fromEntries(Object.keys(_chunk6QNDGMK7cjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
560
587
  };
561
588
  }
562
589
  function brushContracts() {
563
- const presets = _chunkGHGBIAWQcjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
564
- const resolved = _chunkGHGBIAWQcjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunkGHGBIAWQcjs.resolveEngine.call(void 0, b), category: _chunkGHGBIAWQcjs.resolveCategory.call(void 0, b), brush: _chunkGHGBIAWQcjs.brushToJSON.call(void 0, _chunkGHGBIAWQcjs.resolveBrush.call(void 0, b)) }));
565
- const profiles = Object.values(_chunkGHGBIAWQcjs.BRUSH_HOST_PROFILES);
566
- const checks = _chunkGHGBIAWQcjs.BRUSH_PRESETS.map((b) => ({
590
+ const presets = _chunk6QNDGMK7cjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
591
+ const resolved = _chunk6QNDGMK7cjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunk6QNDGMK7cjs.resolveEngine.call(void 0, b), category: _chunk6QNDGMK7cjs.resolveCategory.call(void 0, b), brush: _chunk6QNDGMK7cjs.brushToJSON.call(void 0, _chunk6QNDGMK7cjs.resolveBrush.call(void 0, b)) }));
592
+ const profiles = Object.values(_chunk6QNDGMK7cjs.BRUSH_HOST_PROFILES);
593
+ const checks = _chunk6QNDGMK7cjs.BRUSH_PRESETS.map((b) => ({
567
594
  id: b.id,
568
595
  hosts: Object.fromEntries(profiles.map((p) => {
569
- const c = _chunkGHGBIAWQcjs.checkBrush.call(void 0, b, p);
596
+ const c = _chunk6QNDGMK7cjs.checkBrush.call(void 0, b, p);
570
597
  return [p.id, { ok: c.ok, issues: c.issues.map(({ facet, severity }) => ({ facet, severity })) }];
571
598
  }))
572
599
  }));
573
- const migrations = migrationInputs().map((input) => ({ input, output: _chunkGHGBIAWQcjs.migrateBrushV1.call(void 0, input), resolved: _chunkGHGBIAWQcjs.brushToJSON.call(void 0, _chunkGHGBIAWQcjs.resolveBrush.call(void 0, _chunkGHGBIAWQcjs.migrateBrushV1.call(void 0, input))), engine: _chunkGHGBIAWQcjs.normalizePaintBrush.call(void 0, input).engine }));
600
+ const migrations = migrationInputs().map((input) => ({ input, output: _chunk6QNDGMK7cjs.migrateBrushV1.call(void 0, input), resolved: _chunk6QNDGMK7cjs.brushToJSON.call(void 0, _chunk6QNDGMK7cjs.resolveBrush.call(void 0, _chunk6QNDGMK7cjs.migrateBrushV1.call(void 0, input))), engine: _chunk6QNDGMK7cjs.normalizePaintBrush.call(void 0, input).engine }));
574
601
  const files = {
575
- "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkGHGBIAWQcjs.BRUSH_JSON_SCHEMA },
602
+ "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunk6QNDGMK7cjs.BRUSH_JSON_SCHEMA },
576
603
  "profile.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "profile.schema.json", ...BRUSH_PROFILE_JSON_SCHEMA },
577
604
  "library-file.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "library-file.schema.json", ...BRUSH_LIBRARY_FILE_JSON_SCHEMA },
578
605
  "presets.json": presets,
@@ -586,7 +613,7 @@ function brushContracts() {
586
613
  files["manifest.json"] = {
587
614
  domain: "brushes",
588
615
  formatVersion: BRUSH_CONTRACT_FORMAT_VERSION,
589
- limits: { maxPalette: _chunkGHGBIAWQcjs.MAX_BRUSH_PALETTE },
616
+ limits: { maxPalette: _chunk6QNDGMK7cjs.MAX_BRUSH_PALETTE },
590
617
  counts: { presets: presets.length, profiles: profiles.length, migrations: migrations.length, editorSections: files["editor-sections.json"].length },
591
618
  files: Object.keys(files).sort()
592
619
  };
@@ -686,4 +713,5 @@ function brushContracts() {
686
713
 
687
714
 
688
715
 
689
- exports.AbrError = _chunk3JKCREEUcjs.AbrError; exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunkGHGBIAWQcjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_FLIPS = _chunkGHGBIAWQcjs.BRUSH_FLIPS; exports.BRUSH_GRAIN_MODES = _chunkGHGBIAWQcjs.BRUSH_GRAIN_MODES; exports.BRUSH_GRAIN_SOURCE_PATTERN = _chunkGHGBIAWQcjs.BRUSH_GRAIN_SOURCE_PATTERN; exports.BRUSH_HOST_PROFILES = _chunkGHGBIAWQcjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunkGHGBIAWQcjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunkGHGBIAWQcjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunkGHGBIAWQcjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunkGHGBIAWQcjs.BRUSH_MEDIA; exports.BRUSH_PACK_FORMATS = _chunk3JKCREEUcjs.BRUSH_PACK_FORMATS; exports.BRUSH_PATCH_PROPERTIES = _chunk3JKCREEUcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunkGHGBIAWQcjs.BRUSH_PRESETS; exports.BRUSH_PREVIEW_DARK_PAPER = _chunk7W2EQQBPcjs.BRUSH_PREVIEW_DARK_PAPER; exports.BRUSH_PREVIEW_FALLBACKS = _chunk7W2EQQBPcjs.BRUSH_PREVIEW_FALLBACKS; exports.BRUSH_PREVIEW_MIN_CONTRAST = _chunk7W2EQQBPcjs.BRUSH_PREVIEW_MIN_CONTRAST; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SOURCE_CHANNELS = _chunkGHGBIAWQcjs.BRUSH_SOURCE_CHANNELS; exports.BRUSH_SOURCE_PROVIDER = _chunkGHGBIAWQcjs.BRUSH_SOURCE_PROVIDER; exports.BRUSH_SURFACES = _chunkGHGBIAWQcjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunkGHGBIAWQcjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunkGHGBIAWQcjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunk3JKCREEUcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunkGHGBIAWQcjs.BRUSH_WORD; exports.BrushLibraryError = _chunkGHGBIAWQcjs.BrushLibraryError; exports.BrushPackError = _chunk3JKCREEUcjs.BrushPackError; exports.BrushSourceError = _chunkGHGBIAWQcjs.BrushSourceError; exports.CANVAS_PROFILE = _chunkGHGBIAWQcjs.CANVAS_PROFILE; exports.IMAGE_PROFILE = _chunkGHGBIAWQcjs.IMAGE_PROFILE; exports.MAX_BRUSH_PACK_BYTES = _chunk3JKCREEUcjs.MAX_BRUSH_PACK_BYTES; exports.MAX_BRUSH_PALETTE = _chunkGHGBIAWQcjs.MAX_BRUSH_PALETTE; exports.MAX_BRUSH_SOURCES = _chunkGHGBIAWQcjs.MAX_BRUSH_SOURCES; exports.MAX_BRUSH_SOURCE_INPUT_PIXELS = _chunkGHGBIAWQcjs.MAX_BRUSH_SOURCE_INPUT_PIXELS; exports.MAX_BRUSH_SOURCE_SIZE = _chunkGHGBIAWQcjs.MAX_BRUSH_SOURCE_SIZE; exports.MAX_PACK_BRUSHES = _chunk3JKCREEUcjs.MAX_PACK_BRUSHES; exports.PAINT_PROFILE = _chunkGHGBIAWQcjs.PAINT_PROFILE; exports.TIP_GRAIN_PATTERNS = _chunkGHGBIAWQcjs.TIP_GRAIN_PATTERNS; exports.UNSETTABLE_BRUSH_FACETS = _chunk3JKCREEUcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunkGHGBIAWQcjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunkGHGBIAWQcjs.WET_BRUSH_TOOLS; exports.addBrushSourceFromFile = addBrushSourceFromFile; exports.brushColourHex = _chunkJBZRVLXVcjs.brushColourHex; exports.brushColourKind = _chunkGHGBIAWQcjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorScope = brushEditorScope; exports.brushEditorSections = brushEditorSections; exports.brushIdFromName = brushIdFromName; exports.brushLibraryGroups = brushLibraryGroups; exports.brushPackFormat = _chunk3JKCREEUcjs.brushPackFormat; exports.brushPreviewColours = _chunk7W2EQQBPcjs.brushPreviewColours; exports.brushPreviewStrength = _chunk7W2EQQBPcjs.brushPreviewStrength; exports.brushPreviewsOnDark = _chunk7W2EQQBPcjs.brushPreviewsOnDark; exports.brushSourceFromMask = _chunkGHGBIAWQcjs.brushSourceFromMask; exports.brushSourceIdFromName = _chunkGHGBIAWQcjs.brushSourceIdFromName; exports.brushSourceIdOf = _chunkGHGBIAWQcjs.brushSourceIdOf; exports.brushSourceIds = _chunkGHGBIAWQcjs.brushSourceIds; exports.brushSourceRef = _chunkGHGBIAWQcjs.brushSourceRef; exports.changedBrushPaths = _chunk3JKCREEUcjs.changedBrushPaths; exports.checkBrush = _chunkGHGBIAWQcjs.checkBrush; exports.checkBrushEdit = _chunkGHGBIAWQcjs.checkBrushEdit; exports.createBrushLibrary = _chunkGHGBIAWQcjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunk3JKCREEUcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunk3JKCREEUcjs.createBrushLibraryTools; exports.decodeBrushSource = _chunkGHGBIAWQcjs.decodeBrushSource; exports.degrade = _chunkGHGBIAWQcjs.degrade; exports.imageFileToPngDataUrl = imageFileToPngDataUrl; exports.importBrushFile = _chunk3JKCREEUcjs.importBrushFile; exports.importBrushPack = _chunk3JKCREEUcjs.importBrushPack; exports.isBrushLibrary = _chunkGHGBIAWQcjs.isBrushLibrary; exports.isBrushSourceRef = _chunkGHGBIAWQcjs.isBrushSourceRef; exports.listPresets = _chunkGHGBIAWQcjs.listPresets; exports.makeBrushSource = _chunkGHGBIAWQcjs.makeBrushSource; exports.mergeBrushPatch = _chunk3JKCREEUcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunkGHGBIAWQcjs.migrateBrushV1; exports.newBrushFor = newBrushFor; exports.normalizeBrushSpec = _chunkGHGBIAWQcjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunkGHGBIAWQcjs.parseBrushLibrary2; exports.parseBrushLibrarySources = _chunkGHGBIAWQcjs.parseBrushLibrarySources; exports.readAbr = _chunk3JKCREEUcjs.readAbr; exports.readBrushPack = _chunk3JKCREEUcjs.readBrushPack; exports.readBrushSource = _chunkGHGBIAWQcjs.readBrushSource; exports.resolveBrush = _chunkGHGBIAWQcjs.resolveBrush; exports.resolveCategory = _chunkGHGBIAWQcjs.resolveCategory; exports.resolveEngine = _chunkGHGBIAWQcjs.resolveEngine; exports.resolveWetMedium = _chunkGHGBIAWQcjs.resolveWetMedium; exports.saveBrushEdit = saveBrushEdit; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunkGHGBIAWQcjs.snapshotBrushLibrary; exports.summarizeBrushSource = _chunkGHGBIAWQcjs.summarizeBrushSource; exports.withBrushSource = withBrushSource; exports.withKeptIssues = _chunkGHGBIAWQcjs.withKeptIssues;
716
+
717
+ exports.AbrError = _chunkY354ETAEcjs.AbrError; exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunk6QNDGMK7cjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_FLIPS = _chunk6QNDGMK7cjs.BRUSH_FLIPS; exports.BRUSH_GRAIN_MODES = _chunk6QNDGMK7cjs.BRUSH_GRAIN_MODES; exports.BRUSH_GRAIN_SOURCE_PATTERN = _chunk6QNDGMK7cjs.BRUSH_GRAIN_SOURCE_PATTERN; exports.BRUSH_HOST_PROFILES = _chunk6QNDGMK7cjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunk6QNDGMK7cjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunk6QNDGMK7cjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunk6QNDGMK7cjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunk6QNDGMK7cjs.BRUSH_MEDIA; exports.BRUSH_PACK_FORMATS = _chunkY354ETAEcjs.BRUSH_PACK_FORMATS; exports.BRUSH_PATCH_PROPERTIES = _chunkY354ETAEcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunk6QNDGMK7cjs.BRUSH_PRESETS; exports.BRUSH_PREVIEW_DARK_PAPER = _chunkJDXWLCXFcjs.BRUSH_PREVIEW_DARK_PAPER; exports.BRUSH_PREVIEW_FALLBACKS = _chunkJDXWLCXFcjs.BRUSH_PREVIEW_FALLBACKS; exports.BRUSH_PREVIEW_MIN_CONTRAST = _chunkJDXWLCXFcjs.BRUSH_PREVIEW_MIN_CONTRAST; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SOURCE_CHANNELS = _chunk6QNDGMK7cjs.BRUSH_SOURCE_CHANNELS; exports.BRUSH_SOURCE_PROVIDER = _chunk6QNDGMK7cjs.BRUSH_SOURCE_PROVIDER; exports.BRUSH_SURFACES = _chunk6QNDGMK7cjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunk6QNDGMK7cjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunk6QNDGMK7cjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunkY354ETAEcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunk6QNDGMK7cjs.BRUSH_WORD; exports.BrushLibraryError = _chunk6QNDGMK7cjs.BrushLibraryError; exports.BrushPackError = _chunkY354ETAEcjs.BrushPackError; exports.BrushSourceError = _chunk6QNDGMK7cjs.BrushSourceError; exports.CANVAS_PROFILE = _chunk6QNDGMK7cjs.CANVAS_PROFILE; exports.GHOST_TRIGGERS = _chunk6QNDGMK7cjs.GHOST_TRIGGERS2; exports.IMAGE_PROFILE = _chunk6QNDGMK7cjs.IMAGE_PROFILE; exports.MAX_BRUSH_PACK_BYTES = _chunkY354ETAEcjs.MAX_BRUSH_PACK_BYTES; exports.MAX_BRUSH_PALETTE = _chunk6QNDGMK7cjs.MAX_BRUSH_PALETTE; exports.MAX_BRUSH_SOURCES = _chunk6QNDGMK7cjs.MAX_BRUSH_SOURCES; exports.MAX_BRUSH_SOURCE_INPUT_PIXELS = _chunk6QNDGMK7cjs.MAX_BRUSH_SOURCE_INPUT_PIXELS; exports.MAX_BRUSH_SOURCE_SIZE = _chunk6QNDGMK7cjs.MAX_BRUSH_SOURCE_SIZE; exports.MAX_PACK_BRUSHES = _chunkY354ETAEcjs.MAX_PACK_BRUSHES; exports.PAINT_PROFILE = _chunk6QNDGMK7cjs.PAINT_PROFILE; exports.TIP_GRAIN_PATTERNS = _chunk6QNDGMK7cjs.TIP_GRAIN_PATTERNS; exports.UNSETTABLE_BRUSH_FACETS = _chunkY354ETAEcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunk6QNDGMK7cjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunk6QNDGMK7cjs.WET_BRUSH_TOOLS; exports.addBrushSourceFromFile = addBrushSourceFromFile; exports.brushColourHex = _chunkJBZRVLXVcjs.brushColourHex; exports.brushColourKind = _chunk6QNDGMK7cjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorScope = brushEditorScope; exports.brushEditorSections = brushEditorSections; exports.brushIdFromName = brushIdFromName; exports.brushLibraryGroups = brushLibraryGroups; exports.brushPackFormat = _chunkY354ETAEcjs.brushPackFormat; exports.brushPreviewColours = _chunkJDXWLCXFcjs.brushPreviewColours; exports.brushPreviewStrength = _chunkJDXWLCXFcjs.brushPreviewStrength; exports.brushPreviewsOnDark = _chunkJDXWLCXFcjs.brushPreviewsOnDark; exports.brushSourceFromMask = _chunk6QNDGMK7cjs.brushSourceFromMask; exports.brushSourceIdFromName = _chunk6QNDGMK7cjs.brushSourceIdFromName; exports.brushSourceIdOf = _chunk6QNDGMK7cjs.brushSourceIdOf; exports.brushSourceIds = _chunk6QNDGMK7cjs.brushSourceIds; exports.brushSourceRef = _chunk6QNDGMK7cjs.brushSourceRef; exports.changedBrushPaths = _chunkY354ETAEcjs.changedBrushPaths; exports.checkBrush = _chunk6QNDGMK7cjs.checkBrush; exports.checkBrushEdit = _chunk6QNDGMK7cjs.checkBrushEdit; exports.createBrushLibrary = _chunk6QNDGMK7cjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunkY354ETAEcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunkY354ETAEcjs.createBrushLibraryTools; exports.decodeBrushSource = _chunk6QNDGMK7cjs.decodeBrushSource; exports.degrade = _chunk6QNDGMK7cjs.degrade; exports.imageFileToPngDataUrl = imageFileToPngDataUrl; exports.importBrushFile = _chunkY354ETAEcjs.importBrushFile; exports.importBrushPack = _chunkY354ETAEcjs.importBrushPack; exports.isBrushLibrary = _chunk6QNDGMK7cjs.isBrushLibrary; exports.isBrushSourceRef = _chunk6QNDGMK7cjs.isBrushSourceRef; exports.listPresets = _chunk6QNDGMK7cjs.listPresets; exports.makeBrushSource = _chunk6QNDGMK7cjs.makeBrushSource; exports.mergeBrushPatch = _chunkY354ETAEcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunk6QNDGMK7cjs.migrateBrushV1; exports.newBrushFor = newBrushFor; exports.normalizeBrushSpec = _chunk6QNDGMK7cjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunk6QNDGMK7cjs.parseBrushLibrary2; exports.parseBrushLibrarySources = _chunk6QNDGMK7cjs.parseBrushLibrarySources; exports.readAbr = _chunkY354ETAEcjs.readAbr; exports.readBrushPack = _chunkY354ETAEcjs.readBrushPack; exports.readBrushSource = _chunk6QNDGMK7cjs.readBrushSource; exports.resolveBrush = _chunk6QNDGMK7cjs.resolveBrush; exports.resolveCategory = _chunk6QNDGMK7cjs.resolveCategory; exports.resolveEngine = _chunk6QNDGMK7cjs.resolveEngine; exports.resolveWetMedium = _chunk6QNDGMK7cjs.resolveWetMedium; exports.saveBrushEdit = saveBrushEdit; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunk6QNDGMK7cjs.snapshotBrushLibrary; exports.summarizeBrushSource = _chunk6QNDGMK7cjs.summarizeBrushSource; exports.withBrushSource = withBrushSource; exports.withKeptIssues = _chunk6QNDGMK7cjs.withKeptIssues;
@@ -18,7 +18,7 @@ import {
18
18
  mergeBrushPatch,
19
19
  readAbr,
20
20
  readBrushPack
21
- } from "../chunk-NAHJV3O6.js";
21
+ } from "../chunk-G5TCMKX5.js";
22
22
  import "../chunk-VE6UKYQ2.js";
23
23
  import {
24
24
  BRUSH_PREVIEW_DARK_PAPER,
@@ -27,7 +27,7 @@ import {
27
27
  brushPreviewColours,
28
28
  brushPreviewStrength,
29
29
  brushPreviewsOnDark
30
- } from "../chunk-CLB2I2FU.js";
30
+ } from "../chunk-RJGW3RQS.js";
31
31
  import {
32
32
  BRUSH_FACET_SCHEMAS,
33
33
  BRUSH_FIELDS,
@@ -54,6 +54,7 @@ import {
54
54
  CANVAS_PROFILE,
55
55
  DOT_ROTATIONS,
56
56
  DOT_TEXTURE_ORDERS,
57
+ GHOST_TRIGGERS2 as GHOST_TRIGGERS,
57
58
  IMAGE_PROFILE,
58
59
  IMPASTO_TOOLS,
59
60
  MAX_BRUSH_PALETTE,
@@ -101,7 +102,7 @@ import {
101
102
  snapshotBrushLibrary,
102
103
  summarizeBrushSource,
103
104
  withKeptIssues
104
- } from "../chunk-UXYCY3HP.js";
105
+ } from "../chunk-ZM7IKQ4X.js";
105
106
  import {
106
107
  STAMP_KINDS
107
108
  } from "../chunk-JL6YH5WD.js";
@@ -262,7 +263,7 @@ function brushEditorSections(brush, profile = PAINT_PROFILE, context = {}) {
262
263
  stampDabs && choice("dynamics.flip", "Flip", options(BRUSH_FLIPS, FLIP_LABELS), "none")
263
264
  ]);
264
265
  const surfaces = profile.surfaces;
265
- const engineSliders = (engineOk ? engineControls?.sliders ?? [] : []).filter((c) => !/^(bristle|particle|sticker)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
266
+ const engineSliders = (engineOk ? engineControls?.sliders ?? [] : []).filter((c) => !/^(bristle|particle|sticker|iridescence)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
266
267
  const exchangeOk = (path) => !path?.startsWith("behaviour.exchange") || (path.startsWith("behaviour.exchange.reservoir") ? full(profile.reservoir) : exchangeFull);
267
268
  add("behaviour", engineControls?.title ?? "Behaviour", [
268
269
  !isTool && surfaces.length > 1 && !refused.has("behaviour.surface") && choice("behaviour.surface", "Surface", options(surfaces, SURFACE_LABELS), "dry"),
@@ -280,7 +281,17 @@ function brushEditorSections(brush, profile = PAINT_PROFILE, context = {}) {
280
281
  toggle("light.pressure", "Light follows pressure"),
281
282
  ...engine === "impasto" ? [slider({ path: "impasto.rim", label: "Rim", min: 0, max: 1, step: 0.01 }), slider({ path: "impasto.clarity", label: "Clarity", min: 0, max: 1, step: 0.01 })] : [],
282
283
  withNote({ kind: "slider", path: "light.spill.radius", label: "Spill", ariaLabel: "Brush light spill", min: 0, max: 128, step: 1, value: brush.light?.spill?.radius ?? 24 }),
283
- toggle("light.glow", "Suggest a glow")
284
+ toggle("light.glow", "Suggest a glow"),
285
+ withNote({ kind: "slider", path: "fluorescence.amount", label: "UV fluorescence", ariaLabel: "Brush fluorescence amount", min: 0, max: 1, step: 0.01, value: brush.fluorescence?.amount ?? 0 }),
286
+ toggle("fluorescence.invisible", "Invisible in daylight"),
287
+ withNote({ kind: "colour", path: "thermochromic.hotColor", label: "Hot colour", ariaLabel: "Brush thermochromic hot colour", value: brush.thermochromic?.hotColor ?? null, dark: null, gradient: false }),
288
+ withNote({ kind: "slider", path: "thermochromic.threshold", label: "Heat threshold", ariaLabel: "Brush thermochromic threshold", min: 0.05, max: 0.95, step: 0.01, value: brush.thermochromic?.threshold ?? 0.5 }),
289
+ full(profile.iridescence ?? "none") && marks !== "objects" && withNote({ kind: "toggle", path: "iridescence", label: "Thin-film iridescence", ariaLabel: "Brush thin-film iridescence", value: Boolean(brush.iridescence) }),
290
+ ...brush.iridescence && full(profile.iridescence ?? "none") ? [
291
+ slider({ path: "iridescence.thickness", label: "Film (nm)", min: 100, max: 1e3, step: 5 }),
292
+ slider({ path: "iridescence.pressureToThickness", label: "Pressure \u2192 film", min: 0, max: 1, step: 0.01 }),
293
+ slider({ path: "iridescence.ior", label: "Film IOR", min: 1.2, max: 2, step: 0.01 })
294
+ ] : []
284
295
  ]);
285
296
  }
286
297
  if (full(profile.motion) && engineOk && marks === "particles") add("motion", "Motion", [slider({ path: "particle.waveSpeed", label: "Wave speed", min: 0, max: 1, step: 0.01 })]);
@@ -327,8 +338,16 @@ function hiddenLabel(issue, b) {
327
338
  return "several dabs per step";
328
339
  case "light":
329
340
  return "light";
341
+ case "fluorescence":
342
+ return "UV-fluorescent ink";
343
+ case "thermochromic":
344
+ return "thermochromic ink";
345
+ case "iridescence":
346
+ return "iridescence";
330
347
  case "ghost":
331
348
  return "ghost paint";
349
+ case "mutation":
350
+ return "mutation paint";
332
351
  case "motion":
333
352
  return "motion";
334
353
  case "dynamics.velocity":
@@ -389,7 +408,11 @@ function setBrushEditorValue(brush, path, value) {
389
408
  delete next.variety;
390
409
  delete next.marks;
391
410
  delete next.light;
411
+ delete next.fluorescence;
412
+ delete next.thermochromic;
413
+ delete next.iridescence;
392
414
  delete next.ghost;
415
+ delete next.mutation;
393
416
  delete next.colour;
394
417
  next.tool = next.tool ?? "eraser";
395
418
  if (next.tip.shape === "stamp") next.tip = { shape: "round", ...next.tip.size !== void 0 ? { size: next.tip.size } : {} };
@@ -399,6 +422,9 @@ function setBrushEditorValue(brush, path, value) {
399
422
  next.marks = value === "continuous" ? void 0 : { kind: value };
400
423
  if (value !== "continuous" && next.tip.shape === "bristle") next.tip = { ...next.tip, shape: "round", bristle: void 0 };
401
424
  if (value === "objects") next.tip = { ...next.tip, shape: "stamp" };
425
+ } else if (path === "iridescence") {
426
+ if (value) next.iridescence = next.iridescence ?? { thickness: 400 };
427
+ else delete next.iridescence;
402
428
  } else if (path === "tip.grain.source" && (value === void 0 || value === "")) {
403
429
  delete next.tip.grain;
404
430
  } else if (path === "tip.shape" && value !== "stamp") {
@@ -486,7 +512,8 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
486
512
  velocity: { ...SUPPORT, description: "Velocity dynamics." },
487
513
  tilt: { ...SUPPORT, description: "Tilt dynamics." },
488
514
  tipGrain: { ...SUPPORT, description: "Texture inside the tip (tip.grain); missing: none." },
489
- dabCount: { ...SUPPORT, description: "Several dabs per spacing step (dynamics.count); missing: none." }
515
+ dabCount: { ...SUPPORT, description: "Several dabs per spacing step (dynamics.count); missing: none." },
516
+ iridescence: { ...SUPPORT, description: "Thin-film iridescence (iridescence); missing: none." }
490
517
  },
491
518
  required: ["id", "name", "kinds", "tools", "tipShapes", "marks", "surfaces", "exchange", "reservoir", "grain", "light", "motion", "colours", "velocity", "tilt"],
492
519
  additionalProperties: false
@@ -623,6 +650,7 @@ export {
623
650
  BrushPackError,
624
651
  BrushSourceError,
625
652
  CANVAS_PROFILE,
653
+ GHOST_TRIGGERS,
626
654
  IMAGE_PROFILE,
627
655
  MAX_BRUSH_PACK_BYTES,
628
656
  MAX_BRUSH_PALETTE,
@@ -13,7 +13,7 @@ export type BrushPatch = {
13
13
  /** The schema of every facet except `id` and `name`, as tool arguments (a patch may leave out `tip.shape`). */
14
14
  export declare const BRUSH_PATCH_PROPERTIES: Readonly<Record<string, JsonSchema>>;
15
15
  /** The facets a patch can remove (`unset`), back to the engine's defaults. */
16
- export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "ghost", "motion", "colour"];
16
+ export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "motion", "colour"];
17
17
  export type UnsettableBrushFacet = (typeof UNSETTABLE_BRUSH_FACETS)[number];
18
18
  /** The `unset` argument of tools that take a patch. */
19
19
  export declare const BRUSH_UNSET_PROPERTY: JsonSchema;
@@ -13,7 +13,7 @@ export type BrushPatch = {
13
13
  /** The schema of every facet except `id` and `name`, as tool arguments (a patch may leave out `tip.shape`). */
14
14
  export declare const BRUSH_PATCH_PROPERTIES: Readonly<Record<string, JsonSchema>>;
15
15
  /** The facets a patch can remove (`unset`), back to the engine's defaults. */
16
- export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "ghost", "motion", "colour"];
16
+ export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "motion", "colour"];
17
17
  export type UnsettableBrushFacet = (typeof UNSETTABLE_BRUSH_FACETS)[number];
18
18
  /** The `unset` argument of tools that take a patch. */
19
19
  export declare const BRUSH_UNSET_PROPERTY: JsonSchema;