@pixerate/editor 0.266.2 → 0.267.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 (111) hide show
  1. package/dist/agent/index.cjs +2 -2
  2. package/dist/agent/index.js +1 -1
  3. package/dist/animation-editor/controller.d.cts +8 -0
  4. package/dist/animation-editor/controller.d.ts +8 -0
  5. package/dist/animation-editor/effect-tools.d.cts +1 -1
  6. package/dist/animation-editor/effect-tools.d.ts +1 -1
  7. package/dist/animation-editor/index.cjs +172 -105
  8. package/dist/animation-editor/index.js +91 -24
  9. package/dist/brushes/index.cjs +59 -59
  10. package/dist/brushes/index.js +5 -5
  11. package/dist/brushes/profiles.d.cts +6 -1
  12. package/dist/brushes/profiles.d.ts +6 -1
  13. package/dist/{brushstrokeRender-FSUWXUZY.cjs → brushstrokeRender-L7JYRR2R.cjs} +16 -16
  14. package/dist/{brushstrokeRender-KD453OBX.js → brushstrokeRender-NLFPEBGI.js} +4 -4
  15. package/dist/canvas/brushTypes.d.cts +12 -0
  16. package/dist/canvas/brushTypes.d.ts +12 -0
  17. package/dist/canvas/brushstroke.d.cts +1 -1
  18. package/dist/canvas/brushstroke.d.ts +1 -1
  19. package/dist/canvas/drawController.d.cts +19 -4
  20. package/dist/canvas/drawController.d.ts +19 -4
  21. package/dist/canvas/index.cjs +144 -105
  22. package/dist/canvas/index.js +46 -7
  23. package/dist/{chunk-XORJ7UZO.cjs → chunk-3VHH6V67.cjs} +13 -12
  24. package/dist/{chunk-T2LDTEXK.js → chunk-4IDUYB45.js} +2217 -56
  25. package/dist/chunk-7UKFXXWL.js +802 -0
  26. package/dist/chunk-ADMRNWR7.js +340 -0
  27. package/dist/{chunk-CIJBSUM5.js → chunk-AGNUD5BI.js} +2 -2
  28. package/dist/{chunk-WLUVZKVD.cjs → chunk-DT4YQUGT.cjs} +32 -32
  29. package/dist/{chunk-DXYHQ2VN.js → chunk-EF7LZAXQ.js} +1 -1
  30. package/dist/chunk-EXB2EGBE.cjs +802 -0
  31. package/dist/{chunk-4ODRXQRW.js → chunk-EYSHTYLG.js} +1 -1
  32. package/dist/{chunk-R44Y3EFS.js → chunk-FGJHJIMN.js} +8 -336
  33. package/dist/{chunk-AQZQWXEU.cjs → chunk-G7NHE2VD.cjs} +35 -35
  34. package/dist/{chunk-XC6DPRYI.js → chunk-GSTSZPSR.js} +154 -949
  35. package/dist/{chunk-VRK322ZC.cjs → chunk-HIO6E7LC.cjs} +2 -2
  36. package/dist/{chunk-TOID45I2.cjs → chunk-J2TNIZ55.cjs} +1 -1
  37. package/dist/{chunk-YHDHFJUC.cjs → chunk-J5VQYK7T.cjs} +217 -1012
  38. package/dist/{chunk-3C33YTNN.js → chunk-JGWVZPT6.js} +2 -2
  39. package/dist/{chunk-ACFSFUQH.js → chunk-JL6YH5WD.js} +4 -0
  40. package/dist/{chunk-3SBLVGOM.cjs → chunk-LA5Y4ETA.cjs} +23 -23
  41. package/dist/{chunk-MVUQSK5J.cjs → chunk-LHPEG5AU.cjs} +107 -435
  42. package/dist/{chunk-DOZ6F2K2.js → chunk-NSETJI74.js} +3 -2
  43. package/dist/{chunk-XRXFVRGY.cjs → chunk-OKHKA43L.cjs} +2364 -203
  44. package/dist/{chunk-LK4SXL3V.js → chunk-OSEXT7JL.js} +1 -1
  45. package/dist/{chunk-PE6YJMQT.cjs → chunk-PFHJS4HE.cjs} +20 -19
  46. package/dist/{chunk-7KNW3WXZ.cjs → chunk-QEVLRLUN.cjs} +63 -0
  47. package/dist/{chunk-OTN6VB5S.cjs → chunk-RDFHWAHL.cjs} +5 -1
  48. package/dist/{chunk-6JL2D5SG.js → chunk-VE6UKYQ2.js} +3 -2
  49. package/dist/{chunk-RFJZGTHA.cjs → chunk-XVOP3CGQ.cjs} +9 -9
  50. package/dist/{chunk-EZOJBP4D.js → chunk-YIC6MAJ2.js} +1 -1
  51. package/dist/chunk-YZWM6ZIP.cjs +340 -0
  52. package/dist/{chunk-472INMWH.js → chunk-ZA7L5YJB.js} +63 -0
  53. package/dist/commands/builtins.d.cts +12 -1
  54. package/dist/commands/builtins.d.ts +12 -1
  55. package/dist/commands/index.cjs +2 -2
  56. package/dist/commands/index.js +1 -1
  57. package/dist/image-editor/controller.d.cts +1 -1
  58. package/dist/image-editor/controller.d.ts +1 -1
  59. package/dist/image-editor/index.cjs +837 -833
  60. package/dist/image-editor/index.js +105 -101
  61. package/dist/paint/index.cjs +5 -3
  62. package/dist/paint/index.js +46 -44
  63. package/dist/paint-editor/controller.d.cts +5 -3
  64. package/dist/paint-editor/controller.d.ts +5 -3
  65. package/dist/paint-editor/index.cjs +832 -2295
  66. package/dist/paint-editor/index.js +285 -1748
  67. package/dist/paint-editor/path-samples.d.cts +2 -0
  68. package/dist/paint-editor/path-samples.d.ts +2 -0
  69. package/dist/paint-editor/presence.d.cts +20 -1
  70. package/dist/paint-editor/presence.d.ts +20 -1
  71. package/dist/stickers/helpers.d.cts +2 -0
  72. package/dist/stickers/helpers.d.ts +2 -0
  73. package/dist/stickers/index.cjs +41 -35
  74. package/dist/stickers/index.js +22 -16
  75. package/dist/stickers/types.d.cts +4 -2
  76. package/dist/stickers/types.d.ts +4 -2
  77. package/dist/vector/backdrop.d.cts +13 -0
  78. package/dist/vector/backdrop.d.ts +13 -0
  79. package/dist/vector/brushstroke.d.cts +54 -7
  80. package/dist/vector/brushstroke.d.ts +54 -7
  81. package/dist/vector/brushstrokeMedia.d.cts +96 -0
  82. package/dist/vector/brushstrokeMedia.d.ts +96 -0
  83. package/dist/vector/controller.d.cts +17 -3
  84. package/dist/vector/controller.d.ts +17 -3
  85. package/dist/vector/index.cjs +1846 -1386
  86. package/dist/vector/index.d.cts +2 -0
  87. package/dist/vector/index.d.ts +2 -0
  88. package/dist/vector/index.js +517 -57
  89. package/dist/vector/render.d.cts +6 -0
  90. package/dist/vector/render.d.ts +6 -0
  91. package/dist/vector/types.d.cts +14 -0
  92. package/dist/vector/types.d.ts +14 -0
  93. package/package.json +1 -1
  94. package/skills/pixerate-animation-editor/SKILL.md +1 -0
  95. package/skills/pixerate-brushes/SKILL.md +2 -2
  96. package/skills/pixerate-brushes-design/SKILL.md +7 -4
  97. package/skills/pixerate-brushes-design/evals/port-to-vector.json +8 -8
  98. package/skills/pixerate-canvas/SKILL.md +11 -1
  99. package/skills/pixerate-image-editor/SKILL.md +19 -64
  100. package/skills/pixerate-image-editor/references/color-management.md +2 -1
  101. package/skills/pixerate-image-editor/references/free-transform.md +12 -0
  102. package/skills/pixerate-image-editor/references/layer-effects.md +10 -0
  103. package/skills/pixerate-image-editor/references/painting.md +17 -0
  104. package/skills/pixerate-image-editor/references/photoshop-files.md +1 -1
  105. package/skills/pixerate-image-editor/references/shapes-and-type.md +14 -0
  106. package/skills/pixerate-image-editor/references/smart-objects.md +10 -0
  107. package/skills/pixerate-paint-editor/SKILL.md +8 -4
  108. package/skills/pixerate-paint-editor/references/wet-media.md +9 -0
  109. package/skills/pixerate-vector/SKILL.md +16 -6
  110. package/skills/pixerate-vector/references/best-practices.md +1 -0
  111. package/skills/pixerate-vector/references/commands.md +19 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createVectorMorph
3
- } from "../chunk-LK4SXL3V.js";
3
+ } from "../chunk-OSEXT7JL.js";
4
4
  import {
5
5
  MOTION_ISSUE_CODES,
6
6
  motionIssue,
@@ -39,9 +39,9 @@ import {
39
39
  vectorNodeBounds,
40
40
  vectorPathWorldBezier,
41
41
  vectorTextHasOutlines
42
- } from "../chunk-T2LDTEXK.js";
43
- import "../chunk-CIJBSUM5.js";
44
- import "../chunk-ACFSFUQH.js";
42
+ } from "../chunk-4IDUYB45.js";
43
+ import "../chunk-AGNUD5BI.js";
44
+ import "../chunk-JL6YH5WD.js";
45
45
  import "../chunk-M6DNZNVY.js";
46
46
  import {
47
47
  bezierPathLength,
@@ -74,6 +74,7 @@ import {
74
74
  resolveEffectValues
75
75
  } from "../chunk-MV7CYFMJ.js";
76
76
  import "../chunk-V2ZCJRDM.js";
77
+ import "../chunk-GSTSZPSR.js";
77
78
  import "../chunk-TXFWZ5ZJ.js";
78
79
  import "../chunk-GCVFEPJG.js";
79
80
  import "../chunk-4D6KP5BV.js";
@@ -4901,6 +4902,25 @@ var AnimationEditorController = class {
4901
4902
  return { scene: { ...this.scene, shots }, label: `Apply ${d.name}`, instance, notes };
4902
4903
  });
4903
4904
  }
4905
+ async resolveVectorPath(artwork, d, path, controlName) {
4906
+ const controls = pathControlsOf(d);
4907
+ if (!controls.length) throw new Error(`"${d.id}" does not draw along a path. Find one that does with search_effects accepts ["path"] (kind vector).`);
4908
+ const control = controlName ?? (controls.length === 1 ? controls[0] : void 0);
4909
+ if (!control) throw new Error(`"${d.id}" has several path controls (${controls.join(", ")}); pass control.`);
4910
+ if (!controls.includes(control)) throw new Error(`"${control}" is not a path control of "${d.id}"; its path controls are ${controls.join(", ")}.`);
4911
+ if ("node" in path) {
4912
+ const entry = indexMotionNodes(artwork.nodes).get(path.node);
4913
+ if (!entry) throw new Error(`There is no node "${path.node}"; find_animation_elements lists the artwork's nodes.`);
4914
+ if (entry.node.type !== "path") throw new Error(`Node "${path.node}" is a ${entry.node.type}, not a path; pass a path node (find_animation_elements shows each node's type).`);
4915
+ const value2 = bezierPathToSvg(vectorPathWorldBezier(entry.node, entry.parentWorld, { effects: false }));
4916
+ return { control, value: value2, place: "viewBox" };
4917
+ }
4918
+ const provider = this.effects.require();
4919
+ if (!provider.pathFromText) throw new Error(`The effects provider "${provider.id}" cannot write words as a path; pass a path node instead.`);
4920
+ if (typeof path.text !== "string" || !path.text.trim()) throw new Error("text is empty; pass the words to write.");
4921
+ const value = await provider.pathFromText(path.text, { ...path.font ? { font: path.font } : {}, ...path.align ? { align: path.align } : {} });
4922
+ return { control, value };
4923
+ }
4904
4924
  /**
4905
4925
  * Adds a provider vector effect (one with its own picture: a lower third, a loader): its SVG as
4906
4926
  * an artwork group (id: the instance) fitted into `box` (default the whole artwork), and its
@@ -4912,25 +4932,9 @@ var AnimationEditorController = class {
4912
4932
  let given = options.values;
4913
4933
  let place = options.box;
4914
4934
  if (options.path) {
4915
- const controls = pathControlsOf(d);
4916
- if (!controls.length) throw new Error(`"${d.id}" does not draw along a path. Find one that does with search_effects accepts ["path"] (kind vector).`);
4917
- const control = options.control ?? (controls.length === 1 ? controls[0] : void 0);
4918
- if (!control) throw new Error(`"${d.id}" has several path controls (${controls.join(", ")}); pass control.`);
4919
- if (!controls.includes(control)) throw new Error(`"${control}" is not a path control of "${d.id}"; its path controls are ${controls.join(", ")}.`);
4920
- let value;
4921
- if ("node" in options.path) {
4922
- const entry = indexMotionNodes(this.scene.artwork.nodes).get(options.path.node);
4923
- if (!entry) throw new Error(`There is no node "${options.path.node}"; find_animation_elements lists the artwork's nodes.`);
4924
- if (entry.node.type !== "path") throw new Error(`Node "${options.path.node}" is a ${entry.node.type}, not a path; pass a path node (find_animation_elements shows each node's type).`);
4925
- value = bezierPathToSvg(vectorPathWorldBezier(entry.node, entry.parentWorld, { effects: false }));
4926
- place ??= "viewBox";
4927
- } else {
4928
- const provider = this.effects.require();
4929
- if (!provider.pathFromText) throw new Error(`The effects provider "${provider.id}" cannot write words as a path; pass a path node instead.`);
4930
- if (typeof options.path.text !== "string" || !options.path.text.trim()) throw new Error("text is empty; pass the words to write.");
4931
- value = await provider.pathFromText(options.path.text, { ...options.path.font ? { font: options.path.font } : {}, ...options.path.align ? { align: options.path.align } : {} });
4932
- }
4933
- given = { ...given ?? {}, [control]: value };
4935
+ const resolved = await this.resolveVectorPath(this.scene.artwork, d, options.path, options.control);
4936
+ if (resolved.place) place ??= resolved.place;
4937
+ given = { ...given ?? {}, [resolved.control]: resolved.value };
4934
4938
  }
4935
4939
  const values = resolveEffectValues(d, given);
4936
4940
  const instance = options.instance ?? nextMotionEffectInstance(this.scene);
@@ -4940,6 +4944,33 @@ var AnimationEditorController = class {
4940
4944
  return { scene: { ...this.scene, artwork: { ...this.scene.artwork, nodes: [...this.scene.artwork.nodes, group] }, shots: [...this.scene.shots, ...shots] }, label: `Add ${d.name}`, instance, notes };
4941
4945
  });
4942
4946
  }
4947
+ /**
4948
+ * Sets an applied vector effect's path from a path node in the artwork (landing on the node at
4949
+ * scale 1) or words written by the provider (keeping where the picture was placed). One undo step.
4950
+ */
4951
+ setVectorEffectPath(instance, path, options = {}) {
4952
+ return this.effectEdit(async () => {
4953
+ const was = motionSceneEffects(this.scene).find((e) => e.instance === instance);
4954
+ if (!was) throw new Error(`There is no applied effect "${instance}"; list_applied_effects lists them.`);
4955
+ if (was.kind !== "vector") throw new Error(`"${instance}" is a motion effect, not a vector effect.`);
4956
+ const d = await this.describeFor(was.effect, ["vector"]);
4957
+ const { scene: bare } = withoutMotionEffect(this.scene, instance);
4958
+ const { control, value, place } = await this.resolveVectorPath(bare.artwork, d, path, options.control);
4959
+ const merged = { ...was.values, [control]: value };
4960
+ const provider = this.effects.require();
4961
+ const source = { instance, effect: d.id, provider: provider.id, name: d.name, values: merged };
4962
+ const motion = await provider.applyVectorEffect(d.id, motionArtworkSvg(bare.artwork), merged);
4963
+ const { group, shots, notes } = motionPartsFromVectorEffect(bare.artwork, motion, source, place);
4964
+ const old = this.scene.artwork.nodes.find((n2) => n2.id === instance);
4965
+ const index = this.scene.artwork.nodes.findIndex((n2) => n2.id === instance);
4966
+ const nodes = [...bare.artwork.nodes];
4967
+ nodes.splice(Math.max(0, index), 0, !place && old?.transform ? { ...group, transform: old.transform } : group);
4968
+ const at = this.scene.shots.findIndex((s) => was.shots.includes(s.id));
4969
+ const kept = bare.shots;
4970
+ const nextShots = [...kept.slice(0, Math.max(0, at)), ...shots, ...kept.slice(Math.max(0, at))];
4971
+ return { scene: { ...bare, artwork: { ...bare.artwork, nodes }, shots: nextShots }, label: `Set ${d.name} path`, instance, notes };
4972
+ });
4973
+ }
4943
4974
  /**
4944
4975
  * Makes an applied effect again with new `values` (merged over its own; `null` resets a
4945
4976
  * control), in the same place. One undo step.
@@ -7239,7 +7270,7 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
7239
7270
  {
7240
7271
  name: "add_vector_effect",
7241
7272
  title: "Add a vector effect",
7242
- description: 'Adds a provider vector effect that brings its own picture (search_effects with kind vector: lower thirds, loaders, stickers): its SVG becomes an artwork group, fitted into box (default the whole artwork), and its motion becomes shots after the last one. For an effect that draws along a path (search_effects accepts ["path"]: a signature, a route), pass path: { node } to run it along a path node (its outline with every transform applied; the picture then lands on the node at scale 1 unless box is given) or { text } for words the provider writes. Use it instead of follow or draw-on when the effect itself should trace the path. The path is copied when added; add it again after reshaping the node. Change it with update_effect (target and effect: the returned instance) or remove it with remove_effect. One undo step. Returns the instance, the group id and any notes on what could not be carried over.',
7273
+ description: 'Adds a provider vector effect that brings its own picture (search_effects with kind vector: lower thirds, loaders, stickers): its SVG becomes an artwork group, fitted into box (default the whole artwork), and its motion becomes shots after the last one. For an effect that draws along a path (search_effects accepts ["path"]: a signature, a route), pass path: { node } to run it along a path node (its outline with every transform applied; the picture then lands on the node at scale 1 unless box is given) or { text } for words the provider writes. Use it instead of follow or draw-on when the effect itself should trace the path. The path is copied when added; after reshaping the node, give it the path again with set_vector_effect_path. Change it with update_effect (target and effect: the returned instance) or remove it with remove_effect. One undo step. Returns the instance, the group id and any notes on what could not be carried over.',
7243
7274
  inputSchema: {
7244
7275
  type: "object",
7245
7276
  properties: {
@@ -7283,6 +7314,42 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
7283
7314
  if (!r.ok) throw new Error(r.error);
7284
7315
  return { instance: r.effect.instance, group: r.effect.group, effect: info(r.effect), ...r.notes.length ? { notes: r.notes } : {} };
7285
7316
  }
7317
+ },
7318
+ {
7319
+ name: "set_vector_effect_path",
7320
+ title: "Run a vector effect along a path",
7321
+ description: 'Gives a vector effect already added with add_vector_effect (instance: its id from add_vector_effect or list_applied_effects) a new path to draw along, in place: path: { node } runs it along a path node (its outline with every transform applied) and lands the picture on the node at scale 1; { text } writes words with the provider and keeps the picture where it was. Use it after reshaping the node the effect was run along, or to switch between a node and words. To clear the path, call update_effect with the path control set to "". Refuses a motion effect, an effect without a path control, an unknown or non-path node, and a provider that cannot write words, saying what to pass. One undo step. Returns the instance, the control set, its new path data and any notes.',
7322
+ inputSchema: {
7323
+ type: "object",
7324
+ properties: {
7325
+ instance: { type: "string", minLength: 1, description: "The applied vector effect id (add_vector_effect instance, or list_applied_effects)." },
7326
+ path: {
7327
+ type: "object",
7328
+ description: "The path the effect draws along: { node } or { text }.",
7329
+ properties: {
7330
+ node: { type: "string", minLength: 1, description: "A path node id (find_animation_elements)." },
7331
+ text: { type: "string", minLength: 1, description: "Words the provider writes as a single-stroke path." },
7332
+ font: { type: "string", minLength: 1, description: "With text: a single-stroke font the provider offers (default its first)." },
7333
+ align: { type: "string", enum: ["start", "middle", "end"], description: "With text: where the line sits (default start)." }
7334
+ },
7335
+ oneOf: [{ required: ["node"] }, { required: ["text"] }],
7336
+ additionalProperties: false
7337
+ },
7338
+ control: { type: "string", minLength: 1, description: "Which path control takes the path (default the effect's only one; describe_effect pathControls lists them)." }
7339
+ },
7340
+ required: ["instance", "path"],
7341
+ additionalProperties: false
7342
+ },
7343
+ annotations: { title: "Run a vector effect along a path", ...ctx.annotations.write, idempotentHint: true },
7344
+ handler: async (args) => {
7345
+ ctx.requireProvider();
7346
+ if (args.path.node !== void 0 && args.path.text !== void 0) throw new Error("Pass path as { node } or { text }, not both.");
7347
+ const path = args.path.node !== void 0 ? { node: args.path.node } : { text: args.path.text, font: args.path.font, align: args.path.align };
7348
+ const r = await controller.setVectorEffectPath(args.instance, path, { control: args.control });
7349
+ if (!r.ok) throw new Error(r.error);
7350
+ const control = args.control ?? pathControlsOf(await controller.effectsProvider.describe(r.effect.effect))[0];
7351
+ return { instance: r.effect.instance, group: r.effect.group, control, value: r.effect.values[control], effect: info(r.effect), ...r.notes.length ? { notes: r.notes } : {} };
7352
+ }
7286
7353
  }
7287
7354
  ]
7288
7355
  }), options.playbackSurface);
@@ -8,8 +8,8 @@
8
8
 
9
9
 
10
10
 
11
- var _chunkWLUVZKVDcjs = require('../chunk-WLUVZKVD.cjs');
12
- require('../chunk-PE6YJMQT.cjs');
11
+ var _chunkDT4YQUGTcjs = require('../chunk-DT4YQUGT.cjs');
12
+ require('../chunk-PFHJS4HE.cjs');
13
13
 
14
14
 
15
15
 
@@ -17,7 +17,7 @@ require('../chunk-PE6YJMQT.cjs');
17
17
 
18
18
 
19
19
 
20
- var _chunkVRK322ZCcjs = require('../chunk-VRK322ZC.cjs');
20
+ var _chunkHIO6E7LCcjs = require('../chunk-HIO6E7LC.cjs');
21
21
 
22
22
 
23
23
 
@@ -69,10 +69,10 @@ var _chunkVRK322ZCcjs = require('../chunk-VRK322ZC.cjs');
69
69
 
70
70
 
71
71
 
72
- var _chunkRFJZGTHAcjs = require('../chunk-RFJZGTHA.cjs');
72
+ var _chunkXVOP3CGQcjs = require('../chunk-XVOP3CGQ.cjs');
73
73
 
74
74
 
75
- var _chunkOTN6VB5Scjs = require('../chunk-OTN6VB5S.cjs');
75
+ var _chunkRDFHWAHLcjs = require('../chunk-RDFHWAHL.cjs');
76
76
 
77
77
 
78
78
  var _chunkJBZRVLXVcjs = require('../chunk-JBZRVLXV.cjs');
@@ -106,7 +106,7 @@ var PHYSICS_LABELS = { string: "Strings", spring: "Springs", orbit: "Orbits", fl
106
106
  var RENDER_LABELS = { dot: "Dots", line: "Lines", sequence: "Beads", ribbon: "Ribbon" };
107
107
  var APPLICATOR_LABELS = { brush: "Brush", tube: "Paint tube", knife: "Palette knife", roller: "Roller", gloop: "Gloop pen" };
108
108
  var WET_MEDIUM_LABELS = { watercolor: "Watercolour", gouache: "Gouache", oil: "Oil" };
109
- var STAMP_OPTIONS = _chunkOTN6VB5Scjs.STAMP_KINDS.map((k) => ({ value: `editor:${k}`, label: title(k) }));
109
+ var STAMP_OPTIONS = _chunkRDFHWAHLcjs.STAMP_KINDS.map((k) => ({ value: `editor:${k}`, label: title(k) }));
110
110
  var ARIA = {
111
111
  "dynamics.rotation": "Brush rotation",
112
112
  "tip.blend": "Brush blend",
@@ -122,20 +122,20 @@ var ARIA = {
122
122
  "light.pressure": "Light follows pressure"
123
123
  };
124
124
  var aria = (path, label) => _nullishCoalesce(ARIA[path], () => ( `Brush ${label.toLowerCase()}`));
125
- function brushEditorSections(brush, profile = _chunkRFJZGTHAcjs.PAINT_PROFILE) {
126
- const resolved = _chunkRFJZGTHAcjs.resolveBrush.call(void 0, brush);
127
- const engine = _chunkRFJZGTHAcjs.resolveEngine.call(void 0, brush);
128
- const fieldOf = (facet) => _chunkRFJZGTHAcjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
129
- const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunkRFJZGTHAcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunkRFJZGTHAcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
125
+ function brushEditorSections(brush, profile = _chunkXVOP3CGQcjs.PAINT_PROFILE) {
126
+ const resolved = _chunkXVOP3CGQcjs.resolveBrush.call(void 0, brush);
127
+ const engine = _chunkXVOP3CGQcjs.resolveEngine.call(void 0, brush);
128
+ const fieldOf = (facet) => _chunkXVOP3CGQcjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
129
+ const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunkXVOP3CGQcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunkXVOP3CGQcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
130
130
  const value = (path) => {
131
- const own = _chunkRFJZGTHAcjs.getPath.call(void 0, brush, path);
131
+ const own = _chunkXVOP3CGQcjs.getPath.call(void 0, brush, path);
132
132
  if (own !== void 0) return own;
133
133
  const field = fieldOf(path);
134
134
  if (!field) return void 0;
135
- const v = _chunkRFJZGTHAcjs.getPath.call(void 0, resolved, field.engine);
135
+ const v = _chunkXVOP3CGQcjs.getPath.call(void 0, resolved, field.engine);
136
136
  return field.map ? field.map.toFacet(v) : v;
137
137
  };
138
- const issues = _chunkRFJZGTHAcjs.checkBrush.call(void 0, brush, profile).issues;
138
+ const issues = _chunkXVOP3CGQcjs.checkBrush.call(void 0, brush, profile).issues;
139
139
  const warned = new Map(issues.filter((i) => i.severity === "warning").map((i) => [i.facet, i.reason]));
140
140
  const refused = new Set(issues.filter((i) => i.severity === "error").map((i) => i.facet));
141
141
  const full = (s) => s === "full";
@@ -164,18 +164,18 @@ function brushEditorSections(brush, profile = _chunkRFJZGTHAcjs.PAINT_PROFILE) {
164
164
  const exchangeFull = full(_optionalChain([brush, 'access', _9 => _9.behaviour, 'optionalAccess', _10 => _10.exchange, 'optionalAccess', _11 => _11.reservoir]) ? profile.reservoir : profile.exchange);
165
165
  add("medium", "Medium", [
166
166
  profile.kinds.length > 1 && profile.kinds.includes(brush.kind) && choice("kind", "Kind", options(profile.kinds, { mark: "Lays a material", tool: "Works on paint" })),
167
- !isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunkRFJZGTHAcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
167
+ !isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunkXVOP3CGQcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
168
168
  !isTool && withNote({ kind: "text", path: "variety", label: "Variety", ariaLabel: "Brush variety", value: _nullishCoalesce(brush.variety, () => ( "")), placeholder: "pencil, oil, highlighter\u2026" }),
169
169
  isTool && !!brush.tool && profile.tools.includes(brush.tool) && choice("tool", "Tool", options(profile.tools, TOOL_LABELS))
170
170
  ]);
171
- const engineControls = _chunkWLUVZKVDcjs.brushEngineControls.call(void 0, resolved);
172
- const tipSliders = _chunkWLUVZKVDcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
171
+ const engineControls = _chunkDT4YQUGTcjs.brushEngineControls.call(void 0, resolved);
172
+ const tipSliders = _chunkDT4YQUGTcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
173
173
  add("shape", "Shape", [
174
174
  !refused.has("tip.shape") && choice("tip.shape", "Tip", options(profile.tipShapes.filter((s) => !isTool || s !== "stamp"), SHAPE_LABELS)),
175
175
  ...tipSliders.map((c) => slider(c)),
176
176
  engine === "dab" && choice("tip.blend", "Blend", _chunk2VX55NFMcjs.BLEND_MODES.map((m) => ({ value: m.id, label: m.label })), "normal"),
177
177
  ...shape === "bristle" && engineOk && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("bristle.")).map((c) => slider(c)) : [],
178
- shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunkRFJZGTHAcjs.MAX_DOT_TEXTURES : _chunkRFJZGTHAcjs.MAX_STICKER_STAMPS, options: STAMP_OPTIONS })
178
+ shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunkXVOP3CGQcjs.MAX_DOT_TEXTURES : _chunkXVOP3CGQcjs.MAX_STICKER_STAMPS, options: STAMP_OPTIONS })
179
179
  ]);
180
180
  if (!isTool && profile.marks.length > 1 && engineOk) {
181
181
  const particles = marks === "particles" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("particle.") && c.path !== "particle.waveSpeed") : [];
@@ -183,21 +183,21 @@ function brushEditorSections(brush, profile = _chunkRFJZGTHAcjs.PAINT_PROFILE) {
183
183
  const render = value("marks.render");
184
184
  add("marks", "Marks", [
185
185
  choice("marks.kind", "Laid as", options(profile.marks, MARKS_LABELS), "continuous"),
186
- marks === "particles" && choice("marks.physics", "Particles", options(_chunkRFJZGTHAcjs.PARTICLE_KINDS, PHYSICS_LABELS)),
187
- marks === "particles" && choice("marks.render", "Drawn as", options(_chunkRFJZGTHAcjs.PARTICLE_RENDERS, RENDER_LABELS)),
188
- marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunkRFJZGTHAcjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
189
- marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunkRFJZGTHAcjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
190
- marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunkRFJZGTHAcjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
186
+ marks === "particles" && choice("marks.physics", "Particles", options(_chunkXVOP3CGQcjs.PARTICLE_KINDS, PHYSICS_LABELS)),
187
+ marks === "particles" && choice("marks.render", "Drawn as", options(_chunkXVOP3CGQcjs.PARTICLE_RENDERS, RENDER_LABELS)),
188
+ marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunkXVOP3CGQcjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
189
+ marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunkXVOP3CGQcjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
190
+ marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunkXVOP3CGQcjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
191
191
  ...particles.map((c) => slider(c)),
192
192
  ...objects.map((c) => slider(c))
193
193
  ]);
194
194
  }
195
- const feel = _chunkWLUVZKVDcjs.BRUSH_SLIDERS.filter((c) => ["tip.smoothing", "pressureSmoothing", "dynamics.minSize", "dynamics.tiltSize", "dynamics.velocitySize"].includes(c.path)).filter((c) => !(c.path === "dynamics.tiltSize" && !full(profile.tilt)) && !(c.path === "dynamics.velocitySize" && !full(profile.velocity)));
195
+ const feel = _chunkDT4YQUGTcjs.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)));
196
196
  add("feel", "Feel", [
197
197
  ...feel.map((c) => slider(c)),
198
198
  toggle("dynamics.pressureSize", "Pressure \u2192 size"),
199
199
  toggle("dynamics.pressureOpacity", "Pressure \u2192 opacity"),
200
- choice("dynamics.rotation", "Rotation", options(_chunkRFJZGTHAcjs.BRUSH_ROTATIONS, ROTATION_LABELS))
200
+ choice("dynamics.rotation", "Rotation", options(_chunkXVOP3CGQcjs.BRUSH_ROTATIONS, ROTATION_LABELS))
201
201
  ]);
202
202
  const surfaces = profile.surfaces;
203
203
  const engineSliders = (engineOk ? _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _12 => _12.sliders]), () => ( [])) : []).filter((c) => !/^(bristle|particle|sticker)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
@@ -205,8 +205,8 @@ function brushEditorSections(brush, profile = _chunkRFJZGTHAcjs.PAINT_PROFILE) {
205
205
  add("behaviour", _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _15 => _15.title]), () => ( "Behaviour")), [
206
206
  !isTool && surfaces.length > 1 && !refused.has("behaviour.surface") && choice("behaviour.surface", "Surface", options(surfaces, SURFACE_LABELS), "dry"),
207
207
  full(profile.grain) && slider({ path: "grain", label: "Grain", min: 0, max: 1, step: 0.01 }, "behaviour.grain"),
208
- engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunkRFJZGTHAcjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
209
- engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(_chunkRFJZGTHAcjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
208
+ engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunkXVOP3CGQcjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
209
+ engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(_chunkXVOP3CGQcjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
210
210
  ...engineSliders.map((c) => exchangeOk(facetOf(c.path)) ? slider(c) : null),
211
211
  engineOk && _optionalChain([engineControls, 'optionalAccess', _16 => _16.mixingPath]) && (engine === "wet" || exchangeFull) && fieldOf("behaviour.mixing") && choice("behaviour.mixing", "Mixing", options(["pigment", "rgb"], { pigment: "Pigment", rgb: "RGB" })),
212
212
  engineOk && _optionalChain([engineControls, 'optionalAccess', _17 => _17.dirty]) && exchangeFull && fieldOf("behaviour.exchange.dirty") && toggle("behaviour.exchange.dirty", "Dirty brush"),
@@ -234,7 +234,7 @@ function brushEditorSections(brush, profile = _chunkRFJZGTHAcjs.PAINT_PROFILE) {
234
234
  label: "Palette",
235
235
  ariaLabel: "Brush palette",
236
236
  value: (_nullishCoalesce(_optionalChain([brush, 'access', _24 => _24.colour, 'optionalAccess', _25 => _25.palette]), () => ( []))).flatMap((c) => _chunkMLLTWAXHcjs.isDualColor.call(void 0, c) ? [{ light: _chunkJBZRVLXVcjs.brushColourHex.call(void 0, c, "light"), dark: _chunkJBZRVLXVcjs.brushColourHex.call(void 0, c, "dark") }] : hex(c) ? [hex(c)] : []),
237
- max: _chunkRFJZGTHAcjs.MAX_BRUSH_PALETTE
237
+ max: _chunkXVOP3CGQcjs.MAX_BRUSH_PALETTE
238
238
  }),
239
239
  toggle("colour.own", "Always its own colour")
240
240
  ]);
@@ -268,15 +268,15 @@ function hiddenLabel(issue, b) {
268
268
  case "dynamics.tilt":
269
269
  return "tilt dynamics";
270
270
  case "colour.default":
271
- return `a ${_chunkRFJZGTHAcjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
271
+ return `a ${_chunkXVOP3CGQcjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
272
272
  default:
273
273
  return null;
274
274
  }
275
275
  }
276
276
  var sentence = (words) => words.length < 2 ? _nullishCoalesce(words[0], () => ( "")) : `${words.slice(0, -1).join(", ")} and ${words.at(-1)}`;
277
- function brushEditorScope(brush, profile = _chunkRFJZGTHAcjs.PAINT_PROFILE) {
277
+ function brushEditorScope(brush, profile = _chunkXVOP3CGQcjs.PAINT_PROFILE) {
278
278
  const hidden = [];
279
- for (const issue of _chunkRFJZGTHAcjs.checkBrush.call(void 0, brush, profile).issues) {
279
+ for (const issue of _chunkXVOP3CGQcjs.checkBrush.call(void 0, brush, profile).issues) {
280
280
  const label = hiddenLabel(issue, brush);
281
281
  if (label && !hidden.some((h) => h.label === label)) hidden.push({ facet: issue.facet, label });
282
282
  }
@@ -289,17 +289,17 @@ function newBrushFor(profile, from, name = "New brush") {
289
289
  const id = brushIdFromName(name);
290
290
  const base = { id, name, kind: profile.kinds.includes("mark") ? "mark" : profile.kinds[0], ...profile.kinds.includes("mark") ? {} : { tool: profile.tools[0] }, tip: { shape: profile.tipShapes.includes("round") ? "round" : profile.tipShapes[0] } };
291
291
  if (from) {
292
- const stripped = _chunkRFJZGTHAcjs.degrade.call(void 0, from, profile, { ignored: true });
292
+ const stripped = _chunkXVOP3CGQcjs.degrade.call(void 0, from, profile, { ignored: true });
293
293
  if (!stripped.issues.length) return { ...stripped.brush, id, name };
294
294
  }
295
295
  return base;
296
296
  }
297
297
  async function saveBrushEdit(library, options2) {
298
298
  const { original, profile } = options2;
299
- const check = _chunkRFJZGTHAcjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
299
+ const check = _chunkXVOP3CGQcjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
300
300
  if (!check.ok) {
301
301
  const errors = check.issues.filter((i) => i.severity === "error").map((i) => `${i.facet}: ${i.reason} ${i.fix}`);
302
- throw new (0, _chunkRFJZGTHAcjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
302
+ throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
303
303
  }
304
304
  const inPlace = !!original && options2.name === void 0 && !library.isBuiltin(original.id) && original.id === options2.brush.id && !!await library.get(original.id);
305
305
  let brush = options2.brush;
@@ -335,13 +335,13 @@ function setBrushEditorValue(brush, path, value) {
335
335
  if (value !== "bristle") delete next.tip.bristle;
336
336
  } else if (value === void 0 || value === "") {
337
337
  const keys = path.split(".");
338
- const parent = _chunkRFJZGTHAcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
338
+ const parent = _chunkXVOP3CGQcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
339
339
  if (keys.length === 1) delete next[keys[0]];
340
340
  else if (parent) delete parent[keys[keys.length - 1]];
341
- } else _chunkRFJZGTHAcjs.setPath.call(void 0, next, path, value);
341
+ } else _chunkXVOP3CGQcjs.setPath.call(void 0, next, path, value);
342
342
  const problems = [];
343
343
  try {
344
- return { brush: _chunkRFJZGTHAcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
344
+ return { brush: _chunkXVOP3CGQcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
345
345
  } catch (e) {
346
346
  return { brush, problems: [e.message] };
347
347
  }
@@ -357,7 +357,7 @@ function brushLibraryGroups(entries, filter = {}) {
357
357
  const text = words([b.id, b.name, _nullishCoalesce(b.variety, () => ( "")), _nullishCoalesce(b.medium, () => ( "")), _nullishCoalesce(b.tool, () => ( "")), ..._nullishCoalesce(b.tags, () => ( []))].join(" "));
358
358
  if (!wanted.every((w) => text.some((t) => t.startsWith(w)))) continue;
359
359
  }
360
- if (filter.profile && !_chunkRFJZGTHAcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
360
+ if (filter.profile && !_chunkXVOP3CGQcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
361
361
  const id = b.kind === "tool" ? "tools" : _nullishCoalesce(b.medium, () => ( "other"));
362
362
  let g = groups.get(id);
363
363
  if (!g) groups.set(id, g = { id, title: id === "tools" ? "Tools" : id === "other" ? "Other" : MEDIUM_LABELS[id], varieties: [] });
@@ -379,11 +379,11 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
379
379
  properties: {
380
380
  id: { type: "string", description: "paint, image, canvas, vector\u2026" },
381
381
  name: { type: "string", description: "Display name, used in messages." },
382
- kinds: { type: "array", items: { type: "string", enum: [..._chunkRFJZGTHAcjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
383
- tools: { type: "array", items: { type: "string", enum: [..._chunkRFJZGTHAcjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
384
- tipShapes: { type: "array", items: { type: "string", enum: [..._chunkRFJZGTHAcjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
385
- marks: { type: "array", items: { type: "string", enum: [..._chunkRFJZGTHAcjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
386
- surfaces: { type: "array", items: { type: "string", enum: [..._chunkRFJZGTHAcjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
382
+ kinds: { type: "array", items: { type: "string", enum: [..._chunkXVOP3CGQcjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
383
+ tools: { type: "array", items: { type: "string", enum: [..._chunkXVOP3CGQcjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
384
+ tipShapes: { type: "array", items: { type: "string", enum: [..._chunkXVOP3CGQcjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
385
+ marks: { type: "array", items: { type: "string", enum: [..._chunkXVOP3CGQcjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
386
+ surfaces: { type: "array", items: { type: "string", enum: [..._chunkXVOP3CGQcjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
387
387
  exchange: { ...SUPPORT, description: "Picking paint up and mixing it in." },
388
388
  reservoir: { ...SUPPORT, description: "The Mixer Brush reservoir." },
389
389
  grain: { ...SUPPORT, description: "Paper grain response." },
@@ -408,7 +408,7 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
408
408
  additionalProperties: false
409
409
  };
410
410
  function migrationInputs() {
411
- const pick = (id) => _chunkRFJZGTHAcjs.brushToJSON.call(void 0, _chunkRFJZGTHAcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
411
+ const pick = (id) => _chunkXVOP3CGQcjs.brushToJSON.call(void 0, _chunkXVOP3CGQcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
412
412
  return [
413
413
  { id: "plain", name: "Plain" },
414
414
  pick("pencil-6b"),
@@ -430,34 +430,34 @@ function migrationInputs() {
430
430
  function editorSectionFixtures() {
431
431
  const ids = ["highlighter", "chalk", "watercolor-wash", "hair-strands", "mixer-brush", "blender", "spray-can"];
432
432
  return ids.flatMap(
433
- (id) => Object.keys(_chunkRFJZGTHAcjs.BRUSH_HOST_PROFILES).map((host) => {
434
- const brush = _chunkRFJZGTHAcjs.BRUSH_PRESETS.find((b) => b.id === id);
435
- return { brush: id, host, sections: brushEditorSections(brush, _chunkRFJZGTHAcjs.BRUSH_HOST_PROFILES[host]) };
433
+ (id) => Object.keys(_chunkXVOP3CGQcjs.BRUSH_HOST_PROFILES).map((host) => {
434
+ const brush = _chunkXVOP3CGQcjs.BRUSH_PRESETS.find((b) => b.id === id);
435
+ return { brush: id, host, sections: brushEditorSections(brush, _chunkXVOP3CGQcjs.BRUSH_HOST_PROFILES[host]) };
436
436
  })
437
437
  );
438
438
  }
439
439
  function toolDefinitions() {
440
- const library = _chunkRFJZGTHAcjs.createBrushLibrary.call(void 0, );
441
- const toolsFor = (host) => _chunkWLUVZKVDcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunkRFJZGTHAcjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
440
+ const library = _chunkXVOP3CGQcjs.createBrushLibrary.call(void 0, );
441
+ const toolsFor = (host) => _chunkDT4YQUGTcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunkXVOP3CGQcjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
442
442
  return {
443
443
  tools: toolsFor("paint").map((t) => ({ name: t.name, title: t.title, description: t.description, inputSchema: t.inputSchema, annotations: t.annotations })),
444
- hosts: Object.fromEntries(Object.keys(_chunkRFJZGTHAcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
444
+ hosts: Object.fromEntries(Object.keys(_chunkXVOP3CGQcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
445
445
  };
446
446
  }
447
447
  function brushContracts() {
448
- const presets = _chunkRFJZGTHAcjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
449
- const resolved = _chunkRFJZGTHAcjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunkRFJZGTHAcjs.resolveEngine.call(void 0, b), category: _chunkRFJZGTHAcjs.resolveCategory.call(void 0, b), brush: _chunkRFJZGTHAcjs.brushToJSON.call(void 0, _chunkRFJZGTHAcjs.resolveBrush.call(void 0, b)) }));
450
- const profiles = Object.values(_chunkRFJZGTHAcjs.BRUSH_HOST_PROFILES);
451
- const checks = _chunkRFJZGTHAcjs.BRUSH_PRESETS.map((b) => ({
448
+ const presets = _chunkXVOP3CGQcjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
449
+ const resolved = _chunkXVOP3CGQcjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunkXVOP3CGQcjs.resolveEngine.call(void 0, b), category: _chunkXVOP3CGQcjs.resolveCategory.call(void 0, b), brush: _chunkXVOP3CGQcjs.brushToJSON.call(void 0, _chunkXVOP3CGQcjs.resolveBrush.call(void 0, b)) }));
450
+ const profiles = Object.values(_chunkXVOP3CGQcjs.BRUSH_HOST_PROFILES);
451
+ const checks = _chunkXVOP3CGQcjs.BRUSH_PRESETS.map((b) => ({
452
452
  id: b.id,
453
453
  hosts: Object.fromEntries(profiles.map((p) => {
454
- const c = _chunkRFJZGTHAcjs.checkBrush.call(void 0, b, p);
454
+ const c = _chunkXVOP3CGQcjs.checkBrush.call(void 0, b, p);
455
455
  return [p.id, { ok: c.ok, issues: c.issues.map(({ facet, severity }) => ({ facet, severity })) }];
456
456
  }))
457
457
  }));
458
- const migrations = migrationInputs().map((input) => ({ input, output: _chunkRFJZGTHAcjs.migrateBrushV1.call(void 0, input), resolved: _chunkRFJZGTHAcjs.brushToJSON.call(void 0, _chunkRFJZGTHAcjs.resolveBrush.call(void 0, _chunkRFJZGTHAcjs.migrateBrushV1.call(void 0, input))), engine: _chunkRFJZGTHAcjs.normalizePaintBrush.call(void 0, input).engine }));
458
+ const migrations = migrationInputs().map((input) => ({ input, output: _chunkXVOP3CGQcjs.migrateBrushV1.call(void 0, input), resolved: _chunkXVOP3CGQcjs.brushToJSON.call(void 0, _chunkXVOP3CGQcjs.resolveBrush.call(void 0, _chunkXVOP3CGQcjs.migrateBrushV1.call(void 0, input))), engine: _chunkXVOP3CGQcjs.normalizePaintBrush.call(void 0, input).engine }));
459
459
  const files = {
460
- "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkRFJZGTHAcjs.BRUSH_JSON_SCHEMA },
460
+ "brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkXVOP3CGQcjs.BRUSH_JSON_SCHEMA },
461
461
  "profile.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "profile.schema.json", ...BRUSH_PROFILE_JSON_SCHEMA },
462
462
  "library-file.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "library-file.schema.json", ...BRUSH_LIBRARY_FILE_JSON_SCHEMA },
463
463
  "presets.json": presets,
@@ -471,7 +471,7 @@ function brushContracts() {
471
471
  files["manifest.json"] = {
472
472
  domain: "brushes",
473
473
  formatVersion: BRUSH_CONTRACT_FORMAT_VERSION,
474
- limits: { maxPalette: _chunkRFJZGTHAcjs.MAX_BRUSH_PALETTE },
474
+ limits: { maxPalette: _chunkXVOP3CGQcjs.MAX_BRUSH_PALETTE },
475
475
  counts: { presets: presets.length, profiles: profiles.length, migrations: migrations.length, editorSections: files["editor-sections.json"].length },
476
476
  files: Object.keys(files).sort()
477
477
  };
@@ -537,4 +537,4 @@ function brushContracts() {
537
537
 
538
538
 
539
539
 
540
- exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunkRFJZGTHAcjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_HOST_PROFILES = _chunkRFJZGTHAcjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunkRFJZGTHAcjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunkRFJZGTHAcjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunkRFJZGTHAcjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunkRFJZGTHAcjs.BRUSH_MEDIA; exports.BRUSH_PATCH_PROPERTIES = _chunkWLUVZKVDcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunkRFJZGTHAcjs.BRUSH_PRESETS; exports.BRUSH_PREVIEW_DARK_PAPER = _chunkVRK322ZCcjs.BRUSH_PREVIEW_DARK_PAPER; exports.BRUSH_PREVIEW_FALLBACKS = _chunkVRK322ZCcjs.BRUSH_PREVIEW_FALLBACKS; exports.BRUSH_PREVIEW_MIN_CONTRAST = _chunkVRK322ZCcjs.BRUSH_PREVIEW_MIN_CONTRAST; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SURFACES = _chunkRFJZGTHAcjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunkRFJZGTHAcjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunkRFJZGTHAcjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunkWLUVZKVDcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunkRFJZGTHAcjs.BRUSH_WORD; exports.BrushLibraryError = _chunkRFJZGTHAcjs.BrushLibraryError; exports.CANVAS_PROFILE = _chunkRFJZGTHAcjs.CANVAS_PROFILE; exports.IMAGE_PROFILE = _chunkRFJZGTHAcjs.IMAGE_PROFILE; exports.MAX_BRUSH_PALETTE = _chunkRFJZGTHAcjs.MAX_BRUSH_PALETTE; exports.PAINT_PROFILE = _chunkRFJZGTHAcjs.PAINT_PROFILE; exports.UNSETTABLE_BRUSH_FACETS = _chunkWLUVZKVDcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunkRFJZGTHAcjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunkRFJZGTHAcjs.WET_BRUSH_TOOLS; exports.brushColourHex = _chunkJBZRVLXVcjs.brushColourHex; exports.brushColourKind = _chunkRFJZGTHAcjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorScope = brushEditorScope; exports.brushEditorSections = brushEditorSections; exports.brushIdFromName = brushIdFromName; exports.brushLibraryGroups = brushLibraryGroups; exports.brushPreviewColours = _chunkVRK322ZCcjs.brushPreviewColours; exports.brushPreviewStrength = _chunkVRK322ZCcjs.brushPreviewStrength; exports.brushPreviewsOnDark = _chunkVRK322ZCcjs.brushPreviewsOnDark; exports.changedBrushPaths = _chunkWLUVZKVDcjs.changedBrushPaths; exports.checkBrush = _chunkRFJZGTHAcjs.checkBrush; exports.checkBrushEdit = _chunkRFJZGTHAcjs.checkBrushEdit; exports.createBrushLibrary = _chunkRFJZGTHAcjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunkWLUVZKVDcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunkWLUVZKVDcjs.createBrushLibraryTools; exports.degrade = _chunkRFJZGTHAcjs.degrade; exports.isBrushLibrary = _chunkRFJZGTHAcjs.isBrushLibrary; exports.listPresets = _chunkRFJZGTHAcjs.listPresets; exports.mergeBrushPatch = _chunkWLUVZKVDcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunkRFJZGTHAcjs.migrateBrushV1; exports.newBrushFor = newBrushFor; exports.normalizeBrushSpec = _chunkRFJZGTHAcjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunkRFJZGTHAcjs.parseBrushLibrary2; exports.resolveBrush = _chunkRFJZGTHAcjs.resolveBrush; exports.resolveCategory = _chunkRFJZGTHAcjs.resolveCategory; exports.resolveEngine = _chunkRFJZGTHAcjs.resolveEngine; exports.resolveWetMedium = _chunkRFJZGTHAcjs.resolveWetMedium; exports.saveBrushEdit = saveBrushEdit; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunkRFJZGTHAcjs.snapshotBrushLibrary; exports.withKeptIssues = _chunkRFJZGTHAcjs.withKeptIssues;
540
+ exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunkXVOP3CGQcjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_HOST_PROFILES = _chunkXVOP3CGQcjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunkXVOP3CGQcjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunkXVOP3CGQcjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunkXVOP3CGQcjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunkXVOP3CGQcjs.BRUSH_MEDIA; exports.BRUSH_PATCH_PROPERTIES = _chunkDT4YQUGTcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunkXVOP3CGQcjs.BRUSH_PRESETS; exports.BRUSH_PREVIEW_DARK_PAPER = _chunkHIO6E7LCcjs.BRUSH_PREVIEW_DARK_PAPER; exports.BRUSH_PREVIEW_FALLBACKS = _chunkHIO6E7LCcjs.BRUSH_PREVIEW_FALLBACKS; exports.BRUSH_PREVIEW_MIN_CONTRAST = _chunkHIO6E7LCcjs.BRUSH_PREVIEW_MIN_CONTRAST; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SURFACES = _chunkXVOP3CGQcjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunkXVOP3CGQcjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunkXVOP3CGQcjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunkDT4YQUGTcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunkXVOP3CGQcjs.BRUSH_WORD; exports.BrushLibraryError = _chunkXVOP3CGQcjs.BrushLibraryError; exports.CANVAS_PROFILE = _chunkXVOP3CGQcjs.CANVAS_PROFILE; exports.IMAGE_PROFILE = _chunkXVOP3CGQcjs.IMAGE_PROFILE; exports.MAX_BRUSH_PALETTE = _chunkXVOP3CGQcjs.MAX_BRUSH_PALETTE; exports.PAINT_PROFILE = _chunkXVOP3CGQcjs.PAINT_PROFILE; exports.UNSETTABLE_BRUSH_FACETS = _chunkDT4YQUGTcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunkXVOP3CGQcjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunkXVOP3CGQcjs.WET_BRUSH_TOOLS; exports.brushColourHex = _chunkJBZRVLXVcjs.brushColourHex; exports.brushColourKind = _chunkXVOP3CGQcjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorScope = brushEditorScope; exports.brushEditorSections = brushEditorSections; exports.brushIdFromName = brushIdFromName; exports.brushLibraryGroups = brushLibraryGroups; exports.brushPreviewColours = _chunkHIO6E7LCcjs.brushPreviewColours; exports.brushPreviewStrength = _chunkHIO6E7LCcjs.brushPreviewStrength; exports.brushPreviewsOnDark = _chunkHIO6E7LCcjs.brushPreviewsOnDark; exports.changedBrushPaths = _chunkDT4YQUGTcjs.changedBrushPaths; exports.checkBrush = _chunkXVOP3CGQcjs.checkBrush; exports.checkBrushEdit = _chunkXVOP3CGQcjs.checkBrushEdit; exports.createBrushLibrary = _chunkXVOP3CGQcjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunkDT4YQUGTcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunkDT4YQUGTcjs.createBrushLibraryTools; exports.degrade = _chunkXVOP3CGQcjs.degrade; exports.isBrushLibrary = _chunkXVOP3CGQcjs.isBrushLibrary; exports.listPresets = _chunkXVOP3CGQcjs.listPresets; exports.mergeBrushPatch = _chunkDT4YQUGTcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunkXVOP3CGQcjs.migrateBrushV1; exports.newBrushFor = newBrushFor; exports.normalizeBrushSpec = _chunkXVOP3CGQcjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunkXVOP3CGQcjs.parseBrushLibrary2; exports.resolveBrush = _chunkXVOP3CGQcjs.resolveBrush; exports.resolveCategory = _chunkXVOP3CGQcjs.resolveCategory; exports.resolveEngine = _chunkXVOP3CGQcjs.resolveEngine; exports.resolveWetMedium = _chunkXVOP3CGQcjs.resolveWetMedium; exports.saveBrushEdit = saveBrushEdit; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunkXVOP3CGQcjs.snapshotBrushLibrary; exports.withKeptIssues = _chunkXVOP3CGQcjs.withKeptIssues;
@@ -8,8 +8,8 @@ import {
8
8
  createBrushLibraryToolProvider,
9
9
  createBrushLibraryTools,
10
10
  mergeBrushPatch
11
- } from "../chunk-3C33YTNN.js";
12
- import "../chunk-6JL2D5SG.js";
11
+ } from "../chunk-JGWVZPT6.js";
12
+ import "../chunk-VE6UKYQ2.js";
13
13
  import {
14
14
  BRUSH_PREVIEW_DARK_PAPER,
15
15
  BRUSH_PREVIEW_FALLBACKS,
@@ -17,7 +17,7 @@ import {
17
17
  brushPreviewColours,
18
18
  brushPreviewStrength,
19
19
  brushPreviewsOnDark
20
- } from "../chunk-4ODRXQRW.js";
20
+ } from "../chunk-EYSHTYLG.js";
21
21
  import {
22
22
  BRUSH_FACET_SCHEMAS,
23
23
  BRUSH_FIELDS,
@@ -69,10 +69,10 @@ import {
69
69
  setPath,
70
70
  snapshotBrushLibrary,
71
71
  withKeptIssues
72
- } from "../chunk-CIJBSUM5.js";
72
+ } from "../chunk-AGNUD5BI.js";
73
73
  import {
74
74
  STAMP_KINDS
75
- } from "../chunk-ACFSFUQH.js";
75
+ } from "../chunk-JL6YH5WD.js";
76
76
  import {
77
77
  brushColourHex
78
78
  } from "../chunk-DVPQFMH6.js";
@@ -58,7 +58,12 @@ export declare const IMAGE_PROFILE: BrushHostProfile;
58
58
  * light channel (glow and spill), which canvas strokes don't have, so it is refused.
59
59
  */
60
60
  export declare const CANVAS_PROFILE: BrushHostProfile;
61
- /** Vector brushstrokes: dry dab brushes along a path; light brushes paint as plain colour. */
61
+ /**
62
+ * Vector brushstrokes: dab brushes along a path; light brushes paint as plain colour. Wet paint
63
+ * settles in its own small wet area and dries to a cached image; the Mixer Brush, smudge and
64
+ * blender act on the shapes beneath the stroke. The wet tools (water, hair dryer, blow, wet blend,
65
+ * wet drag, blot) act on wet paint, which a vector document never holds, so they are refused.
66
+ */
62
67
  export declare const VECTOR_PROFILE: BrushHostProfile;
63
68
  /** The built-in profiles by id. */
64
69
  export declare const BRUSH_HOST_PROFILES: Readonly<Record<string, BrushHostProfile>>;
@@ -58,7 +58,12 @@ export declare const IMAGE_PROFILE: BrushHostProfile;
58
58
  * light channel (glow and spill), which canvas strokes don't have, so it is refused.
59
59
  */
60
60
  export declare const CANVAS_PROFILE: BrushHostProfile;
61
- /** Vector brushstrokes: dry dab brushes along a path; light brushes paint as plain colour. */
61
+ /**
62
+ * Vector brushstrokes: dab brushes along a path; light brushes paint as plain colour. Wet paint
63
+ * settles in its own small wet area and dries to a cached image; the Mixer Brush, smudge and
64
+ * blender act on the shapes beneath the stroke. The wet tools (water, hair dryer, blow, wet blend,
65
+ * wet drag, blot) act on wet paint, which a vector document never holds, so they are refused.
66
+ */
62
67
  export declare const VECTOR_PROFILE: BrushHostProfile;
63
68
  /** The built-in profiles by id. */
64
69
  export declare const BRUSH_HOST_PROFILES: Readonly<Record<string, BrushHostProfile>>;