@pixerate/editor 0.250.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 (123) 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 +70 -70
  6. package/dist/animation-editor/index.js +12 -12
  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-2FHFLSEG.js → brushstrokeRender-5PYSKZIJ.js} +8 -8
  24. package/dist/{brushstrokeRender-QGRXOKDA.cjs → brushstrokeRender-7FLLSQEC.cjs} +14 -14
  25. package/dist/canvas/index.cjs +57 -58
  26. package/dist/canvas/index.js +31 -32
  27. package/dist/chart/index.cjs +159 -160
  28. package/dist/chart/index.js +9 -10
  29. package/dist/{chunk-NOHJP5TK.js → chunk-2ZJ4DT3M.js} +1 -1
  30. package/dist/{chunk-XZNU4DUX.cjs → chunk-3NS5C7FB.cjs} +76 -76
  31. package/dist/{chunk-UTI5IITZ.cjs → chunk-4ZC5QJE2.cjs} +3 -3
  32. package/dist/{chunk-SMSGP2HQ.js → chunk-5JNA6LLY.js} +1 -1
  33. package/dist/{chunk-RD7RX52G.cjs → chunk-5UEFBM2M.cjs} +207 -18
  34. package/dist/{chunk-WA44NKPF.js → chunk-62Z5WLRA.js} +1 -1
  35. package/dist/{chunk-BVRRIW7F.js → chunk-6GRUVGKU.js} +3 -3
  36. package/dist/{chunk-QARCM66V.js → chunk-6ZZKRH7R.js} +3 -3
  37. package/dist/{chunk-BP6KSGVD.js → chunk-7272D3K2.js} +4 -6
  38. package/dist/{chunk-NTRAVM2I.js → chunk-7P6VF3FG.js} +2 -2
  39. package/dist/chunk-APX63ILU.js +173 -0
  40. package/dist/{chunk-W7L4HUT2.cjs → chunk-CJ6TBL2N.cjs} +16 -16
  41. package/dist/{chunk-7PT4RJL5.cjs → chunk-EUIDTZNQ.cjs} +111 -113
  42. package/dist/{chunk-CXXXAZ7H.js → chunk-F6R67I3A.js} +1 -1
  43. package/dist/{chunk-I7NJPHWV.cjs → chunk-FQPUF2W2.cjs} +35 -606
  44. package/dist/{chunk-D5KGAO4Z.js → chunk-GCVFEPJG.js} +2 -573
  45. package/dist/{chunk-LEQKZGQI.js → chunk-GOBOCZZI.js} +1 -1
  46. package/dist/{chunk-KDLBJ6QR.js → chunk-GYMMNCFT.js} +3 -3
  47. package/dist/{chunk-NUTMINJZ.cjs → chunk-H7ET2ISK.cjs} +52 -52
  48. package/dist/chunk-HS6QDWDF.cjs +1029 -0
  49. package/dist/{chunk-T7KQEMAE.cjs → chunk-HUAISCUX.cjs} +18 -18
  50. package/dist/{chunk-YGQVCQTG.js → chunk-ILP77UD6.js} +1 -1
  51. package/dist/{chunk-S6OT6CTS.cjs → chunk-IWEVV63O.cjs} +31 -33
  52. package/dist/{chunk-M2VKFE5L.cjs → chunk-JFHBXNR2.cjs} +88 -88
  53. package/dist/{chunk-WPUXGDH4.cjs → chunk-JPEHXIB5.cjs} +10 -10
  54. package/dist/chunk-JSDND7DF.cjs +173 -0
  55. package/dist/{chunk-36ZTV7WO.js → chunk-L6Y7TSQ4.js} +1 -1
  56. package/dist/{chunk-YW43M56C.cjs → chunk-LFMKWGFL.cjs} +1 -1
  57. package/dist/{chunk-V6DT2CDH.js → chunk-M2TPMYJE.js} +1 -1
  58. package/dist/{chunk-LJZRHVZV.cjs → chunk-M5GLQQWG.cjs} +2 -2
  59. package/dist/{chunk-JEGJP4OW.js → chunk-MHLU6GRJ.js} +196 -7
  60. package/dist/{chunk-KMPM5JM5.js → chunk-MONXNVZK.js} +4 -6
  61. package/dist/chunk-MTKY6K3Q.js +1029 -0
  62. package/dist/{chunk-MOW3JMNG.cjs → chunk-N76AMOKE.cjs} +42 -42
  63. package/dist/{chunk-75K3W4D6.cjs → chunk-NKGB64CW.cjs} +16 -16
  64. package/dist/{chunk-SGPIVHJB.js → chunk-P3K2JCJA.js} +3 -3
  65. package/dist/chunk-PXDIAYB6.cjs +594 -0
  66. package/dist/{chunk-3TWOCSCY.js → chunk-QC3OXRE4.js} +9 -9
  67. package/dist/{chunk-YM6ZBTXG.cjs → chunk-QLSGTCYT.cjs} +23 -23
  68. package/dist/{chunk-7YW7T5TJ.js → chunk-RHPSE2YR.js} +2 -2
  69. package/dist/{chunk-44BMJJVA.cjs → chunk-RUONPPMC.cjs} +8 -8
  70. package/dist/{chunk-ATK6ABN3.cjs → chunk-SABJMH6M.cjs} +145 -12
  71. package/dist/{chunk-XWOLPNBW.cjs → chunk-SOSBOS5T.cjs} +22 -22
  72. package/dist/{chunk-PPFJHTW5.cjs → chunk-TFF2GTGN.cjs} +22 -24
  73. package/dist/{chunk-X7WRL5ZZ.cjs → chunk-TLOGFIIV.cjs} +37 -37
  74. package/dist/chunk-TXFWZ5ZJ.js +594 -0
  75. package/dist/{chunk-GXAK6Q5J.js → chunk-UFEDHACQ.js} +2 -2
  76. package/dist/{chunk-GA4EU4P3.cjs → chunk-UXETV2NC.cjs} +4 -4
  77. package/dist/{chunk-N4DFDI73.js → chunk-WKMUBATU.js} +1 -1
  78. package/dist/{chunk-3R5P3DVY.cjs → chunk-WRZ6C4TU.cjs} +6 -6
  79. package/dist/{chunk-U4NUOKBT.js → chunk-WZOGDKCQ.js} +134 -1
  80. package/dist/{chunk-6ADHGQ73.js → chunk-YBAPT7NL.js} +2 -4
  81. package/dist/color/index.cjs +4 -6
  82. package/dist/color/index.js +7 -9
  83. package/dist/export/index.cjs +7 -8
  84. package/dist/export/index.js +6 -7
  85. package/dist/extensions/index.cjs +10 -11
  86. package/dist/extensions/index.js +9 -10
  87. package/dist/gradient/index.cjs +33 -34
  88. package/dist/gradient/index.js +4 -5
  89. package/dist/image-editor/index.cjs +845 -844
  90. package/dist/image-editor/index.js +39 -38
  91. package/dist/index.cjs +16 -17
  92. package/dist/index.js +10 -11
  93. package/dist/paint/index.cjs +6 -4
  94. package/dist/paint/index.js +21 -19
  95. package/dist/paint-editor/brushes.d.cts +1 -2
  96. package/dist/paint-editor/brushes.d.ts +1 -2
  97. package/dist/paint-editor/index.cjs +2193 -694
  98. package/dist/paint-editor/index.js +1575 -76
  99. package/dist/paint-editor/mark-settings.d.cts +104 -0
  100. package/dist/paint-editor/mark-settings.d.ts +104 -0
  101. package/dist/paint-editor/procedural.d.cts +2 -75
  102. package/dist/paint-editor/procedural.d.ts +2 -75
  103. package/dist/paint-editor/stickers.d.cts +1 -22
  104. package/dist/paint-editor/stickers.d.ts +1 -22
  105. package/dist/raster/index.cjs +2 -2
  106. package/dist/raster/index.js +9 -9
  107. package/dist/stickers/index.cjs +10 -10
  108. package/dist/stickers/index.js +9 -9
  109. package/dist/tokens/index.cjs +3 -4
  110. package/dist/tokens/index.js +2 -3
  111. package/dist/typography/index.cjs +7 -8
  112. package/dist/typography/index.js +2 -3
  113. package/dist/vector/index.cjs +974 -974
  114. package/dist/vector/index.js +12 -12
  115. package/dist/video-editor/index.cjs +6 -7
  116. package/dist/video-editor/index.js +5 -6
  117. package/package.json +11 -1
  118. package/dist/chunk-4JNWA3VT.cjs +0 -302
  119. package/dist/chunk-7AHBW2CQ.cjs +0 -200
  120. package/dist/chunk-F67XMVDI.js +0 -200
  121. package/dist/chunk-GT77U7QG.cjs +0 -2637
  122. package/dist/chunk-OTEPAQJX.js +0 -2637
  123. package/dist/chunk-WKH5ZAUA.js +0 -302
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Version 1 brushes (`PaintBrush`, the flat engine form) to facet brushes. Files, documents and
3
+ * recorded strokes written before the facet model still load: each v1 brush becomes the sparse
4
+ * facet brush that resolves back to it.
5
+ *
6
+ * What the engine reads survives exactly. Settings of engine blocks the brush's engine never
7
+ * reads (a dab brush's mixer settings) are dropped, and the category is derived again
8
+ * (`resolveCategory`), so a v1 brush filed under a category its settings do not match moves.
9
+ */
10
+ import { type PaintBrushInput } from '../paint-editor/brushes.cjs';
11
+ import type { Brush } from './types.cjs';
12
+ /**
13
+ * The facet brush a v1 brush (any `PaintBrush`, or the JSON of one) amounts to: its engine's
14
+ * settings, stored only where they differ from that engine's defaults.
15
+ * `resolveBrush(migrateBrushV1(b))` paints exactly as `b` does.
16
+ */
17
+ export declare function migrateBrushV1(raw: PaintBrushInput): Brush;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Version 1 brushes (`PaintBrush`, the flat engine form) to facet brushes. Files, documents and
3
+ * recorded strokes written before the facet model still load: each v1 brush becomes the sparse
4
+ * facet brush that resolves back to it.
5
+ *
6
+ * What the engine reads survives exactly. Settings of engine blocks the brush's engine never
7
+ * reads (a dab brush's mixer settings) are dropped, and the category is derived again
8
+ * (`resolveCategory`), so a v1 brush filed under a category its settings do not match moves.
9
+ */
10
+ import { type PaintBrushInput } from '../paint-editor/brushes.js';
11
+ import type { Brush } from './types.js';
12
+ /**
13
+ * The facet brush a v1 brush (any `PaintBrush`, or the JSON of one) amounts to: its engine's
14
+ * settings, stored only where they differ from that engine's defaults.
15
+ * `resolveBrush(migrateBrushV1(b))` paints exactly as `b` does.
16
+ */
17
+ export declare function migrateBrushV1(raw: PaintBrushInput): Brush;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `normalizeBrushSpec`: a brush with every given field checked against `BRUSH_JSON_SCHEMA`. It
3
+ * stays sparse (missing fields are not filled in): numbers are clamped into range, integers
4
+ * rounded, unknown fields, bad values and facets the brush does not use are dropped, and each
5
+ * change is reported in `problems` so a caller (or an agent) sees what was fixed. Only an id,
6
+ * name or kind it cannot make sense of throws.
7
+ */
8
+ import { type Brush, type BrushTool } from './types.cjs';
9
+ /** The tools that work on the wet layer. */
10
+ export declare const WET_BRUSH_TOOLS: readonly BrushTool[];
11
+ /**
12
+ * A brush with every given field in range (see the module comment). Throws when the id, name or
13
+ * kind cannot be used; every other fix is reported in `problems`.
14
+ */
15
+ export declare function normalizeBrushSpec(raw: unknown, problems?: string[]): Brush;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `normalizeBrushSpec`: a brush with every given field checked against `BRUSH_JSON_SCHEMA`. It
3
+ * stays sparse (missing fields are not filled in): numbers are clamped into range, integers
4
+ * rounded, unknown fields, bad values and facets the brush does not use are dropped, and each
5
+ * change is reported in `problems` so a caller (or an agent) sees what was fixed. Only an id,
6
+ * name or kind it cannot make sense of throws.
7
+ */
8
+ import { type Brush, type BrushTool } from './types.js';
9
+ /** The tools that work on the wet layer. */
10
+ export declare const WET_BRUSH_TOOLS: readonly BrushTool[];
11
+ /**
12
+ * A brush with every given field in range (see the module comment). Throws when the id, name or
13
+ * kind cannot be used; every other fix is reported in `problems`.
14
+ */
15
+ export declare function normalizeBrushSpec(raw: unknown, problems?: string[]): Brush;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The built-in brushes as facet specs. Each resolves (`resolveBrush`) to exactly the paint
3
+ * editor's built-in brush of the same id (`BUILTIN_BRUSHES`, which `tests/brushes.test.ts`
4
+ * checks), so the engine paints them as it always has. Medium and variety are new: they file
5
+ * each brush under what it is for browsing and filtering. Only what differs from the engine's
6
+ * defaults is written down.
7
+ *
8
+ * Our own settings; none come from another product.
9
+ */
10
+ import type { Brush } from './types.cjs';
11
+ /** The built-in brush library, in the paint editor's order. */
12
+ export declare const BRUSH_PRESETS: readonly Brush[];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The built-in brushes as facet specs. Each resolves (`resolveBrush`) to exactly the paint
3
+ * editor's built-in brush of the same id (`BUILTIN_BRUSHES`, which `tests/brushes.test.ts`
4
+ * checks), so the engine paints them as it always has. Medium and variety are new: they file
5
+ * each brush under what it is for browsing and filtering. Only what differs from the engine's
6
+ * defaults is written down.
7
+ *
8
+ * Our own settings; none come from another product.
9
+ */
10
+ import type { Brush } from './types.js';
11
+ /** The built-in brush library, in the paint editor's order. */
12
+ export declare const BRUSH_PRESETS: readonly Brush[];
@@ -0,0 +1,56 @@
1
+ /**
2
+ * From a facet `Brush` to the flat form the paint engine reads (`ResolvedBrush`, today's
3
+ * `PaintBrush`). The engine is derived from the tip, the marks and the behaviour
4
+ * (`resolveEngine`); the category the libraries group by is derived too (`resolveCategory`).
5
+ *
6
+ * `BRUSH_FIELDS` maps each facet field to the engine field it sets, for the engines that read it.
7
+ * `migrateBrushV1` reads the same map the other way, so the two directions cannot drift apart.
8
+ */
9
+ import { type PaintBrushCategory, type PaintBrushEngine, type WetMediumKind, type WetTool } from '../paint-editor/brushes.cjs';
10
+ import type { Brush, BrushTool, ResolvedBrush } from './types.cjs';
11
+ /** One facet field and the engine field it sets. */
12
+ export interface BrushField {
13
+ /** Dot path in the facet brush. */
14
+ facet: string;
15
+ /** Dot path in the resolved brush. */
16
+ engine: string;
17
+ /** The engines that read it. */
18
+ engines: readonly PaintBrushEngine[];
19
+ /** When the two forms differ: facet value → engine value, and back. */
20
+ map?: {
21
+ toEngine(v: unknown): unknown;
22
+ toFacet(v: unknown): unknown;
23
+ };
24
+ /** Read only on these tip shapes. */
25
+ shapes?: readonly string[];
26
+ }
27
+ /** Every facet field and where it lands in the resolved brush. */
28
+ export declare const BRUSH_FIELDS: readonly BrushField[];
29
+ /** The wet tool each wet-layer tool brush is. */
30
+ export declare const WET_TOOL_OF: Readonly<Partial<Record<BrushTool, WetTool>>>;
31
+ export declare function getPath(o: unknown, path: string): unknown;
32
+ export declare function setPath(o: Record<string, unknown>, path: string, value: unknown): void;
33
+ /**
34
+ * The engine that renders a brush: tools by what they do; marks by how they are laid
35
+ * (particles, objects), the tip (bristle), the surface (thick, wet) and the paint exchange (a
36
+ * reservoir makes a Mixer Brush); everything else paints dabs.
37
+ */
38
+ export declare function resolveEngine(brush: Pick<Brush, 'kind' | 'tool' | 'tip' | 'marks' | 'behaviour'>): PaintBrushEngine;
39
+ /** The wet medium a wet brush paints: `behaviour.wet.medium`, else its variety when that is a wet medium. */
40
+ export declare function resolveWetMedium(brush: Pick<Brush, 'variety' | 'behaviour'>): WetMediumKind | undefined;
41
+ /**
42
+ * The library category a brush is grouped under: tools by what they do; light brushes; then by
43
+ * engine (particles are procedural, objects stickers, bristle, thick impasto, wet oil or
44
+ * watercolour, the Mixer Brush); dab brushes by variety, then medium.
45
+ */
46
+ export declare function resolveCategory(brush: Brush, engine?: PaintBrushEngine): PaintBrushCategory;
47
+ export interface ResolveBrushOptions {
48
+ /** Mark the result built-in (a library's presets). */
49
+ builtin?: boolean;
50
+ }
51
+ /**
52
+ * The flat engine form of a brush. Missing fields take the engine's defaults, and every value is
53
+ * clamped into range, so any brush resolves (check it with `normalizeBrushSpec` first to hear
54
+ * what was out of range).
55
+ */
56
+ export declare function resolveBrush(brush: Brush, options?: ResolveBrushOptions): ResolvedBrush;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * From a facet `Brush` to the flat form the paint engine reads (`ResolvedBrush`, today's
3
+ * `PaintBrush`). The engine is derived from the tip, the marks and the behaviour
4
+ * (`resolveEngine`); the category the libraries group by is derived too (`resolveCategory`).
5
+ *
6
+ * `BRUSH_FIELDS` maps each facet field to the engine field it sets, for the engines that read it.
7
+ * `migrateBrushV1` reads the same map the other way, so the two directions cannot drift apart.
8
+ */
9
+ import { type PaintBrushCategory, type PaintBrushEngine, type WetMediumKind, type WetTool } from '../paint-editor/brushes.js';
10
+ import type { Brush, BrushTool, ResolvedBrush } from './types.js';
11
+ /** One facet field and the engine field it sets. */
12
+ export interface BrushField {
13
+ /** Dot path in the facet brush. */
14
+ facet: string;
15
+ /** Dot path in the resolved brush. */
16
+ engine: string;
17
+ /** The engines that read it. */
18
+ engines: readonly PaintBrushEngine[];
19
+ /** When the two forms differ: facet value → engine value, and back. */
20
+ map?: {
21
+ toEngine(v: unknown): unknown;
22
+ toFacet(v: unknown): unknown;
23
+ };
24
+ /** Read only on these tip shapes. */
25
+ shapes?: readonly string[];
26
+ }
27
+ /** Every facet field and where it lands in the resolved brush. */
28
+ export declare const BRUSH_FIELDS: readonly BrushField[];
29
+ /** The wet tool each wet-layer tool brush is. */
30
+ export declare const WET_TOOL_OF: Readonly<Partial<Record<BrushTool, WetTool>>>;
31
+ export declare function getPath(o: unknown, path: string): unknown;
32
+ export declare function setPath(o: Record<string, unknown>, path: string, value: unknown): void;
33
+ /**
34
+ * The engine that renders a brush: tools by what they do; marks by how they are laid
35
+ * (particles, objects), the tip (bristle), the surface (thick, wet) and the paint exchange (a
36
+ * reservoir makes a Mixer Brush); everything else paints dabs.
37
+ */
38
+ export declare function resolveEngine(brush: Pick<Brush, 'kind' | 'tool' | 'tip' | 'marks' | 'behaviour'>): PaintBrushEngine;
39
+ /** The wet medium a wet brush paints: `behaviour.wet.medium`, else its variety when that is a wet medium. */
40
+ export declare function resolveWetMedium(brush: Pick<Brush, 'variety' | 'behaviour'>): WetMediumKind | undefined;
41
+ /**
42
+ * The library category a brush is grouped under: tools by what they do; light brushes; then by
43
+ * engine (particles are procedural, objects stickers, bristle, thick impasto, wet oil or
44
+ * watercolour, the Mixer Brush); dab brushes by variety, then medium.
45
+ */
46
+ export declare function resolveCategory(brush: Brush, engine?: PaintBrushEngine): PaintBrushCategory;
47
+ export interface ResolveBrushOptions {
48
+ /** Mark the result built-in (a library's presets). */
49
+ builtin?: boolean;
50
+ }
51
+ /**
52
+ * The flat engine form of a brush. Missing fields take the engine's defaults, and every value is
53
+ * clamped into range, so any brush resolves (check it with `normalizeBrushSpec` first to hear
54
+ * what was out of range).
55
+ */
56
+ export declare function resolveBrush(brush: Brush, options?: ResolveBrushOptions): ResolvedBrush;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * JSON Schema of a `Brush`: strict (`additionalProperties: false` at every level), every field
3
+ * described with its units and default. `normalizeBrushSpec` clamps and checks against the same
4
+ * ranges, so the schema, the normaliser and the engine agree.
5
+ */
6
+ import type { JsonSchema } from '../tools/schema.cjs';
7
+ /** Most colours in a brush's palette. */
8
+ export declare const MAX_BRUSH_PALETTE = 16;
9
+ /** Variety and tag ids: lowercase letters, digits and dashes. */
10
+ export declare const BRUSH_WORD: RegExp;
11
+ /** A sticker ref `provider:id`, or a bare editor stamp (read as `editor:<stamp>`). */
12
+ export declare const BRUSH_STAMP_PATTERN: string;
13
+ /** JSON Schema of a `Brush`. */
14
+ export declare const BRUSH_JSON_SCHEMA: JsonSchema;
15
+ /** The facet schemas, for tools that take one facet. */
16
+ export declare const BRUSH_FACET_SCHEMAS: {
17
+ readonly tip: JsonSchema;
18
+ readonly marks: {
19
+ readonly continuous: JsonSchema;
20
+ readonly particles: JsonSchema;
21
+ readonly objects: JsonSchema;
22
+ };
23
+ readonly dynamics: JsonSchema;
24
+ readonly behaviour: JsonSchema;
25
+ readonly light: JsonSchema;
26
+ readonly motion: JsonSchema;
27
+ readonly colour: JsonSchema;
28
+ readonly paint: JsonSchema;
29
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * JSON Schema of a `Brush`: strict (`additionalProperties: false` at every level), every field
3
+ * described with its units and default. `normalizeBrushSpec` clamps and checks against the same
4
+ * ranges, so the schema, the normaliser and the engine agree.
5
+ */
6
+ import type { JsonSchema } from '../tools/schema.js';
7
+ /** Most colours in a brush's palette. */
8
+ export declare const MAX_BRUSH_PALETTE = 16;
9
+ /** Variety and tag ids: lowercase letters, digits and dashes. */
10
+ export declare const BRUSH_WORD: RegExp;
11
+ /** A sticker ref `provider:id`, or a bare editor stamp (read as `editor:<stamp>`). */
12
+ export declare const BRUSH_STAMP_PATTERN: string;
13
+ /** JSON Schema of a `Brush`. */
14
+ export declare const BRUSH_JSON_SCHEMA: JsonSchema;
15
+ /** The facet schemas, for tools that take one facet. */
16
+ export declare const BRUSH_FACET_SCHEMAS: {
17
+ readonly tip: JsonSchema;
18
+ readonly marks: {
19
+ readonly continuous: JsonSchema;
20
+ readonly particles: JsonSchema;
21
+ readonly objects: JsonSchema;
22
+ };
23
+ readonly dynamics: JsonSchema;
24
+ readonly behaviour: JsonSchema;
25
+ readonly light: JsonSchema;
26
+ readonly motion: JsonSchema;
27
+ readonly colour: JsonSchema;
28
+ readonly paint: JsonSchema;
29
+ };
@@ -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.cjs';
14
+ import type { PaintGradientSource } from '../paint/gradient-paint.cjs';
15
+ import type { MixingModel } from '../paint/exchange.cjs';
16
+ import type { BlendMode } from '../raster/blend.cjs';
17
+ import type { BrushRotation, ImpastoTool, PaintBrush, WetMediumKind } from '../paint-editor/brushes.cjs';
18
+ import type { PaintEffectPaint } from '../paint-editor/effect-paint.cjs';
19
+ import type { DotRotation, DotTextureOrder, ParticleKind, ParticleRender, RibbonPairs } from '../paint-editor/mark-settings.cjs';
20
+ import type { StickerRef } from '../stickers/types.cjs';
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;