@almadar/shell-web 0.0.0-stage → 1.0.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 (266) hide show
  1. package/bundling.d.mts +18 -0
  2. package/bundling.mjs +28 -0
  3. package/dist/ArbitraryClassCompiler-CO_iASBn.d.ts +195 -0
  4. package/dist/AvlGlyph-EPJKFEO3.js +6 -0
  5. package/dist/AvlStateMachine-RKZIKNGC.js +9 -0
  6. package/dist/AvlTransitionDetail-63SD6GZF.js +11 -0
  7. package/dist/AvlTransitionExplainer-ZBTLOM3T.js +12 -0
  8. package/dist/BehaviorView-YS5G4GNB.js +11 -0
  9. package/dist/Canvas3DHost-BkZQB5l2.d.ts +552 -0
  10. package/dist/EventBusProvider-BFFHfN4O.d.ts +296 -0
  11. package/dist/FileTree-BCFnBEuQ.d.ts +254 -0
  12. package/dist/FlowCanvas-3JRMNJLV.css +1756 -0
  13. package/dist/FlowCanvas-AUMTWMNG.js +26 -0
  14. package/dist/GameAudioProvider-ceM_n0ey.d.ts +90 -0
  15. package/dist/KaTeX_AMS-Regular-CYEKBG2K.woff +0 -0
  16. package/dist/KaTeX_AMS-Regular-JKX5W2C4.ttf +0 -0
  17. package/dist/KaTeX_AMS-Regular-U6PRYMIZ.woff2 +0 -0
  18. package/dist/KaTeX_Caligraphic-Bold-5QL5CMTE.woff2 +0 -0
  19. package/dist/KaTeX_Caligraphic-Bold-WZ3QSGD3.woff +0 -0
  20. package/dist/KaTeX_Caligraphic-Bold-ZTS3R3HK.ttf +0 -0
  21. package/dist/KaTeX_Caligraphic-Regular-3LKEU76G.woff +0 -0
  22. package/dist/KaTeX_Caligraphic-Regular-A7XRTZ5Q.ttf +0 -0
  23. package/dist/KaTeX_Caligraphic-Regular-KX5MEWCF.woff2 +0 -0
  24. package/dist/KaTeX_Fraktur-Bold-2QVFK6NQ.woff2 +0 -0
  25. package/dist/KaTeX_Fraktur-Bold-T4SWXBMT.woff +0 -0
  26. package/dist/KaTeX_Fraktur-Bold-WGHVTYOR.ttf +0 -0
  27. package/dist/KaTeX_Fraktur-Regular-2PEIFJSJ.woff2 +0 -0
  28. package/dist/KaTeX_Fraktur-Regular-5U4OPH2X.ttf +0 -0
  29. package/dist/KaTeX_Fraktur-Regular-PQMHCIK6.woff +0 -0
  30. package/dist/KaTeX_Main-Bold-2GA4IZIN.woff +0 -0
  31. package/dist/KaTeX_Main-Bold-W5FBVCZM.ttf +0 -0
  32. package/dist/KaTeX_Main-Bold-YP5VVQRP.woff2 +0 -0
  33. package/dist/KaTeX_Main-BoldItalic-4P4C7HJH.woff +0 -0
  34. package/dist/KaTeX_Main-BoldItalic-N4V3DX7S.woff2 +0 -0
  35. package/dist/KaTeX_Main-BoldItalic-ODMLBJJQ.ttf +0 -0
  36. package/dist/KaTeX_Main-Italic-I43T2HSR.ttf +0 -0
  37. package/dist/KaTeX_Main-Italic-RELBIK7M.woff2 +0 -0
  38. package/dist/KaTeX_Main-Italic-SASNQFN2.woff +0 -0
  39. package/dist/KaTeX_Main-Regular-ARRPAO67.woff2 +0 -0
  40. package/dist/KaTeX_Main-Regular-P5I74A2A.woff +0 -0
  41. package/dist/KaTeX_Main-Regular-W74P5G27.ttf +0 -0
  42. package/dist/KaTeX_Math-BoldItalic-6EBV3DK5.woff +0 -0
  43. package/dist/KaTeX_Math-BoldItalic-K4WTGH3J.woff2 +0 -0
  44. package/dist/KaTeX_Math-BoldItalic-VB447A4D.ttf +0 -0
  45. package/dist/KaTeX_Math-Italic-6KGCHLFN.woff2 +0 -0
  46. package/dist/KaTeX_Math-Italic-KKK3USB2.woff +0 -0
  47. package/dist/KaTeX_Math-Italic-SON4MRCA.ttf +0 -0
  48. package/dist/KaTeX_SansSerif-Bold-RRNVJFFW.woff2 +0 -0
  49. package/dist/KaTeX_SansSerif-Bold-STQ6RXC7.ttf +0 -0
  50. package/dist/KaTeX_SansSerif-Bold-X5M5EMOD.woff +0 -0
  51. package/dist/KaTeX_SansSerif-Italic-HMPFTM52.woff2 +0 -0
  52. package/dist/KaTeX_SansSerif-Italic-PSN4QKYX.woff +0 -0
  53. package/dist/KaTeX_SansSerif-Italic-WTBAZBGY.ttf +0 -0
  54. package/dist/KaTeX_SansSerif-Regular-2TL3USAE.ttf +0 -0
  55. package/dist/KaTeX_SansSerif-Regular-OQCII6EP.woff +0 -0
  56. package/dist/KaTeX_SansSerif-Regular-XIQ62X4E.woff2 +0 -0
  57. package/dist/KaTeX_Script-Regular-72OLXYNA.ttf +0 -0
  58. package/dist/KaTeX_Script-Regular-A5IFOEBS.woff +0 -0
  59. package/dist/KaTeX_Script-Regular-APUWIHLP.woff2 +0 -0
  60. package/dist/KaTeX_Size1-Regular-4HRHTS65.woff +0 -0
  61. package/dist/KaTeX_Size1-Regular-5LRUTBFT.woff2 +0 -0
  62. package/dist/KaTeX_Size1-Regular-7K6AASVL.ttf +0 -0
  63. package/dist/KaTeX_Size2-Regular-222HN3GT.ttf +0 -0
  64. package/dist/KaTeX_Size2-Regular-K5ZHAIS6.woff +0 -0
  65. package/dist/KaTeX_Size2-Regular-LELKET5D.woff2 +0 -0
  66. package/dist/KaTeX_Size3-Regular-TLFPAHDE.woff +0 -0
  67. package/dist/KaTeX_Size3-Regular-UFCO6WCA.ttf +0 -0
  68. package/dist/KaTeX_Size3-Regular-WQRQ47UD.woff2 +0 -0
  69. package/dist/KaTeX_Size4-Regular-7PGNVPQK.ttf +0 -0
  70. package/dist/KaTeX_Size4-Regular-CDMV7U5C.woff2 +0 -0
  71. package/dist/KaTeX_Size4-Regular-PKMWZHNC.woff +0 -0
  72. package/dist/KaTeX_Typewriter-Regular-3F5K6SQ6.ttf +0 -0
  73. package/dist/KaTeX_Typewriter-Regular-MJMFSK64.woff +0 -0
  74. package/dist/KaTeX_Typewriter-Regular-VBYJ4NRC.woff2 +0 -0
  75. package/dist/KernelEngineContext-CcxGYtlr.d.ts +33 -0
  76. package/dist/LayersPanel-M2LHWUFF.js +6 -0
  77. package/dist/ModuleCard-QHDGK5XK.js +7 -0
  78. package/dist/OrbInspector-MHLJ6OEE.css +1756 -0
  79. package/dist/OrbInspector-QCPEPUPH.js +26 -0
  80. package/dist/Select-B-iDdnvE.d.ts +185 -0
  81. package/dist/ServerBridge-Bqsj-lOU.d.ts +124 -0
  82. package/dist/ThemeContext-DJmO59xd.d.ts +147 -0
  83. package/dist/UISlotContext-Dl_ewwCI.d.ts +79 -0
  84. package/dist/UISlotRenderer-C7WWOK43.js +26 -0
  85. package/dist/UISlotRenderer-KVFO6J7R.css +1756 -0
  86. package/dist/auth/browser/index.d.ts +2 -0
  87. package/dist/auth/browser/index.js +2 -0
  88. package/dist/auth/react/index.d.ts +56 -0
  89. package/dist/auth/react/index.js +157 -0
  90. package/dist/avl/index.css +1756 -0
  91. package/dist/avl/index.d.ts +2248 -0
  92. package/dist/avl/index.js +2693 -0
  93. package/dist/avl-3d-context-BycmO6tG.d.ts +201 -0
  94. package/dist/avl-schema-parser-CtJxJ9KU.d.ts +132 -0
  95. package/dist/avl-zoom-state-CKMVuBFg.d.ts +17 -0
  96. package/dist/chunk-3BBUBJFF.js +339 -0
  97. package/dist/chunk-3S54FWRC.js +131 -0
  98. package/dist/chunk-3VZ36ZKO.js +775 -0
  99. package/dist/chunk-4T3P43NS.js +1133 -0
  100. package/dist/chunk-4YXBKHHM.js +11488 -0
  101. package/dist/chunk-57DC34LY.js +525 -0
  102. package/dist/chunk-5QTYQTPS.js +15 -0
  103. package/dist/chunk-A2LR6VQQ.js +349 -0
  104. package/dist/chunk-AB3X7QTE.js +505 -0
  105. package/dist/chunk-AE7VCQB6.js +561 -0
  106. package/dist/chunk-AGXD77SL.js +98 -0
  107. package/dist/chunk-AU7O65OX.js +66 -0
  108. package/dist/chunk-CPLN6NBQ.js +701 -0
  109. package/dist/chunk-DZBQA2OW.js +176 -0
  110. package/dist/chunk-E6KA4J6N.js +227 -0
  111. package/dist/chunk-EOWMARUB.js +16 -0
  112. package/dist/chunk-G7DCAZ22.js +19 -0
  113. package/dist/chunk-GFXCPUMX.js +1334 -0
  114. package/dist/chunk-HH5KSMH5.js +311 -0
  115. package/dist/chunk-ILQXJ2AR.js +280 -0
  116. package/dist/chunk-ILZ7ORX7.js +432 -0
  117. package/dist/chunk-K4MOPSEL.js +674 -0
  118. package/dist/chunk-LHP2TK7O.js +47587 -0
  119. package/dist/chunk-P4ZFUQFF.js +93 -0
  120. package/dist/chunk-PCR37T3U.js +296 -0
  121. package/dist/chunk-PRXQGGCO.js +580 -0
  122. package/dist/chunk-REXYVBUO.js +191 -0
  123. package/dist/chunk-ROICKAU7.js +24 -0
  124. package/dist/chunk-SP5CDJ6K.js +338 -0
  125. package/dist/chunk-TUPZWTRE.js +1051 -0
  126. package/dist/chunk-TXAUOLWZ.js +490 -0
  127. package/dist/chunk-TZZBINQY.js +82 -0
  128. package/dist/chunk-UTDC2NEA.js +14 -0
  129. package/dist/chunk-UU57VNS2.js +1053 -0
  130. package/dist/chunk-UXLE3IPR.js +421 -0
  131. package/dist/chunk-VO2TTLS5.js +94 -0
  132. package/dist/chunk-X3DMMX27.js +11 -0
  133. package/dist/chunk-YHMRX6YA.js +455 -0
  134. package/dist/components/index.css +1756 -0
  135. package/dist/components/index.d.ts +11299 -0
  136. package/dist/components/index.js +1110 -0
  137. package/dist/context/index.d.ts +8 -0
  138. package/dist/context/index.js +8 -0
  139. package/dist/core.d.ts +2599 -0
  140. package/dist/core.js +3 -0
  141. package/dist/design-classes/index.cjs +431 -0
  142. package/dist/design-classes/index.d.cts +165 -0
  143. package/dist/design-classes/index.d.ts +165 -0
  144. package/dist/design-classes/index.js +399 -0
  145. package/dist/emojiItems-QGSNAABW.js +20 -0
  146. package/dist/fx-CmQjnHmT.d.ts +371 -0
  147. package/dist/hooks/index.d.ts +971 -0
  148. package/dist/hooks/index.js +8 -0
  149. package/dist/index.d.ts +408 -0
  150. package/dist/index.js +178 -0
  151. package/dist/katexPlugin-FA7NX4PE.css +1161 -0
  152. package/dist/katexPlugin-NCDKOOQY.js +2 -0
  153. package/dist/kernel-client-TZKGHJRY.js +516 -0
  154. package/dist/kernel-wire-wNdAPfhJ.d.ts +88 -0
  155. package/dist/lib/index.d.ts +602 -0
  156. package/dist/lib/index.js +1289 -0
  157. package/dist/paintDispatch-CuJLsr9Y.d.ts +688 -0
  158. package/dist/parseLessonSegments-GpCeMrb2.d.ts +334 -0
  159. package/dist/perf-CKiBKbkw.d.ts +22 -0
  160. package/dist/perf-Dr28-AgT.d.ts +57 -0
  161. package/dist/prism-X5YWKXO5.js +136 -0
  162. package/dist/providers/index.css +1756 -0
  163. package/dist/providers/index.d.ts +355 -0
  164. package/dist/providers/index.js +29 -0
  165. package/dist/renderer/index.d.ts +465 -0
  166. package/dist/renderer/index.js +4 -0
  167. package/dist/runtime/index.css +1756 -0
  168. package/dist/runtime/index.d.ts +239 -0
  169. package/dist/runtime/index.js +28 -0
  170. package/dist/slot-host-CPzrxLo9.d.ts +48 -0
  171. package/dist/ssr/index.cjs +9739 -0
  172. package/dist/ssr/index.d.cts +464 -0
  173. package/dist/ssr/index.d.ts +464 -0
  174. package/dist/ssr/index.js +9703 -0
  175. package/dist/storage/browser/index.d.ts +1 -0
  176. package/dist/storage/browser/index.js +2 -0
  177. package/dist/test-support.d.ts +42 -0
  178. package/dist/test-support.js +181 -0
  179. package/dist/themeTokens-CRd8AEDF.d.ts +125 -0
  180. package/dist/three/index.css +503 -0
  181. package/dist/three/index.d.ts +1185 -0
  182. package/dist/three/index.js +3908 -0
  183. package/dist/useUISlots-CiobNFGb.d.ts +211 -0
  184. package/dist/verification-C5pTeMJv.d.ts +66 -0
  185. package/dist/verificationRegistry-CVrcxG1s.d.ts +122 -0
  186. package/dist/wrapCallbackForEvent-B9QLbhxX.d.ts +19 -0
  187. package/index.css +199 -0
  188. package/package.json +273 -3
  189. package/src/core/lib/band-shapes.json +7 -0
  190. package/src/core/locales/ar.json +1276 -0
  191. package/src/core/locales/en.json +1276 -0
  192. package/src/core/locales/index.ts +54 -0
  193. package/src/core/locales/sl.json +1276 -0
  194. package/src/core/tokens/native-tokens.json +369 -0
  195. package/tailwind-compile.cjs +29 -0
  196. package/tailwind-preset.cjs +1020 -0
  197. package/themes/_base.css +451 -0
  198. package/themes/_contract.md +307 -0
  199. package/themes/_fonts-kenney.css +11 -0
  200. package/themes/_fonts.css +12 -0
  201. package/themes/_foundation.css +105 -0
  202. package/themes/_head.css +22 -0
  203. package/themes/_presets.css +67 -0
  204. package/themes/almadar-heritage.css +455 -0
  205. package/themes/almadar-website.css +269 -0
  206. package/themes/almadar.css +269 -0
  207. package/themes/aqua.css +455 -0
  208. package/themes/arabesque.css +459 -0
  209. package/themes/art-deco.css +457 -0
  210. package/themes/art-nouveau.css +459 -0
  211. package/themes/atelier.css +463 -0
  212. package/themes/bauhaus.css +461 -0
  213. package/themes/bloomberg-dense.css +463 -0
  214. package/themes/blueprint.css +457 -0
  215. package/themes/clay.css +449 -0
  216. package/themes/comic.css +453 -0
  217. package/themes/constructivist.css +457 -0
  218. package/themes/corporate.css +449 -0
  219. package/themes/cyberpunk.css +453 -0
  220. package/themes/frutiger-aero.css +458 -0
  221. package/themes/game-adventure.css +201 -0
  222. package/themes/game-rpg.css +203 -0
  223. package/themes/game-sci-fi.css +201 -0
  224. package/themes/game-ui-pack.css +200 -0
  225. package/themes/gazette.css +449 -0
  226. package/themes/glass.css +457 -0
  227. package/themes/gothic.css +453 -0
  228. package/themes/index.css +21 -0
  229. package/themes/ink-wash.css +459 -0
  230. package/themes/kawaii.css +459 -0
  231. package/themes/kflow.css +310 -0
  232. package/themes/kiosk.css +449 -0
  233. package/themes/linear-clean.css +463 -0
  234. package/themes/luxury.css +451 -0
  235. package/themes/mac-classic.css +455 -0
  236. package/themes/material.css +463 -0
  237. package/themes/memphis.css +453 -0
  238. package/themes/mid-century.css +455 -0
  239. package/themes/minimalist.css +449 -0
  240. package/themes/mudcloth.css +459 -0
  241. package/themes/nata.css +310 -0
  242. package/themes/neon.css +453 -0
  243. package/themes/neumorphic.css +451 -0
  244. package/themes/newsprint.css +455 -0
  245. package/themes/notion-editorial.css +463 -0
  246. package/themes/orb.css +465 -0
  247. package/themes/pixel.css +449 -0
  248. package/themes/prism.css +309 -0
  249. package/themes/rawi.css +310 -0
  250. package/themes/retro.css +452 -0
  251. package/themes/risograph.css +463 -0
  252. package/themes/scandi.css +469 -0
  253. package/themes/sketch.css +455 -0
  254. package/themes/solarpunk.css +469 -0
  255. package/themes/steampunk.css +451 -0
  256. package/themes/swiss.css +455 -0
  257. package/themes/terminal.css +466 -0
  258. package/themes/trait-wars.css +487 -0
  259. package/themes/ukiyo-e.css +459 -0
  260. package/themes/vaporwave.css +455 -0
  261. package/themes/victorian.css +453 -0
  262. package/themes/wabi-sabi.css +459 -0
  263. package/themes/win95.css +455 -0
  264. package/themes/wireframe.css +439 -0
  265. package/themes/zine.css +455 -0
  266. package/README.md +0 -3
@@ -0,0 +1,688 @@
1
+ import React__default from 'react';
2
+ import { ScenePos, Asset } from '@almadar/core';
3
+ import { P as Point, R as Rect, F as FxItem, a as FxPreset } from './fx-CmQjnHmT.js';
4
+ import './EventBusProvider-BFFHfN4O.js';
5
+
6
+ /** A polyline/polygon vertex in pixel space. */
7
+ interface PainterPoint {
8
+ x: number;
9
+ y: number;
10
+ }
11
+ /** One color stop of a {@link PainterGradient}; `offset` is 0..1 along the gradient. */
12
+ interface PainterGradientStop {
13
+ offset: number;
14
+ color: string;
15
+ }
16
+
17
+ /**
18
+ * Drawable contract — the shared vocabulary every neutral drawable primitive
19
+ * (the `draw-sprite`/`draw-shape`/`draw-text` atoms, `draw-sprite-layer`/
20
+ * `draw-shape-layer` molecules) is authored against. A drawable is a pure
21
+ * descriptor the canvas HOST walks and paints via the portable {@link Painter2D}
22
+ * seam — no `CanvasRenderingContext2D`, no DOM. Genre (a "unit"/"tile"/
23
+ * "highlight") is a `.lolo` COMPOSITION of these, never its own primitive.
24
+ *
25
+ * A position is a core `ScenePos` (logical scene space). The host's {@link Projector}
26
+ * maps it to pixels; primitives never do projection math themselves. Because the
27
+ * `ScenePos` type identity is what pattern-sync stamps as the `drawable`
28
+ * capability, every drawable descriptor's `position` MUST be a core `ScenePos`.
29
+ */
30
+
31
+ /**
32
+ * How a drawable aligns to its projected position.
33
+ * - `top-left` — the cell's top-left corner (tiles).
34
+ * - `ground` — the cell's ground point, bottom-center of the drawable (units/features).
35
+ * - `center` — the cell's visual center (effects).
36
+ */
37
+ type DrawableAnchor = 'top-left' | 'ground' | 'center';
38
+ /**
39
+ * Maps logical scene coordinates to pixel space for one projection (iso/hex/flat/free).
40
+ * Owns ALL projection geometry so the primitives stay projection-agnostic. The host
41
+ * applies the camera transform on the painter around the walk; the projector is
42
+ * pre-camera (logical→cell-pixel).
43
+ */
44
+ interface Projector {
45
+ /** Cell top-left in pixels. */
46
+ project(pos: ScenePos): PainterPoint;
47
+ /** The pixel reference point for an anchor (see {@link DrawableAnchor}). */
48
+ anchorPoint(pos: ScenePos, anchor: DrawableAnchor): PainterPoint;
49
+ /** The cell footprint polygon — a rect (square grids) or a diamond (iso/hex). */
50
+ cellPath(pos: ScenePos): PainterPoint[];
51
+ /** Cell width in source-px tile-space — the board's native tile width for grid layouts (`flat`/`iso`/`hex`), 1 for `free`/`side` (world-pixel-direct). The host camera applies the on-screen zoom once. */
52
+ readonly tileWidth: number;
53
+ /** Cell floor height in source-px tile-space (`tileWidth / 2` for grid layouts, 1 for `free`/`side`). */
54
+ readonly floorHeight: number;
55
+ /** Diamond-top offset in source-px tile-space (where the iso diamond starts in the sprite). */
56
+ readonly diamondTopY: number;
57
+ /** Render scale factor. */
58
+ /** True for square-pitch grids (`flat`/`free`); false for diamond (iso/hex). */
59
+ readonly squareGrid: boolean;
60
+ /** True for world-pixel-direct layouts (`free`/`side`); false for tile grids (`flat`/`iso`/`hex`). */
61
+ readonly worldPixelDirect: boolean;
62
+ }
63
+ /** Common shape of every drawable descriptor. `type` keys the host's paint dispatch. */
64
+ interface DrawableBase {
65
+ type: string;
66
+ /**
67
+ * Optional hit-test handle. When a board authors a per-entity id here (e.g.
68
+ * `id: (object/get @u id)` on a unit sprite), the canvas host indexes the
69
+ * descriptor's `ScenePos → id` and resolves a pointer/raycast at that cell to
70
+ * this id — the source of `unitClickEvent {unitId}`. A source-tagged handle,
71
+ * NOT a heuristic: no id → the host emits only the coordinate (tile click).
72
+ */
73
+ id?: string;
74
+ }
75
+
76
+ /**
77
+ * `draw-shape` — the neutral vector-fill/stroke drawable atom (dimension-agnostic).
78
+ *
79
+ * ONE descriptor (`DrawShapeProps`, grounded in core `ScenePos`) with TWO
80
+ * backends: `paintShape` (2D, here) and an R3F ground-plane mesh (`Shape3D` in
81
+ * `lib/drawable/mesh3d`, kept OUT of this file so the 2D path never pulls R3F).
82
+ * Paints a cell footprint, an axis-aligned rect, an ellipse, a poly, or an SVG
83
+ * path at a scene position, fill and/or stroke. Genre uses (tile fallback, iso/hex
84
+ * diamond fallback, cell highlight, feature disc, unit selection ring, unit
85
+ * fallback circle, ground/ghost discs, solid backgrounds, side-view platform
86
+ * rects, hand-authored vector art) are all this atom with different
87
+ * `shape`/`anchor`/geometry — composed in `.lolo`, not here. The React component renders `null`; it exists so the pattern pipeline
88
+ * registers a `draw-shape` pattern and standalone pages stay inspectable.
89
+ */
90
+
91
+ type ShapeKind = 'cell' | 'rect' | 'ellipse' | 'poly' | 'path';
92
+ /** Composite modes a shape may blend with — the canvas `globalCompositeOperation` set, spelled out so the pattern schema carries a real enum. */
93
+ 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';
94
+ /** One gradient color stop; `offset` is 0..1 along the gradient axis. */
95
+ type DrawShapeGradientStop = PainterGradientStop;
96
+ /**
97
+ * A gradient fill in world units relative to the cell's projected top-left —
98
+ * same coordinate convention as `points` and `d`. Overrides `fill` when present.
99
+ */
100
+ interface DrawShapeGradient {
101
+ kind: 'linear' | 'radial' | 'conic';
102
+ /** Linear start point in world units. */
103
+ from?: Point;
104
+ /** Linear end point in world units. */
105
+ to?: Point;
106
+ /** Radial/conic center in world units. */
107
+ center?: Point;
108
+ /** Radial radius in world units. */
109
+ radius?: number;
110
+ /** Conic start angle in radians. */
111
+ angle?: number;
112
+ /** Ordered color stops. */
113
+ stops: DrawShapeGradientStop[];
114
+ }
115
+ /**
116
+ * A repeating texture painted OVER the fill, clipped to the same geometry —
117
+ * procedural grain (`noise`) or a tiling image. `scale` is painter-px per noise
118
+ * cell (default 2) / an image scale multiplier; grain stays constant-px under
119
+ * group scale, like strokes.
120
+ */
121
+ interface DrawShapeFillPattern {
122
+ kind: 'noise' | 'image';
123
+ /** Image pattern URL (`kind: 'image'`). */
124
+ url?: string;
125
+ scale?: number;
126
+ /** Noise speckle max alpha (default 0.12). */
127
+ alpha?: number;
128
+ /** Noise speckle color (default black). */
129
+ color?: string;
130
+ }
131
+ /** A soft glow / drop-shadow behind the shape; `blur` is in world units. */
132
+ interface DrawShapeShadow {
133
+ color: string;
134
+ blur: number;
135
+ }
136
+ /**
137
+ * One keyframe of a {@link DrawShapeAnimation}: `at` is the 0..1 position in
138
+ * the cycle; every other field overrides the shape's base prop at that moment.
139
+ */
140
+ interface DrawShapeKeyframe {
141
+ at: number;
142
+ offsetX?: number;
143
+ offsetY?: number;
144
+ rotate?: number;
145
+ opacity?: number;
146
+ radiusX?: number;
147
+ radiusY?: number;
148
+ width?: number;
149
+ height?: number;
150
+ strokeWidth?: number;
151
+ strokeDashOffset?: number;
152
+ blur?: number;
153
+ fill?: string;
154
+ stroke?: string;
155
+ shadow?: DrawShapeShadow;
156
+ }
157
+ /**
158
+ * Declarative keyframe animation for a drawable. The host runs a paint clock
159
+ * while any drawable declares one; numeric tracks lerp between keyframes,
160
+ * string tracks hold the previous keyframe's value, `shadow` lerps `blur` and
161
+ * holds `color`. A track starts from the shape's base prop until its first
162
+ * keyframe defines it.
163
+ */
164
+ interface DrawShapeAnimation {
165
+ /** One cycle length in ms. */
166
+ durationMs: number;
167
+ /** Loop the cycle (default true); false plays once and holds the final keyframes. */
168
+ loop?: boolean;
169
+ /** Keyframes ordered by `at` (0..1). */
170
+ keyframes: DrawShapeKeyframe[];
171
+ }
172
+ interface DrawShapeProps extends DrawableBase {
173
+ type: 'draw-shape';
174
+ shape: ShapeKind;
175
+ /** Logical scene position; the projector maps it to pixels / world. */
176
+ position: ScenePos;
177
+ /** How the shape aligns to its projected position. Default varies by `shape`. */
178
+ anchor?: DrawableAnchor;
179
+ /** Rect width in world units (fractions of `projector.tileWidth`). */
180
+ width?: number;
181
+ /** Rect height in world units (fractions of `projector.tileWidth`). */
182
+ height?: number;
183
+ /** Ellipse horizontal radius in world units (fractions of `projector.tileWidth`). */
184
+ radiusX?: number;
185
+ /** Ellipse vertical radius in world units; omitted → `radiusX` (a circle). */
186
+ radiusY?: number;
187
+ /** 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). */
188
+ offsetX?: number;
189
+ offsetY?: number;
190
+ /** Poly vertices as world-unit offsets relative to the cell's projected top-left. */
191
+ points?: Point[];
192
+ /** SVG path data in world units relative to the cell's projected top-left — same coordinate convention as `points`. */
193
+ d?: string;
194
+ fill?: string;
195
+ /** Gradient fill in world units; overrides `fill` when present. */
196
+ gradient?: DrawShapeGradient;
197
+ /** Repeating texture painted over the fill (grain / tiling image). */
198
+ fillPattern?: DrawShapeFillPattern;
199
+ stroke?: string;
200
+ strokeWidth?: number;
201
+ /** Gradient stroke in world units; overrides `stroke` when present. */
202
+ strokeGradient?: DrawShapeGradient;
203
+ /** Dash pattern in painter-px (constant under group scale, like `strokeWidth`). */
204
+ strokeDash?: number[];
205
+ /** Dash phase offset in painter-px; animatable (marching ants). */
206
+ strokeDashOffset?: number;
207
+ /** Composite/blend mode for this shape's draws (`lighter`, `multiply`, `screen`, …). */
208
+ blendMode?: DrawShapeBlendMode;
209
+ /** Gaussian blur in painter-px. Expensive — forces an intermediate raster; use sparingly. */
210
+ blur?: number;
211
+ /** Rotation in radians (painter units, same as `draw-group`), about `pivot`. */
212
+ rotate?: number;
213
+ /** Rotation pivot in world units relative to the cell's projected top-left; default `{x:0.5, y:0.5}` (cell center). */
214
+ pivot?: Point;
215
+ /** Soft glow / drop-shadow behind the shape; `blur` in world units. */
216
+ shadow?: DrawShapeShadow;
217
+ /** Keyframe animation over this shape's props; the host runs a paint clock while present. */
218
+ animation?: DrawShapeAnimation;
219
+ /** 0..1 opacity. */
220
+ opacity?: number;
221
+ }
222
+ /** Registry/standalone stub — the host paints this atom; the DOM renders nothing.
223
+ * When composed as a React child of a draw-host (Canvas2D), registers its
224
+ * descriptor via context so the host paints it. */
225
+ declare function DrawShape(props: DrawShapeProps): React__default.JSX.Element | null;
226
+
227
+ /**
228
+ * `draw-sprite` — the neutral image/atlas-frame drawable atom (dimension-agnostic).
229
+ *
230
+ * ONE descriptor (`DrawSpriteProps`, grounded in core `ScenePos` + `Asset`) with
231
+ * TWO backends: `paintSprite` (2D, here — via the portable `Painter2D` seam) and
232
+ * an R3F mesh (`Sprite3D` in `lib/drawable/mesh3d`, kept OUT of this file so the
233
+ * 2D paint path never pulls `three`/`drei` into an app bundle — the codebase
234
+ * code-splits R3F). The canvas host picks the backend by `mode`; that is what
235
+ * makes canvas-2d and canvas-3d the same `children` interface. Genre uses (tile,
236
+ * unit body, feature, effect, movement ghost, background cover) are all this atom
237
+ * with different `anchor`/`size`/`frame`/`flip`/`shadow` — composed in `.lolo`,
238
+ * not here. The React component renders `null` (a drawable is painted by the host,
239
+ * not the DOM); it exists so the pattern pipeline registers a `draw-sprite`
240
+ * pattern and standalone pages stay inspectable.
241
+ */
242
+
243
+ interface DrawSpriteProps extends DrawableBase {
244
+ type: 'draw-sprite';
245
+ /** Logical scene position; the projector maps it to pixels / world. */
246
+ position: ScenePos;
247
+ /** The image / atlas reference to blit. */
248
+ asset: Asset;
249
+ /** How the sprite aligns to its projected position. Default `'top-left'`. */
250
+ anchor?: DrawableAnchor;
251
+ /** Draw width in world units (fractions of `projector.tileWidth`). Omitted → one cell on tile grids (`flat`/`iso`/`hex`); native source px on `free`/`side`. */
252
+ width?: number;
253
+ /** Draw height in world units (fractions of `projector.tileWidth`). Omitted → one cell on tile grids (`flat`/`iso`/`hex`); native source px on `free`/`side`. */
254
+ height?: number;
255
+ /** Explicit atlas sub-rect override (px); omitted → resolved from `asset.atlas`/`asset.sprite`. */
256
+ frame?: Rect;
257
+ /** Animation to play. 3D backend: a named GLB clip (matched case-insensitively). 2D painter: when `asset.atlas` resolves to a `SpriteSheetAtlas` manifest, the canonical row of that name (idle/walk/attack/hit/death) plays off the host paint clock; an explicit `frame` rect overrides. */
258
+ animation?: string;
259
+ /** Override the sheet row's loop flag. The paint clock is wall-time, so one-shot rows hold their final frame — preview pages set `true` to cycle attack/hit/death continuously. */
260
+ loop?: boolean;
261
+ /** Animation clock override in ms (e.g. an fx entry's age since spawn). Omitted → the host paint clock; one-shot rows anchored to wall-time would otherwise sit on their final frame. */
262
+ clockMs?: number;
263
+ /** Mirror horizontally (facing). */
264
+ flipX?: boolean;
265
+ /** Rotation in radians about the sprite's center. */
266
+ rotation?: number;
267
+ /** 0..1 opacity. */
268
+ opacity?: number;
269
+ /** Drop shadow (e.g. a team-colored glow). */
270
+ shadow?: DrawShapeShadow;
271
+ }
272
+ /** Registry/standalone stub — the host paints this atom; the DOM renders nothing. */
273
+ declare function DrawSprite(_props: DrawSpriteProps): React__default.JSX.Element | null;
274
+
275
+ /**
276
+ * `draw-text` — the neutral text drawable atom (dimension-agnostic).
277
+ *
278
+ * ONE descriptor (`DrawTextProps`, grounded in core `ScenePos`) with TWO backends:
279
+ * `paintText` (2D, here) and an R3F billboarded `<Text>` (`Text3D` in
280
+ * `lib/drawable/mesh3d`, kept OUT of this file so the 2D path never pulls R3F).
281
+ * Paints a string at a scene position with font/color/alignment. The React
282
+ * component renders `null` (a drawable is painted by the host, not the DOM).
283
+ */
284
+
285
+ /**
286
+ * Mirrors DOM lib.dom.d.ts `CanvasTextAlign` by value (used directly instead
287
+ * of the ambient global so the pattern-sync scanner — which only indexes
288
+ * `components/**` and can't see ambient TS-lib types — resolves this to a
289
+ * concrete enum instead of `json`). Structurally identical; `node.align`
290
+ * still flows straight into `Painter2D.text`'s `TextStyle.align`.
291
+ */
292
+ type DrawTextAlign = 'center' | 'end' | 'left' | 'right' | 'start';
293
+ /** Mirrors DOM `CanvasTextBaseline` by value — see {@link DrawTextAlign}. */
294
+ type DrawTextBaseline = 'alphabetic' | 'bottom' | 'hanging' | 'ideographic' | 'middle' | 'top';
295
+ interface DrawTextProps extends DrawableBase {
296
+ type: 'draw-text';
297
+ text: string;
298
+ /** Logical scene position; the projector maps it to pixels / world. */
299
+ position: ScenePos;
300
+ anchor?: DrawableAnchor;
301
+ offsetX?: number;
302
+ offsetY?: number;
303
+ color: string;
304
+ font?: string;
305
+ align?: DrawTextAlign;
306
+ baseline?: DrawTextBaseline;
307
+ opacity?: number;
308
+ }
309
+ /** Registry/standalone stub — the host paints this atom; the DOM renders nothing. */
310
+ declare function DrawText(_props: DrawTextProps): React__default.JSX.Element | null;
311
+
312
+ /**
313
+ * `draw-mesh` — the volumetric 3D drawable atom (3D-canvas backend).
314
+ *
315
+ * ONE descriptor (`DrawMeshProps`, grounded in core `ScenePos`) with the R3F
316
+ * backend `Mesh3D` in `lib/drawable/three/DrawMesh3D` (kept OUT of this file so
317
+ * the 2D path never pulls three). A parametric primitive (box, sphere, capsule,
318
+ * cylinder, cone, torus, plane, circle — `plane`/`circle` lie flat in the
319
+ * scene ground plane facing up, matching the 2D painter) or a raw-geometry `polyhedron`
320
+ * (`vertices` + `faces` as plain data) at a scene position — `position.z` is
321
+ * height in cells — with a data-driven material (`standard`/`physical`/`toon`/
322
+ * `basic`), an optional inverted-hull outline, and keyframe animation over
323
+ * transform/material tracks. Low-poly is a knob, not a geometry rewrite:
324
+ * `segments` 4–8 + `material.flatShading`. Composed in `.lolo` like every
325
+ * drawable; the 2D painter skips it with a one-time warn. The React component
326
+ * renders `null`; it exists so the pattern pipeline registers a `draw-mesh`
327
+ * pattern and standalone pages stay inspectable.
328
+ */
329
+
330
+ type MeshShapeKind = 'box' | 'sphere' | 'capsule' | 'cylinder' | 'cone' | 'torus' | 'plane' | 'circle' | 'polyhedron';
331
+ type MeshMaterialKind = 'standard' | 'physical' | 'toon' | 'basic';
332
+ type MeshMaterialSide = 'front' | 'back' | 'double';
333
+ /**
334
+ * Data-driven surface description — the 3D analog of the 2D fill/gradient knobs.
335
+ * `standard`/`physical` are lit PBR (physical adds `transmission`/`ior` for glass
336
+ * and crystal), `toon` is cel-banded, `basic` is unlit flat color.
337
+ */
338
+ interface MeshMaterial {
339
+ kind?: MeshMaterialKind;
340
+ /** Albedo color (CSS color string). */
341
+ color?: string;
342
+ /** 0..1 — how metallic the surface reads (PBR kinds). */
343
+ metalness?: number;
344
+ /** 0..1 — microfacet roughness; low = glossy (PBR kinds). */
345
+ roughness?: number;
346
+ /** Emissive color; pairs with the canvas `post.bloom` for neon/glow. */
347
+ emissive?: string;
348
+ /** Emissive strength multiplier (default 1 when `emissive` is set). */
349
+ emissiveIntensity?: number;
350
+ /** 0..1 material opacity; multiplies the node/group opacity. */
351
+ opacity?: number;
352
+ /** 0..1 light transmission — glass/crystal (`physical` only). */
353
+ transmission?: number;
354
+ /** Index of refraction (`physical` only, default 1.5). */
355
+ ior?: number;
356
+ /** Faceted shading — the low-poly look (pairs with low `segments`). */
357
+ flatShading?: boolean;
358
+ /** Which faces render (default `front`). */
359
+ side?: MeshMaterialSide;
360
+ /** Albedo texture: an image URL or `data:` URI, sampled through the polyhedron's `uvs`. Multiplied by `color` — keep `color` white (or unset) to show the texture unmodified. */
361
+ map?: string;
362
+ }
363
+ /** Inverted-hull toon outline: a back-face shell of the same geometry, scaled out by `width`. */
364
+ interface MeshOutline {
365
+ /** Outline color (default near-black). */
366
+ color?: string;
367
+ /** Shell expansion as a fraction of the mesh size (default 0.05). */
368
+ width?: number;
369
+ }
370
+ /**
371
+ * One keyframe of a {@link DrawMeshAnimation}: `at` is the 0..1 position in the
372
+ * cycle. Transform tracks are DELTAS from the base props (offsets in cells,
373
+ * rotations in radians, `scale` a multiplier); material tracks override.
374
+ */
375
+ interface DrawMeshKeyframe {
376
+ at: number;
377
+ offsetX?: number;
378
+ offsetY?: number;
379
+ offsetZ?: number;
380
+ rotateX?: number;
381
+ rotateY?: number;
382
+ rotateZ?: number;
383
+ scale?: number;
384
+ opacity?: number;
385
+ emissiveIntensity?: number;
386
+ color?: string;
387
+ emissive?: string;
388
+ }
389
+ /**
390
+ * Declarative keyframe animation for a mesh; the 3D host advances it per frame.
391
+ * Numeric tracks lerp between keyframes, color tracks hold the previous
392
+ * keyframe's value. A track rests at its identity until its first keyframe.
393
+ */
394
+ interface DrawMeshAnimation {
395
+ /** One cycle length in ms. */
396
+ durationMs: number;
397
+ /** Loop the cycle (default true); false plays once and holds the final keyframes. */
398
+ loop?: boolean;
399
+ /** Keyframes ordered by `at` (0..1). */
400
+ keyframes: DrawMeshKeyframe[];
401
+ }
402
+ /**
403
+ * Smooth-skinning data for a `polyhedron` — plain declarative data, no runtime
404
+ * objects. Vertices carry blended bone weights (a neck-base vertex can be 60%
405
+ * neck / 40% spine), so the surface stretches continuously across joints
406
+ * instead of cracking at rigid chunk boundaries.
407
+ */
408
+ interface DrawMeshSkin {
409
+ /** Bone names, resolved against sibling `draw-group` `bone:` names in the same canvas. */
410
+ bones: string[];
411
+ /** One 16-float column-major inverse bind matrix per bone (model space → bone bind-local; translations in cells). */
412
+ inverseBindMatrices: number[][];
413
+ /** Per-vertex bone indices into `bones`, up to 4 each (pad with 0). */
414
+ indices: number[][];
415
+ /** Per-vertex blend weights matching `indices`, normalized to sum 1 (pad with 0). */
416
+ weights: number[][];
417
+ }
418
+ interface DrawMeshProps extends DrawableBase {
419
+ type: 'draw-mesh';
420
+ shape: MeshShapeKind;
421
+ /** Logical scene position; `z` is height in cells (projected to world Y). */
422
+ position: ScenePos;
423
+ /** Box/plane X extent in cells (default 1). */
424
+ width?: number;
425
+ /** Box Y (height) extent / capsule-cylinder-cone length in cells (default 1). */
426
+ height?: number;
427
+ /** Box/plane Z extent in cells (default `width`). */
428
+ depth?: number;
429
+ /** Sphere/capsule/cone/torus/circle radius in cells (default 0.4). */
430
+ radius?: number;
431
+ /** Cylinder top radius (default `radius`). */
432
+ radiusTop?: number;
433
+ /** Cylinder bottom radius (default `radius`). */
434
+ radiusBottom?: number;
435
+ /** Torus tube radius in cells (default `radius` / 3). */
436
+ tube?: number;
437
+ /** Curved-surface tessellation, clamped 3..64 (default 24). 4–8 + `flatShading` = low-poly. */
438
+ segments?: number;
439
+ /** `polyhedron` only: raw vertices as scene-frame `[x, y, z]` triples in cells, `z` = up. */
440
+ vertices?: number[][];
441
+ /** `polyhedron` only: triangle index triples into `vertices`, wound counter-clockwise seen from OUTSIDE in the scene frame. */
442
+ faces?: number[][];
443
+ /** `polyhedron` only: per-vertex `[u, v]` texture coordinates parallel to `vertices`, glTF convention (`v` grows DOWN from the image's top-left). Pairs with `material.map`. */
444
+ uvs?: number[][];
445
+ /** `polyhedron` only: smooth-skinning weights binding the vertices to named bone groups. Vertices must then be authored in BIND POSE model space; the bones' animated transforms deform them. */
446
+ skin?: DrawMeshSkin;
447
+ /** Euler rotation `[x, y, z]` in radians. */
448
+ rotation?: [number, number, number];
449
+ /** `bottom` (default) rests the mesh on its position's ground plane; `center` centers it there. For `polyhedron`, `bottom` lifts by −min(z) and `center` applies no offset — the vertices are authoritative. */
450
+ pivot?: 'bottom' | 'center';
451
+ material?: MeshMaterial;
452
+ outline?: MeshOutline;
453
+ castShadow?: boolean;
454
+ receiveShadow?: boolean;
455
+ /** Keyframe animation over transform/material tracks; the 3D host runs it per frame. */
456
+ animation?: DrawMeshAnimation;
457
+ /** 0..1 opacity; multiplies the material and enclosing group opacity. */
458
+ opacity?: number;
459
+ }
460
+ /** Registry/standalone stub — the 3D host renders this atom; the DOM renders nothing.
461
+ * When composed as a React child of a draw-host, registers its descriptor via
462
+ * context so the host paints it — same path as DrawShape. */
463
+ declare function DrawMesh(props: DrawMeshProps): React__default.JSX.Element | null;
464
+
465
+ /**
466
+ * `draw-group` — the drawable CONTAINER atom (dimension-agnostic).
467
+ *
468
+ * Multi-shape art (a hero token = cloak + head + sword shapes) travels as ONE
469
+ * node: the host paints the group by translating to its projected position,
470
+ * applying `scale`/`rotate`/`opacity`, then painting each `items` descriptor
471
+ * through the normal dispatch. `items` is a plain data prop (NOT `children`,
472
+ * which UISlotRenderer special-cases) — same convention as the `draw-*-layer`
473
+ * molecules. The React component renders `null`; it exists so the pattern
474
+ * pipeline registers a `draw-group` pattern and standalone pages stay
475
+ * inspectable. Both backends paint it: 2D as a canvas transform, 3D as a three
476
+ * `<group>` — with `rotation` + `animation` a nested group chain is a skeleton
477
+ * bone chain (rotate the shoulder group and the forearm group follows).
478
+ */
479
+
480
+ interface DrawGroupProps extends DrawableBase {
481
+ type: 'draw-group';
482
+ /** Logical scene position; the projector maps it to pixels / world. */
483
+ position: ScenePos;
484
+ /** Uniform scale applied to the whole group. */
485
+ scale?: number;
486
+ /** Rotation in radians (painter units). */
487
+ rotate?: number;
488
+ /** Euler rotation `[x, y, z]` in radians (world axes) — per-axis joint rotation for the 3D backend; a group placed at a joint with children authored joint-local IS a bone. The 2D painter applies only the in-plane `z` component, after `rotate`. */
489
+ rotation?: [number, number, number];
490
+ /** Skeleton bone name. A named group is addressable by a `draw-mesh` `skin`
491
+ * block (smooth skinning): the skinned mesh deforms with this group's
492
+ * animated transform. Names resolve within the nearest enclosing
493
+ * `skeleton: true` group (falling back to the canvas), so multiple
494
+ * instances of one rig never collide. Distinct from `id` (the hit-test
495
+ * handle). */
496
+ bone?: string;
497
+ /** Marks this group as a skeleton SCOPE: `bone` names and `skin` bindings in
498
+ * its subtree resolve against each other only — one scope per rig instance. */
499
+ skeleton?: boolean;
500
+ /** Keyframe animation over the group TRANSFORM tracks (`offsetX/Y/Z` in cells, `rotateX/Y/Z` in radians, `scale`; the 2D painter also honors `opacity`) — children inherit it, so nested animated groups form a joint chain. Material tracks belong on leaf meshes. */
501
+ animation?: DrawMeshAnimation;
502
+ /** 0..1 opacity. */
503
+ opacity?: number;
504
+ /** Clip the group's items to an SVG path (`d` syntax) in world units relative to the group origin — masked reveals, meters, portraits. */
505
+ clip?: string;
506
+ /** The grouped drawables, painted through the normal dispatch. */
507
+ items: DrawableNode[];
508
+ }
509
+ /** Registry/standalone stub — the host paints this atom; the DOM renders nothing.
510
+ * When composed as a React child of a draw-host (Canvas2D), registers its
511
+ * descriptor via context so the host paints it — same path as DrawShape. */
512
+ declare function DrawGroup(props: DrawGroupProps): React__default.JSX.Element | null;
513
+
514
+ interface SkinWeight {
515
+ /** Index into the drawable's `bones` array. */
516
+ bone: number;
517
+ w: number;
518
+ }
519
+ interface SkinVertex {
520
+ x: number;
521
+ y: number;
522
+ /** Normalized 0..1 texture coordinates. */
523
+ u: number;
524
+ v: number;
525
+ weights: SkinWeight[];
526
+ }
527
+ interface SkinMesh {
528
+ vertices: SkinVertex[];
529
+ triangles: [number, number, number][];
530
+ }
531
+ interface BoneDef {
532
+ name: string;
533
+ parent: string | null;
534
+ /** Rotation pivot in local space (the joint the bone turns about). */
535
+ pivot: [number, number];
536
+ /** Bone end point in local space (render/inspect hint; no skinning role). */
537
+ tip: [number, number];
538
+ }
539
+ /** Bone name → rotation in degrees relative to the bind pose. */
540
+ type Pose = Record<string, number>;
541
+
542
+ /**
543
+ * `draw-skinned-mesh` — the skeletal-mesh drawable atom: a bind-pose triangle
544
+ * mesh deformed by linear blend skinning and painted per-triangle from a texture.
545
+ *
546
+ * The general-purpose primitive for animated 2D characters (puppet rigs): a pose
547
+ * rotates each bone about its pivot (degrees, relative to bind), `lib/skinning`
548
+ * computes the deformed vertices, and each triangle is blit through the affine
549
+ * mapping its UV tri → its painted tri (clipped to the tri, so seams don't bleed).
550
+ * Mesh + bones + UVs come from the bundle exporter (inline `mesh` or a fetched
551
+ * `meshUrl`); animation is `clip.frames[frame % len]`, driven by the host like
552
+ * any other drawable frame counter. `weightsOverlay` swaps the texture for a
553
+ * per-bone categorical fill (rig inspection); `ghost` paints an onion-skin pass
554
+ * of another clip frame underneath. The React component renders `null` (the host
555
+ * paints it); it exists so the pattern pipeline registers a `draw-skinned-mesh`
556
+ * pattern and JSX children register through the drawable registry.
557
+ */
558
+
559
+ interface DrawSkinnedMeshProps extends DrawableBase {
560
+ type: 'draw-skinned-mesh';
561
+ /** Logical scene position; mesh local coords are world units relative to its projected top-left. */
562
+ position: ScenePos;
563
+ /** The texture the mesh UVs cut into. */
564
+ asset: Asset;
565
+ /** Inline bind mesh; wins over `meshUrl`. */
566
+ mesh?: SkinMesh;
567
+ /** URL of a JSON `SkinMesh` (fetched + cached); used when `mesh` is absent. */
568
+ meshUrl?: string;
569
+ /** The skeleton (bind pose; FK chain via `parent` names). Falls back to the rigbundle's `bones` when empty. */
570
+ bones: BoneDef[];
571
+ /** Static pose (bone name → degrees relative to bind). Overridden by `clip` + `frame`. */
572
+ pose?: Pose;
573
+ /** Pose animation clip; with `frame`, pose = `frames[frame % frames.length]`. */
574
+ clip?: {
575
+ frames: Pose[];
576
+ };
577
+ /** Named clip inside the rigbundle at `meshUrl` (`clips[clipName].frames`); used when `clip` is absent. Empty/unknown = no clip. */
578
+ clipName?: string;
579
+ /** Clip frame counter (host-driven paint clock frame). */
580
+ frame?: number;
581
+ /** 0..1 opacity. */
582
+ opacity?: number;
583
+ /** Paint per-triangle dominant-bone colors instead of the texture (rig inspection). */
584
+ weightsOverlay?: boolean;
585
+ /** Onion skin: render the mesh at this clip frame underneath, at this opacity. */
586
+ ghost?: {
587
+ frame: number;
588
+ opacity: number;
589
+ };
590
+ }
591
+ /** Registry/standalone stub — the host paints this atom; the DOM renders nothing.
592
+ * When composed as a React child of a draw-host (Canvas2D), registers its
593
+ * descriptor via context so the host paints it. */
594
+ declare function DrawSkinnedMesh(props: DrawSkinnedMeshProps): React__default.JSX.Element | null;
595
+
596
+ /**
597
+ * `draw-sprite-layer` — batch multiple sprites in one descriptor for O(layers) rendering.
598
+ *
599
+ * Composes the `draw-sprite` atom; the layer itself carries no `position` — each
600
+ * item does. It is drawable-by-composition: its `items` are `draw-sprite`
601
+ * descriptors (each grounded in core `ScenePos`), which is what stamps the layer
602
+ * `drawable` at pattern-sync time.
603
+ */
604
+
605
+ interface DrawSpriteLayerProps extends DrawableBase {
606
+ type: 'draw-sprite-layer';
607
+ /** Sprites painted in array order; z-ordering is the caller's responsibility. */
608
+ items: DrawSpriteProps[];
609
+ }
610
+ /** Registry/standalone stub — the host paints this molecule; the DOM renders nothing. */
611
+ declare function DrawSpriteLayer(_props: DrawSpriteLayerProps): React__default.JSX.Element | null;
612
+
613
+ /**
614
+ * `draw-shape-layer` — batch of shapes in one descriptor for O(layers) perf.
615
+ *
616
+ * Composes the `draw-shape` atom; drawable-by-composition (its `items` are
617
+ * `draw-shape` descriptors, each grounded in core `ScenePos`). The React
618
+ * component renders `null` (a drawable is painted by the host, not the DOM).
619
+ */
620
+
621
+ interface DrawShapeLayerProps extends DrawableBase {
622
+ type: 'draw-shape-layer';
623
+ items: DrawShapeProps[];
624
+ }
625
+ /** Registry/standalone stub — the host paints this molecule; the DOM renders nothing. */
626
+ declare function DrawShapeLayer(_props: DrawShapeLayerProps): React__default.JSX.Element | null;
627
+
628
+ /**
629
+ * `draw-text-layer` — batch of text labels in one descriptor for O(layers) perf.
630
+ *
631
+ * Composes the `draw-text` atom; drawable-by-composition (its `items` are
632
+ * `draw-text` descriptors, each grounded in core `ScenePos`). Covers the batched
633
+ * world-space text pass — fx messages, damage numbers, unit labels — that a
634
+ * board maps from an entity array (`items: (array/map @entity.fx (fn ...))`),
635
+ * which a literal `children` array can't express. The React component renders
636
+ * `null` (a drawable is painted by the host, not the DOM).
637
+ */
638
+
639
+ interface DrawTextLayerProps extends DrawableBase {
640
+ type: 'draw-text-layer';
641
+ items: DrawTextProps[];
642
+ }
643
+ /** Registry/standalone stub — the host paints this molecule; the DOM renders nothing. */
644
+ declare function DrawTextLayer(_props: DrawTextLayerProps): React__default.JSX.Element | null;
645
+
646
+ /**
647
+ * `draw-fx-layer` — the batched transient-effects pass in one descriptor.
648
+ *
649
+ * The descriptor and its paint clock go to the shared Rust projector through
650
+ * the installed kernel WASM module. `std-fx-particles` owns ttl and removal;
651
+ * the projector derives world-space art, sprites, shapes, and messages. The
652
+ * React component renders `null` because its canvas host paints the result.
653
+ */
654
+
655
+ interface DrawFxLayerProps extends DrawableBase {
656
+ type: 'draw-fx-layer';
657
+ /** The live fx entries — the mechanic's `@entity.fx` list passed whole; `space: "screen"` entries are skipped (the overlay owns those). */
658
+ items: FxItem[];
659
+ /** Consumer-declared effect vocabulary — one row per fx `type` (look + recipe). Unknown types fall back to a neutral spark burst. */
660
+ presets?: FxPreset[];
661
+ /** Vector art per fx type (an asset-art map: type → anim-state → drawables); a type's `idle` state wins over sprites/procedural. */
662
+ art?: Record<string, Record<string, DrawableNode[]>>;
663
+ /** Sprite asset per fx type (an asset-manifest effects map) — used when no vector art matches. */
664
+ sprites?: Record<string, Asset>;
665
+ /** The fx mechanic's decay tick period in ms; lifetime = maxTtl × tickMs. Default 500. */
666
+ tickMs?: number;
667
+ /** Floating-message text color when an item declares none. Default `#ffe066`. */
668
+ textColor?: string;
669
+ }
670
+ /** Registry/standalone stub — the host paints this molecule; the DOM renders nothing. */
671
+ declare function DrawFxLayer(_props: DrawFxLayerProps): React__default.JSX.Element | null;
672
+
673
+ /**
674
+ * Drawable paint dispatch (2D) + the `DrawableNode` union.
675
+ *
676
+ * `paintDrawable` routes ONE descriptor to its 2D painter; the host walks its
677
+ * `children` through it. The "drawable" designation itself is NOT recorded here —
678
+ * it is DERIVED from the core `ScenePos` type each descriptor's `position` uses
679
+ * and stamped into `patterns-registry.json` by pattern-sync (mirroring how `Asset`
680
+ * is tagged), then read by the orbital-rust validator. So this module is pure
681
+ * paint routing; the capability is the registry's, not a hand-list.
682
+ */
683
+
684
+ /** Every drawable descriptor. The host's `children` are a `DrawableNode[]`. */
685
+ type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawMeshProps | DrawSkinnedMeshProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps | DrawFxLayerProps;
686
+
687
+ export { DrawFxLayer as e, DrawGroup as f, DrawMesh as g, DrawShape as h, DrawShapeLayer as i, DrawSkinnedMesh as j, DrawSprite as k, DrawSpriteLayer as l, DrawText as m, DrawTextLayer as n };
688
+ export type { DrawableNode as D, MeshShapeKind as M, Projector as P, MeshMaterial as a, DrawGroupProps as b, DrawTextProps as c, DrawMeshProps as d };