@pascal-app/editor 0.4.0

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 (165) hide show
  1. package/package.json +62 -0
  2. package/src/components/editor/custom-camera-controls.tsx +387 -0
  3. package/src/components/editor/editor-layout-v2.tsx +220 -0
  4. package/src/components/editor/export-manager.tsx +78 -0
  5. package/src/components/editor/first-person-controls.tsx +249 -0
  6. package/src/components/editor/floating-action-menu.tsx +231 -0
  7. package/src/components/editor/floorplan-panel.tsx +9609 -0
  8. package/src/components/editor/grid.tsx +161 -0
  9. package/src/components/editor/index.tsx +928 -0
  10. package/src/components/editor/node-action-menu.tsx +66 -0
  11. package/src/components/editor/preset-thumbnail-generator.tsx +125 -0
  12. package/src/components/editor/selection-manager.tsx +897 -0
  13. package/src/components/editor/site-edge-labels.tsx +90 -0
  14. package/src/components/editor/thumbnail-generator.tsx +166 -0
  15. package/src/components/editor/wall-measurement-label.tsx +258 -0
  16. package/src/components/feedback-dialog.tsx +265 -0
  17. package/src/components/pascal-radio.tsx +280 -0
  18. package/src/components/preview-button.tsx +16 -0
  19. package/src/components/systems/ceiling/ceiling-system.tsx +77 -0
  20. package/src/components/systems/roof/roof-edit-system.tsx +69 -0
  21. package/src/components/systems/stair/stair-edit-system.tsx +69 -0
  22. package/src/components/systems/zone/zone-label-editor-system.tsx +320 -0
  23. package/src/components/systems/zone/zone-system.tsx +87 -0
  24. package/src/components/tools/ceiling/ceiling-boundary-editor.tsx +42 -0
  25. package/src/components/tools/ceiling/ceiling-hole-editor.tsx +47 -0
  26. package/src/components/tools/ceiling/ceiling-tool.tsx +465 -0
  27. package/src/components/tools/door/door-math.ts +110 -0
  28. package/src/components/tools/door/door-tool.tsx +293 -0
  29. package/src/components/tools/door/move-door-tool.tsx +373 -0
  30. package/src/components/tools/item/item-tool.tsx +26 -0
  31. package/src/components/tools/item/move-tool.tsx +90 -0
  32. package/src/components/tools/item/placement-math.ts +85 -0
  33. package/src/components/tools/item/placement-strategies.ts +556 -0
  34. package/src/components/tools/item/placement-types.ts +117 -0
  35. package/src/components/tools/item/use-draft-node.ts +227 -0
  36. package/src/components/tools/item/use-placement-coordinator.tsx +877 -0
  37. package/src/components/tools/roof/move-roof-tool.tsx +288 -0
  38. package/src/components/tools/roof/roof-tool.tsx +318 -0
  39. package/src/components/tools/select/box-select-tool.tsx +626 -0
  40. package/src/components/tools/shared/cursor-sphere.tsx +119 -0
  41. package/src/components/tools/shared/polygon-editor.tsx +361 -0
  42. package/src/components/tools/site/site-boundary-editor.tsx +42 -0
  43. package/src/components/tools/slab/slab-boundary-editor.tsx +42 -0
  44. package/src/components/tools/slab/slab-hole-editor.tsx +47 -0
  45. package/src/components/tools/slab/slab-tool.tsx +322 -0
  46. package/src/components/tools/stair/stair-defaults.ts +7 -0
  47. package/src/components/tools/stair/stair-tool.tsx +194 -0
  48. package/src/components/tools/tool-manager.tsx +120 -0
  49. package/src/components/tools/wall/wall-drafting.ts +140 -0
  50. package/src/components/tools/wall/wall-tool.tsx +210 -0
  51. package/src/components/tools/window/move-window-tool.tsx +410 -0
  52. package/src/components/tools/window/window-math.ts +117 -0
  53. package/src/components/tools/window/window-tool.tsx +303 -0
  54. package/src/components/tools/zone/zone-boundary-editor.tsx +39 -0
  55. package/src/components/tools/zone/zone-tool.tsx +364 -0
  56. package/src/components/ui/action-menu/action-button.tsx +59 -0
  57. package/src/components/ui/action-menu/camera-actions.tsx +74 -0
  58. package/src/components/ui/action-menu/control-modes.tsx +240 -0
  59. package/src/components/ui/action-menu/furnish-tools.tsx +102 -0
  60. package/src/components/ui/action-menu/index.tsx +152 -0
  61. package/src/components/ui/action-menu/structure-tools.tsx +100 -0
  62. package/src/components/ui/action-menu/view-toggles.tsx +397 -0
  63. package/src/components/ui/command-palette/editor-commands.tsx +396 -0
  64. package/src/components/ui/command-palette/index.tsx +730 -0
  65. package/src/components/ui/controls/action-button.tsx +33 -0
  66. package/src/components/ui/controls/material-picker.tsx +194 -0
  67. package/src/components/ui/controls/metric-control.tsx +262 -0
  68. package/src/components/ui/controls/panel-section.tsx +65 -0
  69. package/src/components/ui/controls/segmented-control.tsx +45 -0
  70. package/src/components/ui/controls/slider-control.tsx +245 -0
  71. package/src/components/ui/controls/toggle-control.tsx +38 -0
  72. package/src/components/ui/floating-level-selector.tsx +355 -0
  73. package/src/components/ui/helpers/ceiling-helper.tsx +20 -0
  74. package/src/components/ui/helpers/helper-manager.tsx +33 -0
  75. package/src/components/ui/helpers/item-helper.tsx +40 -0
  76. package/src/components/ui/helpers/roof-helper.tsx +16 -0
  77. package/src/components/ui/helpers/slab-helper.tsx +20 -0
  78. package/src/components/ui/helpers/wall-helper.tsx +20 -0
  79. package/src/components/ui/item-catalog/catalog-items.tsx +1580 -0
  80. package/src/components/ui/item-catalog/item-catalog.tsx +219 -0
  81. package/src/components/ui/panels/ceiling-panel.tsx +230 -0
  82. package/src/components/ui/panels/collections/collections-popover.tsx +356 -0
  83. package/src/components/ui/panels/door-panel.tsx +600 -0
  84. package/src/components/ui/panels/item-panel.tsx +306 -0
  85. package/src/components/ui/panels/panel-manager.tsx +59 -0
  86. package/src/components/ui/panels/panel-wrapper.tsx +80 -0
  87. package/src/components/ui/panels/presets/presets-popover.tsx +511 -0
  88. package/src/components/ui/panels/reference-panel.tsx +177 -0
  89. package/src/components/ui/panels/roof-panel.tsx +262 -0
  90. package/src/components/ui/panels/roof-segment-panel.tsx +326 -0
  91. package/src/components/ui/panels/slab-panel.tsx +228 -0
  92. package/src/components/ui/panels/stair-panel.tsx +304 -0
  93. package/src/components/ui/panels/stair-segment-panel.tsx +339 -0
  94. package/src/components/ui/panels/wall-panel.tsx +123 -0
  95. package/src/components/ui/panels/window-panel.tsx +441 -0
  96. package/src/components/ui/primitives/button.tsx +69 -0
  97. package/src/components/ui/primitives/card.tsx +75 -0
  98. package/src/components/ui/primitives/color-dot.tsx +61 -0
  99. package/src/components/ui/primitives/context-menu.tsx +227 -0
  100. package/src/components/ui/primitives/dialog.tsx +129 -0
  101. package/src/components/ui/primitives/dropdown-menu.tsx +228 -0
  102. package/src/components/ui/primitives/error-boundary.tsx +52 -0
  103. package/src/components/ui/primitives/input.tsx +21 -0
  104. package/src/components/ui/primitives/number-input.tsx +187 -0
  105. package/src/components/ui/primitives/opacity-control.tsx +79 -0
  106. package/src/components/ui/primitives/popover.tsx +42 -0
  107. package/src/components/ui/primitives/separator.tsx +28 -0
  108. package/src/components/ui/primitives/sheet.tsx +130 -0
  109. package/src/components/ui/primitives/shortcut-token.tsx +64 -0
  110. package/src/components/ui/primitives/sidebar.tsx +855 -0
  111. package/src/components/ui/primitives/skeleton.tsx +13 -0
  112. package/src/components/ui/primitives/slider.tsx +58 -0
  113. package/src/components/ui/primitives/switch.tsx +29 -0
  114. package/src/components/ui/primitives/tooltip.tsx +57 -0
  115. package/src/components/ui/scene-loader.tsx +40 -0
  116. package/src/components/ui/sidebar/app-sidebar.tsx +103 -0
  117. package/src/components/ui/sidebar/icon-rail.tsx +147 -0
  118. package/src/components/ui/sidebar/panels/settings-panel/audio-settings-dialog.tsx +100 -0
  119. package/src/components/ui/sidebar/panels/settings-panel/index.tsx +438 -0
  120. package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +188 -0
  121. package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +80 -0
  122. package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +126 -0
  123. package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +64 -0
  124. package/src/components/ui/sidebar/panels/site-panel/index.tsx +1543 -0
  125. package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +98 -0
  126. package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +117 -0
  127. package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +65 -0
  128. package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +214 -0
  129. package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +96 -0
  130. package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +216 -0
  131. package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +115 -0
  132. package/src/components/ui/sidebar/panels/site-panel/tree-node-drag.tsx +342 -0
  133. package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +271 -0
  134. package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +106 -0
  135. package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +64 -0
  136. package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +87 -0
  137. package/src/components/ui/sidebar/panels/zone-panel/index.tsx +167 -0
  138. package/src/components/ui/sidebar/tab-bar.tsx +39 -0
  139. package/src/components/ui/slider-demo.tsx +36 -0
  140. package/src/components/ui/slider.tsx +81 -0
  141. package/src/components/ui/viewer-toolbar.tsx +342 -0
  142. package/src/components/viewer-overlay.tsx +499 -0
  143. package/src/components/viewer-zone-system.tsx +48 -0
  144. package/src/contexts/presets-context.tsx +121 -0
  145. package/src/hooks/use-auto-save.ts +194 -0
  146. package/src/hooks/use-contextual-tools.ts +52 -0
  147. package/src/hooks/use-grid-events.ts +106 -0
  148. package/src/hooks/use-keyboard.ts +214 -0
  149. package/src/hooks/use-mobile.ts +19 -0
  150. package/src/hooks/use-reduced-motion.ts +20 -0
  151. package/src/index.tsx +33 -0
  152. package/src/lib/constants.ts +3 -0
  153. package/src/lib/level-selection.ts +31 -0
  154. package/src/lib/scene.ts +394 -0
  155. package/src/lib/sfx/index.ts +2 -0
  156. package/src/lib/sfx-bus.ts +49 -0
  157. package/src/lib/sfx-player.ts +60 -0
  158. package/src/lib/utils.ts +43 -0
  159. package/src/store/use-audio.tsx +45 -0
  160. package/src/store/use-command-registry.ts +36 -0
  161. package/src/store/use-editor.tsx +522 -0
  162. package/src/store/use-palette-view-registry.ts +45 -0
  163. package/src/store/use-upload.ts +90 -0
  164. package/src/three-types.ts +3 -0
  165. package/tsconfig.json +9 -0
@@ -0,0 +1,161 @@
1
+ 'use client'
2
+
3
+ import { emitter, type GridEvent, sceneRegistry } from '@pascal-app/core'
4
+ import { useViewer } from '@pascal-app/viewer'
5
+ import { useFrame } from '@react-three/fiber'
6
+ import { useEffect, useMemo, useRef, useState } from 'react'
7
+ import { MathUtils, type Mesh, Vector2 } from 'three'
8
+ import { color, float, fract, fwidth, mix, positionLocal, uniform } from 'three/tsl'
9
+ import { MeshBasicNodeMaterial } from 'three/webgpu'
10
+ import { useGridEvents } from '../../hooks/use-grid-events'
11
+ import { EDITOR_LAYER } from '../../lib/constants'
12
+
13
+ export const Grid = ({
14
+ cellSize = 0.5,
15
+ cellThickness = 0.5,
16
+ cellColor = '#888888',
17
+ sectionSize = 1,
18
+ sectionThickness = 1,
19
+ sectionColor = '#000000',
20
+ fadeDistance = 100,
21
+ fadeStrength = 1,
22
+ revealRadius = 10,
23
+ }: {
24
+ cellSize?: number
25
+ cellThickness?: number
26
+ cellColor?: string
27
+ sectionSize?: number
28
+ sectionThickness?: number
29
+ sectionColor?: string
30
+ fadeDistance?: number
31
+ fadeStrength?: number
32
+ revealRadius?: number
33
+ }) => {
34
+ const theme = useViewer((state) => state.theme)
35
+
36
+ // Use slightly lighter colors for dark mode grid to make it apparent
37
+ const effectiveCellColor = theme === 'dark' ? '#555566' : cellColor
38
+ const effectiveSectionColor = theme === 'dark' ? '#666677' : sectionColor
39
+
40
+ const cursorPositionRef = useRef(new Vector2(0, 0))
41
+
42
+ const material = useMemo(() => {
43
+ // Use xy since plane geometry is in XY space (before rotation)
44
+ const pos = positionLocal.xy
45
+
46
+ // Cursor position uniform
47
+ const cursorPos = uniform(cursorPositionRef.current)
48
+
49
+ // Grid line function using fwidth for anti-aliasing
50
+ // Returns 1 on grid lines, 0 elsewhere
51
+ const getGrid = (size: number, thickness: number) => {
52
+ const r = pos.div(size)
53
+ const fw = fwidth(r)
54
+ // Distance to nearest grid line for each axis
55
+ const grid = fract(r.sub(0.5)).sub(0.5).abs()
56
+ // Anti-aliased step: divide by fwidth and clamp
57
+ const lineX = float(1).sub(
58
+ grid.x
59
+ .div(fw.x)
60
+ .add(1 - thickness)
61
+ .min(1),
62
+ )
63
+ const lineY = float(1).sub(
64
+ grid.y
65
+ .div(fw.y)
66
+ .add(1 - thickness)
67
+ .min(1),
68
+ )
69
+ // Combine both axes - max gives us lines in both directions
70
+ return lineX.max(lineY)
71
+ }
72
+
73
+ const g1 = getGrid(cellSize, cellThickness)
74
+ const g2 = getGrid(sectionSize, sectionThickness)
75
+
76
+ // Distance fade from center
77
+ const dist = pos.length()
78
+ const fade = float(1).sub(dist.div(fadeDistance).min(1)).pow(fadeStrength)
79
+
80
+ // Cursor reveal effect - distance from cursor
81
+ const cursorDist = pos.sub(cursorPos).length()
82
+ const cursorFade = float(1).sub(cursorDist.div(revealRadius).clamp(0, 1)).smoothstep(0, 1)
83
+
84
+ // Mix colors based on section grid
85
+ const gridColor = mix(
86
+ color(effectiveCellColor),
87
+ color(effectiveSectionColor),
88
+ float(sectionThickness).mul(g2).min(1),
89
+ )
90
+
91
+ // Baseline alpha: small amount of opacity everywhere the grid exists
92
+ const baseAlpha = float(0.4) // Subtle global visibility
93
+
94
+ // Combined alpha with cursor fade and baseline minimum
95
+ const alpha = g1.add(g2).mul(fade).mul(cursorFade.max(baseAlpha))
96
+ const finalAlpha = mix(alpha.mul(0.75), alpha, g2)
97
+
98
+ return new MeshBasicNodeMaterial({
99
+ transparent: true,
100
+ colorNode: gridColor,
101
+ opacityNode: finalAlpha,
102
+ depthWrite: false,
103
+ })
104
+ }, [
105
+ cellSize,
106
+ cellThickness,
107
+ effectiveCellColor,
108
+ sectionSize,
109
+ sectionThickness,
110
+ effectiveSectionColor,
111
+ fadeDistance,
112
+ fadeStrength,
113
+ revealRadius,
114
+ ])
115
+
116
+ const gridRef = useRef<Mesh>(null!)
117
+ const [gridY, setGridY] = useState(0)
118
+
119
+ // Use custom raycasting for grid events (independent of mesh events)
120
+ useGridEvents(gridY)
121
+
122
+ // Update cursor position from grid:move events
123
+ useEffect(() => {
124
+ const onGridMove = (event: GridEvent) => {
125
+ cursorPositionRef.current.set(event.position[0], -event.position[2])
126
+ }
127
+
128
+ emitter.on('grid:move', onGridMove)
129
+ return () => {
130
+ emitter.off('grid:move', onGridMove)
131
+ }
132
+ }, [])
133
+
134
+ useFrame((_, delta) => {
135
+ const currentLevelId = useViewer.getState().selection.levelId
136
+ let targetY = 0
137
+ if (currentLevelId) {
138
+ const levelMesh = sceneRegistry.nodes.get(currentLevelId)
139
+ if (levelMesh) {
140
+ targetY = levelMesh.position.y
141
+ }
142
+ }
143
+ const newY = MathUtils.lerp(gridRef.current.position.y, targetY, 12 * delta)
144
+ gridRef.current.position.y = newY
145
+ setGridY(newY)
146
+ })
147
+
148
+ const showGrid = useViewer((state) => state.showGrid)
149
+
150
+ return (
151
+ <mesh
152
+ layers={EDITOR_LAYER}
153
+ material={material}
154
+ ref={gridRef}
155
+ rotation-x={-Math.PI / 2}
156
+ visible={showGrid}
157
+ >
158
+ <planeGeometry args={[fadeDistance * 2, fadeDistance * 2]} />
159
+ </mesh>
160
+ )
161
+ }