@pascal-app/editor 0.8.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (350) hide show
  1. package/package.json +15 -13
  2. package/src/components/editor/alignment-3d-guide-layer.tsx +168 -0
  3. package/src/components/editor/bake-exporter.tsx +47 -0
  4. package/src/components/editor/custom-camera-controls.tsx +795 -28
  5. package/src/components/editor/editor-layout-mobile.tsx +8 -3
  6. package/src/components/editor/editor-layout-v2.tsx +76 -51
  7. package/src/components/editor/export-manager.tsx +69 -32
  8. package/src/components/editor/fence-tangent-lines-3d.tsx +87 -0
  9. package/src/components/editor/first-person/build-collider-world.test.ts +182 -0
  10. package/src/components/editor/first-person/build-collider-world.ts +228 -83
  11. package/src/components/editor/first-person-controls.tsx +943 -27
  12. package/src/components/editor/floating-action-menu.tsx +676 -208
  13. package/src/components/editor/floating-building-action-menu.tsx +2 -2
  14. package/src/components/editor/floorplan-background-selection.test.ts +58 -0
  15. package/src/components/editor/floorplan-background-selection.ts +3 -2
  16. package/src/components/editor/floorplan-panel.tsx +6916 -12137
  17. package/src/components/editor/grid.tsx +197 -36
  18. package/src/components/editor/group-actions.ts +457 -0
  19. package/src/components/editor/group-floating-action-menu.tsx +130 -0
  20. package/src/components/editor/group-move-3d.ts +397 -0
  21. package/src/components/editor/group-rotate-handle.tsx +420 -0
  22. package/src/components/editor/group-selection-box-3d.tsx +173 -0
  23. package/src/components/editor/group-transform-shared.test.ts +396 -0
  24. package/src/components/editor/group-transform-shared.ts +489 -0
  25. package/src/components/editor/handles/handle-arrow.tsx +581 -0
  26. package/src/components/editor/handles/use-handle-drag.ts +246 -0
  27. package/src/components/editor/index.tsx +412 -162
  28. package/src/components/editor/measurement-pill.tsx +115 -0
  29. package/src/components/editor/node-action-menu.tsx +14 -1
  30. package/src/components/editor/node-arrow-handles.tsx +1646 -0
  31. package/src/components/editor/opening-guides-3d-layer.tsx +144 -0
  32. package/src/components/editor/quick-measurement-card.tsx +70 -0
  33. package/src/components/editor/quick-measurement-hud.tsx +28 -0
  34. package/src/components/editor/riser-diagram-panel.tsx +137 -0
  35. package/src/components/editor/selection-manager.tsx +1106 -483
  36. package/src/components/editor/site-edge-labels.tsx +45 -21
  37. package/src/components/editor/slab-hole-highlights.tsx +474 -0
  38. package/src/components/editor/snapshot-capture-overlay.tsx +369 -155
  39. package/src/components/editor/three-context-bridge.ts +22 -0
  40. package/src/components/editor/thumbnail-generator.tsx +140 -41
  41. package/src/components/editor/use-floorplan-background-placement.ts +190 -35
  42. package/src/components/editor/use-floorplan-hit-testing.ts +24 -0
  43. package/src/components/editor/use-floorplan-scene-data.ts +19 -7
  44. package/src/components/editor/use-mesh-settle-epoch.ts +26 -0
  45. package/src/components/editor/wall-measurement-label.tsx +14 -19
  46. package/src/components/editor/wall-move-side-handles.tsx +870 -0
  47. package/src/components/editor/wall-opening-highlights.tsx +181 -0
  48. package/src/components/editor/wall-snap-beacon-layer.tsx +304 -0
  49. package/src/components/editor-2d/floorplan-action-menu-layer.tsx +15 -6
  50. package/src/components/editor-2d/floorplan-alignment-guide-layer.tsx +142 -0
  51. package/src/components/editor-2d/floorplan-cursor-indicator-overlay.tsx +5 -3
  52. package/src/components/editor-2d/floorplan-group-action-menu.tsx +87 -0
  53. package/src/components/editor-2d/floorplan-group-move.tsx +701 -0
  54. package/src/components/editor-2d/floorplan-measurement-tool-layer.test.ts +113 -0
  55. package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +1656 -0
  56. package/src/components/editor-2d/floorplan-quick-measure-layer.tsx +212 -0
  57. package/src/components/editor-2d/floorplan-registry-action-menu.tsx +392 -0
  58. package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +857 -0
  59. package/src/components/editor-2d/floorplan-render-context.tsx +62 -0
  60. package/src/components/editor-2d/floorplan-snap-beacon-layer.tsx +77 -0
  61. package/src/components/editor-2d/floorplan-wall-move-ghost-layer.tsx +47 -0
  62. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +266 -0
  63. package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +15 -0
  64. package/src/components/editor-2d/renderers/floorplan-label-angle.ts +14 -0
  65. package/src/components/editor-2d/renderers/floorplan-measurements-layer.tsx +108 -66
  66. package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +62 -0
  67. package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +308 -0
  68. package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +3325 -0
  69. package/src/components/editor-2d/renderers/floorplan-stair-layer.tsx +24 -9
  70. package/src/components/editor-2d/renderers/floorplan-voronoi-layer.tsx +128 -0
  71. package/src/components/editor-2d/svg-paths.ts +10 -2
  72. package/src/components/systems/ceiling/ceiling-selection-affordance-system.tsx +439 -57
  73. package/src/components/systems/ceiling/ceiling-system.tsx +109 -12
  74. package/src/components/systems/roof/roof-edit-system.tsx +1851 -22
  75. package/src/components/systems/selection-affordance-manager.tsx +38 -0
  76. package/src/components/systems/stair/stair-edit-system.tsx +1 -1
  77. package/src/components/systems/zone/zone-label-editor-system.tsx +14 -1
  78. package/src/components/systems/zone/zone-system.tsx +42 -13
  79. package/src/components/tools/elevator/elevator-defaults.ts +8 -0
  80. package/src/components/tools/elevator/elevator-tool.tsx +375 -0
  81. package/src/components/tools/elevator/move-elevator-tool.tsx +263 -0
  82. package/src/components/tools/fence/fence-drafting.ts +141 -27
  83. package/src/components/tools/item/move-tool.tsx +45 -105
  84. package/src/components/tools/item/placement-math.test.ts +22 -0
  85. package/src/components/tools/item/placement-math.ts +59 -7
  86. package/src/components/tools/item/placement-strategies.ts +432 -16
  87. package/src/components/tools/item/placement-types.ts +22 -1
  88. package/src/components/tools/item/use-draft-node.ts +51 -2
  89. package/src/components/tools/item/use-placement-coordinator.tsx +1399 -256
  90. package/src/components/tools/registry/move-registry-node-tool.tsx +1064 -0
  91. package/src/components/tools/roof/roof-tool.tsx +350 -28
  92. package/src/components/tools/select/box-select-state.ts +88 -0
  93. package/src/components/tools/select/box-select-tool.tsx +442 -520
  94. package/src/components/tools/select/marquee-geometry.test.ts +161 -0
  95. package/src/components/tools/select/marquee-geometry.ts +155 -0
  96. package/src/components/tools/select/plane-box-select-tool.tsx +570 -0
  97. package/src/components/tools/select/screen-rectangle-selection.ts +84 -0
  98. package/src/components/tools/select/select-candidates.test.ts +109 -0
  99. package/src/components/tools/select/select-candidates.ts +85 -0
  100. package/src/components/tools/shared/affordance-dispatch.ts +30 -0
  101. package/src/components/tools/shared/cursor-sphere.tsx +62 -26
  102. package/src/components/tools/shared/drag-bounding-box.tsx +195 -0
  103. package/src/components/tools/shared/facing-indicator.tsx +87 -0
  104. package/src/components/tools/shared/facing-pose-indicator.tsx +54 -0
  105. package/src/components/tools/shared/floor-stack-preview.ts +25 -0
  106. package/src/components/tools/shared/fresh-placement-visibility.ts +61 -0
  107. package/src/components/tools/shared/placement-box-geometry.ts +123 -0
  108. package/src/components/tools/shared/placement-box.tsx +305 -0
  109. package/src/components/tools/shared/polygon-editor.tsx +866 -175
  110. package/src/components/tools/shared/segment-angle.ts +56 -0
  111. package/src/components/tools/site/site-boundary-editor.tsx +520 -16
  112. package/src/components/tools/site/site-flag-model.ts +18 -0
  113. package/src/components/tools/stair/stair-defaults.ts +2 -1
  114. package/src/components/tools/stair/stair-tool.tsx +342 -37
  115. package/src/components/tools/tool-manager.tsx +239 -62
  116. package/src/components/tools/wall/wall-drafting.test.ts +330 -0
  117. package/src/components/tools/wall/wall-drafting.ts +248 -171
  118. package/src/components/tools/wall/wall-snap-geometry.test.ts +123 -0
  119. package/src/components/tools/wall/wall-snap-geometry.ts +331 -0
  120. package/src/components/tools/zone/zone-boundary-editor.tsx +5 -1
  121. package/src/components/tools/zone/zone-tool.tsx +86 -82
  122. package/src/components/ui/action-menu/action-button.tsx +21 -1
  123. package/src/components/ui/action-menu/camera-actions.tsx +24 -17
  124. package/src/components/ui/action-menu/control-modes.tsx +40 -170
  125. package/src/components/ui/action-menu/furnish-tools.tsx +5 -5
  126. package/src/components/ui/action-menu/index.tsx +3 -117
  127. package/src/components/ui/action-menu/measurement-control.tsx +188 -0
  128. package/src/components/ui/action-menu/structure-tools.tsx +27 -93
  129. package/src/components/ui/action-menu/view-toggles.tsx +279 -90
  130. package/src/components/ui/command-palette/editor-commands.tsx +20 -15
  131. package/src/components/ui/command-palette/index.tsx +5 -3
  132. package/src/components/ui/controls/material-paint-panel.tsx +152 -0
  133. package/src/components/ui/controls/material-picker.tsx +87 -177
  134. package/src/components/ui/controls/material-properties-editor.tsx +108 -0
  135. package/src/components/ui/controls/metric-control.tsx +142 -46
  136. package/src/components/ui/controls/scene-material-list.tsx +247 -0
  137. package/src/components/ui/controls/slider-control.tsx +88 -38
  138. package/src/components/ui/floating-level-selector.tsx +47 -10
  139. package/src/components/ui/helpers/building-helper.tsx +10 -23
  140. package/src/components/ui/helpers/contextual-helper-panel.tsx +428 -0
  141. package/src/components/ui/helpers/helper-manager.tsx +235 -23
  142. package/src/components/ui/helpers/item-helper.tsx +28 -32
  143. package/src/components/ui/helpers/registered-tool-helper.tsx +59 -0
  144. package/src/components/ui/helpers/roof-helper.tsx +10 -12
  145. package/src/components/ui/icon-ref.tsx +47 -0
  146. package/src/components/ui/item-catalog/catalog-items.tsx +40 -1
  147. package/src/components/ui/item-catalog/item-catalog.tsx +16 -36
  148. package/src/components/ui/level-duplicate-dialog.tsx +2 -1
  149. package/src/components/ui/panels/node-display.ts +17 -16
  150. package/src/components/ui/panels/panel-manager.tsx +55 -58
  151. package/src/components/ui/panels/panel-wrapper.tsx +238 -12
  152. package/src/components/ui/panels/parametric-inspector.tsx +482 -0
  153. package/src/components/ui/panels/reference-panel.tsx +54 -19
  154. package/src/components/ui/primitives/dropdown-menu.tsx +12 -8
  155. package/src/components/ui/primitives/shortcut-token.tsx +39 -3
  156. package/src/components/ui/primitives/sidebar.tsx +1 -0
  157. package/src/components/ui/scene-loader.tsx +1 -3
  158. package/src/components/ui/sidebar/app-sidebar.tsx +5 -1
  159. package/src/components/ui/sidebar/icon-rail.tsx +50 -31
  160. package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +263 -0
  161. package/src/components/ui/sidebar/panels/items-panel/index.tsx +82 -8
  162. package/src/components/ui/sidebar/panels/plugins-panel.tsx +218 -0
  163. package/src/components/ui/sidebar/panels/settings-panel/index.tsx +122 -41
  164. package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +66 -7
  165. package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +267 -0
  166. package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +3 -1
  167. package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +9 -5
  168. package/src/components/ui/sidebar/panels/site-panel/chimney-tree-node.tsx +86 -0
  169. package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +1 -1
  170. package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +7 -2
  171. package/src/components/ui/sidebar/panels/site-panel/dormer-tree-node.tsx +92 -0
  172. package/src/components/ui/sidebar/panels/site-panel/elevator-tree-node.tsx +75 -0
  173. package/src/components/ui/sidebar/panels/site-panel/fence-tree-node.tsx +3 -3
  174. package/src/components/ui/sidebar/panels/site-panel/gutter-tree-node.tsx +86 -0
  175. package/src/components/ui/sidebar/panels/site-panel/index.tsx +42 -21
  176. package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +31 -17
  177. package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +2 -1
  178. package/src/components/ui/sidebar/panels/site-panel/registry-tree-node.tsx +140 -0
  179. package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +48 -8
  180. package/src/components/ui/sidebar/panels/site-panel/shelf-tree-node.tsx +132 -0
  181. package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +9 -5
  182. package/src/components/ui/sidebar/panels/site-panel/solar-panel-tree-node.tsx +86 -0
  183. package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +7 -1
  184. package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +2 -2
  185. package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +112 -39
  186. package/src/components/ui/sidebar/panels/site-panel/tree-structure.ts +36 -0
  187. package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +1 -1
  188. package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +7 -2
  189. package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +3 -3
  190. package/src/components/ui/sidebar/panels/zone-panel/index.tsx +51 -2
  191. package/src/components/ui/sidebar/tab-bar.tsx +75 -1
  192. package/src/components/ui/sidebar/use-plugin-panels.tsx +132 -0
  193. package/src/components/ui/snap-target-badge.test.tsx +40 -0
  194. package/src/components/ui/snap-target-badge.tsx +88 -0
  195. package/src/components/viewer-overlay.tsx +253 -61
  196. package/src/components/viewer-zone-system.tsx +7 -2
  197. package/src/hooks/use-auto-save.test.ts +14 -0
  198. package/src/hooks/use-auto-save.ts +64 -10
  199. package/src/hooks/use-ceiling-events.ts +176 -0
  200. package/src/hooks/use-drag-action.ts +127 -0
  201. package/src/hooks/use-keyboard.ts +493 -95
  202. package/src/hooks/use-selection.ts +64 -0
  203. package/src/index.tsx +451 -6
  204. package/src/lib/active-placement-surface.ts +35 -0
  205. package/src/lib/ceiling-plan-snap.ts +24 -0
  206. package/src/lib/constants.ts +6 -2
  207. package/src/lib/contextual-help.test.ts +112 -0
  208. package/src/lib/contextual-help.ts +144 -0
  209. package/src/lib/continuation.ts +64 -0
  210. package/src/lib/direct-manipulation.test.ts +192 -0
  211. package/src/lib/direct-manipulation.ts +109 -0
  212. package/src/lib/editor-api.ts +50 -0
  213. package/src/lib/elevator-support.ts +96 -0
  214. package/src/lib/floorplan/apply-alignment.test.ts +25 -0
  215. package/src/lib/floorplan/apply-alignment.ts +117 -0
  216. package/src/lib/floorplan/floorplan-export.tsx +364 -0
  217. package/src/lib/floorplan/geometry.ts +53 -0
  218. package/src/lib/floorplan/index.ts +10 -0
  219. package/src/lib/floorplan/items.ts +5 -2
  220. package/src/lib/floorplan/plan-coords.ts +21 -0
  221. package/src/lib/floorplan/selection-tool.ts +40 -0
  222. package/src/lib/floorplan/stairs.ts +12 -1
  223. package/src/lib/fresh-planar-placement.test.ts +339 -0
  224. package/src/lib/fresh-planar-placement.ts +130 -0
  225. package/src/lib/glb-export.test.ts +441 -0
  226. package/src/lib/glb-export.ts +874 -0
  227. package/src/lib/history.ts +11 -1
  228. package/src/lib/interaction/hot-set.test.ts +133 -0
  229. package/src/lib/interaction/hot-set.ts +67 -0
  230. package/src/lib/interaction/overlay-policy.test.ts +51 -0
  231. package/src/lib/interaction/overlay-policy.ts +59 -0
  232. package/src/lib/interaction/scope.ts +211 -0
  233. package/src/lib/level-duplication.ts +54 -42
  234. package/src/lib/level-selection.ts +2 -2
  235. package/src/lib/material-paint.ts +227 -48
  236. package/src/lib/measurement-kind.test.ts +30 -0
  237. package/src/lib/measurement-kind.ts +19 -0
  238. package/src/lib/measurement-label.test.ts +47 -0
  239. package/src/lib/measurement-label.ts +68 -0
  240. package/src/lib/measurement-parser.ts +116 -0
  241. package/src/lib/measurements.test.ts +183 -0
  242. package/src/lib/measurements.ts +199 -0
  243. package/src/lib/paint-scope.test.ts +454 -0
  244. package/src/lib/paint-scope.ts +461 -0
  245. package/src/lib/placement-drag-release.ts +23 -0
  246. package/src/lib/placement-metadata.ts +29 -0
  247. package/src/lib/planar-cursor-placement.test.ts +100 -0
  248. package/src/lib/planar-cursor-placement.ts +42 -0
  249. package/src/lib/plugin-panels.test.ts +19 -0
  250. package/src/lib/plugin-panels.ts +91 -0
  251. package/src/lib/quick-measurement.test.ts +77 -0
  252. package/src/lib/quick-measurement.ts +109 -0
  253. package/src/lib/roof-duplication.ts +7 -7
  254. package/src/lib/roof-hover-outline-proxy.ts +22 -0
  255. package/src/lib/roof-wall-hit.ts +164 -0
  256. package/src/lib/scene-clipboard.test.ts +196 -0
  257. package/src/lib/scene-clipboard.ts +332 -0
  258. package/src/lib/scene.ts +40 -8
  259. package/src/lib/selection-routing.test.ts +298 -0
  260. package/src/lib/selection-routing.ts +175 -0
  261. package/src/lib/sfx/index.ts +1 -0
  262. package/src/lib/sfx/movement-tick.test.ts +65 -0
  263. package/src/lib/sfx/movement-tick.ts +18 -0
  264. package/src/lib/sfx-bus.ts +69 -10
  265. package/src/lib/sfx-player.test.ts +124 -0
  266. package/src/lib/sfx-player.ts +148 -55
  267. package/src/lib/site-boundary.ts +1 -0
  268. package/src/lib/slab-plan-snap.test.ts +93 -0
  269. package/src/lib/slab-plan-snap.ts +108 -0
  270. package/src/lib/snapping-mode.test.ts +138 -0
  271. package/src/lib/snapping-mode.ts +179 -0
  272. package/src/lib/stair-duplication.ts +4 -4
  273. package/src/lib/stair-levels.test.ts +146 -0
  274. package/src/lib/stair-levels.ts +177 -0
  275. package/src/lib/surface-plan-snap.test.ts +71 -0
  276. package/src/lib/surface-plan-snap.ts +256 -0
  277. package/src/lib/use-linear-display.ts +40 -0
  278. package/src/lib/world-grid-snap.ts +231 -0
  279. package/src/lib/zone-content.ts +130 -0
  280. package/src/store/use-alignment-guides.ts +21 -0
  281. package/src/store/use-direct-manipulation-feedback.ts +20 -0
  282. package/src/store/use-editor.tsx +767 -114
  283. package/src/store/use-facing-pose.ts +44 -0
  284. package/src/store/use-fence-curve-draft.ts +21 -0
  285. package/src/store/use-floorplan-draft-preview.ts +101 -0
  286. package/src/store/use-floorplan-marquee.ts +50 -0
  287. package/src/store/use-interaction-scope.test.ts +186 -0
  288. package/src/store/use-interaction-scope.ts +132 -0
  289. package/src/store/use-measurement-draft.test.ts +530 -0
  290. package/src/store/use-measurement-draft.ts +543 -0
  291. package/src/store/use-opening-guides.ts +41 -0
  292. package/src/store/use-placement-preview.ts +39 -0
  293. package/src/store/use-quick-measurement-hud.test.ts +53 -0
  294. package/src/store/use-quick-measurement-hud.ts +77 -0
  295. package/src/store/use-segment-draft-chain.ts +28 -0
  296. package/src/store/use-stair-build-preview.ts +43 -0
  297. package/src/store/use-wall-move-ghosts.ts +36 -0
  298. package/src/store/use-wall-snap-indicator.ts +34 -0
  299. package/src/components/editor/first-person/bvh-ecctrl.tsx +0 -860
  300. package/src/components/editor/preset-thumbnail-generator.tsx +0 -125
  301. package/src/components/editor-2d/renderers/floorplan-roof-layer.tsx +0 -113
  302. package/src/components/tools/building/move-building-tool.tsx +0 -157
  303. package/src/components/tools/ceiling/ceiling-boundary-editor.tsx +0 -43
  304. package/src/components/tools/ceiling/ceiling-hole-editor.tsx +0 -49
  305. package/src/components/tools/ceiling/ceiling-tool.tsx +0 -465
  306. package/src/components/tools/ceiling/move-ceiling-tool.tsx +0 -264
  307. package/src/components/tools/column/column-tool.tsx +0 -97
  308. package/src/components/tools/column/move-column-tool.tsx +0 -105
  309. package/src/components/tools/door/door-math.ts +0 -110
  310. package/src/components/tools/door/door-tool.tsx +0 -324
  311. package/src/components/tools/door/move-door-tool.tsx +0 -412
  312. package/src/components/tools/fence/curve-fence-tool.tsx +0 -178
  313. package/src/components/tools/fence/fence-tool.tsx +0 -346
  314. package/src/components/tools/fence/move-fence-endpoint-tool.tsx +0 -441
  315. package/src/components/tools/fence/move-fence-tool.tsx +0 -302
  316. package/src/components/tools/item/item-tool.tsx +0 -26
  317. package/src/components/tools/roof/move-roof-tool.tsx +0 -364
  318. package/src/components/tools/slab/move-slab-tool.tsx +0 -182
  319. package/src/components/tools/slab/slab-boundary-editor.tsx +0 -43
  320. package/src/components/tools/slab/slab-hole-editor.tsx +0 -49
  321. package/src/components/tools/slab/slab-tool.tsx +0 -322
  322. package/src/components/tools/spawn/move-spawn-tool.tsx +0 -101
  323. package/src/components/tools/spawn/spawn-tool.tsx +0 -130
  324. package/src/components/tools/wall/curve-wall-tool.tsx +0 -178
  325. package/src/components/tools/wall/move-wall-endpoint-tool.tsx +0 -426
  326. package/src/components/tools/wall/move-wall-tool.tsx +0 -358
  327. package/src/components/tools/wall/wall-tool.tsx +0 -332
  328. package/src/components/tools/window/move-window-tool.tsx +0 -447
  329. package/src/components/tools/window/window-math.ts +0 -117
  330. package/src/components/tools/window/window-tool.tsx +0 -332
  331. package/src/components/ui/helpers/ceiling-helper.tsx +0 -20
  332. package/src/components/ui/helpers/slab-helper.tsx +0 -20
  333. package/src/components/ui/helpers/wall-helper.tsx +0 -20
  334. package/src/components/ui/panels/ceiling-panel.tsx +0 -249
  335. package/src/components/ui/panels/column-panel.tsx +0 -759
  336. package/src/components/ui/panels/door-panel.tsx +0 -1299
  337. package/src/components/ui/panels/fence-panel.tsx +0 -222
  338. package/src/components/ui/panels/item-panel.tsx +0 -306
  339. package/src/components/ui/panels/paint-panel.tsx +0 -163
  340. package/src/components/ui/panels/presets/presets-popover.tsx +0 -511
  341. package/src/components/ui/panels/roof-panel.tsx +0 -280
  342. package/src/components/ui/panels/roof-segment-panel.tsx +0 -311
  343. package/src/components/ui/panels/slab-panel.tsx +0 -250
  344. package/src/components/ui/panels/spawn-panel.tsx +0 -161
  345. package/src/components/ui/panels/stair-panel.tsx +0 -577
  346. package/src/components/ui/panels/stair-segment-panel.tsx +0 -325
  347. package/src/components/ui/panels/wall-panel.tsx +0 -273
  348. package/src/components/ui/panels/window-panel.tsx +0 -968
  349. package/src/contexts/presets-context.tsx +0 -121
  350. package/src/hooks/use-contextual-tools.ts +0 -61
@@ -1,511 +0,0 @@
1
- 'use client'
2
-
3
- import { emitter } from '@pascal-app/core'
4
- import {
5
- BookMarked,
6
- Check,
7
- Globe,
8
- GlobeLock,
9
- MoreHorizontal,
10
- Pencil,
11
- Plus,
12
- Save,
13
- Trash2,
14
- Users,
15
- X,
16
- } from 'lucide-react'
17
- import { useCallback, useEffect, useState } from 'react'
18
- import type { PresetsTab } from '../../../../contexts/presets-context'
19
- import { cn } from '../../../../lib/utils'
20
- import {
21
- DropdownMenu,
22
- DropdownMenuContent,
23
- DropdownMenuItem,
24
- DropdownMenuTrigger,
25
- } from '../../primitives/dropdown-menu'
26
- import { Popover, PopoverContent, PopoverTrigger } from '../../primitives/popover'
27
-
28
- export type PresetType = 'door' | 'window'
29
-
30
- export interface PresetData {
31
- id: string
32
- type: string
33
- name: string
34
- data: Record<string, unknown>
35
- thumbnail_url: string | null
36
- user_id: string | null
37
- is_community: boolean
38
- created_at: string
39
- }
40
-
41
- interface PresetsPopoverProps {
42
- type: PresetType
43
- children: React.ReactNode
44
- isAuthenticated?: boolean
45
- tabs?: PresetsTab[]
46
- onFetchPresets: (tab: PresetsTab) => Promise<PresetData[]>
47
- onApply: (data: Record<string, unknown>) => void
48
- onSave: (name: string) => Promise<void>
49
- onOverwrite: (id: string) => Promise<void>
50
- onRename: (id: string, name: string) => Promise<void>
51
- onDelete: (id: string) => Promise<void>
52
- onToggleCommunity?: (id: string, current: boolean) => Promise<void>
53
- }
54
-
55
- export function PresetsPopover({
56
- type,
57
- onApply,
58
- onSave,
59
- onOverwrite,
60
- onFetchPresets,
61
- onRename,
62
- onDelete,
63
- onToggleCommunity,
64
- children,
65
- isAuthenticated = false,
66
- tabs = ['community', 'mine'],
67
- }: PresetsPopoverProps) {
68
- const defaultTab = tabs[0] ?? 'mine'
69
- const [open, setOpen] = useState(false)
70
- const [tab, setTab] = useState<PresetsTab>(defaultTab)
71
- const [presets, setPresets] = useState<PresetData[]>([])
72
- const [loading, setLoading] = useState(false)
73
-
74
- const [showSaveInput, setShowSaveInput] = useState(false)
75
- const [saveName, setSaveName] = useState('')
76
- const [saving, setSaving] = useState(false)
77
-
78
- const [renamingId, setRenamingId] = useState<string | null>(null)
79
- const [renameValue, setRenameValue] = useState('')
80
- const [deletingId, setDeletingId] = useState<string | null>(null)
81
- const [overwrittenId, setOverwrittenId] = useState<string | null>(null)
82
-
83
- const fetchPresets = useCallback(async () => {
84
- setLoading(true)
85
- try {
86
- const data = await onFetchPresets(tab)
87
- setPresets(data)
88
- } finally {
89
- setLoading(false)
90
- }
91
- }, [onFetchPresets, tab])
92
-
93
- useEffect(() => {
94
- if (open) fetchPresets()
95
- }, [open, fetchPresets])
96
-
97
- useEffect(() => {
98
- if (!isAuthenticated && tab === 'mine') setTab(defaultTab)
99
- }, [isAuthenticated, tab, defaultTab])
100
-
101
- useEffect(() => {
102
- const handler = ({ presetId, thumbnailUrl }: { presetId: string; thumbnailUrl: string }) => {
103
- setPresets((prev) =>
104
- prev.map((p) => (p.id === presetId ? { ...p, thumbnail_url: thumbnailUrl } : p)),
105
- )
106
- }
107
- emitter.on('preset:thumbnail-updated', handler)
108
- return () => emitter.off('preset:thumbnail-updated', handler)
109
- }, [])
110
-
111
- const handleSaveNew = async () => {
112
- if (!saveName.trim()) return
113
- setSaving(true)
114
- try {
115
- await onSave(saveName.trim())
116
- setSaveName('')
117
- setShowSaveInput(false)
118
- if (tab === 'mine') fetchPresets()
119
- else setTab('mine')
120
- } finally {
121
- setSaving(false)
122
- }
123
- }
124
-
125
- const handleRename = async (id: string) => {
126
- if (!renameValue.trim()) return
127
- await onRename(id, renameValue.trim())
128
- setPresets((prev) => prev.map((p) => (p.id === id ? { ...p, name: renameValue.trim() } : p)))
129
- setRenamingId(null)
130
- }
131
-
132
- const handleDelete = async (id: string) => {
133
- await onDelete(id)
134
- setPresets((prev) => prev.filter((p) => p.id !== id))
135
- setDeletingId(null)
136
- }
137
-
138
- const handleOverwrite = async (id: string) => {
139
- await onOverwrite(id)
140
- setOverwrittenId(id)
141
- setTimeout(() => setOverwrittenId(null), 1500)
142
- }
143
-
144
- const handleToggleCommunity = async (id: string, current: boolean) => {
145
- if (!onToggleCommunity) return
146
- await onToggleCommunity(id, current)
147
- setPresets((prev) => prev.map((p) => (p.id === id ? { ...p, is_community: !current } : p)))
148
- }
149
-
150
- const showTabs = tabs.length > 1
151
-
152
- return (
153
- <Popover onOpenChange={setOpen} open={open}>
154
- <PopoverTrigger asChild>{children}</PopoverTrigger>
155
- <PopoverContent
156
- align="start"
157
- className="w-72 overflow-hidden rounded-xl border-border/50 bg-sidebar/95 p-0 shadow-2xl backdrop-blur-xl"
158
- side="left"
159
- sideOffset={8}
160
- >
161
- <div className="flex items-center justify-between border-border/50 border-b px-3 py-2.5">
162
- <div className="flex items-center gap-1.5">
163
- <BookMarked className="h-3.5 w-3.5 text-muted-foreground" />
164
- <span className="font-semibold text-foreground text-xs tracking-tight">
165
- {type === 'door' ? 'Door' : 'Window'} Presets
166
- </span>
167
- </div>
168
- {isAuthenticated && (
169
- <button
170
- className="flex items-center gap-1 rounded-md px-2 py-1 font-medium text-[11px] text-muted-foreground transition-colors hover:bg-white/10 hover:text-foreground"
171
- onClick={() => {
172
- setShowSaveInput((v) => !v)
173
- setSaveName('')
174
- }}
175
- type="button"
176
- >
177
- <Plus className="h-3 w-3" />
178
- Save new
179
- </button>
180
- )}
181
- </div>
182
-
183
- {showSaveInput && (
184
- <div className="flex items-center gap-1.5 border-border/50 border-b bg-white/5 px-3 py-2">
185
- <input
186
- autoFocus
187
- className="min-w-0 flex-1 rounded-md border border-border/50 bg-background/50 px-2 py-1 text-foreground text-xs outline-none placeholder:text-muted-foreground/60 focus:border-ring focus:ring-1 focus:ring-ring/30"
188
- onChange={(e) => setSaveName(e.target.value)}
189
- onKeyDown={(e) => {
190
- if (e.key === 'Enter') handleSaveNew()
191
- if (e.key === 'Escape') {
192
- setShowSaveInput(false)
193
- setSaveName('')
194
- }
195
- }}
196
- placeholder="Preset name…"
197
- value={saveName}
198
- />
199
- <button
200
- className="flex h-6 w-6 items-center justify-center rounded-md bg-primary/20 text-primary transition-colors hover:bg-primary/30 disabled:opacity-40"
201
- disabled={!saveName.trim() || saving}
202
- onClick={handleSaveNew}
203
- type="button"
204
- >
205
- <Check className="h-3.5 w-3.5" />
206
- </button>
207
- <button
208
- className="flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-white/10"
209
- onClick={() => {
210
- setShowSaveInput(false)
211
- setSaveName('')
212
- }}
213
- type="button"
214
- >
215
- <X className="h-3.5 w-3.5" />
216
- </button>
217
- </div>
218
- )}
219
-
220
- {showTabs && (
221
- <div className="flex border-border/50 border-b">
222
- {tabs.includes('community') && (
223
- <TabButton active={tab === 'community'} onClick={() => setTab('community')}>
224
- <Users className="h-3 w-3" />
225
- Community
226
- </TabButton>
227
- )}
228
- {tabs.includes('mine') && (
229
- <TabButton
230
- active={tab === 'mine'}
231
- disabled={!isAuthenticated}
232
- onClick={() => {
233
- if (isAuthenticated) setTab('mine')
234
- }}
235
- >
236
- <BookMarked className="h-3 w-3" />
237
- My presets
238
- </TabButton>
239
- )}
240
- </div>
241
- )}
242
-
243
- <div className="no-scrollbar max-h-72 overflow-y-auto">
244
- {loading ? (
245
- <div className="flex items-center justify-center py-8">
246
- <div className="h-4 w-4 animate-spin rounded-full border-2 border-border border-t-foreground" />
247
- </div>
248
- ) : presets.length === 0 ? (
249
- <EmptyState isAuthenticated={isAuthenticated} tab={tab} />
250
- ) : (
251
- <ul className="divide-y divide-border/30">
252
- {presets.map((preset) => (
253
- <PresetRow
254
- deletingId={deletingId}
255
- isMine={tab === 'mine'}
256
- key={preset.id}
257
- onApply={() => {
258
- onApply(preset.data)
259
- setOpen(false)
260
- }}
261
- onDeleteCancel={() => setDeletingId(null)}
262
- onDeleteConfirm={() => handleDelete(preset.id)}
263
- onDeleteRequest={() => setDeletingId(preset.id)}
264
- onOverwrite={() => handleOverwrite(preset.id)}
265
- onRenameCancel={() => setRenamingId(null)}
266
- onRenameChange={setRenameValue}
267
- onRenameConfirm={() => handleRename(preset.id)}
268
- onStartRename={() => {
269
- setRenamingId(preset.id)
270
- setRenameValue(preset.name)
271
- }}
272
- onToggleCommunity={() => handleToggleCommunity(preset.id, preset.is_community)}
273
- overwrittenId={overwrittenId}
274
- preset={preset}
275
- renameValue={renameValue}
276
- renamingId={renamingId}
277
- showCommunityToggle={!!onToggleCommunity}
278
- />
279
- ))}
280
- </ul>
281
- )}
282
- </div>
283
- </PopoverContent>
284
- </Popover>
285
- )
286
- }
287
-
288
- function TabButton({
289
- active,
290
- onClick,
291
- disabled,
292
- children,
293
- }: {
294
- active: boolean
295
- onClick: () => void
296
- disabled?: boolean
297
- children: React.ReactNode
298
- }) {
299
- return (
300
- <button
301
- className={cn(
302
- 'flex flex-1 items-center justify-center gap-1.5 py-2 font-medium text-[11px] transition-colors',
303
- active
304
- ? '-mb-px border-primary border-b-2 text-foreground'
305
- : 'text-muted-foreground hover:text-foreground',
306
- disabled && 'cursor-not-allowed opacity-40',
307
- )}
308
- disabled={disabled}
309
- onClick={onClick}
310
- type="button"
311
- >
312
- {children}
313
- </button>
314
- )
315
- }
316
-
317
- function EmptyState({ tab, isAuthenticated }: { tab: PresetsTab; isAuthenticated: boolean }) {
318
- return (
319
- <div className="flex flex-col items-center justify-center gap-2 px-4 py-8 text-center">
320
- <BookMarked className="h-6 w-6 text-muted-foreground/40" />
321
- <p className="text-muted-foreground text-xs">
322
- {tab === 'community'
323
- ? 'No community presets yet.'
324
- : isAuthenticated
325
- ? 'No presets saved yet. Use "Save new" to save the current configuration.'
326
- : 'Sign in to save and view your presets.'}
327
- </p>
328
- </div>
329
- )
330
- }
331
-
332
- interface PresetRowProps {
333
- preset: PresetData
334
- isMine: boolean
335
- showCommunityToggle: boolean
336
- renamingId: string | null
337
- renameValue: string
338
- deletingId: string | null
339
- overwrittenId: string | null
340
- onApply: () => void
341
- onOverwrite: () => void
342
- onToggleCommunity: () => void
343
- onStartRename: () => void
344
- onRenameChange: (v: string) => void
345
- onRenameConfirm: () => void
346
- onRenameCancel: () => void
347
- onDeleteRequest: () => void
348
- onDeleteConfirm: () => void
349
- onDeleteCancel: () => void
350
- }
351
-
352
- function PresetRow({
353
- preset,
354
- isMine,
355
- showCommunityToggle,
356
- renamingId,
357
- renameValue,
358
- deletingId,
359
- overwrittenId,
360
- onApply,
361
- onOverwrite,
362
- onToggleCommunity,
363
- onStartRename,
364
- onRenameChange,
365
- onRenameConfirm,
366
- onRenameCancel,
367
- onDeleteRequest,
368
- onDeleteConfirm,
369
- onDeleteCancel,
370
- }: PresetRowProps) {
371
- const isRenaming = renamingId === preset.id
372
- const isDeleting = deletingId === preset.id
373
- const justOverwritten = overwrittenId === preset.id
374
-
375
- if (isDeleting) {
376
- return (
377
- <li className="flex items-center justify-between gap-2 bg-red-500/10 px-3 py-2.5">
378
- <span className="truncate text-foreground/80 text-xs">Delete "{preset.name}"?</span>
379
- <div className="flex shrink-0 items-center gap-1">
380
- <button
381
- className="rounded-md bg-red-500/20 px-2 py-0.5 font-medium text-[11px] text-red-400 transition-colors hover:bg-red-500/30"
382
- onClick={onDeleteConfirm}
383
- type="button"
384
- >
385
- Delete
386
- </button>
387
- <button
388
- className="rounded-md px-2 py-0.5 font-medium text-[11px] text-muted-foreground transition-colors hover:bg-white/10"
389
- onClick={onDeleteCancel}
390
- type="button"
391
- >
392
- Cancel
393
- </button>
394
- </div>
395
- </li>
396
- )
397
- }
398
-
399
- if (isRenaming) {
400
- return (
401
- <li className="flex items-center gap-1.5 px-3 py-2">
402
- <input
403
- autoFocus
404
- className="min-w-0 flex-1 rounded-md border border-border/50 bg-background/50 px-2 py-1 text-foreground text-xs outline-none focus:border-ring focus:ring-1 focus:ring-ring/30"
405
- onChange={(e) => onRenameChange(e.target.value)}
406
- onKeyDown={(e) => {
407
- if (e.key === 'Enter') onRenameConfirm()
408
- if (e.key === 'Escape') onRenameCancel()
409
- }}
410
- value={renameValue}
411
- />
412
- <button
413
- className="flex h-6 w-6 items-center justify-center rounded-md bg-primary/20 text-primary transition-colors hover:bg-primary/30"
414
- onClick={onRenameConfirm}
415
- type="button"
416
- >
417
- <Check className="h-3.5 w-3.5" />
418
- </button>
419
- <button
420
- className="flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-white/10"
421
- onClick={onRenameCancel}
422
- type="button"
423
- >
424
- <X className="h-3.5 w-3.5" />
425
- </button>
426
- </li>
427
- )
428
- }
429
-
430
- return (
431
- <li className="group flex items-center gap-2 px-3 py-2.5 transition-colors hover:bg-white/5">
432
- <div className="h-12 w-12 shrink-0 overflow-hidden rounded-md border border-border/40 bg-white/5">
433
- {preset.thumbnail_url ? (
434
- // eslint-disable-next-line @next/next/no-img-element
435
- <img
436
- alt={preset.name}
437
- className="h-full w-full object-cover"
438
- src={preset.thumbnail_url}
439
- />
440
- ) : (
441
- <div className="flex h-full w-full items-center justify-center">
442
- <div className="h-3 w-5 rounded-sm border border-muted-foreground/30" />
443
- </div>
444
- )}
445
- </div>
446
- <button className="min-w-0 flex-1 text-left" onClick={onApply} type="button">
447
- <span className="flex items-center gap-1.5">
448
- <span className="block truncate font-medium text-foreground text-xs group-hover:text-foreground/90">
449
- {preset.name}
450
- </span>
451
- {isMine && preset.is_community && (
452
- <Globe className="h-2.5 w-2.5 shrink-0 text-muted-foreground/50" />
453
- )}
454
- </span>
455
- <span className="block text-[10px] text-muted-foreground/60">
456
- {new Date(preset.created_at).toLocaleDateString()}
457
- </span>
458
- </button>
459
- {isMine && (
460
- <DropdownMenu>
461
- <DropdownMenuTrigger asChild>
462
- <button
463
- className={cn(
464
- 'flex h-6 w-6 shrink-0 items-center justify-center rounded-md opacity-0 transition-colors group-hover:opacity-100',
465
- justOverwritten
466
- ? 'bg-green-500/10 text-green-400 opacity-100'
467
- : 'text-muted-foreground hover:bg-white/10 hover:text-foreground',
468
- )}
469
- type="button"
470
- >
471
- {justOverwritten ? (
472
- <Check className="h-3 w-3" />
473
- ) : (
474
- <MoreHorizontal className="h-3.5 w-3.5" />
475
- )}
476
- </button>
477
- </DropdownMenuTrigger>
478
- <DropdownMenuContent align="start" className="min-w-44" side="left">
479
- <DropdownMenuItem onClick={onOverwrite}>
480
- <Save className="h-3.5 w-3.5" />
481
- Update with current
482
- </DropdownMenuItem>
483
- {showCommunityToggle && (
484
- <DropdownMenuItem onClick={onToggleCommunity}>
485
- {preset.is_community ? (
486
- <>
487
- <GlobeLock className="h-3.5 w-3.5" />
488
- Remove from community
489
- </>
490
- ) : (
491
- <>
492
- <Globe className="h-3.5 w-3.5" />
493
- Share with community
494
- </>
495
- )}
496
- </DropdownMenuItem>
497
- )}
498
- <DropdownMenuItem onClick={onStartRename}>
499
- <Pencil className="h-3.5 w-3.5" />
500
- Rename
501
- </DropdownMenuItem>
502
- <DropdownMenuItem onClick={onDeleteRequest} variant="destructive">
503
- <Trash2 className="h-3.5 w-3.5" />
504
- Delete
505
- </DropdownMenuItem>
506
- </DropdownMenuContent>
507
- </DropdownMenu>
508
- )}
509
- </li>
510
- )
511
- }