@almadar/ui 5.139.0 → 5.141.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.
@@ -1,7 +1,7 @@
1
- export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-CL0kdshO.cjs';
1
+ export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-rwc3svaX.cjs';
2
2
  import { FieldValue, EntityRow, EventPayload } from '@almadar/core';
3
3
  export { AssetLoadStatus, BridgeHealth, CheckStatus, EffectTrace, EventLogEntry, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary } from '@almadar/core';
4
- import '../paintDispatch-DXygiK7M.cjs';
4
+ import '../paintDispatch-BQn5Lyx1.cjs';
5
5
  import 'clsx';
6
6
 
7
7
  /**
@@ -1,7 +1,7 @@
1
- export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-CCaph5o9.js';
1
+ export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-BDwC4QpH.js';
2
2
  import { FieldValue, EntityRow, EventPayload } from '@almadar/core';
3
3
  export { AssetLoadStatus, BridgeHealth, CheckStatus, EffectTrace, EventLogEntry, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary } from '@almadar/core';
4
- import '../paintDispatch-DXygiK7M.js';
4
+ import '../paintDispatch-BQn5Lyx1.js';
5
5
  import 'clsx';
6
6
 
7
7
  /**
@@ -17,6 +17,11 @@ interface PainterShadow {
17
17
  color: string;
18
18
  blur: number;
19
19
  }
20
+ /** One color stop of a {@link PainterGradient}; `offset` is 0..1 along the gradient. */
21
+ interface PainterGradientStop {
22
+ offset: number;
23
+ color: string;
24
+ }
20
25
 
21
26
  /**
22
27
  * Drawable contract — the shared vocabulary every neutral drawable primitive
@@ -110,6 +115,86 @@ interface DrawSpriteProps extends DrawableBase {
110
115
  */
111
116
 
112
117
  type ShapeKind = 'cell' | 'rect' | 'ellipse' | 'poly' | 'path';
118
+ /** Composite modes a shape may blend with — the canvas `globalCompositeOperation` set, spelled out so the pattern schema carries a real enum. */
119
+ type DrawShapeBlendMode = 'source-over' | 'lighter' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'color-dodge' | 'color-burn' | 'hard-light' | 'soft-light' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity' | 'source-atop' | 'destination-over' | 'destination-out' | 'xor';
120
+ /** One gradient color stop; `offset` is 0..1 along the gradient axis. */
121
+ type DrawShapeGradientStop = PainterGradientStop;
122
+ /**
123
+ * A gradient fill in world units relative to the cell's projected top-left —
124
+ * same coordinate convention as `points` and `d`. Overrides `fill` when present.
125
+ */
126
+ interface DrawShapeGradient {
127
+ kind: 'linear' | 'radial' | 'conic';
128
+ /** Linear start point in world units. */
129
+ from?: PainterPoint;
130
+ /** Linear end point in world units. */
131
+ to?: PainterPoint;
132
+ /** Radial/conic center in world units. */
133
+ center?: PainterPoint;
134
+ /** Radial radius in world units. */
135
+ radius?: number;
136
+ /** Conic start angle in radians. */
137
+ angle?: number;
138
+ /** Ordered color stops. */
139
+ stops: DrawShapeGradientStop[];
140
+ }
141
+ /**
142
+ * A repeating texture painted OVER the fill, clipped to the same geometry —
143
+ * procedural grain (`noise`) or a tiling image. `scale` is painter-px per noise
144
+ * cell (default 2) / an image scale multiplier; grain stays constant-px under
145
+ * group scale, like strokes.
146
+ */
147
+ interface DrawShapeFillPattern {
148
+ kind: 'noise' | 'image';
149
+ /** Image pattern URL (`kind: 'image'`). */
150
+ url?: string;
151
+ scale?: number;
152
+ /** Noise speckle max alpha (default 0.12). */
153
+ alpha?: number;
154
+ /** Noise speckle color (default black). */
155
+ color?: string;
156
+ }
157
+ /** A soft glow / drop-shadow behind the shape; `blur` is in world units. */
158
+ interface DrawShapeShadow {
159
+ color: string;
160
+ blur: number;
161
+ }
162
+ /**
163
+ * One keyframe of a {@link DrawShapeAnimation}: `at` is the 0..1 position in
164
+ * the cycle; every other field overrides the shape's base prop at that moment.
165
+ */
166
+ interface DrawShapeKeyframe {
167
+ at: number;
168
+ offsetX?: number;
169
+ offsetY?: number;
170
+ rotate?: number;
171
+ opacity?: number;
172
+ radiusX?: number;
173
+ radiusY?: number;
174
+ width?: number;
175
+ height?: number;
176
+ strokeWidth?: number;
177
+ strokeDashOffset?: number;
178
+ blur?: number;
179
+ fill?: string;
180
+ stroke?: string;
181
+ shadow?: DrawShapeShadow;
182
+ }
183
+ /**
184
+ * Declarative keyframe animation for a drawable. The host runs a paint clock
185
+ * while any drawable declares one; numeric tracks lerp between keyframes,
186
+ * string tracks hold the previous keyframe's value, `shadow` lerps `blur` and
187
+ * holds `color`. A track starts from the shape's base prop until its first
188
+ * keyframe defines it.
189
+ */
190
+ interface DrawShapeAnimation {
191
+ /** One cycle length in ms. */
192
+ durationMs: number;
193
+ /** Loop the cycle (default true); false plays once and holds the final keyframes. */
194
+ loop?: boolean;
195
+ /** Keyframes ordered by `at` (0..1). */
196
+ keyframes: DrawShapeKeyframe[];
197
+ }
113
198
  interface DrawShapeProps extends DrawableBase {
114
199
  type: 'draw-shape';
115
200
  shape: ShapeKind;
@@ -125,7 +210,7 @@ interface DrawShapeProps extends DrawableBase {
125
210
  radiusX?: number;
126
211
  /** Ellipse vertical radius in world units; omitted → `radiusX` (a circle). */
127
212
  radiusY?: number;
128
- /** Fine nudge from the anchor point in world units. */
213
+ /** Fine nudge in world units — applies to every shape kind except `cell` (rect/ellipse from their anchor point; poly/path from the projected top-left). */
129
214
  offsetX?: number;
130
215
  offsetY?: number;
131
216
  /** Poly vertices as world-unit offsets relative to the cell's projected top-left. */
@@ -133,8 +218,30 @@ interface DrawShapeProps extends DrawableBase {
133
218
  /** SVG path data in world units relative to the cell's projected top-left — same coordinate convention as `points`. */
134
219
  d?: string;
135
220
  fill?: string;
221
+ /** Gradient fill in world units; overrides `fill` when present. */
222
+ gradient?: DrawShapeGradient;
223
+ /** Repeating texture painted over the fill (grain / tiling image). */
224
+ fillPattern?: DrawShapeFillPattern;
136
225
  stroke?: string;
137
226
  strokeWidth?: number;
227
+ /** Gradient stroke in world units; overrides `stroke` when present. */
228
+ strokeGradient?: DrawShapeGradient;
229
+ /** Dash pattern in painter-px (constant under group scale, like `strokeWidth`). */
230
+ strokeDash?: number[];
231
+ /** Dash phase offset in painter-px; animatable (marching ants). */
232
+ strokeDashOffset?: number;
233
+ /** Composite/blend mode for this shape's draws (`lighter`, `multiply`, `screen`, …). */
234
+ blendMode?: DrawShapeBlendMode;
235
+ /** Gaussian blur in painter-px. Expensive — forces an intermediate raster; use sparingly. */
236
+ blur?: number;
237
+ /** Rotation in radians (painter units, same as `draw-group`), about `pivot`. */
238
+ rotate?: number;
239
+ /** Rotation pivot in world units relative to the cell's projected top-left; default `{x:0.5, y:0.5}` (cell center). */
240
+ pivot?: PainterPoint;
241
+ /** Soft glow / drop-shadow behind the shape; `blur` in world units. */
242
+ shadow?: DrawShapeShadow;
243
+ /** Keyframe animation over this shape's props; the host runs a paint clock while present. */
244
+ animation?: DrawShapeAnimation;
138
245
  /** 0..1 opacity. */
139
246
  opacity?: number;
140
247
  }
@@ -187,10 +294,133 @@ interface DrawGroupProps extends DrawableBase {
187
294
  rotate?: number;
188
295
  /** 0..1 opacity. */
189
296
  opacity?: number;
297
+ /** Clip the group's items to an SVG path (`d` syntax) in world units relative to the group origin — masked reveals, meters, portraits. */
298
+ clip?: string;
190
299
  /** The grouped drawables, painted through the normal dispatch. */
191
300
  items: DrawableNode[];
192
301
  }
193
302
 
303
+ /**
304
+ * `draw-mesh` — the volumetric 3D drawable atom (3D-canvas backend).
305
+ *
306
+ * ONE descriptor (`DrawMeshProps`, grounded in core `ScenePos`) with the R3F
307
+ * backend `Mesh3D` in `lib/drawable/three/DrawMesh3D` (kept OUT of this file so
308
+ * the 2D path never pulls three). A parametric primitive (box, sphere, capsule,
309
+ * cylinder, cone, torus, plane, circle) at a scene position — `position.z` is
310
+ * height in cells — with a data-driven material (`standard`/`physical`/`toon`/
311
+ * `basic`), an optional inverted-hull outline, and keyframe animation over
312
+ * transform/material tracks. Low-poly is a knob, not a geometry rewrite:
313
+ * `segments` 4–8 + `material.flatShading`. Composed in `.lolo` like every
314
+ * drawable; the 2D painter skips it with a one-time warn. The React component
315
+ * renders `null`; it exists so the pattern pipeline registers a `draw-mesh`
316
+ * pattern and standalone pages stay inspectable.
317
+ */
318
+
319
+ type MeshShapeKind = 'box' | 'sphere' | 'capsule' | 'cylinder' | 'cone' | 'torus' | 'plane' | 'circle';
320
+ type MeshMaterialKind = 'standard' | 'physical' | 'toon' | 'basic';
321
+ type MeshMaterialSide = 'front' | 'back' | 'double';
322
+ /**
323
+ * Data-driven surface description — the 3D analog of the 2D fill/gradient knobs.
324
+ * `standard`/`physical` are lit PBR (physical adds `transmission`/`ior` for glass
325
+ * and crystal), `toon` is cel-banded, `basic` is unlit flat color.
326
+ */
327
+ interface MeshMaterial {
328
+ kind?: MeshMaterialKind;
329
+ /** Albedo color (CSS color string). */
330
+ color?: string;
331
+ /** 0..1 — how metallic the surface reads (PBR kinds). */
332
+ metalness?: number;
333
+ /** 0..1 — microfacet roughness; low = glossy (PBR kinds). */
334
+ roughness?: number;
335
+ /** Emissive color; pairs with the canvas `post.bloom` for neon/glow. */
336
+ emissive?: string;
337
+ /** Emissive strength multiplier (default 1 when `emissive` is set). */
338
+ emissiveIntensity?: number;
339
+ /** 0..1 material opacity; multiplies the node/group opacity. */
340
+ opacity?: number;
341
+ /** 0..1 light transmission — glass/crystal (`physical` only). */
342
+ transmission?: number;
343
+ /** Index of refraction (`physical` only, default 1.5). */
344
+ ior?: number;
345
+ /** Faceted shading — the low-poly look (pairs with low `segments`). */
346
+ flatShading?: boolean;
347
+ /** Which faces render (default `front`). */
348
+ side?: MeshMaterialSide;
349
+ }
350
+ /** Inverted-hull toon outline: a back-face shell of the same geometry, scaled out by `width`. */
351
+ interface MeshOutline {
352
+ /** Outline color (default near-black). */
353
+ color?: string;
354
+ /** Shell expansion as a fraction of the mesh size (default 0.05). */
355
+ width?: number;
356
+ }
357
+ /**
358
+ * One keyframe of a {@link DrawMeshAnimation}: `at` is the 0..1 position in the
359
+ * cycle. Transform tracks are DELTAS from the base props (offsets in cells,
360
+ * rotations in radians, `scale` a multiplier); material tracks override.
361
+ */
362
+ interface DrawMeshKeyframe {
363
+ at: number;
364
+ offsetX?: number;
365
+ offsetY?: number;
366
+ offsetZ?: number;
367
+ rotateX?: number;
368
+ rotateY?: number;
369
+ rotateZ?: number;
370
+ scale?: number;
371
+ opacity?: number;
372
+ emissiveIntensity?: number;
373
+ color?: string;
374
+ emissive?: string;
375
+ }
376
+ /**
377
+ * Declarative keyframe animation for a mesh; the 3D host advances it per frame.
378
+ * Numeric tracks lerp between keyframes, color tracks hold the previous
379
+ * keyframe's value. A track rests at its identity until its first keyframe.
380
+ */
381
+ interface DrawMeshAnimation {
382
+ /** One cycle length in ms. */
383
+ durationMs: number;
384
+ /** Loop the cycle (default true); false plays once and holds the final keyframes. */
385
+ loop?: boolean;
386
+ /** Keyframes ordered by `at` (0..1). */
387
+ keyframes: DrawMeshKeyframe[];
388
+ }
389
+ interface DrawMeshProps extends DrawableBase {
390
+ type: 'draw-mesh';
391
+ shape: MeshShapeKind;
392
+ /** Logical scene position; `z` is height in cells (projected to world Y). */
393
+ position: ScenePos;
394
+ /** Box/plane X extent in cells (default 1). */
395
+ width?: number;
396
+ /** Box Y (height) extent / capsule-cylinder-cone length in cells (default 1). */
397
+ height?: number;
398
+ /** Box/plane Z extent in cells (default `width`). */
399
+ depth?: number;
400
+ /** Sphere/capsule/cone/torus/circle radius in cells (default 0.4). */
401
+ radius?: number;
402
+ /** Cylinder top radius (default `radius`). */
403
+ radiusTop?: number;
404
+ /** Cylinder bottom radius (default `radius`). */
405
+ radiusBottom?: number;
406
+ /** Torus tube radius in cells (default `radius` / 3). */
407
+ tube?: number;
408
+ /** Curved-surface tessellation, clamped 3..64 (default 24). 4–8 + `flatShading` = low-poly. */
409
+ segments?: number;
410
+ /** Euler rotation `[x, y, z]` in radians. */
411
+ rotation?: [number, number, number];
412
+ /** `bottom` (default) rests the mesh on its position's ground plane; `center` centers it there. */
413
+ pivot?: 'bottom' | 'center';
414
+ material?: MeshMaterial;
415
+ outline?: MeshOutline;
416
+ castShadow?: boolean;
417
+ receiveShadow?: boolean;
418
+ /** Keyframe animation over transform/material tracks; the 3D host runs it per frame. */
419
+ animation?: DrawMeshAnimation;
420
+ /** 0..1 opacity; multiplies the material and enclosing group opacity. */
421
+ opacity?: number;
422
+ }
423
+
194
424
  /**
195
425
  * `draw-sprite-layer` — batch multiple sprites in one descriptor for O(layers) rendering.
196
426
  *
@@ -247,6 +477,6 @@ interface DrawTextLayerProps extends DrawableBase {
247
477
  */
248
478
 
249
479
  /** Every drawable descriptor. The host's `children` are a `DrawableNode[]`. */
250
- type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
480
+ type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawMeshProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
251
481
 
252
482
  export type { DrawableNode as D };
@@ -17,6 +17,11 @@ interface PainterShadow {
17
17
  color: string;
18
18
  blur: number;
19
19
  }
20
+ /** One color stop of a {@link PainterGradient}; `offset` is 0..1 along the gradient. */
21
+ interface PainterGradientStop {
22
+ offset: number;
23
+ color: string;
24
+ }
20
25
 
21
26
  /**
22
27
  * Drawable contract — the shared vocabulary every neutral drawable primitive
@@ -110,6 +115,86 @@ interface DrawSpriteProps extends DrawableBase {
110
115
  */
111
116
 
112
117
  type ShapeKind = 'cell' | 'rect' | 'ellipse' | 'poly' | 'path';
118
+ /** Composite modes a shape may blend with — the canvas `globalCompositeOperation` set, spelled out so the pattern schema carries a real enum. */
119
+ type DrawShapeBlendMode = 'source-over' | 'lighter' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'color-dodge' | 'color-burn' | 'hard-light' | 'soft-light' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity' | 'source-atop' | 'destination-over' | 'destination-out' | 'xor';
120
+ /** One gradient color stop; `offset` is 0..1 along the gradient axis. */
121
+ type DrawShapeGradientStop = PainterGradientStop;
122
+ /**
123
+ * A gradient fill in world units relative to the cell's projected top-left —
124
+ * same coordinate convention as `points` and `d`. Overrides `fill` when present.
125
+ */
126
+ interface DrawShapeGradient {
127
+ kind: 'linear' | 'radial' | 'conic';
128
+ /** Linear start point in world units. */
129
+ from?: PainterPoint;
130
+ /** Linear end point in world units. */
131
+ to?: PainterPoint;
132
+ /** Radial/conic center in world units. */
133
+ center?: PainterPoint;
134
+ /** Radial radius in world units. */
135
+ radius?: number;
136
+ /** Conic start angle in radians. */
137
+ angle?: number;
138
+ /** Ordered color stops. */
139
+ stops: DrawShapeGradientStop[];
140
+ }
141
+ /**
142
+ * A repeating texture painted OVER the fill, clipped to the same geometry —
143
+ * procedural grain (`noise`) or a tiling image. `scale` is painter-px per noise
144
+ * cell (default 2) / an image scale multiplier; grain stays constant-px under
145
+ * group scale, like strokes.
146
+ */
147
+ interface DrawShapeFillPattern {
148
+ kind: 'noise' | 'image';
149
+ /** Image pattern URL (`kind: 'image'`). */
150
+ url?: string;
151
+ scale?: number;
152
+ /** Noise speckle max alpha (default 0.12). */
153
+ alpha?: number;
154
+ /** Noise speckle color (default black). */
155
+ color?: string;
156
+ }
157
+ /** A soft glow / drop-shadow behind the shape; `blur` is in world units. */
158
+ interface DrawShapeShadow {
159
+ color: string;
160
+ blur: number;
161
+ }
162
+ /**
163
+ * One keyframe of a {@link DrawShapeAnimation}: `at` is the 0..1 position in
164
+ * the cycle; every other field overrides the shape's base prop at that moment.
165
+ */
166
+ interface DrawShapeKeyframe {
167
+ at: number;
168
+ offsetX?: number;
169
+ offsetY?: number;
170
+ rotate?: number;
171
+ opacity?: number;
172
+ radiusX?: number;
173
+ radiusY?: number;
174
+ width?: number;
175
+ height?: number;
176
+ strokeWidth?: number;
177
+ strokeDashOffset?: number;
178
+ blur?: number;
179
+ fill?: string;
180
+ stroke?: string;
181
+ shadow?: DrawShapeShadow;
182
+ }
183
+ /**
184
+ * Declarative keyframe animation for a drawable. The host runs a paint clock
185
+ * while any drawable declares one; numeric tracks lerp between keyframes,
186
+ * string tracks hold the previous keyframe's value, `shadow` lerps `blur` and
187
+ * holds `color`. A track starts from the shape's base prop until its first
188
+ * keyframe defines it.
189
+ */
190
+ interface DrawShapeAnimation {
191
+ /** One cycle length in ms. */
192
+ durationMs: number;
193
+ /** Loop the cycle (default true); false plays once and holds the final keyframes. */
194
+ loop?: boolean;
195
+ /** Keyframes ordered by `at` (0..1). */
196
+ keyframes: DrawShapeKeyframe[];
197
+ }
113
198
  interface DrawShapeProps extends DrawableBase {
114
199
  type: 'draw-shape';
115
200
  shape: ShapeKind;
@@ -125,7 +210,7 @@ interface DrawShapeProps extends DrawableBase {
125
210
  radiusX?: number;
126
211
  /** Ellipse vertical radius in world units; omitted → `radiusX` (a circle). */
127
212
  radiusY?: number;
128
- /** Fine nudge from the anchor point in world units. */
213
+ /** Fine nudge in world units — applies to every shape kind except `cell` (rect/ellipse from their anchor point; poly/path from the projected top-left). */
129
214
  offsetX?: number;
130
215
  offsetY?: number;
131
216
  /** Poly vertices as world-unit offsets relative to the cell's projected top-left. */
@@ -133,8 +218,30 @@ interface DrawShapeProps extends DrawableBase {
133
218
  /** SVG path data in world units relative to the cell's projected top-left — same coordinate convention as `points`. */
134
219
  d?: string;
135
220
  fill?: string;
221
+ /** Gradient fill in world units; overrides `fill` when present. */
222
+ gradient?: DrawShapeGradient;
223
+ /** Repeating texture painted over the fill (grain / tiling image). */
224
+ fillPattern?: DrawShapeFillPattern;
136
225
  stroke?: string;
137
226
  strokeWidth?: number;
227
+ /** Gradient stroke in world units; overrides `stroke` when present. */
228
+ strokeGradient?: DrawShapeGradient;
229
+ /** Dash pattern in painter-px (constant under group scale, like `strokeWidth`). */
230
+ strokeDash?: number[];
231
+ /** Dash phase offset in painter-px; animatable (marching ants). */
232
+ strokeDashOffset?: number;
233
+ /** Composite/blend mode for this shape's draws (`lighter`, `multiply`, `screen`, …). */
234
+ blendMode?: DrawShapeBlendMode;
235
+ /** Gaussian blur in painter-px. Expensive — forces an intermediate raster; use sparingly. */
236
+ blur?: number;
237
+ /** Rotation in radians (painter units, same as `draw-group`), about `pivot`. */
238
+ rotate?: number;
239
+ /** Rotation pivot in world units relative to the cell's projected top-left; default `{x:0.5, y:0.5}` (cell center). */
240
+ pivot?: PainterPoint;
241
+ /** Soft glow / drop-shadow behind the shape; `blur` in world units. */
242
+ shadow?: DrawShapeShadow;
243
+ /** Keyframe animation over this shape's props; the host runs a paint clock while present. */
244
+ animation?: DrawShapeAnimation;
138
245
  /** 0..1 opacity. */
139
246
  opacity?: number;
140
247
  }
@@ -187,10 +294,133 @@ interface DrawGroupProps extends DrawableBase {
187
294
  rotate?: number;
188
295
  /** 0..1 opacity. */
189
296
  opacity?: number;
297
+ /** Clip the group's items to an SVG path (`d` syntax) in world units relative to the group origin — masked reveals, meters, portraits. */
298
+ clip?: string;
190
299
  /** The grouped drawables, painted through the normal dispatch. */
191
300
  items: DrawableNode[];
192
301
  }
193
302
 
303
+ /**
304
+ * `draw-mesh` — the volumetric 3D drawable atom (3D-canvas backend).
305
+ *
306
+ * ONE descriptor (`DrawMeshProps`, grounded in core `ScenePos`) with the R3F
307
+ * backend `Mesh3D` in `lib/drawable/three/DrawMesh3D` (kept OUT of this file so
308
+ * the 2D path never pulls three). A parametric primitive (box, sphere, capsule,
309
+ * cylinder, cone, torus, plane, circle) at a scene position — `position.z` is
310
+ * height in cells — with a data-driven material (`standard`/`physical`/`toon`/
311
+ * `basic`), an optional inverted-hull outline, and keyframe animation over
312
+ * transform/material tracks. Low-poly is a knob, not a geometry rewrite:
313
+ * `segments` 4–8 + `material.flatShading`. Composed in `.lolo` like every
314
+ * drawable; the 2D painter skips it with a one-time warn. The React component
315
+ * renders `null`; it exists so the pattern pipeline registers a `draw-mesh`
316
+ * pattern and standalone pages stay inspectable.
317
+ */
318
+
319
+ type MeshShapeKind = 'box' | 'sphere' | 'capsule' | 'cylinder' | 'cone' | 'torus' | 'plane' | 'circle';
320
+ type MeshMaterialKind = 'standard' | 'physical' | 'toon' | 'basic';
321
+ type MeshMaterialSide = 'front' | 'back' | 'double';
322
+ /**
323
+ * Data-driven surface description — the 3D analog of the 2D fill/gradient knobs.
324
+ * `standard`/`physical` are lit PBR (physical adds `transmission`/`ior` for glass
325
+ * and crystal), `toon` is cel-banded, `basic` is unlit flat color.
326
+ */
327
+ interface MeshMaterial {
328
+ kind?: MeshMaterialKind;
329
+ /** Albedo color (CSS color string). */
330
+ color?: string;
331
+ /** 0..1 — how metallic the surface reads (PBR kinds). */
332
+ metalness?: number;
333
+ /** 0..1 — microfacet roughness; low = glossy (PBR kinds). */
334
+ roughness?: number;
335
+ /** Emissive color; pairs with the canvas `post.bloom` for neon/glow. */
336
+ emissive?: string;
337
+ /** Emissive strength multiplier (default 1 when `emissive` is set). */
338
+ emissiveIntensity?: number;
339
+ /** 0..1 material opacity; multiplies the node/group opacity. */
340
+ opacity?: number;
341
+ /** 0..1 light transmission — glass/crystal (`physical` only). */
342
+ transmission?: number;
343
+ /** Index of refraction (`physical` only, default 1.5). */
344
+ ior?: number;
345
+ /** Faceted shading — the low-poly look (pairs with low `segments`). */
346
+ flatShading?: boolean;
347
+ /** Which faces render (default `front`). */
348
+ side?: MeshMaterialSide;
349
+ }
350
+ /** Inverted-hull toon outline: a back-face shell of the same geometry, scaled out by `width`. */
351
+ interface MeshOutline {
352
+ /** Outline color (default near-black). */
353
+ color?: string;
354
+ /** Shell expansion as a fraction of the mesh size (default 0.05). */
355
+ width?: number;
356
+ }
357
+ /**
358
+ * One keyframe of a {@link DrawMeshAnimation}: `at` is the 0..1 position in the
359
+ * cycle. Transform tracks are DELTAS from the base props (offsets in cells,
360
+ * rotations in radians, `scale` a multiplier); material tracks override.
361
+ */
362
+ interface DrawMeshKeyframe {
363
+ at: number;
364
+ offsetX?: number;
365
+ offsetY?: number;
366
+ offsetZ?: number;
367
+ rotateX?: number;
368
+ rotateY?: number;
369
+ rotateZ?: number;
370
+ scale?: number;
371
+ opacity?: number;
372
+ emissiveIntensity?: number;
373
+ color?: string;
374
+ emissive?: string;
375
+ }
376
+ /**
377
+ * Declarative keyframe animation for a mesh; the 3D host advances it per frame.
378
+ * Numeric tracks lerp between keyframes, color tracks hold the previous
379
+ * keyframe's value. A track rests at its identity until its first keyframe.
380
+ */
381
+ interface DrawMeshAnimation {
382
+ /** One cycle length in ms. */
383
+ durationMs: number;
384
+ /** Loop the cycle (default true); false plays once and holds the final keyframes. */
385
+ loop?: boolean;
386
+ /** Keyframes ordered by `at` (0..1). */
387
+ keyframes: DrawMeshKeyframe[];
388
+ }
389
+ interface DrawMeshProps extends DrawableBase {
390
+ type: 'draw-mesh';
391
+ shape: MeshShapeKind;
392
+ /** Logical scene position; `z` is height in cells (projected to world Y). */
393
+ position: ScenePos;
394
+ /** Box/plane X extent in cells (default 1). */
395
+ width?: number;
396
+ /** Box Y (height) extent / capsule-cylinder-cone length in cells (default 1). */
397
+ height?: number;
398
+ /** Box/plane Z extent in cells (default `width`). */
399
+ depth?: number;
400
+ /** Sphere/capsule/cone/torus/circle radius in cells (default 0.4). */
401
+ radius?: number;
402
+ /** Cylinder top radius (default `radius`). */
403
+ radiusTop?: number;
404
+ /** Cylinder bottom radius (default `radius`). */
405
+ radiusBottom?: number;
406
+ /** Torus tube radius in cells (default `radius` / 3). */
407
+ tube?: number;
408
+ /** Curved-surface tessellation, clamped 3..64 (default 24). 4–8 + `flatShading` = low-poly. */
409
+ segments?: number;
410
+ /** Euler rotation `[x, y, z]` in radians. */
411
+ rotation?: [number, number, number];
412
+ /** `bottom` (default) rests the mesh on its position's ground plane; `center` centers it there. */
413
+ pivot?: 'bottom' | 'center';
414
+ material?: MeshMaterial;
415
+ outline?: MeshOutline;
416
+ castShadow?: boolean;
417
+ receiveShadow?: boolean;
418
+ /** Keyframe animation over transform/material tracks; the 3D host runs it per frame. */
419
+ animation?: DrawMeshAnimation;
420
+ /** 0..1 opacity; multiplies the material and enclosing group opacity. */
421
+ opacity?: number;
422
+ }
423
+
194
424
  /**
195
425
  * `draw-sprite-layer` — batch multiple sprites in one descriptor for O(layers) rendering.
196
426
  *
@@ -247,6 +477,6 @@ interface DrawTextLayerProps extends DrawableBase {
247
477
  */
248
478
 
249
479
  /** Every drawable descriptor. The host's `children` are a `DrawableNode[]`. */
250
- type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
480
+ type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawMeshProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
251
481
 
252
482
  export type { DrawableNode as D };