@pascal-app/nodes 0.1.1 → 1.0.0-beta.2

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 (408) hide show
  1. package/README.md +34 -0
  2. package/dist/building/definition.js +1 -1
  3. package/dist/cabinet/definition.d.ts.map +1 -1
  4. package/dist/cabinet/definition.js +809 -72
  5. package/dist/cabinet/geometry.d.ts.map +1 -1
  6. package/dist/cabinet/geometry.js +4 -0
  7. package/dist/cabinet/move-frame.js +3 -3
  8. package/dist/cabinet/panel.d.ts.map +1 -1
  9. package/dist/cabinet/panel.js +1 -0
  10. package/dist/cabinet/placement-snap.d.ts +8 -0
  11. package/dist/cabinet/placement-snap.d.ts.map +1 -0
  12. package/dist/cabinet/placement-snap.js +19 -0
  13. package/dist/cabinet/presets.js +8 -8
  14. package/dist/cabinet/quick-actions.d.ts.map +1 -1
  15. package/dist/cabinet/quick-actions.js +9 -3
  16. package/dist/cabinet/resize-limits.d.ts +11 -0
  17. package/dist/cabinet/resize-limits.d.ts.map +1 -0
  18. package/dist/cabinet/resize-limits.js +22 -0
  19. package/dist/cabinet/run-layout.d.ts +8 -2
  20. package/dist/cabinet/run-layout.d.ts.map +1 -1
  21. package/dist/cabinet/run-layout.js +59 -7
  22. package/dist/cabinet/run-ops.d.ts +44 -3
  23. package/dist/cabinet/run-ops.d.ts.map +1 -1
  24. package/dist/cabinet/run-ops.js +646 -110
  25. package/dist/cabinet/run-panel.d.ts +2 -1
  26. package/dist/cabinet/run-panel.d.ts.map +1 -1
  27. package/dist/cabinet/run-panel.js +38 -4
  28. package/dist/cabinet/stack-transitions.js +4 -4
  29. package/dist/cabinet/tool.d.ts.map +1 -1
  30. package/dist/cabinet/tool.js +95 -17
  31. package/dist/cabinet/wall-snap.d.ts.map +1 -1
  32. package/dist/cabinet/wall-snap.js +2 -6
  33. package/dist/ceiling/boundary-editor.d.ts.map +1 -1
  34. package/dist/ceiling/boundary-editor.js +2 -2
  35. package/dist/ceiling/definition.d.ts +1 -1
  36. package/dist/ceiling/definition.d.ts.map +1 -1
  37. package/dist/ceiling/definition.js +36 -5
  38. package/dist/ceiling/floorplan-affordances.d.ts +4 -4
  39. package/dist/ceiling/floorplan-move.d.ts +4 -4
  40. package/dist/ceiling/floorplan-move.d.ts.map +1 -1
  41. package/dist/ceiling/floorplan-move.js +5 -4
  42. package/dist/ceiling/hole-editor.d.ts.map +1 -1
  43. package/dist/ceiling/hole-editor.js +2 -2
  44. package/dist/ceiling/move-tool.d.ts.map +1 -1
  45. package/dist/ceiling/move-tool.js +4 -3
  46. package/dist/ceiling/panel.d.ts.map +1 -1
  47. package/dist/ceiling/panel.js +65 -3
  48. package/dist/ceiling/renderer.d.ts.map +1 -1
  49. package/dist/ceiling/renderer.js +6 -2
  50. package/dist/ceiling/tool.d.ts.map +1 -1
  51. package/dist/ceiling/tool.js +12 -1
  52. package/dist/chimney/definition.d.ts.map +1 -1
  53. package/dist/chimney/definition.js +1 -0
  54. package/dist/chimney/tool.d.ts.map +1 -1
  55. package/dist/chimney/tool.js +16 -1
  56. package/dist/column/definition.d.ts.map +1 -1
  57. package/dist/column/definition.js +14 -2
  58. package/dist/column/floorplan-affordances.d.ts.map +1 -1
  59. package/dist/column/floorplan-affordances.js +19 -14
  60. package/dist/column/floorplan-move.d.ts.map +1 -1
  61. package/dist/column/floorplan-move.js +7 -2
  62. package/dist/column/floorplan.d.ts +9 -1
  63. package/dist/column/floorplan.d.ts.map +1 -1
  64. package/dist/column/floorplan.js +59 -4
  65. package/dist/column/tool.d.ts.map +1 -1
  66. package/dist/column/tool.js +33 -7
  67. package/dist/construction-dimension/definition.d.ts +4 -0
  68. package/dist/construction-dimension/definition.d.ts.map +1 -0
  69. package/dist/construction-dimension/definition.js +83 -0
  70. package/dist/construction-dimension/drawing-coordination.d.ts +7 -0
  71. package/dist/construction-dimension/drawing-coordination.d.ts.map +1 -0
  72. package/dist/construction-dimension/drawing-coordination.js +54 -0
  73. package/dist/construction-dimension/floorplan-affordances.d.ts +4 -0
  74. package/dist/construction-dimension/floorplan-affordances.d.ts.map +1 -0
  75. package/dist/construction-dimension/floorplan-affordances.js +114 -0
  76. package/dist/construction-dimension/floorplan-tool.d.ts +21 -0
  77. package/dist/construction-dimension/floorplan-tool.d.ts.map +1 -0
  78. package/dist/construction-dimension/floorplan-tool.js +557 -0
  79. package/dist/construction-dimension/floorplan.d.ts +3 -0
  80. package/dist/construction-dimension/floorplan.d.ts.map +1 -0
  81. package/dist/construction-dimension/floorplan.js +457 -0
  82. package/dist/construction-dimension/geometry.d.ts +31 -0
  83. package/dist/construction-dimension/geometry.d.ts.map +1 -0
  84. package/dist/construction-dimension/geometry.js +144 -0
  85. package/dist/construction-dimension/index.d.ts +4 -0
  86. package/dist/construction-dimension/index.d.ts.map +1 -0
  87. package/dist/construction-dimension/index.js +3 -0
  88. package/dist/construction-dimension/panel.d.ts +2 -0
  89. package/dist/construction-dimension/panel.d.ts.map +1 -0
  90. package/dist/construction-dimension/panel.js +128 -0
  91. package/dist/construction-dimension/parametrics.d.ts +3 -0
  92. package/dist/construction-dimension/parametrics.d.ts.map +1 -0
  93. package/dist/construction-dimension/parametrics.js +4 -0
  94. package/dist/construction-dimension/schema.d.ts +2 -0
  95. package/dist/construction-dimension/schema.d.ts.map +1 -0
  96. package/dist/construction-dimension/schema.js +1 -0
  97. package/dist/door/contextual-dimensions.d.ts +3 -0
  98. package/dist/door/contextual-dimensions.d.ts.map +1 -0
  99. package/dist/door/contextual-dimensions.js +7 -0
  100. package/dist/door/definition.d.ts.map +1 -1
  101. package/dist/door/definition.js +13 -8
  102. package/dist/door/floorplan-affordances.d.ts +2 -5
  103. package/dist/door/floorplan-affordances.d.ts.map +1 -1
  104. package/dist/door/floorplan-affordances.js +9 -18
  105. package/dist/door/floorplan.d.ts +3 -4
  106. package/dist/door/floorplan.d.ts.map +1 -1
  107. package/dist/door/floorplan.js +88 -6
  108. package/dist/door/move-tool.d.ts.map +1 -1
  109. package/dist/door/move-tool.js +2 -2
  110. package/dist/door/panel.d.ts.map +1 -1
  111. package/dist/door/panel.js +3 -1
  112. package/dist/door/schema.d.ts +1 -1
  113. package/dist/door/schema.d.ts.map +1 -1
  114. package/dist/door/schema.js +1 -1
  115. package/dist/door/tool.d.ts.map +1 -1
  116. package/dist/door/tool.js +63 -6
  117. package/dist/dormer/definition.d.ts.map +1 -1
  118. package/dist/dormer/definition.js +1 -0
  119. package/dist/dormer/tool.d.ts.map +1 -1
  120. package/dist/dormer/tool.js +23 -1
  121. package/dist/duct-segment/tool.d.ts.map +1 -1
  122. package/dist/duct-segment/tool.js +20 -9
  123. package/dist/duct-terminal/tool.d.ts.map +1 -1
  124. package/dist/duct-terminal/tool.js +9 -6
  125. package/dist/elevator/floorplan-affordances.d.ts +2 -6
  126. package/dist/elevator/floorplan-affordances.d.ts.map +1 -1
  127. package/dist/elevator/floorplan-affordances.js +13 -12
  128. package/dist/fence/actions/move-endpoint.d.ts.map +1 -1
  129. package/dist/fence/actions/move-endpoint.js +29 -1
  130. package/dist/fence/definition.d.ts.map +1 -1
  131. package/dist/fence/definition.js +74 -14
  132. package/dist/fence/floorplan-affordances.d.ts.map +1 -1
  133. package/dist/fence/floorplan-affordances.js +48 -11
  134. package/dist/fence/floorplan-move.d.ts.map +1 -1
  135. package/dist/fence/floorplan-move.js +38 -3
  136. package/dist/fence/geometry.d.ts.map +1 -1
  137. package/dist/fence/geometry.js +15 -1
  138. package/dist/fence/lift.d.ts +38 -0
  139. package/dist/fence/lift.d.ts.map +1 -0
  140. package/dist/fence/lift.js +51 -0
  141. package/dist/fence/move-tool.d.ts.map +1 -1
  142. package/dist/fence/move-tool.js +25 -5
  143. package/dist/fence/system.d.ts +3 -0
  144. package/dist/fence/system.d.ts.map +1 -0
  145. package/dist/fence/system.js +46 -0
  146. package/dist/fence/tool.d.ts.map +1 -1
  147. package/dist/fence/tool.js +103 -32
  148. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  149. package/dist/hvac-equipment/tool.js +8 -3
  150. package/dist/index.d.ts +2 -0
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/index.js +6 -0
  153. package/dist/item/definition.d.ts.map +1 -1
  154. package/dist/item/definition.js +7 -1
  155. package/dist/item/floorplan-move.d.ts.map +1 -1
  156. package/dist/item/floorplan-move.js +50 -43
  157. package/dist/item/floorplan.d.ts +1 -0
  158. package/dist/item/floorplan.d.ts.map +1 -1
  159. package/dist/item/floorplan.js +49 -0
  160. package/dist/item/renderer.d.ts +3 -0
  161. package/dist/item/renderer.d.ts.map +1 -1
  162. package/dist/item/renderer.js +96 -8
  163. package/dist/level/definition.d.ts.map +1 -1
  164. package/dist/level/definition.js +7 -3
  165. package/dist/lineset/tool.d.ts.map +1 -1
  166. package/dist/lineset/tool.js +5 -1
  167. package/dist/liquid-line/tool.d.ts.map +1 -1
  168. package/dist/liquid-line/tool.js +7 -1
  169. package/dist/measurement/definition.d.ts.map +1 -1
  170. package/dist/measurement/definition.js +5 -0
  171. package/dist/measurement/floorplan.d.ts.map +1 -1
  172. package/dist/measurement/floorplan.js +11 -10
  173. package/dist/measurement/index.d.ts +1 -1
  174. package/dist/measurement/index.d.ts.map +1 -1
  175. package/dist/measurement/index.js +1 -1
  176. package/dist/measurement/resolve.d.ts +5 -0
  177. package/dist/measurement/resolve.d.ts.map +1 -1
  178. package/dist/measurement/resolve.js +2 -2
  179. package/dist/measurement/surface-query.js +5 -5
  180. package/dist/measurement/tool.d.ts +6 -1
  181. package/dist/measurement/tool.d.ts.map +1 -1
  182. package/dist/measurement/tool.js +7 -11
  183. package/dist/pipe-segment/tool.d.ts.map +1 -1
  184. package/dist/pipe-segment/tool.js +22 -19
  185. package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
  186. package/dist/roof-segment/floorplan-affordances.js +14 -8
  187. package/dist/shared/construction-dimension-standards.d.ts +34 -0
  188. package/dist/shared/construction-dimension-standards.d.ts.map +1 -0
  189. package/dist/shared/construction-dimension-standards.js +18 -0
  190. package/dist/shared/construction-length.d.ts +10 -0
  191. package/dist/shared/construction-length.d.ts.map +1 -0
  192. package/dist/shared/construction-length.js +57 -0
  193. package/dist/shared/dimension-string.d.ts +20 -0
  194. package/dist/shared/dimension-string.d.ts.map +1 -0
  195. package/dist/shared/dimension-string.js +19 -0
  196. package/dist/shared/draft-axis-guides.d.ts +36 -0
  197. package/dist/shared/draft-axis-guides.d.ts.map +1 -0
  198. package/dist/shared/draft-axis-guides.js +107 -0
  199. package/dist/shared/move-roof-tool.d.ts.map +1 -1
  200. package/dist/shared/move-roof-tool.js +17 -3
  201. package/dist/shared/opening-documentation-fields.d.ts +16 -0
  202. package/dist/shared/opening-documentation-fields.d.ts.map +1 -0
  203. package/dist/shared/opening-documentation-fields.js +54 -0
  204. package/dist/shared/opening-documentation.d.ts +47 -0
  205. package/dist/shared/opening-documentation.d.ts.map +1 -0
  206. package/dist/shared/opening-documentation.js +300 -0
  207. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  208. package/dist/shared/opening-guides-runtime.js +3 -2
  209. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  210. package/dist/shared/opening-placement-dimensions.js +14 -5
  211. package/dist/shared/wall-opening-ceiling.d.ts +30 -0
  212. package/dist/shared/wall-opening-ceiling.d.ts.map +1 -0
  213. package/dist/shared/wall-opening-ceiling.js +29 -0
  214. package/dist/shelf/floorplan-affordances.d.ts.map +1 -1
  215. package/dist/shelf/floorplan-affordances.js +10 -5
  216. package/dist/shelf/floorplan-move.d.ts +2 -16
  217. package/dist/shelf/floorplan-move.d.ts.map +1 -1
  218. package/dist/shelf/floorplan-move.js +19 -40
  219. package/dist/shelf/tool.d.ts.map +1 -1
  220. package/dist/shelf/tool.js +8 -3
  221. package/dist/site/recessed-slab-ground-holes.d.ts.map +1 -1
  222. package/dist/site/recessed-slab-ground-holes.js +1 -4
  223. package/dist/site/renderer.d.ts.map +1 -1
  224. package/dist/site/renderer.js +118 -28
  225. package/dist/site/terrain-drape.d.ts +91 -0
  226. package/dist/site/terrain-drape.d.ts.map +1 -0
  227. package/dist/site/terrain-drape.js +205 -0
  228. package/dist/site/terrain-geometry.d.ts +131 -0
  229. package/dist/site/terrain-geometry.d.ts.map +1 -0
  230. package/dist/site/terrain-geometry.js +259 -0
  231. package/dist/site/terrain-mesh.d.ts +49 -0
  232. package/dist/site/terrain-mesh.d.ts.map +1 -0
  233. package/dist/site/terrain-mesh.js +122 -0
  234. package/dist/site/terrain-renderer.d.ts +28 -0
  235. package/dist/site/terrain-renderer.d.ts.map +1 -0
  236. package/dist/site/terrain-renderer.js +69 -0
  237. package/dist/skylight/definition.d.ts.map +1 -1
  238. package/dist/skylight/definition.js +1 -0
  239. package/dist/skylight/tool.d.ts.map +1 -1
  240. package/dist/skylight/tool.js +16 -1
  241. package/dist/slab/definition.d.ts.map +1 -1
  242. package/dist/slab/definition.js +87 -10
  243. package/dist/slab/elevation-limit.d.ts +43 -0
  244. package/dist/slab/elevation-limit.d.ts.map +1 -0
  245. package/dist/slab/elevation-limit.js +124 -0
  246. package/dist/slab/floorplan-affordances.d.ts +16 -0
  247. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  248. package/dist/slab/geometry.d.ts.map +1 -1
  249. package/dist/slab/geometry.js +98 -5
  250. package/dist/slab/panel.d.ts.map +1 -1
  251. package/dist/slab/panel.js +82 -4
  252. package/dist/slab/parametrics.d.ts +1 -1
  253. package/dist/slab/parametrics.d.ts.map +1 -1
  254. package/dist/slab/parametrics.js +13 -1
  255. package/dist/slab/placement-ownership.d.ts +3 -0
  256. package/dist/slab/placement-ownership.d.ts.map +1 -0
  257. package/dist/slab/placement-ownership.js +3 -0
  258. package/dist/slab/quick-measurement.d.ts.map +1 -1
  259. package/dist/slab/quick-measurement.js +3 -2
  260. package/dist/slab/system.d.ts.map +1 -1
  261. package/dist/slab/system.js +14 -4
  262. package/dist/slab/tool.d.ts.map +1 -1
  263. package/dist/slab/tool.js +81 -23
  264. package/dist/solar-panel/definition.d.ts.map +1 -1
  265. package/dist/solar-panel/definition.js +1 -0
  266. package/dist/solar-panel/tool.d.ts.map +1 -1
  267. package/dist/solar-panel/tool.js +17 -1
  268. package/dist/spawn/definition.d.ts.map +1 -1
  269. package/dist/spawn/definition.js +1 -0
  270. package/dist/spawn/floorplan-affordances.d.ts.map +1 -1
  271. package/dist/spawn/floorplan-affordances.js +7 -4
  272. package/dist/spawn/floorplan-move.d.ts.map +1 -1
  273. package/dist/spawn/floorplan-move.js +8 -6
  274. package/dist/spawn/renderer.d.ts +4 -0
  275. package/dist/spawn/renderer.d.ts.map +1 -1
  276. package/dist/spawn/renderer.js +32 -18
  277. package/dist/spawn/tool.d.ts +2 -2
  278. package/dist/spawn/tool.d.ts.map +1 -1
  279. package/dist/spawn/tool.js +78 -11
  280. package/dist/stair/definition.d.ts.map +1 -1
  281. package/dist/stair/definition.js +15 -7
  282. package/dist/stair/destination.d.ts +16 -0
  283. package/dist/stair/destination.d.ts.map +1 -0
  284. package/dist/stair/destination.js +24 -0
  285. package/dist/stair/documentation.d.ts +8 -0
  286. package/dist/stair/documentation.d.ts.map +1 -0
  287. package/dist/stair/documentation.js +245 -0
  288. package/dist/stair/floor-stack.d.ts.map +1 -1
  289. package/dist/stair/floor-stack.js +38 -0
  290. package/dist/stair/floorplan-affordances.d.ts.map +1 -1
  291. package/dist/stair/floorplan-affordances.js +28 -9
  292. package/dist/stair/floorplan-move.d.ts +3 -5
  293. package/dist/stair/floorplan-move.d.ts.map +1 -1
  294. package/dist/stair/floorplan-move.js +14 -16
  295. package/dist/stair/floorplan.d.ts.map +1 -1
  296. package/dist/stair/floorplan.js +27 -14
  297. package/dist/stair/panel.d.ts.map +1 -1
  298. package/dist/stair/panel.js +35 -2
  299. package/dist/stair/renderer.d.ts.map +1 -1
  300. package/dist/stair/renderer.js +4 -3
  301. package/dist/structural-grid/coordination.d.ts +16 -0
  302. package/dist/structural-grid/coordination.d.ts.map +1 -0
  303. package/dist/structural-grid/coordination.js +105 -0
  304. package/dist/structural-grid/definition.d.ts +4 -0
  305. package/dist/structural-grid/definition.d.ts.map +1 -0
  306. package/dist/structural-grid/definition.js +51 -0
  307. package/dist/structural-grid/floorplan-tool.d.ts +16 -0
  308. package/dist/structural-grid/floorplan-tool.d.ts.map +1 -0
  309. package/dist/structural-grid/floorplan-tool.js +183 -0
  310. package/dist/structural-grid/floorplan.d.ts +3 -0
  311. package/dist/structural-grid/floorplan.d.ts.map +1 -0
  312. package/dist/structural-grid/floorplan.js +61 -0
  313. package/dist/structural-grid/index.d.ts +2 -0
  314. package/dist/structural-grid/index.d.ts.map +1 -0
  315. package/dist/structural-grid/index.js +1 -0
  316. package/dist/structural-grid/schema.d.ts +2 -0
  317. package/dist/structural-grid/schema.d.ts.map +1 -0
  318. package/dist/structural-grid/schema.js +1 -0
  319. package/dist/wall/construction-dimensions.d.ts +32 -0
  320. package/dist/wall/construction-dimensions.d.ts.map +1 -0
  321. package/dist/wall/construction-dimensions.js +1031 -0
  322. package/dist/wall/contextual-dimensions.d.ts +13 -0
  323. package/dist/wall/contextual-dimensions.d.ts.map +1 -0
  324. package/dist/wall/contextual-dimensions.js +221 -0
  325. package/dist/wall/definition.d.ts.map +1 -1
  326. package/dist/wall/definition.js +20 -1
  327. package/dist/wall/floorplan-affordances.d.ts.map +1 -1
  328. package/dist/wall/floorplan-affordances.js +23 -8
  329. package/dist/wall/floorplan-overrides.d.ts +9 -6
  330. package/dist/wall/floorplan-overrides.d.ts.map +1 -1
  331. package/dist/wall/floorplan-overrides.js +20 -11
  332. package/dist/wall/floorplan.d.ts +12 -3
  333. package/dist/wall/floorplan.d.ts.map +1 -1
  334. package/dist/wall/floorplan.js +121 -79
  335. package/dist/wall/measurement.d.ts.map +1 -1
  336. package/dist/wall/measurement.js +17 -4
  337. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  338. package/dist/wall/move-endpoint-tool.js +74 -27
  339. package/dist/wall/move-shared.d.ts.map +1 -1
  340. package/dist/wall/move-shared.js +3 -2
  341. package/dist/wall/move-tool.d.ts.map +1 -1
  342. package/dist/wall/move-tool.js +15 -3
  343. package/dist/wall/paint.d.ts.map +1 -1
  344. package/dist/wall/paint.js +10 -6
  345. package/dist/wall/panel.d.ts.map +1 -1
  346. package/dist/wall/panel.js +32 -5
  347. package/dist/wall/parametrics.d.ts.map +1 -1
  348. package/dist/wall/parametrics.js +2 -0
  349. package/dist/wall/preview.d.ts +8 -0
  350. package/dist/wall/preview.d.ts.map +1 -0
  351. package/dist/wall/preview.js +39 -0
  352. package/dist/wall/quick-measurement.d.ts.map +1 -1
  353. package/dist/wall/quick-measurement.js +3 -2
  354. package/dist/wall/renderer.d.ts.map +1 -1
  355. package/dist/wall/renderer.js +7 -5
  356. package/dist/wall/system.d.ts +1 -1
  357. package/dist/wall/system.d.ts.map +1 -1
  358. package/dist/wall/system.js +37 -2
  359. package/dist/wall/tool.d.ts.map +1 -1
  360. package/dist/wall/tool.js +148 -96
  361. package/dist/wall/treatment-level-data.d.ts +14 -0
  362. package/dist/wall/treatment-level-data.d.ts.map +1 -0
  363. package/dist/wall/treatment-level-data.js +31 -0
  364. package/dist/wall/treatments.d.ts +8 -2
  365. package/dist/wall/treatments.d.ts.map +1 -1
  366. package/dist/wall/treatments.js +58 -15
  367. package/dist/window/contextual-dimensions.d.ts +3 -0
  368. package/dist/window/contextual-dimensions.d.ts.map +1 -0
  369. package/dist/window/contextual-dimensions.js +7 -0
  370. package/dist/window/definition.d.ts.map +1 -1
  371. package/dist/window/definition.js +15 -10
  372. package/dist/window/floorplan-affordances.d.ts +2 -5
  373. package/dist/window/floorplan-affordances.d.ts.map +1 -1
  374. package/dist/window/floorplan-affordances.js +9 -15
  375. package/dist/window/floorplan-move.d.ts.map +1 -1
  376. package/dist/window/floorplan-move.js +1 -1
  377. package/dist/window/floorplan.d.ts.map +1 -1
  378. package/dist/window/floorplan.js +7 -1
  379. package/dist/window/move-tool.d.ts.map +1 -1
  380. package/dist/window/move-tool.js +3 -3
  381. package/dist/window/panel.d.ts.map +1 -1
  382. package/dist/window/panel.js +4 -1
  383. package/dist/window/schema.d.ts +1 -1
  384. package/dist/window/schema.d.ts.map +1 -1
  385. package/dist/window/schema.js +1 -1
  386. package/dist/window/tool.d.ts.map +1 -1
  387. package/dist/window/tool.js +64 -7
  388. package/dist/window/window-math.d.ts +7 -3
  389. package/dist/window/window-math.d.ts.map +1 -1
  390. package/dist/window/window-math.js +8 -3
  391. package/dist/zone/contextual-dimensions.d.ts +3 -0
  392. package/dist/zone/contextual-dimensions.d.ts.map +1 -0
  393. package/dist/zone/contextual-dimensions.js +43 -0
  394. package/dist/zone/definition.d.ts.map +1 -1
  395. package/dist/zone/definition.js +9 -1
  396. package/dist/zone/floorplan-affordances.d.ts +36 -0
  397. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  398. package/dist/zone/floorplan.d.ts.map +1 -1
  399. package/dist/zone/floorplan.js +59 -3
  400. package/dist/zone/quantities-panel.d.ts.map +1 -1
  401. package/dist/zone/quantities-panel.js +48 -4
  402. package/dist/zone/room-clear-dimensions.d.ts +3 -0
  403. package/dist/zone/room-clear-dimensions.d.ts.map +1 -0
  404. package/dist/zone/room-clear-dimensions.js +406 -0
  405. package/dist/zone/room-documentation.d.ts +11 -0
  406. package/dist/zone/room-documentation.d.ts.map +1 -0
  407. package/dist/zone/room-documentation.js +97 -0
  408. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/item/renderer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,QAAQ,EAWd,MAAM,kBAAkB,CAAA;AAkUzB,eAAO,MAAM,YAAY,GAAI,qBAAqB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,gCAqDnE,CAAA;AAwTD,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/item/renderer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,QAAQ,EAWd,MAAM,kBAAkB,CAAA;AAmZzB,eAAO,MAAM,YAAY,GAAI,qBAAqB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,gCAqDnE,CAAA;AA+CD,eAAO,MAAM,WAAW,GAAI,UAAU;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,gCAUvD,CAAA;AAuRD,eAAe,YAAY,CAAA"}
@@ -1,12 +1,12 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { deriveSlotId, getScaledDimensions, isSlotMaterialName, itemClipRegistry, LIBRARY_MATERIAL_REF_PREFIX, SCENE_MATERIAL_REF_PREFIX, toLibraryMaterialRef, useInteractive, useLiveNodeOverrides, useRegistry, useScene, } from '@pascal-app/core';
4
- import { createDefaultMaterial, createSurfaceRoleMaterial, ErrorBoundary, glassMaterial, NodeRenderer, resolveCdnUrl, resolveMaterialRef, useItemLightPool, useNodeEvents, useViewer, } from '@pascal-app/viewer';
4
+ import { configureKtx2Support, createDefaultMaterial, createSurfaceRoleMaterial, ErrorBoundary, glassMaterial, NodeRenderer, resolveCdnUrl, resolveMaterialRef, stampPascalTextureRef, useItemLightPool, useNodeEvents, useViewer, } from '@pascal-app/viewer';
5
5
  import { useAnimations } from '@react-three/drei';
6
6
  import { Clone } from '@react-three/drei/core/Clone';
7
- import { useFrame, useLoader } from '@react-three/fiber';
7
+ import { useFrame, useLoader, useThree } from '@react-three/fiber';
8
8
  import { Suspense, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
9
- import { MathUtils } from 'three';
9
+ import { MathUtils, Texture } from 'three';
10
10
  import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
11
11
  import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
12
12
  import { positionLocal, smoothstep, time } from 'three/tsl';
@@ -110,7 +110,8 @@ const BrokenItemFallback = ({ node }) => {
110
110
  return (_jsxs("mesh", { "position-y": h / 2, ...handlers, children: [_jsx("boxGeometry", { args: [w, h, d] }), _jsx("primitive", { attach: "material", object: material })] }));
111
111
  };
112
112
  let itemDracoLoader = null;
113
- const configureItemModelLoader = (loader) => {
113
+ const configureItemModelLoader = (loader, renderer) => {
114
+ configureKtx2Support(loader, renderer);
114
115
  if (!itemDracoLoader) {
115
116
  itemDracoLoader = new DRACOLoader(loader.manager);
116
117
  itemDracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.5/');
@@ -118,7 +119,82 @@ const configureItemModelLoader = (loader) => {
118
119
  loader.setDRACOLoader(itemDracoLoader);
119
120
  loader.setMeshoptDecoder(MeshoptDecoder);
120
121
  };
121
- const useItemGltf = (url) => useLoader(ItemGLTFLoader, url, configureItemModelLoader);
122
+ const ITEM_TEXTURE_SLOTS = [
123
+ 'map',
124
+ 'normalMap',
125
+ 'roughnessMap',
126
+ 'metalnessMap',
127
+ 'emissiveMap',
128
+ 'aoMap',
129
+ 'alphaMap',
130
+ 'lightMap',
131
+ 'bumpMap',
132
+ 'displacementMap',
133
+ 'clearcoatMap',
134
+ 'clearcoatNormalMap',
135
+ 'clearcoatRoughnessMap',
136
+ 'iridescenceMap',
137
+ 'iridescenceThicknessMap',
138
+ 'transmissionMap',
139
+ 'thicknessMap',
140
+ 'specularIntensityMap',
141
+ 'specularColorMap',
142
+ 'sheenRoughnessMap',
143
+ 'sheenColorMap',
144
+ 'anisotropyMap',
145
+ ];
146
+ function getItemTextureImageIndex(gltf, texture) {
147
+ const association = gltf.parser?.associations.get(texture);
148
+ const textureIndex = association?.textures;
149
+ if (!Number.isInteger(textureIndex))
150
+ return null;
151
+ const textureDef = gltf.parser.json.textures?.[textureIndex];
152
+ const imageIndex = textureDef?.extensions?.KHR_texture_basisu?.source ??
153
+ textureDef?.extensions?.EXT_texture_webp?.source ??
154
+ textureDef?.extensions?.EXT_texture_avif?.source ??
155
+ textureDef?.source;
156
+ return Number.isInteger(imageIndex) && imageIndex >= 0 ? imageIndex : null;
157
+ }
158
+ function stampItemTextureReferences(gltf, src) {
159
+ if (!gltf.parser?.associations)
160
+ return;
161
+ const stamped = new Set();
162
+ gltf.scene.traverse((object) => {
163
+ const mesh = object;
164
+ if (!mesh.isMesh)
165
+ return;
166
+ const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
167
+ for (const material of materials) {
168
+ const textureMaterial = material;
169
+ for (const slot of ITEM_TEXTURE_SLOTS) {
170
+ const texture = textureMaterial[slot];
171
+ if (!(texture instanceof Texture))
172
+ continue;
173
+ if (stamped.has(texture))
174
+ continue;
175
+ const imageIndex = getItemTextureImageIndex(gltf, texture);
176
+ if (imageIndex === null)
177
+ continue;
178
+ if (stampPascalTextureRef(texture, {
179
+ kind: 'item-glb',
180
+ src,
181
+ slot,
182
+ imageIndex,
183
+ })) {
184
+ stamped.add(texture);
185
+ }
186
+ }
187
+ }
188
+ });
189
+ }
190
+ const useItemGltf = (url) => {
191
+ const renderer = useThree((state) => state.gl);
192
+ const gltf = useLoader(ItemGLTFLoader, url, (loader) => configureItemModelLoader(loader, renderer));
193
+ return useMemo(() => {
194
+ stampItemTextureReferences(gltf, url);
195
+ return gltf;
196
+ }, [gltf, url]);
197
+ };
122
198
  const unavailableAssetConsumers = new Map();
123
199
  const unavailableFailureConsumers = new Map();
124
200
  const retainUnavailableConsumer = (entries, key) => {
@@ -236,10 +312,23 @@ function getPreviewMaterial(shading) {
236
312
  const PreviewModel = ({ node }) => {
237
313
  const shading = useViewer((s) => s.shading);
238
314
  const isExporting = useViewer((s) => s.isExporting);
315
+ const [w, h, d] = getScaledDimensions(node);
239
316
  // Loading placeholder — must never land in an exported GLB.
240
317
  if (isExporting)
241
318
  return null;
242
- return (_jsx("mesh", { material: getPreviewMaterial(shading), "position-y": node.asset.dimensions[1] / 2, children: _jsx("boxGeometry", { args: [node.asset.dimensions[0], node.asset.dimensions[1], node.asset.dimensions[2]] }) }));
319
+ return (_jsx("mesh", { material: getPreviewMaterial(shading), "position-y": h / 2, children: _jsx("boxGeometry", { args: [w, h, d] }) }));
320
+ };
321
+ const LoadedItemPreview = ({ node }) => {
322
+ const gltf = useItemGltf(resolveCdnUrl(node.asset.src) || '');
323
+ if (getUnavailableItemAsset(gltf))
324
+ return _jsx(PreviewModel, { node: node });
325
+ return (_jsx("group", { rotation: node.rotation, scale: node.scale, children: _jsx(Clone, { dispose: null, object: gltf.scene, position: node.asset.offset, rotation: node.asset.rotation, scale: node.asset.scale || [1, 1, 1] }) }));
326
+ };
327
+ export const ItemPreview = ({ node }) => {
328
+ const url = resolveCdnUrl(node.asset.src) || '';
329
+ if (!url)
330
+ return _jsx(PreviewModel, { node: node });
331
+ return (_jsx(Suspense, { fallback: _jsx(PreviewModel, { node: node }), children: _jsx(ErrorBoundary, { fallback: _jsx(PreviewModel, { node: node }), scope: "item-preview-model", children: _jsx(LoadedItemPreview, { node: node }) }) }));
243
332
  };
244
333
  const ClearPreviewModel = ({ node }) => {
245
334
  const shading = useViewer((s) => s.shading);
@@ -255,7 +344,6 @@ const ClearPreviewModel = ({ node }) => {
255
344
  }, [shading]);
256
345
  return (_jsx("mesh", { material: material, "position-y": h / 2, children: _jsx("boxGeometry", { args: [w, h, d] }) }));
257
346
  };
258
- const multiplyScales = (a, b) => [a[0] * b[0], a[1] * b[1], a[2] * b[2]];
259
347
  const ModelRenderer = ({ node, markSettled }) => {
260
348
  const gltf = useItemGltf(resolveCdnUrl(node.asset.src) || '');
261
349
  const unavailable = getUnavailableItemAsset(gltf);
@@ -354,7 +442,7 @@ const LoadedModelRenderer = ({ gltf: { scene, nodes, animations }, node, markSet
354
442
  }, [node.id, animEffect, animations]);
355
443
  // useGLTF caches scenes, and Clone shares child geometry/material references.
356
444
  // Undo can unmount one item while another clone of the same asset still needs them.
357
- return (_jsxs(_Fragment, { children: [_jsx(Clone, { dispose: null, object: scene, position: node.asset.offset, ref: ref, rotation: node.asset.rotation, scale: multiplyScales(node.asset.scale || [1, 1, 1], node.scale || [1, 1, 1]), ...handlers }), animations.length > 0 && (_jsx(ItemAnimation, { actions: actions, animations: animations, animEffect: animEffect, interactive: interactive ?? null, nodeId: node.id })), lightEffects.map((effect, i) => (_jsx(ItemLightRegistrar, { effect: effect, index: i, interactive: interactive, nodeId: node.id }, i)))] }));
445
+ return (_jsxs(_Fragment, { children: [_jsx("group", { scale: node.scale, children: _jsx(Clone, { dispose: null, object: scene, position: node.asset.offset, ref: ref, rotation: node.asset.rotation, scale: node.asset.scale || [1, 1, 1], ...handlers }) }), animations.length > 0 && (_jsx(ItemAnimation, { actions: actions, animations: animations, animEffect: animEffect, interactive: interactive ?? null, nodeId: node.id })), lightEffects.map((effect, i) => (_jsx(ItemLightRegistrar, { effect: effect, index: i, interactive: interactive, nodeId: node.id }, i)))] }));
358
446
  };
359
447
  const ItemAnimation = ({ nodeId, animEffect, interactive, actions, animations, }) => {
360
448
  const activeClipRef = useRef(null);
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/level/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEpF,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEpC;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,OAAO,SAAS,CAoD5D,CAAA"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/level/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEpC;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,OAAO,SAAS,CAwD5D,CAAA"}
@@ -1,4 +1,4 @@
1
- import { LevelNode as LevelNodeSchema } from '@pascal-app/core';
1
+ import { DEFAULT_LEVEL_HEIGHT, LevelNode as LevelNodeSchema, } from '@pascal-app/core';
2
2
  import { levelParametrics } from './parametrics';
3
3
  import { LevelNode } from './schema';
4
4
  /**
@@ -8,11 +8,15 @@ import { LevelNode } from './schema';
8
8
  */
9
9
  export const levelDefinition = {
10
10
  kind: 'level',
11
- schemaVersion: 1,
11
+ schemaVersion: 2,
12
12
  schema: LevelNode,
13
13
  category: 'site',
14
14
  defaults: () => {
15
- const stub = LevelNodeSchema.parse({ id: 'level_default', type: 'level' });
15
+ const stub = LevelNodeSchema.parse({
16
+ id: 'level_default',
17
+ type: 'level',
18
+ height: DEFAULT_LEVEL_HEIGHT,
19
+ });
16
20
  const { id: _id, type: _type, ...rest } = stub;
17
21
  return rest;
18
22
  },
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/lineset/tool.tsx"],"names":[],"mappings":"AAuFA,QAAA,MAAM,WAAW,0CAuQhB,CAAA;AAgCD,eAAe,WAAW,CAAA"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/lineset/tool.tsx"],"names":[],"mappings":"AAwFA,QAAA,MAAM,WAAW,0CA4QhB,CAAA;AAgCD,eAAe,WAAW,CAAA"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { emitter, LinesetNode, useScene } from '@pascal-app/core';
4
- import { CursorSphere, DimensionPill, EDITOR_LAYER, isAngleSnapActive, isGridSnapActive, isMagneticSnapActive, markToolCancelConsumed, triggerSFX, useEditor, } from '@pascal-app/editor';
4
+ import { CursorSphere, DimensionPill, EDITOR_LAYER, isAngleSnapActive, isGridSnapActive, isMagneticSnapActive, markToolCancelConsumed, triggerSFX, useEditor, usePathDraftPreview, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Html } from '@react-three/drei';
7
7
  import { useEffect, useRef, useState } from 'react';
@@ -77,6 +77,10 @@ const LinesetTool = () => {
77
77
  draftRef.current = draftPoints;
78
78
  const altAnchorRef = useRef(null);
79
79
  const lastClientYRef = useRef(null);
80
+ useEffect(() => {
81
+ usePathDraftPreview.getState().setDraft('lineset', draftPoints, cursorPos);
82
+ }, [cursorPos, draftPoints]);
83
+ useEffect(() => () => usePathDraftPreview.getState().clear('lineset'), []);
80
84
  useEffect(() => {
81
85
  if (!activeLevelId)
82
86
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/liquid-line/tool.tsx"],"names":[],"mappings":"AAkQA,QAAA,MAAM,cAAc,0CA2VnB,CAAA;AA8BD,eAAe,cAAc,CAAA"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/liquid-line/tool.tsx"],"names":[],"mappings":"AAmQA,QAAA,MAAM,cAAc,0CAkWnB,CAAA;AA8BD,eAAe,cAAc,CAAA"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { emitter, LiquidLineNode, useScene, } from '@pascal-app/core';
4
- import { CursorSphere, DimensionPill, EDITOR_LAYER, isAngleSnapActive, isGridSnapActive, isMagneticSnapActive, markToolCancelConsumed, triggerSFX, useEditor, } from '@pascal-app/editor';
4
+ import { CursorSphere, DimensionPill, EDITOR_LAYER, isAngleSnapActive, isGridSnapActive, isMagneticSnapActive, markToolCancelConsumed, triggerSFX, useEditor, usePathDraftPreview, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Html } from '@react-three/drei';
7
7
  import { useEffect, useRef, useState } from 'react';
@@ -242,6 +242,12 @@ const LiquidLineTool = () => {
242
242
  }, [follow]);
243
243
  // Leaving the tool clears Follow so re-arming it starts in free-draw.
244
244
  useEffect(() => () => useLiquidLineToolOptions.getState().setFollow(false), []);
245
+ useEffect(() => {
246
+ usePathDraftPreview
247
+ .getState()
248
+ .setDraft('liquid-line', traceGhost ?? draftPoints, traceGhost ? null : cursorPos);
249
+ }, [cursorPos, draftPoints, traceGhost]);
250
+ useEffect(() => () => usePathDraftPreview.getState().clear('liquid-line'), []);
245
251
  useEffect(() => {
246
252
  if (!activeLevelId)
247
253
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/measurement/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAGnF,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE1C,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,OAAO,eAAe,CA+DxE,CAAA"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/measurement/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAInF,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE1C,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,OAAO,eAAe,CAoExE,CAAA"}
@@ -35,6 +35,11 @@ export const measurementDefinition = {
35
35
  },
36
36
  floorplan: buildMeasurementFloorplan,
37
37
  floorplanDependencies: (node) => measurementReferenceNodeIds(node.measurement),
38
+ extensions: {
39
+ 'pascal:editor/floorplan': {
40
+ referencedSelectionAnnotationRole: 'measurement',
41
+ },
42
+ },
38
43
  floorplanAffordances: {
39
44
  'move-measurement-vertex': measurementMoveVertexAffordance,
40
45
  },
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/measurement/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAGtB,KAAK,eAAe,EACpB,KAAK,eAAe,EAOrB,MAAM,kBAAkB,CAAA;AA6BzB,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,eAAe,GACnB,iBAAiB,GAAG,IAAI,CA+L1B"}
1
+ {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/measurement/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAGtB,KAAK,eAAe,EACpB,KAAK,eAAe,EAOrB,MAAM,kBAAkB,CAAA;AA+BzB,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,eAAe,GACnB,iBAAiB,GAAG,IAAI,CA4M1B"}
@@ -1,5 +1,5 @@
1
1
  import { measurementAngle, measurementArea, measurementDistance, measurementPerimeter, measurementPrismVolume, } from '@pascal-app/core';
2
- import { buildMeasurementAngleArcPoints, formatAngleRadians, formatAreaLabel, formatLinearMeasurement, formatVolumeLabel, measurementFloorplanPresentationColor, measurementPolygonLabelAnchor, } from '@pascal-app/editor';
2
+ import { buildMeasurementAngleArcPoints, formatAngleRadians, formatAreaLabel, formatLinearMeasurement, formatVolumeLabel, measurementFloorplanPresentationColor, measurementPolygonLabelAnchor, readFloorplanContext, withFloorplanGeometryMetadata, } from '@pascal-app/editor';
3
3
  import { measurementResolvedEditPoints } from './edit';
4
4
  import { resolveMeasurementNode } from './resolve';
5
5
  const projectPoint = (point) => [point[0], point[2]];
@@ -19,6 +19,7 @@ export function buildMeasurementFloorplan(node, ctx) {
19
19
  if (node.visible === false)
20
20
  return null;
21
21
  const unit = ctx.viewState?.unit ?? 'metric';
22
+ const metricNotation = readFloorplanContext(ctx).metricNotation;
22
23
  const resolved = resolveMeasurementNode(node, (id) => ctx.resolve(id));
23
24
  const measurement = resolved.payload;
24
25
  const selected = ctx.viewState?.selected || ctx.viewState?.highlighted;
@@ -52,7 +53,7 @@ export function buildMeasurementFloorplan(node, ctx) {
52
53
  },
53
54
  ]
54
55
  : [];
55
- return {
56
+ return withFloorplanGeometryMetadata({
56
57
  kind: 'group',
57
58
  children: [
58
59
  { kind: 'line', x1, y1, x2, y2, ...style },
@@ -79,19 +80,19 @@ export function buildMeasurementFloorplan(node, ctx) {
79
80
  appearance: 'outlined',
80
81
  cx: (x1 + x2) / 2,
81
82
  cy: (y1 + y2) / 2,
82
- text: `${statusPrefix}${formatLinearMeasurement(measurementDistance(start, end), unit)}`,
83
+ text: `${statusPrefix}${formatLinearMeasurement(measurementDistance(start, end), unit, metricNotation)}`,
83
84
  angle: Math.atan2(y2 - y1, x2 - x1),
84
85
  offsetPx: 14,
85
86
  },
86
87
  ...editHandles,
87
88
  ],
88
- };
89
+ }, { annotationRole: 'measurement' });
89
90
  }
90
91
  if (measurement.kind === 'angle') {
91
92
  const [start, vertex, end] = measurement.points;
92
93
  const angleArc = buildMeasurementAngleArcPoints(start, vertex, end);
93
94
  const labelPoint = angleArc[Math.floor(angleArc.length / 2)] ?? vertex;
94
- return {
95
+ return withFloorplanGeometryMetadata({
95
96
  kind: 'group',
96
97
  children: [
97
98
  {
@@ -121,14 +122,14 @@ export function buildMeasurementFloorplan(node, ctx) {
121
122
  },
122
123
  ...editHandles,
123
124
  ],
124
- };
125
+ }, { annotationRole: 'measurement' });
125
126
  }
126
127
  if (measurement.kind === 'area' || measurement.kind === 'perimeter') {
127
128
  const centroid = measurementPolygonLabelAnchor(measurement.base) ?? measurement.base[0];
128
129
  const label = measurement.kind === 'area'
129
130
  ? `A ${formatAreaLabel(measurementArea(measurement.base), unit)}`
130
- : `P ${formatLinearMeasurement(measurementPerimeter(measurement.base), unit)}`;
131
- return {
131
+ : `P ${formatLinearMeasurement(measurementPerimeter(measurement.base), unit, metricNotation)}`;
132
+ return withFloorplanGeometryMetadata({
132
133
  kind: 'group',
133
134
  children: [
134
135
  {
@@ -150,7 +151,7 @@ export function buildMeasurementFloorplan(node, ctx) {
150
151
  },
151
152
  ...editHandles,
152
153
  ],
153
- };
154
+ }, { annotationRole: 'measurement' });
154
155
  }
155
156
  const volume = measurement;
156
157
  const top = volume.base.map((point) => add(point, volume.extrusion));
@@ -191,5 +192,5 @@ export function buildMeasurementFloorplan(node, ctx) {
191
192
  screenUpright: true,
192
193
  });
193
194
  children.push(...editHandles);
194
- return { kind: 'group', children };
195
+ return withFloorplanGeometryMetadata({ kind: 'group', children }, { annotationRole: 'measurement' });
195
196
  }
@@ -1,3 +1,3 @@
1
1
  export { measurementDefinition } from './definition';
2
- export { closestMeasurementFeature, detachMeasurementPayload, freeMeasurementPoint, type MeasurementFeatureMatch, matchMeasurementFeatureForNode, measurementDependencyIds, measurementFeaturePoint, measurementFeaturesForNode, type ResolvedMeasurement, type ResolvedMeasurementPayload, remapMeasurementReferences, resolveMeasurementNode, } from './resolve';
2
+ export { closestMeasurementFeature, detachMeasurementPayload, freeMeasurementPoint, type MeasurementFeatureMatch, matchMeasurementFeatureForNode, measurementDependencyIds, measurementFeaturePoint, measurementFeaturesForNode, type ResolvedMeasurement, type ResolvedMeasurementPayload, remapMeasurementReferences, resolveMeasurementAnchor, resolveMeasurementNode, } from './resolve';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/measurement/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,EACpB,KAAK,uBAAuB,EAC5B,8BAA8B,EAC9B,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/measurement/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,EACpB,KAAK,uBAAuB,EAC5B,8BAA8B,EAC9B,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,0BAA0B,EAC1B,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,WAAW,CAAA"}
@@ -1,2 +1,2 @@
1
1
  export { measurementDefinition } from './definition';
2
- export { closestMeasurementFeature, detachMeasurementPayload, freeMeasurementPoint, matchMeasurementFeatureForNode, measurementDependencyIds, measurementFeaturePoint, measurementFeaturesForNode, remapMeasurementReferences, resolveMeasurementNode, } from './resolve';
2
+ export { closestMeasurementFeature, detachMeasurementPayload, freeMeasurementPoint, matchMeasurementFeatureForNode, measurementDependencyIds, measurementFeaturePoint, measurementFeaturesForNode, remapMeasurementReferences, resolveMeasurementAnchor, resolveMeasurementNode, } from './resolve';
@@ -34,6 +34,11 @@ export declare function measurementFeaturesForNode(node: AnyNode, resolve: NodeR
34
34
  export declare function matchMeasurementFeatureForNode(node: AnyNode, resolve: NodeResolver, point: MeasurementPoint, maxDistance: number): MeasurementFeatureMatch | null;
35
35
  export declare function closestMeasurementFeature(features: readonly MeasurementFeature[], point: MeasurementPoint, maxDistance: number): MeasurementFeatureMatch | null;
36
36
  export declare function measurementFeaturePoint(feature: MeasurementFeature, reference: MeasurementFeatureReference): MeasurementPoint | null;
37
+ export declare function resolveMeasurementAnchor(anchor: MeasurementAnchor, resolve: NodeResolver): {
38
+ point: MeasurementPoint;
39
+ normal: MeasurementPoint | null;
40
+ dangling: MeasurementFeatureReference | null;
41
+ };
37
42
  export declare function measurementDependencyIds(measurement: MeasurementPayload, resolve?: NodeResolver): AnyNodeId[];
38
43
  export declare function resolveMeasurementNode(node: Pick<MeasurementNode, 'measurement'>, resolve: NodeResolver): ResolvedMeasurement;
39
44
  export declare function detachMeasurementPayload(node: Pick<MeasurementNode, 'measurement'>, resolve: NodeResolver): MeasurementPayload;
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/measurement/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EAGd,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EAGrB,0BAA0B,EAC3B,MAAM,kBAAkB,CAAA;AAEzB,MAAM,MAAM,0BAA0B,GAClC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAA;CAAE,GACjF;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,EAAE,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,gBAAgB,EAAE,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,gBAAgB,EAAE,CAAC;IAAC,SAAS,EAAE,gBAAgB,CAAA;CAAE,CAAA;AAE7E,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,0BAA0B,CAAA;IACnC,QAAQ,EAAE,2BAA2B,EAAE,CAAA;IACvC,YAAY,EAAE,SAAS,EAAE,CAAA;IACzB,aAAa,EAAE,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;CAC9C,CAAA;AAED,KAAK,YAAY,GAAG,CAAC,EAAE,EAAE,SAAS,KAAK,OAAO,GAAG,SAAS,CAAA;AAE1D,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,kBAAkB,CAAA;IAC3B,KAAK,EAAE,gBAAgB,CAAA;IACvB,CAAC,EAAE,MAAM,CAAA;IACT,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;IACrD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAwBD,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,wBAG9E;AAED,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,GAClB,uBAAuB,GAAG,IAAI,CA2BhC;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,EACvC,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,GAClB,uBAAuB,GAAG,IAAI,CAahC;AAoCD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,2BAA2B,GACrC,gBAAgB,GAAG,IAAI,CAazB;AAqCD,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,kBAAkB,EAC/B,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,EAAE,CAUb;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,EAC1C,OAAO,EAAE,YAAY,GACpB,mBAAmB,CAkDrB;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,EAC1C,OAAO,EAAE,YAAY,GACpB,kBAAkB,CAEpB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,gBAAgB,CAEhF;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAA"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/measurement/resolve.ts"],"names":[],"mappings":"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"}
@@ -111,7 +111,7 @@ export function measurementFeaturePoint(feature, reference) {
111
111
  return pointOnPath(feature.geometry.points, t, true);
112
112
  }
113
113
  }
114
- function resolveAnchor(anchor, resolve) {
114
+ export function resolveMeasurementAnchor(anchor, resolve) {
115
115
  if (Array.isArray(anchor))
116
116
  return { point: anchor, normal: null, dangling: null };
117
117
  const referencedNode = resolve(anchor.reference.nodeId);
@@ -152,7 +152,7 @@ export function resolveMeasurementNode(node, resolve) {
152
152
  const dangling = [];
153
153
  const anchorNormals = [];
154
154
  const point = (anchor) => {
155
- const result = resolveAnchor(anchor, resolve);
155
+ const result = resolveMeasurementAnchor(anchor, resolve);
156
156
  if (result.dangling)
157
157
  dangling.push(result.dangling);
158
158
  anchorNormals.push(result.normal);
@@ -254,14 +254,14 @@ export function selectMeasurementSurfaceHit(hits, levelObject, preference) {
254
254
  const nearest = hits[0] ?? null;
255
255
  if (!(nearest && preference))
256
256
  return nearest;
257
- const nearby = hits.filter((hit) => hit.intersection.distance <=
258
- nearest.intersection.distance + SURFACE_INTENT_MAX_OCCLUSION_DISTANCE);
259
257
  if (preference.kind === 'horizontal') {
260
258
  if (Math.abs(toLocalSurfaceHit(nearest, levelObject).normal[1]) >=
261
259
  HORIZONTAL_SURFACE_MAX_OCCLUDER_NORMAL_Y) {
262
260
  return nearest;
263
261
  }
264
262
  const nodes = useScene.getState().nodes;
263
+ const nearby = hits.filter((hit) => hit.intersection.distance <=
264
+ nearest.intersection.distance + SURFACE_INTENT_MAX_OCCLUSION_DISTANCE);
265
265
  return (nearby.find((hit) => {
266
266
  const type = hit.targetNodeId ? nodes[hit.targetNodeId]?.type : undefined;
267
267
  return (Boolean(type && HORIZONTAL_SURFACE_TYPES.has(type)) &&
@@ -270,16 +270,16 @@ export function selectMeasurementSurfaceHit(hits, levelObject, preference) {
270
270
  }
271
271
  const preferredNormal = new Vector3(...preference.normal);
272
272
  if (preferredNormal.lengthSq() <= 1e-12)
273
- return nearest;
273
+ return null;
274
274
  preferredNormal.normalize();
275
275
  const preferredPoint = new Vector3(...preference.point);
276
- return (nearby.find((hit) => {
276
+ return (hits.find((hit) => {
277
277
  const localHit = toLocalSurfaceHit(hit, levelObject);
278
278
  const normalAlignment = Math.abs(preferredNormal.dot(new Vector3(...localHit.normal)));
279
279
  const planeDistance = Math.abs(new Vector3(...localHit.point).sub(preferredPoint).dot(preferredNormal));
280
280
  return (normalAlignment >= SURFACE_INTENT_MIN_NORMAL_ALIGNMENT &&
281
281
  planeDistance <= SURFACE_INTENT_PLANE_TOLERANCE);
282
- }) ?? nearest);
282
+ }) ?? null);
283
283
  }
284
284
  function setRayFromPointer(raycaster, pointer, event, camera, canvas) {
285
285
  const rect = canvas.getBoundingClientRect();
@@ -1,7 +1,8 @@
1
1
  import { type AlignmentAnchor, type MeasurementFeatureAnchor, type MeasurementSnapKind } from '@pascal-app/core';
2
- import { type LinearUnit, type MeasurementAxis, type MeasurementAxisGuide, type MeasurementPoint } from '@pascal-app/editor';
2
+ import { type LinearUnit, type MeasurementAxis, type MeasurementAxisGuide, type MeasurementKind, type MeasurementPoint } from '@pascal-app/editor';
3
3
  import { type FC } from 'react';
4
4
  import { type Camera, type Intersection, type Object3D, Raycaster, Vector2, Vector3 } from 'three';
5
+ import { type MeasurementSurfacePreference } from './surface-query';
5
6
  export type MeasurementRaycastContext = {
6
7
  ownerByObject: Map<Object3D, string>;
7
8
  roots: Object3D[];
@@ -35,6 +36,10 @@ export declare function selectClosestVerifiedAxisProjection(candidates: readonly
35
36
  export declare function selectAxisCandidateForSurfaceVerification<T extends MeasurementAxisCandidate>(candidates: readonly T[], threshold?: number, lockedAxis?: MeasurementAxis | null, releaseThreshold?: number, lockedFrom?: MeasurementPoint | null): T | null;
36
37
  export declare function measurementVertexSnapAnchors(points: readonly MeasurementPoint[], index: number, polygon: boolean): MeasurementPoint[];
37
38
  export declare function selectClosestMeasurementVertexIndex(screenDistances: readonly number[], threshold?: number): number | null;
39
+ export declare function measurementPolygonSurfacePreference(kind: MeasurementKind, plane: {
40
+ point: MeasurementPoint;
41
+ normal: MeasurementPoint;
42
+ } | null, applyMagneticSnap: boolean): MeasurementSurfacePreference | null;
38
43
  export declare function isMeasurementSurfaceMaterialVisible(object: Object3D, materialIndex?: number): boolean;
39
44
  export declare function isMeasurementSurfaceEligible(object: Object3D): boolean;
40
45
  export declare function collectMeasurementSurfaceRoots(scene: Object3D, registeredRoots: readonly Object3D[]): Object3D[];
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/measurement/tool.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/measurement/tool.tsx"],"names":[],"mappings":"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"}
@@ -124,12 +124,14 @@ function isMeasurementKind(value) {
124
124
  value === 'perimeter' ||
125
125
  value === 'volume');
126
126
  }
127
- function polygonSurfacePreference(kind, plane) {
127
+ export function measurementPolygonSurfacePreference(kind, plane, applyMagneticSnap) {
128
128
  if (kind !== 'area' && kind !== 'perimeter' && kind !== 'volume')
129
129
  return null;
130
130
  return plane
131
131
  ? { kind: 'plane', point: plane.point, normal: plane.normal }
132
- : { kind: 'horizontal' };
132
+ : applyMagneticSnap
133
+ ? { kind: 'horizontal' }
134
+ : null;
133
135
  }
134
136
  function isEffectivelyVisible(object) {
135
137
  let current = object;
@@ -1151,9 +1153,7 @@ export const MeasurementTool = () => {
1151
1153
  anchorOrAnchors: anchors,
1152
1154
  lockedGuide: applyMagneticSnap && activeDraft.axisGuide?.snapped ? activeDraft.axisGuide : null,
1153
1155
  planarProximityAnchors: getPlanarProximityAnchors(),
1154
- surfacePreference: applyMagneticSnap
1155
- ? polygonSurfacePreference(activeDraft.kind, activeDraft.collectionPlane)
1156
- : null,
1156
+ surfacePreference: measurementPolygonSurfacePreference(activeDraft.kind, activeDraft.collectionPlane, applyMagneticSnap),
1157
1157
  applyMagneticSnap,
1158
1158
  showAlignmentGuides: isAlignmentGuideActive(),
1159
1159
  });
@@ -1186,9 +1186,7 @@ export const MeasurementTool = () => {
1186
1186
  anchorOrAnchors: draft.points[draft.points.length - 1] ?? null,
1187
1187
  lockedGuide: applyMagneticSnap && draft.axisGuide?.snapped ? draft.axisGuide : null,
1188
1188
  planarProximityAnchors: getPlanarProximityAnchors(),
1189
- surfacePreference: applyMagneticSnap
1190
- ? polygonSurfacePreference(draft.kind, draft.collectionPlane)
1191
- : null,
1189
+ surfacePreference: measurementPolygonSurfacePreference(draft.kind, draft.collectionPlane, applyMagneticSnap),
1192
1190
  applyMagneticSnap,
1193
1191
  showAlignmentGuides: isAlignmentGuideActive(),
1194
1192
  });
@@ -1269,9 +1267,7 @@ export const MeasurementTool = () => {
1269
1267
  anchorOrAnchors: draft.points[draft.points.length - 1] ?? null,
1270
1268
  lockedGuide: applyMagneticSnap && draft.axisGuide?.snapped ? draft.axisGuide : null,
1271
1269
  planarProximityAnchors: getPlanarProximityAnchors(),
1272
- surfacePreference: applyMagneticSnap
1273
- ? polygonSurfacePreference(draft.kind, draft.collectionPlane)
1274
- : null,
1270
+ surfacePreference: measurementPolygonSurfacePreference(draft.kind, draft.collectionPlane, applyMagneticSnap),
1275
1271
  applyMagneticSnap,
1276
1272
  showAlignmentGuides: isAlignmentGuideActive(),
1277
1273
  });
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/pipe-segment/tool.tsx"],"names":[],"mappings":"AAwIA,QAAA,MAAM,eAAe,0CAmjBpB,CAAA;AAkCD,eAAe,eAAe,CAAA"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/pipe-segment/tool.tsx"],"names":[],"mappings":"AAyIA,QAAA,MAAM,eAAe,0CAujBpB,CAAA;AAkCD,eAAe,eAAe,CAAA"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { emitter, PipeSegmentNode, useScene } from '@pascal-app/core';
4
- import { CursorSphere, DimensionPill, EDITOR_LAYER, isAngleSnapActive, isGridSnapActive, isMagneticSnapActive, markToolCancelConsumed, triggerSFX, useEditor, } from '@pascal-app/editor';
4
+ import { CursorSphere, DimensionPill, EDITOR_LAYER, isAngleSnapActive, isGridSnapActive, isMagneticSnapActive, markToolCancelConsumed, triggerSFX, useEditor, usePathDraftPreview, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Html } from '@react-three/drei';
7
7
  import { useEffect, useRef, useState } from 'react';
@@ -124,6 +124,27 @@ const PipeSegmentTool = () => {
124
124
  const startBodyRef = useRef(null);
125
125
  const altAnchorRef = useRef(null);
126
126
  const lastClientYRef = useRef(null);
127
+ const displayStart = draftStart &&
128
+ cursorPos &&
129
+ sloped &&
130
+ system === 'waste' &&
131
+ !startPortRef.current &&
132
+ !startBodyRef.current &&
133
+ !snapTarget &&
134
+ !altActive
135
+ ? [
136
+ draftStart[0],
137
+ draftStart[1] +
138
+ Math.hypot(cursorPos[0] - draftStart[0], cursorPos[2] - draftStart[2]) * DRAIN_SLOPE,
139
+ draftStart[2],
140
+ ]
141
+ : draftStart;
142
+ useEffect(() => {
143
+ usePathDraftPreview
144
+ .getState()
145
+ .setDraft('pipe-segment', displayStart ? [displayStart] : [], cursorPos, { diameter, system });
146
+ }, [cursorPos, diameter, displayStart, system]);
147
+ useEffect(() => () => usePathDraftPreview.getState().clear('pipe-segment'), []);
127
148
  useEffect(() => {
128
149
  if (!activeLevelId)
129
150
  return;
@@ -540,24 +561,6 @@ const PipeSegmentTool = () => {
540
561
  }, [activeLevelId]);
541
562
  if (!activeLevelId)
542
563
  return null;
543
- // Free waste start lifts at commit so the run falls ONTO the grid —
544
- // mirror that here so the preview line / pill match the placed pipe.
545
- // A snapped end (snapTarget set) keeps the start where it is.
546
- const displayStart = draftStart &&
547
- cursorPos &&
548
- sloped &&
549
- system === 'waste' &&
550
- !startPortRef.current &&
551
- !startBodyRef.current &&
552
- !snapTarget &&
553
- !altActive
554
- ? [
555
- draftStart[0],
556
- draftStart[1] +
557
- Math.hypot(cursorPos[0] - draftStart[0], cursorPos[2] - draftStart[2]) * DRAIN_SLOPE,
558
- draftStart[2],
559
- ]
560
- : draftStart;
561
564
  const pillParts = cursorPos
562
565
  ? [
563
566
  ...['x', 'y', 'z'].map((axis, i) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/roof-segment/floorplan-affordances.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EAExB,KAAK,eAAe,EAGrB,MAAM,kBAAkB,CAAA;AA4CzB;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,EAAE,mBAAmB,CAAC,eAAe,CA8C5E,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,EAAE,mBAAmB,CAAC,eAAe,CA4B5E,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,EAAE,mBAAmB,CAAC,eAAe,CAyCtE,CAAA"}
1
+ {"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/roof-segment/floorplan-affordances.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EAExB,KAAK,eAAe,EAIrB,MAAM,kBAAkB,CAAA;AA4CzB;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,EAAE,mBAAmB,CAAC,eAAe,CAgD5E,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,EAAE,mBAAmB,CAAC,eAAe,CA8B5E,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,EAAE,mBAAmB,CAAC,eAAe,CA2CtE,CAAA"}