@pascal-app/nodes 1.0.3 → 1.0.4

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 (708) hide show
  1. package/dist/block/definition.d.ts.map +1 -1
  2. package/dist/block/definition.js +18 -3
  3. package/dist/block/floorplan.d.ts +11 -1
  4. package/dist/block/floorplan.d.ts.map +1 -1
  5. package/dist/block/floorplan.js +81 -13
  6. package/dist/block/geometry.d.ts +2 -2
  7. package/dist/block/geometry.d.ts.map +1 -1
  8. package/dist/block/geometry.js +39 -24
  9. package/dist/block/hosted-edit.d.ts.map +1 -1
  10. package/dist/block/hosted-edit.js +25 -0
  11. package/dist/block/material-slots.d.ts +1 -3
  12. package/dist/block/material-slots.d.ts.map +1 -1
  13. package/dist/block/material-slots.js +1 -11
  14. package/dist/block/paint.d.ts.map +1 -1
  15. package/dist/block/paint.js +4 -10
  16. package/dist/block/panel.d.ts.map +1 -1
  17. package/dist/block/panel.js +8 -3
  18. package/dist/block/selection.d.ts.map +1 -1
  19. package/dist/block/selection.js +2 -2
  20. package/dist/box-vent/definition.d.ts.map +1 -1
  21. package/dist/box-vent/definition.js +2 -5
  22. package/dist/box-vent/panel.d.ts.map +1 -1
  23. package/dist/box-vent/panel.js +5 -28
  24. package/dist/cabinet/countertop-layout.d.ts +13 -2
  25. package/dist/cabinet/countertop-layout.d.ts.map +1 -1
  26. package/dist/cabinet/definition.d.ts.map +1 -1
  27. package/dist/cabinet/definition.js +1 -2
  28. package/dist/cabinet/floorplan.d.ts.map +1 -1
  29. package/dist/cabinet/floorplan.js +125 -28
  30. package/dist/cabinet/geometry/shared.d.ts +1 -2
  31. package/dist/cabinet/geometry/shared.d.ts.map +1 -1
  32. package/dist/cabinet/geometry/shared.js +1 -2
  33. package/dist/cabinet/run-layout.d.ts.map +1 -1
  34. package/dist/cabinet/run-layout.js +8 -5
  35. package/dist/cabinet/run-ops.d.ts +13 -2
  36. package/dist/cabinet/run-ops.d.ts.map +1 -1
  37. package/dist/cabinet/tool.d.ts.map +1 -1
  38. package/dist/cabinet/tool.js +22 -24
  39. package/dist/cabinet/wall-snap.d.ts.map +1 -1
  40. package/dist/cabinet/wall-snap.js +8 -8
  41. package/dist/ceiling/boundary-editor.d.ts.map +1 -1
  42. package/dist/ceiling/boundary-editor.js +5 -3
  43. package/dist/ceiling/definition.d.ts +4 -4
  44. package/dist/ceiling/definition.d.ts.map +1 -1
  45. package/dist/ceiling/definition.js +15 -15
  46. package/dist/ceiling/floorplan-affordances.d.ts +84 -4
  47. package/dist/ceiling/floorplan-affordances.d.ts.map +1 -1
  48. package/dist/ceiling/floorplan-affordances.js +0 -1
  49. package/dist/ceiling/floorplan-move.d.ts.map +1 -1
  50. package/dist/ceiling/floorplan-move.js +0 -1
  51. package/dist/ceiling/floorplan.d.ts +1 -1
  52. package/dist/ceiling/floorplan.d.ts.map +1 -1
  53. package/dist/ceiling/floorplan.js +2 -1
  54. package/dist/ceiling/height-bounds.d.ts +19 -0
  55. package/dist/ceiling/height-bounds.d.ts.map +1 -0
  56. package/dist/ceiling/height-bounds.js +24 -0
  57. package/dist/ceiling/hole-editor.d.ts.map +1 -1
  58. package/dist/ceiling/hole-editor.js +3 -4
  59. package/dist/ceiling/materials.d.ts +1 -1
  60. package/dist/ceiling/materials.d.ts.map +1 -1
  61. package/dist/ceiling/materials.js +10 -3
  62. package/dist/ceiling/paint.d.ts +2 -8
  63. package/dist/ceiling/paint.d.ts.map +1 -1
  64. package/dist/ceiling/paint.js +121 -24
  65. package/dist/ceiling/panel.d.ts.map +1 -1
  66. package/dist/ceiling/panel.js +40 -23
  67. package/dist/ceiling/renderer.d.ts.map +1 -1
  68. package/dist/ceiling/renderer.js +41 -5
  69. package/dist/chimney/move-tool.d.ts.map +1 -1
  70. package/dist/chimney/move-tool.js +8 -2
  71. package/dist/chimney/paint.d.ts.map +1 -1
  72. package/dist/chimney/paint.js +3 -10
  73. package/dist/column/definition.d.ts.map +1 -1
  74. package/dist/column/definition.js +24 -2
  75. package/dist/column/floorplan-affordances.d.ts.map +1 -1
  76. package/dist/column/floorplan-affordances.js +5 -0
  77. package/dist/column/floorplan.d.ts +1 -1
  78. package/dist/column/floorplan.d.ts.map +1 -1
  79. package/dist/column/floorplan.js +47 -2
  80. package/dist/column/hosted-resize.d.ts +101 -2
  81. package/dist/column/hosted-resize.d.ts.map +1 -1
  82. package/dist/column/panel.d.ts.map +1 -1
  83. package/dist/column/panel.js +147 -146
  84. package/dist/column/renderer.d.ts.map +1 -1
  85. package/dist/column/renderer.js +6 -4
  86. package/dist/column/surface.d.ts.map +1 -1
  87. package/dist/column/surface.js +7 -0
  88. package/dist/construction-dimension/floorplan.js +7 -3
  89. package/dist/cupola/definition.d.ts.map +1 -1
  90. package/dist/cupola/definition.js +2 -8
  91. package/dist/cupola/panel.d.ts.map +1 -1
  92. package/dist/cupola/panel.js +5 -23
  93. package/dist/door/definition.d.ts.map +1 -1
  94. package/dist/door/definition.js +12 -3
  95. package/dist/door/door-math.d.ts +5 -10
  96. package/dist/door/door-math.d.ts.map +1 -1
  97. package/dist/door/door-math.js +14 -15
  98. package/dist/door/floorplan-move.d.ts.map +1 -1
  99. package/dist/door/floorplan-move.js +3 -1
  100. package/dist/door/floorplan.d.ts.map +1 -1
  101. package/dist/door/floorplan.js +55 -21
  102. package/dist/door/mechanism.d.ts +4 -0
  103. package/dist/door/mechanism.d.ts.map +1 -0
  104. package/dist/door/mechanism.js +24 -0
  105. package/dist/door/move-tool.d.ts.map +1 -1
  106. package/dist/door/move-tool.js +72 -48
  107. package/dist/door/paint.d.ts.map +1 -1
  108. package/dist/door/paint.js +3 -0
  109. package/dist/door/panel.d.ts.map +1 -1
  110. package/dist/door/panel.js +34 -259
  111. package/dist/door/placement.d.ts +45 -0
  112. package/dist/door/placement.d.ts.map +1 -0
  113. package/dist/door/placement.js +51 -0
  114. package/dist/door/preview.d.ts.map +1 -1
  115. package/dist/door/preview.js +2 -0
  116. package/dist/door/renderer.d.ts.map +1 -1
  117. package/dist/door/renderer.js +3 -2
  118. package/dist/door/tool.d.ts.map +1 -1
  119. package/dist/door/tool.js +92 -21
  120. package/dist/dormer/csg-geometry.d.ts.map +1 -1
  121. package/dist/dormer/csg-geometry.js +2 -0
  122. package/dist/dormer/paint.d.ts.map +1 -1
  123. package/dist/dormer/paint.js +2 -5
  124. package/dist/dormer/panel.d.ts.map +1 -1
  125. package/dist/dormer/panel.js +4 -14
  126. package/dist/downspout/definition.d.ts.map +1 -1
  127. package/dist/downspout/definition.js +2 -2
  128. package/dist/duct-fitting/definition.d.ts.map +1 -1
  129. package/dist/duct-fitting/definition.js +2 -1
  130. package/dist/duct-fitting/geometry.d.ts.map +1 -1
  131. package/dist/duct-fitting/geometry.js +1 -1
  132. package/dist/duct-fitting/move-tool.d.ts.map +1 -1
  133. package/dist/duct-fitting/move-tool.js +8 -2
  134. package/dist/duct-segment/definition.d.ts.map +1 -1
  135. package/dist/duct-segment/definition.js +2 -2
  136. package/dist/duct-segment/geometry.d.ts.map +1 -1
  137. package/dist/duct-segment/geometry.js +1 -1
  138. package/dist/duct-segment/move-tool.d.ts.map +1 -1
  139. package/dist/duct-segment/move-tool.js +8 -2
  140. package/dist/elevator/definition.d.ts.map +1 -1
  141. package/dist/elevator/definition.js +1 -2
  142. package/dist/elevator/panel.d.ts.map +1 -1
  143. package/dist/elevator/panel.js +5 -27
  144. package/dist/elevator/parametrics.js +1 -1
  145. package/dist/elevator/renderer.d.ts.map +1 -1
  146. package/dist/elevator/renderer.js +3 -4
  147. package/dist/eyebrow-vent/definition.d.ts.map +1 -1
  148. package/dist/eyebrow-vent/definition.js +2 -5
  149. package/dist/eyebrow-vent/paint.d.ts.map +1 -1
  150. package/dist/eyebrow-vent/paint.js +3 -6
  151. package/dist/eyebrow-vent/panel.d.ts.map +1 -1
  152. package/dist/eyebrow-vent/panel.js +5 -23
  153. package/dist/fence/actions/move-endpoint.d.ts +1 -1
  154. package/dist/fence/actions/move-endpoint.d.ts.map +1 -1
  155. package/dist/fence/actions/move-endpoint.js +2 -1
  156. package/dist/fence/definition.d.ts +2 -1
  157. package/dist/fence/definition.d.ts.map +1 -1
  158. package/dist/fence/definition.js +83 -28
  159. package/dist/fence/drafting.d.ts +36 -0
  160. package/dist/fence/drafting.d.ts.map +1 -0
  161. package/dist/fence/drafting.js +210 -0
  162. package/dist/fence/feature-tool.d.ts +4 -0
  163. package/dist/fence/feature-tool.d.ts.map +1 -0
  164. package/dist/fence/feature-tool.js +140 -0
  165. package/dist/fence/features.d.ts +2 -0
  166. package/dist/fence/features.d.ts.map +1 -0
  167. package/dist/fence/features.js +12 -0
  168. package/dist/fence/floorplan-affordances.d.ts.map +1 -1
  169. package/dist/fence/floorplan-affordances.js +2 -1
  170. package/dist/fence/floorplan.d.ts +2 -3
  171. package/dist/fence/floorplan.d.ts.map +1 -1
  172. package/dist/fence/floorplan.js +131 -71
  173. package/dist/fence/geometry-parts.d.ts +50 -0
  174. package/dist/fence/geometry-parts.d.ts.map +1 -0
  175. package/dist/fence/geometry-parts.js +1144 -0
  176. package/dist/fence/geometry.d.ts +2 -3
  177. package/dist/fence/geometry.d.ts.map +1 -1
  178. package/dist/fence/geometry.js +84 -7
  179. package/dist/fence/index.d.ts +1 -0
  180. package/dist/fence/index.d.ts.map +1 -1
  181. package/dist/fence/index.js +1 -0
  182. package/dist/fence/inspector-editors.d.ts +15 -0
  183. package/dist/fence/inspector-editors.d.ts.map +1 -1
  184. package/dist/fence/inspector-editors.js +128 -3
  185. package/dist/fence/lift.d.ts.map +1 -1
  186. package/dist/fence/lift.js +5 -2
  187. package/dist/fence/move-tool.js +2 -1
  188. package/dist/fence/panel-model.d.ts +4 -0
  189. package/dist/fence/panel-model.d.ts.map +1 -0
  190. package/dist/fence/panel-model.js +12 -0
  191. package/dist/fence/parametrics.d.ts +0 -12
  192. package/dist/fence/parametrics.d.ts.map +1 -1
  193. package/dist/fence/parametrics.js +185 -18
  194. package/dist/fence/system.d.ts.map +1 -1
  195. package/dist/fence/system.js +141 -31
  196. package/dist/fence/tool.d.ts.map +1 -1
  197. package/dist/fence/tool.js +256 -47
  198. package/dist/fence-feature/actions.d.ts +7 -0
  199. package/dist/fence-feature/actions.d.ts.map +1 -0
  200. package/dist/fence-feature/actions.js +26 -0
  201. package/dist/fence-feature/definition.d.ts +4 -0
  202. package/dist/fence-feature/definition.d.ts.map +1 -0
  203. package/dist/fence-feature/definition.js +112 -0
  204. package/dist/fence-feature/floorplan-affordances.d.ts +3 -0
  205. package/dist/fence-feature/floorplan-affordances.d.ts.map +1 -0
  206. package/dist/fence-feature/floorplan-affordances.js +37 -0
  207. package/dist/fence-feature/floorplan.d.ts +4 -0
  208. package/dist/fence-feature/floorplan.d.ts.map +1 -0
  209. package/dist/fence-feature/floorplan.js +120 -0
  210. package/dist/fence-feature/geometry.d.ts +5 -0
  211. package/dist/fence-feature/geometry.d.ts.map +1 -0
  212. package/dist/fence-feature/geometry.js +43 -0
  213. package/dist/fence-feature/handles.d.ts +5 -0
  214. package/dist/fence-feature/handles.d.ts.map +1 -0
  215. package/dist/fence-feature/handles.js +84 -0
  216. package/dist/fence-feature/inspector.d.ts +6 -0
  217. package/dist/fence-feature/inspector.d.ts.map +1 -0
  218. package/dist/fence-feature/inspector.js +214 -0
  219. package/dist/fence-feature/interaction.d.ts +3 -0
  220. package/dist/fence-feature/interaction.d.ts.map +1 -0
  221. package/dist/fence-feature/interaction.js +41 -0
  222. package/dist/fence-feature/move-session.d.ts +9 -0
  223. package/dist/fence-feature/move-session.d.ts.map +1 -0
  224. package/dist/fence-feature/move-session.js +48 -0
  225. package/dist/fence-feature/move-tool.d.ts +5 -0
  226. package/dist/fence-feature/move-tool.d.ts.map +1 -0
  227. package/dist/fence-feature/move-tool.js +58 -0
  228. package/dist/fence-feature/pick-target.d.ts +7 -0
  229. package/dist/fence-feature/pick-target.d.ts.map +1 -0
  230. package/dist/fence-feature/pick-target.js +52 -0
  231. package/dist/floor-opening/definition.d.ts +3 -0
  232. package/dist/floor-opening/definition.d.ts.map +1 -0
  233. package/dist/floor-opening/definition.js +41 -0
  234. package/dist/floor-opening/floorplan.d.ts +156 -0
  235. package/dist/floor-opening/floorplan.d.ts.map +1 -0
  236. package/dist/floor-opening/floorplan.js +63 -0
  237. package/dist/gutter/definition.d.ts.map +1 -1
  238. package/dist/gutter/definition.js +2 -2
  239. package/dist/imported-mesh/definition.d.ts.map +1 -1
  240. package/dist/imported-mesh/definition.js +2 -0
  241. package/dist/imported-mesh/geometry.d.ts +1 -1
  242. package/dist/imported-mesh/geometry.d.ts.map +1 -1
  243. package/dist/imported-mesh/geometry.js +40 -12
  244. package/dist/index.d.ts +13 -2
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js +20 -2
  247. package/dist/item/authored-face-host.d.ts +10 -0
  248. package/dist/item/authored-face-host.d.ts.map +1 -0
  249. package/dist/item/authored-face-host.js +87 -0
  250. package/dist/item/authored-params.d.ts +15 -0
  251. package/dist/item/authored-params.d.ts.map +1 -0
  252. package/dist/item/authored-params.js +72 -0
  253. package/dist/item/definition.d.ts +2 -2
  254. package/dist/item/definition.d.ts.map +1 -1
  255. package/dist/item/definition.js +33 -4
  256. package/dist/item/floorplan.d.ts +1 -1
  257. package/dist/item/floorplan.d.ts.map +1 -1
  258. package/dist/item/floorplan.js +35 -5
  259. package/dist/item/index.d.ts +1 -0
  260. package/dist/item/index.d.ts.map +1 -1
  261. package/dist/item/index.js +1 -0
  262. package/dist/item/model-loader.d.ts +2 -0
  263. package/dist/item/model-loader.d.ts.map +1 -1
  264. package/dist/item/model-loader.js +55 -23
  265. package/dist/item/move-tool.js +4 -4
  266. package/dist/item/paint.d.ts.map +1 -1
  267. package/dist/item/paint.js +5 -24
  268. package/dist/item/panel.d.ts +1 -3
  269. package/dist/item/panel.d.ts.map +1 -1
  270. package/dist/item/panel.js +20 -24
  271. package/dist/item/placement-notice.d.ts +14 -0
  272. package/dist/item/placement-notice.d.ts.map +1 -0
  273. package/dist/item/placement-notice.js +38 -0
  274. package/dist/item/plan-symbols.d.ts +67 -0
  275. package/dist/item/plan-symbols.d.ts.map +1 -0
  276. package/dist/item/plan-symbols.js +407 -0
  277. package/dist/item/renderer.d.ts +10 -0
  278. package/dist/item/renderer.d.ts.map +1 -1
  279. package/dist/item/renderer.js +64 -38
  280. package/dist/item/script-param-defaults.d.ts +12 -0
  281. package/dist/item/script-param-defaults.d.ts.map +1 -0
  282. package/dist/item/script-param-defaults.js +34 -0
  283. package/dist/lean-to-extension/definition.d.ts.map +1 -1
  284. package/dist/lean-to-extension/definition.js +1 -2
  285. package/dist/lean-to-extension/geometry.d.ts.map +1 -1
  286. package/dist/lean-to-extension/geometry.js +1 -1
  287. package/dist/lean-to-extension/layout.d.ts.map +1 -1
  288. package/dist/lean-to-extension/layout.js +2 -3
  289. package/dist/lean-to-extension/placement-validation.d.ts.map +1 -1
  290. package/dist/lean-to-extension/placement-validation.js +5 -5
  291. package/dist/lean-to-extension/tool.d.ts.map +1 -1
  292. package/dist/lean-to-extension/tool.js +5 -5
  293. package/dist/lineset/move-tool.d.ts.map +1 -1
  294. package/dist/lineset/move-tool.js +8 -2
  295. package/dist/liquid-line/move-tool.d.ts.map +1 -1
  296. package/dist/liquid-line/move-tool.js +8 -2
  297. package/dist/measurement/definition.js +1 -1
  298. package/dist/pipe-fitting/move-tool.d.ts.map +1 -1
  299. package/dist/pipe-fitting/move-tool.js +8 -2
  300. package/dist/pipe-segment/move-tool.d.ts.map +1 -1
  301. package/dist/pipe-segment/move-tool.js +8 -2
  302. package/dist/procedural-item/animation.d.ts +8 -0
  303. package/dist/procedural-item/animation.d.ts.map +1 -0
  304. package/dist/procedural-item/animation.js +116 -0
  305. package/dist/procedural-item/definition.d.ts.map +1 -1
  306. package/dist/procedural-item/definition.js +74 -8
  307. package/dist/procedural-item/geometry.d.ts +5 -1
  308. package/dist/procedural-item/geometry.d.ts.map +1 -1
  309. package/dist/procedural-item/geometry.js +239 -15
  310. package/dist/procedural-item/renderer.d.ts.map +1 -1
  311. package/dist/procedural-item/renderer.js +272 -23
  312. package/dist/ridge-vent/panel.d.ts.map +1 -1
  313. package/dist/ridge-vent/panel.js +5 -23
  314. package/dist/ridge-vent/renderer.d.ts.map +1 -1
  315. package/dist/ridge-vent/renderer.js +9 -8
  316. package/dist/roof/definition.d.ts.map +1 -1
  317. package/dist/roof/definition.js +4 -1
  318. package/dist/roof/floorplan.d.ts +8 -0
  319. package/dist/roof/floorplan.d.ts.map +1 -1
  320. package/dist/roof/floorplan.js +194 -18
  321. package/dist/roof/panel-model.d.ts.map +1 -1
  322. package/dist/roof/panel-model.js +10 -6
  323. package/dist/roof/panel.d.ts.map +1 -1
  324. package/dist/roof/panel.js +3 -10
  325. package/dist/roof/renderer.d.ts.map +1 -1
  326. package/dist/roof/renderer.js +5 -2
  327. package/dist/roof-segment/panel.d.ts.map +1 -1
  328. package/dist/roof-segment/panel.js +5 -24
  329. package/dist/roof-segment/renderer.d.ts.map +1 -1
  330. package/dist/roof-segment/renderer.js +17 -8
  331. package/dist/separator/definition.d.ts +3 -0
  332. package/dist/separator/definition.d.ts.map +1 -0
  333. package/dist/separator/definition.js +39 -0
  334. package/dist/separator/renderer.d.ts +5 -0
  335. package/dist/separator/renderer.d.ts.map +1 -0
  336. package/dist/separator/renderer.js +36 -0
  337. package/dist/shared/duct-body-paint.d.ts +0 -4
  338. package/dist/shared/duct-body-paint.d.ts.map +1 -1
  339. package/dist/shared/duct-body-paint.js +1 -5
  340. package/dist/shared/item-interaction-actions.d.ts +6 -0
  341. package/dist/shared/item-interaction-actions.d.ts.map +1 -0
  342. package/dist/shared/item-interaction-actions.js +27 -0
  343. package/dist/shared/item-interactions.d.ts +9 -0
  344. package/dist/shared/item-interactions.d.ts.map +1 -0
  345. package/dist/shared/item-interactions.js +74 -0
  346. package/dist/shared/item-light-placement.d.ts +2 -0
  347. package/dist/shared/item-light-placement.d.ts.map +1 -0
  348. package/dist/shared/item-light-placement.js +3 -0
  349. package/dist/shared/move-roof-tool.js +2 -1
  350. package/dist/shared/node-batch/batchable.d.ts +12 -0
  351. package/dist/shared/node-batch/batchable.d.ts.map +1 -0
  352. package/dist/shared/node-batch/batchable.js +41 -0
  353. package/dist/shared/node-batch/candidates.d.ts +7 -5
  354. package/dist/shared/node-batch/candidates.d.ts.map +1 -1
  355. package/dist/shared/node-batch/candidates.js +43 -59
  356. package/dist/shared/node-batch/release.d.ts +8 -0
  357. package/dist/shared/node-batch/release.d.ts.map +1 -0
  358. package/dist/shared/node-batch/release.js +16 -0
  359. package/dist/shared/node-batch/system.d.ts.map +1 -1
  360. package/dist/shared/node-batch/system.js +17 -12
  361. package/dist/shared/node-batch/types.d.ts +4 -1
  362. package/dist/shared/node-batch/types.d.ts.map +1 -1
  363. package/dist/shared/opening-documentation.d.ts +13 -1
  364. package/dist/shared/opening-documentation.d.ts.map +1 -1
  365. package/dist/shared/opening-documentation.js +245 -59
  366. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  367. package/dist/shared/opening-guides-runtime.js +17 -14
  368. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  369. package/dist/shared/opening-placement-dimensions.js +3 -3
  370. package/dist/shared/opening-plane-offset.d.ts +23 -0
  371. package/dist/shared/opening-plane-offset.d.ts.map +1 -0
  372. package/dist/shared/opening-plane-offset.js +24 -0
  373. package/dist/shared/polygon-centroid-move.d.ts.map +1 -1
  374. package/dist/shared/polygon-centroid-move.js +4 -1
  375. package/dist/shared/polygon-vertex-affordance.d.ts.map +1 -1
  376. package/dist/shared/polygon-vertex-affordance.js +19 -15
  377. package/dist/shared/run-hangers.d.ts.map +1 -1
  378. package/dist/shared/run-hangers.js +5 -4
  379. package/dist/shared/scripted-opening-handles.d.ts +18 -0
  380. package/dist/shared/scripted-opening-handles.d.ts.map +1 -0
  381. package/dist/shared/scripted-opening-handles.js +53 -0
  382. package/dist/shared/scripted-opening.d.ts +25 -0
  383. package/dist/shared/scripted-opening.d.ts.map +1 -0
  384. package/dist/shared/scripted-opening.js +72 -0
  385. package/dist/shared/slot-paint.d.ts +14 -2
  386. package/dist/shared/slot-paint.d.ts.map +1 -1
  387. package/dist/shared/slot-paint.js +29 -29
  388. package/dist/shared/surface-paint.d.ts.map +1 -1
  389. package/dist/shared/surface-paint.js +2 -5
  390. package/dist/shared/swap-preview-material.d.ts +11 -0
  391. package/dist/shared/swap-preview-material.d.ts.map +1 -0
  392. package/dist/shared/swap-preview-material.js +16 -0
  393. package/dist/shared/system-checks.d.ts.map +1 -1
  394. package/dist/shared/system-checks.js +5 -3
  395. package/dist/shared/wall-attach-target.d.ts +3 -10
  396. package/dist/shared/wall-attach-target.d.ts.map +1 -1
  397. package/dist/shared/wall-attach-target.js +3 -63
  398. package/dist/shared/wall-opening-ceiling.d.ts +5 -15
  399. package/dist/shared/wall-opening-ceiling.d.ts.map +1 -1
  400. package/dist/shared/wall-opening-ceiling.js +10 -18
  401. package/dist/shelf/definition.d.ts.map +1 -1
  402. package/dist/shelf/definition.js +1 -1
  403. package/dist/shelf/geometry.d.ts.map +1 -1
  404. package/dist/shelf/geometry.js +1 -2
  405. package/dist/shelf/paint.d.ts.map +1 -1
  406. package/dist/shelf/paint.js +4 -10
  407. package/dist/site/line-ribbon.d.ts +31 -0
  408. package/dist/site/line-ribbon.d.ts.map +1 -0
  409. package/dist/site/line-ribbon.js +117 -0
  410. package/dist/site/lot-mask.d.ts +18 -0
  411. package/dist/site/lot-mask.d.ts.map +1 -0
  412. package/dist/site/lot-mask.js +35 -0
  413. package/dist/site/panel.d.ts +10 -0
  414. package/dist/site/panel.d.ts.map +1 -0
  415. package/dist/site/panel.js +155 -0
  416. package/dist/site/parametrics.d.ts +7 -0
  417. package/dist/site/parametrics.d.ts.map +1 -1
  418. package/dist/site/parametrics.js +8 -0
  419. package/dist/site/recessed-slab-ground-holes.d.ts.map +1 -1
  420. package/dist/site/recessed-slab-ground-holes.js +5 -2
  421. package/dist/site/renderer.d.ts.map +1 -1
  422. package/dist/site/renderer.js +150 -19
  423. package/dist/site/setbacks.d.ts +33 -0
  424. package/dist/site/setbacks.d.ts.map +1 -0
  425. package/dist/site/setbacks.js +204 -0
  426. package/dist/site/terrain-geometry.d.ts +28 -1
  427. package/dist/site/terrain-geometry.d.ts.map +1 -1
  428. package/dist/site/terrain-geometry.js +78 -4
  429. package/dist/site/terrain-holes.d.ts +15 -0
  430. package/dist/site/terrain-holes.d.ts.map +1 -0
  431. package/dist/site/terrain-holes.js +74 -0
  432. package/dist/site/terrain-mesh.d.ts +9 -2
  433. package/dist/site/terrain-mesh.d.ts.map +1 -1
  434. package/dist/site/terrain-mesh.js +36 -9
  435. package/dist/site/terrain-renderer.d.ts +9 -2
  436. package/dist/site/terrain-renderer.d.ts.map +1 -1
  437. package/dist/site/terrain-renderer.js +14 -4
  438. package/dist/slab/boundary-editor.d.ts +1 -1
  439. package/dist/slab/boundary-editor.d.ts.map +1 -1
  440. package/dist/slab/boundary-editor.js +13 -13
  441. package/dist/slab/definition.d.ts.map +1 -1
  442. package/dist/slab/definition.js +19 -3
  443. package/dist/slab/dependency-tracker.d.ts.map +1 -1
  444. package/dist/slab/dependency-tracker.js +67 -7
  445. package/dist/slab/elevation-limit.d.ts.map +1 -1
  446. package/dist/slab/elevation-limit.js +2 -2
  447. package/dist/slab/floorplan-affordances.d.ts +176 -4
  448. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  449. package/dist/slab/floorplan-affordances.js +0 -1
  450. package/dist/slab/floorplan-move.d.ts.map +1 -1
  451. package/dist/slab/floorplan-move.js +3 -4
  452. package/dist/slab/floorplan.d.ts +7 -0
  453. package/dist/slab/floorplan.d.ts.map +1 -1
  454. package/dist/slab/floorplan.js +22 -5
  455. package/dist/slab/geometry.d.ts.map +1 -1
  456. package/dist/slab/geometry.js +186 -76
  457. package/dist/slab/move-tool.js +7 -6
  458. package/dist/slab/paint.d.ts +18 -5
  459. package/dist/slab/paint.d.ts.map +1 -1
  460. package/dist/slab/paint.js +458 -9
  461. package/dist/slab/panel.d.ts.map +1 -1
  462. package/dist/slab/panel.js +28 -9
  463. package/dist/slab/placement-ownership.d.ts +2 -1
  464. package/dist/slab/placement-ownership.d.ts.map +1 -1
  465. package/dist/slab/placement-ownership.js +2 -2
  466. package/dist/slab/surface-split.d.ts +24 -0
  467. package/dist/slab/surface-split.d.ts.map +1 -0
  468. package/dist/slab/surface-split.js +389 -0
  469. package/dist/slab/tool.d.ts.map +1 -1
  470. package/dist/slab/tool.js +3 -3
  471. package/dist/stair/baluster-geometry.d.ts +21 -0
  472. package/dist/stair/baluster-geometry.d.ts.map +1 -0
  473. package/dist/stair/baluster-geometry.js +74 -0
  474. package/dist/stair/baluster-guard.d.ts +50 -0
  475. package/dist/stair/baluster-guard.d.ts.map +1 -0
  476. package/dist/stair/baluster-guard.js +71 -0
  477. package/dist/stair/boards-guard.d.ts +37 -0
  478. package/dist/stair/boards-guard.d.ts.map +1 -0
  479. package/dist/stair/boards-guard.js +61 -0
  480. package/dist/stair/cable-guard.d.ts +39 -0
  481. package/dist/stair/cable-guard.d.ts.map +1 -0
  482. package/dist/stair/cable-guard.js +105 -0
  483. package/dist/stair/construction-controls.d.ts +15 -0
  484. package/dist/stair/construction-controls.d.ts.map +1 -0
  485. package/dist/stair/construction-controls.js +29 -0
  486. package/dist/stair/continuous-railings.d.ts +10 -0
  487. package/dist/stair/continuous-railings.d.ts.map +1 -0
  488. package/dist/stair/continuous-railings.js +159 -0
  489. package/dist/stair/definition.d.ts.map +1 -1
  490. package/dist/stair/definition.js +16 -37
  491. package/dist/stair/documentation.d.ts +1 -1
  492. package/dist/stair/documentation.d.ts.map +1 -1
  493. package/dist/stair/documentation.js +10 -17
  494. package/dist/stair/floorplan-affordances.d.ts.map +1 -1
  495. package/dist/stair/floorplan-affordances.js +9 -25
  496. package/dist/stair/floorplan.d.ts +1 -23
  497. package/dist/stair/floorplan.d.ts.map +1 -1
  498. package/dist/stair/floorplan.js +102 -86
  499. package/dist/stair/glass-guard.d.ts +72 -0
  500. package/dist/stair/glass-guard.d.ts.map +1 -0
  501. package/dist/stair/glass-guard.js +167 -0
  502. package/dist/stair/guard-path.d.ts +119 -0
  503. package/dist/stair/guard-path.d.ts.map +1 -0
  504. package/dist/stair/guard-path.js +208 -0
  505. package/dist/stair/materials.d.ts +11 -0
  506. package/dist/stair/materials.d.ts.map +1 -0
  507. package/dist/stair/materials.js +51 -0
  508. package/dist/stair/metal-guard.d.ts +38 -0
  509. package/dist/stair/metal-guard.d.ts.map +1 -0
  510. package/dist/stair/metal-guard.js +79 -0
  511. package/dist/stair/paint.d.ts +32 -0
  512. package/dist/stair/paint.d.ts.map +1 -1
  513. package/dist/stair/paint.js +75 -36
  514. package/dist/stair/panel.d.ts.map +1 -1
  515. package/dist/stair/panel.js +154 -17
  516. package/dist/stair/parametrics.d.ts +1 -1
  517. package/dist/stair/parametrics.d.ts.map +1 -1
  518. package/dist/stair/parametrics.js +32 -15
  519. package/dist/stair/plan-entry.d.ts +31 -0
  520. package/dist/stair/plan-entry.d.ts.map +1 -0
  521. package/dist/stair/plan-entry.js +325 -0
  522. package/dist/stair/post-and-rail-guard.d.ts +31 -0
  523. package/dist/stair/post-and-rail-guard.d.ts.map +1 -0
  524. package/dist/stair/post-and-rail-guard.js +63 -0
  525. package/dist/stair/railing-controls.d.ts +9 -0
  526. package/dist/stair/railing-controls.d.ts.map +1 -0
  527. package/dist/stair/railing-controls.js +49 -0
  528. package/dist/stair/renderer.d.ts.map +1 -1
  529. package/dist/stair/renderer.js +259 -259
  530. package/dist/stair/use-stair-render-data.d.ts +317 -0
  531. package/dist/stair/use-stair-render-data.d.ts.map +1 -0
  532. package/dist/stair/use-stair-render-data.js +73 -0
  533. package/dist/stair-segment/definition.d.ts.map +1 -1
  534. package/dist/stair-segment/definition.js +51 -10
  535. package/dist/stair-segment/panel.d.ts.map +1 -1
  536. package/dist/stair-segment/panel.js +36 -42
  537. package/dist/stair-segment/parametrics.d.ts +1 -1
  538. package/dist/stair-segment/parametrics.d.ts.map +1 -1
  539. package/dist/stair-segment/parametrics.js +21 -8
  540. package/dist/stair-segment/renderer.d.ts.map +1 -1
  541. package/dist/stair-segment/renderer.js +16 -28
  542. package/dist/turbine-vent/definition.d.ts.map +1 -1
  543. package/dist/turbine-vent/definition.js +2 -5
  544. package/dist/turbine-vent/paint.d.ts.map +1 -1
  545. package/dist/turbine-vent/paint.js +2 -5
  546. package/dist/turbine-vent/panel.d.ts.map +1 -1
  547. package/dist/turbine-vent/panel.js +5 -23
  548. package/dist/unit/unit-panel.d.ts.map +1 -1
  549. package/dist/unit/unit-panel.js +6 -1
  550. package/dist/wall/actions.d.ts.map +1 -1
  551. package/dist/wall/actions.js +7 -2
  552. package/dist/wall/construction-dimensions.js +8 -5
  553. package/dist/wall/contextual-dimensions.js +4 -4
  554. package/dist/wall/curtain-wall-materials.d.ts +1 -1
  555. package/dist/wall/curtain-wall-materials.d.ts.map +1 -1
  556. package/dist/wall/curtain-wall-materials.js +2 -2
  557. package/dist/wall/curve-tool.d.ts.map +1 -1
  558. package/dist/wall/curve-tool.js +4 -0
  559. package/dist/wall/definition.d.ts.map +1 -1
  560. package/dist/wall/definition.js +41 -17
  561. package/dist/wall/floorplan-move.d.ts +1 -1
  562. package/dist/wall/floorplan-move.d.ts.map +1 -1
  563. package/dist/wall/floorplan-move.js +20 -83
  564. package/dist/wall/floorplan-tool.d.ts.map +1 -1
  565. package/dist/wall/floorplan-tool.js +10 -11
  566. package/dist/wall/floorplan.d.ts +3 -1
  567. package/dist/wall/floorplan.d.ts.map +1 -1
  568. package/dist/wall/floorplan.js +184 -21
  569. package/dist/wall/measurement.d.ts.map +1 -1
  570. package/dist/wall/measurement.js +5 -5
  571. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  572. package/dist/wall/move-endpoint-tool.js +20 -7
  573. package/dist/wall/move-shared.d.ts.map +1 -1
  574. package/dist/wall/move-shared.js +11 -7
  575. package/dist/wall/move-tool.d.ts.map +1 -1
  576. package/dist/wall/move-tool.js +118 -148
  577. package/dist/wall/paint.d.ts +26 -15
  578. package/dist/wall/paint.d.ts.map +1 -1
  579. package/dist/wall/paint.js +306 -117
  580. package/dist/wall/panel-model.d.ts +18 -0
  581. package/dist/wall/panel-model.d.ts.map +1 -1
  582. package/dist/wall/panel-model.js +77 -19
  583. package/dist/wall/panel.d.ts.map +1 -1
  584. package/dist/wall/panel.js +217 -41
  585. package/dist/wall/parametrics.d.ts.map +1 -1
  586. package/dist/wall/parametrics.js +3 -0
  587. package/dist/wall/rectangle-command.d.ts +111 -12
  588. package/dist/wall/rectangle-command.d.ts.map +1 -1
  589. package/dist/wall/rectangle-tool.d.ts.map +1 -1
  590. package/dist/wall/rectangle-tool.js +26 -8
  591. package/dist/wall/renderer.d.ts.map +1 -1
  592. package/dist/wall/renderer.js +4 -2
  593. package/dist/wall/split-floorplan-layer.d.ts.map +1 -1
  594. package/dist/wall/split-floorplan-layer.js +7 -7
  595. package/dist/wall/split-session.d.ts.map +1 -1
  596. package/dist/wall/split-session.js +7 -1
  597. package/dist/wall/system.d.ts.map +1 -1
  598. package/dist/wall/system.js +36 -4
  599. package/dist/wall/tool.d.ts.map +1 -1
  600. package/dist/wall/tool.js +105 -49
  601. package/dist/wall/treatment-level-data.d.ts +3 -2
  602. package/dist/wall/treatment-level-data.d.ts.map +1 -1
  603. package/dist/wall/treatment-level-data.js +17 -13
  604. package/dist/wall/treatments.d.ts +10 -10
  605. package/dist/wall/treatments.d.ts.map +1 -1
  606. package/dist/wall/treatments.js +67 -54
  607. package/dist/wall/wall-batch-system.d.ts +7 -0
  608. package/dist/wall/wall-batch-system.d.ts.map +1 -1
  609. package/dist/wall/wall-batch-system.js +35 -3
  610. package/dist/wall/wall-batch.d.ts +6 -0
  611. package/dist/wall/wall-batch.d.ts.map +1 -1
  612. package/dist/wall/wall-batch.js +7 -1
  613. package/dist/window/definition.d.ts.map +1 -1
  614. package/dist/window/definition.js +12 -4
  615. package/dist/window/floorplan-move.d.ts.map +1 -1
  616. package/dist/window/floorplan-move.js +3 -1
  617. package/dist/window/floorplan.d.ts.map +1 -1
  618. package/dist/window/floorplan.js +145 -60
  619. package/dist/window/mechanism.d.ts +4 -0
  620. package/dist/window/mechanism.d.ts.map +1 -0
  621. package/dist/window/mechanism.js +20 -0
  622. package/dist/window/move-tool.d.ts.map +1 -1
  623. package/dist/window/move-tool.js +79 -48
  624. package/dist/window/paint.d.ts.map +1 -1
  625. package/dist/window/paint.js +3 -0
  626. package/dist/window/panel.d.ts.map +1 -1
  627. package/dist/window/panel.js +32 -88
  628. package/dist/window/placement.d.ts +23 -0
  629. package/dist/window/placement.d.ts.map +1 -0
  630. package/dist/window/placement.js +66 -0
  631. package/dist/window/preview.d.ts.map +1 -1
  632. package/dist/window/preview.js +2 -0
  633. package/dist/window/renderer.d.ts.map +1 -1
  634. package/dist/window/renderer.js +3 -2
  635. package/dist/window/tool.d.ts.map +1 -1
  636. package/dist/window/tool.js +96 -24
  637. package/dist/window/window-math.d.ts +6 -14
  638. package/dist/window/window-math.d.ts.map +1 -1
  639. package/dist/window/window-math.js +14 -20
  640. package/dist/zone/contextual-dimensions.d.ts.map +1 -1
  641. package/dist/zone/contextual-dimensions.js +6 -28
  642. package/dist/zone/definition.d.ts.map +1 -1
  643. package/dist/zone/definition.js +3 -3
  644. package/dist/zone/floorplan-affordances.d.ts +200 -0
  645. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  646. package/dist/zone/floorplan.d.ts +1 -1
  647. package/dist/zone/floorplan.d.ts.map +1 -1
  648. package/dist/zone/floorplan.js +93 -53
  649. package/dist/zone/quantities-panel.d.ts.map +1 -1
  650. package/dist/zone/quantities-panel.js +3 -14
  651. package/dist/zone/quick-measurement.d.ts +2 -2
  652. package/dist/zone/quick-measurement.d.ts.map +1 -1
  653. package/dist/zone/quick-measurement.js +6 -5
  654. package/dist/zone/renderer.d.ts +1 -1
  655. package/dist/zone/renderer.d.ts.map +1 -1
  656. package/dist/zone/renderer.js +58 -146
  657. package/dist/zone/room-clear-dimensions.js +3 -3
  658. package/dist/zone/room-documentation.d.ts.map +1 -1
  659. package/dist/zone/room-documentation.js +2 -6
  660. package/package.json +11 -11
  661. package/dist/block/slots.d.ts +0 -4
  662. package/dist/block/slots.d.ts.map +0 -1
  663. package/dist/block/slots.js +0 -17
  664. package/dist/cabinet/slots.d.ts +0 -4
  665. package/dist/cabinet/slots.d.ts.map +0 -1
  666. package/dist/cabinet/slots.js +0 -24
  667. package/dist/ceiling/slots.d.ts +0 -6
  668. package/dist/ceiling/slots.d.ts.map +0 -1
  669. package/dist/ceiling/slots.js +0 -7
  670. package/dist/column/slots.d.ts +0 -9
  671. package/dist/column/slots.d.ts.map +0 -1
  672. package/dist/column/slots.js +0 -19
  673. package/dist/door/slots.d.ts +0 -9
  674. package/dist/door/slots.d.ts.map +0 -1
  675. package/dist/door/slots.js +0 -20
  676. package/dist/elevator/slots.d.ts +0 -8
  677. package/dist/elevator/slots.d.ts.map +0 -1
  678. package/dist/elevator/slots.js +0 -17
  679. package/dist/fence/slots.d.ts +0 -10
  680. package/dist/fence/slots.d.ts.map +0 -1
  681. package/dist/fence/slots.js +0 -23
  682. package/dist/item/__fixtures__/main-floorplan.d.ts +0 -26
  683. package/dist/item/__fixtures__/main-floorplan.d.ts.map +0 -1
  684. package/dist/item/__fixtures__/main-floorplan.js +0 -297
  685. package/dist/lean-to-extension/slots.d.ts +0 -5
  686. package/dist/lean-to-extension/slots.d.ts.map +0 -1
  687. package/dist/lean-to-extension/slots.js +0 -15
  688. package/dist/shelf/slots.d.ts +0 -9
  689. package/dist/shelf/slots.d.ts.map +0 -1
  690. package/dist/shelf/slots.js +0 -30
  691. package/dist/slab/slots.d.ts +0 -10
  692. package/dist/slab/slots.d.ts.map +0 -1
  693. package/dist/slab/slots.js +0 -20
  694. package/dist/stair/floor-stack.d.ts +0 -10
  695. package/dist/stair/floor-stack.d.ts.map +0 -1
  696. package/dist/stair/floor-stack.js +0 -115
  697. package/dist/stair/slots.d.ts +0 -7
  698. package/dist/stair/slots.d.ts.map +0 -1
  699. package/dist/stair/slots.js +0 -13
  700. package/dist/wall/drawing-mode.d.ts +0 -12
  701. package/dist/wall/drawing-mode.d.ts.map +0 -1
  702. package/dist/wall/drawing-mode.js +0 -38
  703. package/dist/wall/slots.d.ts +0 -10
  704. package/dist/wall/slots.d.ts.map +0 -1
  705. package/dist/wall/slots.js +0 -92
  706. package/dist/window/slots.d.ts +0 -5
  707. package/dist/window/slots.d.ts.map +0 -1
  708. package/dist/window/slots.js +0 -11
@@ -2,9 +2,7 @@
2
2
  * Stage E inspector for item. 1:1 port of the legacy
3
3
  * `editor/components/ui/panels/item-panel.tsx`, relocated into the
4
4
  * kind's folder so `parametrics.customPanel` mounts it through the
5
- * registry inspector. The catalog popover (`<CollectionsPopover>`) is
6
- * the only kind-specific UI that can't be expressed via the generic
7
- * auto-inspector today — kept inline.
5
+ * registry inspector.
8
6
  *
9
7
  * Slider-drag fix recipe applied: scale / position / rotation slider
10
8
  * `onChange` callbacks read from a `useRef(node)` instead of the
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/item/panel.tsx"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,uCAwShC"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/item/panel.tsx"],"names":[],"mappings":"AAyBA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,uCAiShC"}
@@ -1,17 +1,16 @@
1
1
  'use client';
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { getScaledDimensions, ItemNode, useScene } from '@pascal-app/core';
4
- import { ActionButton, ActionGroup, CollectionsPopover, PanelSection, PanelWrapper, SliderControl, triggerSFX, useEditor, } from '@pascal-app/editor';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { getScaledDimensions, scriptImages, useScene, } from '@pascal-app/core';
4
+ import { ActionButton, ActionGroup, duplicateNodeAndPickUp, PanelSection, PanelWrapper, SliderControl, triggerSFX, useEditor, usePlacementNotice, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Copy, Link, Link2Off, Move, Trash2 } from 'lucide-react';
7
7
  import { useCallback, useRef, useState } from 'react';
8
+ import { AuthoredParams } from './authored-params';
8
9
  /**
9
10
  * Stage E inspector for item. 1:1 port of the legacy
10
11
  * `editor/components/ui/panels/item-panel.tsx`, relocated into the
11
12
  * kind's folder so `parametrics.customPanel` mounts it through the
12
- * registry inspector. The catalog popover (`<CollectionsPopover>`) is
13
- * the only kind-specific UI that can't be expressed via the generic
14
- * auto-inspector today — kept inline.
13
+ * registry inspector.
15
14
  *
16
15
  * Slider-drag fix recipe applied: scale / position / rotation slider
17
16
  * `onChange` callbacks read from a `useRef(node)` instead of the
@@ -25,6 +24,7 @@ export default function ItemPanel() {
25
24
  const deleteNode = useScene((s) => s.deleteNode);
26
25
  const setMovingNode = useEditor((s) => s.setMovingNode);
27
26
  const node = useScene((s) => selectedId ? s.nodes[selectedId] : undefined);
27
+ const fitWarning = usePlacementNotice(selectedId);
28
28
  const [uniformScale, setUniformScale] = useState(true);
29
29
  const nodeRef = useRef(node);
30
30
  nodeRef.current = node;
@@ -54,21 +54,9 @@ export default function ItemPanel() {
54
54
  }
55
55
  }, [node, setMovingNode, setSelection]);
56
56
  const handleDuplicate = useCallback(() => {
57
- if (!node)
58
- return;
59
- triggerSFX('sfx:item-pick');
60
- const proto = ItemNode.parse({
61
- position: [...node.position],
62
- rotation: [...node.rotation],
63
- name: node.name,
64
- asset: node.asset,
65
- parentId: node.parentId,
66
- side: node.side,
67
- metadata: { isNew: true },
68
- });
69
- setMovingNode(proto);
70
- setSelection({ selectedIds: [] });
71
- }, [node, setMovingNode, setSelection]);
57
+ if (node)
58
+ duplicateNodeAndPickUp(node);
59
+ }, [node]);
72
60
  const handleDelete = useCallback(() => {
73
61
  if (!selectedId)
74
62
  return;
@@ -78,10 +66,10 @@ export default function ItemPanel() {
78
66
  }, [selectedId, deleteNode, setSelection]);
79
67
  if (!(node && node.type === 'item' && selectedId))
80
68
  return null;
81
- return (_jsxs(PanelWrapper, { icon: node.asset.thumbnail || '/icons/item.webp', onClose: handleClose, title: node.name || node.asset.name, width: 300, children: [_jsxs(PanelSection, { title: "Position", children: [_jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["X", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "pos" })] }), max: node.position[0] + 2, min: node.position[0] - 2, onChange: (value) => handleUpdate({ position: [value, node.position[1], node.position[2]] }), precision: 2, step: 0.01, unit: "m", value: node.position[0] }), _jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["Y", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "pos" })] }), max: node.position[1] + 2, min: node.position[1] - 2, onChange: (value) => handleUpdate({ position: [node.position[0], value, node.position[2]] }), precision: 2, step: 0.01, unit: "m", value: node.position[1] }), _jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["Z", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "pos" })] }), max: node.position[2] + 2, min: node.position[2] - 2, onChange: (value) => handleUpdate({ position: [node.position[0], node.position[1], value] }), precision: 2, step: 0.01, unit: "m", value: node.position[2] })] }), _jsxs(PanelSection, { title: "Rotation", children: [_jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["Y", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "rot" })] }), max: Math.round((node.rotation[1] * 180) / Math.PI) + 45, min: Math.round((node.rotation[1] * 180) / Math.PI) - 45, onChange: (degrees) => {
69
+ return (_jsxs(PanelWrapper, { icon: scriptImages(node)?.thumbnail ?? (node.asset.thumbnail || '/icons/item.webp'), onClose: handleClose, title: node.name || node.asset.name, width: 300, children: [fitWarning && (_jsxs("div", { className: "mx-1 mb-1 flex gap-2 rounded-lg bg-amber-400/10 px-3 py-2 text-xs", children: [_jsx("span", { className: "font-semibold text-amber-400", children: "!" }), _jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "font-medium text-foreground", children: fitWarning.line }), fitWarning.detail && (_jsx("span", { className: "text-muted-foreground", children: fitWarning.detail }))] })] })), _jsx(AuthoredParams, { node: node }), _jsxs(PanelSection, { title: "Position", children: [_jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["X", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "pos" })] }), max: node.position[0] + 2, min: node.position[0] - 2, onChange: (value) => handleUpdate({ position: [value, node.position[1], node.position[2]] }), precision: 2, step: 0.01, unit: "m", value: node.position[0] }), _jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["Y", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "pos" })] }), max: node.position[1] + 2, min: node.position[1] - 2, onChange: (value) => handleUpdate({ position: [node.position[0], value, node.position[2]] }), precision: 2, step: 0.01, unit: "m", value: node.position[1] }), _jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["Z", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "pos" })] }), max: node.position[2] + 2, min: node.position[2] - 2, onChange: (value) => handleUpdate({ position: [node.position[0], node.position[1], value] }), precision: 2, step: 0.01, unit: "m", value: node.position[2] })] }), _jsxs(PanelSection, { title: "Rotation", children: [_jsx(TiltSlider, { axis: 0, label: "X", node: node, onUpdate: handleUpdate }), _jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["Y", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "rot" })] }), max: Math.round((node.rotation[1] * 180) / Math.PI) + 45, min: Math.round((node.rotation[1] * 180) / Math.PI) - 45, onChange: (degrees) => {
82
70
  const radians = (degrees * Math.PI) / 180;
83
71
  handleUpdate({ rotation: [node.rotation[0], radians, node.rotation[2]] });
84
- }, precision: 0, step: 1, unit: "\u00B0", value: Math.round((node.rotation[1] * 180) / Math.PI) }), _jsxs("div", { className: "flex gap-1.5 px-1 pt-2 pb-1", children: [_jsx(ActionButton, { label: "-45\u00B0", onClick: () => {
72
+ }, precision: 0, step: 1, unit: "\u00B0", value: Math.round((node.rotation[1] * 180) / Math.PI) }), _jsx(TiltSlider, { axis: 2, label: "Z", node: node, onUpdate: handleUpdate }), _jsxs("div", { className: "flex gap-1.5 px-1 pt-2 pb-1", children: [_jsx(ActionButton, { label: "-45\u00B0", onClick: () => {
85
73
  triggerSFX('sfx:item-rotate');
86
74
  const currentDegrees = (node.rotation[1] * 180) / Math.PI;
87
75
  const radians = ((currentDegrees - 45) * Math.PI) / 180;
@@ -99,5 +87,13 @@ export default function ItemPanel() {
99
87
  }, precision: 2, step: 0.1, value: Math.round(node.scale[0] * 100) / 100 })) : (_jsxs(_Fragment, { children: [_jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["X", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "scale" })] }), max: 10, min: 0.01, onChange: (value) => handleUpdate({ scale: [Math.max(0.01, value), node.scale[1], node.scale[2]] }), precision: 2, step: 0.1, value: Math.round(node.scale[0] * 100) / 100 }), _jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["Y", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "scale" })] }), max: 10, min: 0.01, onChange: (value) => handleUpdate({ scale: [node.scale[0], Math.max(0.01, value), node.scale[2]] }), precision: 2, step: 0.1, value: Math.round(node.scale[1] * 100) / 100 }), _jsx(SliderControl, { label: _jsxs(_Fragment, { children: ["Z", _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "scale" })] }), max: 10, min: 0.01, onChange: (value) => handleUpdate({ scale: [node.scale[0], node.scale[1], Math.max(0.01, value)] }), precision: 2, step: 0.1, value: Math.round(node.scale[2] * 100) / 100 })] }))] }), _jsx(PanelSection, { title: "Info", children: _jsxs("div", { className: "flex items-center justify-between px-2 py-1 text-muted-foreground text-sm", children: [_jsx("span", { children: "Dimensions" }), (() => {
100
88
  const [w, h, d] = getScaledDimensions(node);
101
89
  return (_jsxs("span", { className: "font-mono text-white", children: [Math.round(w * 100) / 100, "\u00D7", Math.round(h * 100) / 100, "\u00D7", Math.round(d * 100) / 100] }));
102
- })()] }) }), _jsx(PanelSection, { title: "Collections", children: _jsx(ActionGroup, { children: _jsx(CollectionsPopover, { collectionIds: node.collectionIds, nodeId: selectedId, children: _jsx(ActionButton, { label: "Manage collections\u2026" }) }) }) }), _jsx(PanelSection, { title: "Actions", children: _jsxs(ActionGroup, { children: [_jsx(ActionButton, { icon: _jsx(Move, { className: "h-3.5 w-3.5" }), label: "Move", onClick: handleMove }), _jsx(ActionButton, { icon: _jsx(Copy, { className: "h-3.5 w-3.5" }), label: "Duplicate", onClick: handleDuplicate }), _jsx(ActionButton, { className: "hover:bg-red-500/20", icon: _jsx(Trash2, { className: "h-3.5 w-3.5 text-red-400" }), label: "Delete", onClick: handleDelete })] }) })] }));
90
+ })()] }) }), _jsx(PanelSection, { title: "Actions", children: _jsxs(ActionGroup, { children: [_jsx(ActionButton, { icon: _jsx(Move, { className: "h-3.5 w-3.5" }), label: "Move", onClick: handleMove }), _jsx(ActionButton, { icon: _jsx(Copy, { className: "h-3.5 w-3.5" }), label: "Duplicate", onClick: handleDuplicate }), _jsx(ActionButton, { className: "hover:bg-red-500/20", icon: _jsx(Trash2, { className: "h-3.5 w-3.5 text-red-400" }), label: "Delete", onClick: handleDelete })] }) })] }));
91
+ }
92
+ /** Tilt about X or Z: aiming a spotlight, leaning a frame. Y stays the main turn above. */
93
+ function TiltSlider({ axis, label, node, onUpdate, }) {
94
+ return (_jsx(SliderControl, { label: _jsxs(_Fragment, { children: [label, _jsx("sub", { className: "ml-[1px] text-[11px] opacity-70", children: "rot" })] }), max: 180, min: -180, onChange: (degrees) => {
95
+ const rotation = [...node.rotation];
96
+ rotation[axis] = (degrees * Math.PI) / 180;
97
+ onUpdate({ rotation });
98
+ }, precision: 0, step: 1, unit: "\u00B0", value: Math.round((node.rotation[axis] * 180) / Math.PI) }));
103
99
  }
@@ -0,0 +1,14 @@
1
+ import { type AnyNode, type ItemNode, type LiveTransformLike, type PlacementNotice } from '@pascal-app/core';
2
+ import { type FloorItemMisfit } from '@pascal-app/core/building';
3
+ /** What a person reads for a floor item that does not fit: in a door's way, or too large for its room. */
4
+ export declare function floorItemMisfitNotice(misfit: FloorItemMisfit, dimensions: readonly number[]): PlacementNotice;
5
+ /**
6
+ * The item's `placementNotice`: a floor item in a door's way or too large for its room, by the
7
+ * check place_items refuses with (`floorItemFit`), at its live pose while it is placed or moved.
8
+ * An item on a table, a shelf or a wall is not checked.
9
+ */
10
+ export declare function itemPlacementNotice(node: ItemNode, { nodes, live }: {
11
+ nodes: Readonly<Record<string, AnyNode>>;
12
+ live?: LiveTransformLike;
13
+ }): PlacementNotice | null;
14
+ //# sourceMappingURL=placement-notice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placement-notice.d.ts","sourceRoot":"","sources":["../../src/item/placement-notice.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,KAAK,eAAe,EAAgB,MAAM,2BAA2B,CAAA;AAI9E,0GAA0G;AAC1G,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,eAAe,CAQjB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,iBAAiB,CAAA;CAAE,GACtF,eAAe,GAAG,IAAI,CAkBxB"}
@@ -0,0 +1,38 @@
1
+ import { getScaledDimensions, } from '@pascal-app/core';
2
+ import { floorItemFit } from '@pascal-app/core/building';
3
+ const round = (value) => Math.round(value * 100) / 100;
4
+ /** What a person reads for a floor item that does not fit: in a door's way, or too large for its room. */
5
+ export function floorItemMisfitNotice(misfit, dimensions) {
6
+ const name = misfit.room?.name.trim();
7
+ if (misfit.code === 'blocks_door')
8
+ return { line: name ? `Blocks the door to ${name}` : 'Blocks a door' };
9
+ return {
10
+ line: name ? `Too large for ${name}` : 'Too large for its room',
11
+ detail: `${round(dimensions[0] ?? 0)} × ${round(dimensions[2] ?? 0)} m in a ${round(misfit.room.width)} × ${round(misfit.room.depth)} m room`,
12
+ };
13
+ }
14
+ /**
15
+ * The item's `placementNotice`: a floor item in a door's way or too large for its room, by the
16
+ * check place_items refuses with (`floorItemFit`), at its live pose while it is placed or moved.
17
+ * An item on a table, a shelf or a wall is not checked.
18
+ */
19
+ export function itemPlacementNotice(node, { nodes, live }) {
20
+ if (!node.parentId || nodes[node.parentId]?.type !== 'level')
21
+ return null;
22
+ const item = live
23
+ ? {
24
+ ...node,
25
+ position: live.position,
26
+ rotation: [node.rotation[0], live.rotation, node.rotation[2]],
27
+ }
28
+ : node;
29
+ const dimensions = getScaledDimensions(item);
30
+ const misfit = floorItemFit(nodes, {
31
+ levelId: node.parentId,
32
+ x: item.position[0],
33
+ z: item.position[2],
34
+ rotationDeg: ((item.rotation?.[1] ?? 0) * 180) / Math.PI,
35
+ dimensions,
36
+ });
37
+ return misfit ? floorItemMisfitNotice(misfit, dimensions) : null;
38
+ }
@@ -0,0 +1,67 @@
1
+ import type { FloorplanGeometry, FloorplanPoint } from '@pascal-app/core';
2
+ /**
3
+ * PERMIT-SET PLAN SYMBOLS for items — what a sheet draws instead of the
4
+ * asset's raster sprite: real fixtures (sinks …) with fixture labels, as a
5
+ * full plan set shows them.
6
+ *
7
+ * A plans examiner reads plumbing fixtures and appliances off the floor plan,
8
+ * so those draw as crisp linework at true size with the standard label (WC,
9
+ * LAV, TUB, SHWR, W, D, WH, REF, R, DW …). Furniture is thin light-grey
10
+ * outline, a car a light dashed outline, and ceiling-mounted items, wall
11
+ * devices and decor are left off — the lights go on the electrical plan.
12
+ *
13
+ * Symbols are built in the item's LOCAL plan frame, true size: x across the
14
+ * width, y along the depth, the BACK (the wall it stands against) at
15
+ * y = -depth / 2 and the front at +depth / 2. The caller maps the points.
16
+ */
17
+ /**
18
+ * Metadata key on a drafted item's group naming what it is (`fixture`,
19
+ * `furniture`, `car`) — how a sheet tells a WC it must keep text off from a
20
+ * bed it may overlap, without re-classifying the asset itself.
21
+ */
22
+ export declare const PLAN_SYMBOL_METADATA_KEY = "pascal:sheet/plan-symbol";
23
+ export type PlanFixtureKind = 'wc' | 'lav' | 'tub' | 'shower' | 'washer' | 'dryer' | 'washer-dryer' | 'water-heater' | 'ref' | 'range' | 'cooktop' | 'oven' | 'dw' | 'mw' | 'sink' | 'fireplace' | 'ev' | 'condenser';
24
+ export type PlanItemClass = {
25
+ kind: 'fixture';
26
+ fixture: PlanFixtureKind;
27
+ label: string;
28
+ } | {
29
+ kind: 'casework';
30
+ } | {
31
+ kind: 'car';
32
+ } | {
33
+ kind: 'furniture';
34
+ shape: 'bed' | 'sofa' | 'plain';
35
+ } | {
36
+ kind: 'omit';
37
+ };
38
+ type AssetLike = {
39
+ id?: string;
40
+ name?: string;
41
+ category?: string;
42
+ tags?: readonly string[];
43
+ attachTo?: string;
44
+ };
45
+ /** What a sheet draws for an item, from its asset. */
46
+ export declare function classifyPlanItem(asset: AssetLike): PlanItemClass;
47
+ /** Fixture linework — the weight casework draws in, near-black. */
48
+ export declare const FIXTURE_STROKE = "#1f2937";
49
+ export declare const FIXTURE_STROKE_WIDTH = 0.012;
50
+ /** Furniture: thin, light grey — present, never competing with the walls. */
51
+ export declare const FURNITURE_STROKE = "#9ca3af";
52
+ export declare const FURNITURE_STROKE_WIDTH = 0.006;
53
+ /** Fixture label size on the paper, points, and its plan-metre size at 1/4" = 1'-0". */
54
+ export declare const FIXTURE_LABEL_PT = 6.5;
55
+ export declare const FIXTURE_LABEL_SIZE = 0.11;
56
+ export type PlanSymbolFrame = {
57
+ /** Local (x across, y along the depth; back = -depth / 2) → plan point. */
58
+ map: (x: number, y: number) => FloorplanPoint;
59
+ width: number;
60
+ depth: number;
61
+ };
62
+ /**
63
+ * The drafting symbol for an item, in plan coordinates. Empty for `omit`.
64
+ */
65
+ export declare function buildPlanItemSymbol(cls: PlanItemClass, frame: PlanSymbolFrame): FloorplanGeometry[];
66
+ export {};
67
+ //# sourceMappingURL=plan-symbols.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-symbols.d.ts","sourceRoot":"","sources":["../../src/item/plan-symbols.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAGzE;;;;;;;;;;;;;;GAcG;AAEH;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,6BAA6B,CAAA;AAElE,MAAM,MAAM,eAAe,GACvB,IAAI,GACJ,KAAK,GACL,KAAK,GACL,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,cAAc,GACd,cAAc,GACd,KAAK,GACL,OAAO,GACP,SAAS,GACT,MAAM,GACN,IAAI,GACJ,IAAI,GACJ,MAAM,GACN,WAAW,GACX,IAAI,GACJ,WAAW,CAAA;AAEf,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GACf;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpB,KAAK,SAAS,GAAG;IACf,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AA4CD,sDAAsD;AACtD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CA2BhE;AAID,mEAAmE;AACnE,eAAO,MAAM,cAAc,YAAY,CAAA;AACvC,eAAO,MAAM,oBAAoB,QAAQ,CAAA;AAEzC,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,YAAY,CAAA;AACzC,eAAO,MAAM,sBAAsB,QAAQ,CAAA;AAE3C,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,MAAM,CAAA;AACnC,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC,MAAM,MAAM,eAAe,GAAG;IAC5B,2EAA2E;IAC3E,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,cAAc,CAAA;IAC7C,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,eAAe,GACrB,iBAAiB,EAAE,CAqBrB"}
@@ -0,0 +1,407 @@
1
+ import { floorplanGeometryMetadata } from '@pascal-app/editor';
2
+ /**
3
+ * PERMIT-SET PLAN SYMBOLS for items — what a sheet draws instead of the
4
+ * asset's raster sprite: real fixtures (sinks …) with fixture labels, as a
5
+ * full plan set shows them.
6
+ *
7
+ * A plans examiner reads plumbing fixtures and appliances off the floor plan,
8
+ * so those draw as crisp linework at true size with the standard label (WC,
9
+ * LAV, TUB, SHWR, W, D, WH, REF, R, DW …). Furniture is thin light-grey
10
+ * outline, a car a light dashed outline, and ceiling-mounted items, wall
11
+ * devices and decor are left off — the lights go on the electrical plan.
12
+ *
13
+ * Symbols are built in the item's LOCAL plan frame, true size: x across the
14
+ * width, y along the depth, the BACK (the wall it stands against) at
15
+ * y = -depth / 2 and the front at +depth / 2. The caller maps the points.
16
+ */
17
+ /**
18
+ * Metadata key on a drafted item's group naming what it is (`fixture`,
19
+ * `furniture`, `car`) — how a sheet tells a WC it must keep text off from a
20
+ * bed it may overlap, without re-classifying the asset itself.
21
+ */
22
+ export const PLAN_SYMBOL_METADATA_KEY = 'pascal:sheet/plan-symbol';
23
+ const FIXTURES = [
24
+ { test: /\btoilet\b(?!-paper)|water-?closet|\bwc\b/, fixture: 'wc', label: 'WC' },
25
+ { test: /bathroom-sink|lavatory|\blav\b|\bvanity\b|wash-?basin/, fixture: 'lav', label: 'LAV' },
26
+ { test: /\bbathtub\b|\bbath-?tub\b|^bath$|\btub\b/, fixture: 'tub', label: 'TUB' },
27
+ { test: /\bshower\b(?!-rug|-curtain|-caddy)/, fixture: 'shower', label: 'SHWR' },
28
+ {
29
+ test: /washer-?dryer|washer\/dryer|laundry-?pair|stacked-?laundry/,
30
+ fixture: 'washer-dryer',
31
+ label: 'W/D',
32
+ },
33
+ { test: /washing-?machine|(?<!dish)\bwasher\b|clothes-?washer/, fixture: 'washer', label: 'W' },
34
+ { test: /(?<!hair-)\bdryer\b|clothes-?dryer|tumble/, fixture: 'dryer', label: 'D' },
35
+ { test: /water-?heater|\bboiler\b|tankless/, fixture: 'water-heater', label: 'WH' },
36
+ { test: /fridge|refrigerator|freezer/, fixture: 'ref', label: 'REF' },
37
+ { test: /dishwasher/, fixture: 'dw', label: 'DW' },
38
+ { test: /microwave/, fixture: 'mw', label: 'MW' },
39
+ { test: /cooktop|\bhob\b/, fixture: 'cooktop', label: 'CT' },
40
+ { test: /\bstove\b|\brange\b(?!-hood)/, fixture: 'range', label: 'R' },
41
+ { test: /\boven\b/, fixture: 'oven', label: 'OV' },
42
+ {
43
+ test: /kitchen-?sink|bar-?sink|utility-?sink|laundry-?sink|\bsink\b/,
44
+ fixture: 'sink',
45
+ label: 'SINK',
46
+ },
47
+ { test: /fireplace|wood-?stove/, fixture: 'fireplace', label: 'FP' },
48
+ { test: /ev-?(wall-)?charger|\bevse\b/, fixture: 'ev', label: 'EV' },
49
+ { test: /ac-block|condenser|condensing-unit|heat-pump/, fixture: 'condenser', label: 'A/C' },
50
+ ];
51
+ /** Built-in cabinets and counters placed as items: casework, drawn in ink like a cabinet run. */
52
+ const CASEWORK = /kitchen-counter|kitchen-cabinet|kitchen-island|kitchen-bar|^kitchen$|base-cabinet|^cabinet$|modular-cabinet/;
53
+ /** Decor, loose kitchenware and wall devices: not drawn on a permit floor plan. */
54
+ const OMIT = /plant|cactus|\btree\b|\bbush\b|\bpalm\b|carpet|\brug\b|picture|mirror|lamp|light|toilet-?paper|laundry-?bag|\bbooks?\b|\btoy\b|\bball\b|skate|scooter|kettle|toaster|frying|fruit|wine|utensil|cutting-?board|coffee-?machine|\biron\b|ironing|computer|speaker|guitar|easel|sewing|barbell|outlet|thermostat|keypad|detector|sprinkler|exit-?sign|electric-?panel|alarm|umbrella|hydrant|basket|drying-?rack|coat-?rack|\bhood\b|television|\btv\b(?!-stand)|air-?conditioning|parking-?spot|kitchen-?shelf/;
55
+ const CAR = /\bcar\b(?!-toy)|tesla|camaro|chevrolet|\btruck\b|sedan|\bsuv\b|vehicle/;
56
+ const BED = /\bbed\b|bunkbed|double-bed|single-bed/;
57
+ const SOFA = /sofa|couch|sectional|loveseat/;
58
+ /** What a sheet draws for an item, from its asset. */
59
+ export function classifyPlanItem(asset) {
60
+ if (asset.attachTo === 'ceiling')
61
+ return { kind: 'omit' };
62
+ const id = (asset.id ?? '').toLowerCase();
63
+ const name = (asset.name ?? '').toLowerCase().replace(/\s+/g, '-');
64
+ // the id first: it is the catalog's own word for the thing
65
+ for (const text of [id, name]) {
66
+ if (!text)
67
+ continue;
68
+ for (const entry of FIXTURES) {
69
+ if (!entry.test.test(text))
70
+ continue;
71
+ // a tub with a shower over it is the TUB/SHWR a plan labels
72
+ if (entry.fixture === 'tub' && /shower/.test(`${id} ${name}`)) {
73
+ return { kind: 'fixture', fixture: 'tub', label: 'TUB/SHWR' };
74
+ }
75
+ return { kind: 'fixture', fixture: entry.fixture, label: entry.label };
76
+ }
77
+ }
78
+ const words = `${id} ${name}`;
79
+ if (CASEWORK.test(id) || CASEWORK.test(name))
80
+ return { kind: 'casework' };
81
+ if (CAR.test(words))
82
+ return { kind: 'car' };
83
+ if (OMIT.test(words))
84
+ return { kind: 'omit' };
85
+ if (asset.attachTo === 'wall' || asset.attachTo === 'wall-side') {
86
+ // shelves, cabinets and the like hang on a wall inside the cut: outline them
87
+ return { kind: 'furniture', shape: 'plain' };
88
+ }
89
+ if (BED.test(words))
90
+ return { kind: 'furniture', shape: 'bed' };
91
+ if (SOFA.test(words))
92
+ return { kind: 'furniture', shape: 'sofa' };
93
+ return { kind: 'furniture', shape: 'plain' };
94
+ }
95
+ /* ------------------------------------------------------------ styles */
96
+ /** Fixture linework — the weight casework draws in, near-black. */
97
+ export const FIXTURE_STROKE = '#1f2937';
98
+ export const FIXTURE_STROKE_WIDTH = 0.012;
99
+ const FIXTURE_DETAIL_WIDTH = 0.008;
100
+ /** Furniture: thin, light grey — present, never competing with the walls. */
101
+ export const FURNITURE_STROKE = '#9ca3af';
102
+ export const FURNITURE_STROKE_WIDTH = 0.006;
103
+ const LABEL_FILL = '#111827';
104
+ /** Fixture label size on the paper, points, and its plan-metre size at 1/4" = 1'-0". */
105
+ export const FIXTURE_LABEL_PT = 6.5;
106
+ export const FIXTURE_LABEL_SIZE = 0.11;
107
+ /**
108
+ * The drafting symbol for an item, in plan coordinates. Empty for `omit`.
109
+ */
110
+ export function buildPlanItemSymbol(cls, frame) {
111
+ switch (cls.kind) {
112
+ case 'omit':
113
+ return [];
114
+ case 'car':
115
+ return [carOutline(frame)];
116
+ case 'casework': {
117
+ const hw = frame.width / 2;
118
+ const hd = frame.depth / 2;
119
+ return [
120
+ polygon(frame, rect(-hw, -hd, hw, hd), {
121
+ ...OUTLINE,
122
+ strokeWidth: FIXTURE_DETAIL_WIDTH * 1.25,
123
+ }),
124
+ ];
125
+ }
126
+ case 'furniture':
127
+ return furnitureSymbol(cls.shape, frame);
128
+ case 'fixture':
129
+ return fixtureSymbol(cls.fixture, cls.label, frame);
130
+ }
131
+ }
132
+ const OUTLINE = {
133
+ stroke: FIXTURE_STROKE,
134
+ strokeWidth: FIXTURE_STROKE_WIDTH,
135
+ fill: '#ffffff',
136
+ };
137
+ const DETAIL = { stroke: FIXTURE_STROKE, strokeWidth: FIXTURE_DETAIL_WIDTH, fill: 'none' };
138
+ const FURNITURE = {
139
+ stroke: FURNITURE_STROKE,
140
+ strokeWidth: FURNITURE_STROKE_WIDTH,
141
+ fill: 'none',
142
+ };
143
+ function polygon(frame, points, style) {
144
+ return {
145
+ kind: 'polygon',
146
+ points: points.map(([x, y]) => frame.map(x, y)),
147
+ fill: style.fill ?? 'none',
148
+ stroke: style.stroke,
149
+ strokeWidth: style.strokeWidth,
150
+ strokeDasharray: style.strokeDasharray,
151
+ strokeLinejoin: 'round',
152
+ };
153
+ }
154
+ function line(frame, x1, y1, x2, y2, style) {
155
+ const [ax, ay] = frame.map(x1, y1);
156
+ const [bx, by] = frame.map(x2, y2);
157
+ return {
158
+ kind: 'line',
159
+ x1: ax,
160
+ y1: ay,
161
+ x2: bx,
162
+ y2: by,
163
+ stroke: style.stroke,
164
+ strokeWidth: style.strokeWidth,
165
+ strokeDasharray: style.strokeDasharray,
166
+ };
167
+ }
168
+ function circle(frame, x, y, r, style) {
169
+ const [cx, cy] = frame.map(x, y);
170
+ return {
171
+ kind: 'circle',
172
+ cx,
173
+ cy,
174
+ r,
175
+ fill: style.fill ?? 'none',
176
+ stroke: style.stroke,
177
+ strokeWidth: style.strokeWidth,
178
+ };
179
+ }
180
+ function rect(x0, y0, x1, y1) {
181
+ return [
182
+ [x0, y0],
183
+ [x1, y0],
184
+ [x1, y1],
185
+ [x0, y1],
186
+ ];
187
+ }
188
+ function roundedRect(x0, y0, x1, y1, radius) {
189
+ const r = Math.max(0, Math.min(radius, (x1 - x0) / 2, (y1 - y0) / 2));
190
+ if (r < 1e-4)
191
+ return rect(x0, y0, x1, y1);
192
+ const out = [];
193
+ const corner = (cx, cy, from) => {
194
+ for (let i = 0; i <= 4; i++) {
195
+ const a = from + (i / 4) * (Math.PI / 2);
196
+ out.push([cx + Math.cos(a) * r, cy + Math.sin(a) * r]);
197
+ }
198
+ };
199
+ corner(x1 - r, y0 + r, -Math.PI / 2);
200
+ corner(x1 - r, y1 - r, 0);
201
+ corner(x0 + r, y1 - r, Math.PI / 2);
202
+ corner(x0 + r, y0 + r, Math.PI);
203
+ return out;
204
+ }
205
+ function ellipse(cx, cy, rx, ry, segments = 32) {
206
+ const out = [];
207
+ for (let i = 0; i < segments; i++) {
208
+ const a = (i / segments) * Math.PI * 2;
209
+ out.push([cx + Math.cos(a) * rx, cy + Math.sin(a) * ry]);
210
+ }
211
+ return out;
212
+ }
213
+ /**
214
+ * A fixture label. Text is an annotation on a sheet, printed at a fixed paper
215
+ * size (`FIXTURE_LABEL_PT`) whatever the scale; `fontSize` is its plan-metre
216
+ * size at 1/4" = 1'-0" for any view that draws it in plan units. Each label
217
+ * is its own group so two labels that share an x (a double vanity's LAVs)
218
+ * are never read as one stacked block and re-spaced together.
219
+ */
220
+ function label(frame, text, x, y) {
221
+ const [px, py] = frame.map(x, y);
222
+ return {
223
+ kind: 'group',
224
+ children: [
225
+ {
226
+ kind: 'text',
227
+ x: px,
228
+ y: py,
229
+ text,
230
+ fontSize: FIXTURE_LABEL_SIZE,
231
+ fill: LABEL_FILL,
232
+ fontWeight: 700,
233
+ fontFamily: 'Helvetica, Arial, sans-serif',
234
+ textAnchor: 'middle',
235
+ dominantBaseline: 'central',
236
+ upright: true,
237
+ metadata: floorplanGeometryMetadata({ textSizePt: FIXTURE_LABEL_PT }),
238
+ },
239
+ ],
240
+ };
241
+ }
242
+ /* ------------------------------------------------------------ symbols */
243
+ function carOutline(frame) {
244
+ const hw = frame.width / 2;
245
+ const hd = frame.depth / 2;
246
+ return polygon(frame, roundedRect(-hw, -hd, hw, hd, Math.min(hw, hd) * 0.35), {
247
+ stroke: FURNITURE_STROKE,
248
+ strokeWidth: FURNITURE_STROKE_WIDTH * 1.2,
249
+ fill: 'none',
250
+ strokeDasharray: '0.18 0.12',
251
+ });
252
+ }
253
+ function furnitureSymbol(shape, frame) {
254
+ const hw = frame.width / 2;
255
+ const hd = frame.depth / 2;
256
+ const out = [polygon(frame, rect(-hw, -hd, hw, hd), FURNITURE)];
257
+ if (shape === 'bed' && frame.depth > 1.2) {
258
+ // pillows at the head (the back), the turned-down sheet across
259
+ const pillows = frame.width >= 1.2 ? 2 : 1;
260
+ const gap = 0.06;
261
+ const pw = (frame.width - gap * (pillows + 1)) / pillows;
262
+ for (let i = 0; i < pillows; i++) {
263
+ const x0 = -hw + gap + i * (pw + gap);
264
+ out.push(polygon(frame, roundedRect(x0, -hd + gap, x0 + pw, -hd + gap + 0.2, 0.05), FURNITURE));
265
+ }
266
+ out.push(line(frame, -hw, -hd + 0.5, hw, -hd + 0.5, FURNITURE));
267
+ }
268
+ else if (shape === 'sofa' && frame.depth > 0.5 && frame.width > 1) {
269
+ const back = -hd + Math.min(0.22, frame.depth * 0.25);
270
+ const arm = Math.min(0.2, frame.width * 0.12);
271
+ out.push(line(frame, -hw, back, hw, back, FURNITURE));
272
+ out.push(line(frame, -hw + arm, back, -hw + arm, hd, FURNITURE));
273
+ out.push(line(frame, hw - arm, back, hw - arm, hd, FURNITURE));
274
+ }
275
+ return out;
276
+ }
277
+ function fixtureSymbol(fixture, text, frame) {
278
+ const w = frame.width;
279
+ const d = frame.depth;
280
+ const hw = w / 2;
281
+ const hd = d / 2;
282
+ const out = [];
283
+ switch (fixture) {
284
+ case 'wc': {
285
+ // tank against the wall, elongated bowl in front of it
286
+ const tank = Math.min(0.22, Math.max(0.15, d * 0.3));
287
+ out.push(polygon(frame, roundedRect(-hw, -hd, hw, -hd + tank, 0.03), OUTLINE));
288
+ const bowlLength = Math.max(0.2, d - tank - 0.02);
289
+ const cy = -hd + tank + bowlLength / 2;
290
+ const rx = Math.min(hw * 0.92, 0.2);
291
+ out.push(polygon(frame, ellipse(0, cy, rx, bowlLength / 2), OUTLINE));
292
+ out.push(polygon(frame, ellipse(0, cy + bowlLength * 0.04, rx * 0.68, bowlLength * 0.34), DETAIL));
293
+ out.push(label(frame, text, 0, cy + bowlLength * 0.04));
294
+ return out;
295
+ }
296
+ case 'lav': {
297
+ out.push(polygon(frame, rect(-hw, -hd, hw, hd), OUTLINE));
298
+ // a double vanity from 48 in wide: a basin per sink, each labelled
299
+ const basins = w >= 1.2 ? 2 : 1;
300
+ const pitch = w / basins;
301
+ const rx = Math.min(0.22, pitch * 0.34);
302
+ const ry = Math.min(0.17, d * 0.3);
303
+ for (let i = 0; i < basins; i++) {
304
+ const cx = -hw + pitch * (i + 0.5);
305
+ const cy = d * 0.04;
306
+ out.push(polygon(frame, ellipse(cx, cy, rx, ry), DETAIL));
307
+ out.push(circle(frame, cx, cy - ry - 0.05, 0.018, DETAIL));
308
+ out.push(label(frame, 'LAV', cx, cy));
309
+ }
310
+ return out;
311
+ }
312
+ case 'tub': {
313
+ out.push(polygon(frame, rect(-hw, -hd, hw, hd), OUTLINE));
314
+ const inset = Math.min(0.08, Math.min(w, d) * 0.1);
315
+ // the long axis carries the drain at one end
316
+ const long = w >= d;
317
+ out.push(polygon(frame, roundedRect(-hw + inset, -hd + inset, hw - inset, hd - inset, Math.min(w, d) * 0.22), DETAIL));
318
+ if (long)
319
+ out.push(circle(frame, -hw + inset + 0.14, 0, 0.03, DETAIL));
320
+ else
321
+ out.push(circle(frame, 0, -hd + inset + 0.14, 0.03, DETAIL));
322
+ out.push(label(frame, text, 0, 0));
323
+ return out;
324
+ }
325
+ case 'shower': {
326
+ out.push(polygon(frame, rect(-hw, -hd, hw, hd), OUTLINE));
327
+ const inset = Math.min(0.05, Math.min(w, d) * 0.08);
328
+ out.push(polygon(frame, rect(-hw + inset, -hd + inset, hw - inset, hd - inset), DETAIL));
329
+ // the drain, and the diagonals a shower pan is drawn with, stopped short of the label
330
+ out.push(circle(frame, 0, d * 0.22, 0.035, DETAIL));
331
+ out.push(line(frame, -hw + inset, hd - inset, -0.08, d * 0.22 + 0.06, DETAIL));
332
+ out.push(line(frame, hw - inset, hd - inset, 0.08, d * 0.22 + 0.06, DETAIL));
333
+ out.push(label(frame, text, 0, -d * 0.08));
334
+ return out;
335
+ }
336
+ case 'washer':
337
+ case 'dryer':
338
+ case 'washer-dryer': {
339
+ out.push(polygon(frame, rect(-hw, -hd, hw, hd), OUTLINE));
340
+ if (fixture === 'washer')
341
+ out.push(circle(frame, 0, 0, Math.min(w, d) * 0.32, DETAIL));
342
+ if (fixture === 'washer-dryer')
343
+ out.push(line(frame, -hw, hd - 0.06, hw, hd - 0.06, DETAIL));
344
+ out.push(label(frame, text, 0, 0));
345
+ return out;
346
+ }
347
+ case 'water-heater': {
348
+ const r = Math.min(w, d) / 2;
349
+ out.push(circle(frame, 0, 0, r, OUTLINE));
350
+ out.push(label(frame, text, 0, 0));
351
+ return out;
352
+ }
353
+ case 'ref': {
354
+ out.push(polygon(frame, rect(-hw, -hd, hw, hd), OUTLINE));
355
+ // the door's swing line across the front
356
+ out.push(line(frame, -hw, hd - Math.min(0.06, d * 0.1), hw, hd - Math.min(0.06, d * 0.1), DETAIL));
357
+ out.push(label(frame, text, 0, -d * 0.05));
358
+ return out;
359
+ }
360
+ case 'range':
361
+ case 'cooktop': {
362
+ out.push(polygon(frame, rect(-hw, -hd, hw, hd), OUTLINE));
363
+ const r = Math.min(0.08, w * 0.13, d * 0.14);
364
+ for (const [x, y] of [
365
+ [-w * 0.26, -d * 0.2],
366
+ [w * 0.26, -d * 0.2],
367
+ [-w * 0.26, d * 0.18],
368
+ [w * 0.26, d * 0.18],
369
+ ]) {
370
+ out.push(circle(frame, x, y, r, DETAIL));
371
+ }
372
+ out.push(label(frame, text, 0, 0));
373
+ return out;
374
+ }
375
+ case 'sink': {
376
+ out.push(polygon(frame, rect(-hw, -hd, hw, hd), OUTLINE));
377
+ const inset = Math.min(0.06, Math.min(w, d) * 0.12);
378
+ out.push(polygon(frame, roundedRect(-hw + inset, -hd + inset * 1.8, hw - inset, hd - inset, 0.04), DETAIL));
379
+ out.push(label(frame, text, 0, 0));
380
+ return out;
381
+ }
382
+ case 'fireplace': {
383
+ out.push(polygon(frame, rect(-hw, -hd, hw, hd), {
384
+ ...OUTLINE,
385
+ strokeWidth: FIXTURE_STROKE_WIDTH * 1.4,
386
+ }));
387
+ if (d > 0.3) {
388
+ // the firebox, splayed toward the room
389
+ const back = -hd + d * 0.25;
390
+ out.push(polygon(frame, [
391
+ [-w * 0.2, back],
392
+ [w * 0.2, back],
393
+ [w * 0.32, hd],
394
+ [-w * 0.32, hd],
395
+ ], DETAIL));
396
+ }
397
+ out.push(label(frame, text, 0, 0));
398
+ return out;
399
+ }
400
+ default: {
401
+ // DW, MW, OV, EV: the box and its label
402
+ out.push(polygon(frame, rect(-hw, -hd, hw, hd), OUTLINE));
403
+ out.push(label(frame, text, 0, 0));
404
+ return out;
405
+ }
406
+ }
407
+ }