@pixerate/editor 0.271.0 → 0.272.1

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 (96) hide show
  1. package/dist/agent/index.cjs +34 -32
  2. package/dist/agent/index.js +10 -8
  3. package/dist/animation-editor/index.cjs +60 -60
  4. package/dist/animation-editor/index.js +4 -4
  5. package/dist/brushes/index.cjs +69 -66
  6. package/dist/brushes/index.js +6 -3
  7. package/dist/brushes/patch.d.cts +1 -1
  8. package/dist/brushes/patch.d.ts +1 -1
  9. package/dist/brushes/schema.d.cts +1 -0
  10. package/dist/brushes/schema.d.ts +1 -0
  11. package/dist/brushes/types.d.cts +8 -0
  12. package/dist/brushes/types.d.ts +8 -0
  13. package/dist/{brushstrokeRender-WR2N5HHY.cjs → brushstrokeRender-5YBCLFDQ.cjs} +15 -15
  14. package/dist/{brushstrokeRender-A727TTNQ.js → brushstrokeRender-DZGFU3J4.js} +3 -3
  15. package/dist/canvas/index.cjs +13 -13
  16. package/dist/canvas/index.js +1 -1
  17. package/dist/chart/contract.d.cts +95 -0
  18. package/dist/chart/contract.d.ts +95 -0
  19. package/dist/chart/controller.d.cts +4 -0
  20. package/dist/chart/controller.d.ts +4 -0
  21. package/dist/chart/index.cjs +492 -26
  22. package/dist/chart/index.d.cts +1 -0
  23. package/dist/chart/index.d.ts +1 -0
  24. package/dist/chart/index.js +476 -10
  25. package/dist/chart/tools.d.cts +3 -0
  26. package/dist/chart/tools.d.ts +3 -0
  27. package/dist/chart-maps/index.cjs +4 -64
  28. package/dist/chart-maps/index.js +3 -63
  29. package/dist/{chunk-YNFSH72F.js → chunk-2F3YDXCN.js} +1 -1
  30. package/dist/{chunk-QYXUE37Q.js → chunk-2XDNF73E.js} +1 -1
  31. package/dist/{chunk-3KNQ2W6X.cjs → chunk-3JKCREEU.cjs} +59 -53
  32. package/dist/{chunk-NMZQMPFZ.js → chunk-4LZQO5Y7.js} +2 -0
  33. package/dist/{chunk-B5W677L7.js → chunk-5HP2VSAS.js} +1 -1
  34. package/dist/chunk-5UGRMVNE.js +328 -0
  35. package/dist/{chunk-X4FTNFIA.js → chunk-7MGPW2OV.js} +1 -1
  36. package/dist/{chunk-BPJSI4NT.cjs → chunk-7W2EQQBP.cjs} +2 -2
  37. package/dist/{chunk-DGITFN73.cjs → chunk-BWJBZAUE.cjs} +8 -8
  38. package/dist/chunk-CHZYVNXZ.js +336 -0
  39. package/dist/{chunk-LETF75CA.js → chunk-CLB2I2FU.js} +1 -1
  40. package/dist/chunk-DRMZ5R3S.cjs +67 -0
  41. package/dist/{chunk-BAZMCFVL.js → chunk-DZVRH63Y.js} +1 -1
  42. package/dist/chunk-EI5GFTKG.js +67 -0
  43. package/dist/{chunk-U2ASNGO6.cjs → chunk-FXVCB6YG.cjs} +35 -35
  44. package/dist/{chunk-EU2ZZA6L.cjs → chunk-GHGBIAWQ.cjs} +126 -39
  45. package/dist/chunk-JV7DKLMX.js +1073 -0
  46. package/dist/{chunk-2WOGXEDX.cjs → chunk-M3RZOF3G.cjs} +1 -1
  47. package/dist/chunk-MFBUQC67.cjs +328 -0
  48. package/dist/{chunk-GSTSZPSR.js → chunk-N3SKPQEH.js} +225 -18
  49. package/dist/{chunk-J5VQYK7T.cjs → chunk-N5IMDAHM.cjs} +251 -44
  50. package/dist/{chunk-ININNHLM.js → chunk-NAHJV3O6.js} +11 -5
  51. package/dist/{chunk-IBXEQOGI.js → chunk-PYHB2EHE.js} +2 -324
  52. package/dist/chunk-QEUI6OGE.cjs +336 -0
  53. package/dist/{chunk-6ZSFRRJI.js → chunk-RSF6BT34.js} +1 -1
  54. package/dist/{chunk-JJ2H25JG.cjs → chunk-SNAFFCAX.cjs} +200 -174
  55. package/dist/chunk-T2HUQBRC.cjs +1073 -0
  56. package/dist/{chunk-M2ZVPU7L.cjs → chunk-TNLKFW7D.cjs} +23 -23
  57. package/dist/{chunk-KZI3YWKW.js → chunk-UXYCY3HP.js} +93 -6
  58. package/dist/{chunk-GSLOH2IN.cjs → chunk-VF6ODSYX.cjs} +2 -0
  59. package/dist/{chunk-NQUKTRKN.cjs → chunk-WZLNNGG3.cjs} +45 -45
  60. package/dist/{chunk-NRBGAEFI.cjs → chunk-Y3RUYOOW.cjs} +8 -330
  61. package/dist/{chunk-DDL3ZBHK.cjs → chunk-YJANF2BL.cjs} +86 -86
  62. package/dist/{chunk-TNHDCP4R.js → chunk-ZEI7ZEA4.js} +31 -5
  63. package/dist/commands/index.cjs +7 -323
  64. package/dist/commands/index.js +5 -321
  65. package/dist/extensions/index.cjs +4 -4
  66. package/dist/extensions/index.js +3 -3
  67. package/dist/image-editor/index.cjs +789 -789
  68. package/dist/image-editor/index.js +5 -5
  69. package/dist/index.cjs +9 -9
  70. package/dist/index.js +3 -3
  71. package/dist/paint/index.cjs +2 -2
  72. package/dist/paint/index.js +1 -1
  73. package/dist/paint/wet/world.d.cts +37 -1
  74. package/dist/paint/wet/world.d.ts +37 -1
  75. package/dist/paint-editor/brush-controls.d.cts +2 -0
  76. package/dist/paint-editor/brush-controls.d.ts +2 -0
  77. package/dist/paint-editor/brush-model.d.cts +14 -1
  78. package/dist/paint-editor/brush-model.d.ts +14 -1
  79. package/dist/paint-editor/index.cjs +343 -306
  80. package/dist/paint-editor/index.js +48 -11
  81. package/dist/paint-editor/ui.d.cts +1 -1
  82. package/dist/paint-editor/ui.d.ts +1 -1
  83. package/dist/paint-editor/wet.d.cts +8 -1
  84. package/dist/paint-editor/wet.d.ts +8 -1
  85. package/dist/persistence/index.cjs +24 -1042
  86. package/dist/persistence/index.js +22 -1040
  87. package/dist/tools/index.cjs +5 -3
  88. package/dist/tools/index.js +8 -6
  89. package/dist/vector/index.cjs +999 -999
  90. package/dist/vector/index.js +5 -5
  91. package/package.json +1 -1
  92. package/skills/pixerate-brushes/SKILL.md +1 -0
  93. package/skills/pixerate-paint-editor/SKILL.md +4 -11
  94. package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
  95. package/skills/pixerate-paint-editor/references/ghost.md +47 -0
  96. package/skills/pixerate-paint-watercolour/SKILL.md +1 -0
@@ -35,7 +35,7 @@ import {
35
35
  traceField,
36
36
  traceVectorImage,
37
37
  vectorTraceContours
38
- } from "../chunk-YNFSH72F.js";
38
+ } from "../chunk-2F3YDXCN.js";
39
39
  import {
40
40
  rasterizeCoverage
41
41
  } from "../chunk-ADMRNWR7.js";
@@ -66,7 +66,7 @@ import {
66
66
  reverseMorphContour,
67
67
  subpathToMorphContour,
68
68
  turnMorphContour
69
- } from "../chunk-QYXUE37Q.js";
69
+ } from "../chunk-2XDNF73E.js";
70
70
  import {
71
71
  DEFAULT_VECTOR_FONT,
72
72
  IDENTITY_MATRIX,
@@ -556,10 +556,10 @@ import {
556
556
  withVectorStrokes,
557
557
  withVectorTargetPaint,
558
558
  zigzagPaths
559
- } from "../chunk-TNHDCP4R.js";
559
+ } from "../chunk-ZEI7ZEA4.js";
560
560
  import {
561
561
  snapshotBrushLibrary
562
- } from "../chunk-KZI3YWKW.js";
562
+ } from "../chunk-UXYCY3HP.js";
563
563
  import "../chunk-JL6YH5WD.js";
564
564
  import {
565
565
  createProvenance
@@ -597,7 +597,7 @@ import {
597
597
  resolveEffectValues
598
598
  } from "../chunk-MV7CYFMJ.js";
599
599
  import "../chunk-V2ZCJRDM.js";
600
- import "../chunk-GSTSZPSR.js";
600
+ import "../chunk-N3SKPQEH.js";
601
601
  import "../chunk-W6JDUXP3.js";
602
602
  import {
603
603
  GRAIN_PATTERNS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.271.0",
3
+ "version": "0.272.1",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -20,6 +20,7 @@ built-in presets (read-only) and the user's brushes, shared by every editor that
20
20
  | Dynamics | Pen feel: pressure to size and opacity, smoothing, tilt, velocity, jitter (`sizeJitter`, `angleJitter` for rotation, `opacityJitter`, `scatter`), rotation, `count` (dabs per spacing step, each jittered) and `flip` (mirror dabs at random: `x`, `y`, `xy`). |
21
21
  | Behaviour | `surface` `dry`, `wet` (`wet` settings) or `thick` (`thick` impasto settings); paper `grain`; `exchange` (pick-up and mix; a `reservoir` makes a Mixer Brush); tool `strength`. |
22
22
  | Light | Light the brush gives off (`amount`), plus suggested layer `spill` and `glow`. |
23
+ | Ghost | On wet paint (`behaviour.surface: "wet"`): `linger` (0.5..60 s before the brush's own colour fades away) and `smear` (0..1, how much it lifts and drags the paint it crosses). Presets `ghost-wash`, `ghost-gouache`, `ghost-oil` and `invisible-ink`. |
23
24
  | Motion | Animation after painting (live effect paint, particle `waveSpeed`). |
24
25
  | Colour | A `default` colour, a `palette` of up to 16, `own` (always its own colour). Each is a hex or `rgba()` colour, a light / dark pair `{ light, dark }`, a gradient or effect paint. A gradient default is always painted; a solid or light / dark default becomes the editor's colour when the brush is chosen (unless the user locked theirs), resolved for the colour scheme. Canvas strokes and vector brushstrokes take it too, when they are given no colour. Canvas and vector have the same lock (`canvas.setColorLocked`, `vector.setColorLocked`), and a canvas colour taken from a light / dark default follows the scheme like the paint editor's; vector strokes already made keep theirs. |
25
26
 
@@ -142,10 +142,7 @@ Which facet sets which engine setting: [references/brush-facets.md](references/b
142
142
 
143
143
  ## Wet media
144
144
 
145
- Watercolour, gouache and wet oil run on a fluid simulation: lay washes light to dark, let them
146
- flow (`advance_wet_paint`), dry them (`dry_paint`) before glazing. Nothing moves for an agent
147
- until you advance or dry it, and saving dries the paint. Load `pixerate-paint-watercolour`, and
148
- read [references/wet-media.md](references/wet-media.md) for the engine and the wet tools.
145
+ Watercolour, gouache and wet oil run on a fluid simulation: lay washes light to dark, let them flow (`advance_wet_paint`), dry them (`dry_paint`) before glazing. Nothing moves for an agent until you advance or dry it, and saving dries the paint. Load `pixerate-paint-watercolour`, and read [references/wet-media.md](references/wet-media.md) for the engine and the wet tools. **Ghost paint and invisible ink** (`ghost` facet: `ghost-wash`, `ghost-gouache`, `ghost-oil`, `invisible-ink`) mix and flow while wet, then fade without leaving their own colour, leaving only a smear in the paint they touched: read [references/ghost.md](references/ghost.md).
149
146
 
150
147
  ## Oils and thick paint
151
148
 
@@ -295,7 +292,7 @@ Listing, saving, sharing and previewing brushes are the brush library's tools (`
295
292
  | Tool | Use |
296
293
  | --- | --- |
297
294
  | `get_brush` | Read a brush as facets (`brush`), or the active brush as edited (no `id`), with the `engine` and `category` it paints with, `builtin` (an unchanged preset) and `strokePaint` (what its next stroke paints). Read before changing a brush you did not build. |
298
- | `set_brush` | Choose the active brush (`id`, from `list_brush_presets`) and / or lay facets over it: `tip`, `marks`, `dynamics`, `behaviour`, `light`, `motion`, `colour` (objects merge, lists replace; marks of another kind replace the marks), `unset` facets to drop. Editor state, not saved: `create_brush` stores a brush. Returns `brush` (facets), `engine` and `problems` (values clamped). The old flat fields (`particle`, `impasto`, `behavior`…) are refused. |
295
+ | `set_brush` | Choose the active brush (`id`, from `list_brush_presets`) and / or lay facets over it: `tip`, `marks`, `dynamics`, `behaviour`, `light`, `ghost`, `motion`, `colour` (objects merge, lists replace; marks of another kind replace the marks), `unset` facets to drop. Editor state, not saved: `create_brush` stores a brush. Returns `brush` (facets), `engine` and `problems` (values clamped). The old flat fields (`particle`, `impasto`, `behavior`…) are refused. |
299
296
 
300
297
  ### Colour
301
298
 
@@ -345,7 +342,7 @@ Listing, saving, sharing and previewing brushes are the brush library's tools (`
345
342
 
346
343
  | Tool | Use |
347
344
  | --- | --- |
348
- | `get_wet_paint` | Read the wet paint: `wet`, the clock, `paused`, `speed`, `tilt`, the kernel (`backend`, `message` when it runs slower than it could, e.g. on one thread because the page is not cross-origin isolated (COOP / COEP)), the GPU accelerator (`engine`) and each wet layer (`wetCells`, `wetBounds`, `activeTiles`, settings, flow map). Call after wet strokes. |
345
+ | `get_wet_paint` | Read the wet paint: `wet`, the clock, `paused`, `speed`, `tilt`, the kernel (`backend`, `message` when it runs slower than it could, e.g. on one thread because the page is not cross-origin isolated (COOP / COEP)), the GPU accelerator (`engine`) and each wet layer (`wetCells`, `wetBounds`, `activeTiles`, settings, flow map, and `ghost: { remaining }` while ghost paint is fading). Call after wet strokes. |
349
346
  | `advance_wet_paint` | Let time pass: `steps` (120 = one second at the default speed) or `seconds`. The paint spreads, blooms, runs and dries. Not an undo step. Returns `steps`, `clock`, `stillWet`, `layers`. Call after a group of wet strokes, before `render_preview`. |
350
347
  | `dry_paint` | Dry wet paint at once where it is (one layer with `layerId` or all, optionally inside `rect`). One undo step. Returns `dried` (layer ids and rectangles) and `stillWet`. Dry before glazing over a wash. |
351
348
  | `wet_paper` | Pre-wet the paper with clear water over `rect` (default the canvas) on a layer, `amount` 0..1, for wet-in-wet. One undo step. Returns the rectangle and `wet`. Then paint into it. |
@@ -476,11 +473,7 @@ The host may add the shared document tools (see `pixerate-agent-tools`). A paint
476
473
  - **Wet paint keeps changing.** A preview right after a wet stroke shows it before it has
477
474
  flowed; `advance_wet_paint` first. Paint that should stay exactly where it was laid needs
478
475
  `dry_paint` (or a dry medium).
479
- - **Wet strokes on one layer interact**; washes that must not mix go on separate layers, or dry
480
- the first before painting the second (glazing). At most 8 layers hold wet paint at once, and the simulation holds at most 328 wet tiles (256 × 256 px each) across them; water that spreads past
481
- that limit is lost (`dry_paint` frees tiles). Multi-threaded wet media needs a cross-origin isolated
482
- page (COOP / COEP, for `SharedArrayBuffer`) and runs on one thread otherwise, more slowly but with
483
- the same result.
476
+ - **Wet strokes on one layer interact**; washes that must not mix go on separate layers, or dry the first before painting the second (glazing). Ghost paint (`ghost-wash`, `ghost-gouache`, `ghost-oil`, `invisible-ink`) only meets and smears paint on its own layer, so a ghost stroke on a new empty layer simply vanishes; ghost paint and light paint cannot share a layer while the ghost is fading. At most 8 layers hold wet paint at once, and the simulation holds at most 328 wet tiles (256 × 256 px each) across them; water that spreads past that limit is lost (`dry_paint` frees tiles). Multi-threaded wet media needs a cross-origin isolated page (COOP / COEP, for `SharedArrayBuffer`) and runs on one thread otherwise, more slowly but with the same result.
484
477
  - **Undoing far back** past the wet undo memory (512 MB by default) leaves that paint dry as it
485
478
  looked, rather than wet.
486
479
  - **Replays repeat what was recorded**: strokes, fills, clears, flattened relief and wet events.
@@ -20,6 +20,7 @@ more; this is where each one went.
20
20
  | Bristles | `tip.shape` `bristle` and `tip.bristle` |
21
21
  | A brush's own gradient (paint) | `colour.default` (a gradient); `unset: ['colour']` drops it |
22
22
  | Light | `light` (`amount`, `pressure`) |
23
+ | Ghost paint (linger, smear) | `ghost` (`linger`, `smear`); `unset: ['ghost']` drops it |
23
24
 
24
25
  ## Examples
25
26
 
@@ -0,0 +1,47 @@
1
+ # Ghost paint and invisible ink
2
+
3
+ Ghost paint is wet paint (`behaviour.surface: "wet"`) with a `ghost` facet (`linger` 0.5..60 s,
4
+ default 4; `smear` 0..1, default 0.3). While wet it looks and behaves like any watercolour,
5
+ gouache or wet oil: it flows with the water and its colour mixes visibly with the paint it meets.
6
+ Then its own colour fades away completely, leaving only what it did to the paint already on the
7
+ layer — a smear where it lifted and dragged that paint along. On bare paper it leaves nothing at
8
+ all.
9
+
10
+ ## Presets and settings
11
+
12
+ - **`ghost-wash`**: transparent watercolour ghost (`linger: 4`, `smear: 0.35`).
13
+ - **`ghost-gouache`**: opaque gouache ghost that mixes strongly while wet, then vanishes (`linger: 4`, `smear: 0.45`).
14
+ - **`ghost-oil`**: slow wet oil ghost (`linger: 8`, `smear: 0.55`).
15
+ - **`invisible-ink`**: a ghost brush with `behaviour.wet.pigment: 0` and `smear: 0.6`. Nothing
16
+ shows on bare paper; it reveals itself only as a smear in the wet or dried paint it crosses.
17
+ Because it lays no pigment, it lays no tracer, needs no fade, and does not interrupt another
18
+ ghost already fading on the layer.
19
+ - Any wet paint brush becomes a ghost brush with `set_brush` `{ ghost: { linger, smear } }`;
20
+ `unset: ["ghost"]` makes it ordinary wet paint again.
21
+
22
+ ## Working method
23
+
24
+ 1. **Paint on the layer that holds the paint you want to disturb.** Wet paint is per layer:
25
+ a ghost stroke on a new empty layer has nothing to smear and vanishes into bare paper.
26
+ 2. **Watch it mix while wet.** Call `advance_wet_paint` in short steps (`seconds: 0.5..1`) and
27
+ `render_preview` to see the ghost colour mixing and flowing with the layer's paint, and check
28
+ `get_wet_paint` (`layers[].ghost.remaining`, from 1 down to 0) to see how much of the fade is
29
+ left.
30
+ 3. **Finish the fade.** Advance past `linger` seconds, or call `dry_paint` (which finishes the
31
+ ghost fade at once before baking). With `smear: 0`, ghost paint passes over dried paint and
32
+ leaves it untouched; with `smear > 0`, it lifts dried paint along its path (`rewet` scaled by
33
+ `smear`) and drags both wet and lifted paint along the stroke.
34
+
35
+ ## Pitfalls
36
+
37
+ - **Wet paint is per layer.** Ghost paint only meets paint on its own layer. Painting a ghost
38
+ stroke on a new empty layer leaves nothing behind once it fades.
39
+ - **One ghost colour per layer at a time.** Painting a ghost stroke in a new colour on a layer
40
+ whose earlier ghost is still fading finishes the earlier ghost's colour fade at once (keeping
41
+ its smear) before starting the new colour.
42
+ - **Ghost and light paint cannot share a layer.** The ghost tracer uses the wet layer's light
43
+ channel, so a ghost stroke is refused on a layer that has light paint (`clear_light` or paint on
44
+ another layer), and a light brush is refused on a layer where ghost paint is still fading
45
+ (`dry_paint` first or use another layer). Once the ghost has faded, the layer is free again.
46
+ - **One solid colour per stroke.** Gradient paint, effect paint and multi-colour are refused on
47
+ ghost brushes.
@@ -77,6 +77,7 @@ block the light. See `references/light-paint.md` in `pixerate-paint-editor`.
77
77
  | Cauliflower blooms | Add water into a drying wash; `bloom` up |
78
78
  | A glowing (neon) wash | Dark paper (`set_paper` `color`), `glow-wash` or `light.amount` on a wet brush; flow, dry, `get_light` |
79
79
  | Stained glass, a lightbox | `set_paper` `stained-glass` (or `backlight`); strong glazes for panes, opaque black lines above |
80
+ | Disturb or smear a wash without adding colour | `ghost-wash`, `ghost-gouache` or `invisible-ink` (`ghost` `linger`, `smear`) on the same layer; see `references/ghost.md` |
80
81
 
81
82
  ## Recipes
82
83