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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +67 -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 +9 -1
  138. package/dist/fence/lift.d.ts +15 -0
  139. package/dist/fence/lift.d.ts.map +1 -0
  140. package/dist/fence/lift.js +23 -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 +41 -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
@@ -0,0 +1,128 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { resolveConstructionDimensionDrawingOverride, resolveConstructionDimensionDrawingPresentation, setConstructionDimensionDrawingPresentation, setConstructionDimensionDrawingSuppressedSegments, useScene, } from '@pascal-app/core';
4
+ import { ActionButton, ActionGroup, DRAWING_TYPE_OPTIONS, PanelSection, PanelWrapper, SliderControl, triggerSFX, useDrawingView, } from '@pascal-app/editor';
5
+ import { useViewer } from '@pascal-app/viewer';
6
+ import { Trash2 } from 'lucide-react';
7
+ import { useShallow } from 'zustand/react/shallow';
8
+ const MODE_LABELS = {
9
+ linear: 'Linear',
10
+ radius: 'Radius',
11
+ diameter: 'Diameter',
12
+ 'center-mark': 'Center mark',
13
+ chord: 'Chord',
14
+ 'arc-length': 'Arc length',
15
+ angular: 'Angular',
16
+ coordinate: 'Coordinate',
17
+ };
18
+ const DATUM_POLICY_OPTIONS = [
19
+ { label: 'Centerline', value: 'centerline' },
20
+ { label: 'Wall face', value: 'wall-face' },
21
+ { label: 'Structural face', value: 'structural-face' },
22
+ { label: 'Finish face', value: 'finish-face' },
23
+ ];
24
+ const TERMINATOR_OPTIONS = [
25
+ { label: 'Architectural tick', value: 'architectural-tick' },
26
+ { label: 'Filled arrow', value: 'filled-arrow' },
27
+ { label: 'Open arrow', value: 'open-arrow' },
28
+ { label: 'Dot', value: 'dot' },
29
+ ];
30
+ const TEXT_POSITION_OPTIONS = [
31
+ { label: 'Above line', value: 'above' },
32
+ { label: 'Centered on line', value: 'centered' },
33
+ ];
34
+ const IMPERIAL_PRECISION_OPTIONS = [
35
+ { label: 'Nearest inch', value: '1' },
36
+ { label: 'Nearest 1/2 inch', value: '1/2' },
37
+ { label: 'Nearest 1/4 inch', value: '1/4' },
38
+ { label: 'Nearest 1/8 inch', value: '1/8' },
39
+ { label: 'Nearest 1/16 inch', value: '1/16' },
40
+ ];
41
+ const METRIC_NOTATION_OPTIONS = [
42
+ { label: 'Meters', value: 'meters' },
43
+ { label: 'Millimeters', value: 'millimeters' },
44
+ ];
45
+ export default function ConstructionDimensionPanel() {
46
+ const selectedId = useViewer((state) => state.selection.selectedIds[0]);
47
+ const setSelection = useViewer((state) => state.setSelection);
48
+ const dimension = useScene((state) => {
49
+ const node = selectedId ? state.nodes[selectedId] : undefined;
50
+ return node?.type === 'construction-dimension' ? node : null;
51
+ });
52
+ const updateNode = useScene((state) => state.updateNode);
53
+ const deleteNode = useScene((state) => state.deleteNode);
54
+ const activeDrawingType = useDrawingView((state) => state.drawingType);
55
+ if (!(dimension && selectedId))
56
+ return null;
57
+ const update = (patch) => updateNode(dimension.id, patch);
58
+ const supportsCenterMark = ['radius', 'diameter', 'arc-length', 'angular'].includes(dimension.mode);
59
+ const activeDrawingLabel = DRAWING_TYPE_OPTIONS.find((option) => option.id === activeDrawingType)?.label ?? 'Floor plan';
60
+ const activePresentation = resolveConstructionDimensionDrawingPresentation(dimension, activeDrawingType);
61
+ const activeDrawingOverride = resolveConstructionDimensionDrawingOverride(dimension, activeDrawingType);
62
+ const suppressedSegmentsText = formatSuppressedSegments(activeDrawingOverride?.suppressedSegmentIndexes ?? []);
63
+ const updateDrawingPresentation = (drawingType, presentation) => {
64
+ const drawingOverrides = setConstructionDimensionDrawingPresentation(dimension, drawingType, presentation);
65
+ const firstFoundationController = presentation === 'controlled' && !dimension.controllingDimensionId
66
+ ? selectFoundationControllers(useScene.getState().nodes, dimension.id)[0]
67
+ : undefined;
68
+ update({
69
+ drawingOverrides,
70
+ ...(presentation === 'controlled' && !dimension.controllingDimensionId
71
+ ? { controllingDimensionId: firstFoundationController?.id ?? null }
72
+ : {}),
73
+ });
74
+ };
75
+ const updateSuppressedSegments = (value) => {
76
+ update({
77
+ drawingOverrides: setConstructionDimensionDrawingSuppressedSegments(dimension, activeDrawingType, parseSuppressedSegments(value)),
78
+ });
79
+ };
80
+ return (_jsxs(PanelWrapper, { icon: "/icons/blueprint.webp", onClose: () => setSelection({ selectedIds: [] }), title: "Construction Dimension", width: 320, children: [_jsxs(PanelSection, { title: "Dimension", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Mode" }), _jsx("span", { className: "font-medium text-foreground", children: MODE_LABELS[dimension.mode] })] }), _jsx(SliderControl, { label: "Feature count", max: 999, min: 1, onChange: (featureCount) => update({ featureCount }), precision: 0, step: 1, value: dimension.featureCount }), supportsCenterMark ? (_jsxs("label", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Center mark" }), _jsx("input", { checked: dimension.showCenterMark, onChange: (event) => update({ showCenterMark: event.target.checked }), type: "checkbox" })] })) : null] }), _jsxs(PanelSection, { title: "Drawing coordination", children: [_jsx(SelectField, { label: "Primary drawing", onChange: (drawingType) => update({ drawingType: drawingType }), options: DRAWING_TYPE_OPTIONS.map((option) => ({
81
+ label: option.label,
82
+ value: option.id,
83
+ })), value: dimension.drawingType }), _jsx(SelectField, { label: `${activeDrawingLabel} presentation`, onChange: (presentation) => updateDrawingPresentation(activeDrawingType, presentation), options: [
84
+ { label: 'Shown', value: 'shown' },
85
+ { label: 'Omitted', value: 'omit' },
86
+ ...(activeDrawingType === 'floor-plan'
87
+ ? [{ label: 'Controlled by foundation', value: 'controlled' }]
88
+ : []),
89
+ ], value: activePresentation }), activeDrawingType === 'floor-plan' && activePresentation === 'controlled' ? (_jsx(FoundationControllerField, { dimensionId: dimension.id, onChange: (controllingDimensionId) => update({
90
+ controllingDimensionId,
91
+ }), value: dimension.controllingDimensionId ?? '' })) : null, _jsx("p", { className: "text-muted-foreground text-xs", children: "Linked dimensions reuse the controller's associative anchors and update with it." }), _jsx(TextField, { label: `${activeDrawingLabel} suppressed segments`, onCommit: updateSuppressedSegments, placeholder: "e.g. 2, 4", value: suppressedSegmentsText }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Segment numbers are one-based and apply only in this drawing view." })] }), _jsxs(PanelSection, { title: "Notation", children: [_jsx(TextField, { label: "Prefix", onCommit: (prefix) => update({ prefix }), value: dimension.prefix }), _jsx(TextField, { label: "Suffix", onCommit: (suffix) => update({ suffix }), value: dimension.suffix }), _jsx(TextField, { label: "Text override", onCommit: (textOverride) => update({ textOverride: textOverride || null }), placeholder: "Use measured value", value: dimension.textOverride ?? '' })] }), _jsxs(PanelSection, { title: "Standards", children: [_jsx(SelectField, { label: "Datum policy", onChange: (datumPolicy) => update({ datumPolicy: datumPolicy }), options: DATUM_POLICY_OPTIONS, value: dimension.datumPolicy }), _jsx(SelectField, { label: "Terminator", onChange: (terminator) => update({ terminator: terminator }), options: TERMINATOR_OPTIONS, value: dimension.terminator }), _jsx(SelectField, { label: "Text position", onChange: (textPosition) => update({ textPosition: textPosition }), options: TEXT_POSITION_OPTIONS, value: dimension.textPosition }), _jsx(SelectField, { label: "Imperial precision", onChange: (imperialPrecision) => update({
92
+ imperialPrecision: imperialPrecision,
93
+ }), options: IMPERIAL_PRECISION_OPTIONS, value: dimension.imperialPrecision }), _jsx(SelectField, { label: "Metric notation", onChange: (metricNotation) => update({ metricNotation: metricNotation }), options: METRIC_NOTATION_OPTIONS, value: dimension.metricNotation }), _jsx(SliderControl, { label: "Extension gap", max: 0.5, min: 0, onChange: (extensionStartGap) => update({ extensionStartGap }), precision: 3, step: 0.005, value: dimension.extensionStartGap }), _jsx(SliderControl, { label: "Extension overshoot", max: 0.5, min: 0, onChange: (extensionOvershoot) => update({ extensionOvershoot }), precision: 3, step: 0.005, value: dimension.extensionOvershoot })] }), _jsx(PanelSection, { title: "Actions", children: _jsx(ActionGroup, { children: _jsx(ActionButton, { className: "border-red-500/40 text-red-200 hover:bg-red-500/15", icon: _jsx(Trash2, { className: "h-4 w-4" }), label: "Delete", onClick: () => {
94
+ triggerSFX('sfx:structure-delete');
95
+ deleteNode(dimension.id);
96
+ setSelection({ selectedIds: [] });
97
+ } }) }) })] }));
98
+ }
99
+ function selectFoundationControllers(nodes, excludedId) {
100
+ return Object.values(nodes).filter((candidate) => candidate.type === 'construction-dimension' &&
101
+ candidate.id !== excludedId &&
102
+ candidate.drawingType === 'foundation-plan');
103
+ }
104
+ function FoundationControllerField({ dimensionId, value, onChange, }) {
105
+ const foundationControllers = useScene(useShallow((state) => selectFoundationControllers(state.nodes, dimensionId)));
106
+ return (_jsx(SelectField, { disabled: foundationControllers.length === 0, label: "Foundation controller", onChange: (controllingDimensionId) => onChange(controllingDimensionId), options: foundationControllers.map((controller) => ({
107
+ label: controller.name || 'Foundation dimension',
108
+ value: controller.id,
109
+ })), placeholder: "No foundation dimensions", value: value }));
110
+ }
111
+ function parseSuppressedSegments(value) {
112
+ return [
113
+ ...new Set(value
114
+ .split(/[,\s]+/)
115
+ .map((part) => Number.parseInt(part, 10))
116
+ .filter((index) => Number.isInteger(index) && index > 0)
117
+ .map((index) => index - 1)),
118
+ ].sort((left, right) => left - right);
119
+ }
120
+ function formatSuppressedSegments(indexes) {
121
+ return indexes.map((index) => index + 1).join(', ');
122
+ }
123
+ function SelectField({ label, value, options, placeholder, disabled, onChange, }) {
124
+ return (_jsxs("label", { className: "space-y-1 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: label }), _jsxs("select", { className: "w-full rounded-md border border-border/70 bg-background px-2 py-1.5 text-foreground disabled:opacity-50", disabled: disabled, onChange: (event) => onChange(event.target.value), value: value, children: [placeholder && options.length === 0 ? _jsx("option", { value: "", children: placeholder }) : null, options.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value)))] })] }));
125
+ }
126
+ function TextField({ label, value, placeholder, onCommit, }) {
127
+ return (_jsxs("label", { className: "space-y-1 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: label }), _jsx("input", { className: "w-full rounded-md border border-border/70 bg-background px-2 py-1.5 text-foreground", defaultValue: value, onBlur: (event) => onCommit(event.target.value), placeholder: placeholder }, value)] }));
128
+ }
@@ -0,0 +1,3 @@
1
+ import type { ConstructionDimensionNode, ParametricDescriptor } from '@pascal-app/core';
2
+ export declare const constructionDimensionParametrics: ParametricDescriptor<ConstructionDimensionNode>;
3
+ //# sourceMappingURL=parametrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parametrics.d.ts","sourceRoot":"","sources":["../../src/construction-dimension/parametrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEvF,eAAO,MAAM,gCAAgC,EAAE,oBAAoB,CAAC,yBAAyB,CAG5F,CAAA"}
@@ -0,0 +1,4 @@
1
+ export const constructionDimensionParametrics = {
2
+ groups: [],
3
+ customPanel: () => import('./panel'),
4
+ };
@@ -0,0 +1,2 @@
1
+ export { ConstructionDimensionBaseline, ConstructionDimensionChainMode, ConstructionDimensionMode, ConstructionDimensionNode, } from '@pascal-app/core';
2
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/construction-dimension/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,EAC9B,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1 @@
1
+ export { ConstructionDimensionBaseline, ConstructionDimensionChainMode, ConstructionDimensionMode, ConstructionDimensionNode, } from '@pascal-app/core';
@@ -0,0 +1,3 @@
1
+ import type { DoorNode, FloorplanGeometry, GeometryContext } from '@pascal-app/core';
2
+ export declare function buildDoorContextualDimensions(node: DoorNode, ctx: GeometryContext): FloorplanGeometry | null;
3
+ //# sourceMappingURL=contextual-dimensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextual-dimensions.d.ts","sourceRoot":"","sources":["../../src/door/contextual-dimensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGpF,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,eAAe,GACnB,iBAAiB,GAAG,IAAI,CAK1B"}
@@ -0,0 +1,7 @@
1
+ import { buildWallHostedOpeningContextualDimensions } from '../wall/contextual-dimensions';
2
+ export function buildDoorContextualDimensions(node, ctx) {
3
+ return buildWallHostedOpeningContextualDimensions(node, ctx, {
4
+ showClearancesWhileMoving: false,
5
+ useExteriorNormal: false,
6
+ });
7
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/door/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,cAAc,EAGf,MAAM,kBAAkB,CAAA;AAWzB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAkInC;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,OAAO,QAAQ,CA6G1D,CAAA"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/door/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,cAAc,EAGf,MAAM,kBAAkB,CAAA;AAkBzB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AA4HnC;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,OAAO,QAAQ,CAqH1D,CAAA"}
@@ -1,7 +1,10 @@
1
+ import { buildDoorFloorplanSchedule, computeDoorFloorplanLevelData, } from '../shared/opening-documentation';
1
2
  import { publishOpeningResizeGuides } from '../shared/opening-guides-runtime';
2
3
  import { readRoofFaceHeightMax, readRoofFaceWidthMax } from '../shared/roof-opening-host';
3
4
  import { buildRoofWallOpeningCut } from '../shared/roof-wall-opening-cut';
5
+ import { readHostWallCeiling } from '../shared/wall-opening-ceiling';
4
6
  import { wallFloorplanSiblingOverrides } from '../wall/floorplan-overrides';
7
+ import { buildDoorContextualDimensions } from './contextual-dimensions';
5
8
  import { scaleHandleHeight } from './door-math';
6
9
  import { buildDoorFloorplan } from './floorplan';
7
10
  import { doorWidthAffordance } from './floorplan-affordances';
@@ -25,12 +28,6 @@ function readWallLength(door, scene) {
25
28
  return Number.POSITIVE_INFINITY;
26
29
  return Math.hypot(wall.end[0] - wall.start[0], wall.end[1] - wall.start[1]);
27
30
  }
28
- function readWallHeight(door, scene) {
29
- if (!door.wallId)
30
- return Number.POSITIVE_INFINITY;
31
- const wall = scene.get(door.wallId);
32
- return wall?.height ?? Number.POSITIVE_INFINITY;
33
- }
34
31
  // Width arrow on the door-local +X (right) or -X (left) side. Drag grows
35
32
  // the door from the anchored OPPOSITE edge; the door's wall-local center
36
33
  // re-centers so the anchored edge stays put.
@@ -92,7 +89,7 @@ function doorHeightHandle() {
92
89
  if (roofMax !== null)
93
90
  return Math.max(MIN_DOOR_HEIGHT, roofMax);
94
91
  const bottom = n.position[1] - n.height / 2;
95
- return Math.max(MIN_DOOR_HEIGHT, readWallHeight(n, scene) - bottom);
92
+ return Math.max(MIN_DOOR_HEIGHT, readHostWallCeiling(n.wallId, scene) - bottom);
96
93
  },
97
94
  currentValue: (n) => n.height,
98
95
  onDrag: (node) => publishOpeningResizeGuides(node, false),
@@ -158,9 +155,15 @@ export const doorDefinition = {
158
155
  kind: 'door',
159
156
  snapProfile: 'item',
160
157
  facingIndicator: true,
161
- schemaVersion: 1,
158
+ schemaVersion: 2,
162
159
  schema: DoorNode,
163
160
  category: 'structure',
161
+ extensions: {
162
+ 'pascal:editor/floorplan': {
163
+ contextualDimensions: buildDoorContextualDimensions,
164
+ schedule: buildDoorFloorplanSchedule,
165
+ },
166
+ },
164
167
  surfaceRole: 'joinery',
165
168
  // Leverage the schema's zod `.default()` annotations to compute the
166
169
  // full default shape — door has 40+ fields, listing them inline would
@@ -201,6 +204,7 @@ export const doorDefinition = {
201
204
  kind: 'parametric',
202
205
  module: () => import('./renderer'),
203
206
  },
207
+ preview: () => import('./preview'),
204
208
  system: {
205
209
  module: () => import('./system'),
206
210
  // Priority 3 mirrors the legacy DoorSystem (after animation at 2,
@@ -210,6 +214,7 @@ export const doorDefinition = {
210
214
  // Stage C: floor-plan polygon. Needs ctx.parent (the wall) to compute
211
215
  // direction + perpendicular for the cutout footprint.
212
216
  floorplan: buildDoorFloorplan,
217
+ computeFloorplanLevelData: computeDoorFloorplanLevelData,
213
218
  floorplanDependsOnSiblings: true,
214
219
  // Opening symbols position from `ctx.parent` (the host wall); merge the
215
220
  // walls' live drag overrides so the symbol tracks a wall / group drag in
@@ -11,11 +11,8 @@ import { type DoorNode, type FloorplanAffordance } from '@pascal-app/core';
11
11
  * - `'end'`: arrow at the edge closer to `wall.end`. The wall-start
12
12
  * edge stays fixed.
13
13
  *
14
- * Uses the scene-write preview pattern (writes directly to `useScene`
15
- * each tick): the registry layer's `effectiveNode` only merges live
16
- * overrides for walls, so an override-based preview wouldn't show on
17
- * doors. The dispatcher snapshots / pauses history at start, so per-tick
18
- * scene writes still collapse to one undoable entry on commit.
14
+ * Preview state stays in the live override store so the scene graph is
15
+ * written only once, when the drag commits.
19
16
  */
20
17
  export declare const doorWidthAffordance: FloorplanAffordance<DoorNode>;
21
18
  //# sourceMappingURL=floorplan-affordances.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/door/floorplan-affordances.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,mBAAmB,EAIzB,MAAM,kBAAkB,CAAA;AAMzB;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,mBAAmB,EAAE,mBAAmB,CAAC,QAAQ,CA6F7D,CAAA"}
1
+ {"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/door/floorplan-affordances.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,mBAAmB,EAKzB,MAAM,kBAAkB,CAAA;AAMzB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,EAAE,mBAAmB,CAAC,QAAQ,CAuF7D,CAAA"}
@@ -1,4 +1,4 @@
1
- import { useScene, } from '@pascal-app/core';
1
+ import { useLiveNodeOverrides, useScene, } from '@pascal-app/core';
2
2
  const MIN_DOOR_WIDTH = 0.3;
3
3
  /**
4
4
  * 2D drag affordance for the door's width side-arrows. Sister to the 3D
@@ -12,11 +12,8 @@ const MIN_DOOR_WIDTH = 0.3;
12
12
  * - `'end'`: arrow at the edge closer to `wall.end`. The wall-start
13
13
  * edge stays fixed.
14
14
  *
15
- * Uses the scene-write preview pattern (writes directly to `useScene`
16
- * each tick): the registry layer's `effectiveNode` only merges live
17
- * overrides for walls, so an override-based preview wouldn't show on
18
- * doors. The dispatcher snapshots / pauses history at start, so per-tick
19
- * scene writes still collapse to one undoable entry on commit.
15
+ * Preview state stays in the live override store so the scene graph is
16
+ * written only once, when the drag commits.
20
17
  */
21
18
  export const doorWidthAffordance = {
22
19
  start({ node, payload, nodes, initialPlanPoint }) {
@@ -63,18 +60,11 @@ export const doorWidthAffordance = {
63
60
  const newDoorX = anchorX + growDir * (newWidth / 2);
64
61
  lastWidth = newWidth;
65
62
  lastDoorX = newDoorX;
66
- // Scene-write preview so the 2D plan + 3D viewer both pick up
67
- // the change immediately. The dispatcher paused history at
68
- // session start, so per-tick writes don't pollute undo.
69
- useScene.getState().updateNodes([
70
- {
71
- id: doorId,
72
- data: {
73
- width: newWidth,
74
- position: [newDoorX, initialDoorY, initialDoorZ],
75
- },
76
- },
77
- ]);
63
+ useLiveNodeOverrides.getState().set(doorId, {
64
+ width: newWidth,
65
+ position: [newDoorX, initialDoorY, initialDoorZ],
66
+ });
67
+ useScene.getState().markDirty(doorId);
78
68
  },
79
69
  canCommit() {
80
70
  // Width is always clamped to >= MIN_DOOR_WIDTH inside apply, so
@@ -87,6 +77,7 @@ export const doorWidthAffordance = {
87
77
  // fields that differ from the pre-drag snapshot — if the user
88
78
  // drags back to the original size by accident, the diff is empty
89
79
  // and the door would otherwise revert to its starting state).
80
+ useLiveNodeOverrides.getState().clear(doorId);
90
81
  useScene.getState().updateNodes([
91
82
  {
92
83
  id: doorId,
@@ -28,10 +28,9 @@ import type { DoorNode, FloorplanGeometry, GeometryContext } from '@pascal-app/c
28
28
  * mounted on). Returns null when the parent isn't a wall (orphaned
29
29
  * doors during placement etc.).
30
30
  *
31
- * Skipped vs the full legacy for now: hinge / strike cubes (small
32
- * indicator squares at the rotation pivots), rounded-opening shape
33
- * variants, panic bar markers. Those are rare visual variations the
34
- * follow-up port can revisit.
31
+ * Swing leaves include hinge / strike indicators and panic hardware
32
+ * when present. Rounded and arched heads are shown as dashed overhead
33
+ * lines because their geometry sits above the horizontal plan cut.
35
34
  */
36
35
  export declare function buildDoorFloorplan(node: DoorNode, ctx: GeometryContext): FloorplanGeometry | null;
37
36
  //# sourceMappingURL=floorplan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/door/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,iBAAiB,EAEjB,eAAe,EAEhB,MAAM,kBAAkB,CAAA;AAGzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CA0qBjG"}
1
+ {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/door/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,iBAAiB,EAEjB,eAAe,EAEhB,MAAM,kBAAkB,CAAA;AAYzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CAmvBjG"}
@@ -1,3 +1,5 @@
1
+ import { readFloorplanContext, readFloorplanGeometryMetadata, withFloorplanGeometryMetadata, } from '@pascal-app/editor';
2
+ import { buildOpeningMarkAnnotation, } from '../shared/opening-documentation';
1
3
  import { buildOpeningPlacementDimensions } from '../shared/opening-placement-dimensions';
2
4
  /**
3
5
  * Stage C floor-plan builder for door. 1:1 visual port of the legacy
@@ -28,10 +30,9 @@ import { buildOpeningPlacementDimensions } from '../shared/opening-placement-dim
28
30
  * mounted on). Returns null when the parent isn't a wall (orphaned
29
31
  * doors during placement etc.).
30
32
  *
31
- * Skipped vs the full legacy for now: hinge / strike cubes (small
32
- * indicator squares at the rotation pivots), rounded-opening shape
33
- * variants, panic bar markers. Those are rare visual variations the
34
- * follow-up port can revisit.
33
+ * Swing leaves include hinge / strike indicators and panic hardware
34
+ * when present. Rounded and arched heads are shown as dashed overhead
35
+ * lines because their geometry sits above the horizontal plan cut.
35
36
  */
36
37
  export function buildDoorFloorplan(node, ctx) {
37
38
  const wall = ctx.parent;
@@ -103,6 +104,25 @@ export function buildDoorFloorplan(node, ctx) {
103
104
  strokeLinejoin: 'round',
104
105
  },
105
106
  ];
107
+ if (node.openingShape !== 'rectangle') {
108
+ const overheadRise = Math.min(width, node.openingShape === 'arch' ? node.archHeight : node.cornerRadius) * 0.2;
109
+ const overheadSide = swingDirection === 'inward' ? 1 : -1;
110
+ const startX = cx - dirX * halfWidth;
111
+ const startZ = cz - dirZ * halfWidth;
112
+ const endX = cx + dirX * halfWidth;
113
+ const endZ = cz + dirZ * halfWidth;
114
+ children.push({
115
+ kind: 'path',
116
+ d: `M ${startX} ${startZ} Q ${cx + perpX * overheadRise * overheadSide} ${cz + perpZ * overheadRise * overheadSide} ${endX} ${endZ}`,
117
+ fill: 'none',
118
+ stroke: accentColor,
119
+ strokeWidth: showSelectedChrome ? 1.4 : 1,
120
+ strokeOpacity: 0.8,
121
+ strokeDasharray: '4 3',
122
+ strokeLinecap: 'round',
123
+ vectorEffect: 'non-scaling-stroke',
124
+ });
125
+ }
106
126
  // Swing geometry. A leaf is drawn as a wedge fill + dashed swing arc +
107
127
  // solid leaf line. `drawSwingLeaf` emits one leaf given its hinge, the
108
128
  // closed-leaf vector (hinge → strike, whose length is the swing
@@ -161,6 +181,45 @@ export function buildDoorFloorplan(node, ctx) {
161
181
  strokeLinecap: 'round',
162
182
  vectorEffect: 'non-scaling-stroke',
163
183
  });
184
+ const markerSize = Math.min(0.05, Math.max(0.025, radius * 0.05));
185
+ const markerHalf = markerSize / 2;
186
+ const hardwareMarkers = [
187
+ [hX, hZ],
188
+ [closedTipX, closedTipZ],
189
+ ];
190
+ for (const [markerX, markerZ] of hardwareMarkers) {
191
+ children.push({
192
+ kind: 'rect',
193
+ x: markerX - markerHalf,
194
+ y: markerZ - markerHalf,
195
+ width: markerSize,
196
+ height: markerSize,
197
+ fill: fillColor,
198
+ stroke: accentColor,
199
+ strokeWidth: showSelectedChrome ? 1.4 : 1,
200
+ vectorEffect: 'non-scaling-stroke',
201
+ });
202
+ }
203
+ if (node.panicBar) {
204
+ const leafX = (tipX - hX) / radius;
205
+ const leafZ = (tipZ - hZ) / radius;
206
+ const barCenterX = hX + leafX * radius * 0.7;
207
+ const barCenterZ = hZ + leafZ * radius * 0.7;
208
+ const barHalfLength = Math.min(0.12, Math.max(0.06, depth * 0.75));
209
+ const barX = -leafZ * barHalfLength;
210
+ const barZ = leafX * barHalfLength;
211
+ children.push({
212
+ kind: 'line',
213
+ x1: barCenterX - barX,
214
+ y1: barCenterZ - barZ,
215
+ x2: barCenterX + barX,
216
+ y2: barCenterZ + barZ,
217
+ stroke: accentColor,
218
+ strokeWidth: showSelectedChrome ? 2.6 : 2.2,
219
+ strokeLinecap: 'square',
220
+ vectorEffect: 'non-scaling-stroke',
221
+ });
222
+ }
164
223
  };
165
224
  const isDoubleLeaf = node.doorType === 'double' || node.doorType === 'french';
166
225
  const isFolding = node.doorType === 'folding';
@@ -681,12 +740,35 @@ export function buildDoorFloorplan(node, ctx) {
681
740
  // Placement-measurement dimensions — distances to adjacent openings
682
741
  // (or wall ends) on each side. Only visible while actively moving
683
742
  // (the user clicked Move or grabbed the orange dot).
684
- if (view?.moving) {
743
+ if (view?.moving && readFloorplanContext(ctx).automaticDimensions) {
685
744
  for (const dim of buildOpeningPlacementDimensions(node, ctx)) {
686
745
  children.push(dim);
687
746
  }
688
747
  }
689
- return { kind: 'group', children };
748
+ const markAnnotation = buildOpeningMarkAnnotation(node, wall, ctx.levelData, {
749
+ preferredSide: swingSign === 1 ? -1 : 1,
750
+ stroke: showSelectedChrome ? '#f97316' : '#334155',
751
+ });
752
+ if (markAnnotation)
753
+ children.push(markAnnotation);
754
+ return { kind: 'group', children: children.map(markDoorPlanObstacle) };
755
+ }
756
+ function markDoorPlanObstacle(geometry) {
757
+ if (geometry.kind === 'group') {
758
+ const isOpeningMark = readFloorplanGeometryMetadata(geometry).annotationRole === 'opening-mark';
759
+ return isOpeningMark
760
+ ? geometry
761
+ : { ...geometry, children: geometry.children.map(markDoorPlanObstacle) };
762
+ }
763
+ if (geometry.kind === 'path' ||
764
+ geometry.kind === 'polygon' ||
765
+ geometry.kind === 'polyline' ||
766
+ geometry.kind === 'rect' ||
767
+ geometry.kind === 'circle' ||
768
+ geometry.kind === 'line') {
769
+ return withFloorplanGeometryMetadata(geometry, { annotationObstacle: 'bounds' });
770
+ }
771
+ return geometry;
690
772
  }
691
773
  /**
692
774
  * The opening's wall-normal orientation is encoded in the door's Y
@@ -1 +1 @@
1
- {"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/door/move-tool.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAWT,MAAM,kBAAkB,CAAA;AA6CzB,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAg+B9C,CAAA;AAED,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/door/move-tool.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAWT,MAAM,kBAAkB,CAAA;AA6CzB,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAs+B9C,CAAA;AAED,eAAe,YAAY,CAAA"}
@@ -155,7 +155,7 @@ const MoveDoorTool = ({ node: movingDoorNode }) => {
155
155
  const id = getLevelId();
156
156
  return id ? (sceneRegistry.nodes.get(id)?.position.y ?? 0) : 0;
157
157
  };
158
- const getSlabElevation = (wallEvent) => spatialGridManager.getSlabElevationForWall(wallEvent.node.parentId ?? '', wallEvent.node.start, wallEvent.node.end);
158
+ const getSlabElevation = (wallEvent) => spatialGridManager.getSlabElevationForWall(wallEvent.node.parentId ?? '', wallEvent.node.start, wallEvent.node.end, wallEvent.node.curveOffset ?? 0, wallEvent.node.thickness, wallEvent.node.supportSlabId);
159
159
  const hideCursor = () => {
160
160
  if (cursorGroupRef.current)
161
161
  cursorGroupRef.current.visible = false;
@@ -821,7 +821,7 @@ const MoveDoorTool = ({ node: movingDoorNode }) => {
821
821
  if (hostWall?.type === 'wall') {
822
822
  const wallAngle = Math.atan2(hostWall.end[1] - hostWall.start[1], hostWall.end[0] - hostWall.start[0]);
823
823
  const ghostYaw = movingDoorNode.rotation[1] - wallAngle;
824
- const seedPos = wallLocalToWorld(hostWall, movingDoorNode.position[0], movingDoorNode.position[1], getLevelYOffset(), spatialGridManager.getSlabElevationForWall(hostWall.parentId ?? '', hostWall.start, hostWall.end));
824
+ const seedPos = wallLocalToWorld(hostWall, movingDoorNode.position[0], movingDoorNode.position[1], getLevelYOffset(), spatialGridManager.getSlabElevationForWall(hostWall.parentId ?? '', hostWall.start, hostWall.end, hostWall.curveOffset ?? 0, hostWall.thickness, hostWall.supportSlabId));
825
825
  publishPlacementSurface(new Vector3(...seedPos), new Vector3(Math.sin(ghostYaw), 0, Math.cos(ghostYaw)));
826
826
  // Claim the pointer for the wall so the floor free-follow stands down for
827
827
  // the first frames after grab. Otherwise the first `grid:move` (the door
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/door/panel.tsx"],"names":[],"mappings":"AAsIA,MAAM,CAAC,OAAO,UAAU,SAAS,uCAmoChC"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/door/panel.tsx"],"names":[],"mappings":"AAuIA,MAAM,CAAC,OAAO,UAAU,SAAS,uCAmpChC"}
@@ -5,6 +5,7 @@ import { ActionButton, ActionGroup, cn, PanelSection, PanelWrapper, SegmentedCon
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Copy, DoorOpen, FlipHorizontal2, Move, Trash2 } from 'lucide-react';
7
7
  import { useCallback, useRef } from 'react';
8
+ import { OpeningDocumentationFields } from '../shared/opening-documentation-fields';
8
9
  import { scaleHandleHeight } from './door-math';
9
10
  const doorTypeOptions = [
10
11
  { label: 'Hinged', value: 'hinged', available: true },
@@ -201,6 +202,7 @@ export default function DoorPanel() {
201
202
  useScene.temporal.getState().pause();
202
203
  const cloned = structuredClone(node);
203
204
  delete cloned.id;
205
+ delete cloned.mark;
204
206
  cloned.metadata = { ...cloned.metadata, isNew: true };
205
207
  const duplicate = DoorNode.parse(cloned);
206
208
  useScene.getState().createNode(duplicate, node.parentId);
@@ -476,7 +478,7 @@ export default function DoorPanel() {
476
478
  ? 'border-orange-400/60 bg-orange-400/10 text-foreground'
477
479
  : 'border-border/50 bg-[#2C2C2E] text-muted-foreground hover:bg-[#3e3e3e] hover:text-foreground', !option.available &&
478
480
  'cursor-not-allowed opacity-45 hover:bg-[#2C2C2E] hover:text-muted-foreground'), disabled: !option.available, onClick: () => handleUpdate(getDoorTypeUpdates(option.value)), type: "button", children: [_jsx(DoorOpen, { className: "h-4 w-4 shrink-0" }), _jsx("span", { className: "truncate font-medium", children: option.label })] }, option.value));
479
- }) }))] }), _jsxs(PanelSection, { title: "Position", children: [_jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["X", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "wall" })] }), max: 10, min: -10, onChange: (v) => handleUpdate({ position: [v, node.position[1], node.position[2]] }), precision: 2, step: 0.1, unit: "m", value: Math.round(node.position[0] * 100) / 100 }), showFlipSide && (_jsx("div", { className: "px-1 pt-2 pb-1", children: _jsx(ActionButton, { className: "w-full", icon: _jsx(FlipHorizontal2, { className: "h-4 w-4" }), label: "Flip Side", onClick: handleFlip }) }))] }), showFoldSection && (_jsxs(PanelSection, { title: "Fold", children: [_jsx("div", { className: "flex flex-col gap-2 px-1 pb-1", children: _jsxs("div", { className: "space-y-1", children: [_jsx("span", { className: "font-medium text-[10px] text-muted-foreground/80 uppercase tracking-wider", children: "Panels" }), _jsx(SegmentedControl, { onChange: (v) => handleUpdate({ leafCount: v === '2' ? 2 : 4 }), options: [
481
+ }) }))] }), _jsx(PanelSection, { title: "Documentation", children: _jsx(OpeningDocumentationFields, { constructionType: node.constructionType, dimensionReference: node.dimensionReference, finishOpeningHeight: node.finishOpeningHeight, finishOpeningWidth: node.finishOpeningWidth, mark: node.mark, masonryOpeningHeight: node.masonryOpeningHeight, masonryOpeningWidth: node.masonryOpeningWidth, onChange: handleUpdate, roughOpeningHeight: node.roughOpeningHeight, roughOpeningWidth: node.roughOpeningWidth }) }), _jsxs(PanelSection, { title: "Position", children: [_jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["X", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "wall" })] }), max: 10, min: -10, onChange: (v) => handleUpdate({ position: [v, node.position[1], node.position[2]] }), precision: 2, step: 0.1, unit: "m", value: Math.round(node.position[0] * 100) / 100 }), showFlipSide && (_jsx("div", { className: "px-1 pt-2 pb-1", children: _jsx(ActionButton, { className: "w-full", icon: _jsx(FlipHorizontal2, { className: "h-4 w-4" }), label: "Flip Side", onClick: handleFlip }) }))] }), showFoldSection && (_jsxs(PanelSection, { title: "Fold", children: [_jsx("div", { className: "flex flex-col gap-2 px-1 pb-1", children: _jsxs("div", { className: "space-y-1", children: [_jsx("span", { className: "font-medium text-[10px] text-muted-foreground/80 uppercase tracking-wider", children: "Panels" }), _jsx(SegmentedControl, { onChange: (v) => handleUpdate({ leafCount: v === '2' ? 2 : 4 }), options: [
480
482
  { label: '2', value: '2' },
481
483
  { label: '4', value: '4' },
482
484
  ], value: node.leafCount === 2 ? '2' : '4' })] }) }), _jsx(SliderControl, { label: "Open", max: 100, min: 0, onChange: (v) => handleUpdate({ operationState: v / 100 }), precision: 0, restoreOnCommit: false, step: 5, unit: "%", value: Math.round((node.operationState ?? 0) * 100) })] })), showSlideSection && (_jsxs(PanelSection, { title: "Slide", children: [_jsx("div", { className: "flex flex-col gap-2 px-1 pb-1", children: _jsxs("div", { className: "space-y-1", children: [_jsx("span", { className: "font-medium text-[10px] text-muted-foreground/80 uppercase tracking-wider", children: doorType === 'pocket' ? 'Pocket' : doorType === 'barn' ? 'Rail' : 'Panel' }), _jsx(SegmentedControl, { onChange: (v) => handleUpdate({ slideDirection: v }), options: [
@@ -1,2 +1,2 @@
1
- export { DoorNode } from '@pascal-app/core';
1
+ export { DoorNode, OpeningConstructionType, OpeningDimensionReference, } from '@pascal-app/core';
2
2
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/door/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/door/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,kBAAkB,CAAA"}
@@ -1 +1 @@
1
- export { DoorNode } from '@pascal-app/core';
1
+ export { DoorNode, OpeningConstructionType, OpeningDimensionReference, } from '@pascal-app/core';
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/door/tool.tsx"],"names":[],"mappings":"AA8DA;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAmnBrB,CAAA;AAED,eAAe,QAAQ,CAAA"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/door/tool.tsx"],"names":[],"mappings":"AAiEA;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAkrBrB,CAAA;AAED,eAAe,QAAQ,CAAA"}