@jkwd/inbase 0.1.1 → 0.1.3
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/apps/explorer/src/index.css +60 -8
- package/apps/explorer/src/scene/FileBlock.tsx +1 -1
- package/apps/explorer/src/scene/FolderArea.tsx +5 -2
- package/apps/explorer/src/scene/MapView.tsx +36 -29
- package/apps/explorer/src/scene/World.tsx +14 -5
- package/apps/explorer/src/ui/HUD.tsx +107 -77
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ body,
|
|
|
21
21
|
.stage {
|
|
22
22
|
position: absolute;
|
|
23
23
|
inset: 0;
|
|
24
|
+
z-index: 0;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
* {
|
|
@@ -35,7 +36,7 @@ button {
|
|
|
35
36
|
position: fixed;
|
|
36
37
|
inset: 0;
|
|
37
38
|
pointer-events: none;
|
|
38
|
-
z-index:
|
|
39
|
+
z-index: 10;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
.hud-top,
|
|
@@ -243,6 +244,7 @@ button {
|
|
|
243
244
|
left: 0;
|
|
244
245
|
right: 0;
|
|
245
246
|
bottom: 0;
|
|
247
|
+
z-index: 3;
|
|
246
248
|
display: flex;
|
|
247
249
|
align-items: center;
|
|
248
250
|
justify-content: space-between;
|
|
@@ -306,11 +308,15 @@ button {
|
|
|
306
308
|
position: absolute;
|
|
307
309
|
top: 68px;
|
|
308
310
|
right: 20px;
|
|
311
|
+
z-index: 4;
|
|
309
312
|
width: min(320px, calc(100% - 40px));
|
|
310
|
-
|
|
311
|
-
|
|
313
|
+
height: auto;
|
|
314
|
+
max-height: calc(100dvh - 168px);
|
|
315
|
+
overflow-x: hidden;
|
|
316
|
+
overflow-y: auto;
|
|
312
317
|
overscroll-behavior: contain;
|
|
313
|
-
padding: 16px;
|
|
318
|
+
padding: 16px 16px 20px;
|
|
319
|
+
background: var(--vc-chrome);
|
|
314
320
|
}
|
|
315
321
|
|
|
316
322
|
.hud-panel-info {
|
|
@@ -352,18 +358,31 @@ button {
|
|
|
352
358
|
|
|
353
359
|
.hud-steps {
|
|
354
360
|
margin: 10px 0 0;
|
|
355
|
-
padding
|
|
361
|
+
padding: 0;
|
|
362
|
+
list-style: none;
|
|
356
363
|
color: #8b95a5;
|
|
357
364
|
}
|
|
358
365
|
|
|
359
366
|
.hud-steps li {
|
|
360
|
-
|
|
367
|
+
display: grid;
|
|
368
|
+
grid-template-columns: 1.6em minmax(0, 1fr);
|
|
369
|
+
align-items: start;
|
|
370
|
+
justify-content: start;
|
|
371
|
+
gap: 8px;
|
|
372
|
+
margin: 0 0 8px;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.hud-step-index {
|
|
376
|
+
font-variant-numeric: tabular-nums;
|
|
377
|
+
line-height: 1.4;
|
|
361
378
|
}
|
|
362
379
|
|
|
363
380
|
.hud-step-main {
|
|
364
|
-
display:
|
|
381
|
+
display: flex;
|
|
382
|
+
flex-wrap: wrap;
|
|
365
383
|
align-items: baseline;
|
|
366
384
|
gap: 8px;
|
|
385
|
+
min-width: 0;
|
|
367
386
|
}
|
|
368
387
|
|
|
369
388
|
.hud-steps li[data-next='true'] {
|
|
@@ -488,6 +507,39 @@ button {
|
|
|
488
507
|
opacity: 0.35;
|
|
489
508
|
}
|
|
490
509
|
|
|
510
|
+
.hud-fold {
|
|
511
|
+
margin-top: 12px;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
.hud-fold-summary {
|
|
515
|
+
cursor: pointer;
|
|
516
|
+
list-style: none;
|
|
517
|
+
display: flex;
|
|
518
|
+
align-items: center;
|
|
519
|
+
gap: 8px;
|
|
520
|
+
user-select: none;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.hud-fold-summary::-webkit-details-marker,
|
|
524
|
+
.hud-fold-summary::marker {
|
|
525
|
+
display: none;
|
|
526
|
+
content: '';
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.hud-fold-summary::before {
|
|
530
|
+
content: '';
|
|
531
|
+
width: 0;
|
|
532
|
+
height: 0;
|
|
533
|
+
border-top: 4px solid transparent;
|
|
534
|
+
border-bottom: 4px solid transparent;
|
|
535
|
+
border-left: 6px solid currentColor;
|
|
536
|
+
transition: transform 0.12s ease;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.hud-fold[open] > .hud-fold-summary::before {
|
|
540
|
+
transform: rotate(90deg);
|
|
541
|
+
}
|
|
542
|
+
|
|
491
543
|
.hud-button-approve {
|
|
492
544
|
border-color: #9ad8ff;
|
|
493
545
|
color: #d7eef8;
|
|
@@ -519,7 +571,7 @@ button {
|
|
|
519
571
|
padding-left: 18px;
|
|
520
572
|
}
|
|
521
573
|
|
|
522
|
-
.hud-panel li {
|
|
574
|
+
.hud-panel ul li {
|
|
523
575
|
margin: 0 0 4px;
|
|
524
576
|
display: flex;
|
|
525
577
|
align-items: center;
|
|
@@ -95,7 +95,7 @@ export function FileBlock({
|
|
|
95
95
|
onCancelName,
|
|
96
96
|
}: FileBlockProps) {
|
|
97
97
|
const [width, height, depth] = placed.size
|
|
98
|
-
const highlight = changeKind ? CHANGE_HIGHLIGHT[changeKind] : null
|
|
98
|
+
const highlight = changeKind && mapMode ? CHANGE_HIGHLIGHT[changeKind] : null
|
|
99
99
|
const color = added || file.userCreated ? '#7ec8e8' : fileColor(file.language)
|
|
100
100
|
const muted = dimColor(color, 0.32)
|
|
101
101
|
const walkSelected = selected && !mapMode
|
|
@@ -8,6 +8,7 @@ type FolderAreaProps = {
|
|
|
8
8
|
folder: PlacedFolder
|
|
9
9
|
naming?: boolean
|
|
10
10
|
selected?: boolean
|
|
11
|
+
mapMode?: boolean
|
|
11
12
|
highlightKind?: ChangeKind | null
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -15,10 +16,12 @@ export function FolderArea({
|
|
|
15
16
|
folder,
|
|
16
17
|
naming = false,
|
|
17
18
|
selected = false,
|
|
19
|
+
mapMode = false,
|
|
18
20
|
highlightKind = null,
|
|
19
21
|
}: FolderAreaProps) {
|
|
20
22
|
const added = Boolean(folder.added)
|
|
21
|
-
const highlight =
|
|
23
|
+
const highlight =
|
|
24
|
+
mapMode && highlightKind ? CHANGE_HIGHLIGHT[highlightKind] : null
|
|
22
25
|
const addedOnly = added && !highlight
|
|
23
26
|
const outline = highlight ? highlight.color : addedOnly ? '#7ec8e8' : null
|
|
24
27
|
const color = highlight
|
|
@@ -48,7 +51,7 @@ export function FolderArea({
|
|
|
48
51
|
<planeGeometry args={[folder.width, folder.depth]} />
|
|
49
52
|
<meshBasicMaterial color={color} />
|
|
50
53
|
</mesh>
|
|
51
|
-
{selected && (
|
|
54
|
+
{selected && mapMode && (
|
|
52
55
|
<MapSelectBorder
|
|
53
56
|
width={folder.width}
|
|
54
57
|
depth={folder.depth}
|
|
@@ -34,25 +34,32 @@ export function MapView({
|
|
|
34
34
|
const bounds = useMemo(() => worldBounds(layout), [layout])
|
|
35
35
|
const drag = useRef({ x: 0, y: 0, moved: false, active: false })
|
|
36
36
|
const sized = size.width > 16 && size.height > 16
|
|
37
|
+
const hudReserve = 88
|
|
38
|
+
const topReserve = 28
|
|
39
|
+
const viewWidth = Math.max(size.width, 1)
|
|
40
|
+
const viewHeight = Math.max(size.height - hudReserve - topReserve, 1)
|
|
37
41
|
|
|
38
42
|
const fitZoom = sized
|
|
39
43
|
? Math.min(
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
viewWidth / Math.max(bounds.width + 36, 1),
|
|
45
|
+
viewHeight / Math.max(bounds.depth + 36, 1),
|
|
42
46
|
)
|
|
43
47
|
: 8
|
|
44
|
-
const zoom = Math.max(fitZoom * 0.92,
|
|
48
|
+
const zoom = Math.max(fitZoom * 0.92, 0.08)
|
|
49
|
+
// Ortho up is -Z, so +Z is down the screen. Shift the view so the map sits
|
|
50
|
+
// above the bottom HUD instead of centering under it.
|
|
51
|
+
const cz = bounds.cz + hudReserve / 2 / zoom
|
|
45
52
|
|
|
46
53
|
useLayoutEffect(() => {
|
|
47
54
|
if (!enabled || !(camera instanceof THREE.OrthographicCamera)) return
|
|
48
55
|
camera.up.set(0, 0, -1)
|
|
49
|
-
camera.position.set(bounds.cx, 120,
|
|
50
|
-
camera.lookAt(bounds.cx, 0,
|
|
56
|
+
camera.position.set(bounds.cx, 120, cz)
|
|
57
|
+
camera.lookAt(bounds.cx, 0, cz)
|
|
51
58
|
camera.near = 1
|
|
52
59
|
camera.far = 2000
|
|
53
60
|
camera.zoom = zoom
|
|
54
61
|
camera.updateProjectionMatrix()
|
|
55
|
-
}, [bounds.cx,
|
|
62
|
+
}, [bounds.cx, camera, cz, enabled, zoom])
|
|
56
63
|
|
|
57
64
|
useEffect(() => {
|
|
58
65
|
if (!enabled) return
|
|
@@ -86,12 +93,31 @@ export function MapView({
|
|
|
86
93
|
return { raycaster, relationHit, fileHit }
|
|
87
94
|
}
|
|
88
95
|
|
|
96
|
+
const landAtPointer = (clientX: number, clientY: number) => {
|
|
97
|
+
const pick = pickAt(clientX, clientY)
|
|
98
|
+
if (!pick) return false
|
|
99
|
+
const { raycaster, relationHit, fileHit } = pick
|
|
100
|
+
if (relationHit || fileHit) return false
|
|
101
|
+
|
|
102
|
+
const hit = new THREE.Vector3()
|
|
103
|
+
const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)
|
|
104
|
+
if (!raycaster.ray.intersectPlane(plane, hit)) return false
|
|
105
|
+
const lock = element.requestPointerLock()
|
|
106
|
+
if (lock && typeof lock.catch === 'function') {
|
|
107
|
+
void lock.catch(() => {})
|
|
108
|
+
}
|
|
109
|
+
onLand(hit.x, hit.z)
|
|
110
|
+
return true
|
|
111
|
+
}
|
|
112
|
+
|
|
89
113
|
const onUp = (event: PointerEvent) => {
|
|
90
114
|
element.style.cursor = 'grab'
|
|
91
115
|
const startedOnCanvas = drag.current.active
|
|
92
116
|
drag.current.active = false
|
|
93
117
|
if (!startedOnCanvas || event.button !== 0 || drag.current.moved) return
|
|
94
118
|
|
|
119
|
+
if (event.shiftKey && landAtPointer(event.clientX, event.clientY)) return
|
|
120
|
+
|
|
95
121
|
const pick = pickAt(event.clientX, event.clientY)
|
|
96
122
|
if (!pick) return
|
|
97
123
|
const { relationHit, fileHit } = pick
|
|
@@ -123,34 +149,14 @@ export function MapView({
|
|
|
123
149
|
onSelectFolder(null)
|
|
124
150
|
}
|
|
125
151
|
|
|
126
|
-
const onDblClick = (event: MouseEvent) => {
|
|
127
|
-
if (event.button !== 0 || drag.current.moved) return
|
|
128
|
-
const pick = pickAt(event.clientX, event.clientY)
|
|
129
|
-
if (!pick) return
|
|
130
|
-
const { raycaster, relationHit, fileHit } = pick
|
|
131
|
-
if (relationHit || fileHit) return
|
|
132
|
-
|
|
133
|
-
const hit = new THREE.Vector3()
|
|
134
|
-
const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)
|
|
135
|
-
if (raycaster.ray.intersectPlane(plane, hit)) {
|
|
136
|
-
const lock = element.requestPointerLock()
|
|
137
|
-
if (lock && typeof lock.catch === 'function') {
|
|
138
|
-
void lock.catch(() => {})
|
|
139
|
-
}
|
|
140
|
-
onLand(hit.x, hit.z)
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
152
|
element.addEventListener('pointerdown', onDown)
|
|
145
153
|
window.addEventListener('pointermove', onMove)
|
|
146
154
|
window.addEventListener('pointerup', onUp)
|
|
147
|
-
element.addEventListener('dblclick', onDblClick)
|
|
148
155
|
return () => {
|
|
149
156
|
element.style.cursor = ''
|
|
150
157
|
element.removeEventListener('pointerdown', onDown)
|
|
151
158
|
window.removeEventListener('pointermove', onMove)
|
|
152
159
|
window.removeEventListener('pointerup', onUp)
|
|
153
|
-
element.removeEventListener('dblclick', onDblClick)
|
|
154
160
|
}
|
|
155
161
|
}, [
|
|
156
162
|
camera,
|
|
@@ -169,7 +175,7 @@ export function MapView({
|
|
|
169
175
|
{enabled && (
|
|
170
176
|
<OrthographicCamera
|
|
171
177
|
makeDefault
|
|
172
|
-
position={[bounds.cx, 120,
|
|
178
|
+
position={[bounds.cx, 120, cz]}
|
|
173
179
|
zoom={zoom}
|
|
174
180
|
near={1}
|
|
175
181
|
far={2000}
|
|
@@ -183,9 +189,9 @@ export function MapView({
|
|
|
183
189
|
dampingFactor={0.12}
|
|
184
190
|
screenSpacePanning
|
|
185
191
|
zoomSpeed={1.15}
|
|
186
|
-
minZoom={Math.max(fitZoom * 0.
|
|
192
|
+
minZoom={Math.max(fitZoom * 0.35, 0.05)}
|
|
187
193
|
maxZoom={Math.max(fitZoom * 10, 20)}
|
|
188
|
-
target={[bounds.cx, 0,
|
|
194
|
+
target={[bounds.cx, 0, cz]}
|
|
189
195
|
/>
|
|
190
196
|
)}
|
|
191
197
|
{enabled &&
|
|
@@ -194,6 +200,7 @@ export function MapView({
|
|
|
194
200
|
key={folder.path}
|
|
195
201
|
position={[folder.x, 14, folder.z + 1.35]}
|
|
196
202
|
center
|
|
203
|
+
zIndexRange={[1, 0]}
|
|
197
204
|
style={{ pointerEvents: 'none' }}
|
|
198
205
|
>
|
|
199
206
|
<div
|
|
@@ -8,7 +8,7 @@ import { SelectionController } from './SelectionController'
|
|
|
8
8
|
import { UserContextTracker } from './UserContextTracker'
|
|
9
9
|
import { BlockPlacer } from './BlockPlacer'
|
|
10
10
|
import { IslandPlacer } from './IslandPlacer'
|
|
11
|
-
import { folderOfFile, filesImporting } from '../layout'
|
|
11
|
+
import { folderOfFile, filesImporting, worldBounds } from '../layout'
|
|
12
12
|
import { EDITOR_GREY } from '../theme'
|
|
13
13
|
import type { ChangeKind } from '../theme'
|
|
14
14
|
import type {
|
|
@@ -159,18 +159,26 @@ export function World({
|
|
|
159
159
|
return null
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
const bounds = worldBounds(layout)
|
|
163
|
+
const groundPad = 120
|
|
164
|
+
const groundWidth = Math.max(bounds.width + groundPad * 2, 400)
|
|
165
|
+
const groundDepth = Math.max(bounds.depth + groundPad * 2, 400)
|
|
166
|
+
|
|
162
167
|
return (
|
|
163
168
|
<>
|
|
164
|
-
<color attach="background" args={[EDITOR_GREY.
|
|
165
|
-
{!mapping && <fog attach="fog" args={[EDITOR_GREY.
|
|
169
|
+
<color attach="background" args={[EDITOR_GREY.chrome]} />
|
|
170
|
+
{!mapping && <fog attach="fog" args={[EDITOR_GREY.chrome, 38, 160]} />}
|
|
166
171
|
<hemisphereLight args={['#d7e2ee', '#2a3038', mapping ? 1.1 : 0.85]} />
|
|
167
172
|
<directionalLight
|
|
168
173
|
position={mapping ? [8, 60, 8] : [12, 22, 8]}
|
|
169
174
|
intensity={mapping ? 1.35 : 0.55}
|
|
170
175
|
/>
|
|
171
176
|
<ambientLight intensity={mapping ? 0.7 : 0.42} />
|
|
172
|
-
<mesh
|
|
173
|
-
|
|
177
|
+
<mesh
|
|
178
|
+
rotation={[-Math.PI / 2, 0, 0]}
|
|
179
|
+
position={[bounds.cx, -0.06, bounds.cz]}
|
|
180
|
+
>
|
|
181
|
+
<planeGeometry args={[groundWidth, groundDepth]} />
|
|
174
182
|
<meshBasicMaterial color={EDITOR_GREY.chrome} />
|
|
175
183
|
</mesh>
|
|
176
184
|
<MapView
|
|
@@ -191,6 +199,7 @@ export function World({
|
|
|
191
199
|
folder={folder}
|
|
192
200
|
naming={folder.path === namingIslandId}
|
|
193
201
|
selected={folder.path === selectedFolder}
|
|
202
|
+
mapMode={mapping}
|
|
194
203
|
highlightKind={highlightedFolders[folder.path] ?? null}
|
|
195
204
|
/>
|
|
196
205
|
))}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from 'react'
|
|
1
|
+
import { useEffect, useRef, useState, type ReactNode } from 'react'
|
|
2
2
|
import { NameInput } from './NameInput'
|
|
3
3
|
import {
|
|
4
4
|
isReviewingIntent,
|
|
@@ -72,6 +72,25 @@ function PanelList({
|
|
|
72
72
|
)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
function MutationFold({
|
|
76
|
+
hasContent,
|
|
77
|
+
children,
|
|
78
|
+
}: {
|
|
79
|
+
hasContent: boolean
|
|
80
|
+
children: ReactNode
|
|
81
|
+
}) {
|
|
82
|
+
if (!hasContent) return null
|
|
83
|
+
return (
|
|
84
|
+
<details
|
|
85
|
+
className="hud-fold"
|
|
86
|
+
onKeyDown={(event) => event.stopPropagation()}
|
|
87
|
+
>
|
|
88
|
+
<summary className="hud-section-title hud-fold-summary">Mutations</summary>
|
|
89
|
+
{children}
|
|
90
|
+
</details>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
75
94
|
function AddIntentRow({
|
|
76
95
|
placeholder,
|
|
77
96
|
onAdd,
|
|
@@ -539,6 +558,7 @@ export function HUD({
|
|
|
539
558
|
nextStep?.index === step.index && !doneSteps.has(step.index)
|
|
540
559
|
}
|
|
541
560
|
>
|
|
561
|
+
<span className="hud-step-index">{step.index}.</span>
|
|
542
562
|
<span className="hud-step-main">
|
|
543
563
|
<span className="hud-step-title">{step.title}</span>
|
|
544
564
|
{((canRunNext && nextStep?.index === step.index) ||
|
|
@@ -587,81 +607,91 @@ export function HUD({
|
|
|
587
607
|
</button>
|
|
588
608
|
</div>
|
|
589
609
|
)}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
{id}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
{id}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
{id}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
<PanelList
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
610
|
+
<MutationFold
|
|
611
|
+
hasContent={
|
|
612
|
+
previewing &&
|
|
613
|
+
(intent.files.length > 0 ||
|
|
614
|
+
(intent.createFolders ?? []).length > 0 ||
|
|
615
|
+
intent.creates.length > 0 ||
|
|
616
|
+
intent.deletes.length > 0 ||
|
|
617
|
+
addedFunctions.length > 0 ||
|
|
618
|
+
addedVariables.length > 0 ||
|
|
619
|
+
addedImports.length > 0 ||
|
|
620
|
+
(intent.imports ?? []).length > 0)
|
|
621
|
+
}
|
|
622
|
+
>
|
|
623
|
+
{intent.files.length > 0 && (
|
|
624
|
+
<>
|
|
625
|
+
<div className="hud-section-title hud-section-title-edit">Changed</div>
|
|
626
|
+
<ul>
|
|
627
|
+
{intent.files.map((id) => (
|
|
628
|
+
<li className="hud-file-edit" key={id}>
|
|
629
|
+
{id}
|
|
630
|
+
</li>
|
|
631
|
+
))}
|
|
632
|
+
</ul>
|
|
633
|
+
</>
|
|
634
|
+
)}
|
|
635
|
+
{(intent.createFolders ?? []).length > 0 && (
|
|
636
|
+
<>
|
|
637
|
+
<div className="hud-section-title hud-section-title-add">Added islands</div>
|
|
638
|
+
<ul>
|
|
639
|
+
{intent.createFolders.map((id) => (
|
|
640
|
+
<li className="hud-file-add" key={id}>
|
|
641
|
+
{id}/
|
|
642
|
+
</li>
|
|
643
|
+
))}
|
|
644
|
+
</ul>
|
|
645
|
+
</>
|
|
646
|
+
)}
|
|
647
|
+
{intent.creates.length > 0 && (
|
|
648
|
+
<>
|
|
649
|
+
<div className="hud-section-title hud-section-title-add">Added</div>
|
|
650
|
+
<ul>
|
|
651
|
+
{intent.creates.map((id) => (
|
|
652
|
+
<li className="hud-file-add" key={id}>
|
|
653
|
+
{id}
|
|
654
|
+
</li>
|
|
655
|
+
))}
|
|
656
|
+
</ul>
|
|
657
|
+
</>
|
|
658
|
+
)}
|
|
659
|
+
{intent.deletes.length > 0 && (
|
|
660
|
+
<>
|
|
661
|
+
<div className="hud-section-title hud-section-title-remove">Removed</div>
|
|
662
|
+
<ul>
|
|
663
|
+
{intent.deletes.map((id) => (
|
|
664
|
+
<li className="hud-file-remove" key={id}>
|
|
665
|
+
{id}
|
|
666
|
+
</li>
|
|
667
|
+
))}
|
|
668
|
+
</ul>
|
|
669
|
+
</>
|
|
670
|
+
)}
|
|
671
|
+
<PanelList
|
|
672
|
+
title="Functions"
|
|
673
|
+
items={symbolLabels(addedFunctions)}
|
|
674
|
+
/>
|
|
675
|
+
<PanelList
|
|
676
|
+
title="Variables"
|
|
677
|
+
items={symbolLabels(addedVariables)}
|
|
678
|
+
/>
|
|
679
|
+
{addedImports.length > 0 && (
|
|
680
|
+
<PanelList title="Imports" items={importLabels(addedImports)} />
|
|
681
|
+
)}
|
|
682
|
+
{addedImports.length === 0 && (intent.imports ?? []).length > 0 && (
|
|
683
|
+
<>
|
|
684
|
+
<div className="hud-section-title">Imports</div>
|
|
685
|
+
<ul>
|
|
686
|
+
{intent.imports.map((edge) => (
|
|
687
|
+
<li key={`${edge.from}->${edge.to}`}>
|
|
688
|
+
{edge.from.split('/').pop()} → {edge.to.split('/').pop()}
|
|
689
|
+
</li>
|
|
690
|
+
))}
|
|
691
|
+
</ul>
|
|
692
|
+
</>
|
|
693
|
+
)}
|
|
694
|
+
</MutationFold>
|
|
665
695
|
{(planReady || preparing) && (
|
|
666
696
|
<div className="hud-decide">
|
|
667
697
|
<button
|
|
@@ -971,7 +1001,7 @@ export function HUD({
|
|
|
971
1001
|
</>
|
|
972
1002
|
)}
|
|
973
1003
|
<span>Click a line to fly there</span>
|
|
974
|
-
<span>
|
|
1004
|
+
<span>Shift-click ground to walk</span>
|
|
975
1005
|
{selected?.userCreated && creatingBlueprint && (
|
|
976
1006
|
<span>Backspace delete</span>
|
|
977
1007
|
)}
|