@pascal-app/editor 0.5.1 → 0.7.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.
- package/package.json +12 -7
- package/src/components/editor/bottom-sheet.tsx +149 -0
- package/src/components/editor/custom-camera-controls.tsx +75 -7
- package/src/components/editor/editor-layout-mobile.tsx +264 -0
- package/src/components/editor/editor-layout-v2.tsx +29 -0
- package/src/components/editor/first-person/build-collider-world.ts +365 -0
- package/src/components/editor/first-person/bvh-ecctrl.tsx +795 -0
- package/src/components/editor/first-person-controls.tsx +496 -143
- package/src/components/editor/floating-action-menu.tsx +281 -83
- package/src/components/editor/floating-building-action-menu.tsx +4 -3
- package/src/components/editor/floorplan-background-selection.ts +113 -0
- package/src/components/editor/floorplan-panel.tsx +10442 -3275
- package/src/components/editor/index.tsx +270 -20
- package/src/components/editor/node-action-menu.tsx +14 -1
- package/src/components/editor/selection-manager.tsx +766 -12
- package/src/components/editor/site-edge-labels.tsx +9 -3
- package/src/components/editor/thumbnail-generator.tsx +350 -157
- package/src/components/editor/use-floorplan-background-placement.ts +257 -0
- package/src/components/editor/use-floorplan-hit-testing.ts +171 -0
- package/src/components/editor/use-floorplan-scene-data.ts +189 -0
- package/src/components/editor/wall-measurement-label.tsx +377 -58
- package/src/components/editor-2d/floorplan-action-menu-layer.tsx +95 -0
- package/src/components/editor-2d/floorplan-cursor-indicator-overlay.tsx +160 -0
- package/src/components/editor-2d/floorplan-hotkey-handlers.tsx +92 -0
- package/src/components/editor-2d/renderers/floorplan-draft-layer.tsx +119 -0
- package/src/components/editor-2d/renderers/floorplan-marquee-layer.tsx +58 -0
- package/src/components/editor-2d/renderers/floorplan-measurements-layer.tsx +197 -0
- package/src/components/editor-2d/renderers/floorplan-roof-layer.tsx +113 -0
- package/src/components/editor-2d/renderers/floorplan-stair-layer.tsx +474 -0
- package/src/components/editor-2d/svg-paths.ts +119 -0
- package/src/components/systems/ceiling/ceiling-selection-affordance-system.tsx +272 -0
- package/src/components/systems/roof/roof-edit-system.tsx +5 -5
- package/src/components/tools/ceiling/ceiling-boundary-editor.tsx +1 -0
- package/src/components/tools/ceiling/ceiling-hole-editor.tsx +2 -0
- package/src/components/tools/ceiling/ceiling-tool.tsx +5 -5
- package/src/components/tools/ceiling/move-ceiling-tool.tsx +257 -0
- package/src/components/tools/column/column-tool.tsx +97 -0
- package/src/components/tools/column/move-column-tool.tsx +105 -0
- package/src/components/tools/door/door-tool.tsx +19 -0
- package/src/components/tools/door/move-door-tool.tsx +38 -8
- package/src/components/tools/fence/curve-fence-tool.tsx +179 -0
- package/src/components/tools/fence/fence-drafting.ts +27 -8
- package/src/components/tools/fence/fence-tool.tsx +159 -3
- package/src/components/tools/fence/move-fence-endpoint-tool.tsx +438 -0
- package/src/components/tools/fence/move-fence-tool.tsx +102 -27
- package/src/components/tools/item/move-tool.tsx +19 -1
- package/src/components/tools/item/placement-math.ts +44 -7
- package/src/components/tools/item/placement-strategies.ts +111 -33
- package/src/components/tools/item/placement-types.ts +7 -0
- package/src/components/tools/item/use-draft-node.ts +2 -0
- package/src/components/tools/item/use-placement-coordinator.tsx +701 -61
- package/src/components/tools/roof/move-roof-tool.tsx +111 -43
- package/src/components/tools/shared/polygon-editor.tsx +244 -29
- package/src/components/tools/shared/segment-angle.ts +156 -0
- package/src/components/tools/slab/move-slab-tool.tsx +182 -0
- package/src/components/tools/slab/slab-boundary-editor.tsx +1 -0
- package/src/components/tools/slab/slab-hole-editor.tsx +2 -0
- package/src/components/tools/spawn/move-spawn-tool.tsx +101 -0
- package/src/components/tools/spawn/spawn-tool.tsx +130 -0
- package/src/components/tools/stair/stair-tool.tsx +11 -3
- package/src/components/tools/tool-manager.tsx +30 -3
- package/src/components/tools/wall/curve-wall-tool.tsx +176 -0
- package/src/components/tools/wall/move-wall-endpoint-tool.tsx +423 -0
- package/src/components/tools/wall/move-wall-tool.tsx +356 -0
- package/src/components/tools/wall/wall-drafting.ts +348 -17
- package/src/components/tools/wall/wall-tool.tsx +134 -2
- package/src/components/tools/window/move-window-tool.tsx +28 -0
- package/src/components/tools/window/window-tool.tsx +17 -0
- package/src/components/ui/action-menu/camera-actions.tsx +37 -33
- package/src/components/ui/action-menu/control-modes.tsx +37 -5
- package/src/components/ui/action-menu/index.tsx +91 -1
- package/src/components/ui/action-menu/structure-tools.tsx +2 -0
- package/src/components/ui/action-menu/view-toggles.tsx +424 -35
- package/src/components/ui/command-palette/editor-commands.tsx +27 -5
- package/src/components/ui/command-palette/index.tsx +0 -1
- package/src/components/ui/controls/material-picker.tsx +189 -169
- package/src/components/ui/controls/slider-control.tsx +88 -26
- package/src/components/ui/floating-level-selector.tsx +286 -55
- package/src/components/ui/helpers/helper-manager.tsx +5 -0
- package/src/components/ui/item-catalog/catalog-items.tsx +1121 -1219
- package/src/components/ui/item-catalog/item-catalog.tsx +42 -175
- package/src/components/ui/level-duplicate-dialog.tsx +115 -0
- package/src/components/ui/panels/ceiling-panel.tsx +47 -27
- package/src/components/ui/panels/column-panel.tsx +715 -0
- package/src/components/ui/panels/door-panel.tsx +986 -294
- package/src/components/ui/panels/fence-panel.tsx +55 -12
- package/src/components/ui/panels/item-panel.tsx +5 -5
- package/src/components/ui/panels/mobile-panel-sheet.tsx +108 -0
- package/src/components/ui/panels/mobile-selection-bar.tsx +100 -0
- package/src/components/ui/panels/node-display.ts +39 -0
- package/src/components/ui/panels/paint-panel.tsx +138 -0
- package/src/components/ui/panels/panel-manager.tsx +241 -30
- package/src/components/ui/panels/panel-wrapper.tsx +48 -39
- package/src/components/ui/panels/reference-panel.tsx +243 -9
- package/src/components/ui/panels/roof-panel.tsx +30 -62
- package/src/components/ui/panels/roof-segment-panel.tsx +8 -23
- package/src/components/ui/panels/slab-panel.tsx +46 -24
- package/src/components/ui/panels/spawn-panel.tsx +155 -0
- package/src/components/ui/panels/stair-panel.tsx +117 -69
- package/src/components/ui/panels/stair-segment-panel.tsx +13 -27
- package/src/components/ui/panels/wall-panel.tsx +71 -17
- package/src/components/ui/panels/window-panel.tsx +665 -146
- package/src/components/ui/sidebar/mobile-tab-bar.tsx +46 -0
- package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +2 -2
- package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +9 -5
- package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +7 -3
- package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +77 -0
- package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +7 -3
- package/src/components/ui/sidebar/panels/site-panel/fence-tree-node.tsx +7 -3
- package/src/components/ui/sidebar/panels/site-panel/index.tsx +138 -56
- package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +7 -3
- package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +9 -5
- package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +7 -3
- package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +7 -3
- package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +82 -0
- package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +7 -3
- package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +3 -3
- package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +12 -6
- package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +7 -3
- package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +7 -3
- package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +15 -8
- package/src/components/ui/sidebar/tab-bar.tsx +3 -0
- package/src/components/ui/viewer-toolbar.tsx +96 -2
- package/src/components/viewer-overlay.tsx +25 -19
- package/src/hooks/use-auto-frame.ts +45 -0
- package/src/hooks/use-contextual-tools.ts +14 -13
- package/src/hooks/use-keyboard.ts +67 -9
- package/src/hooks/use-mobile.ts +12 -12
- package/src/index.tsx +2 -1
- package/src/lib/door-interaction.ts +88 -0
- package/src/lib/floorplan/geometry.ts +263 -0
- package/src/lib/floorplan/index.ts +38 -0
- package/src/lib/floorplan/items.ts +179 -0
- package/src/lib/floorplan/selection-tool.ts +231 -0
- package/src/lib/floorplan/stairs.ts +478 -0
- package/src/lib/floorplan/types.ts +57 -0
- package/src/lib/floorplan/walls.ts +23 -0
- package/src/lib/guide-events.ts +10 -0
- package/src/lib/history.ts +20 -0
- package/src/lib/level-duplication.test.ts +72 -0
- package/src/lib/level-duplication.ts +153 -0
- package/src/lib/local-guide-image.ts +42 -0
- package/src/lib/material-paint.ts +284 -0
- package/src/lib/roof-duplication.ts +214 -0
- package/src/lib/scene-bounds.test.ts +183 -0
- package/src/lib/scene-bounds.ts +169 -0
- package/src/lib/sfx-player.ts +96 -13
- package/src/lib/stair-duplication.ts +126 -0
- package/src/lib/window-interaction.ts +86 -0
- package/src/store/use-editor.tsx +279 -15
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { cn } from './../../../lib/utils'
|
|
4
|
+
import type { SidebarTab } from './tab-bar'
|
|
5
|
+
|
|
6
|
+
interface MobileTabBarProps {
|
|
7
|
+
tabs: SidebarTab[]
|
|
8
|
+
activeTab: string
|
|
9
|
+
onTabPress: (id: string) => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function MobileTabBar({ tabs, activeTab, onTabPress }: MobileTabBarProps) {
|
|
13
|
+
return (
|
|
14
|
+
<div
|
|
15
|
+
className="z-50 flex h-14 shrink-0 border-border/50 border-t bg-sidebar text-sidebar-foreground"
|
|
16
|
+
style={{
|
|
17
|
+
// Cap the safe-area inset — iOS Chrome can report its bottom UI bar
|
|
18
|
+
// (50–100px) as part of the safe area which would balloon the tab bar.
|
|
19
|
+
// 34px matches the iPhone home-indicator height (the typical max).
|
|
20
|
+
paddingBottom: 'min(env(safe-area-inset-bottom, 0px), 34px)',
|
|
21
|
+
}}
|
|
22
|
+
>
|
|
23
|
+
{tabs.map((tab) => {
|
|
24
|
+
const isActive = activeTab === tab.id
|
|
25
|
+
return (
|
|
26
|
+
<button
|
|
27
|
+
className={cn(
|
|
28
|
+
'flex flex-1 flex-col items-center justify-center gap-0.5 text-xs transition-colors',
|
|
29
|
+
isActive ? 'text-foreground' : 'text-muted-foreground',
|
|
30
|
+
)}
|
|
31
|
+
key={tab.id}
|
|
32
|
+
onClick={() => onTabPress(tab.id)}
|
|
33
|
+
type="button"
|
|
34
|
+
>
|
|
35
|
+
{tab.mobileIcon ? (
|
|
36
|
+
<span className={cn('flex h-5 w-5 items-center justify-center')}>
|
|
37
|
+
{tab.mobileIcon}
|
|
38
|
+
</span>
|
|
39
|
+
) : null}
|
|
40
|
+
<span className="font-medium">{tab.label}</span>
|
|
41
|
+
</button>
|
|
42
|
+
)
|
|
43
|
+
})}
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
@@ -88,8 +88,8 @@ const SHORTCUT_CATEGORIES: ShortcutCategory[] = [
|
|
|
88
88
|
{
|
|
89
89
|
title: 'Item Placement',
|
|
90
90
|
shortcuts: [
|
|
91
|
-
{ keys: ['R'], action: 'Rotate item clockwise
|
|
92
|
-
{ keys: ['T'], action: 'Rotate item counter-clockwise
|
|
91
|
+
{ keys: ['R'], action: 'Rotate item clockwise, or toggle selected door open/closed' },
|
|
92
|
+
{ keys: ['T'], action: 'Rotate item counter-clockwise, or close selected door' },
|
|
93
93
|
{
|
|
94
94
|
keys: ['Shift'],
|
|
95
95
|
action: 'Temporarily bypass placement validation constraints',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type BuildingNode, LevelNode, useScene } from '@pascal-app/core'
|
|
2
2
|
import { useViewer } from '@pascal-app/viewer'
|
|
3
3
|
import { Building2, Plus } from 'lucide-react'
|
|
4
|
-
import { useState } from 'react'
|
|
4
|
+
import { memo, useState } from 'react'
|
|
5
5
|
import { useShallow } from 'zustand/react/shallow'
|
|
6
6
|
import {
|
|
7
7
|
Tooltip,
|
|
@@ -12,12 +12,16 @@ import { focusTreeNode, TreeNode, TreeNodeWrapper } from './tree-node'
|
|
|
12
12
|
import { TreeNodeActions } from './tree-node-actions'
|
|
13
13
|
|
|
14
14
|
interface BuildingTreeNodeProps {
|
|
15
|
-
nodeId:
|
|
15
|
+
nodeId: BuildingNode['id']
|
|
16
16
|
depth: number
|
|
17
17
|
isLast?: boolean
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export
|
|
20
|
+
export const BuildingTreeNode = memo(function BuildingTreeNode({
|
|
21
|
+
nodeId,
|
|
22
|
+
depth,
|
|
23
|
+
isLast,
|
|
24
|
+
}: BuildingTreeNodeProps) {
|
|
21
25
|
const [expanded, setExpanded] = useState(true)
|
|
22
26
|
const createNode = useScene((state) => state.createNode)
|
|
23
27
|
const isVisible = useScene((s) => s.nodes[nodeId]?.visible !== false)
|
|
@@ -84,4 +88,4 @@ export function BuildingTreeNode({ nodeId, depth, isLast }: BuildingTreeNodeProp
|
|
|
84
88
|
))}
|
|
85
89
|
</TreeNodeWrapper>
|
|
86
90
|
)
|
|
87
|
-
}
|
|
91
|
+
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AnyNodeId, type CeilingNode, useScene } from '@pascal-app/core'
|
|
2
2
|
import { useViewer } from '@pascal-app/viewer'
|
|
3
3
|
import Image from 'next/image'
|
|
4
|
-
import { useCallback, useEffect, useState } from 'react'
|
|
4
|
+
import { memo, useCallback, useEffect, useState } from 'react'
|
|
5
5
|
import { useShallow } from 'zustand/react/shallow'
|
|
6
6
|
import useEditor from './../../../../../store/use-editor'
|
|
7
7
|
import { InlineRenameInput } from './inline-rename-input'
|
|
@@ -14,7 +14,11 @@ interface CeilingTreeNodeProps {
|
|
|
14
14
|
isLast?: boolean
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export
|
|
17
|
+
export const CeilingTreeNode = memo(function CeilingTreeNode({
|
|
18
|
+
nodeId,
|
|
19
|
+
depth,
|
|
20
|
+
isLast,
|
|
21
|
+
}: CeilingTreeNodeProps) {
|
|
18
22
|
const [expanded, setExpanded] = useState(false)
|
|
19
23
|
const [isEditing, setIsEditing] = useState(false)
|
|
20
24
|
const isVisible = useScene((s) => s.nodes[nodeId as AnyNodeId]?.visible !== false)
|
|
@@ -113,7 +117,7 @@ export function CeilingTreeNode({ nodeId, depth, isLast }: CeilingTreeNodeProps)
|
|
|
113
117
|
))}
|
|
114
118
|
</TreeNodeWrapper>
|
|
115
119
|
)
|
|
116
|
-
}
|
|
120
|
+
})
|
|
117
121
|
|
|
118
122
|
/**
|
|
119
123
|
* Calculate the area of a polygon using the shoelace formula
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type AnyNodeId, type ColumnNode, useScene } from '@pascal-app/core'
|
|
2
|
+
import { useViewer } from '@pascal-app/viewer'
|
|
3
|
+
import Image from 'next/image'
|
|
4
|
+
import { memo, useCallback, useState } from 'react'
|
|
5
|
+
import useEditor from './../../../../../store/use-editor'
|
|
6
|
+
import { InlineRenameInput } from './inline-rename-input'
|
|
7
|
+
import { focusTreeNode, handleTreeSelection, TreeNodeWrapper } from './tree-node'
|
|
8
|
+
import { TreeNodeActions } from './tree-node-actions'
|
|
9
|
+
|
|
10
|
+
interface ColumnTreeNodeProps {
|
|
11
|
+
nodeId: AnyNodeId
|
|
12
|
+
depth: number
|
|
13
|
+
isLast?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const ColumnTreeNode = memo(function ColumnTreeNode({
|
|
17
|
+
nodeId,
|
|
18
|
+
depth,
|
|
19
|
+
isLast,
|
|
20
|
+
}: ColumnTreeNodeProps) {
|
|
21
|
+
const [isEditing, setIsEditing] = useState(false)
|
|
22
|
+
const isVisible = useScene((s) => s.nodes[nodeId]?.visible !== false)
|
|
23
|
+
const node = useScene((s) => s.nodes[nodeId] as ColumnNode | undefined)
|
|
24
|
+
const isSelected = useViewer((state) => state.selection.selectedIds.includes(nodeId))
|
|
25
|
+
const isHovered = useViewer((state) => state.hoveredId === nodeId)
|
|
26
|
+
const setSelection = useViewer((state) => state.setSelection)
|
|
27
|
+
const setHoveredId = useViewer((state) => state.setHoveredId)
|
|
28
|
+
|
|
29
|
+
const handleClick = useCallback(
|
|
30
|
+
(e: React.MouseEvent) => {
|
|
31
|
+
e.stopPropagation()
|
|
32
|
+
const handled = handleTreeSelection(
|
|
33
|
+
e,
|
|
34
|
+
nodeId,
|
|
35
|
+
useViewer.getState().selection.selectedIds,
|
|
36
|
+
setSelection,
|
|
37
|
+
)
|
|
38
|
+
if (!handled && useEditor.getState().phase === 'furnish') {
|
|
39
|
+
useEditor.getState().setPhase('structure')
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
[nodeId, setSelection],
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
const defaultName = node?.name || 'Column'
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<TreeNodeWrapper
|
|
49
|
+
actions={<TreeNodeActions nodeId={nodeId} />}
|
|
50
|
+
depth={depth}
|
|
51
|
+
expanded={false}
|
|
52
|
+
hasChildren={false}
|
|
53
|
+
icon={
|
|
54
|
+
<Image alt="" className="object-contain" height={14} src="/icons/column.png" width={14} />
|
|
55
|
+
}
|
|
56
|
+
isHovered={isHovered}
|
|
57
|
+
isLast={isLast}
|
|
58
|
+
isSelected={isSelected}
|
|
59
|
+
isVisible={isVisible}
|
|
60
|
+
label={
|
|
61
|
+
<InlineRenameInput
|
|
62
|
+
defaultName={defaultName}
|
|
63
|
+
isEditing={isEditing}
|
|
64
|
+
nodeId={nodeId}
|
|
65
|
+
onStartEditing={() => setIsEditing(true)}
|
|
66
|
+
onStopEditing={() => setIsEditing(false)}
|
|
67
|
+
/>
|
|
68
|
+
}
|
|
69
|
+
nodeId={nodeId}
|
|
70
|
+
onClick={handleClick}
|
|
71
|
+
onDoubleClick={() => focusTreeNode(nodeId)}
|
|
72
|
+
onMouseEnter={() => setHoveredId(nodeId)}
|
|
73
|
+
onMouseLeave={() => setHoveredId(null)}
|
|
74
|
+
onToggle={() => {}}
|
|
75
|
+
/>
|
|
76
|
+
)
|
|
77
|
+
})
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { type AnyNodeId, useScene } from '@pascal-app/core'
|
|
4
4
|
import { useViewer } from '@pascal-app/viewer'
|
|
5
5
|
import Image from 'next/image'
|
|
6
|
-
import { useCallback, useState } from 'react'
|
|
6
|
+
import { memo, useCallback, useState } from 'react'
|
|
7
7
|
import useEditor from './../../../../../store/use-editor'
|
|
8
8
|
import { InlineRenameInput } from './inline-rename-input'
|
|
9
9
|
import { focusTreeNode, handleTreeSelection, TreeNodeWrapper } from './tree-node'
|
|
@@ -15,7 +15,11 @@ interface DoorTreeNodeProps {
|
|
|
15
15
|
isLast?: boolean
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export
|
|
18
|
+
export const DoorTreeNode = memo(function DoorTreeNode({
|
|
19
|
+
nodeId,
|
|
20
|
+
depth,
|
|
21
|
+
isLast,
|
|
22
|
+
}: DoorTreeNodeProps) {
|
|
19
23
|
const [isEditing, setIsEditing] = useState(false)
|
|
20
24
|
const isVisible = useScene((s) => s.nodes[nodeId as AnyNodeId]?.visible !== false)
|
|
21
25
|
const isSelected = useViewer((state) => state.selection.selectedIds.includes(nodeId))
|
|
@@ -72,4 +76,4 @@ export function DoorTreeNode({ nodeId, depth, isLast }: DoorTreeNodeProps) {
|
|
|
72
76
|
onToggle={() => {}}
|
|
73
77
|
/>
|
|
74
78
|
)
|
|
75
|
-
}
|
|
79
|
+
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AnyNodeId, type FenceNode, useScene } from '@pascal-app/core'
|
|
2
2
|
import { useViewer } from '@pascal-app/viewer'
|
|
3
3
|
import Image from 'next/image'
|
|
4
|
-
import { useState } from 'react'
|
|
4
|
+
import { memo, useState } from 'react'
|
|
5
5
|
import useEditor from '../../../../../store/use-editor'
|
|
6
6
|
import { InlineRenameInput } from './inline-rename-input'
|
|
7
7
|
import { focusTreeNode, handleTreeSelection, TreeNodeWrapper } from './tree-node'
|
|
@@ -13,7 +13,11 @@ interface FenceTreeNodeProps {
|
|
|
13
13
|
isLast?: boolean
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export
|
|
16
|
+
export const FenceTreeNode = memo(function FenceTreeNode({
|
|
17
|
+
nodeId,
|
|
18
|
+
depth,
|
|
19
|
+
isLast,
|
|
20
|
+
}: FenceTreeNodeProps) {
|
|
17
21
|
const node = useScene((state) => state.nodes[nodeId]) as FenceNode | undefined
|
|
18
22
|
const [isEditing, setIsEditing] = useState(false)
|
|
19
23
|
const selectedIds = useViewer((state) => state.selection.selectedIds)
|
|
@@ -62,4 +66,4 @@ export function FenceTreeNode({ nodeId, depth, isLast }: FenceTreeNodeProps) {
|
|
|
62
66
|
onToggle={() => {}}
|
|
63
67
|
/>
|
|
64
68
|
)
|
|
65
|
-
}
|
|
69
|
+
})
|