@things-factory/figure-ui 10.1.75 → 10.1.77

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 (282) hide show
  1. package/client/figure-assistant.ts +3 -3
  2. package/client/graphql/{v3-store.ts → store.ts} +6 -6
  3. package/client/modeller/{v3-ai-proposal.ts → ai-proposal.ts} +8 -8
  4. package/client/modeller/{v3-align.ts → align.ts} +14 -14
  5. package/client/modeller/{v3-canvas.ts → canvas.ts} +13 -13
  6. package/client/modeller/{v3-clips.ts → clips.ts} +5 -5
  7. package/client/modeller/{v3-controls.ts → controls.ts} +2 -2
  8. package/client/modeller/{v3-editor.ts → editor.ts} +117 -117
  9. package/client/modeller/{figure-v3-capability.ts → figure-capability-panel.ts} +7 -7
  10. package/client/modeller/{figure-v3-clips.ts → figure-clips.ts} +10 -10
  11. package/client/modeller/{figure-v3-controls.ts → figure-controls.ts} +9 -9
  12. package/client/modeller/{v3-figure-facts.ts → figure-facts.ts} +11 -11
  13. package/client/modeller/{figure-v3-first-save.ts → figure-first-save.ts} +3 -3
  14. package/client/modeller/figure-history-panel.ts +1 -1
  15. package/client/modeller/{figure-v3-links.ts → figure-links.ts} +35 -35
  16. package/client/modeller/{figure-v3-material.ts → figure-material-panel.ts} +20 -20
  17. package/client/modeller/{figure-v3-parts.ts → figure-parts.ts} +15 -15
  18. package/client/modeller/{figure-v3-preview.ts → figure-preview.ts} +14 -14
  19. package/client/modeller/{figure-v3-properties.ts → figure-properties.ts} +25 -25
  20. package/client/modeller/{figure-v3-recipe-catalog.ts → figure-recipe-catalog.ts} +10 -10
  21. package/client/modeller/{figure-v3-verdict.ts → figure-verdict.ts} +24 -24
  22. package/client/modeller/gate-findings.ts +2 -2
  23. package/client/modeller/{v3-gizmo.ts → gizmo.ts} +11 -11
  24. package/client/modeller/{v3-joint-drag.ts → joint-drag.ts} +11 -11
  25. package/client/modeller/{v3-joint-fan.ts → joint-fan.ts} +13 -13
  26. package/client/modeller/{v3-links.ts → links.ts} +59 -59
  27. package/client/modeller/{v3-live.ts → live.ts} +9 -9
  28. package/client/modeller/{v3-maturity.ts → maturity.ts} +65 -65
  29. package/client/modeller/modeller-route.ts +1 -1
  30. package/client/modeller/{v3-occupancy.ts → occupancy.ts} +6 -6
  31. package/client/modeller/{v3-palette.ts → palette.ts} +3 -3
  32. package/client/modeller/{v3-preview-model.ts → preview-model.ts} +8 -8
  33. package/client/modeller/{v3-product-session.ts → product-session.ts} +25 -25
  34. package/client/modeller/{v3-recipe-source.ts → recipe-source.ts} +2 -2
  35. package/client/modeller/{v3-recipes.ts → recipes.ts} +9 -9
  36. package/client/modeller/{v3-renderer.ts → renderer.ts} +16 -16
  37. package/client/modeller/{v3-stage-model.ts → stage-model.ts} +15 -15
  38. package/client/modeller/{v3-thumbnail.ts → thumbnail.ts} +8 -8
  39. package/client/pages/figure-list-page.ts +4 -4
  40. package/client/pages/{figure-v3-modeller-page.ts → figure-modeller-page.ts} +37 -37
  41. package/client/route.ts +1 -5
  42. package/dist-client/figure-assistant.js +3 -3
  43. package/dist-client/figure-assistant.js.map +1 -1
  44. package/dist-client/graphql/store.d.ts +3 -0
  45. package/dist-client/graphql/{v3-store.js → store.js} +6 -6
  46. package/dist-client/graphql/store.js.map +1 -0
  47. package/dist-client/modeller/{v3-ai-proposal.d.ts → ai-proposal.d.ts} +7 -7
  48. package/dist-client/modeller/{v3-ai-proposal.js → ai-proposal.js} +1 -1
  49. package/dist-client/modeller/ai-proposal.js.map +1 -0
  50. package/dist-client/modeller/{v3-align.d.ts → align.d.ts} +8 -8
  51. package/dist-client/modeller/{v3-align.js → align.js} +6 -6
  52. package/dist-client/modeller/align.js.map +1 -0
  53. package/dist-client/modeller/{v3-canvas.d.ts → canvas.d.ts} +7 -7
  54. package/dist-client/modeller/{v3-canvas.js → canvas.js} +20 -20
  55. package/dist-client/modeller/canvas.js.map +1 -0
  56. package/dist-client/modeller/{v3-clips.d.ts → clips.d.ts} +4 -4
  57. package/dist-client/modeller/{v3-clips.js → clips.js} +1 -1
  58. package/dist-client/modeller/clips.js.map +1 -0
  59. package/dist-client/modeller/{v3-controls.d.ts → controls.d.ts} +2 -2
  60. package/dist-client/modeller/{v3-controls.js → controls.js} +1 -1
  61. package/dist-client/modeller/controls.js.map +1 -0
  62. package/dist-client/modeller/{v3-editor.d.ts → editor.d.ts} +19 -19
  63. package/dist-client/modeller/{v3-editor.js → editor.js} +103 -103
  64. package/dist-client/modeller/editor.js.map +1 -0
  65. package/dist-client/modeller/{v3-fields.js → fields.js} +1 -1
  66. package/dist-client/modeller/fields.js.map +1 -0
  67. package/dist-client/modeller/{figure-v3-capability.d.ts → figure-capability-panel.d.ts} +4 -4
  68. package/dist-client/modeller/{figure-v3-capability.js → figure-capability-panel.js} +12 -12
  69. package/dist-client/modeller/figure-capability-panel.js.map +1 -0
  70. package/dist-client/modeller/{figure-v3-clips.d.ts → figure-clips.d.ts} +4 -4
  71. package/dist-client/modeller/{figure-v3-clips.js → figure-clips.js} +16 -16
  72. package/dist-client/modeller/figure-clips.js.map +1 -0
  73. package/dist-client/modeller/{figure-v3-controls.d.ts → figure-controls.d.ts} +5 -5
  74. package/dist-client/modeller/{figure-v3-controls.js → figure-controls.js} +16 -16
  75. package/dist-client/modeller/figure-controls.js.map +1 -0
  76. package/dist-client/modeller/{v3-figure-facts.d.ts → figure-facts.d.ts} +5 -5
  77. package/dist-client/modeller/{v3-figure-facts.js → figure-facts.js} +5 -5
  78. package/dist-client/modeller/figure-facts.js.map +1 -0
  79. package/dist-client/modeller/{figure-v3-first-save.d.ts → figure-first-save.d.ts} +1 -1
  80. package/dist-client/modeller/{figure-v3-first-save.js → figure-first-save.js} +11 -11
  81. package/dist-client/modeller/figure-first-save.js.map +1 -0
  82. package/dist-client/modeller/figure-history-panel.d.ts +1 -1
  83. package/dist-client/modeller/figure-history-panel.js.map +1 -1
  84. package/dist-client/modeller/{figure-v3-links.d.ts → figure-links.d.ts} +5 -5
  85. package/dist-client/modeller/{figure-v3-links.js → figure-links.js} +24 -24
  86. package/dist-client/modeller/figure-links.js.map +1 -0
  87. package/dist-client/modeller/{figure-v3-material.d.ts → figure-material-panel.d.ts} +9 -9
  88. package/dist-client/modeller/{figure-v3-material.js → figure-material-panel.js} +19 -19
  89. package/dist-client/modeller/figure-material-panel.js.map +1 -0
  90. package/dist-client/modeller/{figure-v3-parts.d.ts → figure-parts.d.ts} +12 -12
  91. package/dist-client/modeller/{figure-v3-parts.js → figure-parts.js} +14 -14
  92. package/dist-client/modeller/figure-parts.js.map +1 -0
  93. package/dist-client/modeller/{figure-v3-preview.d.ts → figure-preview.d.ts} +4 -4
  94. package/dist-client/modeller/{figure-v3-preview.js → figure-preview.js} +21 -21
  95. package/dist-client/modeller/figure-preview.js.map +1 -0
  96. package/dist-client/modeller/{figure-v3-properties.d.ts → figure-properties.d.ts} +8 -8
  97. package/dist-client/modeller/{figure-v3-properties.js → figure-properties.js} +25 -25
  98. package/dist-client/modeller/figure-properties.js.map +1 -0
  99. package/dist-client/modeller/{figure-v3-recipe-catalog.d.ts → figure-recipe-catalog.d.ts} +4 -4
  100. package/dist-client/modeller/{figure-v3-recipe-catalog.js → figure-recipe-catalog.js} +21 -21
  101. package/dist-client/modeller/figure-recipe-catalog.js.map +1 -0
  102. package/dist-client/modeller/{figure-v3-verdict.d.ts → figure-verdict.d.ts} +2 -2
  103. package/dist-client/modeller/{figure-v3-verdict.js → figure-verdict.js} +26 -26
  104. package/dist-client/modeller/figure-verdict.js.map +1 -0
  105. package/dist-client/modeller/{v3-first-save.js → first-save.js} +1 -1
  106. package/dist-client/modeller/first-save.js.map +1 -0
  107. package/dist-client/modeller/gate-findings.d.ts +2 -2
  108. package/dist-client/modeller/gate-findings.js +2 -2
  109. package/dist-client/modeller/gate-findings.js.map +1 -1
  110. package/dist-client/modeller/{v3-gizmo.d.ts → gizmo.d.ts} +5 -5
  111. package/dist-client/modeller/{v3-gizmo.js → gizmo.js} +3 -3
  112. package/dist-client/modeller/gizmo.js.map +1 -0
  113. package/dist-client/modeller/{v3-help.js → help.js} +1 -1
  114. package/dist-client/modeller/help.js.map +1 -0
  115. package/dist-client/modeller/joint-drag.d.ts +19 -0
  116. package/dist-client/modeller/{v3-joint-drag.js → joint-drag.js} +4 -4
  117. package/dist-client/modeller/joint-drag.js.map +1 -0
  118. package/dist-client/modeller/{v3-joint-fan.d.ts → joint-fan.d.ts} +3 -3
  119. package/dist-client/modeller/{v3-joint-fan.js → joint-fan.js} +6 -6
  120. package/dist-client/modeller/joint-fan.js.map +1 -0
  121. package/dist-client/modeller/{v3-keys.js → keys.js} +1 -1
  122. package/dist-client/modeller/keys.js.map +1 -0
  123. package/dist-client/modeller/{v3-links.d.ts → links.d.ts} +48 -48
  124. package/dist-client/modeller/{v3-links.js → links.js} +15 -15
  125. package/dist-client/modeller/links.js.map +1 -0
  126. package/dist-client/modeller/{v3-live.d.ts → live.d.ts} +6 -6
  127. package/dist-client/modeller/{v3-live.js → live.js} +5 -5
  128. package/dist-client/modeller/live.js.map +1 -0
  129. package/dist-client/modeller/{v3-maturity.d.ts → maturity.d.ts} +26 -26
  130. package/dist-client/modeller/{v3-maturity.js → maturity.js} +28 -28
  131. package/dist-client/modeller/maturity.js.map +1 -0
  132. package/dist-client/modeller/modeller-route.d.ts +1 -1
  133. package/dist-client/modeller/modeller-route.js +1 -1
  134. package/dist-client/modeller/modeller-route.js.map +1 -1
  135. package/dist-client/modeller/{v3-occupancy.d.ts → occupancy.d.ts} +4 -4
  136. package/dist-client/modeller/{v3-occupancy.js → occupancy.js} +6 -6
  137. package/dist-client/modeller/occupancy.js.map +1 -0
  138. package/dist-client/modeller/palette.d.ts +7 -0
  139. package/dist-client/modeller/{v3-palette.js → palette.js} +1 -1
  140. package/dist-client/modeller/palette.js.map +1 -0
  141. package/dist-client/modeller/{v3-preview-model.d.ts → preview-model.d.ts} +3 -3
  142. package/dist-client/modeller/{v3-preview-model.js → preview-model.js} +6 -6
  143. package/dist-client/modeller/preview-model.js.map +1 -0
  144. package/dist-client/modeller/{v3-product-session.d.ts → product-session.d.ts} +56 -56
  145. package/dist-client/modeller/{v3-product-session.js → product-session.js} +7 -7
  146. package/dist-client/modeller/product-session.js.map +1 -0
  147. package/dist-client/modeller/{v3-recipe-source.d.ts → recipe-source.d.ts} +2 -2
  148. package/dist-client/modeller/{v3-recipe-source.js → recipe-source.js} +3 -3
  149. package/dist-client/modeller/recipe-source.js.map +1 -0
  150. package/dist-client/modeller/{v3-recipes.d.ts → recipes.d.ts} +7 -7
  151. package/dist-client/modeller/{v3-recipes.js → recipes.js} +4 -4
  152. package/dist-client/modeller/recipes.js.map +1 -0
  153. package/dist-client/modeller/{v3-refusals.js → refusals.js} +1 -1
  154. package/dist-client/modeller/refusals.js.map +1 -0
  155. package/dist-client/modeller/{v3-renderer.d.ts → renderer.d.ts} +6 -6
  156. package/dist-client/modeller/{v3-renderer.js → renderer.js} +13 -13
  157. package/dist-client/modeller/renderer.js.map +1 -0
  158. package/dist-client/modeller/{v3-stage-model.d.ts → stage-model.d.ts} +7 -7
  159. package/dist-client/modeller/{v3-stage-model.js → stage-model.js} +5 -5
  160. package/dist-client/modeller/stage-model.js.map +1 -0
  161. package/dist-client/modeller/thumbnail.d.ts +3 -0
  162. package/dist-client/modeller/{v3-thumbnail.js → thumbnail.js} +6 -6
  163. package/dist-client/modeller/thumbnail.js.map +1 -0
  164. package/dist-client/pages/figure-list-page.d.ts +1 -1
  165. package/dist-client/pages/figure-list-page.js +4 -4
  166. package/dist-client/pages/figure-list-page.js.map +1 -1
  167. package/dist-client/pages/{figure-v3-modeller-page.d.ts → figure-modeller-page.d.ts} +10 -10
  168. package/dist-client/pages/{figure-v3-modeller-page.js → figure-modeller-page.js} +42 -42
  169. package/dist-client/pages/figure-modeller-page.js.map +1 -0
  170. package/dist-client/route.d.ts +1 -1
  171. package/dist-client/route.js +1 -5
  172. package/dist-client/route.js.map +1 -1
  173. package/dist-client/tsconfig.tsbuildinfo +1 -1
  174. package/docs/product-cutover.md +25 -0
  175. package/package.json +5 -5
  176. package/test/{v3-ai-proposal.test.ts → ai-proposal.test.ts} +6 -6
  177. package/test/{v3-align.test.ts → align.test.ts} +8 -8
  178. package/test/browser/modeller-page.js +30 -30
  179. package/test/browser/modeller.check.mjs +14 -14
  180. package/test/browser/serve.mjs +1 -1
  181. package/test/browser/thumbnail-page.js +6 -6
  182. package/test/{v3-clips.test.ts → clips.test.ts} +18 -18
  183. package/test/{v3-controls.test.ts → controls.test.ts} +15 -15
  184. package/test/{v3-fields.test.ts → fields.test.ts} +13 -13
  185. package/test/figure-assistant-surface.test.ts +3 -3
  186. package/test/{v3-first-save.test.ts → first-save.test.ts} +10 -10
  187. package/test/fixtures/joint-column.json +2 -2
  188. package/test/fixtures/joint-roller.json +2 -2
  189. package/test/fixtures/robot-arm-6dof.json +2 -2
  190. package/test/{v3-gizmo.test.ts → gizmo.test.ts} +33 -33
  191. package/test/{v3-joint-drag.test.ts → joint-drag.test.ts} +17 -17
  192. package/test/{v3-joint-fan.test.ts → joint-fan.test.ts} +18 -18
  193. package/test/joints.ts +6 -6
  194. package/test/{v3-keys.test.ts → keys.test.ts} +2 -2
  195. package/test/{v3-layout.test.ts → layout.test.ts} +8 -8
  196. package/test/{v3-links.test.ts → links.test.ts} +201 -201
  197. package/test/{v3-live.test.ts → live.test.ts} +18 -18
  198. package/test/{v3-material.test.ts → material.test.ts} +12 -12
  199. package/test/{v3-maturity.test.ts → maturity.test.ts} +74 -74
  200. package/test/modeller-route.test.ts +5 -6
  201. package/test/{v3-palette-icons.test.ts → palette-icons.test.ts} +1 -1
  202. package/test/{v3-parts-wiring.test.ts → parts-wiring.test.ts} +5 -5
  203. package/test/{v3-preview.test.ts → preview.test.ts} +12 -12
  204. package/test/{v3-product-session.test.ts → product-session.test.ts} +17 -17
  205. package/test/{v3-product-write.test.ts → product-write.test.ts} +20 -20
  206. package/test/{v3-properties.test.ts → properties.test.ts} +24 -24
  207. package/test/{v3-recipes.test.ts → recipes.test.ts} +9 -9
  208. package/test/{v3-refusals.test.ts → refusals.test.ts} +43 -43
  209. package/test/{v3-release-panel.test.ts → release-panel.test.ts} +21 -21
  210. package/test/renderer.test.ts +24 -0
  211. package/test/resolve-ts-siblings.mjs +1 -1
  212. package/test/{v3-scene-canvas.test.ts → scene-canvas.test.ts} +6 -6
  213. package/test/{v3-stage-model.test.ts → stage-model.test.ts} +5 -5
  214. package/test/{v3-theme.test.ts → theme.test.ts} +4 -4
  215. package/test/{v3-thumbnail.test.ts → thumbnail.test.ts} +4 -4
  216. package/test/{v3-verdict.test.ts → verdict.test.ts} +17 -17
  217. package/test/{v3-view.test.ts → view.test.ts} +2 -2
  218. package/things-factory.config.js +2 -3
  219. package/translations/en.json +2 -2
  220. package/translations/ja.json +2 -2
  221. package/translations/ko.json +2 -2
  222. package/translations/ms.json +2 -2
  223. package/translations/zh.json +2 -2
  224. package/dist-client/graphql/v3-store.d.ts +0 -3
  225. package/dist-client/graphql/v3-store.js.map +0 -1
  226. package/dist-client/modeller/figure-v3-capability.js.map +0 -1
  227. package/dist-client/modeller/figure-v3-clips.js.map +0 -1
  228. package/dist-client/modeller/figure-v3-controls.js.map +0 -1
  229. package/dist-client/modeller/figure-v3-first-save.js.map +0 -1
  230. package/dist-client/modeller/figure-v3-links.js.map +0 -1
  231. package/dist-client/modeller/figure-v3-material.js.map +0 -1
  232. package/dist-client/modeller/figure-v3-parts.js.map +0 -1
  233. package/dist-client/modeller/figure-v3-preview.js.map +0 -1
  234. package/dist-client/modeller/figure-v3-properties.js.map +0 -1
  235. package/dist-client/modeller/figure-v3-recipe-catalog.js.map +0 -1
  236. package/dist-client/modeller/figure-v3-verdict.js.map +0 -1
  237. package/dist-client/modeller/v3-ai-proposal.js.map +0 -1
  238. package/dist-client/modeller/v3-align.js.map +0 -1
  239. package/dist-client/modeller/v3-canvas.js.map +0 -1
  240. package/dist-client/modeller/v3-clips.js.map +0 -1
  241. package/dist-client/modeller/v3-controls.js.map +0 -1
  242. package/dist-client/modeller/v3-editor.js.map +0 -1
  243. package/dist-client/modeller/v3-fields.js.map +0 -1
  244. package/dist-client/modeller/v3-figure-facts.js.map +0 -1
  245. package/dist-client/modeller/v3-first-save.js.map +0 -1
  246. package/dist-client/modeller/v3-gizmo.js.map +0 -1
  247. package/dist-client/modeller/v3-help.js.map +0 -1
  248. package/dist-client/modeller/v3-joint-drag.d.ts +0 -19
  249. package/dist-client/modeller/v3-joint-drag.js.map +0 -1
  250. package/dist-client/modeller/v3-joint-fan.js.map +0 -1
  251. package/dist-client/modeller/v3-keys.js.map +0 -1
  252. package/dist-client/modeller/v3-links.js.map +0 -1
  253. package/dist-client/modeller/v3-live.js.map +0 -1
  254. package/dist-client/modeller/v3-maturity.js.map +0 -1
  255. package/dist-client/modeller/v3-occupancy.js.map +0 -1
  256. package/dist-client/modeller/v3-palette.d.ts +0 -7
  257. package/dist-client/modeller/v3-palette.js.map +0 -1
  258. package/dist-client/modeller/v3-preview-model.js.map +0 -1
  259. package/dist-client/modeller/v3-product-session.js.map +0 -1
  260. package/dist-client/modeller/v3-recipe-source.js.map +0 -1
  261. package/dist-client/modeller/v3-recipes.js.map +0 -1
  262. package/dist-client/modeller/v3-refusals.js.map +0 -1
  263. package/dist-client/modeller/v3-renderer.js.map +0 -1
  264. package/dist-client/modeller/v3-stage-model.js.map +0 -1
  265. package/dist-client/modeller/v3-thumbnail.d.ts +0 -3
  266. package/dist-client/modeller/v3-thumbnail.js.map +0 -1
  267. package/dist-client/pages/figure-v3-modeller-page.js.map +0 -1
  268. package/dist-client/tsconfig.chk.tsbuildinfo +0 -1
  269. package/dist-client/tsconfig.fui.tsbuildinfo +0 -1
  270. package/dist-client/tsconfig.scratch-fm.tsbuildinfo +0 -1
  271. package/docs/v3-product-cutover.md +0 -25
  272. package/test/v3-renderer.test.ts +0 -24
  273. /package/client/modeller/{v3-fields.ts → fields.ts} +0 -0
  274. /package/client/modeller/{v3-first-save.ts → first-save.ts} +0 -0
  275. /package/client/modeller/{v3-help.ts → help.ts} +0 -0
  276. /package/client/modeller/{v3-keys.ts → keys.ts} +0 -0
  277. /package/client/modeller/{v3-refusals.ts → refusals.ts} +0 -0
  278. /package/dist-client/modeller/{v3-fields.d.ts → fields.d.ts} +0 -0
  279. /package/dist-client/modeller/{v3-first-save.d.ts → first-save.d.ts} +0 -0
  280. /package/dist-client/modeller/{v3-help.d.ts → help.d.ts} +0 -0
  281. /package/dist-client/modeller/{v3-keys.d.ts → keys.d.ts} +0 -0
  282. /package/dist-client/modeller/{v3-refusals.d.ts → refusals.d.ts} +0 -0
@@ -1,9 +1,9 @@
1
- import { V3_FACES, v3ShapeFaces, v3PartsExtentOf, compileV3Asset, compileV3Graph, v3FollowOf, proposeV3Proportion, defaultInstanceSizeRange, foldInstanceSizeRange, v3AttachmentsOf, v3BindingsOf, v3InstanceSizeLimitsOf } from '@hatiolab/figure-model'
2
- import type { V3Follow, V3SizeRange } from '@hatiolab/figure-model'
3
- import type { V3Asset, V3BindingPlace, V3Face, V3Joint } from '@hatiolab/figure-model'
1
+ import { FIGURE_FACES, figureShapeFaces, figurePartsExtentOf, compileFigureAsset, compileFigureGraph, figureFollowOf, proposeFigureProportion, defaultInstanceSizeRange, foldInstanceSizeRange, figureAttachmentsOf, figureBindingsOf, figureInstanceSizeLimitsOf } from '@hatiolab/figure-model'
2
+ import type { FigureFollow, FigureSizeRange } from '@hatiolab/figure-model'
3
+ import type { FigureAsset, FigureBindingPlace, FigureFace, FigureJoint } from '@hatiolab/figure-model'
4
4
 
5
5
  /*
6
- * What a V3 part is tied to — the readers behind the parts' size response, fastening and motion sections. Kept apart from the element so they can be tested without a browser.
6
+ * What a part is tied to — the readers behind the parts' size response, fastening and motion sections. Kept apart from the element so they can be tested without a browser.
7
7
  */
8
8
 
9
9
  export type Axis = 'x' | 'y' | 'z'
@@ -15,11 +15,11 @@ interface Node {
15
15
  args: string[]
16
16
  outputs: Record<string, string>
17
17
  }
18
- const modelOf = (asset: V3Asset) =>
18
+ const modelOf = (asset: FigureAsset) =>
19
19
  asset.document.model as unknown as { nodes: Node[]; inputs: Array<{ id: string; role?: string; unit?: string; min?: number; max?: number }>; constants: Array<{ id: string; value: number }> }
20
20
 
21
- /** What one dimension of a part is worked out from (figure-model's `V3Follow`). */
22
- export type Follow = V3Follow
21
+ /** What one dimension of a part is worked out from (figure-model's `FigureFollow`). */
22
+ export type Follow = FigureFollow
23
23
 
24
24
  /**
25
25
  * `link-dimension` routes a part's dimension through `<part>.dimension.<axis>` and points its first argument at the
@@ -27,16 +27,16 @@ export type Follow = V3Follow
27
27
  * instance size (`size.<axis>`), another part's dimension (`<part>.dimension.<axis>.value`) or a declared input.
28
28
  */
29
29
  /** What one measure of a part is worked out from, read back from the graph (figure-model's reader, one copy). */
30
- export function followOf(asset: V3Asset, part: string, axis: Axis): Follow {
31
- return v3FollowOf(asset, part, axis)
30
+ export function followOf(asset: FigureAsset, part: string, axis: Axis): Follow {
31
+ return figureFollowOf(asset, part, axis)
32
32
  }
33
33
 
34
34
  /** Whether the asset declares an instance size on an axis — only then can a dimension follow it. */
35
- export const hasInstanceSize = (asset: V3Asset, axis: Axis) => modelOf(asset).inputs.some(i => i.id === `size.${axis}` && i.role === 'design')
35
+ export const hasInstanceSize = (asset: FigureAsset, axis: Axis) => modelOf(asset).inputs.some(i => i.id === `size.${axis}` && i.role === 'design')
36
36
 
37
37
  /** The part this one is fastened to, or `null`. The mounting plane counts as fastened (the model names no part). */
38
- export function fastenedTo(asset: V3Asset, part: string): string | null {
39
- return v3AttachmentsOf(asset)[part] ?? null
38
+ export function fastenedTo(asset: FigureAsset, part: string): string | null {
39
+ return figureAttachmentsOf(asset)[part] ?? null
40
40
  }
41
41
 
42
42
  /**
@@ -44,7 +44,7 @@ export function fastenedTo(asset: V3Asset, part: string): string | null {
44
44
  * it; a part standing on the plane had read as fastened to nothing, so the form offered no way to move it and sent
45
45
  * no replace -- the fastening was refused as already made (the door's post, 2026-09-25).
46
46
  */
47
- export function heldBy(asset: V3Asset, part: string): { part: string } | { plane: true } | null {
47
+ export function heldBy(asset: FigureAsset, part: string): { part: string } | { plane: true } | null {
48
48
  const record = asset.joints?.find(j => j.body1.part === part)
49
49
  if (record) return 'plane' in record.body0 ? { plane: true } : { part: record.body0.part }
50
50
  const to = fastenedTo(asset, part)
@@ -52,7 +52,7 @@ export function heldBy(asset: V3Asset, part: string): { part: string } | { plane
52
52
  }
53
53
 
54
54
  /** Whether a dimension of this part can follow something — box-shaped, whose three sizes are X, Y and Z. */
55
- export function canFollow(asset: V3Asset, part: string): boolean {
55
+ export function canFollow(asset: FigureAsset, part: string): boolean {
56
56
  return followableAxes(asset, part).length > 0
57
57
  }
58
58
 
@@ -60,7 +60,7 @@ export function canFollow(asset: V3Asset, part: string): boolean {
60
60
  * The axes whose size can follow something, by the shape's own measures: a box's X · Y · Z; a cylinder's radius (read
61
61
  * as X) and length (Y) -- its shape takes those two, so it has no Z of its own.
62
62
  */
63
- export function followableAxes(asset: V3Asset, part: string): Axis[] {
63
+ export function followableAxes(asset: FigureAsset, part: string): Axis[] {
64
64
  const shape = modelOf(asset).nodes.find(n => n.id === `${part}.shape`)
65
65
  if (!shape) return []
66
66
  /* A door frame's first three measures are its width, height and depth, as a box's (figure-model portal-profile@2). */
@@ -70,12 +70,12 @@ export function followableAxes(asset: V3Asset, part: string): Axis[] {
70
70
  }
71
71
 
72
72
  /** What a part's own measure on an axis is now (a box's side, a cylinder's radius or length), at the design as it stands. */
73
- export function dimensionNow(asset: V3Asset, part: string, axis: Axis): number | undefined {
73
+ export function dimensionNow(asset: FigureAsset, part: string, axis: Axis): number | undefined {
74
74
  const m = modelOf(asset)
75
75
  const ref = m.nodes.find(n => n.id === `${part}.shape`)?.args[AXES.indexOf(axis)]
76
76
  if (!ref) return undefined
77
77
  try {
78
- const values = compileV3Graph(asset.document.model as never).evaluate({ ...asset.designInputs, ...asset.stateDefaults }).values as Record<string, number>
78
+ const values = compileFigureGraph(asset.document.model as never).evaluate({ ...asset.designInputs, ...asset.stateDefaults }).values as Record<string, number>
79
79
  const value = values[ref]
80
80
  return typeof value === 'number' && Number.isFinite(value) ? value : undefined
81
81
  } catch {
@@ -87,19 +87,19 @@ export function dimensionNow(asset: V3Asset, part: string, axis: Axis): number |
87
87
  * The flat faces a part's shape declares, by name -- figure-model's shape definitions are the one place they are
88
88
  * written (a portal's opening sides as well as its outer faces). A sphere has none.
89
89
  */
90
- export function facesOf(asset: V3Asset, part: string): string[] {
90
+ export function facesOf(asset: FigureAsset, part: string): string[] {
91
91
  const shape = modelOf(asset).nodes.find(n => n.id === `${part}.shape`)
92
- return Object.keys((shape && v3ShapeFaces(shape.op)) ?? {})
92
+ return Object.keys((shape && figureShapeFaces(shape.op)) ?? {})
93
93
  }
94
94
 
95
95
  /** The axis a face of a part faces along, from the same definitions. */
96
- export function faceAxisOf(asset: V3Asset, part: string, face: string): Axis | undefined {
96
+ export function faceAxisOf(asset: FigureAsset, part: string, face: string): Axis | undefined {
97
97
  const shape = modelOf(asset).nodes.find(n => n.id === `${part}.shape`)
98
- return (shape && v3ShapeFaces(shape.op)?.[face]?.axis) as Axis | undefined
98
+ return (shape && figureShapeFaces(shape.op)?.[face]?.axis) as Axis | undefined
99
99
  }
100
100
 
101
101
  /** Whether `attach` can take this part: any part whose shape has a flat face. */
102
- export function canFasten(asset: V3Asset, part: string): boolean {
102
+ export function canFasten(asset: FigureAsset, part: string): boolean {
103
103
  return facesOf(asset, part).length > 0
104
104
  }
105
105
 
@@ -110,16 +110,16 @@ const OUTER: Record<Axis, [string, string]> = { x: ['left', 'right'], y: ['botto
110
110
  * it is fastened fixed to another part and holds nothing. None for a part that is loose, moves, stands on the floor or
111
111
  * already repeats -- the command would refuse those, so they are not offered.
112
112
  */
113
- export function rowAxesOf(asset: V3Asset, part: string): Axis[] {
113
+ export function rowAxesOf(asset: FigureAsset, part: string): Axis[] {
114
114
  const joints = asset.joints ?? []
115
115
  const j = joints.find(o => o.body1.part === part)
116
116
  if (!j || j.type !== 'fixed' || j.repeat || !('part' in j.body0)) return []
117
117
  if (joints.some(o => 'part' in o.body0 && o.body0.part === part)) return []
118
- return AXES.filter(axis => axis !== V3_FACES[j.body1.face])
118
+ return AXES.filter(axis => axis !== FIGURE_FACES[j.body1.face])
119
119
  }
120
120
 
121
121
  /** The row a part is made into, as its fastening's record keeps it. */
122
- export const rowOf = (asset: V3Asset, part: string) => asset.joints?.find(o => o.body1.part === part)?.repeat
122
+ export const rowOf = (asset: FigureAsset, part: string) => asset.joints?.find(o => o.body1.part === part)?.repeat
123
123
 
124
124
  /** Where a part sits across the face it is fastened to, on one axis: centred, level with an edge, or a distance off centre. */
125
125
  /** `share`: the distance as a share of the figure's size on that axis, so it keeps its place when the figure is resized. */
@@ -134,11 +134,11 @@ export type Alignment = 'centre' | 'min' | 'max' | 'mm' | 'share'
134
134
  * The mounting plane of this figure, by its placement (ADR-0093): the floor or the ceiling is Y = 0 and a part stands
135
135
  * on it by its bottom or hangs from it by its top; a wall is Z = 0 and a part is fastened to it by its back.
136
136
  */
137
- export function mountingPlaneOf(asset: V3Asset): { normal: Axis; faces: V3Face[] } {
137
+ export function mountingPlaneOf(asset: FigureAsset): { normal: Axis; faces: FigureFace[] } {
138
138
  return asset.occupancy?.placement === 'wall' ? { normal: 'z', faces: ['back'] } : { normal: 'y', faces: ['bottom', 'top'] }
139
139
  }
140
140
 
141
- export function alignAxesOf(asset: V3Asset, part: string, target: { part: string; face: string } | 'plane', twisted = false): { axis: Axis; edges: boolean }[] {
141
+ export function alignAxesOf(asset: FigureAsset, part: string, target: { part: string; face: string } | 'plane', twisted = false): { axis: Axis; edges: boolean }[] {
142
142
  /* The plane has no edges, but a figure that declares its size has sides on it (figure-model 0.1.64). */
143
143
  if (target === 'plane') {
144
144
  const { normal } = mountingPlaneOf(asset)
@@ -153,7 +153,7 @@ export function alignAxesOf(asset: V3Asset, part: string, target: { part: string
153
153
  }
154
154
 
155
155
  /** The controls a part's showing can follow: the figure's state inputs, with their range and label. */
156
- export function visibilityControlsOf(asset: V3Asset): Array<{ id: string; unit: string; min: number; max: number; label: string }> {
156
+ export function visibilityControlsOf(asset: FigureAsset): Array<{ id: string; unit: string; min: number; max: number; label: string }> {
157
157
  const labels = (asset as unknown as { stateInputs?: Record<string, { label?: string }> }).stateInputs ?? {}
158
158
  return modelOf(asset)
159
159
  .inputs.filter(input => input.role === 'state')
@@ -161,7 +161,7 @@ export function visibilityControlsOf(asset: V3Asset): Array<{ id: string; unit:
161
161
  }
162
162
 
163
163
  /** When the part is drawn (figure-model `set-visibility`): always (null), or while a control is at least a value. */
164
- export function shownWhenOf(asset: V3Asset, part: string): { input: string; atLeast: number } | null {
164
+ export function shownWhenOf(asset: FigureAsset, part: string): { input: string; atLeast: number } | null {
165
165
  const look = asset.appearance.find(one => one.target === part) as { visibility?: string } | undefined
166
166
  if (!look?.visibility) return null
167
167
  const m = modelOf(asset)
@@ -171,11 +171,11 @@ export function shownWhenOf(asset: V3Asset, part: string): { input: string; atLe
171
171
  }
172
172
 
173
173
  /** Whether `part` hangs from `from`, through any number of fastenings. */
174
- export function hangsFrom(asset: V3Asset, part: string, from: string): boolean {
174
+ export function hangsFrom(asset: FigureAsset, part: string, from: string): boolean {
175
175
  const seen = new Set<string>()
176
176
  for (let at: string | undefined = part; at && !seen.has(at); ) {
177
177
  seen.add(at)
178
- const j = ((asset.joints ?? []) as V3Joint[]).find(o => o.body1.part === at)
178
+ const j = ((asset.joints ?? []) as FigureJoint[]).find(o => o.body1.part === at)
179
179
  at = j && 'part' in j.body0 ? (j.body0 as { part: string }).part : undefined
180
180
  if (at === from) return true
181
181
  }
@@ -189,7 +189,7 @@ export function hangsFrom(asset: V3Asset, part: string, from: string): boolean {
189
189
  * from there broke its turning in place (walk 1, 2026-09-26). Null for a part fastened to nothing.
190
190
  */
191
191
  export function fasteningOf(
192
- asset: V3Asset,
192
+ asset: FigureAsset,
193
193
  part: string
194
194
  ): {
195
195
  face: string
@@ -238,7 +238,7 @@ export function fasteningOf(
238
238
  * its frame slid into it (2026-09-26). Left centred where it already is, and where the target stands turned.
239
239
  */
240
240
  export function placeKeptOf(
241
- asset: V3Asset,
241
+ asset: FigureAsset,
242
242
  part: string,
243
243
  target: { part: string; face: string } | 'plane',
244
244
  twisted = false
@@ -246,7 +246,7 @@ export function placeKeptOf(
246
246
  const kept = { align: {} as Partial<Record<Axis, Alignment>>, alignMm: {} as Partial<Record<Axis, number>> }
247
247
  let geometry
248
248
  try {
249
- geometry = compileV3Asset(asset).evaluate().geometry as unknown as Array<{ id: string; pose?: { r: number[][]; t: number[] } }>
249
+ geometry = compileFigureAsset(asset).evaluate().geometry as unknown as Array<{ id: string; pose?: { r: number[][]; t: number[] } }>
250
250
  } catch {
251
251
  return kept
252
252
  }
@@ -272,7 +272,7 @@ export function placeKeptOf(
272
272
 
273
273
  /** The `align` of an attach command from the form's choices: only the axes across that face, and centred ones left out. */
274
274
  export function alignOf(
275
- asset: V3Asset,
275
+ asset: FigureAsset,
276
276
  part: string,
277
277
  target: { part: string; face: string } | 'plane',
278
278
  how: Partial<Record<Axis, Alignment>>,
@@ -294,7 +294,7 @@ export function alignOf(
294
294
  /**
295
295
  * The axes on which the part's position is worked out from other values rather than being its own number. `fix-position` makes one its own number where it is now.
296
296
  */
297
- export function positionsWorkedOut(asset: V3Asset, part: string): Axis[] {
297
+ export function positionsWorkedOut(asset: FigureAsset, part: string): Axis[] {
298
298
  const m = modelOf(asset)
299
299
  const pose = m.nodes.find(n => n.id === `${part}.pose`)
300
300
  if (!pose || pose.op !== 'rigid@1' || fastenedTo(asset, part)) return []
@@ -307,7 +307,7 @@ export function positionsWorkedOut(asset: V3Asset, part: string): Axis[] {
307
307
  * Whether the part's position on an axis is a share of the instance size (`scale-position`): `size.<axis> × share`.
308
308
  * Such a position is worked out too, but it already grows with the figure, so it is not offered again.
309
309
  */
310
- export function positionIsShare(asset: V3Asset, part: string, axis: Axis): boolean {
310
+ export function positionIsShare(asset: FigureAsset, part: string, axis: Axis): boolean {
311
311
  const m = modelOf(asset)
312
312
  const ref = m.nodes.find(n => n.id === `${part}.pose`)?.args[AXES.indexOf(axis)]
313
313
  const writer = ref ? m.nodes.find(n => Object.values(n.outputs).includes(ref)) : undefined
@@ -325,7 +325,7 @@ export interface Motion {
325
325
  travel?: { part: string; axis: string; plus?: number }
326
326
  }
327
327
 
328
- export function motionOf(asset: V3Asset, part: string): Motion | undefined {
328
+ export function motionOf(asset: FigureAsset, part: string): Motion | undefined {
329
329
  const m = modelOf(asset)
330
330
  const node = m.nodes.find(n => n.id === `${part}.motion`)
331
331
  if (!node) return undefined
@@ -377,7 +377,7 @@ export interface MotionForm {
377
377
  * travels by, what it follows -- rather than taken away and made again. Taking it away is refused while another joint
378
378
  * follows it, which left a leader's stroke fixed for good (the telescopic conveyor, 2026-09-25).
379
379
  */
380
- export function motionFormOf(joint: V3Joint): MotionForm {
380
+ export function motionFormOf(joint: FigureJoint): MotionForm {
381
381
  const kind: MotionForm['kind'] = joint.type === 'prismatic' ? 'slide' : joint.lowerLimit === undefined && joint.upperLimit === undefined && !joint.mimic ? 'continuous' : 'turn'
382
382
  const travel = joint.travel?.source && 'part' in joint.travel.source ? `${joint.travel.source.part}:${joint.travel.source.axis}` : ''
383
383
  return {
@@ -398,7 +398,7 @@ export function motionFormOf(joint: V3Joint): MotionForm {
398
398
  * The joints a part's joint can move with (URDF's mimic): a joint that moves the same way — a slide follows a slide, a
399
399
  * turn a turn — and has a control of its own, since a follower follows the joint that is driven.
400
400
  */
401
- export function leadersFor(asset: V3Asset, part: string, kind: MotionForm['kind']): V3Joint[] {
401
+ export function leadersFor(asset: FigureAsset, part: string, kind: MotionForm['kind']): FigureJoint[] {
402
402
  return (asset.joints ?? []).filter(j => j.body1.part !== part && j.type !== 'fixed' && !j.mimic && (j.type === 'prismatic') === (kind === 'slide'))
403
403
  }
404
404
 
@@ -407,7 +407,7 @@ export function leadersFor(asset: V3Asset, part: string, kind: MotionForm['kind'
407
407
  * a turn without end, as in USD) and a control; a follower gets the leader, the multiplier and the offset, and no
408
408
  * control or limits of its own — its range is the leader's times the multiplier.
409
409
  */
410
- export function motionJoint(joint: V3Joint, m: MotionForm, part: string): V3Joint {
410
+ export function motionJoint(joint: FigureJoint, m: MotionForm, part: string): FigureJoint {
411
411
  const moving = {
412
412
  id: joint.id,
413
413
  body0: joint.body0,
@@ -441,7 +441,7 @@ export function choiceOf(follow: Follow): string {
441
441
  }
442
442
 
443
443
  /** The faces a place can sit on for this part: a box's six, a rounded box's top and bottom, none for a round body. */
444
- export function placeFacesOf(asset: V3Asset, part: string): V3Face[] {
444
+ export function placeFacesOf(asset: FigureAsset, part: string): FigureFace[] {
445
445
  const shape = modelOf(asset).nodes.find(n => n.id === `${part}.shape`)
446
446
  if (shape?.op === 'box-shape@1') return ['left', 'right', 'bottom', 'top', 'back', 'front']
447
447
  if (shape?.op === 'rounded-box@1') return ['bottom', 'top']
@@ -449,12 +449,12 @@ export function placeFacesOf(asset: V3Asset, part: string): V3Face[] {
449
449
  }
450
450
 
451
451
  /** The places things are held that sit on this part. */
452
- export function placesOn(asset: V3Asset, part: string): V3BindingPlace[] {
453
- return v3BindingsOf(asset).filter(one => one.part === part)
452
+ export function placesOn(asset: FigureAsset, part: string): FigureBindingPlace[] {
453
+ return figureBindingsOf(asset).filter(one => one.part === part)
454
454
  }
455
455
 
456
456
  /** An id for a new place on this part, not yet taken: `<part>-<role>`, then `-2`, `-3`. */
457
- export function placeIdFor(asset: V3Asset, part: string, role: 'seat' | 'grip'): string {
457
+ export function placeIdFor(asset: FigureAsset, part: string, role: 'seat' | 'grip'): string {
458
458
  const taken = new Set(asset.document.capabilities.bindings.map(b => b.id))
459
459
  const base = `${part}-${role}`
460
460
  if (!taken.has(base)) return base
@@ -467,7 +467,7 @@ export function placeIdFor(asset: V3Asset, part: string, role: 'seat' | 'grip'):
467
467
  * Whether a board will hand this figure anything: a place is a slot only on a figure that declares it holds things
468
468
  * (`Capacity`, or `FlowNode`, which includes it). Without it the places are declared and nothing arrives.
469
469
  */
470
- export const holdsThings = (asset: V3Asset) => (asset.document.capabilities.names ?? []).some(n => n === 'Capacity' || n === 'FlowNode')
470
+ export const holdsThings = (asset: FigureAsset) => (asset.document.capabilities.names ?? []).some(n => n === 'Capacity' || n === 'FlowNode')
471
471
 
472
472
  /** What `accepts` a person typed: names split on commas, trimmed, blanks and repeats dropped. */
473
473
  export const acceptsOf = (typed: string) => [...new Set(typed.split(',').map(one => one.trim()).filter(Boolean))]
@@ -478,9 +478,9 @@ export const acceptsOf = (typed: string) => [...new Set(typed.split(',').map(one
478
478
  * A range measured when a part filled what the others left (ROBOT_ARM: Y from 1,854 mm) stays narrow after the part is
479
479
  * made to grow with the figure; measuring again gives the figure its whole range back. Nothing when no size is declared.
480
480
  */
481
- export function instanceRangeOf(asset: V3Asset): { declared: V3SizeRange; measured: V3SizeRange } | undefined {
481
+ export function instanceRangeOf(asset: FigureAsset): { declared: FigureSizeRange; measured: FigureSizeRange } | undefined {
482
482
  const inputs = modelOf(asset).inputs
483
- const declared = {} as V3SizeRange
483
+ const declared = {} as FigureSizeRange
484
484
  const authored = {} as Record<Axis, number>
485
485
  for (const axis of AXES) {
486
486
  const input = inputs.find(i => i.id === `size.${axis}` && i.role === 'design')
@@ -490,7 +490,7 @@ export function instanceRangeOf(asset: V3Asset): { declared: V3SizeRange; measur
490
490
  authored[axis] = at
491
491
  }
492
492
  const start = defaultInstanceSizeRange(authored)
493
- const measured = foldInstanceSizeRange(start, v3InstanceSizeLimitsOf(asset, start)).range
493
+ const measured = foldInstanceSizeRange(start, figureInstanceSizeLimitsOf(asset, start)).range
494
494
  return { declared, measured }
495
495
  }
496
496
 
@@ -500,13 +500,13 @@ export function instanceRangeOf(asset: V3Asset): { declared: V3SizeRange; measur
500
500
  * size or has nothing to measure. Without a declared size a board cannot resize the figure, and no part is offered
501
501
  * to follow its size -- every figure made in the modeller was left there (user, 2026-09-25).
502
502
  */
503
- export function instanceRangeToDeclare(asset: V3Asset): { range: V3SizeRange; at: Record<Axis, number> } | undefined {
503
+ export function instanceRangeToDeclare(asset: FigureAsset): { range: FigureSizeRange; at: Record<Axis, number> } | undefined {
504
504
  if (instanceRangeOf(asset) || !asset.appearance.length) return undefined
505
505
  /* The parts as they rest -- not the room their joints swing them through, which declared a door 8208 mm every way. */
506
- const at = v3PartsExtentOf(asset) as Record<Axis, number>
506
+ const at = figurePartsExtentOf(asset) as Record<Axis, number>
507
507
  if (AXES.some(axis => !(at[axis] > 0))) return undefined
508
508
  const start = defaultInstanceSizeRange(at)
509
- return { range: foldInstanceSizeRange(start, v3InstanceSizeLimitsOf(asset, start)).range, at }
509
+ return { range: foldInstanceSizeRange(start, figureInstanceSizeLimitsOf(asset, start)).range, at }
510
510
  }
511
511
 
512
512
  /** Whether measuring again would change the declared range (to a micrometre). */
@@ -515,7 +515,7 @@ export function instanceRangeToDeclare(asset: V3Asset): { range: V3SizeRange; at
515
515
  * product (a gantry spans metres, not 30 cm to 29 m), and measuring only ever widens them. Nothing when the typed
516
516
  * value is not a number; whether the figure holds there is the command's to say.
517
517
  */
518
- export function rangeWith(declared: V3SizeRange, axis: Axis, bound: 'min' | 'max', value: number): V3SizeRange | undefined {
518
+ export function rangeWith(declared: FigureSizeRange, axis: Axis, bound: 'min' | 'max', value: number): FigureSizeRange | undefined {
519
519
  if (!Number.isFinite(value)) return undefined
520
520
  const next = structuredClone(declared)
521
521
  next[axis][bound] = value
@@ -526,10 +526,10 @@ export function rangeWith(declared: V3SizeRange, axis: Axis, bound: 'min' | 'max
526
526
  * For a figure that grows by one ratio: how many of its lengths would follow the ratio, and which it leaves with their
527
527
  * own number (not those that follow another length -- they grow with it). Nothing for a figure of another sizing.
528
528
  */
529
- export function proportionToFollow(asset: V3Asset): { count: number; kept: string[] } | undefined {
529
+ export function proportionToFollow(asset: FigureAsset): { count: number; kept: string[] } | undefined {
530
530
  if (asset.sizing !== 'uniform') return undefined
531
531
  try {
532
- const plan = proposeV3Proportion(asset)
532
+ const plan = proposeFigureProportion(asset)
533
533
  return { count: plan.dimensions.length + plan.lengths.length, kept: plan.skipped.filter(s => !s.follows).map(s => s.what) }
534
534
  } catch {
535
535
  return undefined
@@ -537,10 +537,10 @@ export function proportionToFollow(asset: V3Asset): { count: number; kept: strin
537
537
  }
538
538
 
539
539
  /** A value of the figure as it stands, by its graph reference. */
540
- export function valueNow(asset: V3Asset, ref: string | undefined): number | undefined {
540
+ export function valueNow(asset: FigureAsset, ref: string | undefined): number | undefined {
541
541
  if (!ref) return undefined
542
542
  try {
543
- const values = compileV3Graph(asset.document.model as never).evaluate({ ...asset.designInputs, ...asset.stateDefaults }).values as Record<string, number>
543
+ const values = compileFigureGraph(asset.document.model as never).evaluate({ ...asset.designInputs, ...asset.stateDefaults }).values as Record<string, number>
544
544
  const value = values[ref]
545
545
  return typeof value === 'number' && Number.isFinite(value) ? value : undefined
546
546
  } catch {
@@ -548,7 +548,7 @@ export function valueNow(asset: V3Asset, ref: string | undefined): number | unde
548
548
  }
549
549
  }
550
550
 
551
- export function rangeDiffers(a: V3SizeRange, b: V3SizeRange): boolean {
551
+ export function rangeDiffers(a: FigureSizeRange, b: FigureSizeRange): boolean {
552
552
  return AXES.some(axis => Math.abs(a[axis].min - b[axis].min) > 1e-3 || Math.abs(a[axis].max - b[axis].max) > 1e-3)
553
553
  }
554
554
 
@@ -556,7 +556,7 @@ export function rangeDiffers(a: V3SizeRange, b: V3SizeRange): boolean {
556
556
  * Whether the figure is a mechanism -- a part turns about a joint. Such a figure should grow by one ratio (chief
557
557
  * architect's ruling 2026-09-24); the modeller proposes it, the author declares it.
558
558
  */
559
- export function turnsAboutAJoint(asset: V3Asset): boolean {
559
+ export function turnsAboutAJoint(asset: FigureAsset): boolean {
560
560
  return modelOf(asset).nodes.some(n => n.op === 'axis-turn@1')
561
561
  }
562
562
 
@@ -1,7 +1,7 @@
1
- import { compileV3Asset, editV3Part } from '@hatiolab/figure-model'
2
- import type { V3Asset, V3PartEdit } from '@hatiolab/figure-model'
1
+ import { compileFigureAsset, editFigurePart } from '@hatiolab/figure-model'
2
+ import type { FigureAsset, FigurePartEdit } from '@hatiolab/figure-model'
3
3
 
4
- import { drawableV3Parts, type V3RenderPart } from './v3-renderer.js'
4
+ import { drawableFigureParts, type FigureRenderPart } from './renderer.js'
5
5
 
6
6
  /*
7
7
  * The figure while a value is in hand: evaluated with the values being typed or dragged, drawn at once and written
@@ -18,13 +18,13 @@ export interface LiveValues {
18
18
  /** Input values in hand, design or state, by input id. */
19
19
  values: Record<string, number>
20
20
  /** A part edit in hand, not yet committed. */
21
- edit?: V3PartEdit
21
+ edit?: FigurePartEdit
22
22
  }
23
23
 
24
24
  export const NOTHING_LIVE: LiveValues = { values: {} }
25
25
 
26
26
  /** Known inputs with a number, split by what they are. An id the figure does not declare is dropped. */
27
- export function liveOverridesOf(asset: V3Asset, values: Record<string, number>): { design: Record<string, number>; state: Record<string, number> } {
27
+ export function liveOverridesOf(asset: FigureAsset, values: Record<string, number>): { design: Record<string, number>; state: Record<string, number> } {
28
28
  const roles = new Map(asset.document.model.inputs.map(i => [i.id, i.role]))
29
29
  const design: Record<string, number> = {},
30
30
  state: Record<string, number> = {}
@@ -48,13 +48,13 @@ export function isLive(live: LiveValues): boolean {
48
48
  * refuses): the canvas keeps the figure as it stands until the release, and the release reports why through the same
49
49
  * refusal every committed edit gets. A preview never invents a figure the commit would not make.
50
50
  */
51
- export function livePartsOf(asset: V3Asset, live: LiveValues): V3RenderPart[] | null {
51
+ export function livePartsOf(asset: FigureAsset, live: LiveValues): FigureRenderPart[] | null {
52
52
  if (!isLive(live)) return null
53
53
  const { design, state } = liveOverridesOf(asset, live.values)
54
54
  try {
55
- let next = live.edit ? editV3Part(asset, live.edit) : asset
55
+ let next = live.edit ? editFigurePart(asset, live.edit) : asset
56
56
  if (Object.keys(design).length) next = { ...next, designInputs: { ...next.designInputs, ...design } }
57
- return drawableV3Parts(compileV3Asset(next).evaluate(state).geometry)
57
+ return drawableFigureParts(compileFigureAsset(next).evaluate(state).geometry)
58
58
  } catch {
59
59
  return null
60
60
  }
@@ -83,7 +83,7 @@ export function scrubbed(start: number, pixels: number, step: number): number {
83
83
  * author has already set with the other controls, and the design values. Drawing over the asset's saved defaults put
84
84
  * every other joint back to its saved angle while one slider moved (user, 2026-09-24: the arm jumped on release).
85
85
  */
86
- export function liveOverSession(asset: V3Asset, current: Record<string, number>, live: LiveValues): V3RenderPart[] | null {
86
+ export function liveOverSession(asset: FigureAsset, current: Record<string, number>, live: LiveValues): FigureRenderPart[] | null {
87
87
  if (!isLive(live)) return null
88
88
  return livePartsOf(asset, { ...live, values: { ...current, ...live.values } })
89
89
  }