@pixerate/editor 0.270.0 → 0.272.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 (77) hide show
  1. package/dist/animation-editor/index.cjs +62 -62
  2. package/dist/animation-editor/index.js +5 -5
  3. package/dist/brushes/index.cjs +69 -66
  4. package/dist/brushes/index.js +6 -3
  5. package/dist/brushes/patch.d.cts +1 -1
  6. package/dist/brushes/patch.d.ts +1 -1
  7. package/dist/brushes/schema.d.cts +1 -0
  8. package/dist/brushes/schema.d.ts +1 -0
  9. package/dist/brushes/types.d.cts +8 -0
  10. package/dist/brushes/types.d.ts +8 -0
  11. package/dist/{brushstrokeRender-WR2N5HHY.cjs → brushstrokeRender-5YBCLFDQ.cjs} +15 -15
  12. package/dist/{brushstrokeRender-A727TTNQ.js → brushstrokeRender-DZGFU3J4.js} +3 -3
  13. package/dist/canvas/index.cjs +15 -15
  14. package/dist/canvas/index.js +2 -2
  15. package/dist/{chunk-THBJHPUL.js → chunk-2F3YDXCN.js} +1 -1
  16. package/dist/{chunk-4CPOKP27.js → chunk-2XDNF73E.js} +1 -1
  17. package/dist/{chunk-3KNQ2W6X.cjs → chunk-3JKCREEU.cjs} +59 -53
  18. package/dist/{chunk-4YSPQGZW.js → chunk-5HP2VSAS.js} +1 -1
  19. package/dist/{chunk-BPJSI4NT.cjs → chunk-7W2EQQBP.cjs} +2 -2
  20. package/dist/{chunk-LETF75CA.js → chunk-CLB2I2FU.js} +1 -1
  21. package/dist/{chunk-BAZMCFVL.js → chunk-DZVRH63Y.js} +1 -1
  22. package/dist/{chunk-PY4GWSE2.cjs → chunk-EBFPMSJO.cjs} +27 -5
  23. package/dist/{chunk-VBRHE4AM.cjs → chunk-FXVCB6YG.cjs} +35 -35
  24. package/dist/{chunk-EU2ZZA6L.cjs → chunk-GHGBIAWQ.cjs} +126 -39
  25. package/dist/{chunk-CBVNCWJM.cjs → chunk-LBDC5434.cjs} +2 -2
  26. package/dist/{chunk-2WOGXEDX.cjs → chunk-M3RZOF3G.cjs} +1 -1
  27. package/dist/{chunk-GSTSZPSR.js → chunk-N3SKPQEH.js} +225 -18
  28. package/dist/{chunk-J5VQYK7T.cjs → chunk-N5IMDAHM.cjs} +251 -44
  29. package/dist/{chunk-ININNHLM.js → chunk-NAHJV3O6.js} +11 -5
  30. package/dist/{chunk-MWUZCEFT.js → chunk-S2XPXA47.js} +1 -1
  31. package/dist/{chunk-56RHCIJV.cjs → chunk-SNAFFCAX.cjs} +296 -203
  32. package/dist/{chunk-EHLOCVWB.js → chunk-T2URHAJX.js} +27 -5
  33. package/dist/{chunk-BENSE3VX.cjs → chunk-TNLKFW7D.cjs} +23 -23
  34. package/dist/{chunk-KZI3YWKW.js → chunk-UXYCY3HP.js} +93 -6
  35. package/dist/{chunk-4NMPUJUK.cjs → chunk-YJANF2BL.cjs} +86 -86
  36. package/dist/{chunk-FUDP5QBB.js → chunk-ZEI7ZEA4.js} +101 -8
  37. package/dist/effects/index.cjs +5 -2
  38. package/dist/effects/index.js +4 -1
  39. package/dist/effects/pool.d.cts +9 -0
  40. package/dist/effects/pool.d.ts +9 -0
  41. package/dist/effects/types.d.cts +2 -0
  42. package/dist/effects/types.d.ts +2 -0
  43. package/dist/image-editor/index.cjs +791 -791
  44. package/dist/image-editor/index.js +6 -6
  45. package/dist/paint/index.cjs +2 -2
  46. package/dist/paint/index.js +1 -1
  47. package/dist/paint/wet/world.d.cts +37 -1
  48. package/dist/paint/wet/world.d.ts +37 -1
  49. package/dist/paint-editor/brush-controls.d.cts +2 -0
  50. package/dist/paint-editor/brush-controls.d.ts +2 -0
  51. package/dist/paint-editor/brush-model.d.cts +14 -1
  52. package/dist/paint-editor/brush-model.d.ts +14 -1
  53. package/dist/paint-editor/controller.d.cts +75 -4
  54. package/dist/paint-editor/controller.d.ts +75 -4
  55. package/dist/paint-editor/effect-paint.d.cts +33 -8
  56. package/dist/paint-editor/effect-paint.d.ts +33 -8
  57. package/dist/paint-editor/effects.d.cts +4 -0
  58. package/dist/paint-editor/effects.d.ts +4 -0
  59. package/dist/paint-editor/index.cjs +814 -483
  60. package/dist/paint-editor/index.js +408 -77
  61. package/dist/paint-editor/stroke.d.cts +13 -5
  62. package/dist/paint-editor/stroke.d.ts +13 -5
  63. package/dist/paint-editor/ui.d.cts +1 -1
  64. package/dist/paint-editor/ui.d.ts +1 -1
  65. package/dist/paint-editor/wet.d.cts +8 -1
  66. package/dist/paint-editor/wet.d.ts +8 -1
  67. package/dist/vector/index.cjs +999 -999
  68. package/dist/vector/index.js +5 -5
  69. package/dist/video-editor/index.cjs +317 -317
  70. package/dist/video-editor/index.js +2 -2
  71. package/package.json +1 -1
  72. package/skills/pixerate-brushes/SKILL.md +1 -0
  73. package/skills/pixerate-paint-editor/SKILL.md +6 -13
  74. package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
  75. package/skills/pixerate-paint-editor/references/effect-paint.md +28 -6
  76. package/skills/pixerate-paint-editor/references/ghost.md +47 -0
  77. package/skills/pixerate-paint-watercolour/SKILL.md +1 -0
@@ -18,7 +18,7 @@
18
18
 
19
19
 
20
20
 
21
- var _chunk3KNQ2W6Xcjs = require('../chunk-3KNQ2W6X.cjs');
21
+ var _chunk3JKCREEUcjs = require('../chunk-3JKCREEU.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 _chunkBPJSI4NTcjs = require('../chunk-BPJSI4NT.cjs');
30
+ var _chunk7W2EQQBPcjs = require('../chunk-7W2EQQBP.cjs');
31
31
 
32
32
 
33
33
 
@@ -101,7 +101,7 @@ var _chunkBPJSI4NTcjs = require('../chunk-BPJSI4NT.cjs');
101
101
 
102
102
 
103
103
 
104
- var _chunkEU2ZZA6Lcjs = require('../chunk-EU2ZZA6L.cjs');
104
+ var _chunkGHGBIAWQcjs = require('../chunk-GHGBIAWQ.cjs');
105
105
 
106
106
 
107
107
  var _chunkRDFHWAHLcjs = require('../chunk-RDFHWAHL.cjs');
@@ -164,20 +164,20 @@ var ARIA = {
164
164
  "dynamics.angleJitter": "Brush rotation jitter"
165
165
  };
166
166
  var aria = (path, label) => _nullishCoalesce(ARIA[path], () => ( `Brush ${label.toLowerCase()}`));
167
- function brushEditorSections(brush, profile = _chunkEU2ZZA6Lcjs.PAINT_PROFILE, context = {}) {
168
- const resolved = _chunkEU2ZZA6Lcjs.resolveBrush.call(void 0, brush);
169
- const engine = _chunkEU2ZZA6Lcjs.resolveEngine.call(void 0, brush);
170
- const fieldOf = (facet) => _chunkEU2ZZA6Lcjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
171
- const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunkEU2ZZA6Lcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunkEU2ZZA6Lcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
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]);
172
172
  const value = (path) => {
173
- const own = _chunkEU2ZZA6Lcjs.getPath.call(void 0, brush, path);
173
+ const own = _chunkGHGBIAWQcjs.getPath.call(void 0, brush, path);
174
174
  if (own !== void 0) return own;
175
175
  const field = fieldOf(path);
176
176
  if (!field) return void 0;
177
- const v = _chunkEU2ZZA6Lcjs.getPath.call(void 0, resolved, field.engine);
177
+ const v = _chunkGHGBIAWQcjs.getPath.call(void 0, resolved, field.engine);
178
178
  return field.map ? field.map.toFacet(v) : v;
179
179
  };
180
- const issues = _chunkEU2ZZA6Lcjs.checkBrush.call(void 0, brush, profile).issues;
180
+ const issues = _chunkGHGBIAWQcjs.checkBrush.call(void 0, brush, profile).issues;
181
181
  const warned = new Map(issues.filter((i) => i.severity === "warning").map((i) => [i.facet, i.reason]));
182
182
  const refused = new Set(issues.filter((i) => i.severity === "error").map((i) => i.facet));
183
183
  const full = (s) => s === "full";
@@ -202,30 +202,30 @@ function brushEditorSections(brush, profile = _chunkEU2ZZA6Lcjs.PAINT_PROFILE, c
202
202
  };
203
203
  const isTool = brush.kind === "tool";
204
204
  const shape = brush.tip.shape;
205
- const sourceOptions = (_nullishCoalesce(context.sources, () => ( []))).map((x) => ({ value: _chunkEU2ZZA6Lcjs.brushSourceRef.call(void 0, x.id), label: x.name }));
205
+ const sourceOptions = (_nullishCoalesce(context.sources, () => ( []))).map((x) => ({ value: _chunkGHGBIAWQcjs.brushSourceRef.call(void 0, x.id), label: x.name }));
206
206
  const marks = _nullishCoalesce(_optionalChain([brush, 'access', _7 => _7.marks, 'optionalAccess', _8 => _8.kind]), () => ( "continuous"));
207
207
  const exchangeFull = full(_optionalChain([brush, 'access', _9 => _9.behaviour, 'optionalAccess', _10 => _10.exchange, 'optionalAccess', _11 => _11.reservoir]) ? profile.reservoir : profile.exchange);
208
208
  add("medium", "Medium", [
209
209
  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(_chunkEU2ZZA6Lcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
210
+ !isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunkGHGBIAWQcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
211
211
  !isTool && withNote({ kind: "text", path: "variety", label: "Variety", ariaLabel: "Brush variety", value: _nullishCoalesce(brush.variety, () => ( "")), placeholder: "pencil, oil, highlighter\u2026" }),
212
212
  isTool && !!brush.tool && profile.tools.includes(brush.tool) && choice("tool", "Tool", options(profile.tools, TOOL_LABELS))
213
213
  ]);
214
- const engineControls = _chunk3KNQ2W6Xcjs.brushEngineControls.call(void 0, resolved);
215
- const tipSliders = _chunk3KNQ2W6Xcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
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");
216
216
  add("shape", "Shape", [
217
217
  !refused.has("tip.shape") && choice("tip.shape", "Tip", options(profile.tipShapes.filter((s) => !isTool || s !== "stamp"), SHAPE_LABELS)),
218
218
  ...tipSliders.map((c) => slider(c)),
219
219
  engine === "dab" && choice("tip.blend", "Blend", _chunk2VX55NFMcjs.BLEND_MODES.map((m) => ({ value: m.id, label: m.label })), "normal"),
220
220
  ...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" ? _chunkEU2ZZA6Lcjs.MAX_DOT_TEXTURES : _chunkEU2ZZA6Lcjs.MAX_STICKER_STAMPS, options: marks === "objects" ? STAMP_OPTIONS : [...STAMP_OPTIONS, ...sourceOptions] })
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
222
  ]);
223
223
  const dabs = DAB_ENGINES.has(engine) && engineOk && shape !== "bristle" && marks !== "particles" && marks !== "objects";
224
224
  const grain = brush.tip.grain;
225
225
  if (dabs && full(_nullishCoalesce(profile.tipGrain, () => ( "none")))) {
226
226
  add("grain", "Tip grain", [
227
- choice("tip.grain.source", "Texture", [{ value: "", label: "None" }, ...options(_chunkEU2ZZA6Lcjs.TIP_GRAIN_PATTERNS), ...sourceOptions], ""),
228
- !!grain && choice("tip.grain.mode", "Grain moves", options(_chunkEU2ZZA6Lcjs.BRUSH_GRAIN_MODES, GRAIN_MODE_LABELS), "texturised"),
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"),
229
229
  !!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
230
  !!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
231
  !!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,28 +238,28 @@ function brushEditorSections(brush, profile = _chunkEU2ZZA6Lcjs.PAINT_PROFILE, c
238
238
  const render = value("marks.render");
239
239
  add("marks", "Marks", [
240
240
  choice("marks.kind", "Laid as", options(profile.marks, MARKS_LABELS), "continuous"),
241
- marks === "particles" && choice("marks.physics", "Particles", options(_chunkEU2ZZA6Lcjs.PARTICLE_KINDS, PHYSICS_LABELS)),
242
- marks === "particles" && choice("marks.render", "Drawn as", options(_chunkEU2ZZA6Lcjs.PARTICLE_RENDERS, RENDER_LABELS)),
243
- marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunkEU2ZZA6Lcjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
244
- marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunkEU2ZZA6Lcjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
245
- marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunkEU2ZZA6Lcjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
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" })),
246
246
  ...particles.map((c) => slider(c)),
247
247
  ...objects.map((c) => slider(c))
248
248
  ]);
249
249
  }
250
- const feel = _chunk3KNQ2W6Xcjs.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)));
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
251
  const stampDabs = dabs && shape === "stamp";
252
252
  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
253
  add("feel", "Feel", [
254
254
  ...feel.map((c) => slider(c)),
255
255
  toggle("dynamics.pressureSize", "Pressure \u2192 size"),
256
256
  toggle("dynamics.pressureOpacity", "Pressure \u2192 opacity"),
257
- choice("dynamics.rotation", "Rotation", options(_chunkEU2ZZA6Lcjs.BRUSH_ROTATIONS, ROTATION_LABELS)),
257
+ choice("dynamics.rotation", "Rotation", options(_chunkGHGBIAWQcjs.BRUSH_ROTATIONS, ROTATION_LABELS)),
258
258
  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
259
  stampDabs && jitter("dynamics.scatter", "Scatter", 4),
260
260
  stampDabs && jitter("dynamics.angleJitter", "Rotation jitter"),
261
261
  stampDabs && jitter("dynamics.sizeJitter", "Size jitter"),
262
- stampDabs && choice("dynamics.flip", "Flip", options(_chunkEU2ZZA6Lcjs.BRUSH_FLIPS, FLIP_LABELS), "none")
262
+ stampDabs && choice("dynamics.flip", "Flip", options(_chunkGHGBIAWQcjs.BRUSH_FLIPS, FLIP_LABELS), "none")
263
263
  ]);
264
264
  const surfaces = profile.surfaces;
265
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");
@@ -267,8 +267,8 @@ function brushEditorSections(brush, profile = _chunkEU2ZZA6Lcjs.PAINT_PROFILE, c
267
267
  add("behaviour", _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _17 => _17.title]), () => ( "Behaviour")), [
268
268
  !isTool && surfaces.length > 1 && !refused.has("behaviour.surface") && choice("behaviour.surface", "Surface", options(surfaces, SURFACE_LABELS), "dry"),
269
269
  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(_chunkEU2ZZA6Lcjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
271
- engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(_chunkEU2ZZA6Lcjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
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"),
272
272
  ...engineSliders.map((c) => exchangeOk(facetOf(c.path)) ? slider(c) : null),
273
273
  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
274
  engineOk && _optionalChain([engineControls, 'optionalAccess', _19 => _19.dirty]) && exchangeFull && fieldOf("behaviour.exchange.dirty") && toggle("behaviour.exchange.dirty", "Dirty brush"),
@@ -296,7 +296,7 @@ function brushEditorSections(brush, profile = _chunkEU2ZZA6Lcjs.PAINT_PROFILE, c
296
296
  label: "Palette",
297
297
  ariaLabel: "Brush palette",
298
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: _chunkEU2ZZA6Lcjs.MAX_BRUSH_PALETTE
299
+ max: _chunkGHGBIAWQcjs.MAX_BRUSH_PALETTE
300
300
  }),
301
301
  toggle("colour.own", "Always its own colour")
302
302
  ]);
@@ -327,6 +327,8 @@ function hiddenLabel(issue, b) {
327
327
  return "several dabs per step";
328
328
  case "light":
329
329
  return "light";
330
+ case "ghost":
331
+ return "ghost paint";
330
332
  case "motion":
331
333
  return "motion";
332
334
  case "dynamics.velocity":
@@ -334,15 +336,15 @@ function hiddenLabel(issue, b) {
334
336
  case "dynamics.tilt":
335
337
  return "tilt dynamics";
336
338
  case "colour.default":
337
- return `a ${_chunkEU2ZZA6Lcjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
339
+ return `a ${_chunkGHGBIAWQcjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
338
340
  default:
339
341
  return null;
340
342
  }
341
343
  }
342
344
  var sentence = (words) => words.length < 2 ? _nullishCoalesce(words[0], () => ( "")) : `${words.slice(0, -1).join(", ")} and ${words.at(-1)}`;
343
- function brushEditorScope(brush, profile = _chunkEU2ZZA6Lcjs.PAINT_PROFILE) {
345
+ function brushEditorScope(brush, profile = _chunkGHGBIAWQcjs.PAINT_PROFILE) {
344
346
  const hidden = [];
345
- for (const issue of _chunkEU2ZZA6Lcjs.checkBrush.call(void 0, brush, profile).issues) {
347
+ for (const issue of _chunkGHGBIAWQcjs.checkBrush.call(void 0, brush, profile).issues) {
346
348
  const label = hiddenLabel(issue, brush);
347
349
  if (label && !hidden.some((h) => h.label === label)) hidden.push({ facet: issue.facet, label });
348
350
  }
@@ -355,17 +357,17 @@ function newBrushFor(profile, from, name = "New brush") {
355
357
  const id = brushIdFromName(name);
356
358
  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] } };
357
359
  if (from) {
358
- const stripped = _chunkEU2ZZA6Lcjs.degrade.call(void 0, from, profile, { ignored: true });
360
+ const stripped = _chunkGHGBIAWQcjs.degrade.call(void 0, from, profile, { ignored: true });
359
361
  if (!stripped.issues.length) return { ...stripped.brush, id, name };
360
362
  }
361
363
  return base;
362
364
  }
363
365
  async function saveBrushEdit(library, options2) {
364
366
  const { original, profile } = options2;
365
- const check = _chunkEU2ZZA6Lcjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
367
+ const check = _chunkGHGBIAWQcjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
366
368
  if (!check.ok) {
367
369
  const errors = check.issues.filter((i) => i.severity === "error").map((i) => `${i.facet}: ${i.reason} ${i.fix}`);
368
- throw new (0, _chunkEU2ZZA6Lcjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
370
+ throw new (0, _chunkGHGBIAWQcjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
369
371
  }
370
372
  const inPlace = !!original && options2.name === void 0 && !library.isBuiltin(original.id) && original.id === options2.brush.id && !!await library.get(original.id);
371
373
  let brush = options2.brush;
@@ -387,6 +389,7 @@ function setBrushEditorValue(brush, path, value) {
387
389
  delete next.variety;
388
390
  delete next.marks;
389
391
  delete next.light;
392
+ delete next.ghost;
390
393
  delete next.colour;
391
394
  next.tool = _nullishCoalesce(next.tool, () => ( "eraser"));
392
395
  if (next.tip.shape === "stamp") next.tip = { shape: "round", ...next.tip.size !== void 0 ? { size: next.tip.size } : {} };
@@ -403,13 +406,13 @@ function setBrushEditorValue(brush, path, value) {
403
406
  if (value !== "bristle") delete next.tip.bristle;
404
407
  } else if (value === void 0 || value === "") {
405
408
  const keys = path.split(".");
406
- const parent = _chunkEU2ZZA6Lcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
409
+ const parent = _chunkGHGBIAWQcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
407
410
  if (keys.length === 1) delete next[keys[0]];
408
411
  else if (parent) delete parent[keys[keys.length - 1]];
409
- } else _chunkEU2ZZA6Lcjs.setPath.call(void 0, next, path, value);
412
+ } else _chunkGHGBIAWQcjs.setPath.call(void 0, next, path, value);
410
413
  const problems = [];
411
414
  try {
412
- return { brush: _chunkEU2ZZA6Lcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
415
+ return { brush: _chunkGHGBIAWQcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
413
416
  } catch (e) {
414
417
  return { brush, problems: [e.message] };
415
418
  }
@@ -425,7 +428,7 @@ function brushLibraryGroups(entries, filter = {}) {
425
428
  const text = words([b.id, b.name, _nullishCoalesce(b.variety, () => ( "")), _nullishCoalesce(b.medium, () => ( "")), _nullishCoalesce(b.tool, () => ( "")), ..._nullishCoalesce(b.tags, () => ( []))].join(" "));
426
429
  if (!wanted.every((w) => text.some((t) => t.startsWith(w)))) continue;
427
430
  }
428
- if (filter.profile && !_chunkEU2ZZA6Lcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
431
+ if (filter.profile && !_chunkGHGBIAWQcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
429
432
  const id = b.kind === "tool" ? "tools" : _nullishCoalesce(b.medium, () => ( "other"));
430
433
  let g = groups.get(id);
431
434
  if (!g) groups.set(id, g = { id, title: id === "tools" ? "Tools" : id === "other" ? "Other" : MEDIUM_LABELS[id], varieties: [] });
@@ -441,7 +444,7 @@ async function imageFileToPngDataUrl(file) {
441
444
  const bytes = new Uint8Array(await file.arrayBuffer());
442
445
  if (_chunkW5M3J7PVcjs.isPng.call(void 0, bytes)) return `data:image/png;base64,${_chunkW5M3J7PVcjs.bytesToBase64.call(void 0, bytes)}`;
443
446
  const g = globalThis;
444
- if (!g.createImageBitmap || !g.OffscreenCanvas) throw new (0, _chunkEU2ZZA6Lcjs.BrushSourceError)("Only PNG images can be read here; convert the image to PNG.");
447
+ if (!g.createImageBitmap || !g.OffscreenCanvas) throw new (0, _chunkGHGBIAWQcjs.BrushSourceError)("Only PNG images can be read here; convert the image to PNG.");
445
448
  const bitmap = await g.createImageBitmap(file);
446
449
  const canvas = new g.OffscreenCanvas(bitmap.width, bitmap.height);
447
450
  canvas.getContext("2d").drawImage(bitmap, 0, 0);
@@ -451,7 +454,7 @@ async function imageFileToPngDataUrl(file) {
451
454
  async function addBrushSourceFromFile(library, file, options2 = {}) {
452
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";
453
456
  const result = await library.addSource({ name, image: await imageFileToPngDataUrl(file), origin: file.name, ...options2.channel ? { channel: options2.channel } : {} });
454
- return { ...result, ref: _chunkEU2ZZA6Lcjs.brushSourceRef.call(void 0, result.source.id) };
457
+ return { ...result, ref: _chunkGHGBIAWQcjs.brushSourceRef.call(void 0, result.source.id) };
455
458
  }
456
459
  function withBrushSource(brush, ref, as) {
457
460
  if (as === "grain") return setBrushEditorValue(brush, "tip.grain.source", ref);
@@ -469,11 +472,11 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
469
472
  properties: {
470
473
  id: { type: "string", description: "paint, image, canvas, vector\u2026" },
471
474
  name: { type: "string", description: "Display name, used in messages." },
472
- kinds: { type: "array", items: { type: "string", enum: [..._chunkEU2ZZA6Lcjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
473
- tools: { type: "array", items: { type: "string", enum: [..._chunkEU2ZZA6Lcjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
474
- tipShapes: { type: "array", items: { type: "string", enum: [..._chunkEU2ZZA6Lcjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
475
- marks: { type: "array", items: { type: "string", enum: [..._chunkEU2ZZA6Lcjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
476
- surfaces: { type: "array", items: { type: "string", enum: [..._chunkEU2ZZA6Lcjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
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." },
477
480
  exchange: { ...SUPPORT, description: "Picking paint up and mixing it in." },
478
481
  reservoir: { ...SUPPORT, description: "The Mixer Brush reservoir." },
479
482
  grain: { ...SUPPORT, description: "Paper grain response." },
@@ -497,16 +500,16 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
497
500
  brushes: { type: "array", items: { $ref: "brush.schema.json" }, description: "The brushes, each a facet brush (brush.schema.json)." },
498
501
  sources: {
499
502
  type: "array",
500
- maxItems: _chunkEU2ZZA6Lcjs.MAX_BRUSH_SOURCES,
503
+ maxItems: _chunkGHGBIAWQcjs.MAX_BRUSH_SOURCES,
501
504
  description: "The image sources the brushes name (source:<id> in tip.stamps or tip.grain.source), bytes included.",
502
505
  items: {
503
506
  type: "object",
504
507
  description: "An image source: a grey mask, 255 paints (or is a grain peak).",
505
508
  properties: {
506
- id: { type: "string", pattern: _chunkEU2ZZA6Lcjs.BRUSH_ID.source, description: "Source id." },
509
+ id: { type: "string", pattern: _chunkGHGBIAWQcjs.BRUSH_ID.source, description: "Source id." },
507
510
  name: { type: "string", maxLength: 80, description: "Display name." },
508
- width: { type: "integer", minimum: 1, maximum: _chunkEU2ZZA6Lcjs.MAX_BRUSH_SOURCE_SIZE, description: "Width in px." },
509
- height: { type: "integer", minimum: 1, maximum: _chunkEU2ZZA6Lcjs.MAX_BRUSH_SOURCE_SIZE, description: "Height in px." },
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." },
510
513
  image: { type: "string", pattern: "^data:image/png;base64,", description: "The mask as a greyscale PNG data: URL." },
511
514
  licence: { type: "string", maxLength: 2e3, description: "The licence or terms it came with." },
512
515
  origin: { type: "string", maxLength: 200, description: "Where it came from (a file or pack name)." }
@@ -520,7 +523,7 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
520
523
  additionalProperties: false
521
524
  };
522
525
  function migrationInputs() {
523
- const pick = (id) => _chunkEU2ZZA6Lcjs.brushToJSON.call(void 0, _chunkEU2ZZA6Lcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
526
+ const pick = (id) => _chunkGHGBIAWQcjs.brushToJSON.call(void 0, _chunkGHGBIAWQcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
524
527
  return [
525
528
  { id: "plain", name: "Plain" },
526
529
  pick("pencil-6b"),
@@ -542,34 +545,34 @@ function migrationInputs() {
542
545
  function editorSectionFixtures() {
543
546
  const ids = ["highlighter", "chalk", "watercolor-wash", "hair-strands", "mixer-brush", "blender", "spray-can"];
544
547
  return ids.flatMap(
545
- (id) => Object.keys(_chunkEU2ZZA6Lcjs.BRUSH_HOST_PROFILES).map((host) => {
546
- const brush = _chunkEU2ZZA6Lcjs.BRUSH_PRESETS.find((b) => b.id === id);
547
- return { brush: id, host, sections: brushEditorSections(brush, _chunkEU2ZZA6Lcjs.BRUSH_HOST_PROFILES[host]) };
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]) };
548
551
  })
549
552
  );
550
553
  }
551
554
  function toolDefinitions() {
552
- const library = _chunkEU2ZZA6Lcjs.createBrushLibrary.call(void 0, );
553
- const toolsFor = (host) => _chunk3KNQ2W6Xcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunkEU2ZZA6Lcjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
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" }) });
554
557
  return {
555
558
  tools: toolsFor("paint").map((t) => ({ name: t.name, title: t.title, description: t.description, inputSchema: t.inputSchema, annotations: t.annotations })),
556
- hosts: Object.fromEntries(Object.keys(_chunkEU2ZZA6Lcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
559
+ hosts: Object.fromEntries(Object.keys(_chunkGHGBIAWQcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
557
560
  };
558
561
  }
559
562
  function brushContracts() {
560
- const presets = _chunkEU2ZZA6Lcjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
561
- const resolved = _chunkEU2ZZA6Lcjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunkEU2ZZA6Lcjs.resolveEngine.call(void 0, b), category: _chunkEU2ZZA6Lcjs.resolveCategory.call(void 0, b), brush: _chunkEU2ZZA6Lcjs.brushToJSON.call(void 0, _chunkEU2ZZA6Lcjs.resolveBrush.call(void 0, b)) }));
562
- const profiles = Object.values(_chunkEU2ZZA6Lcjs.BRUSH_HOST_PROFILES);
563
- const checks = _chunkEU2ZZA6Lcjs.BRUSH_PRESETS.map((b) => ({
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) => ({
564
567
  id: b.id,
565
568
  hosts: Object.fromEntries(profiles.map((p) => {
566
- const c = _chunkEU2ZZA6Lcjs.checkBrush.call(void 0, b, p);
569
+ const c = _chunkGHGBIAWQcjs.checkBrush.call(void 0, b, p);
567
570
  return [p.id, { ok: c.ok, issues: c.issues.map(({ facet, severity }) => ({ facet, severity })) }];
568
571
  }))
569
572
  }));
570
- const migrations = migrationInputs().map((input) => ({ input, output: _chunkEU2ZZA6Lcjs.migrateBrushV1.call(void 0, input), resolved: _chunkEU2ZZA6Lcjs.brushToJSON.call(void 0, _chunkEU2ZZA6Lcjs.resolveBrush.call(void 0, _chunkEU2ZZA6Lcjs.migrateBrushV1.call(void 0, input))), engine: _chunkEU2ZZA6Lcjs.normalizePaintBrush.call(void 0, input).engine }));
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 }));
571
574
  const files = {
572
- "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkEU2ZZA6Lcjs.BRUSH_JSON_SCHEMA },
575
+ "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkGHGBIAWQcjs.BRUSH_JSON_SCHEMA },
573
576
  "profile.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "profile.schema.json", ...BRUSH_PROFILE_JSON_SCHEMA },
574
577
  "library-file.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "library-file.schema.json", ...BRUSH_LIBRARY_FILE_JSON_SCHEMA },
575
578
  "presets.json": presets,
@@ -583,7 +586,7 @@ function brushContracts() {
583
586
  files["manifest.json"] = {
584
587
  domain: "brushes",
585
588
  formatVersion: BRUSH_CONTRACT_FORMAT_VERSION,
586
- limits: { maxPalette: _chunkEU2ZZA6Lcjs.MAX_BRUSH_PALETTE },
589
+ limits: { maxPalette: _chunkGHGBIAWQcjs.MAX_BRUSH_PALETTE },
587
590
  counts: { presets: presets.length, profiles: profiles.length, migrations: migrations.length, editorSections: files["editor-sections.json"].length },
588
591
  files: Object.keys(files).sort()
589
592
  };
@@ -683,4 +686,4 @@ function brushContracts() {
683
686
 
684
687
 
685
688
 
686
- exports.AbrError = _chunk3KNQ2W6Xcjs.AbrError; exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunkEU2ZZA6Lcjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_FLIPS = _chunkEU2ZZA6Lcjs.BRUSH_FLIPS; exports.BRUSH_GRAIN_MODES = _chunkEU2ZZA6Lcjs.BRUSH_GRAIN_MODES; exports.BRUSH_GRAIN_SOURCE_PATTERN = _chunkEU2ZZA6Lcjs.BRUSH_GRAIN_SOURCE_PATTERN; exports.BRUSH_HOST_PROFILES = _chunkEU2ZZA6Lcjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunkEU2ZZA6Lcjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunkEU2ZZA6Lcjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunkEU2ZZA6Lcjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunkEU2ZZA6Lcjs.BRUSH_MEDIA; exports.BRUSH_PACK_FORMATS = _chunk3KNQ2W6Xcjs.BRUSH_PACK_FORMATS; exports.BRUSH_PATCH_PROPERTIES = _chunk3KNQ2W6Xcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunkEU2ZZA6Lcjs.BRUSH_PRESETS; exports.BRUSH_PREVIEW_DARK_PAPER = _chunkBPJSI4NTcjs.BRUSH_PREVIEW_DARK_PAPER; exports.BRUSH_PREVIEW_FALLBACKS = _chunkBPJSI4NTcjs.BRUSH_PREVIEW_FALLBACKS; exports.BRUSH_PREVIEW_MIN_CONTRAST = _chunkBPJSI4NTcjs.BRUSH_PREVIEW_MIN_CONTRAST; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SOURCE_CHANNELS = _chunkEU2ZZA6Lcjs.BRUSH_SOURCE_CHANNELS; exports.BRUSH_SOURCE_PROVIDER = _chunkEU2ZZA6Lcjs.BRUSH_SOURCE_PROVIDER; exports.BRUSH_SURFACES = _chunkEU2ZZA6Lcjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunkEU2ZZA6Lcjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunkEU2ZZA6Lcjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunk3KNQ2W6Xcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunkEU2ZZA6Lcjs.BRUSH_WORD; exports.BrushLibraryError = _chunkEU2ZZA6Lcjs.BrushLibraryError; exports.BrushPackError = _chunk3KNQ2W6Xcjs.BrushPackError; exports.BrushSourceError = _chunkEU2ZZA6Lcjs.BrushSourceError; exports.CANVAS_PROFILE = _chunkEU2ZZA6Lcjs.CANVAS_PROFILE; exports.IMAGE_PROFILE = _chunkEU2ZZA6Lcjs.IMAGE_PROFILE; exports.MAX_BRUSH_PACK_BYTES = _chunk3KNQ2W6Xcjs.MAX_BRUSH_PACK_BYTES; exports.MAX_BRUSH_PALETTE = _chunkEU2ZZA6Lcjs.MAX_BRUSH_PALETTE; exports.MAX_BRUSH_SOURCES = _chunkEU2ZZA6Lcjs.MAX_BRUSH_SOURCES; exports.MAX_BRUSH_SOURCE_INPUT_PIXELS = _chunkEU2ZZA6Lcjs.MAX_BRUSH_SOURCE_INPUT_PIXELS; exports.MAX_BRUSH_SOURCE_SIZE = _chunkEU2ZZA6Lcjs.MAX_BRUSH_SOURCE_SIZE; exports.MAX_PACK_BRUSHES = _chunk3KNQ2W6Xcjs.MAX_PACK_BRUSHES; exports.PAINT_PROFILE = _chunkEU2ZZA6Lcjs.PAINT_PROFILE; exports.TIP_GRAIN_PATTERNS = _chunkEU2ZZA6Lcjs.TIP_GRAIN_PATTERNS; exports.UNSETTABLE_BRUSH_FACETS = _chunk3KNQ2W6Xcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunkEU2ZZA6Lcjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunkEU2ZZA6Lcjs.WET_BRUSH_TOOLS; exports.addBrushSourceFromFile = addBrushSourceFromFile; exports.brushColourHex = _chunkJBZRVLXVcjs.brushColourHex; exports.brushColourKind = _chunkEU2ZZA6Lcjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorScope = brushEditorScope; exports.brushEditorSections = brushEditorSections; exports.brushIdFromName = brushIdFromName; exports.brushLibraryGroups = brushLibraryGroups; exports.brushPackFormat = _chunk3KNQ2W6Xcjs.brushPackFormat; exports.brushPreviewColours = _chunkBPJSI4NTcjs.brushPreviewColours; exports.brushPreviewStrength = _chunkBPJSI4NTcjs.brushPreviewStrength; exports.brushPreviewsOnDark = _chunkBPJSI4NTcjs.brushPreviewsOnDark; exports.brushSourceFromMask = _chunkEU2ZZA6Lcjs.brushSourceFromMask; exports.brushSourceIdFromName = _chunkEU2ZZA6Lcjs.brushSourceIdFromName; exports.brushSourceIdOf = _chunkEU2ZZA6Lcjs.brushSourceIdOf; exports.brushSourceIds = _chunkEU2ZZA6Lcjs.brushSourceIds; exports.brushSourceRef = _chunkEU2ZZA6Lcjs.brushSourceRef; exports.changedBrushPaths = _chunk3KNQ2W6Xcjs.changedBrushPaths; exports.checkBrush = _chunkEU2ZZA6Lcjs.checkBrush; exports.checkBrushEdit = _chunkEU2ZZA6Lcjs.checkBrushEdit; exports.createBrushLibrary = _chunkEU2ZZA6Lcjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunk3KNQ2W6Xcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunk3KNQ2W6Xcjs.createBrushLibraryTools; exports.decodeBrushSource = _chunkEU2ZZA6Lcjs.decodeBrushSource; exports.degrade = _chunkEU2ZZA6Lcjs.degrade; exports.imageFileToPngDataUrl = imageFileToPngDataUrl; exports.importBrushFile = _chunk3KNQ2W6Xcjs.importBrushFile; exports.importBrushPack = _chunk3KNQ2W6Xcjs.importBrushPack; exports.isBrushLibrary = _chunkEU2ZZA6Lcjs.isBrushLibrary; exports.isBrushSourceRef = _chunkEU2ZZA6Lcjs.isBrushSourceRef; exports.listPresets = _chunkEU2ZZA6Lcjs.listPresets; exports.makeBrushSource = _chunkEU2ZZA6Lcjs.makeBrushSource; exports.mergeBrushPatch = _chunk3KNQ2W6Xcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunkEU2ZZA6Lcjs.migrateBrushV1; exports.newBrushFor = newBrushFor; exports.normalizeBrushSpec = _chunkEU2ZZA6Lcjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunkEU2ZZA6Lcjs.parseBrushLibrary2; exports.parseBrushLibrarySources = _chunkEU2ZZA6Lcjs.parseBrushLibrarySources; exports.readAbr = _chunk3KNQ2W6Xcjs.readAbr; exports.readBrushPack = _chunk3KNQ2W6Xcjs.readBrushPack; exports.readBrushSource = _chunkEU2ZZA6Lcjs.readBrushSource; exports.resolveBrush = _chunkEU2ZZA6Lcjs.resolveBrush; exports.resolveCategory = _chunkEU2ZZA6Lcjs.resolveCategory; exports.resolveEngine = _chunkEU2ZZA6Lcjs.resolveEngine; exports.resolveWetMedium = _chunkEU2ZZA6Lcjs.resolveWetMedium; exports.saveBrushEdit = saveBrushEdit; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunkEU2ZZA6Lcjs.snapshotBrushLibrary; exports.summarizeBrushSource = _chunkEU2ZZA6Lcjs.summarizeBrushSource; exports.withBrushSource = withBrushSource; exports.withKeptIssues = _chunkEU2ZZA6Lcjs.withKeptIssues;
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;
@@ -18,7 +18,7 @@ import {
18
18
  mergeBrushPatch,
19
19
  readAbr,
20
20
  readBrushPack
21
- } from "../chunk-ININNHLM.js";
21
+ } from "../chunk-NAHJV3O6.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-LETF75CA.js";
30
+ } from "../chunk-CLB2I2FU.js";
31
31
  import {
32
32
  BRUSH_FACET_SCHEMAS,
33
33
  BRUSH_FIELDS,
@@ -101,7 +101,7 @@ import {
101
101
  snapshotBrushLibrary,
102
102
  summarizeBrushSource,
103
103
  withKeptIssues
104
- } from "../chunk-KZI3YWKW.js";
104
+ } from "../chunk-UXYCY3HP.js";
105
105
  import {
106
106
  STAMP_KINDS
107
107
  } from "../chunk-JL6YH5WD.js";
@@ -327,6 +327,8 @@ function hiddenLabel(issue, b) {
327
327
  return "several dabs per step";
328
328
  case "light":
329
329
  return "light";
330
+ case "ghost":
331
+ return "ghost paint";
330
332
  case "motion":
331
333
  return "motion";
332
334
  case "dynamics.velocity":
@@ -387,6 +389,7 @@ function setBrushEditorValue(brush, path, value) {
387
389
  delete next.variety;
388
390
  delete next.marks;
389
391
  delete next.light;
392
+ delete next.ghost;
390
393
  delete next.colour;
391
394
  next.tool = next.tool ?? "eraser";
392
395
  if (next.tip.shape === "stamp") next.tip = { shape: "round", ...next.tip.size !== void 0 ? { size: next.tip.size } : {} };
@@ -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", "motion", "colour"];
16
+ export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "ghost", "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", "motion", "colour"];
16
+ export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "ghost", "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;
@@ -28,6 +28,7 @@ export declare const BRUSH_FACET_SCHEMAS: {
28
28
  readonly dynamics: JsonSchema;
29
29
  readonly behaviour: JsonSchema;
30
30
  readonly light: JsonSchema;
31
+ readonly ghost: JsonSchema;
31
32
  readonly motion: JsonSchema;
32
33
  readonly colour: JsonSchema;
33
34
  readonly paint: JsonSchema;
@@ -28,6 +28,7 @@ export declare const BRUSH_FACET_SCHEMAS: {
28
28
  readonly dynamics: JsonSchema;
29
29
  readonly behaviour: JsonSchema;
30
30
  readonly light: JsonSchema;
31
+ readonly ghost: JsonSchema;
31
32
  readonly motion: JsonSchema;
32
33
  readonly colour: JsonSchema;
33
34
  readonly paint: JsonSchema;
@@ -310,6 +310,13 @@ export interface BrushLight {
310
310
  /** Suggest a glow layer effect for the brush's layer (glow stays a layer effect). */
311
311
  glow?: boolean;
312
312
  }
313
+ /** Ghost paint: wet paint whose colour fades away after `linger` seconds, leaving only what it smeared. */
314
+ export interface BrushGhost {
315
+ /** Seconds of simulated time before the ghost paint has fully faded, 0.5..60 (default 4). */
316
+ linger?: number;
317
+ /** How much the ghost paint drags and lifts the paint it passes through, 0..1 (default 0.3). */
318
+ smear?: number;
319
+ }
313
320
  /** Animation after painting. */
314
321
  export interface BrushMotion {
315
322
  /** Effect paint keeps playing on stroke layers. */
@@ -356,6 +363,7 @@ export interface Brush {
356
363
  dynamics?: BrushDynamics;
357
364
  behaviour?: BrushBehaviour;
358
365
  light?: BrushLight;
366
+ ghost?: BrushGhost;
359
367
  motion?: BrushMotion;
360
368
  colour?: BrushColour;
361
369
  }
@@ -310,6 +310,13 @@ export interface BrushLight {
310
310
  /** Suggest a glow layer effect for the brush's layer (glow stays a layer effect). */
311
311
  glow?: boolean;
312
312
  }
313
+ /** Ghost paint: wet paint whose colour fades away after `linger` seconds, leaving only what it smeared. */
314
+ export interface BrushGhost {
315
+ /** Seconds of simulated time before the ghost paint has fully faded, 0.5..60 (default 4). */
316
+ linger?: number;
317
+ /** How much the ghost paint drags and lifts the paint it passes through, 0..1 (default 0.3). */
318
+ smear?: number;
319
+ }
313
320
  /** Animation after painting. */
314
321
  export interface BrushMotion {
315
322
  /** Effect paint keeps playing on stroke layers. */
@@ -356,6 +363,7 @@ export interface Brush {
356
363
  dynamics?: BrushDynamics;
357
364
  behaviour?: BrushBehaviour;
358
365
  light?: BrushLight;
366
+ ghost?: BrushGhost;
359
367
  motion?: BrushMotion;
360
368
  colour?: BrushColour;
361
369
  }