@almadar/ui 5.140.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-DkGYzPOg.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-B5pPeSEp.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-Do5Ra3l3.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-B5pPeSEp.js';
4
+ import '../paintDispatch-BQn5Lyx1.js';
5
5
  import 'clsx';
6
6
 
7
7
  /**
@@ -115,6 +115,8 @@ interface DrawSpriteProps extends DrawableBase {
115
115
  */
116
116
 
117
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';
118
120
  /** One gradient color stop; `offset` is 0..1 along the gradient axis. */
119
121
  type DrawShapeGradientStop = PainterGradientStop;
120
122
  /**
@@ -122,18 +124,36 @@ type DrawShapeGradientStop = PainterGradientStop;
122
124
  * same coordinate convention as `points` and `d`. Overrides `fill` when present.
123
125
  */
124
126
  interface DrawShapeGradient {
125
- kind: 'linear' | 'radial';
127
+ kind: 'linear' | 'radial' | 'conic';
126
128
  /** Linear start point in world units. */
127
129
  from?: PainterPoint;
128
130
  /** Linear end point in world units. */
129
131
  to?: PainterPoint;
130
- /** Radial center in world units. */
132
+ /** Radial/conic center in world units. */
131
133
  center?: PainterPoint;
132
134
  /** Radial radius in world units. */
133
135
  radius?: number;
136
+ /** Conic start angle in radians. */
137
+ angle?: number;
134
138
  /** Ordered color stops. */
135
139
  stops: DrawShapeGradientStop[];
136
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
+ }
137
157
  /** A soft glow / drop-shadow behind the shape; `blur` is in world units. */
138
158
  interface DrawShapeShadow {
139
159
  color: string;
@@ -154,6 +174,8 @@ interface DrawShapeKeyframe {
154
174
  width?: number;
155
175
  height?: number;
156
176
  strokeWidth?: number;
177
+ strokeDashOffset?: number;
178
+ blur?: number;
157
179
  fill?: string;
158
180
  stroke?: string;
159
181
  shadow?: DrawShapeShadow;
@@ -198,8 +220,20 @@ interface DrawShapeProps extends DrawableBase {
198
220
  fill?: string;
199
221
  /** Gradient fill in world units; overrides `fill` when present. */
200
222
  gradient?: DrawShapeGradient;
223
+ /** Repeating texture painted over the fill (grain / tiling image). */
224
+ fillPattern?: DrawShapeFillPattern;
201
225
  stroke?: string;
202
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;
203
237
  /** Rotation in radians (painter units, same as `draw-group`), about `pivot`. */
204
238
  rotate?: number;
205
239
  /** Rotation pivot in world units relative to the cell's projected top-left; default `{x:0.5, y:0.5}` (cell center). */
@@ -260,10 +294,133 @@ interface DrawGroupProps extends DrawableBase {
260
294
  rotate?: number;
261
295
  /** 0..1 opacity. */
262
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;
263
299
  /** The grouped drawables, painted through the normal dispatch. */
264
300
  items: DrawableNode[];
265
301
  }
266
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
+
267
424
  /**
268
425
  * `draw-sprite-layer` — batch multiple sprites in one descriptor for O(layers) rendering.
269
426
  *
@@ -320,6 +477,6 @@ interface DrawTextLayerProps extends DrawableBase {
320
477
  */
321
478
 
322
479
  /** Every drawable descriptor. The host's `children` are a `DrawableNode[]`. */
323
- type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
480
+ type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawMeshProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
324
481
 
325
482
  export type { DrawableNode as D };
@@ -115,6 +115,8 @@ interface DrawSpriteProps extends DrawableBase {
115
115
  */
116
116
 
117
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';
118
120
  /** One gradient color stop; `offset` is 0..1 along the gradient axis. */
119
121
  type DrawShapeGradientStop = PainterGradientStop;
120
122
  /**
@@ -122,18 +124,36 @@ type DrawShapeGradientStop = PainterGradientStop;
122
124
  * same coordinate convention as `points` and `d`. Overrides `fill` when present.
123
125
  */
124
126
  interface DrawShapeGradient {
125
- kind: 'linear' | 'radial';
127
+ kind: 'linear' | 'radial' | 'conic';
126
128
  /** Linear start point in world units. */
127
129
  from?: PainterPoint;
128
130
  /** Linear end point in world units. */
129
131
  to?: PainterPoint;
130
- /** Radial center in world units. */
132
+ /** Radial/conic center in world units. */
131
133
  center?: PainterPoint;
132
134
  /** Radial radius in world units. */
133
135
  radius?: number;
136
+ /** Conic start angle in radians. */
137
+ angle?: number;
134
138
  /** Ordered color stops. */
135
139
  stops: DrawShapeGradientStop[];
136
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
+ }
137
157
  /** A soft glow / drop-shadow behind the shape; `blur` is in world units. */
138
158
  interface DrawShapeShadow {
139
159
  color: string;
@@ -154,6 +174,8 @@ interface DrawShapeKeyframe {
154
174
  width?: number;
155
175
  height?: number;
156
176
  strokeWidth?: number;
177
+ strokeDashOffset?: number;
178
+ blur?: number;
157
179
  fill?: string;
158
180
  stroke?: string;
159
181
  shadow?: DrawShapeShadow;
@@ -198,8 +220,20 @@ interface DrawShapeProps extends DrawableBase {
198
220
  fill?: string;
199
221
  /** Gradient fill in world units; overrides `fill` when present. */
200
222
  gradient?: DrawShapeGradient;
223
+ /** Repeating texture painted over the fill (grain / tiling image). */
224
+ fillPattern?: DrawShapeFillPattern;
201
225
  stroke?: string;
202
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;
203
237
  /** Rotation in radians (painter units, same as `draw-group`), about `pivot`. */
204
238
  rotate?: number;
205
239
  /** Rotation pivot in world units relative to the cell's projected top-left; default `{x:0.5, y:0.5}` (cell center). */
@@ -260,10 +294,133 @@ interface DrawGroupProps extends DrawableBase {
260
294
  rotate?: number;
261
295
  /** 0..1 opacity. */
262
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;
263
299
  /** The grouped drawables, painted through the normal dispatch. */
264
300
  items: DrawableNode[];
265
301
  }
266
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
+
267
424
  /**
268
425
  * `draw-sprite-layer` — batch multiple sprites in one descriptor for O(layers) rendering.
269
426
  *
@@ -320,6 +477,6 @@ interface DrawTextLayerProps extends DrawableBase {
320
477
  */
321
478
 
322
479
  /** Every drawable descriptor. The host's `children` are a `DrawableNode[]`. */
323
- type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
480
+ type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawMeshProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
324
481
 
325
482
  export type { DrawableNode as D };