@pibbl/core 0.0.2 → 0.0.3-alpha.109.1

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 (549) hide show
  1. package/THIRD_PARTY_NOTICES.txt +81 -0
  2. package/dist/features/physics/2d-testing.d.ts +1 -1
  3. package/dist/features/physics/2d-testing.js +2 -2
  4. package/dist/features/physics/2d-testing.js.map +2 -2
  5. package/dist/features/physics/lib/2d/canvas/components.js +25 -21
  6. package/dist/features/physics/lib/2d/canvas/components.js.map +2 -2
  7. package/dist/features/physics/lib/2d/canvas/presentation.js +1 -2
  8. package/dist/features/physics/lib/2d/canvas/presentation.js.map +2 -2
  9. package/dist/features/physics/lib/2d/collision/casts.js +4 -2
  10. package/dist/features/physics/lib/2d/collision/casts.js.map +2 -2
  11. package/dist/features/physics/lib/2d/runtime/controller.js +1 -1
  12. package/dist/features/physics/lib/2d/runtime/controller.js.map +2 -2
  13. package/dist/features/physics/lib/2d/runtime/obstacles.js +9 -11
  14. package/dist/features/physics/lib/2d/runtime/obstacles.js.map +2 -2
  15. package/dist/features/physics/lib/2d/shapes.js +8 -9
  16. package/dist/features/physics/lib/2d/shapes.js.map +2 -2
  17. package/dist/features/physics/lib/2d/world/rapier.js +22 -26
  18. package/dist/features/physics/lib/2d/world/rapier.js.map +2 -2
  19. package/dist/features/sprites/loader.js +6 -3
  20. package/dist/features/sprites/loader.js.map +2 -2
  21. package/dist/features/textures/index.d.ts +12 -2
  22. package/dist/features/textures/index.js +33 -1
  23. package/dist/features/textures/index.js.map +2 -2
  24. package/dist/features/textures/lib/chemical-field.d.ts +56 -0
  25. package/dist/features/textures/lib/chemical-field.js +154 -0
  26. package/dist/features/textures/lib/chemical-field.js.map +7 -0
  27. package/dist/features/textures/lib/chemical-recipes.d.ts +119 -0
  28. package/dist/features/textures/lib/chemical-recipes.js +275 -0
  29. package/dist/features/textures/lib/chemical-recipes.js.map +7 -0
  30. package/dist/features/textures/lib/definitions.d.ts +3 -18
  31. package/dist/features/textures/lib/definitions.js +17 -24
  32. package/dist/features/textures/lib/definitions.js.map +2 -2
  33. package/dist/features/textures/lib/geometric-patterns.d.ts +149 -0
  34. package/dist/features/textures/lib/geometric-patterns.js +305 -0
  35. package/dist/features/textures/lib/geometric-patterns.js.map +7 -0
  36. package/dist/features/textures/lib/gray-scott.d.ts +55 -0
  37. package/dist/features/textures/lib/gray-scott.js +37 -0
  38. package/dist/features/textures/lib/gray-scott.js.map +7 -0
  39. package/dist/features/textures/lib/palette.js +1 -3
  40. package/dist/features/textures/lib/palette.js.map +2 -2
  41. package/dist/features/textures/lib/patterns.d.ts +123 -0
  42. package/dist/features/textures/lib/patterns.js +344 -0
  43. package/dist/features/textures/lib/patterns.js.map +7 -0
  44. package/dist/features/textures/lib/rain-drops.js +2 -1
  45. package/dist/features/textures/lib/rain-drops.js.map +2 -2
  46. package/dist/features/textures/lib/reaction-diffusion.d.ts +3 -2
  47. package/dist/features/textures/lib/reaction-diffusion.js +9 -20
  48. package/dist/features/textures/lib/reaction-diffusion.js.map +2 -2
  49. package/dist/features/textures/lib/simulation.d.ts +10 -4
  50. package/dist/features/textures/lib/simulation.js +23 -13
  51. package/dist/features/textures/lib/simulation.js.map +2 -2
  52. package/dist/features/textures/lib/wasm/electric.js +8 -1
  53. package/dist/features/textures/lib/wasm/electric.js.map +2 -2
  54. package/dist/features/textures/lib/water-surface.js +1 -3
  55. package/dist/features/textures/lib/water-surface.js.map +2 -2
  56. package/dist/features/viz/index.d.ts +68 -6
  57. package/dist/features/viz/index.js +164 -2
  58. package/dist/features/viz/index.js.map +2 -2
  59. package/dist/features/viz/inspection/bar.d.ts +79 -0
  60. package/dist/features/viz/inspection/bar.js +49 -0
  61. package/dist/features/viz/inspection/bar.js.map +7 -0
  62. package/dist/features/viz/inspection/candle.d.ts +156 -0
  63. package/dist/features/viz/inspection/candle.js +120 -0
  64. package/dist/features/viz/inspection/candle.js.map +7 -0
  65. package/dist/features/viz/inspection/capture-types.d.ts +65 -0
  66. package/dist/features/viz/inspection/capture.d.ts +16 -0
  67. package/dist/features/viz/inspection/capture.js +49 -0
  68. package/dist/features/viz/inspection/capture.js.map +7 -0
  69. package/dist/features/viz/inspection/handler.d.ts +36 -0
  70. package/dist/features/viz/inspection/handler.js +91 -0
  71. package/dist/features/viz/inspection/handler.js.map +7 -0
  72. package/dist/features/viz/inspection/ohlc-bar.d.ts +132 -0
  73. package/dist/features/viz/inspection/ohlc-bar.js +118 -0
  74. package/dist/features/viz/inspection/ohlc-bar.js.map +7 -0
  75. package/dist/features/viz/inspection/owned-ref.d.ts +16 -0
  76. package/dist/features/viz/inspection/owned-ref.js +99 -0
  77. package/dist/features/viz/inspection/owned-ref.js.map +7 -0
  78. package/dist/features/viz/inspection/painted-point.d.ts +22 -0
  79. package/dist/features/viz/inspection/painted-point.js +29 -0
  80. package/dist/features/viz/inspection/painted-point.js.map +7 -0
  81. package/dist/features/viz/inspection/queries.d.ts +100 -0
  82. package/dist/features/viz/inspection/queries.js +192 -0
  83. package/dist/features/viz/inspection/queries.js.map +7 -0
  84. package/dist/features/viz/inspection/query-types.d.ts +177 -0
  85. package/dist/features/viz/inspection/volume.d.ts +104 -0
  86. package/dist/features/viz/inspection/volume.js +95 -0
  87. package/dist/features/viz/inspection/volume.js.map +7 -0
  88. package/dist/features/viz/inspection.d.ts +19 -0
  89. package/dist/features/viz/inspection.js +54 -0
  90. package/dist/features/viz/inspection.js.map +7 -0
  91. package/dist/features/viz/inspection.mjs +1 -0
  92. package/dist/features/viz/lib/area-series.d.ts +62 -0
  93. package/dist/features/viz/lib/area-series.js +120 -0
  94. package/dist/features/viz/lib/area-series.js.map +7 -0
  95. package/dist/features/viz/lib/axis-title.js +2 -1
  96. package/dist/features/viz/lib/axis-title.js.map +2 -2
  97. package/dist/features/viz/lib/axis.js +1 -1
  98. package/dist/features/viz/lib/axis.js.map +2 -2
  99. package/dist/features/viz/lib/bar-series.d.ts +3 -1
  100. package/dist/features/viz/lib/bar-series.js +16 -1
  101. package/dist/features/viz/lib/bar-series.js.map +2 -2
  102. package/dist/features/viz/lib/baseline-series.d.ts +55 -0
  103. package/dist/features/viz/lib/baseline-series.js +136 -0
  104. package/dist/features/viz/lib/baseline-series.js.map +7 -0
  105. package/dist/features/viz/lib/candlestick-series.d.ts +62 -0
  106. package/dist/features/viz/lib/candlestick-series.js +150 -0
  107. package/dist/features/viz/lib/candlestick-series.js.map +7 -0
  108. package/dist/features/viz/lib/censored-point-series.d.ts +71 -0
  109. package/dist/features/viz/lib/censored-point-series.js +129 -0
  110. package/dist/features/viz/lib/censored-point-series.js.map +7 -0
  111. package/dist/features/viz/lib/color-context.d.ts +4 -0
  112. package/dist/features/viz/lib/color-context.js +41 -0
  113. package/dist/features/viz/lib/color-context.js.map +7 -0
  114. package/dist/features/viz/lib/color-math.d.ts +4 -0
  115. package/dist/features/viz/lib/color-math.js +31 -0
  116. package/dist/features/viz/lib/color-math.js.map +7 -0
  117. package/dist/features/viz/lib/color-types.d.ts +53 -0
  118. package/dist/features/viz/lib/curve-definition.d.ts +49 -0
  119. package/dist/features/viz/lib/curve-definition.js +142 -0
  120. package/dist/features/viz/lib/curve-definition.js.map +7 -0
  121. package/dist/features/viz/lib/diverging-color-scale.d.ts +11 -0
  122. package/dist/features/viz/lib/diverging-color-scale.js +51 -0
  123. package/dist/features/viz/lib/diverging-color-scale.js.map +7 -0
  124. package/dist/features/viz/lib/domain-navigation.d.ts +40 -0
  125. package/dist/features/viz/lib/domain-navigation.js +77 -0
  126. package/dist/features/viz/lib/domain-navigation.js.map +7 -0
  127. package/dist/features/viz/lib/editable-chart-elements.d.ts +178 -0
  128. package/dist/features/viz/lib/editable-chart-elements.js +733 -0
  129. package/dist/features/viz/lib/editable-chart-elements.js.map +7 -0
  130. package/dist/features/viz/lib/financial-aggregation.d.ts +127 -0
  131. package/dist/features/viz/lib/financial-aggregation.js +116 -0
  132. package/dist/features/viz/lib/financial-aggregation.js.map +7 -0
  133. package/dist/features/viz/lib/financial-autoscale.d.ts +64 -0
  134. package/dist/features/viz/lib/financial-autoscale.js +61 -0
  135. package/dist/features/viz/lib/financial-autoscale.js.map +7 -0
  136. package/dist/features/viz/lib/financial-comparison.d.ts +62 -0
  137. package/dist/features/viz/lib/financial-comparison.js +98 -0
  138. package/dist/features/viz/lib/financial-comparison.js.map +7 -0
  139. package/dist/features/viz/lib/financial-geometry.d.ts +77 -0
  140. package/dist/features/viz/lib/financial-geometry.js +67 -0
  141. package/dist/features/viz/lib/financial-geometry.js.map +7 -0
  142. package/dist/features/viz/lib/financial-indicators.d.ts +114 -0
  143. package/dist/features/viz/lib/financial-indicators.js +135 -0
  144. package/dist/features/viz/lib/financial-indicators.js.map +7 -0
  145. package/dist/features/viz/lib/financial-oscillators.d.ts +171 -0
  146. package/dist/features/viz/lib/financial-oscillators.js +265 -0
  147. package/dist/features/viz/lib/financial-oscillators.js.map +7 -0
  148. package/dist/features/viz/lib/graph/bipartite.d.ts +14 -0
  149. package/dist/features/viz/lib/graph/bipartite.js +250 -0
  150. package/dist/features/viz/lib/graph/bipartite.js.map +7 -0
  151. package/dist/features/viz/lib/graph/chord.d.ts +44 -0
  152. package/dist/features/viz/lib/graph/chord.js +348 -0
  153. package/dist/features/viz/lib/graph/chord.js.map +7 -0
  154. package/dist/features/viz/lib/graph/dependency.d.ts +26 -0
  155. package/dist/features/viz/lib/graph/dependency.js +140 -0
  156. package/dist/features/viz/lib/graph/dependency.js.map +7 -0
  157. package/dist/features/viz/lib/graph/force.d.ts +28 -0
  158. package/dist/features/viz/lib/graph/force.js +580 -0
  159. package/dist/features/viz/lib/graph/force.js.map +7 -0
  160. package/dist/features/viz/lib/graph/hierarchy.d.ts +21 -0
  161. package/dist/features/viz/lib/graph/hierarchy.js +112 -0
  162. package/dist/features/viz/lib/graph/hierarchy.js.map +7 -0
  163. package/dist/features/viz/lib/graph/icicle.d.ts +16 -0
  164. package/dist/features/viz/lib/graph/icicle.js +153 -0
  165. package/dist/features/viz/lib/graph/icicle.js.map +7 -0
  166. package/dist/features/viz/lib/graph/matrix.d.ts +30 -0
  167. package/dist/features/viz/lib/graph/matrix.js +243 -0
  168. package/dist/features/viz/lib/graph/matrix.js.map +7 -0
  169. package/dist/features/viz/lib/graph/neighborhood.d.ts +11 -0
  170. package/dist/features/viz/lib/graph/neighborhood.js +281 -0
  171. package/dist/features/viz/lib/graph/neighborhood.js.map +7 -0
  172. package/dist/features/viz/lib/graph/routes.d.ts +35 -0
  173. package/dist/features/viz/lib/graph/routes.js +101 -0
  174. package/dist/features/viz/lib/graph/routes.js.map +7 -0
  175. package/dist/features/viz/lib/graph/sankey.d.ts +44 -0
  176. package/dist/features/viz/lib/graph/sankey.js +341 -0
  177. package/dist/features/viz/lib/graph/sankey.js.map +7 -0
  178. package/dist/features/viz/lib/graph/shared.d.ts +59 -0
  179. package/dist/features/viz/lib/graph/shared.js +301 -0
  180. package/dist/features/viz/lib/graph/shared.js.map +7 -0
  181. package/dist/features/viz/lib/graph/tree.d.ts +11 -0
  182. package/dist/features/viz/lib/graph/tree.js +232 -0
  183. package/dist/features/viz/lib/graph/tree.js.map +7 -0
  184. package/dist/features/viz/lib/graph/treemap.d.ts +20 -0
  185. package/dist/features/viz/lib/graph/treemap.js +227 -0
  186. package/dist/features/viz/lib/graph/treemap.js.map +7 -0
  187. package/dist/features/viz/lib/graph/types.d.ts +1097 -0
  188. package/dist/features/viz/lib/hover-card.js +8 -9
  189. package/dist/features/viz/lib/hover-card.js.map +2 -2
  190. package/dist/features/viz/lib/hover-data.d.ts +1 -1
  191. package/dist/features/viz/lib/hover-data.js +5 -2
  192. package/dist/features/viz/lib/hover-data.js.map +2 -2
  193. package/dist/features/viz/lib/interval-band-series.d.ts +49 -0
  194. package/dist/features/viz/lib/interval-band-series.js +136 -0
  195. package/dist/features/viz/lib/interval-band-series.js.map +7 -0
  196. package/dist/features/viz/lib/interval-diamond-series.d.ts +43 -0
  197. package/dist/features/viz/lib/interval-diamond-series.js +122 -0
  198. package/dist/features/viz/lib/interval-diamond-series.js.map +7 -0
  199. package/dist/features/viz/lib/interval-series.d.ts +79 -0
  200. package/dist/features/viz/lib/interval-series.js +158 -0
  201. package/dist/features/viz/lib/interval-series.js.map +7 -0
  202. package/dist/features/viz/lib/layout-pie.js +9 -13
  203. package/dist/features/viz/lib/layout-pie.js.map +2 -2
  204. package/dist/features/viz/lib/line-series.d.ts +1 -1
  205. package/dist/features/viz/lib/line-series.js +47 -28
  206. package/dist/features/viz/lib/line-series.js.map +2 -2
  207. package/dist/features/viz/lib/linear-scale.js +1 -1
  208. package/dist/features/viz/lib/linear-scale.js.map +2 -2
  209. package/dist/features/viz/lib/monotone-curve.d.ts +11 -0
  210. package/dist/features/viz/lib/monotone-curve.js +63 -0
  211. package/dist/features/viz/lib/monotone-curve.js.map +7 -0
  212. package/dist/features/viz/lib/numeric-range-interpolation.d.ts +15 -0
  213. package/dist/features/viz/lib/numeric-range-interpolation.js +36 -0
  214. package/dist/features/viz/lib/numeric-range-interpolation.js.map +7 -0
  215. package/dist/features/viz/lib/ohlc-bar-series.d.ts +55 -0
  216. package/dist/features/viz/lib/ohlc-bar-series.js +168 -0
  217. package/dist/features/viz/lib/ohlc-bar-series.js.map +7 -0
  218. package/dist/features/viz/lib/paired-series.d.ts +44 -0
  219. package/dist/features/viz/lib/paired-series.js +93 -0
  220. package/dist/features/viz/lib/paired-series.js.map +7 -0
  221. package/dist/features/viz/lib/pie-layout.js +2 -1
  222. package/dist/features/viz/lib/pie-layout.js.map +2 -2
  223. package/dist/features/viz/lib/plot-series.js +11 -6
  224. package/dist/features/viz/lib/plot-series.js.map +2 -2
  225. package/dist/features/viz/lib/plot-types.d.ts +4 -3
  226. package/dist/features/viz/lib/point-series.d.ts +1 -1
  227. package/dist/features/viz/lib/point-series.js +36 -9
  228. package/dist/features/viz/lib/point-series.js.map +2 -2
  229. package/dist/features/viz/lib/point-types.d.ts +5 -2
  230. package/dist/features/viz/lib/reference-band.js +4 -1
  231. package/dist/features/viz/lib/reference-band.js.map +2 -2
  232. package/dist/features/viz/lib/scale-context.d.ts +1 -1
  233. package/dist/features/viz/lib/scale-ticks.js +21 -6
  234. package/dist/features/viz/lib/scale-ticks.js.map +2 -2
  235. package/dist/features/viz/lib/sequential-color-scale.d.ts +11 -0
  236. package/dist/features/viz/lib/sequential-color-scale.js +49 -0
  237. package/dist/features/viz/lib/sequential-color-scale.js.map +7 -0
  238. package/dist/features/viz/lib/series-position.d.ts +12 -0
  239. package/dist/features/viz/lib/series-position.js +44 -0
  240. package/dist/features/viz/lib/series-position.js.map +7 -0
  241. package/dist/features/viz/lib/step-curves.d.ts +19 -0
  242. package/dist/features/viz/lib/step-curves.js +53 -0
  243. package/dist/features/viz/lib/step-curves.js.map +7 -0
  244. package/dist/features/viz/lib/threshold-color-scale.d.ts +43 -0
  245. package/dist/features/viz/lib/threshold-color-scale.js +59 -0
  246. package/dist/features/viz/lib/threshold-color-scale.js.map +7 -0
  247. package/dist/features/viz/lib/trading-time-mapping.d.ts +32 -0
  248. package/dist/features/viz/lib/trading-time-mapping.js +89 -0
  249. package/dist/features/viz/lib/trading-time-mapping.js.map +7 -0
  250. package/dist/features/viz/lib/trading-time-scale.d.ts +83 -0
  251. package/dist/features/viz/lib/trading-time-scale.js +96 -0
  252. package/dist/features/viz/lib/trading-time-scale.js.map +7 -0
  253. package/dist/features/viz/lib/trajectory-series.d.ts +71 -0
  254. package/dist/features/viz/lib/trajectory-series.js +111 -0
  255. package/dist/features/viz/lib/trajectory-series.js.map +7 -0
  256. package/dist/features/viz/lib/types.d.ts +20 -4
  257. package/dist/features/viz/lib/use-continuous-scale.js +6 -1
  258. package/dist/features/viz/lib/use-continuous-scale.js.map +2 -2
  259. package/dist/features/viz/lib/utc-scale.js +11 -10
  260. package/dist/features/viz/lib/utc-scale.js.map +2 -2
  261. package/dist/features/viz/lib/volume-series.d.ts +59 -0
  262. package/dist/features/viz/lib/volume-series.js +117 -0
  263. package/dist/features/viz/lib/volume-series.js.map +7 -0
  264. package/dist/features/viz/lib/weighted-point-series.d.ts +71 -0
  265. package/dist/features/viz/lib/weighted-point-series.js +169 -0
  266. package/dist/features/viz/lib/weighted-point-series.js.map +7 -0
  267. package/dist/filters/backdrop-contrast-gpu.d.ts +5 -0
  268. package/dist/filters/backdrop-contrast-gpu.js +33 -0
  269. package/dist/filters/backdrop-contrast-gpu.js.map +7 -0
  270. package/dist/filters/backdrop-contrast.d.ts +21 -0
  271. package/dist/filters/backdrop-contrast.js +61 -0
  272. package/dist/filters/backdrop-contrast.js.map +7 -0
  273. package/dist/filters/displacement.js +1 -1
  274. package/dist/filters/displacement.js.map +2 -2
  275. package/dist/filters/emboss-gpu.d.ts +4 -0
  276. package/dist/filters/emboss-gpu.js +39 -0
  277. package/dist/filters/emboss-gpu.js.map +7 -0
  278. package/dist/filters/emboss.d.ts +32 -0
  279. package/dist/filters/emboss.js +104 -0
  280. package/dist/filters/emboss.js.map +7 -0
  281. package/dist/filters/filter-executor.d.ts +11 -4
  282. package/dist/filters/filter-executor.js +104 -49
  283. package/dist/filters/filter-executor.js.map +2 -2
  284. package/dist/filters/reflected-light.js +1 -1
  285. package/dist/filters/reflected-light.js.map +2 -2
  286. package/dist/filters/reflection-gpu.d.ts +3 -1
  287. package/dist/filters/reflection-gpu.js +5 -2
  288. package/dist/filters/reflection-gpu.js.map +2 -2
  289. package/dist/filters/render-backdrop-contrast-boundary.d.ts +31 -0
  290. package/dist/filters/render-backdrop-contrast-boundary.js +116 -0
  291. package/dist/filters/render-backdrop-contrast-boundary.js.map +7 -0
  292. package/dist/filters/render-emboss-boundary.d.ts +13 -0
  293. package/dist/filters/render-emboss-boundary.js +131 -0
  294. package/dist/filters/render-emboss-boundary.js.map +7 -0
  295. package/dist/filters.d.ts +9 -5
  296. package/dist/filters.js +4 -0
  297. package/dist/filters.js.map +2 -2
  298. package/dist/index.d.ts +9 -5
  299. package/dist/index.js +18 -2
  300. package/dist/index.js.map +2 -2
  301. package/dist/internal.d.ts +4 -0
  302. package/dist/internal.js +6 -0
  303. package/dist/internal.js.map +2 -2
  304. package/dist/layout-kernel.d.ts +12 -0
  305. package/dist/layout-kernel.js +11 -0
  306. package/dist/layout-kernel.js.map +7 -0
  307. package/dist/layout-kernel.mjs +1 -0
  308. package/dist/lib/backend/types.d.ts +13 -1
  309. package/dist/lib/backend/types.js.map +2 -2
  310. package/dist/lib/components/arc-geometry.js +2 -1
  311. package/dist/lib/components/arc-geometry.js.map +2 -2
  312. package/dist/lib/components/g.js +2 -0
  313. package/dist/lib/components/g.js.map +2 -2
  314. package/dist/lib/components/html-box.js +2 -1
  315. package/dist/lib/components/html-box.js.map +2 -2
  316. package/dist/lib/components/img.js +3 -3
  317. package/dist/lib/components/img.js.map +2 -2
  318. package/dist/lib/components/layer.js +98 -16
  319. package/dist/lib/components/layer.js.map +3 -3
  320. package/dist/lib/components/text.d.ts +16 -0
  321. package/dist/lib/components/text.js +131 -24
  322. package/dist/lib/components/text.js.map +2 -2
  323. package/dist/lib/define-primitive.d.ts +4 -2
  324. package/dist/lib/define-primitive.js +3 -1
  325. package/dist/lib/define-primitive.js.map +2 -2
  326. package/dist/lib/element/metadata.d.ts +9 -0
  327. package/dist/lib/element/metadata.js +19 -0
  328. package/dist/lib/element/metadata.js.map +2 -2
  329. package/dist/lib/element/resolve-primitive-inputs.d.ts +2 -0
  330. package/dist/lib/element/resolve-primitive-inputs.js +17 -4
  331. package/dist/lib/element/resolve-primitive-inputs.js.map +2 -2
  332. package/dist/lib/events/event-facade.d.ts +18 -0
  333. package/dist/lib/events/event-facade.js +28 -2
  334. package/dist/lib/events/event-facade.js.map +2 -2
  335. package/dist/lib/events/hit-test.js +2 -1
  336. package/dist/lib/events/hit-test.js.map +2 -2
  337. package/dist/lib/events/propagation.d.ts +2 -1
  338. package/dist/lib/events/propagation.js +22 -16
  339. package/dist/lib/events/propagation.js.map +2 -2
  340. package/dist/lib/events/registrations.d.ts +10 -0
  341. package/dist/lib/events/registrations.js +160 -5
  342. package/dist/lib/events/registrations.js.map +2 -2
  343. package/dist/lib/execute-render.js +25 -1
  344. package/dist/lib/execute-render.js.map +2 -2
  345. package/dist/lib/filter/filter-region.js +3 -10
  346. package/dist/lib/filter/filter-region.js.map +2 -2
  347. package/dist/lib/focus/focus-manager.d.ts +8 -1
  348. package/dist/lib/focus/focus-manager.js +87 -43
  349. package/dist/lib/focus/focus-manager.js.map +2 -2
  350. package/dist/lib/focus/geometry.d.ts +2 -0
  351. package/dist/lib/focus/geometry.js +6 -0
  352. package/dist/lib/focus/geometry.js.map +2 -2
  353. package/dist/lib/geometry/path-bend-guide.js +1 -1
  354. package/dist/lib/geometry/path-bend-guide.js.map +2 -2
  355. package/dist/lib/geometry/path-geometry.js +12 -11
  356. package/dist/lib/geometry/path-geometry.js.map +2 -2
  357. package/dist/lib/geometry/path-transforms.js +17 -21
  358. package/dist/lib/geometry/path-transforms.js.map +2 -2
  359. package/dist/lib/geometry/path-warp-bezier.js +3 -1
  360. package/dist/lib/geometry/path-warp-bezier.js.map +2 -2
  361. package/dist/lib/geometry/path-warp.js +1 -1
  362. package/dist/lib/geometry/path-warp.js.map +2 -2
  363. package/dist/lib/global-state.js +2 -0
  364. package/dist/lib/global-state.js.map +2 -2
  365. package/dist/lib/html/html-events.d.ts +32 -0
  366. package/dist/lib/html/html-events.js +179 -0
  367. package/dist/lib/html/html-events.js.map +7 -0
  368. package/dist/lib/html/html-service.d.ts +8 -2
  369. package/dist/lib/html/html-service.js +198 -65
  370. package/dist/lib/html/html-service.js.map +2 -2
  371. package/dist/lib/html/overlay-config.js +7 -6
  372. package/dist/lib/html/overlay-config.js.map +2 -2
  373. package/dist/lib/html/types.d.ts +29 -2
  374. package/dist/lib/layout/absolute.d.ts +11 -5
  375. package/dist/lib/layout/absolute.js +329 -55
  376. package/dist/lib/layout/absolute.js.map +3 -3
  377. package/dist/lib/layout/allocation-checkpoint-owner.d.ts +11 -0
  378. package/dist/lib/layout/allocation-checkpoint-owner.js +86 -0
  379. package/dist/lib/layout/allocation-checkpoint-owner.js.map +7 -0
  380. package/dist/lib/layout/allocation-checkpoint.d.ts +53 -0
  381. package/dist/lib/layout/allocation-checkpoint.js +463 -0
  382. package/dist/lib/layout/allocation-checkpoint.js.map +7 -0
  383. package/dist/lib/layout/allocation-dependencies.d.ts +30 -0
  384. package/dist/lib/layout/allocation-dependencies.js +90 -0
  385. package/dist/lib/layout/allocation-dependencies.js.map +7 -0
  386. package/dist/lib/layout/allocation-revision.d.ts +13 -0
  387. package/dist/lib/layout/allocation-revision.js +67 -0
  388. package/dist/lib/layout/allocation-revision.js.map +7 -0
  389. package/dist/lib/layout/box-insets.d.ts +17 -0
  390. package/dist/lib/layout/box-insets.js +138 -0
  391. package/dist/lib/layout/box-insets.js.map +7 -0
  392. package/dist/lib/layout/box-sizing.d.ts +16 -0
  393. package/dist/lib/layout/box-sizing.js +77 -0
  394. package/dist/lib/layout/box-sizing.js.map +7 -0
  395. package/dist/lib/layout/box.js +42 -12
  396. package/dist/lib/layout/box.js.map +2 -2
  397. package/dist/lib/layout/canvas-measurement.d.ts +13 -0
  398. package/dist/lib/layout/canvas-measurement.js +57 -0
  399. package/dist/lib/layout/canvas-measurement.js.map +7 -0
  400. package/dist/lib/layout/context.d.ts +35 -6
  401. package/dist/lib/layout/context.js +72 -3
  402. package/dist/lib/layout/context.js.map +2 -2
  403. package/dist/lib/layout/define-layout-component.d.ts +23 -0
  404. package/dist/lib/layout/define-layout-component.js +84 -0
  405. package/dist/lib/layout/define-layout-component.js.map +7 -0
  406. package/dist/lib/layout/flex-allocation-cache.d.ts +42 -0
  407. package/dist/lib/layout/flex-baseline-mode.d.ts +2 -0
  408. package/dist/lib/layout/flex-baseline-mode.js +7 -0
  409. package/dist/lib/layout/flex-baseline-mode.js.map +7 -0
  410. package/dist/lib/layout/flex.d.ts +50 -15
  411. package/dist/lib/layout/flex.js +2124 -195
  412. package/dist/lib/layout/flex.js.map +3 -3
  413. package/dist/lib/layout/flow.js +225 -49
  414. package/dist/lib/layout/flow.js.map +2 -2
  415. package/dist/lib/layout/geometry-publication.d.ts +53 -0
  416. package/dist/lib/layout/geometry-publication.js +244 -0
  417. package/dist/lib/layout/geometry-publication.js.map +7 -0
  418. package/dist/lib/layout/grid-kernel.d.ts +63 -0
  419. package/dist/lib/layout/grid-kernel.js +168 -0
  420. package/dist/lib/layout/grid-kernel.js.map +7 -0
  421. package/dist/lib/layout/grid.d.ts +63 -4
  422. package/dist/lib/layout/grid.js +767 -171
  423. package/dist/lib/layout/grid.js.map +3 -3
  424. package/dist/lib/layout/measure.d.ts +55 -3
  425. package/dist/lib/layout/measure.js +448 -15
  426. package/dist/lib/layout/measure.js.map +2 -2
  427. package/dist/lib/layout/overlay.js +81 -23
  428. package/dist/lib/layout/overlay.js.map +2 -2
  429. package/dist/lib/layout/participation.d.ts +27 -0
  430. package/dist/lib/layout/participation.js +188 -0
  431. package/dist/lib/layout/participation.js.map +7 -0
  432. package/dist/lib/layout/place-child.js +1 -1
  433. package/dist/lib/layout/place-child.js.map +2 -2
  434. package/dist/lib/layout/positioning-diagnostics.d.ts +1 -1
  435. package/dist/lib/layout/positioning-diagnostics.js +13 -2
  436. package/dist/lib/layout/positioning-diagnostics.js.map +2 -2
  437. package/dist/lib/layout/prepared-root.d.ts +121 -0
  438. package/dist/lib/layout/prepared-root.js +360 -0
  439. package/dist/lib/layout/prepared-root.js.map +7 -0
  440. package/dist/lib/layout/standalone-kernel.d.ts +60 -0
  441. package/dist/lib/layout/standalone-kernel.js +722 -0
  442. package/dist/lib/layout/standalone-kernel.js.map +7 -0
  443. package/dist/lib/layout/topology.d.ts +21 -0
  444. package/dist/lib/layout/topology.js +113 -0
  445. package/dist/lib/layout/topology.js.map +7 -0
  446. package/dist/lib/layout/types.d.ts +5 -0
  447. package/dist/lib/layout/wasm/artifact.d.ts +1 -0
  448. package/dist/lib/layout/wasm/artifact.js +5 -0
  449. package/dist/lib/layout/wasm/artifact.js.map +7 -0
  450. package/dist/lib/layout/wasm/bytes.d.ts +1 -0
  451. package/dist/lib/layout/wasm/bytes.js +5 -0
  452. package/dist/lib/layout/wasm/bytes.js.map +7 -0
  453. package/dist/lib/layout/wasm/embedded.d.ts +2 -0
  454. package/dist/lib/layout/wasm/embedded.js +12 -0
  455. package/dist/lib/layout/wasm/embedded.js.map +7 -0
  456. package/dist/lib/layout/wasm/layout.wasm +0 -0
  457. package/dist/lib/layout/wasm/module.d.ts +8 -0
  458. package/dist/lib/layout/wasm/module.js +70 -0
  459. package/dist/lib/layout/wasm/module.js.map +7 -0
  460. package/dist/lib/layout/wasm/region.d.ts +267 -0
  461. package/dist/lib/layout/wasm/region.js +1018 -0
  462. package/dist/lib/layout/wasm/region.js.map +7 -0
  463. package/dist/lib/manipulation/controller.js +4 -7
  464. package/dist/lib/manipulation/controller.js.map +2 -2
  465. package/dist/lib/manipulation/frame.js +1 -1
  466. package/dist/lib/manipulation/frame.js.map +2 -2
  467. package/dist/lib/manipulation/handles.js +32 -33
  468. package/dist/lib/manipulation/handles.js.map +2 -2
  469. package/dist/lib/manipulation/solve.js +12 -10
  470. package/dist/lib/manipulation/solve.js.map +2 -2
  471. package/dist/lib/mount-pibbl.js +1 -0
  472. package/dist/lib/mount-pibbl.js.map +2 -2
  473. package/dist/lib/mount-prepared-pibbl.d.ts +5 -0
  474. package/dist/lib/mount-prepared-pibbl.js +29 -0
  475. package/dist/lib/mount-prepared-pibbl.js.map +7 -0
  476. package/dist/lib/mount-request.d.ts +8 -0
  477. package/dist/lib/mount-request.js +41 -0
  478. package/dist/lib/mount-request.js.map +7 -0
  479. package/dist/lib/pibbl.d.ts +21 -13
  480. package/dist/lib/pibbl.js +18 -16
  481. package/dist/lib/pibbl.js.map +2 -2
  482. package/dist/lib/recording/recording.d.ts +43 -0
  483. package/dist/lib/recording/recording.js +555 -0
  484. package/dist/lib/recording/recording.js.map +7 -0
  485. package/dist/lib/recording/types.d.ts +118 -0
  486. package/dist/lib/recording/wasm-bytes.d.ts +1 -0
  487. package/dist/lib/recording/wasm-bytes.js +5 -0
  488. package/dist/lib/recording/wasm-bytes.js.map +7 -0
  489. package/dist/lib/recording/worker-source.d.ts +1 -0
  490. package/dist/lib/recording/worker-source.js +5 -0
  491. package/dist/lib/recording/worker-source.js.map +7 -0
  492. package/dist/lib/render-layer/controller.d.ts +9 -3
  493. package/dist/lib/render-layer/controller.js +259 -110
  494. package/dist/lib/render-layer/controller.js.map +2 -2
  495. package/dist/lib/render-transaction.d.ts +12 -2
  496. package/dist/lib/render-transaction.js +69 -1
  497. package/dist/lib/render-transaction.js.map +2 -2
  498. package/dist/lib/render.js +32 -8
  499. package/dist/lib/render.js.map +2 -2
  500. package/dist/lib/scheduler/realm-scheduler.d.ts +2 -0
  501. package/dist/lib/scheduler/realm-scheduler.js +55 -26
  502. package/dist/lib/scheduler/realm-scheduler.js.map +2 -2
  503. package/dist/lib/scheduler/renderer-participant.js +1 -0
  504. package/dist/lib/scheduler/renderer-participant.js.map +2 -2
  505. package/dist/lib/series-inspection-frame.d.ts +18 -0
  506. package/dist/lib/series-inspection-frame.js +70 -0
  507. package/dist/lib/series-inspection-frame.js.map +7 -0
  508. package/dist/lib/signals/edge.d.ts +7 -4
  509. package/dist/lib/signals/edge.js +25 -3
  510. package/dist/lib/signals/edge.js.map +2 -2
  511. package/dist/lib/signals/graph.d.ts +16 -2
  512. package/dist/lib/signals/graph.js +54 -12
  513. package/dist/lib/signals/graph.js.map +2 -2
  514. package/dist/lib/signals/input-provision.d.ts +15 -0
  515. package/dist/lib/signals/input-provision.js +53 -3
  516. package/dist/lib/signals/input-provision.js.map +2 -2
  517. package/dist/lib/signals/render-consumer.d.ts +3 -0
  518. package/dist/lib/signals/render-consumer.js +22 -14
  519. package/dist/lib/signals/render-consumer.js.map +2 -2
  520. package/dist/lib/style/positioning.d.ts +50 -2
  521. package/dist/lib/style/positioning.js +28 -4
  522. package/dist/lib/style/positioning.js.map +2 -2
  523. package/dist/lib/style/resolve-built-in.d.ts +4 -3
  524. package/dist/lib/style/resolve-built-in.js +17 -3
  525. package/dist/lib/style/resolve-built-in.js.map +2 -2
  526. package/dist/lib/style/resolve-dispatch.d.ts +3 -0
  527. package/dist/lib/style/resolve-dispatch.js +77 -4
  528. package/dist/lib/style/resolve-dispatch.js.map +2 -2
  529. package/dist/lib/style/resolve-length.d.ts +2 -0
  530. package/dist/lib/style/resolve-length.js +13 -9
  531. package/dist/lib/style/resolve-length.js.map +2 -2
  532. package/dist/lib/style/sizing-length.d.ts +51 -0
  533. package/dist/lib/style/sizing-length.js +77 -0
  534. package/dist/lib/style/sizing-length.js.map +7 -0
  535. package/dist/lib/style/types.d.ts +63 -25
  536. package/dist/lib/surface/root-surface.js +10 -6
  537. package/dist/lib/surface/root-surface.js.map +2 -2
  538. package/dist/lib/textures/texture.js +10 -8
  539. package/dist/lib/textures/texture.js.map +2 -2
  540. package/dist/lib/transitions/capture.js +4 -1
  541. package/dist/lib/transitions/capture.js.map +2 -2
  542. package/dist/lib/transitions/embers-physics.js +17 -10
  543. package/dist/lib/transitions/embers-physics.js.map +2 -2
  544. package/dist/lib/types.d.ts +110 -1
  545. package/dist/sync.d.ts +16 -0
  546. package/dist/sync.js +13 -0
  547. package/dist/sync.js.map +7 -0
  548. package/dist/sync.mjs +1 -0
  549. package/package.json +26 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/textures/texture.ts"],
4
- "sourcesContent": ["import { GLOBAL_STATE } from \"../global-state.js\";\nimport {\n requireHookContext,\n useHookSlot,\n withHooksForbidden,\n} from \"../hooks/hook-slot.js\";\nimport { registerAdvanceParticipant } from \"../scheduler/realm-scheduler.js\";\nimport { signal } from \"../signals/graph.js\";\nimport type { PibblInstance, RenderingContext2D } from \"../types.js\";\nimport {\n registerTexturePaint,\n type BorrowedTextureRaster,\n type TexturePaint,\n type TexturePlacement,\n} from \"./texture-protocol.js\";\n\nexport type { TexturePaint, TexturePlacement } from \"./texture-protocol.js\";\n\ndeclare const recipeBrand: unique symbol;\n/**\n * A mount-owned texture handle that provides paint and accepts recipe messages.\n *\n * @see {@link TexturePaint}\n * @see {@link TexturePlacement}\n * @see {@link useTexture}\n */\nexport interface Texture<Message = never> extends TexturePaint {\n /**\n * Delivers a typed message to the mounted recipe instance. See {@link Texture}.\n * @param message - Message delivered to the texture definition's receive callback.\n */\n send(message: Message): void;\n /**\n * Returns a paint view with the requested placement while retaining the same texture ownership.\n * See {@link TexturePaint}.\n * @param placement - Destination bounds and texture placement policy. See\n * {@link TexturePlacement} .\n * @returns A paint descriptor referencing this mounted texture. See {@link TexturePaint}.\n */\n paint(placement: TexturePlacement): TexturePaint;\n}\n/**\n * Resolution and runtime configuration for a mounted texture recipe.\n *\n * @see {@link useTexture}\n */\nexport interface TextureOptions {\n /** Dimensions of the simulation or raster grid. See {@link TextureOptions}. */\n readonly resolution?: {\n /**\n * Horizontal extent in the units of the containing geometry or surface. See\n * {@link TextureOptions}.\n */\n readonly width: number;\n /**\n * Vertical extent in the units of the containing geometry or surface. See\n * {@link TextureOptions}.\n */\n readonly height: number;\n };\n /** Ordered colors used to present texture intensity. See {@link TextureOptions}. */\n readonly palette?: readonly string[];\n}\n/**\n * Surface and invalidation facilities supplied to texture lifecycle callbacks.\n *\n * @see {@link TextureDefinition}\n */\nexport interface TextureContext {\n /** Canvas surface associated with this resource or mount. See {@link TextureContext}. */\n readonly canvas: OffscreenCanvas;\n /** Ordered colors used to present texture intensity. See {@link TextureContext}. */\n readonly palette: readonly string[] | undefined;\n /** Marks the source pixels dirty and requests a Pibbl update. */\n invalidate(): void;\n /** Requests another Pibbl frame; implementations stop by not requesting again. */\n requestFrame(): void;\n}\n/**\n * Shared logical time and elapsed milliseconds supplied while advancing a texture.\n *\n * @see {@link TextureDefinition}\n */\nexport interface TextureFrame {\n /** Elapsed time since the preceding texture frame, in milliseconds. See {@link TextureFrame}. */\n readonly delta: number;\n /** Current shared logical time, in milliseconds. See {@link TextureFrame}. */\n readonly time: number;\n}\n/**\n * Lifecycle callbacks for creating, updating, painting, and disposing texture resources.\n *\n * @see {@link TexturePlacement}\n * @see {@link TextureContext}\n * @see {@link TextureFrame}\n * @see {@link defineTexture}\n */\nexport interface TextureDefinition<Config, State, Message = never> {\n /**\n * Texture placement used when no paint-specific override is supplied. See\n * {@link TexturePlacement}.\n */\n readonly defaultPlacement?: TexturePlacement;\n /**\n * Allocates state for a mounted texture recipe. See {@link TextureDefinition}.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n * @param config - Initial recipe configuration.\n * @returns State retained for this mounted texture lifetime.\n */\n create(context: TextureContext, config: Readonly<Config>): State;\n /**\n * Updates existing state when the recipe configuration changes. See {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param config - Latest recipe configuration.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n update?(state: State, config: Readonly<Config>, context: TextureContext): void;\n /**\n * Handles a typed application message for this recipe instance. See {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param message - Message sent through the mounted texture handle.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n receive?(state: State, message: Message, context: TextureContext): void;\n /**\n * Advances simulation using the shared Pibbl frame timing. See {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param frame - Shared animation time and delta. See {@link TextureFrame}.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n advance?(state: State, frame: TextureFrame, context: TextureContext): void;\n /**\n * Draws current texture pixels into the owned offscreen surface. See {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n rasterize(state: State, context: TextureContext): void;\n /**\n * Releases state and resources when the mounted texture is disposed. See\n * {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n dispose?(state: State, context: TextureContext): void;\n}\n/**\n * A reusable texture definition together with the options used to instantiate it.\n *\n * @see {@link defineTexture}\n * @see {@link useTexture}\n */\nexport interface TextureRecipe<Message = never> {\n readonly [recipeBrand]: (message: Message) => Message;\n}\ntype Definition = TextureDefinition<any, any, any>;\ninterface Recipe {\n definition: Definition;\n config: any;\n}\nconst recipes = new WeakMap<object, Recipe>();\n\n/**\n * Defines a pure recipe factory; resource allocation starts at useTexture.\n *\n * @param definition - State creation, update, simulation, rasterization, and disposal callbacks.\n * See {@link TextureDefinition} .\n * @returns A configuration-to-recipe factory; resources are allocated when a recipe is mounted.\n * See {@link TextureRecipe} .\n *\n * @see {@link TextureDefinition}\n * @see {@link TextureRecipe}\n */\nexport function defineTexture<Config, State, Message = never>(\n definition: TextureDefinition<Config, State, Message>,\n): (config: Config) => TextureRecipe<Message> {\n const stable = Object.freeze({ ...definition });\n return (config) => {\n const recipe = Object.freeze({}) as TextureRecipe<Message>;\n recipes.set(recipe, {\n definition: stable,\n config: structuredClone(config),\n });\n return recipe;\n };\n}\nfunction placement(value: TexturePlacement = {}): Readonly<TexturePlacement> {\n if (\n value.mode !== undefined &&\n value.mode !== \"repeat\" &&\n value.mode !== \"stretch\"\n )\n throw new TypeError(\"Unknown texture placement mode.\");\n for (const key of [\n \"tileWidth\",\n \"tileHeight\",\n \"offsetX\",\n \"offsetY\",\n \"rotation\",\n ] as const) {\n const n = value[key];\n if (\n n !== undefined &&\n (!Number.isFinite(n) ||\n ((key === \"tileWidth\" || key === \"tileHeight\") && n <= 0))\n )\n throw new RangeError(`Invalid texture placement ${key}.`);\n }\n return Object.freeze({ ...value });\n}\nfunction dimensions(options: TextureOptions): [number, number] {\n const width = options.resolution?.width ?? 256,\n height = options.resolution?.height ?? 160;\n if (\n ![width, height].every((n) => Number.isInteger(n) && n >= 8 && n <= 1024) ||\n width * height > 262144\n )\n throw new RangeError(\n \"Texture resolution must be 8..1024 cells per axis, at most 262144 cells.\",\n );\n return [width, height];\n}\nclass Resource {\n readonly revision = signal(0);\n readonly canvas: OffscreenCanvas;\n private committed: OffscreenCanvas | undefined;\n private spare: OffscreenCanvas | undefined;\n private provisional: { canvas: OffscreenCanvas; transaction: NonNullable<typeof GLOBAL_STATE.renderTransaction> } | undefined;\n readonly context: TextureContext;\n readonly handle: Texture<any>;\n state: any;\n definition: Definition;\n disposed = false;\n private hasState = false;\n dirty = true;\n private sequence = 0;\n private publicationCanvasesCreated = 0;\n private messages: unknown[] = [];\n private unregister?: () => void;\n private continuing = false;\n private lastTime?: number;\n private initializing = true;\n private retryScheduled = false;\n private palette?: readonly string[];\n private optionsKey: string;\n constructor(\n private owner: PibblInstance | undefined,\n recipe: Recipe,\n options: TextureOptions,\n ) {\n const [width, height] = dimensions(options);\n this.optionsKey = JSON.stringify(options);\n this.palette = options.palette && Object.freeze([...options.palette]);\n this.canvas = new OffscreenCanvas(width, height);\n this.definition = recipe.definition;\n const self = this;\n this.context = Object.freeze({\n canvas: this.canvas,\n get palette() {\n return self.palette;\n },\n invalidate() {\n if (!self.disposed) {\n self.dirty = true;\n if (!self.initializing) self.schedule();\n }\n },\n requestFrame() {\n if (!self.disposed) {\n self.continuing = true;\n self.schedule();\n }\n },\n });\n const registerPaint = (value: TexturePaint, placement: Readonly<TexturePlacement>) =>\n registerTexturePaint(value, {\n resolvePaint: (ctx, bounds) => this.resolvePaint(ctx, bounds, placement),\n validate: () => this.assertOwner(),\n borrow: callback => callback(this.borrow(placement)),\n });\n this.handle = Object.freeze({\n send: (message: unknown) => {\n if (this.disposed) return;\n if (GLOBAL_STATE.currentPibblInstance)\n throw new Error(\"Texture.send cannot run during Pibbl evaluation.\");\n if (!this.definition.receive)\n throw new Error(\"This texture does not accept messages.\");\n if (this.messages.length >= 8192)\n throw new RangeError(\"Texture message queue is full.\");\n this.messages.push(structuredClone(message));\n this.schedule();\n },\n paint: (value: TexturePlacement) => {\n const paint = Object.freeze({}) as TexturePaint;\n registerPaint(paint, placement(value));\n return paint;\n },\n }) as Texture<any>;\n registerPaint(this.handle, placement(this.definition.defaultPlacement));\n try {\n this.state = this.call(() =>\n this.definition.create(this.context, recipe.config),\n );\n this.hasState = true;\n this.publishInitial();\n this.initializing = false;\n } catch (error) {\n try {\n this.dispose();\n } catch {\n // The initialization failure remains the actionable error.\n }\n throw error;\n }\n }\n private call<T>(fn: () => T): T {\n return withHooksForbidden(\n \"Texture implementations cannot call Pibbl hooks.\",\n fn,\n );\n }\n update(recipe: Recipe, options: TextureOptions) {\n if (this.disposed) return;\n if (recipe.definition !== this.definition)\n throw new Error(\n \"Changing a texture definition requires a new keyed owner.\",\n );\n const [width, height] = dimensions(options);\n const nextKey = JSON.stringify(options);\n if (nextKey !== this.optionsKey) {\n this.palette = options.palette && Object.freeze([...options.palette]);\n this.optionsKey = nextKey;\n if (width !== this.canvas.width || height !== this.canvas.height) {\n try {\n this.disposeState();\n this.canvas.width = width;\n this.canvas.height = height;\n this.messages.length = 0;\n this.lastTime = undefined;\n this.state = this.call(() =>\n this.definition.create(this.context, recipe.config),\n );\n this.hasState = true;\n } catch (error) {\n try { this.dispose(); } catch { /* Preserve the recreate failure. */ }\n throw error;\n }\n }\n this.context.invalidate();\n }\n this.call(() =>\n this.definition.update?.(this.state, recipe.config, this.context),\n );\n }\n private unschedule() {\n this.unregister?.();\n this.unregister = undefined;\n }\n private schedule() {\n if (this.unregister || this.disposed) return;\n const participant = (frame: { logicalTime: number }, batch: any) => {\n const retryAtEntry = this.retryScheduled;\n this.unschedule();\n const wasContinuing = this.continuing;\n this.continuing = false;\n try {\n const messages = this.messages;\n this.messages = [];\n for (const message of messages)\n this.call(() =>\n this.definition.receive?.(this.state, message, this.context),\n );\n if (wasContinuing)\n this.call(() =>\n this.definition.advance?.(\n this.state,\n {\n delta:\n this.lastTime === undefined\n ? 0\n : Math.max(0, frame.logicalTime - this.lastTime),\n time: frame.logicalTime,\n },\n this.context,\n ),\n );\n this.lastTime = this.continuing ? frame.logicalTime : undefined;\n if (this.dirty) {\n const candidate = this.rasterizeCandidate();\n let previous: OffscreenCanvas | undefined;\n batch.stage(this.revision, ++this.sequence, participant);\n batch.registerLifecycle(participant, {\n apply: () => {\n if (this.disposed) {\n candidate.width = candidate.height = 0;\n } else {\n previous = this.committed;\n this.committed = candidate;\n this.spare = previous;\n this.retryScheduled = false;\n }\n },\n rollback: () => {\n if (!this.disposed) {\n this.committed = previous;\n this.spare = candidate;\n }\n },\n abort: () => {\n this.spare = candidate;\n if (!this.disposed) {\n this.dirty = true;\n this.schedule();\n }\n },\n });\n }\n if (!this.continuing && this.messages.length === 0) {\n this.unschedule();\n }\n } catch (error) {\n this.unschedule();\n this.continuing = false;\n if (this.retryScheduled && !retryAtEntry) this.schedule();\n throw error;\n }\n };\n this.unregister = registerAdvanceParticipant(participant);\n }\n private rasterizeCandidate(): OffscreenCanvas {\n const ctx = this.canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Textures require OffscreenCanvas 2D.\");\n ctx.save();\n try {\n ctx.resetTransform();\n ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n this.call(() => this.definition.rasterize(this.state, this.context));\n this.dirty = false;\n } finally {\n ctx.restore();\n }\n const spare = this.spare;\n this.spare = undefined;\n const reusable = spare?.width === this.canvas.width && spare.height === this.canvas.height ?\n spare : undefined;\n if (spare && spare !== reusable) spare.width = spare.height = 0;\n let candidate: OffscreenCanvas | undefined;\n try {\n candidate = reusable ?? this.createPublicationCanvas();\n const candidateContext = candidate.getContext(\"2d\");\n if (!candidateContext) throw new Error(\"Textures require OffscreenCanvas 2D.\");\n // Publication canvases are reused; transparent source pixels must erase old paint.\n candidateContext.clearRect(0, 0, candidate.width, candidate.height);\n candidateContext.drawImage(this.canvas, 0, 0);\n return candidate;\n } catch (error) {\n if (candidate) candidate.width = candidate.height = 0;\n this.dirty = true;\n if (!this.retryScheduled) {\n this.retryScheduled = true;\n this.schedule();\n }\n throw error;\n }\n }\n private createPublicationCanvas(): OffscreenCanvas {\n this.publicationCanvasesCreated++;\n return new OffscreenCanvas(this.canvas.width, this.canvas.height);\n }\n /** @internal Structural ownership evidence for texture publication tests. */\n publicationSnapshot(): Readonly<{ publicationCanvasesCreated: number; hasOwner: boolean }> {\n return Object.freeze({ publicationCanvasesCreated: this.publicationCanvasesCreated, hasOwner: this.owner !== undefined });\n }\n private publishInitial(): void {\n const candidate = this.rasterizeCandidate();\n const transaction = GLOBAL_STATE.renderTransaction;\n if (!transaction) {\n this.committed = candidate;\n return;\n }\n this.provisional = { canvas: candidate, transaction };\n transaction.onFinish(success => {\n if (this.provisional?.transaction !== transaction) return;\n const provisional = this.provisional;\n this.provisional = undefined;\n if (success && !this.disposed) this.committed = provisional.canvas;\n else provisional.canvas.width = provisional.canvas.height = 0;\n });\n }\n private assertOwner(): void {\n if (this.disposed) throw new Error(\"Cannot paint with a disposed texture.\");\n let root = GLOBAL_STATE.currentPibblInstance;\n while (root?.parent) root = GLOBAL_STATE.pibblInstances.get(root.parent);\n let owner = this.owner;\n while (owner?.parent) owner = GLOBAL_STATE.pibblInstances.get(owner.parent);\n if (root !== owner) throw new Error(\"Textures may only be shared within their owning Pibbl tree.\");\n }\n private borrow(placement: Readonly<TexturePlacement>): BorrowedTextureRaster {\n this.assertOwner();\n const revision = this.revision.get();\n const provisional = this.provisional;\n const source =\n provisional !== undefined && provisional.transaction === GLOBAL_STATE.renderTransaction ?\n provisional.canvas : this.committed;\n if (!source) throw new Error(\"Texture pixels are not committed for this render transaction.\");\n return Object.freeze({ source, width: source.width, height: source.height, revision, resource: this, placement });\n }\n private resolvePaint(ctx: RenderingContext2D, bounds: { x: number; y: number; width: number; height: number }, p: Readonly<TexturePlacement>): string | CanvasGradient | CanvasPattern {\n const borrowed = this.borrow(p);\n const pattern = ctx.createPattern(borrowed.source, \"repeat\");\n if (!pattern) throw new Error(\"Could not create texture paint.\");\n const stretch = p.mode === \"stretch\";\n const width = stretch ? bounds.width : (p.tileWidth ?? borrowed.width);\n const height = stretch ? bounds.height : (p.tileHeight ?? borrowed.height);\n pattern.setTransform(new DOMMatrix().translate(bounds.x + (p.offsetX ?? 0), bounds.y + (p.offsetY ?? 0)).rotate(p.rotation ?? 0).scale(Math.max(0.000001, width) / borrowed.width, Math.max(0.000001, height) / borrowed.height));\n return pattern;\n }\n dispose() {\n if (this.disposed) return;\n this.disposed = true;\n this.unschedule();\n this.messages.length = 0;\n try {\n this.disposeState();\n } finally {\n this.canvas.width = this.canvas.height = 0;\n this.committed && (this.committed.width = this.committed.height = 0);\n this.spare && (this.spare.width = this.spare.height = 0);\n this.provisional && (this.provisional.canvas.width = this.provisional.canvas.height = 0);\n this.state = undefined;\n this.hasState = false;\n this.committed = undefined;\n this.spare = undefined;\n this.provisional = undefined;\n this.owner = undefined;\n }\n }\n private disposeState() {\n if (!this.hasState) return;\n this.hasState = false;\n const state = this.state;\n this.state = undefined;\n this.call(() => this.definition.dispose?.(state, this.context));\n }\n}\n\n/**\n * Owns one persistent texture resource for the current mounted hook slot.\n *\n * @param input - Texture recipe to mount or update. See {@link TextureRecipe}.\n * @param options - Resolution and lifecycle options for the mounted texture. See\n * {@link TextureOptions} .\n * @returns A mount-owned texture handle for sending messages and creating paint placements. See\n * {@link Texture} .\n *\n * @see {@link TextureRecipe}\n * @see {@link TextureOptions}\n * @see {@link Texture}\n */\nexport function useTexture<Message>(\n input: TextureRecipe<Message>,\n options: TextureOptions = {},\n): Texture<Message> {\n const recipe = recipes.get(input);\n if (!recipe)\n throw new TypeError(\"useTexture requires a defineTexture recipe.\");\n const { pibblInstance } = requireHookContext();\n let created = false;\n const resource = useHookSlot(\"texture\", (teardowns) => {\n created = true;\n const value = new Resource(pibblInstance, recipe, options);\n teardowns.add(() => value.dispose());\n return value;\n }).value;\n if (!created)\n GLOBAL_STATE.renderTransaction!.onFinish((success) => {\n if (success) resource.update(recipe, options);\n });\n return resource.handle;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { GLOBAL_STATE } from \"../global-state.js\";\nimport {\n requireHookContext,\n useHookSlot,\n withHooksForbidden,\n} from \"../hooks/hook-slot.js\";\nimport { registerAdvanceParticipant } from \"../scheduler/realm-scheduler.js\";\nimport { signal } from \"../signals/graph.js\";\nimport type { PibblInstance, RenderingContext2D } from \"../types.js\";\nimport {\n registerTexturePaint,\n type BorrowedTextureRaster,\n type TexturePaint,\n type TexturePlacement,\n} from \"./texture-protocol.js\";\nconst placementKeys = [\n \"tileWidth\",\n \"tileHeight\",\n \"offsetX\",\n \"offsetY\",\n \"rotation\",\n ] as const;\n\nexport type { TexturePaint, TexturePlacement } from \"./texture-protocol.js\";\n\ndeclare const recipeBrand: unique symbol;\n/**\n * A mount-owned texture handle that provides paint and accepts recipe messages.\n *\n * @see {@link TexturePaint}\n * @see {@link TexturePlacement}\n * @see {@link useTexture}\n */\nexport interface Texture<Message = never> extends TexturePaint {\n /**\n * Delivers a typed message to the mounted recipe instance. See {@link Texture}.\n * @param message - Message delivered to the texture definition's receive callback.\n */\n send(message: Message): void;\n /**\n * Returns a paint view with the requested placement while retaining the same texture ownership.\n * See {@link TexturePaint}.\n * @param placement - Destination bounds and texture placement policy. See\n * {@link TexturePlacement} .\n * @returns A paint descriptor referencing this mounted texture. See {@link TexturePaint}.\n */\n paint(placement: TexturePlacement): TexturePaint;\n}\n/**\n * Resolution and runtime configuration for a mounted texture recipe.\n *\n * @see {@link useTexture}\n */\nexport interface TextureOptions {\n /** Dimensions of the simulation or raster grid. See {@link TextureOptions}. */\n readonly resolution?: {\n /**\n * Horizontal extent in the units of the containing geometry or surface. See\n * {@link TextureOptions}.\n */\n readonly width: number;\n /**\n * Vertical extent in the units of the containing geometry or surface. See\n * {@link TextureOptions}.\n */\n readonly height: number;\n };\n /** Ordered colors used to present texture intensity. See {@link TextureOptions}. */\n readonly palette?: readonly string[];\n}\n/**\n * Surface and invalidation facilities supplied to texture lifecycle callbacks.\n *\n * @see {@link TextureDefinition}\n */\nexport interface TextureContext {\n /** Canvas surface associated with this resource or mount. See {@link TextureContext}. */\n readonly canvas: OffscreenCanvas;\n /** Ordered colors used to present texture intensity. See {@link TextureContext}. */\n readonly palette: readonly string[] | undefined;\n /** Marks the source pixels dirty and requests a Pibbl update. */\n invalidate(): void;\n /** Requests another Pibbl frame; implementations stop by not requesting again. */\n requestFrame(): void;\n}\n/**\n * Shared logical time and elapsed milliseconds supplied while advancing a texture.\n *\n * @see {@link TextureDefinition}\n */\nexport interface TextureFrame {\n /** Elapsed time since the preceding texture frame, in milliseconds. See {@link TextureFrame}. */\n readonly delta: number;\n /** Current shared logical time, in milliseconds. See {@link TextureFrame}. */\n readonly time: number;\n}\n/**\n * Lifecycle callbacks for creating, updating, painting, and disposing texture resources.\n *\n * @see {@link TexturePlacement}\n * @see {@link TextureContext}\n * @see {@link TextureFrame}\n * @see {@link defineTexture}\n */\nexport interface TextureDefinition<Config, State, Message = never> {\n /**\n * Texture placement used when no paint-specific override is supplied. See\n * {@link TexturePlacement}.\n */\n readonly defaultPlacement?: TexturePlacement;\n /**\n * Allocates state for a mounted texture recipe. See {@link TextureDefinition}.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n * @param config - Initial recipe configuration.\n * @returns State retained for this mounted texture lifetime.\n */\n create(context: TextureContext, config: Readonly<Config>): State;\n /**\n * Updates existing state when the recipe configuration changes. See {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param config - Latest recipe configuration.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n update?(state: State, config: Readonly<Config>, context: TextureContext): void;\n /**\n * Handles a typed application message for this recipe instance. See {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param message - Message sent through the mounted texture handle.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n receive?(state: State, message: Message, context: TextureContext): void;\n /**\n * Advances simulation using the shared Pibbl frame timing. See {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param frame - Shared animation time and delta. See {@link TextureFrame}.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n advance?(state: State, frame: TextureFrame, context: TextureContext): void;\n /**\n * Draws current texture pixels into the owned offscreen surface. See {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n rasterize(state: State, context: TextureContext): void;\n /**\n * Releases state and resources when the mounted texture is disposed. See\n * {@link TextureDefinition}.\n * @param state - State returned by create.\n * @param context - Texture-owned drawing surface and scheduling services. See\n * {@link TextureContext} .\n */\n dispose?(state: State, context: TextureContext): void;\n}\n/**\n * A reusable texture definition together with the options used to instantiate it.\n *\n * @see {@link defineTexture}\n * @see {@link useTexture}\n */\nexport interface TextureRecipe<Message = never> {\n readonly [recipeBrand]: (message: Message) => Message;\n}\ntype Definition = TextureDefinition<any, any, any>;\ninterface Recipe {\n definition: Definition;\n config: any;\n}\nconst recipes = new WeakMap<object, Recipe>();\n\n/**\n * Defines a pure recipe factory; resource allocation starts at useTexture.\n *\n * @param definition - State creation, update, simulation, rasterization, and disposal callbacks.\n * See {@link TextureDefinition} .\n * @returns A configuration-to-recipe factory; resources are allocated when a recipe is mounted.\n * See {@link TextureRecipe} .\n *\n * @see {@link TextureDefinition}\n * @see {@link TextureRecipe}\n */\nexport function defineTexture<Config, State, Message = never>(\n definition: TextureDefinition<Config, State, Message>,\n): (config: Config) => TextureRecipe<Message> {\n const stable = Object.freeze({ ...definition });\n return (config) => {\n const recipe = Object.freeze({}) as TextureRecipe<Message>;\n recipes.set(recipe, {\n definition: stable,\n config: structuredClone(config),\n });\n return recipe;\n };\n}\nfunction placement(value: TexturePlacement = {}): Readonly<TexturePlacement> {\n if (\n value.mode !== undefined &&\n value.mode !== \"repeat\" &&\n value.mode !== \"stretch\"\n )\n throw new TypeError(\"Unknown texture placement mode.\");\n for (let keyIndex = 0; keyIndex < placementKeys.length; keyIndex++) {\n const key = placementKeys[keyIndex];\n const n = value[key];\n if (\n n !== undefined &&\n (!Number.isFinite(n) ||\n ((key === \"tileWidth\" || key === \"tileHeight\") && n <= 0))\n )\n throw new RangeError(`Invalid texture placement ${key}.`);\n }\n return Object.freeze({ ...value });\n}\nfunction dimensions(options: TextureOptions): [number, number] {\n const width = options.resolution?.width ?? 256,\n height = options.resolution?.height ?? 160;\n if (\n !(\n Number.isInteger(width) &&\n width >= 8 &&\n width <= 1024 &&\n Number.isInteger(height) &&\n height >= 8 &&\n height <= 1024\n ) ||\n width * height > 262144\n )\n throw new RangeError(\n \"Texture resolution must be 8..1024 cells per axis, at most 262144 cells.\",\n );\n return [width, height];\n}\nclass Resource {\n readonly revision = signal(0);\n readonly canvas: OffscreenCanvas;\n private committed: OffscreenCanvas | undefined;\n private spare: OffscreenCanvas | undefined;\n private provisional: { canvas: OffscreenCanvas; transaction: NonNullable<typeof GLOBAL_STATE.renderTransaction> } | undefined;\n readonly context: TextureContext;\n readonly handle: Texture<any>;\n state: any;\n definition: Definition;\n disposed = false;\n private hasState = false;\n dirty = true;\n private sequence = 0;\n private publicationCanvasesCreated = 0;\n private messages: unknown[] = [];\n private unregister?: () => void;\n private continuing = false;\n private lastTime?: number;\n private initializing = true;\n private retryScheduled = false;\n private palette?: readonly string[];\n private optionsKey: string;\n constructor(\n private owner: PibblInstance | undefined,\n recipe: Recipe,\n options: TextureOptions,\n ) {\n const [width, height] = dimensions(options);\n this.optionsKey = JSON.stringify(options);\n this.palette = options.palette && Object.freeze([...options.palette]);\n this.canvas = new OffscreenCanvas(width, height);\n this.definition = recipe.definition;\n const self = this;\n this.context = Object.freeze({\n canvas: this.canvas,\n get palette() {\n return self.palette;\n },\n invalidate() {\n if (!self.disposed) {\n self.dirty = true;\n if (!self.initializing) self.schedule();\n }\n },\n requestFrame() {\n if (!self.disposed) {\n self.continuing = true;\n self.schedule();\n }\n },\n });\n const registerPaint = (value: TexturePaint, placement: Readonly<TexturePlacement>) =>\n registerTexturePaint(value, {\n resolvePaint: (ctx, bounds) => this.resolvePaint(ctx, bounds, placement),\n validate: () => this.assertOwner(),\n borrow: callback => callback(this.borrow(placement)),\n });\n this.handle = Object.freeze({\n send: (message: unknown) => {\n if (this.disposed) return;\n if (GLOBAL_STATE.currentPibblInstance)\n throw new Error(\"Texture.send cannot run during Pibbl evaluation.\");\n if (!this.definition.receive)\n throw new Error(\"This texture does not accept messages.\");\n if (this.messages.length >= 8192)\n throw new RangeError(\"Texture message queue is full.\");\n this.messages.push(structuredClone(message));\n this.schedule();\n },\n paint: (value: TexturePlacement) => {\n const paint = Object.freeze({}) as TexturePaint;\n registerPaint(paint, placement(value));\n return paint;\n },\n }) as Texture<any>;\n registerPaint(this.handle, placement(this.definition.defaultPlacement));\n try {\n this.state = this.call(() =>\n this.definition.create(this.context, recipe.config),\n );\n this.hasState = true;\n this.publishInitial();\n this.initializing = false;\n } catch (error) {\n try {\n this.dispose();\n } catch {\n // The initialization failure remains the actionable error.\n }\n throw error;\n }\n }\n private call<T>(fn: () => T): T {\n return withHooksForbidden(\n \"Texture implementations cannot call Pibbl hooks.\",\n fn,\n );\n }\n update(recipe: Recipe, options: TextureOptions) {\n if (this.disposed) return;\n if (recipe.definition !== this.definition)\n throw new Error(\n \"Changing a texture definition requires a new keyed owner.\",\n );\n const [width, height] = dimensions(options);\n const nextKey = JSON.stringify(options);\n if (nextKey !== this.optionsKey) {\n this.palette = options.palette && Object.freeze([...options.palette]);\n this.optionsKey = nextKey;\n if (width !== this.canvas.width || height !== this.canvas.height) {\n try {\n this.disposeState();\n this.canvas.width = width;\n this.canvas.height = height;\n this.messages.length = 0;\n this.lastTime = undefined;\n this.state = this.call(() =>\n this.definition.create(this.context, recipe.config),\n );\n this.hasState = true;\n } catch (error) {\n try { this.dispose(); } catch { /* Preserve the recreate failure. */ }\n throw error;\n }\n }\n this.context.invalidate();\n }\n this.call(() =>\n this.definition.update?.(this.state, recipe.config, this.context),\n );\n }\n private unschedule() {\n this.unregister?.();\n this.unregister = undefined;\n }\n private schedule() {\n if (this.unregister || this.disposed) return;\n const participant = (frame: { logicalTime: number }, batch: any) => {\n const retryAtEntry = this.retryScheduled;\n this.unschedule();\n const wasContinuing = this.continuing;\n this.continuing = false;\n try {\n const messages = this.messages;\n this.messages = [];\n for (const message of messages)\n this.call(() =>\n this.definition.receive?.(this.state, message, this.context),\n );\n if (wasContinuing)\n this.call(() =>\n this.definition.advance?.(\n this.state,\n {\n delta:\n this.lastTime === undefined\n ? 0\n : Math.max(0, frame.logicalTime - this.lastTime),\n time: frame.logicalTime,\n },\n this.context,\n ),\n );\n this.lastTime = this.continuing ? frame.logicalTime : undefined;\n if (this.dirty) {\n const candidate = this.rasterizeCandidate();\n let previous: OffscreenCanvas | undefined;\n batch.stage(this.revision, ++this.sequence, participant);\n batch.registerLifecycle(participant, {\n apply: () => {\n if (this.disposed) {\n candidate.width = candidate.height = 0;\n } else {\n previous = this.committed;\n this.committed = candidate;\n this.spare = previous;\n this.retryScheduled = false;\n }\n },\n rollback: () => {\n if (!this.disposed) {\n this.committed = previous;\n this.spare = candidate;\n }\n },\n abort: () => {\n this.spare = candidate;\n if (!this.disposed) {\n this.dirty = true;\n this.schedule();\n }\n },\n });\n }\n if (!this.continuing && this.messages.length === 0) {\n this.unschedule();\n }\n } catch (error) {\n this.unschedule();\n this.continuing = false;\n if (this.retryScheduled && !retryAtEntry) this.schedule();\n throw error;\n }\n };\n this.unregister = registerAdvanceParticipant(participant);\n }\n private rasterizeCandidate(): OffscreenCanvas {\n const ctx = this.canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Textures require OffscreenCanvas 2D.\");\n ctx.save();\n try {\n ctx.resetTransform();\n ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n this.call(() => this.definition.rasterize(this.state, this.context));\n this.dirty = false;\n } finally {\n ctx.restore();\n }\n const spare = this.spare;\n this.spare = undefined;\n const reusable = spare?.width === this.canvas.width && spare.height === this.canvas.height ?\n spare : undefined;\n if (spare && spare !== reusable) spare.width = spare.height = 0;\n let candidate: OffscreenCanvas | undefined;\n try {\n candidate = reusable ?? this.createPublicationCanvas();\n const candidateContext = candidate.getContext(\"2d\");\n if (!candidateContext) throw new Error(\"Textures require OffscreenCanvas 2D.\");\n // Publication canvases are reused; transparent source pixels must erase old paint.\n candidateContext.clearRect(0, 0, candidate.width, candidate.height);\n candidateContext.drawImage(this.canvas, 0, 0);\n return candidate;\n } catch (error) {\n if (candidate) candidate.width = candidate.height = 0;\n this.dirty = true;\n if (!this.retryScheduled) {\n this.retryScheduled = true;\n this.schedule();\n }\n throw error;\n }\n }\n private createPublicationCanvas(): OffscreenCanvas {\n this.publicationCanvasesCreated++;\n return new OffscreenCanvas(this.canvas.width, this.canvas.height);\n }\n /** @internal Structural ownership evidence for texture publication tests. */\n publicationSnapshot(): Readonly<{ publicationCanvasesCreated: number; hasOwner: boolean }> {\n return Object.freeze({ publicationCanvasesCreated: this.publicationCanvasesCreated, hasOwner: this.owner !== undefined });\n }\n private publishInitial(): void {\n const candidate = this.rasterizeCandidate();\n const transaction = GLOBAL_STATE.renderTransaction;\n if (!transaction) {\n this.committed = candidate;\n return;\n }\n this.provisional = { canvas: candidate, transaction };\n transaction.onFinish(success => {\n if (this.provisional?.transaction !== transaction) return;\n const provisional = this.provisional;\n this.provisional = undefined;\n if (success && !this.disposed) this.committed = provisional.canvas;\n else provisional.canvas.width = provisional.canvas.height = 0;\n });\n }\n private assertOwner(): void {\n if (this.disposed) throw new Error(\"Cannot paint with a disposed texture.\");\n let root = GLOBAL_STATE.currentPibblInstance;\n while (root?.parent) root = GLOBAL_STATE.pibblInstances.get(root.parent);\n let owner = this.owner;\n while (owner?.parent) owner = GLOBAL_STATE.pibblInstances.get(owner.parent);\n if (root !== owner) throw new Error(\"Textures may only be shared within their owning Pibbl tree.\");\n }\n private borrow(placement: Readonly<TexturePlacement>): BorrowedTextureRaster {\n this.assertOwner();\n const revision = this.revision.get();\n const provisional = this.provisional;\n const source =\n provisional !== undefined && provisional.transaction === GLOBAL_STATE.renderTransaction ?\n provisional.canvas : this.committed;\n if (!source) throw new Error(\"Texture pixels are not committed for this render transaction.\");\n return Object.freeze({ source, width: source.width, height: source.height, revision, resource: this, placement });\n }\n private resolvePaint(ctx: RenderingContext2D, bounds: { x: number; y: number; width: number; height: number }, p: Readonly<TexturePlacement>): string | CanvasGradient | CanvasPattern {\n const borrowed = this.borrow(p);\n const pattern = ctx.createPattern(borrowed.source, \"repeat\");\n if (!pattern) throw new Error(\"Could not create texture paint.\");\n const stretch = p.mode === \"stretch\";\n const width = stretch ? bounds.width : (p.tileWidth ?? borrowed.width);\n const height = stretch ? bounds.height : (p.tileHeight ?? borrowed.height);\n pattern.setTransform(new DOMMatrix().translate(bounds.x + (p.offsetX ?? 0), bounds.y + (p.offsetY ?? 0)).rotate(p.rotation ?? 0).scale(Math.max(0.000001, width) / borrowed.width, Math.max(0.000001, height) / borrowed.height));\n return pattern;\n }\n dispose() {\n if (this.disposed) return;\n this.disposed = true;\n this.unschedule();\n this.messages.length = 0;\n try {\n this.disposeState();\n } finally {\n this.canvas.width = this.canvas.height = 0;\n this.committed && (this.committed.width = this.committed.height = 0);\n this.spare && (this.spare.width = this.spare.height = 0);\n this.provisional && (this.provisional.canvas.width = this.provisional.canvas.height = 0);\n this.state = undefined;\n this.hasState = false;\n this.committed = undefined;\n this.spare = undefined;\n this.provisional = undefined;\n this.owner = undefined;\n }\n }\n private disposeState() {\n if (!this.hasState) return;\n this.hasState = false;\n const state = this.state;\n this.state = undefined;\n this.call(() => this.definition.dispose?.(state, this.context));\n }\n}\n\n/**\n * Owns one persistent texture resource for the current mounted hook slot.\n *\n * @param input - Texture recipe to mount or update. See {@link TextureRecipe}.\n * @param options - Resolution and lifecycle options for the mounted texture. See\n * {@link TextureOptions} .\n * @returns A mount-owned texture handle for sending messages and creating paint placements. See\n * {@link Texture} .\n *\n * @see {@link TextureRecipe}\n * @see {@link TextureOptions}\n * @see {@link Texture}\n */\nexport function useTexture<Message>(\n input: TextureRecipe<Message>,\n options: TextureOptions = {},\n): Texture<Message> {\n const recipe = recipes.get(input);\n if (!recipe)\n throw new TypeError(\"useTexture requires a defineTexture recipe.\");\n const { pibblInstance } = requireHookContext();\n let created = false;\n const resource = useHookSlot(\"texture\", (teardowns) => {\n created = true;\n const value = new Resource(pibblInstance, recipe, options);\n teardowns.add(() => value.dispose());\n return value;\n }).value;\n if (!created)\n GLOBAL_STATE.renderTransaction!.onFinish((success) => {\n if (success) resource.update(recipe, options);\n });\n return resource.handle;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["placement"]
7
7
  }
@@ -68,7 +68,10 @@ function captureTransition(draw) {
68
68
  }
69
69
  function regionSnapshot(value) {
70
70
  const region = Object.freeze({ ...value });
71
- for (const key of ["x", "y", "width", "height"]) finite(region[key], `region.${key}`);
71
+ finite(region.x, "region.x");
72
+ finite(region.y, "region.y");
73
+ finite(region.width, "region.width");
74
+ finite(region.height, "region.height");
72
75
  if (region.width <= 0 || region.height <= 0) throw new RangeError("Transition region must have positive width and height.");
73
76
  return region;
74
77
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/transitions/capture.ts"],
4
- "sourcesContent": ["import { filterBoundaryExecutor, type CustomPreparedFilter } from '../../filters/filter-executor.js';\nimport { GLOBAL_STATE } from '../global-state.js';\nimport { getOptionalService } from '../optional-services.js';\nimport { PIBBL_FILTER_EXECUTOR, type PibblFilter, type PibblFilterExecutor } from '../style/filter-types.js';\nimport type { PibblInstance } from '../types.js';\nimport type { FilterWindows } from '../filter/filter-region.js';\n\nconst SCRATCH = Symbol('pibbl.transition.capture');\nclass TransitionSurfaces {\n private surfaces: OffscreenCanvas[] = [];\n used = false;\n private committed = false;\n constructor(private readonly instance: PibblInstance) {}\n beginRender(): void { this.used = false; }\n endRender(success: boolean): void {\n if (success && this.used) { this.committed = true; return; }\n if (success || !this.committed) this.dispose();\n }\n context(index: number, width: number, height: number): OffscreenCanvasRenderingContext2D {\n const canvas = this.surfaces[index] ??= new OffscreenCanvas(width, height);\n if (canvas.width !== width) canvas.width = width;\n if (canvas.height !== height) canvas.height = height;\n const context = canvas.getContext('2d');\n if (!context) throw new Error('Transitions require Canvas 2D.');\n context.reset(); return context;\n }\n dispose(): void {\n for (const surface of this.surfaces) { surface.width = 0; surface.height = 0; }\n this.surfaces = []; this.instance.optionalServices.delete(SCRATCH);\n }\n}\nexport interface CaptureFrame {\n readonly context: OffscreenCanvasRenderingContext2D;\n readonly windows: FilterWindows;\n readonly source: OffscreenCanvas;\n /** Draw in local coordinates, including any caller-applied transform. */\n drawSource(): void;\n drawTint(color: string): void;\n}\nexport function captureTransition(draw: (frame: CaptureFrame) => void): PibblFilter {\n const executor: PibblFilterExecutor = {\n render: filterBoundaryExecutor.render,\n prepare(): CustomPreparedFilter {\n return { executor: filterBoundaryExecutor, reverseInfluence: output => ({ ...output }), process(source, windows) {\n const instance = GLOBAL_STATE.currentPibblInstance;\n if (!instance) throw new Error('Transition rendering requires an active Pibbl instance.');\n const scratch = getOptionalService(instance, SCRATCH, () => new TransitionSurfaces(instance)); scratch.used = true;\n const context = scratch.context(0, source.width, source.height);\n context.setTransform(windows.source.renderTransform);\n const bounds = windows.source.logicalBounds;\n const drawImage = (image: OffscreenCanvas) => context.drawImage(image, bounds.x, bounds.y, bounds.width, bounds.height);\n draw({ context, windows, source, drawSource: () => drawImage(source), drawTint(color) {\n const tint = scratch.context(1, source.width, source.height);\n tint.drawImage(source, 0, 0); tint.globalCompositeOperation = 'source-in';\n tint.fillStyle = color; tint.fillRect(0, 0, source.width, source.height); drawImage(tint.canvas);\n } });\n return context.canvas.transferToImageBitmap();\n } };\n },\n };\n return Object.freeze({ [PIBBL_FILTER_EXECUTOR]: executor });\n}\nexport interface TransitionRegion { readonly x: number; readonly y: number; readonly width: number; readonly height: number }\nexport function regionSnapshot(value: TransitionRegion): Readonly<TransitionRegion> {\n const region = Object.freeze({ ...value });\n for (const key of ['x', 'y', 'width', 'height'] as const) finite(region[key], `region.${key}`);\n if (region.width <= 0 || region.height <= 0) throw new RangeError('Transition region must have positive width and height.');\n return region;\n}\nexport function finite(value: number, name: string, minimum = -Infinity): number {\n if (!Number.isFinite(value) || value < minimum) throw new RangeError(`${name} must be finite and at least ${minimum}.`);\n return value;\n}\nexport const clamp = (value: number) => Math.max(0, Math.min(1, value));\nexport const seededNoise = (seed: number) => (n: number) => { const v = Math.sin(n * 127.1 + seed * 31.7) * 43758.5453; return v - Math.floor(v); };\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { filterBoundaryExecutor, type CustomPreparedFilter } from '../../filters/filter-executor.js';\nimport { GLOBAL_STATE } from '../global-state.js';\nimport { getOptionalService } from '../optional-services.js';\nimport { PIBBL_FILTER_EXECUTOR, type PibblFilter, type PibblFilterExecutor } from '../style/filter-types.js';\nimport type { PibblInstance } from '../types.js';\nimport type { FilterWindows } from '../filter/filter-region.js';\n\n\nconst SCRATCH = Symbol('pibbl.transition.capture');\nclass TransitionSurfaces {\n private surfaces: OffscreenCanvas[] = [];\n used = false;\n private committed = false;\n constructor(private readonly instance: PibblInstance) {}\n beginRender(): void { this.used = false; }\n endRender(success: boolean): void {\n if (success && this.used) { this.committed = true; return; }\n if (success || !this.committed) this.dispose();\n }\n context(index: number, width: number, height: number): OffscreenCanvasRenderingContext2D {\n const canvas = this.surfaces[index] ??= new OffscreenCanvas(width, height);\n if (canvas.width !== width) canvas.width = width;\n if (canvas.height !== height) canvas.height = height;\n const context = canvas.getContext('2d');\n if (!context) throw new Error('Transitions require Canvas 2D.');\n context.reset(); return context;\n }\n dispose(): void {\n for (const surface of this.surfaces) { surface.width = 0; surface.height = 0; }\n this.surfaces = []; this.instance.optionalServices.delete(SCRATCH);\n }\n}\nexport interface CaptureFrame {\n readonly context: OffscreenCanvasRenderingContext2D;\n readonly windows: FilterWindows;\n readonly source: OffscreenCanvas;\n /** Draw in local coordinates, including any caller-applied transform. */\n drawSource(): void;\n drawTint(color: string): void;\n}\nexport function captureTransition(draw: (frame: CaptureFrame) => void): PibblFilter {\n const executor: PibblFilterExecutor = {\n render: filterBoundaryExecutor.render,\n prepare(): CustomPreparedFilter {\n return { executor: filterBoundaryExecutor, reverseInfluence: output => ({ ...output }), process(source, windows) {\n const instance = GLOBAL_STATE.currentPibblInstance;\n if (!instance) throw new Error('Transition rendering requires an active Pibbl instance.');\n const scratch = getOptionalService(instance, SCRATCH, () => new TransitionSurfaces(instance)); scratch.used = true;\n const context = scratch.context(0, source.width, source.height);\n context.setTransform(windows.source.renderTransform);\n const bounds = windows.source.logicalBounds;\n const drawImage = (image: OffscreenCanvas) => context.drawImage(image, bounds.x, bounds.y, bounds.width, bounds.height);\n draw({ context, windows, source, drawSource: () => drawImage(source), drawTint(color) {\n const tint = scratch.context(1, source.width, source.height);\n tint.drawImage(source, 0, 0); tint.globalCompositeOperation = 'source-in';\n tint.fillStyle = color; tint.fillRect(0, 0, source.width, source.height); drawImage(tint.canvas);\n } });\n return context.canvas.transferToImageBitmap();\n } };\n },\n };\n return Object.freeze({ [PIBBL_FILTER_EXECUTOR]: executor });\n}\nexport interface TransitionRegion { readonly x: number; readonly y: number; readonly width: number; readonly height: number }\nexport function regionSnapshot(value: TransitionRegion): Readonly<TransitionRegion> {\n const region = Object.freeze({ ...value });\n finite(region.x, 'region.x');\n finite(region.y, 'region.y');\n finite(region.width, 'region.width');\n finite(region.height, 'region.height');\n if (region.width <= 0 || region.height <= 0) throw new RangeError('Transition region must have positive width and height.');\n return region;\n}\nexport function finite(value: number, name: string, minimum = -Infinity): number {\n if (!Number.isFinite(value) || value < minimum) throw new RangeError(`${name} must be finite and at least ${minimum}.`);\n return value;\n}\nexport const clamp = (value: number) => Math.max(0, Math.min(1, value));\nexport const seededNoise = (seed: number) => (n: number) => { const v = Math.sin(n * 127.1 + seed * 31.7) * 43758.5453; return v - Math.floor(v); };\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -61,16 +61,11 @@ function emberSimulation(kernel, options, region, linger, burnWidth) {
61
61
  throw new RangeError(
62
62
  "Invalid ember obstacle batch or capacity exceeded (8192 numbers)."
63
63
  );
64
- for (const packed of [boxes, ellipses, polygons])
65
- for (const value of packed)
66
- if (!Number.isFinite(value))
67
- throw new RangeError("Ember obstacles must be finite.");
68
- for (const packed of [boxes, ellipses])
69
- for (let i = 0; i < packed.length; i += 10)
70
- if (packed[i + 2] <= 0 || packed[i + 3] <= 0)
71
- throw new RangeError(
72
- "Ember obstacle extents must be positive."
73
- );
64
+ validateFiniteObstacles(boxes);
65
+ validateFiniteObstacles(ellipses);
66
+ validateFiniteObstacles(polygons);
67
+ validateObstacleExtents(boxes);
68
+ validateObstacleExtents(ellipses);
74
69
  for (let at = 0; at < polygons.length; ) {
75
70
  const count = polygons[at];
76
71
  if (!Number.isInteger(count) || count < 3 || at + 6 + count * 2 > polygons.length)
@@ -154,6 +149,18 @@ function emberSimulation(kernel, options, region, linger, burnWidth) {
154
149
  }
155
150
  };
156
151
  }
152
+ function validateFiniteObstacles(packed) {
153
+ for (let i = 0; i < packed.length; i++)
154
+ if (!Number.isFinite(packed[i]))
155
+ throw new RangeError("Ember obstacles must be finite.");
156
+ }
157
+ function validateObstacleExtents(packed) {
158
+ for (let i = 0; i < packed.length; i += 10)
159
+ if (packed[i + 2] <= 0 || packed[i + 3] <= 0)
160
+ throw new RangeError(
161
+ "Ember obstacle extents must be positive."
162
+ );
163
+ }
157
164
  export {
158
165
  emberSimulation,
159
166
  resolveEmbersPhysics
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/transitions/embers-physics.ts"],
4
- "sourcesContent": ["import type { PibblEmbersOptions } from './embers.js';\nimport { finite } from \"./capture.js\";\nimport type { lazyTransitionKernel } from \"./wasm/kernel.js\";\n/**\n * Collision information produced by an ember's physical interaction.\n *\n * @see {@link PibblEmbersPhysicsOptions}\n */\nexport interface PibblEmberCollision {\n /** Fraction of the swept segment at impact, from zero to one. */\n readonly fraction: number;\n /** Outward surface normal in the receiving primitive's local coordinates. */\n readonly normal: readonly [number, number];\n}\n/**\n * Collision and physical motion options for transition embers.\n *\n * @see {@link PibblEmberCollision}\n * @see {@link PibblEmbersOptions}\n */\nexport interface PibblEmbersPhysicsOptions {\n /** Local units/second\u00B2. Default [0, -60]. */\n readonly gravity?: readonly [number, number];\n /** Target air velocity in local units/second. Default [0, -45]. */\n readonly wind?: readonly [number, number];\n /** Velocity damping per second. Default 4. */\n readonly drag?: number;\n /** Bounce coefficient, zero to one. Default 0.5. */\n readonly restitution?: number;\n /** Packed committed solids in receiver-local coordinates (e.g. physicsObstacles2D).\n * Revision must change whenever data changes. Up to 8192 packed numbers.\n * Sweeps run as one WASM batch; mutually exclusive with collide.\n */\n readonly obstacles?: Readonly<{\n /**\n * Reads the current committed values required by this integration. See\n * {@link PibblEmbersPhysicsOptions}.\n * @returns The current obstacle revision and packed geometry arrays.\n */\n read(): Readonly<{\n /**\n * Revision used to detect changes to the underlying state or geometry. See\n * {@link PibblEmbersPhysicsOptions}.\n */\n revision: number;\n /** Packed box obstacle data consumed by the simulation. See {@link PibblEmbersPhysicsOptions}. */\n boxes: Float64Array;\n /**\n * Packed ellipse obstacle data consumed by the simulation. See\n * {@link PibblEmbersPhysicsOptions}.\n */\n ellipses: Float64Array;\n /**\n * Packed polygon obstacle data consumed by the simulation. See\n * {@link PibblEmbersPhysicsOptions}.\n */\n polygons: Float64Array;\n }>;\n }>;\n /**\n * Synchronous point sweep, called in Advance. Return the closest hit, if any.\n * @param from - Previous particle position.\n * @param to - Proposed particle position.\n * @returns Collision information, or undefined when motion is unobstructed. See\n * {@link PibblEmberCollision} .\n */\n readonly collide?: (\n from: readonly [number, number],\n to: readonly [number, number],\n ) => PibblEmberCollision | undefined;\n}\nexport function resolveEmbersPhysics(options: PibblEmbersPhysicsOptions) {\n const vector = (value: readonly [number, number], name: string) =>\n Object.freeze([\n finite(value[0], `${name}.x`),\n finite(value[1], `${name}.y`),\n ] as const);\n const restitution = finite(\n options.restitution ?? 0.5,\n \"physics.restitution\",\n 0,\n );\n if (restitution > 1)\n throw new RangeError(\"physics.restitution must be between zero and one.\");\n if (options.collide !== undefined && typeof options.collide !== \"function\")\n throw new TypeError(\"physics.collide must be a synchronous function.\");\n if (\n options.obstacles &&\n (typeof options.obstacles.read !== \"function\" || options.collide)\n )\n throw new TypeError(\n \"physics.obstacles requires read() and cannot be combined with collide.\",\n );\n return Object.freeze({\n obstacles: options.obstacles,\n gravity: vector(options.gravity ?? [0, -60], \"physics.gravity\"),\n wind: vector(options.wind ?? [0, -45], \"physics.wind\"),\n drag: finite(options.drag ?? 4, \"physics.drag\", 0),\n restitution,\n collide: options.collide,\n });\n}\ntype Kernel = ReturnType<ReturnType<typeof lazyTransitionKernel>>;\nexport function emberSimulation(\n kernel: Kernel,\n options: ReturnType<typeof resolveEmbersPhysics>,\n region: Readonly<{ x: number; y: number; width: number; height: number }>,\n linger: number,\n burnWidth: number,\n) {\n let previous = 0,\n remainder = 0,\n needsReset = true,\n disposed = false;\n const step = 1000 / 60;\n let obstacleRevision: number | undefined;\n let boxLength = 0,\n ellipseLength = 0,\n polygonLength = 0;\n return {\n reset() {\n previous = 0;\n remainder = 0;\n needsReset = true;\n },\n get disposed() {\n return disposed;\n },\n dispose() {\n disposed = true;\n kernel.dispose();\n },\n advance(elapsed: number, progressAt: (time: number) => number) {\n if (disposed || elapsed <= previous) return;\n const { exports, values } = kernel();\n if (needsReset) {\n exports.resetPhysics!();\n needsReset = false;\n }\n remainder += Math.min(elapsed - previous, step * 4);\n previous = elapsed;\n if (remainder + 1e-8 >= step && options.obstacles) {\n const batch = options.obstacles.read();\n if (batch.revision !== obstacleRevision) {\n const { boxes, ellipses, polygons } = batch;\n if (\n !Number.isFinite(batch.revision) ||\n boxes.length % 10 ||\n ellipses.length % 10 ||\n boxes.length + ellipses.length + polygons.length > 8192\n )\n throw new RangeError(\n \"Invalid ember obstacle batch or capacity exceeded (8192 numbers).\",\n );\n for (const packed of [boxes, ellipses, polygons])\n for (const value of packed)\n if (!Number.isFinite(value))\n throw new RangeError(\"Ember obstacles must be finite.\");\n for (const packed of [boxes, ellipses])\n for (let i = 0; i < packed.length; i += 10)\n if (packed[i + 2]! <= 0 || packed[i + 3]! <= 0)\n throw new RangeError(\n \"Ember obstacle extents must be positive.\",\n );\n for (let at = 0; at < polygons.length;) {\n const count = polygons[at]!;\n if (\n !Number.isInteger(count) ||\n count < 3 ||\n at + 6 + count * 2 > polygons.length\n )\n throw new RangeError(\"Invalid ember obstacle polygon.\");\n at += 6 + count * 2;\n }\n values.set(boxes, 22400);\n values.set(ellipses, 22400 + boxes.length);\n values.set(polygons, 22400 + boxes.length + ellipses.length);\n boxLength = boxes.length;\n ellipseLength = ellipses.length;\n polygonLength = polygons.length;\n obstacleRevision = batch.revision;\n }\n }\n while (remainder + 1e-8 >= step) {\n const time = elapsed - remainder + step;\n remainder = Math.max(0, remainder - step);\n const q = progressAt(time);\n exports.births!(time, linger);\n for (let i = 0; i < 1200; i++)\n values[11166 + i] = progressAt(values[12366 + i]!);\n exports.sample!(\n q,\n 1,\n time,\n linger,\n 0,\n burnWidth,\n region.x,\n region.y,\n region.width,\n region.height,\n Math.min(512, Math.max(1, Math.ceil(region.width / 2))),\n );\n exports.stepPhysics!(\n time,\n step / 1000,\n ...options.gravity,\n ...options.wind,\n options.drag,\n linger,\n );\n if (options.obstacles)\n exports.collideObstacles!(\n boxLength,\n ellipseLength,\n polygonLength,\n options.restitution,\n );\n if (options.collide)\n for (let i = 0; i < 1200; i++) {\n const s = 14000 + i * 7;\n if (values[s + 4]! < 0) continue;\n const from = [values[s + 5]!, values[s + 6]!] as const,\n to = [values[s]!, values[s + 1]!] as const;\n if (from[0] === to[0] && from[1] === to[1]) continue;\n const hit = options.collide(from, to);\n if (!hit) continue;\n const fraction = finite(hit.fraction, \"collision.fraction\", 0);\n const nx = finite(hit.normal?.[0], \"collision.normal.x\"),\n ny = finite(hit.normal?.[1], \"collision.normal.y\"),\n length = Math.hypot(nx, ny);\n if (fraction > 1 || length < 1e-8)\n throw new RangeError(\n \"Ember collision requires a fraction in [0, 1] and a nonzero normal.\",\n );\n exports.collidePhysics!(\n i,\n fraction,\n nx / length,\n ny / length,\n options.restitution,\n );\n }\n }\n },\n present() {\n if (!needsReset && !disposed) kernel().exports.presentPhysics!();\n else {\n const { values } = kernel();\n for (let i = 0; i < 1200; i++) values[1566 + i * 8 + 5] = -1;\n }\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { PibblEmbersOptions } from './embers.js';\nimport { finite } from \"./capture.js\";\nimport type { lazyTransitionKernel } from \"./wasm/kernel.js\";\n/**\n * Collision information produced by an ember's physical interaction.\n *\n * @see {@link PibblEmbersPhysicsOptions}\n */\nexport interface PibblEmberCollision {\n /** Fraction of the swept segment at impact, from zero to one. */\n readonly fraction: number;\n /** Outward surface normal in the receiving primitive's local coordinates. */\n readonly normal: readonly [number, number];\n}\n/**\n * Collision and physical motion options for transition embers.\n *\n * @see {@link PibblEmberCollision}\n * @see {@link PibblEmbersOptions}\n */\nexport interface PibblEmbersPhysicsOptions {\n /** Local units/second\u00B2. Default [0, -60]. */\n readonly gravity?: readonly [number, number];\n /** Target air velocity in local units/second. Default [0, -45]. */\n readonly wind?: readonly [number, number];\n /** Velocity damping per second. Default 4. */\n readonly drag?: number;\n /** Bounce coefficient, zero to one. Default 0.5. */\n readonly restitution?: number;\n /** Packed committed solids in receiver-local coordinates (e.g. physicsObstacles2D).\n * Revision must change whenever data changes. Up to 8192 packed numbers.\n * Sweeps run as one WASM batch; mutually exclusive with collide.\n */\n readonly obstacles?: Readonly<{\n /**\n * Reads the current committed values required by this integration. See\n * {@link PibblEmbersPhysicsOptions}.\n * @returns The current obstacle revision and packed geometry arrays.\n */\n read(): Readonly<{\n /**\n * Revision used to detect changes to the underlying state or geometry. See\n * {@link PibblEmbersPhysicsOptions}.\n */\n revision: number;\n /** Packed box obstacle data consumed by the simulation. See {@link PibblEmbersPhysicsOptions}. */\n boxes: Float64Array;\n /**\n * Packed ellipse obstacle data consumed by the simulation. See\n * {@link PibblEmbersPhysicsOptions}.\n */\n ellipses: Float64Array;\n /**\n * Packed polygon obstacle data consumed by the simulation. See\n * {@link PibblEmbersPhysicsOptions}.\n */\n polygons: Float64Array;\n }>;\n }>;\n /**\n * Synchronous point sweep, called in Advance. Return the closest hit, if any.\n * @param from - Previous particle position.\n * @param to - Proposed particle position.\n * @returns Collision information, or undefined when motion is unobstructed. See\n * {@link PibblEmberCollision} .\n */\n readonly collide?: (\n from: readonly [number, number],\n to: readonly [number, number],\n ) => PibblEmberCollision | undefined;\n}\nexport function resolveEmbersPhysics(options: PibblEmbersPhysicsOptions) {\n const vector = (value: readonly [number, number], name: string) =>\n Object.freeze([\n finite(value[0], `${name}.x`),\n finite(value[1], `${name}.y`),\n ] as const);\n const restitution = finite(\n options.restitution ?? 0.5,\n \"physics.restitution\",\n 0,\n );\n if (restitution > 1)\n throw new RangeError(\"physics.restitution must be between zero and one.\");\n if (options.collide !== undefined && typeof options.collide !== \"function\")\n throw new TypeError(\"physics.collide must be a synchronous function.\");\n if (\n options.obstacles &&\n (typeof options.obstacles.read !== \"function\" || options.collide)\n )\n throw new TypeError(\n \"physics.obstacles requires read() and cannot be combined with collide.\",\n );\n return Object.freeze({\n obstacles: options.obstacles,\n gravity: vector(options.gravity ?? [0, -60], \"physics.gravity\"),\n wind: vector(options.wind ?? [0, -45], \"physics.wind\"),\n drag: finite(options.drag ?? 4, \"physics.drag\", 0),\n restitution,\n collide: options.collide,\n });\n}\ntype Kernel = ReturnType<ReturnType<typeof lazyTransitionKernel>>;\nexport function emberSimulation(\n kernel: Kernel,\n options: ReturnType<typeof resolveEmbersPhysics>,\n region: Readonly<{ x: number; y: number; width: number; height: number }>,\n linger: number,\n burnWidth: number,\n) {\n let previous = 0,\n remainder = 0,\n needsReset = true,\n disposed = false;\n const step = 1000 / 60;\n let obstacleRevision: number | undefined;\n let boxLength = 0,\n ellipseLength = 0,\n polygonLength = 0;\n return {\n reset() {\n previous = 0;\n remainder = 0;\n needsReset = true;\n },\n get disposed() {\n return disposed;\n },\n dispose() {\n disposed = true;\n kernel.dispose();\n },\n advance(elapsed: number, progressAt: (time: number) => number) {\n if (disposed || elapsed <= previous) return;\n const { exports, values } = kernel();\n if (needsReset) {\n exports.resetPhysics!();\n needsReset = false;\n }\n remainder += Math.min(elapsed - previous, step * 4);\n previous = elapsed;\n if (remainder + 1e-8 >= step && options.obstacles) {\n const batch = options.obstacles.read();\n if (batch.revision !== obstacleRevision) {\n const { boxes, ellipses, polygons } = batch;\n if (\n !Number.isFinite(batch.revision) ||\n boxes.length % 10 ||\n ellipses.length % 10 ||\n boxes.length + ellipses.length + polygons.length > 8192\n )\n throw new RangeError(\n \"Invalid ember obstacle batch or capacity exceeded (8192 numbers).\",\n );\n validateFiniteObstacles(boxes);\n validateFiniteObstacles(ellipses);\n validateFiniteObstacles(polygons);\n validateObstacleExtents(boxes);\n validateObstacleExtents(ellipses);\n for (let at = 0; at < polygons.length;) {\n const count = polygons[at]!;\n if (\n !Number.isInteger(count) ||\n count < 3 ||\n at + 6 + count * 2 > polygons.length\n )\n throw new RangeError(\"Invalid ember obstacle polygon.\");\n at += 6 + count * 2;\n }\n values.set(boxes, 22400);\n values.set(ellipses, 22400 + boxes.length);\n values.set(polygons, 22400 + boxes.length + ellipses.length);\n boxLength = boxes.length;\n ellipseLength = ellipses.length;\n polygonLength = polygons.length;\n obstacleRevision = batch.revision;\n }\n }\n while (remainder + 1e-8 >= step) {\n const time = elapsed - remainder + step;\n remainder = Math.max(0, remainder - step);\n const q = progressAt(time);\n exports.births!(time, linger);\n for (let i = 0; i < 1200; i++)\n values[11166 + i] = progressAt(values[12366 + i]!);\n exports.sample!(\n q,\n 1,\n time,\n linger,\n 0,\n burnWidth,\n region.x,\n region.y,\n region.width,\n region.height,\n Math.min(512, Math.max(1, Math.ceil(region.width / 2))),\n );\n exports.stepPhysics!(\n time,\n step / 1000,\n ...options.gravity,\n ...options.wind,\n options.drag,\n linger,\n );\n if (options.obstacles)\n exports.collideObstacles!(\n boxLength,\n ellipseLength,\n polygonLength,\n options.restitution,\n );\n if (options.collide)\n for (let i = 0; i < 1200; i++) {\n const s = 14000 + i * 7;\n if (values[s + 4]! < 0) continue;\n const from = [values[s + 5]!, values[s + 6]!] as const,\n to = [values[s]!, values[s + 1]!] as const;\n if (from[0] === to[0] && from[1] === to[1]) continue;\n const hit = options.collide(from, to);\n if (!hit) continue;\n const fraction = finite(hit.fraction, \"collision.fraction\", 0);\n const nx = finite(hit.normal?.[0], \"collision.normal.x\"),\n ny = finite(hit.normal?.[1], \"collision.normal.y\"),\n length = Math.hypot(nx, ny);\n if (fraction > 1 || length < 1e-8)\n throw new RangeError(\n \"Ember collision requires a fraction in [0, 1] and a nonzero normal.\",\n );\n exports.collidePhysics!(\n i,\n fraction,\n nx / length,\n ny / length,\n options.restitution,\n );\n }\n }\n },\n present() {\n if (!needsReset && !disposed) kernel().exports.presentPhysics!();\n else {\n const { values } = kernel();\n for (let i = 0; i < 1200; i++) values[1566 + i * 8 + 5] = -1;\n }\n },\n };\n}\n\nfunction validateFiniteObstacles(packed: ArrayLike<number>): void {\n for (let i = 0; i < packed.length; i++)\n if (!Number.isFinite(packed[i]))\n throw new RangeError(\"Ember obstacles must be finite.\");\n}\n\nfunction validateObstacleExtents(packed: ArrayLike<number>): void {\n for (let i = 0; i < packed.length; i += 10)\n if (packed[i + 2]! <= 0 || packed[i + 3]! <= 0)\n throw new RangeError(\n \"Ember obstacle extents must be positive.\",\n );\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -41,6 +41,8 @@ export type { PibblComponent, PibblContainerChild, PibblElement, PibblElementTyp
41
41
  * @see {@link PibblTransitionBinding}
42
42
  */
43
43
  export interface SystemStyle {
44
+ /** Numeric layout participation. Hidden subtrees retain mounted ownership without geometry or paint; contents retains logical ancestry without owning a box. See {@link SystemStyle}. */
45
+ layoutParticipation?: 'normal' | 'hidden' | 'contents';
44
46
  /** Visibility-transition binding applied to this primitive and its captured descendants. See {@link SystemStyle}. */
45
47
  transition?: import("./transitions/binding.js").PibblTransitionBinding;
46
48
  /** Application-defined style payload passed through the runtime. See {@link SystemStyle}. */
@@ -261,6 +263,19 @@ export interface CanvasMeasurementService {
261
263
  * @returns Canvas text metrics for the supplied text and font.
262
264
  */
263
265
  measureText(text: string, font: string): TextMetrics;
266
+ /**
267
+ * Measures text with the requested Canvas baseline state. Providers that do not
268
+ * implement this optional capability cannot supply Text baseline composition.
269
+ * @param text - Text to measure.
270
+ * @param options - Exact Canvas font and baseline configuration. See {@link CanvasMeasurementService}.
271
+ * @returns Canvas metrics in the requested baseline coordinate system.
272
+ */
273
+ measureTextAtBaseline?(text: string, options: Readonly<{
274
+ /** Canvas font configuration. See {@link CanvasMeasurementService}. */
275
+ font: string;
276
+ /** Canvas drawing baseline for the returned metrics. See {@link CanvasMeasurementService}. */
277
+ textBaseline: CanvasTextBaseline;
278
+ }>): TextMetrics;
264
279
  }
265
280
  /**
266
281
  * Measured dimensions, or an explicit unsupported result with a diagnostic reason.
@@ -312,6 +327,72 @@ export interface MeasureInput<P, S extends SystemStyle = SystemStyle> {
312
327
  */
313
328
  measureElement(element: PibblElement<any>, constraints: Readonly<Constraints>): MeasureResult;
314
329
  }
330
+ /** Available logical size along one intrinsic query axis. See {@link IntrinsicConstraints}. */
331
+ export type IntrinsicAxisConstraints = Readonly<{
332
+ kind: 'bounded'; /** Minimum logical length. */
333
+ min: number; /** Maximum logical length. */
334
+ max: number;
335
+ }> | Readonly<{
336
+ kind: 'unbounded'; /** Minimum logical length. */
337
+ min: number;
338
+ }>;
339
+ /** Explicit axis availability for intrinsic measurement. See {@link IntrinsicMeasureInput}. */
340
+ export interface IntrinsicConstraints {
341
+ /** Horizontal availability. See {@link IntrinsicAxisConstraints}. */
342
+ readonly width: IntrinsicAxisConstraints;
343
+ /** Vertical availability. See {@link IntrinsicAxisConstraints}. */
344
+ readonly height: IntrinsicAxisConstraints;
345
+ }
346
+ /** Pure custom-leaf input for both intrinsic contributions. See {@link PrimitiveCapabilities}. */
347
+ export interface IntrinsicMeasureInput<P, S extends SystemStyle = SystemStyle> {
348
+ /** Resolved receiver inputs. See {@link MeasureInput}. */
349
+ readonly props: Readonly<P>;
350
+ /** Normalized content style. See {@link NormalizedStyle}. */
351
+ readonly style: NormalizedStyle<S>;
352
+ /** Tagged available dimensions. See {@link IntrinsicConstraints}. */
353
+ readonly constraints: Readonly<IntrinsicConstraints>;
354
+ /** Pure Canvas measurements. See {@link CanvasMeasurementService}. */
355
+ readonly service: CanvasMeasurementService;
356
+ }
357
+ /** Both content-box intrinsic contributions or explicit failure. See {@link IntrinsicMeasureInput}. */
358
+ export type IntrinsicSizesResult = Readonly<{
359
+ status: 'measured'; /** Minimum unbroken content size. See {@link Size}. */
360
+ minContent: Readonly<Size>; /** Preferred content size. See {@link Size}. */
361
+ maxContent: Readonly<Size>;
362
+ }> | Readonly<{
363
+ status: 'unsupported'; /** Actionable explanation. */
364
+ reason: string;
365
+ }>;
366
+ /** Final-allocation input for a pure custom baseline query. See {@link PrimitiveCapabilities}. */
367
+ export interface BaselineMeasureInput<P, S extends SystemStyle = SystemStyle> {
368
+ /** Resolved receiver inputs. See {@link MeasureInput}. */
369
+ readonly props: Readonly<P>;
370
+ /** Normalized content style. See {@link NormalizedStyle}. */
371
+ readonly style: NormalizedStyle<S>;
372
+ /** Final local content allocation; origin is always `{ x: 0, y: 0 }`. See {@link LayoutBox}. */
373
+ readonly allocation: Readonly<LayoutBox>;
374
+ /** Pure Canvas measurements. See {@link CanvasMeasurementService}. */
375
+ readonly service: CanvasMeasurementService;
376
+ }
377
+ /**
378
+ * First/last baseline offsets from content top, or explicit inability to provide them.
379
+ * Finite offsets may be negative or outside the content box; first must not exceed last.
380
+ * @see {@link BaselineMeasureInput}
381
+ * @see {@link PrimitiveCapabilities}
382
+ */
383
+ export type BaselinesResult = Readonly<{
384
+ /** Successful baseline query. See {@link BaselinesResult}. */
385
+ status: 'measured';
386
+ /** First logical baseline offset from the content top. See {@link BaselinesResult}. */
387
+ first: number;
388
+ /** Last logical baseline offset, at or after first. See {@link BaselinesResult}. */
389
+ last: number;
390
+ }> | Readonly<{
391
+ /** Explicit inability to supply baselines. See {@link BaselinesResult}. */
392
+ status: 'unsupported';
393
+ /** Actionable explanation; does not select the missing-provider fallback. See {@link BaselinesResult}. */
394
+ reason: string;
395
+ }>;
315
396
  /**
316
397
  * The synchronous drawing callback of a custom primitive.
317
398
  *
@@ -376,6 +457,18 @@ export interface PrimitiveCapabilities<P, S extends SystemStyle = SystemStyle, N
376
457
  * @returns Measured dimensions or an unsupported measurement result. See {@link MeasureResult}.
377
458
  */
378
459
  measure?: (input: MeasureInput<PrimitiveProgramProps<P>, N>) => MeasureResult;
460
+ /**
461
+ * Measures both intrinsic content contributions without painting, hooks or writes.
462
+ * @param input - Resolved inputs and explicit availability. See {@link IntrinsicMeasureInput}.
463
+ * @returns Finite ordered content sizes or unsupported. See {@link IntrinsicSizesResult}.
464
+ */
465
+ measureIntrinsic?: (input: IntrinsicMeasureInput<PrimitiveProgramProps<P>, N>) => IntrinsicSizesResult;
466
+ /**
467
+ * Pure first/last baseline provider at the final content allocation.
468
+ * @param input - Resolved inputs and final local allocation. See {@link BaselineMeasureInput}.
469
+ * @returns Finite ordered offsets or unsupported. See {@link BaselinesResult}.
470
+ */
471
+ measureBaselines?: (input: BaselineMeasureInput<PrimitiveProgramProps<P>, N>) => BaselinesResult;
379
472
  }
380
473
  export interface InternalIdentityHint {
381
474
  type: PibblElementType<any>;
@@ -385,6 +478,7 @@ export interface InternalIdentityHint {
385
478
  export interface PibblComponentRefs<P> {
386
479
  /** Last traversal entry context, not proof that this evaluation painted successfully. */
387
480
  layoutEntry?: Readonly<{
481
+ layoutDirection?: 'ltr' | 'rtl';
388
482
  allocation: Readonly<LayoutBox>;
389
483
  percentageBasis: Readonly<LayoutBox>;
390
484
  }>;
@@ -459,8 +553,17 @@ export interface PibblEventRoot {
459
553
  }
460
554
  /** @internal Root-wide render completion seam for optional policies. */
461
555
  export interface PibblRenderTransaction {
556
+ /** Distinguishes fail-closed errors from an explicitly cancelled candidate. */
557
+ readonly failed?: boolean;
558
+ fail?(): void;
559
+ /** Validate staged geometry before any fallible resource publication. */
560
+ onPreflight?(callback: () => void): void;
462
561
  onPublish?(callback: () => void): void;
562
+ /** Adopt prepared geometry after all fallible application publications succeed. */
563
+ onAdopt?(callback: () => void): void;
463
564
  onFinish(callback: (success: boolean) => void): void;
565
+ /** Run after all finish callbacks have published their committed state. */
566
+ onAfterFinish?(callback: (success: boolean) => void): void;
464
567
  }
465
568
  export interface PibblFocusPolicyBridge {
466
569
  observeHtmlRegion?(region: HtmlFocusRegion): void;
@@ -469,7 +572,7 @@ export interface PibblFocusPolicyBridge {
469
572
  snapshot(target: PibblEventTargetRegistration): PibblEventTargetSnapshot;
470
573
  observeTarget(target: PibblEventTargetRegistration): void;
471
574
  /** @internal Records a target committed during the active render transaction. */
472
- observeTransactionalTarget?(target: PibblEventTargetRegistration): void;
575
+ observeTransactionalTarget?(target: PibblEventTargetRegistration, preparedFocusable?: boolean): void;
473
576
  removeTarget(target: PibblEventTargetRegistration): void;
474
577
  beforeNativeDispatch?(type: DOMPibblEventType, event: Event): PibblFocusPolicyBridge | undefined;
475
578
  resolveKeyboardTarget(): PibblEventTargetRegistration | undefined;
@@ -529,6 +632,10 @@ export type FillStyle = CanvasRenderingContext2D["fillStyle"] | import('./textur
529
632
  */
530
633
  export type StrokeStyle = CanvasRenderingContext2D["strokeStyle"] | import('./textures/texture.js').TexturePaint;
531
634
  export interface PibblInstance {
635
+ /** Last root traversal published successfully; failed render attempts do not advance it. */
636
+ committedRenderGeneration?: number;
637
+ /** Opt-in root bitmap observers; absent unless a recording is attached. */
638
+ rootFrameObservers?: Set<(success: boolean, generation: number) => void>;
532
639
  canvas: Canvas;
533
640
  controller: PibblController;
534
641
  root: PibblNode;
@@ -554,6 +661,8 @@ export interface PibblInstance {
554
661
  /** Current child-to-parent mapping for focus geometry outside hit order. */
555
662
  focusParentBridge: PibblNestedPaintEntry | undefined;
556
663
  rootLayoutBox: Readonly<LayoutBox>;
664
+ /** Internal inherited direction used when this instance begins a root layout context. */
665
+ rootLayoutDirection: 'ltr' | 'rtl';
557
666
  surface: PibblSurfaceState;
558
667
  /** Feature-owned resources, installed only by imported optional entries. */
559
668
  optionalServices: Map<symbol, OptionalService>;
package/dist/sync.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import type { PibblController, PibblNode } from './lib/types.js';
2
+ import type { PibblConfig } from './lib/surface/types.js';
3
+ /**
4
+ * Mounts or updates synchronously using the embedded layout WASM binary.
5
+ * Import from @pibbl/core/sync to opt into its Base64 payload. Reuses a compatible
6
+ * module prepared by prepareLayoutEngine() or a prior mount. Imports are inert.
7
+ * @param canvas The HTML Canvas owned by the mount.
8
+ * @param element The branded recursive root descriptor. See {@link PibblNode}.
9
+ * @param config Surface and lifetime options. See {@link PibblConfig}.
10
+ * @returns The stable {@link PibblController}, synchronously.
11
+ * @throws Throws on compilation/mount failure, or AbortError for a pre-aborted signal.
12
+ * Supersedes pending asynchronous requests for this Canvas.
13
+ * @see {@link PibblController}
14
+ * @see {@link PibblConfig}
15
+ */
16
+ export declare function pibblSync(canvas: HTMLCanvasElement, element: PibblNode, config?: PibblConfig): PibblController;
package/dist/sync.js ADDED
@@ -0,0 +1,13 @@
1
+ import { prepareLayoutEngineSync } from "./lib/layout/wasm/embedded.js";
2
+ import { cancelPendingMount } from "./lib/mount-request.js";
3
+ import { assertMountRequest, mountPreparedPibbl } from "./lib/mount-prepared-pibbl.js";
4
+ function pibblSync(canvas, element, config) {
5
+ assertMountRequest(canvas, element, config);
6
+ cancelPendingMount(canvas);
7
+ prepareLayoutEngineSync();
8
+ return mountPreparedPibbl(canvas, element, config);
9
+ }
10
+ export {
11
+ pibblSync
12
+ };
13
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/sync.ts"],
4
+ "sourcesContent": ["import { prepareLayoutEngineSync } from './lib/layout/wasm/embedded.js';\nimport { cancelPendingMount } from './lib/mount-request.js';\nimport { assertMountRequest, mountPreparedPibbl } from './lib/mount-prepared-pibbl.js';\nimport type { PibblController, PibblNode } from './lib/types.js';\nimport type { PibblConfig } from './lib/surface/types.js';\n\n/**\n * Mounts or updates synchronously using the embedded layout WASM binary.\n * Import from @pibbl/core/sync to opt into its Base64 payload. Reuses a compatible\n * module prepared by prepareLayoutEngine() or a prior mount. Imports are inert.\n * @param canvas The HTML Canvas owned by the mount.\n * @param element The branded recursive root descriptor. See {@link PibblNode}.\n * @param config Surface and lifetime options. See {@link PibblConfig}.\n * @returns The stable {@link PibblController}, synchronously.\n * @throws Throws on compilation/mount failure, or AbortError for a pre-aborted signal.\n * Supersedes pending asynchronous requests for this Canvas.\n * @see {@link PibblController}\n * @see {@link PibblConfig}\n */\nexport function pibblSync(canvas: HTMLCanvasElement, element: PibblNode, config?: PibblConfig): PibblController {\n assertMountRequest(canvas, element, config);\n cancelPendingMount(canvas);\n prepareLayoutEngineSync();\n return mountPreparedPibbl(canvas, element, config);\n}\n"],
5
+ "mappings": "AAAA,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB,0BAA0B;AAiBhD,SAAS,UAAU,QAA2B,SAAoB,QAAuC;AAC9G,qBAAmB,QAAQ,SAAS,MAAM;AAC1C,qBAAmB,MAAM;AACzB,0BAAwB;AACxB,SAAO,mBAAmB,QAAQ,SAAS,MAAM;AACnD;",
6
+ "names": []
7
+ }
package/dist/sync.mjs ADDED
@@ -0,0 +1 @@
1
+ export * from './sync.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pibbl/core",
3
3
  "type": "module",
4
- "version": "0.0.2",
4
+ "version": "0.0.3-alpha.109.1",
5
5
  "description": "Canvas 2D component runtime with JSX and createElement authoring",
6
6
  "author": "Ben Lesh <ben@benlesh.com>",
7
7
  "license": "MIT",
@@ -27,6 +27,10 @@
27
27
  "types": "./dist/internal.d.ts",
28
28
  "default": "./dist/internal.mjs"
29
29
  },
30
+ "./internal/layout": {
31
+ "types": "./dist/layout-kernel.d.ts",
32
+ "default": "./dist/layout-kernel.mjs"
33
+ },
30
34
  "./filters": {
31
35
  "types": "./dist/filters.d.ts",
32
36
  "default": "./dist/filters.mjs"
@@ -86,7 +90,16 @@
86
90
  "./machines/animation": {
87
91
  "types": "./dist/features/machines/animation.d.ts",
88
92
  "default": "./dist/features/machines/animation.mjs"
89
- }
93
+ },
94
+ "./viz/inspection": {
95
+ "types": "./dist/features/viz/inspection.d.ts",
96
+ "default": "./dist/features/viz/inspection.mjs"
97
+ },
98
+ "./sync": {
99
+ "types": "./dist/sync.d.ts",
100
+ "default": "./dist/sync.mjs"
101
+ },
102
+ "./layout.wasm": "./dist/lib/layout/wasm/layout.wasm"
90
103
  },
91
104
  "main": "./dist/index.mjs",
92
105
  "module": "./dist/index.mjs",
@@ -102,6 +115,9 @@
102
115
  "internal": [
103
116
  "./dist/internal.d.ts"
104
117
  ],
118
+ "internal/layout": [
119
+ "./dist/layout-kernel.d.ts"
120
+ ],
105
121
  "*": [
106
122
  "./dist/*",
107
123
  "./*"
@@ -144,6 +160,12 @@
144
160
  ],
145
161
  "machines/animation": [
146
162
  "./dist/features/machines/animation.d.ts"
163
+ ],
164
+ "viz/inspection": [
165
+ "./dist/features/viz/inspection.d.ts"
166
+ ],
167
+ "sync": [
168
+ "./dist/sync.d.ts"
147
169
  ]
148
170
  }
149
171
  },
@@ -155,8 +177,9 @@
155
177
  "@dimforge/rapier2d-compat": "0.21.0",
156
178
  "assemblyscript": "0.28.20"
157
179
  },
180
+ "pibblAlphaInputHash": "ba1fa15ed2398c469a2b95e833fb2434dd0023f4da0a91a0b85f55301c64d8ab",
158
181
  "scripts": {
159
- "build": "node ../../tooling/build-transition-wasm.mjs --check && rimraf dist && tsc -p tsconfig.build.json && node ../../tooling/build-core.mjs",
182
+ "build": "node ../../tooling/build-transition-wasm.mjs --check && node ../../tooling/build-recording-wasm.mjs --check && node ../../tooling/build-layout-wasm.mjs --check && node ../../tooling/build-recording-worker.mjs --check && rimraf dist && tsc -p tsconfig.build.json && node ../../tooling/build-core.mjs",
160
183
  "dev": "pnpm run build",
161
184
  "test": "vitest"
162
185
  }