@pixerate/editor 0.249.0 → 0.251.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 (158) hide show
  1. package/dist/agent/index.cjs +40 -41
  2. package/dist/agent/index.js +9 -10
  3. package/dist/animation/index.cjs +6 -7
  4. package/dist/animation/index.js +5 -6
  5. package/dist/animation-editor/index.cjs +124 -123
  6. package/dist/animation-editor/index.js +15 -14
  7. package/dist/brushes/index.cjs +1406 -0
  8. package/dist/brushes/index.d.cts +12 -0
  9. package/dist/brushes/index.d.ts +12 -0
  10. package/dist/brushes/index.js +1406 -0
  11. package/dist/brushes/migrate.d.cts +17 -0
  12. package/dist/brushes/migrate.d.ts +17 -0
  13. package/dist/brushes/normalize.d.cts +15 -0
  14. package/dist/brushes/normalize.d.ts +15 -0
  15. package/dist/brushes/presets.d.cts +12 -0
  16. package/dist/brushes/presets.d.ts +12 -0
  17. package/dist/brushes/resolve.d.cts +56 -0
  18. package/dist/brushes/resolve.d.ts +56 -0
  19. package/dist/brushes/schema.d.cts +29 -0
  20. package/dist/brushes/schema.d.ts +29 -0
  21. package/dist/brushes/types.d.cts +323 -0
  22. package/dist/brushes/types.d.ts +323 -0
  23. package/dist/{brushstrokeRender-T3JZST44.js → brushstrokeRender-5PYSKZIJ.js} +9 -8
  24. package/dist/{brushstrokeRender-GCKK7V2I.cjs → brushstrokeRender-7FLLSQEC.cjs} +15 -14
  25. package/dist/canvas/index.cjs +120 -65
  26. package/dist/canvas/index.d.cts +1 -0
  27. package/dist/canvas/index.d.ts +1 -0
  28. package/dist/canvas/index.js +88 -33
  29. package/dist/canvas/stickers.d.cts +35 -0
  30. package/dist/canvas/stickers.d.ts +35 -0
  31. package/dist/chart/index.cjs +159 -160
  32. package/dist/chart/index.js +9 -10
  33. package/dist/{chunk-RXZL4NG5.js → chunk-226QDRO3.js} +1 -1
  34. package/dist/{chunk-DOIU7VJG.js → chunk-2ZJ4DT3M.js} +1 -1
  35. package/dist/{chunk-XZNU4DUX.cjs → chunk-3NS5C7FB.cjs} +76 -76
  36. package/dist/{chunk-UTI5IITZ.cjs → chunk-4ZC5QJE2.cjs} +3 -3
  37. package/dist/{chunk-L3JFOTBQ.js → chunk-5E2Q7ZHI.js} +1 -1
  38. package/dist/{chunk-6BIDVPED.js → chunk-5JNA6LLY.js} +1 -1
  39. package/dist/{chunk-RD7RX52G.cjs → chunk-5UEFBM2M.cjs} +207 -18
  40. package/dist/{chunk-WA44NKPF.js → chunk-62Z5WLRA.js} +1 -1
  41. package/dist/{chunk-BVRRIW7F.js → chunk-6GRUVGKU.js} +3 -3
  42. package/dist/{chunk-QARCM66V.js → chunk-6ZZKRH7R.js} +3 -3
  43. package/dist/{chunk-BP6KSGVD.js → chunk-7272D3K2.js} +4 -6
  44. package/dist/{chunk-O75V4ZS3.js → chunk-7P6VF3FG.js} +2 -2
  45. package/dist/{chunk-AU6MWQKZ.js → chunk-ABL7IWFZ.js} +1 -1
  46. package/dist/{chunk-5RH3VXAK.js → chunk-APX63ILU.js} +4 -100
  47. package/dist/{chunk-W7L4HUT2.cjs → chunk-CJ6TBL2N.cjs} +16 -16
  48. package/dist/{chunk-7PT4RJL5.cjs → chunk-EUIDTZNQ.cjs} +111 -113
  49. package/dist/{chunk-CXXXAZ7H.js → chunk-F6R67I3A.js} +1 -1
  50. package/dist/{chunk-I7NJPHWV.cjs → chunk-FQPUF2W2.cjs} +35 -606
  51. package/dist/{chunk-D5KGAO4Z.js → chunk-GCVFEPJG.js} +2 -573
  52. package/dist/{chunk-LEQKZGQI.js → chunk-GOBOCZZI.js} +1 -1
  53. package/dist/{chunk-PZP2SZIZ.js → chunk-GYMMNCFT.js} +3 -3
  54. package/dist/{chunk-NUTMINJZ.cjs → chunk-H7ET2ISK.cjs} +52 -52
  55. package/dist/chunk-HS6QDWDF.cjs +1029 -0
  56. package/dist/{chunk-T7KQEMAE.cjs → chunk-HUAISCUX.cjs} +18 -18
  57. package/dist/{chunk-YGQVCQTG.js → chunk-ILP77UD6.js} +1 -1
  58. package/dist/{chunk-GHCSC2WP.cjs → chunk-ISIO63Q5.cjs} +21 -15
  59. package/dist/{chunk-S6OT6CTS.cjs → chunk-IWEVV63O.cjs} +31 -33
  60. package/dist/{chunk-OFH6Q67U.js → chunk-JA57JIT5.js} +9 -3
  61. package/dist/{chunk-LP2MCSBE.cjs → chunk-JFHBXNR2.cjs} +88 -88
  62. package/dist/{chunk-IOFVM3L3.cjs → chunk-JPEHXIB5.cjs} +10 -10
  63. package/dist/chunk-JSDND7DF.cjs +173 -0
  64. package/dist/{chunk-36ZTV7WO.js → chunk-L6Y7TSQ4.js} +1 -1
  65. package/dist/{chunk-KYX7NZ5V.cjs → chunk-LFMKWGFL.cjs} +1 -1
  66. package/dist/{chunk-V6DT2CDH.js → chunk-M2TPMYJE.js} +1 -1
  67. package/dist/{chunk-LJZRHVZV.cjs → chunk-M5GLQQWG.cjs} +2 -2
  68. package/dist/{chunk-JEGJP4OW.js → chunk-MHLU6GRJ.js} +196 -7
  69. package/dist/{chunk-KMPM5JM5.js → chunk-MONXNVZK.js} +4 -6
  70. package/dist/chunk-MTKY6K3Q.js +1029 -0
  71. package/dist/{chunk-MOW3JMNG.cjs → chunk-N76AMOKE.cjs} +42 -42
  72. package/dist/{chunk-75K3W4D6.cjs → chunk-NKGB64CW.cjs} +16 -16
  73. package/dist/{chunk-SGPIVHJB.js → chunk-P3K2JCJA.js} +3 -3
  74. package/dist/chunk-PXDIAYB6.cjs +594 -0
  75. package/dist/{chunk-UBRJOIR5.js → chunk-QC3OXRE4.js} +9 -9
  76. package/dist/{chunk-QOBCBGGI.cjs → chunk-QKXO6JPP.cjs} +14 -14
  77. package/dist/{chunk-WLJZZHUZ.cjs → chunk-QLSGTCYT.cjs} +23 -23
  78. package/dist/{chunk-7YW7T5TJ.js → chunk-RHPSE2YR.js} +2 -2
  79. package/dist/{chunk-44BMJJVA.cjs → chunk-RUONPPMC.cjs} +8 -8
  80. package/dist/{chunk-LJRCU3BJ.cjs → chunk-SABJMH6M.cjs} +150 -15
  81. package/dist/{chunk-XWOLPNBW.cjs → chunk-SOSBOS5T.cjs} +22 -22
  82. package/dist/chunk-SZTI6EER.js +13 -0
  83. package/dist/{chunk-PPFJHTW5.cjs → chunk-TFF2GTGN.cjs} +22 -24
  84. package/dist/{chunk-2SMMZDMG.cjs → chunk-TLOGFIIV.cjs} +37 -37
  85. package/dist/chunk-TXFWZ5ZJ.js +594 -0
  86. package/dist/chunk-U67EN7GG.cjs +13 -0
  87. package/dist/{chunk-GXAK6Q5J.js → chunk-UFEDHACQ.js} +2 -2
  88. package/dist/{chunk-GA4EU4P3.cjs → chunk-UXETV2NC.cjs} +4 -4
  89. package/dist/{chunk-N4DFDI73.js → chunk-WKMUBATU.js} +1 -1
  90. package/dist/{chunk-3R5P3DVY.cjs → chunk-WRZ6C4TU.cjs} +6 -6
  91. package/dist/{chunk-EJLRBS5Q.js → chunk-WZOGDKCQ.js} +137 -2
  92. package/dist/{chunk-6ADHGQ73.js → chunk-YBAPT7NL.js} +2 -4
  93. package/dist/{chunk-K5DS2JTA.cjs → chunk-Z3BRH4JK.cjs} +6 -6
  94. package/dist/{chunk-XNZFVYC2.cjs → chunk-ZBCT5MEA.cjs} +7 -7
  95. package/dist/color/index.cjs +4 -6
  96. package/dist/color/index.js +7 -9
  97. package/dist/effects/helpers.d.cts +6 -0
  98. package/dist/effects/helpers.d.ts +6 -0
  99. package/dist/effects/index.cjs +62 -60
  100. package/dist/effects/index.js +5 -3
  101. package/dist/effects/tools.d.cts +6 -0
  102. package/dist/effects/tools.d.ts +6 -0
  103. package/dist/export/index.cjs +7 -8
  104. package/dist/export/index.js +6 -7
  105. package/dist/extensions/index.cjs +10 -11
  106. package/dist/extensions/index.js +9 -10
  107. package/dist/gradient/index.cjs +33 -34
  108. package/dist/gradient/index.js +4 -5
  109. package/dist/image-editor/effects.d.cts +1 -1
  110. package/dist/image-editor/effects.d.ts +1 -1
  111. package/dist/image-editor/index.cjs +887 -863
  112. package/dist/image-editor/index.d.cts +1 -0
  113. package/dist/image-editor/index.d.ts +1 -0
  114. package/dist/image-editor/index.js +69 -45
  115. package/dist/image-editor/stickers.d.cts +9 -0
  116. package/dist/image-editor/stickers.d.ts +9 -0
  117. package/dist/index.cjs +16 -17
  118. package/dist/index.js +10 -11
  119. package/dist/paint/index.cjs +6 -4
  120. package/dist/paint/index.js +21 -19
  121. package/dist/paint-editor/brushes.d.cts +1 -2
  122. package/dist/paint-editor/brushes.d.ts +1 -2
  123. package/dist/paint-editor/index.cjs +2199 -699
  124. package/dist/paint-editor/index.js +1577 -77
  125. package/dist/paint-editor/mark-settings.d.cts +104 -0
  126. package/dist/paint-editor/mark-settings.d.ts +104 -0
  127. package/dist/paint-editor/procedural.d.cts +2 -75
  128. package/dist/paint-editor/procedural.d.ts +2 -75
  129. package/dist/paint-editor/stickers.d.cts +1 -22
  130. package/dist/paint-editor/stickers.d.ts +1 -22
  131. package/dist/raster/index.cjs +2 -2
  132. package/dist/raster/index.js +9 -9
  133. package/dist/stickers/index.cjs +22 -16
  134. package/dist/stickers/index.d.cts +1 -1
  135. package/dist/stickers/index.d.ts +1 -1
  136. package/dist/stickers/index.js +14 -8
  137. package/dist/stickers/tools.d.cts +57 -1
  138. package/dist/stickers/tools.d.ts +57 -1
  139. package/dist/tokens/index.cjs +3 -4
  140. package/dist/tokens/index.js +2 -3
  141. package/dist/typography/index.cjs +7 -8
  142. package/dist/typography/index.js +2 -3
  143. package/dist/vector/index.cjs +1011 -977
  144. package/dist/vector/index.d.cts +1 -0
  145. package/dist/vector/index.d.ts +1 -0
  146. package/dist/vector/index.js +47 -13
  147. package/dist/vector/stickers.d.cts +11 -0
  148. package/dist/vector/stickers.d.ts +11 -0
  149. package/dist/video-editor/index.cjs +349 -350
  150. package/dist/video-editor/index.js +9 -10
  151. package/package.json +11 -1
  152. package/skills/pixerate-image-editor/SKILL.md +1 -1
  153. package/skills/pixerate-stickers/SKILL.md +13 -1
  154. package/dist/chunk-7AHBW2CQ.cjs +0 -200
  155. package/dist/chunk-F67XMVDI.js +0 -200
  156. package/dist/chunk-H4AOUUBE.cjs +0 -2635
  157. package/dist/chunk-J7T5QZ45.js +0 -2635
  158. package/dist/chunk-ZEYMKDYS.cjs +0 -269
@@ -0,0 +1,323 @@
1
+ /**
2
+ * The brush model: one brush type made of facets people and agents can reason about (what it is,
3
+ * its tip, how it lays marks, how it feels, what the material does, light, motion and colour).
4
+ * Every facet but identity and tip is optional and sparse: a missing field takes the default the
5
+ * engine has always used, so a brush stores only what makes it what it is.
6
+ *
7
+ * Medium and variety are descriptive (browsing, filtering). What the renderer does is decided by
8
+ * the tip, the marks and the behaviour: `resolveEngine` derives the engine, and `resolveBrush`
9
+ * turns a brush into the flat form the paint engine reads (`ResolvedBrush`).
10
+ *
11
+ * Type-only imports keep this module free of the renderers.
12
+ */
13
+ import type { ColorValue } from '../color/dual.js';
14
+ import type { PaintGradientSource } from '../paint/gradient-paint.js';
15
+ import type { MixingModel } from '../paint/exchange.js';
16
+ import type { BlendMode } from '../raster/blend.js';
17
+ import type { BrushRotation, ImpastoTool, PaintBrush, WetMediumKind } from '../paint-editor/brushes.js';
18
+ import type { PaintEffectPaint } from '../paint-editor/effect-paint.js';
19
+ import type { DotRotation, DotTextureOrder, ParticleKind, ParticleRender, RibbonPairs } from '../paint-editor/mark-settings.js';
20
+ import type { StickerRef } from '../stickers/types.js';
21
+ /** `mark`: lays a material; `tool`: works on paint already down (erases, blends, smudges, wets…). */
22
+ export type BrushKind = 'mark' | 'tool';
23
+ export declare const BRUSH_KINDS: readonly BrushKind[];
24
+ /** What a mark brush lays: wet or thick `paint`, `ink`, a `dry` medium (pencil, pastel, charcoal) or a `spray`. */
25
+ export type BrushMedium = 'paint' | 'ink' | 'dry' | 'spray';
26
+ export declare const BRUSH_MEDIA: readonly BrushMedium[];
27
+ /** What a tool does to paint already down. */
28
+ export type BrushTool = 'eraser' | 'blender' | 'smudge' | 'water' | 'dryer' | 'blow' | 'blot' | 'wet-blend' | 'wet-drag';
29
+ export declare const BRUSH_TOOLS: readonly BrushTool[];
30
+ /**
31
+ * The tip's shape. `round`, `flat` and `chisel` are ellipses (their `roundness` and `angle` set
32
+ * the ellipse; the name is for people); `bristle` is a tuft of bristles; `stamp` lays textured
33
+ * stamps (with `marks` `objects` or `particles`).
34
+ */
35
+ export type BrushTipShape = 'round' | 'flat' | 'chisel' | 'bristle' | 'stamp';
36
+ export declare const BRUSH_TIP_SHAPES: readonly BrushTipShape[];
37
+ /** How the tip is laid along the path. */
38
+ export type BrushMarksKind = 'continuous' | 'particles' | 'objects';
39
+ export declare const BRUSH_MARKS_KINDS: readonly BrushMarksKind[];
40
+ /** What the material does on the surface: stays where it lands (`dry`), flows and dries (`wet`) or stands up in relief (`thick`). */
41
+ export type BrushSurface = 'dry' | 'wet' | 'thick';
42
+ export declare const BRUSH_SURFACES: readonly BrushSurface[];
43
+ /**
44
+ * A sticker a `stamp` tip lays: a sticker ref `provider:id` (`editor:star`, or a host library's
45
+ * sticker). Objects marks take any sticker; particle marks only the editor's own stamps.
46
+ */
47
+ export type BrushStamp = StickerRef;
48
+ /** The tuft of a `bristle` tip (each 0..1 unless noted). */
49
+ export interface BrushBristles {
50
+ /** Bristles in the tuft, 3..128 (default 32). */
51
+ count?: number;
52
+ /** Stiff bristles follow the tip; soft ones lag and bend into curves at turns (default 0.5). */
53
+ stiffness?: number;
54
+ /** How far pressure spreads the tuft (default 0.5). */
55
+ splay?: number;
56
+ /** Each bristle's line width as a fraction of the tip size (default 0.06). */
57
+ thickness?: number;
58
+ /** Paint per bristle: 1 never runs dry; lower, bristles run out along the stroke (default 0.6). */
59
+ load?: number;
60
+ /** Random variation between bristles (default 0.4). */
61
+ jitter?: number;
62
+ }
63
+ /** The tip: its shape and the dab it lays. */
64
+ export interface BrushTip {
65
+ shape: BrushTipShape;
66
+ /** Diameter in px, 1..2500 (default 20). */
67
+ size?: number;
68
+ /** Edge hardness 0 (soft) .. 1 (hard, default). */
69
+ hardness?: number;
70
+ /** Dab spacing as a fraction of the diameter, 0.01..10 (default 0.1). */
71
+ spacing?: number;
72
+ /** Tip angle in degrees, -360..360 (default 0). */
73
+ angle?: number;
74
+ /** Roundness 0.01..1: 1 round (default), lower a flat ellipse. */
75
+ roundness?: number;
76
+ /** Stroke opacity ceiling 0..1 (default 1). */
77
+ opacity?: number;
78
+ /** Build-up per dab 0..1 (default 1). */
79
+ flow?: number;
80
+ /** How the stroke paints onto the layer (default `normal`). */
81
+ blend?: BlendMode;
82
+ /** `bristle` tips: the tuft. */
83
+ bristle?: BrushBristles;
84
+ /** `stamp` tips: sticker refs (objects: any sticker, one picked at random per mark; particles: up to 4 editor stamps, in `marks.stampOrder`). */
85
+ stamps?: BrushStamp[];
86
+ }
87
+ /** Dabs laid along the path (the default). */
88
+ export interface BrushContinuousMarks {
89
+ kind: 'continuous';
90
+ }
91
+ /** Particles that move with the pen and draw as they go (each 0..1 unless noted). */
92
+ export interface BrushParticleMarks {
93
+ kind: 'particles';
94
+ /** How the particles move (default `spring`). */
95
+ physics?: ParticleKind;
96
+ /** How they draw (default `line`). */
97
+ render?: ParticleRender;
98
+ /** Particles, 1..64 (default 12). */
99
+ count?: number;
100
+ /** Mark size as a fraction of the tip size (default 0.08). */
101
+ size?: number;
102
+ /** How far apart they start, as a fraction of the tip size (default 0.5). */
103
+ spread?: number;
104
+ /** Spring, string and elastic stiffness (default 0.4). */
105
+ stiffness?: number;
106
+ /** How quickly motion dies down (default 0.25). */
107
+ damping?: number;
108
+ /** Orbit and flow speed (default 0.5). */
109
+ speed?: number;
110
+ /** Pull downwards, -1 (up) .. 1 (default 0). */
111
+ gravity?: number;
112
+ /** Flow particles' lifetime (default 0.5). */
113
+ life?: number;
114
+ /** Sequence: spacing of the beads (default 0.3). */
115
+ interval?: number;
116
+ /** Ribbon: fill opacity between the paths (default 0.5). */
117
+ ribbonFill?: number;
118
+ /** Ribbon: which paths are joined (default `adjacent`). */
119
+ ribbonPairs?: RibbonPairs;
120
+ /** Wave: sideways swing as a fraction of the tip size (default 0: none). */
121
+ waveAmplitude?: number;
122
+ /** Wave: wavelength in px of pen travel, 4..2000 (default 60). */
123
+ waveLength?: number;
124
+ /** Wave: how far out of step the particles' waves are (default 0). */
125
+ wavePhaseJitter?: number;
126
+ /** Stamp tips: the stamps in turn or at random (default `sequence`). */
127
+ stampOrder?: DotTextureOrder;
128
+ /** Stamp tips: how each stamp turns (default `random`). */
129
+ stampRotation?: DotRotation;
130
+ }
131
+ /** Each mark stays an editable object (a sticker) on a sticker layer (each 0..1 unless noted). */
132
+ export interface BrushObjectMarks {
133
+ kind: 'objects';
134
+ /** About `density × 4` marks per tip diameter of travel (default 0.4). */
135
+ density?: number;
136
+ /** Random size change (default 0.4). */
137
+ sizeJitter?: number;
138
+ /** Random turn as a fraction of ±180° (default 1). */
139
+ rotationJitter?: number;
140
+ /** How far from the path marks land, in tip diameters, 0..2 (default 0.5). */
141
+ scatter?: number;
142
+ /** Random colour change, hue and lightness (default 0.2). */
143
+ colourJitter?: number;
144
+ }
145
+ export type BrushMarks = BrushContinuousMarks | BrushParticleMarks | BrushObjectMarks;
146
+ /** Pen feel. Every amount is 0 (off) .. 1 unless noted. */
147
+ export interface BrushDynamics {
148
+ /** Pressure scales the size (default true). */
149
+ pressureSize?: boolean;
150
+ /** Pressure scales the opacity (default false). */
151
+ pressureOpacity?: boolean;
152
+ /** Position smoothing 0..0.95 (default 0). */
153
+ smoothing?: number;
154
+ /** Pressure smoothing 0..0.95 (default 0). */
155
+ pressureSmoothing?: number;
156
+ /** What turns the tip: a fixed angle, the stroke direction or the pen barrel (default `fixed`). */
157
+ rotation?: BrushRotation;
158
+ /** Size at zero pressure as a fraction of the full size (default 0). */
159
+ minSize?: number;
160
+ /** How much pressure scales flow (default 0). */
161
+ pressureFlow?: number;
162
+ /** Laying the pen down widens the tip, up to 2.5× (default 0). */
163
+ tiltSize?: number;
164
+ /** Laying the pen down flattens the tip (default 0). */
165
+ tiltRoundness?: number;
166
+ /** Laying the pen down lightens the mark (default 0). */
167
+ tiltOpacity?: number;
168
+ /** -1..1: positive grows the tip on fast strokes, negative thins it (default 0). */
169
+ velocitySize?: number;
170
+ /** -1..1: positive darkens fast marks, negative lightens them (default 0). */
171
+ velocityOpacity?: number;
172
+ /** Random size change per dab (default 0). */
173
+ sizeJitter?: number;
174
+ /** Random angle per dab, as a fraction of ±180° (default 0). */
175
+ angleJitter?: number;
176
+ /** Random opacity drop per dab (default 0). */
177
+ opacityJitter?: number;
178
+ /** Random offset across the stroke in diameters, 0..4 (default 0). */
179
+ scatter?: number;
180
+ }
181
+ /** A Mixer Brush's paint reservoir: the brush is loaded with colour and mixes what it picks up into it. */
182
+ export interface BrushReservoir {
183
+ /** How much paint it holds, 0..1 (default 0.5); below 1 it drains per dab. */
184
+ load?: number;
185
+ /** Refill with the paint colour at the start of each stroke (default true). */
186
+ refill?: boolean;
187
+ /** Load the current colour at all (default true; false: it only moves paint already down). */
188
+ loadsColour?: boolean;
189
+ }
190
+ /** Paint exchange with the canvas: picking paint up and mixing it into what the brush lays. */
191
+ export interface BrushExchange {
192
+ /** Pick-up ratio 0..1 (default 0; with a reservoir 0.5). */
193
+ pickup?: number;
194
+ /** Mix ratio 0..1 (default 0.5). */
195
+ mix?: number;
196
+ /** Keep the picked-up paint for the next stroke (default false). */
197
+ dirty?: boolean;
198
+ /** A reservoir makes this a Mixer Brush. */
199
+ reservoir?: BrushReservoir;
200
+ }
201
+ /** Wet surface settings (each 0..1 unless noted). */
202
+ export interface BrushWet {
203
+ /** The wet medium (default: the variety when it is one, else `watercolor`). */
204
+ medium?: WetMediumKind;
205
+ /** Water laid down (default 0.5). */
206
+ water?: number;
207
+ /** Pigment concentration (default 0.5). */
208
+ pigment?: number;
209
+ /** Body: 0 transparent .. 1 opaque (default 0). */
210
+ body?: number;
211
+ /** How much dried paint the water lifts again (default 0). */
212
+ rewet?: number;
213
+ /** Paint loading: 1 never runs out (default 1). */
214
+ load?: number;
215
+ /** Thinner: more transparent, runnier paint (default 0). */
216
+ thinner?: number;
217
+ }
218
+ /** Thick (impasto) surface settings (each 0..1 unless noted). */
219
+ export interface BrushThick {
220
+ /** What lays the paint (default `brush`). */
221
+ applicator?: ImpastoTool;
222
+ /** Relief per stroke (default 0.6). */
223
+ thickness?: number;
224
+ /** Shine (default 0.4). */
225
+ gloss?: number;
226
+ /** Metallic highlights (default 0). */
227
+ metallic?: number;
228
+ /** Paint loading (default 0.9). */
229
+ load?: number;
230
+ /** Thinner (default 0). */
231
+ thinner?: number;
232
+ /** Knife and brush: how much paint is dragged along (default 0.4). */
233
+ drag?: number;
234
+ /** Light paint: brighter rims, as on backlit glass (default 0). */
235
+ rim?: number;
236
+ /** Light paint: see-through middles (default 0). */
237
+ clarity?: number;
238
+ }
239
+ /** What the material does on the surface, and how tools work. */
240
+ export interface BrushBehaviour {
241
+ /** Default `dry`. */
242
+ surface?: BrushSurface;
243
+ /** Paper grain response 0 (ignores it) .. 1 (catches only the peaks), default 0. */
244
+ grain?: number;
245
+ /** How colours mix: `pigment` (Kubelka-Munk) or `rgb`. Default `pigment`; Mixer Brush and smudge `rgb`. */
246
+ mixing?: MixingModel;
247
+ exchange?: BrushExchange;
248
+ /** `surface: 'wet'` and the wet tools. */
249
+ wet?: BrushWet;
250
+ /** `surface: 'thick'`. */
251
+ thick?: BrushThick;
252
+ /** Tools: how strongly the blender, smudge or wet tool works, 0..1 (default 0.5; smudge 0.7). */
253
+ strength?: number;
254
+ /** Blender: neighbourhood radius as a fraction of the tip diameter, 0..1 (default 0.35). */
255
+ distance?: number;
256
+ /** Smudge: share of the carried paint kept per dab, 0..1 (default 0.85). */
257
+ length?: number;
258
+ }
259
+ /** Light the brush gives off with its colour. */
260
+ export interface BrushLight {
261
+ /** Light per dab, 0..1 (default 0: none). */
262
+ amount?: number;
263
+ /** Pressure scales the light (default false). */
264
+ pressure?: boolean;
265
+ /** Suggested layer spill, applied when the layer has none of its own: radius 0..512 px (0 off), strength 0..2. */
266
+ spill?: {
267
+ radius?: number;
268
+ strength?: number;
269
+ };
270
+ /** Suggest a glow layer effect for the brush's layer (glow stays a layer effect). */
271
+ glow?: boolean;
272
+ }
273
+ /** Animation after painting. */
274
+ export interface BrushMotion {
275
+ /** Effect paint keeps playing on stroke layers. */
276
+ live?: boolean;
277
+ /** Suggested playback rate, 1..60 frames per second. */
278
+ fps?: number;
279
+ /** Particle waves: how fast they run, 0..1 (default 0). */
280
+ waveSpeed?: number;
281
+ }
282
+ /**
283
+ * A colour a brush can carry: a solid colour (hex, `#rrggbbaa`, `rgba()` or a light / dark
284
+ * `DualColor`), a gradient, or effect paint.
285
+ */
286
+ export type BrushPaint = ColorValue | PaintGradientSource | PaintEffectPaint;
287
+ /** The brush's colours. The user's colour still wins unless `own` is set. */
288
+ export interface BrushColour {
289
+ /**
290
+ * The colour the brush starts with. A gradient is always painted (its `paint` / `secondary`
291
+ * stops take the user's colours); a solid colour or effect paint is suggested to the host.
292
+ */
293
+ default?: BrushPaint;
294
+ /** Up to 16 suggested colours. */
295
+ palette?: BrushPaint[];
296
+ /** The brush always paints its own colour (a rainbow marker). */
297
+ own?: boolean;
298
+ }
299
+ /** A brush: identity, what it is, and its facets. */
300
+ export interface Brush {
301
+ /** Library id: lowercase letters, digits and dashes, up to 64 characters. */
302
+ id: string;
303
+ /** Display name, up to 80 characters. */
304
+ name: string;
305
+ description?: string;
306
+ tags?: string[];
307
+ kind: BrushKind;
308
+ /** Marks only: what it lays. */
309
+ medium?: BrushMedium;
310
+ /** What kind of that medium (`oil`, `watercolor`, `pencil`, `highlighter`…): lowercase letters, digits and dashes. */
311
+ variety?: string;
312
+ /** Tools only: what it does. */
313
+ tool?: BrushTool;
314
+ tip: BrushTip;
315
+ marks?: BrushMarks;
316
+ dynamics?: BrushDynamics;
317
+ behaviour?: BrushBehaviour;
318
+ light?: BrushLight;
319
+ motion?: BrushMotion;
320
+ colour?: BrushColour;
321
+ }
322
+ /** The flat form the paint engine reads: every engine block, filled. */
323
+ export type ResolvedBrush = PaintBrush;
@@ -1,32 +1,33 @@
1
1
  import {
2
2
  pathDataToPolyline
3
- } from "./chunk-6BIDVPED.js";
3
+ } from "./chunk-5JNA6LLY.js";
4
4
  import {
5
5
  parseCssColor
6
6
  } from "./chunk-3CI7FRMK.js";
7
7
  import {
8
8
  BUILTIN_BRUSHES
9
- } from "./chunk-J7T5QZ45.js";
10
- import "./chunk-5RH3VXAK.js";
9
+ } from "./chunk-MTKY6K3Q.js";
10
+ import "./chunk-APX63ILU.js";
11
11
  import {
12
12
  formatNumber,
13
13
  getShapeSvg,
14
14
  resolveCanvasGradient
15
15
  } from "./chunk-PWBZH3FK.js";
16
+ import "./chunk-SZTI6EER.js";
16
17
  import {
17
18
  BrushstrokeCache,
18
19
  brushstrokeDataUrl,
19
- isBrushstrokeBrush,
20
+ isBrushstrokeBrush
21
+ } from "./chunk-TXFWZ5ZJ.js";
22
+ import {
20
23
  parsePaintSource
21
- } from "./chunk-D5KGAO4Z.js";
24
+ } from "./chunk-GCVFEPJG.js";
22
25
  import "./chunk-4D6KP5BV.js";
23
26
  import "./chunk-ODBT55Q7.js";
24
- import "./chunk-IRSTHLQQ.js";
25
27
  import "./chunk-OTTT5N3K.js";
28
+ import "./chunk-IRSTHLQQ.js";
26
29
  import "./chunk-HVVR5PZW.js";
27
30
  import "./chunk-QGHEDC7B.js";
28
- import "./chunk-F67XMVDI.js";
29
- import "./chunk-6ONMQ6WF.js";
30
31
 
31
32
  // src/canvas/brushstrokeRender.ts
32
33
  var DRY = BUILTIN_BRUSHES.filter((b) => isBrushstrokeBrush(b) && b.light.amount === 0);
@@ -1,45 +1,46 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkKYX7NZ5Vcjs = require('./chunk-KYX7NZ5V.cjs');
3
+ var _chunkLFMKWGFLcjs = require('./chunk-LFMKWGFL.cjs');
4
4
 
5
5
 
6
6
  var _chunkA2IS7EHEcjs = require('./chunk-A2IS7EHE.cjs');
7
7
 
8
8
 
9
- var _chunkH4AOUUBEcjs = require('./chunk-H4AOUUBE.cjs');
10
- require('./chunk-ZEYMKDYS.cjs');
9
+ var _chunkHS6QDWDFcjs = require('./chunk-HS6QDWDF.cjs');
10
+ require('./chunk-JSDND7DF.cjs');
11
11
 
12
12
 
13
13
 
14
14
 
15
15
  var _chunkNM3G4VQTcjs = require('./chunk-NM3G4VQT.cjs');
16
+ require('./chunk-U67EN7GG.cjs');
16
17
 
17
18
 
18
19
 
19
20
 
21
+ var _chunkPXDIAYB6cjs = require('./chunk-PXDIAYB6.cjs');
20
22
 
21
- var _chunkI7NJPHWVcjs = require('./chunk-I7NJPHWV.cjs');
23
+
24
+ var _chunkFQPUF2W2cjs = require('./chunk-FQPUF2W2.cjs');
22
25
  require('./chunk-3K6HWEXZ.cjs');
23
26
  require('./chunk-YQGCPL5X.cjs');
24
- require('./chunk-2VX55NFM.cjs');
25
27
  require('./chunk-W5M3J7PV.cjs');
28
+ require('./chunk-2VX55NFM.cjs');
26
29
  require('./chunk-474IQG74.cjs');
27
30
  require('./chunk-XFM3OCHU.cjs');
28
- require('./chunk-7AHBW2CQ.cjs');
29
- require('./chunk-IPJ3TEYR.cjs');
30
31
 
31
32
  // src/canvas/brushstrokeRender.ts
32
- var DRY = _chunkH4AOUUBEcjs.BUILTIN_BRUSHES.filter((b) => _chunkI7NJPHWVcjs.isBrushstrokeBrush.call(void 0, b) && b.light.amount === 0);
33
+ var DRY = _chunkHS6QDWDFcjs.BUILTIN_BRUSHES.filter((b) => _chunkPXDIAYB6cjs.isBrushstrokeBrush.call(void 0, b) && b.light.amount === 0);
33
34
  function listCanvasBrushes() {
34
35
  return DRY.map((b) => ({ id: b.id, name: b.name, category: b.category, size: b.tip.size }));
35
36
  }
36
37
  function resolveCanvasBrush(brush, width) {
37
38
  const given = width !== void 0 && Number.isFinite(width) ? Math.max(1, width) : void 0;
38
39
  if (typeof brush === "string") {
39
- const preset = _chunkH4AOUUBEcjs.BUILTIN_BRUSHES.find((b) => b.id === brush);
40
+ const preset = _chunkHS6QDWDFcjs.BUILTIN_BRUSHES.find((b) => b.id === brush);
40
41
  const ids = DRY.map((b) => b.id).join(", ");
41
42
  if (!preset) throw new Error(`Unknown brush '${brush}'. Use one of the dry paint presets (${ids}) or tip settings ({ hardness, spacing, flow, \u2026 }).`);
42
- if (!_chunkI7NJPHWVcjs.isBrushstrokeBrush.call(void 0, preset)) {
43
+ if (!_chunkPXDIAYB6cjs.isBrushstrokeBrush.call(void 0, preset)) {
43
44
  throw new Error(`Brush '${brush}' (${preset.name}) is not a dry brush: brushed canvas strokes use dry media only (wet paint needs an area to flow in; mixer, blender, smudge and eraser brushes need paint under them). Use one of: ${ids}.`);
44
45
  }
45
46
  return given === void 0 ? preset : { ...preset, tip: { ...preset.tip, size: given } };
@@ -50,7 +51,7 @@ function resolveCanvasBrush(brush, width) {
50
51
  return { size: _nullishCoalesce(given, () => ( 3)), ...brush };
51
52
  }
52
53
  function resolveCanvasPaint(paint) {
53
- const source = _chunkI7NJPHWVcjs.parsePaintSource.call(void 0, paint, "paint");
54
+ const source = _chunkFQPUF2W2cjs.parsePaintSource.call(void 0, paint, "paint");
54
55
  if (source.type === "gradient" && (source.map.by === "velocity" || source.map.by === "time")) {
55
56
  throw new Error(`paint.map.by "${source.map.by}" needs timed samples, which canvas strokes do not record; use distance, pressure, tilt, direction, across-tip or random.`);
56
57
  }
@@ -71,14 +72,14 @@ function strokeColor(shape) {
71
72
  const n = parseInt(parsed.hex.slice(1), 16);
72
73
  return [n >> 16 & 255, n >> 8 & 255, n & 255, Math.round(parsed.alpha * 255)];
73
74
  }
74
- var cache = new (0, _chunkI7NJPHWVcjs.BrushstrokeCache)(128);
75
+ var cache = new (0, _chunkPXDIAYB6cjs.BrushstrokeCache)(128);
75
76
  var urls = /* @__PURE__ */ new WeakMap();
76
77
  function renderShapeBrushstrokeNow(shape, scale, place = {}) {
77
78
  const seed = shape.brush.seed;
78
79
  const textured = typeof seed === "number" && Number.isFinite(seed);
79
80
  const size = _nullishCoalesce(shape.brush.size, () => ( (textured ? void 0 : _nullishCoalesce(shape.strokeWidth, () => ( 3)))));
80
81
  const brush = resolveCanvasBrush(shape.brush.brush, size);
81
- const points = _chunkKYX7NZ5Vcjs.pathDataToPolyline.call(void 0, shape.d);
82
+ const points = _chunkLFMKWGFLcjs.pathDataToPolyline.call(void 0, shape.d);
82
83
  if (!points.length) return null;
83
84
  const { pressure, tiltX, tiltY } = shape.brush;
84
85
  const input = {
@@ -101,7 +102,7 @@ function renderShapeBrushstrokeNow(shape, scale, place = {}) {
101
102
  if (!stroke.bounds) return null;
102
103
  let href = urls.get(stroke);
103
104
  if (href === void 0) {
104
- href = _chunkI7NJPHWVcjs.brushstrokeDataUrl.call(void 0, stroke);
105
+ href = _chunkPXDIAYB6cjs.brushstrokeDataUrl.call(void 0, stroke);
105
106
  urls.set(stroke, href);
106
107
  }
107
108
  return { href, ...stroke.bounds, scale: stroke.scale };