@jkwd/inbase 0.1.21 → 0.1.22

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 (58) hide show
  1. package/README.md +13 -7
  2. package/apps/explorer/package.json +1 -0
  3. package/apps/explorer/scripts/explain-store.d.ts +135 -0
  4. package/apps/explorer/scripts/explain-store.mjs +666 -0
  5. package/apps/explorer/scripts/patch-lib.mjs +4 -0
  6. package/apps/explorer/scripts/scan-target.mjs +22 -5
  7. package/apps/explorer/scripts/session-store.d.ts +86 -11
  8. package/apps/explorer/scripts/session-store.mjs +371 -58
  9. package/apps/explorer/scripts/target-config.d.ts +38 -3
  10. package/apps/explorer/scripts/target-config.mjs +147 -3
  11. package/apps/explorer/src/App.tsx +1073 -158
  12. package/apps/explorer/src/agentIntent.ts +61 -7
  13. package/apps/explorer/src/codebase.ts +1 -1
  14. package/apps/explorer/src/devTargets.ts +66 -0
  15. package/apps/explorer/src/explain.ts +312 -0
  16. package/apps/explorer/src/index.css +874 -222
  17. package/apps/explorer/src/layout.ts +55 -0
  18. package/apps/explorer/src/scene/DistantFileBlocks.tsx +4 -2
  19. package/apps/explorer/src/scene/FileBlock.tsx +95 -72
  20. package/apps/explorer/src/scene/FolderArea.tsx +55 -32
  21. package/apps/explorer/src/scene/MapView.tsx +506 -33
  22. package/apps/explorer/src/scene/RelationLines.tsx +7 -0
  23. package/apps/explorer/src/scene/World.tsx +146 -32
  24. package/apps/explorer/src/speech.ts +228 -0
  25. package/apps/explorer/src/theme.ts +29 -0
  26. package/apps/explorer/src/types.ts +98 -8
  27. package/apps/explorer/src/ui/CanvasErrorBoundary.tsx +1 -1
  28. package/apps/explorer/src/ui/ExplainAskCard.tsx +142 -0
  29. package/apps/explorer/src/ui/ExplainHud.tsx +524 -0
  30. package/apps/explorer/src/ui/ExplainInfoPanel.tsx +135 -0
  31. package/apps/explorer/src/ui/ExplainPointer.tsx +73 -0
  32. package/apps/explorer/src/ui/EyeIcon.tsx +38 -1
  33. package/apps/explorer/src/ui/HUD.tsx +1067 -795
  34. package/apps/explorer/src/ui/NameInput.tsx +114 -5
  35. package/apps/explorer/src/userContext.ts +0 -11
  36. package/apps/explorer/src/userCreated.ts +54 -1
  37. package/apps/explorer/vite.config.ts +173 -26
  38. package/bin/inbase.mjs +11 -2
  39. package/bin/project.mjs +1 -1
  40. package/bin/session.mjs +287 -38
  41. package/package.json +4 -1
  42. package/skill/commands/amber.md +23 -0
  43. package/skill/commands/blue.md +13 -0
  44. package/skill/commands/coral.md +23 -0
  45. package/skill/commands/explain.md +77 -0
  46. package/skill/commands/green.md +23 -0
  47. package/skill/commands/inbase.md +7 -5
  48. package/skill/commands/lime.md +23 -0
  49. package/skill/commands/orange.md +23 -0
  50. package/skill/commands/purple.md +23 -0
  51. package/skill/commands/red.md +23 -0
  52. package/skill/commands/skipinbase.md +1 -1
  53. package/skill/commands/violet.md +23 -0
  54. package/skill/commands/yellow.md +23 -0
  55. package/skill/inbase/SKILL.md +124 -76
  56. package/apps/explorer/src/scene/BlockPlacer.tsx +0 -78
  57. package/apps/explorer/src/scene/IslandPlacer.tsx +0 -31
  58. package/apps/explorer/src/scene/SelectionThumbnail.tsx +0 -1069
@@ -572,6 +572,61 @@ export function worldBounds(layout: WorldLayout) {
572
572
  }
573
573
  }
574
574
 
575
+ export function regionBounds(
576
+ layout: WorldLayout,
577
+ fileIds: Iterable<string> = [],
578
+ folderPaths: Iterable<string> = [],
579
+ ) {
580
+ let minX = Infinity
581
+ let maxX = -Infinity
582
+ let minZ = Infinity
583
+ let maxZ = -Infinity
584
+ let found = false
585
+
586
+ const include = (left: number, right: number, top: number, bottom: number) => {
587
+ found = true
588
+ minX = Math.min(minX, left)
589
+ maxX = Math.max(maxX, right)
590
+ minZ = Math.min(minZ, top)
591
+ maxZ = Math.max(maxZ, bottom)
592
+ }
593
+
594
+ for (const path of folderPaths) {
595
+ const folder = layout.folders[path]
596
+ if (!folder) continue
597
+ include(
598
+ folder.x - folder.width / 2,
599
+ folder.x + folder.width / 2,
600
+ folder.z,
601
+ folder.z + folder.depth,
602
+ )
603
+ }
604
+
605
+ for (const id of fileIds) {
606
+ const file = layout.files[id]
607
+ if (!file) continue
608
+ include(
609
+ file.position[0] - file.size[0] / 2,
610
+ file.position[0] + file.size[0] / 2,
611
+ file.position[2] - file.size[2] / 2,
612
+ file.position[2] + file.size[2] / 2,
613
+ )
614
+ }
615
+
616
+ if (!found) return worldBounds(layout)
617
+
618
+ return {
619
+ minX,
620
+ maxX,
621
+ minZ,
622
+ maxZ,
623
+ cx: (minX + maxX) / 2,
624
+ cz: (minZ + maxZ) / 2,
625
+ width: Math.max(maxX - minX, 8),
626
+ depth: Math.max(maxZ - minZ, 8),
627
+ }
628
+ }
629
+
575
630
  export function fileChangeKind(
576
631
  id: string,
577
632
  planned: Set<string>,
@@ -1,6 +1,6 @@
1
1
  import { useRef } from 'react'
2
2
  import { Instances, Instance } from '@react-three/drei'
3
- import { dimColor, fileColor } from '../theme'
3
+ import { dimColor, fileColor, blueprintPalette } from '../theme'
4
4
  import type { FileNode, PlacedFile } from '../types'
5
5
 
6
6
  type DistantFile = {
@@ -28,7 +28,9 @@ export function DistantFileBlocks({
28
28
  <boxGeometry args={[1, 1, 1]} />
29
29
  <meshLambertMaterial />
30
30
  {items.map(({ file, placed, dimmed }) => {
31
- const color = file.userCreated ? '#7ec8e8' : fileColor(file.language)
31
+ const color = file.userCreated || file.colorHex
32
+ ? blueprintPalette(file.colorHex).color
33
+ : fileColor(file.language)
32
34
  return (
33
35
  <Instance
34
36
  key={file.id}
@@ -1,8 +1,8 @@
1
1
  import { memo, Suspense } from 'react'
2
2
  import { Billboard, Edges, Html, Text } from '@react-three/drei'
3
- import { CHANGE_HIGHLIGHT, CONFIG, dimColor, fileColor, FILE_SELECTION, MAP_SELECTION, type ChangeKind } from '../theme'
3
+ import { CHANGE_HIGHLIGHT, CONFIG, blueprintPalette, dimColor, fileColor, FILE_SELECTION, MAP_SELECTION, type ChangeKind } from '../theme'
4
4
  import { NameInput } from '../ui/NameInput'
5
- import { EyeIcon } from '../ui/EyeIcon'
5
+ import { BlueprintEyes } from '../ui/EyeIcon'
6
6
  import { MapSelectBorder } from './MapSelectBorder'
7
7
  import type { FileNode } from '../types'
8
8
  import type { PlacedFile } from '../types'
@@ -26,12 +26,14 @@ type FileBlockProps = {
26
26
  added?: boolean
27
27
  aimed?: boolean
28
28
  dimmed: boolean
29
+ focused?: boolean
29
30
  naming?: boolean
30
31
  mapMode?: boolean
31
32
  highlightMapChange?: boolean
32
- previewLabels?: boolean
33
33
  labelVisible?: boolean
34
34
  pointed?: boolean
35
+ pointedColors?: string[]
36
+ opacity?: number
35
37
  onCommitName?: (name: string) => void
36
38
  onCancelName?: () => void
37
39
  }
@@ -90,32 +92,43 @@ export const FileBlock = memo(function FileBlock({
90
92
  added = false,
91
93
  aimed = false,
92
94
  dimmed,
95
+ focused = false,
93
96
  naming = false,
94
97
  mapMode = false,
95
98
  highlightMapChange = mapMode,
96
- previewLabels = false,
97
99
  labelVisible = true,
98
100
  pointed = false,
101
+ pointedColors,
102
+ opacity = 1,
99
103
  onCommitName,
100
104
  onCancelName,
101
105
  }: FileBlockProps) {
102
106
  const [width, height, depth] = placed.size
103
107
  const highlight =
104
- changeKind && highlightMapChange && !selected
108
+ changeKind && highlightMapChange && !selected && !file.userCreated && !file.colorHex
105
109
  ? CHANGE_HIGHLIGHT[changeKind]
106
110
  : null
107
111
  const isAdded = added || Boolean(file.userCreated)
108
- const color = isAdded ? '#7ec8e8' : fileColor(file.language)
112
+ const tint = file.colorHex || file.userCreated ? blueprintPalette(file.colorHex) : null
113
+ const color = tint ? tint.color : isAdded ? '#7ec8e8' : fileColor(file.language)
109
114
  const muted = dimColor(color, 0.32)
110
115
  const label = fileLabel(file.name, changeKind, isAdded)
111
116
  const mark = changeMark(changeKind, isAdded)
117
+ const eyeColors =
118
+ pointedColors && pointedColors.length > 0
119
+ ? pointedColors
120
+ : pointed
121
+ ? ['#f4f7fb']
122
+ : []
112
123
  const labelColor = aimed
113
124
  ? '#9ad8ff'
114
125
  : highlight
115
126
  ? highlight.color
116
- : dimmed
117
- ? '#b4bcc8'
118
- : '#e7ebf2'
127
+ : tint
128
+ ? tint.label
129
+ : dimmed
130
+ ? '#b4bcc8'
131
+ : '#e7ebf2'
119
132
  const meshColor = aimed
120
133
  ? '#9ad8ff'
121
134
  : highlight
@@ -135,10 +148,19 @@ export const FileBlock = memo(function FileBlock({
135
148
  <mesh userData={{ fileId: file.id }} scale={[width, height, depth]}>
136
149
  <boxGeometry args={[1, 1, 1]} />
137
150
  {mapMode ? (
138
- <meshBasicMaterial color={meshColor} toneMapped={false} />
151
+ <meshBasicMaterial
152
+ color={meshColor}
153
+ toneMapped={false}
154
+ transparent={opacity < 1}
155
+ opacity={opacity}
156
+ depthWrite={opacity >= 1}
157
+ />
139
158
  ) : (
140
159
  <meshLambertMaterial
141
160
  color={meshColor}
161
+ transparent={opacity < 1}
162
+ opacity={opacity}
163
+ depthWrite={opacity >= 1}
142
164
  emissive={
143
165
  aimed
144
166
  ? '#3a6a80'
@@ -148,11 +170,13 @@ export const FileBlock = memo(function FileBlock({
148
170
  ? FILE_SELECTION.emissive
149
171
  : related
150
172
  ? '#1f4a44'
151
- : isAdded
152
- ? '#2a5064'
153
- : dimmed
154
- ? muted
155
- : color
173
+ : tint
174
+ ? tint.emissive
175
+ : isAdded
176
+ ? '#2a5064'
177
+ : dimmed
178
+ ? muted
179
+ : color
156
180
  }
157
181
  emissiveIntensity={
158
182
  aimed
@@ -191,31 +215,43 @@ export const FileBlock = memo(function FileBlock({
191
215
  userData={{ fileId: file.id }}
192
216
  />
193
217
  )}
218
+ {focused && mapMode && (
219
+ <MapSelectBorder
220
+ width={width}
221
+ depth={depth}
222
+ y={height / 2 + (selected ? 0.06 : 0.03)}
223
+ stroke={MAP_SELECTION.explainPad}
224
+ color={MAP_SELECTION.explain}
225
+ userData={{ fileId: file.id }}
226
+ />
227
+ )}
194
228
  {mapMode && !naming && mark && (
195
229
  <MapChangeMark mark={mark} width={width} depth={depth} height={height} />
196
230
  )}
197
- {pointed && !naming && (
231
+ {eyeColors.length > 0 && !naming && (
198
232
  <Html
199
233
  position={
200
234
  mapMode
201
- ? mark
202
- ? [width * 0.28, height / 2 + 0.16, -depth * 0.28]
203
- : [0, height / 2 + 0.12, 0]
204
- : [0, height / 2 + (planned || highlight ? 0.92 : 0.74), 0]
235
+ ? [
236
+ width / 2 + Math.min(width, depth) * 0.28,
237
+ height / 2 + 0.04,
238
+ 0,
239
+ ]
240
+ : [
241
+ width * 0.38,
242
+ height / 2 + 0.18,
243
+ 0,
244
+ ]
205
245
  }
206
246
  center
247
+ distanceFactor={
248
+ mapMode ? Math.min(width, depth) / 24 : undefined
249
+ }
207
250
  occlude={false}
208
251
  style={{ pointerEvents: 'none' }}
209
252
  zIndexRange={[40, 0]}
210
253
  >
211
- <div
212
- className="blueprint-eye"
213
- data-map={mapMode ? 'true' : 'false'}
214
- role="img"
215
- aria-label="Keep in mind"
216
- >
217
- <EyeIcon size={mapMode ? 16 : 18} title="Keep in mind" />
218
- </div>
254
+ <BlueprintEyes colors={eyeColors} mapMode={mapMode} />
219
255
  </Html>
220
256
  )}
221
257
  {naming && onCommitName && onCancelName && (
@@ -236,6 +272,7 @@ export const FileBlock = memo(function FileBlock({
236
272
  >
237
273
  <NameInput
238
274
  placeholder="File name"
275
+ fallbackName="New file"
239
276
  onCommit={onCommitName}
240
277
  onCancel={onCancelName}
241
278
  />
@@ -243,57 +280,43 @@ export const FileBlock = memo(function FileBlock({
243
280
  )}
244
281
  {showLabels && (
245
282
  <Suspense fallback={null}>
246
- {previewLabels ? (
247
- <Html
248
- position={[0, height / 2 + 0.4, 0]}
249
- center
250
- occlude={false}
251
- style={{ pointerEvents: 'none' }}
252
- zIndexRange={[20, 0]}
283
+ <Billboard position={[0, height / 2 + (planned || highlight ? 0.55 : 0.38), 0]}>
284
+ <Text
285
+ fontSize={0.28}
286
+ color={labelColor}
287
+ anchorX="center"
288
+ anchorY="bottom"
289
+ maxWidth={3.4}
253
290
  >
254
- <div className="thumbnail-block-label">{label}</div>
255
- </Html>
256
- ) : (
257
- <>
258
- <Billboard position={[0, height / 2 + (planned || highlight ? 0.55 : 0.38), 0]}>
291
+ {label}
292
+ </Text>
293
+ </Billboard>
294
+ {height >= SIDE_LABEL_MIN_HEIGHT &&
295
+ SIDE_LABELS.map((side) => {
296
+ const face = side.axis === 'x' ? width : depth
297
+ const x =
298
+ side.axis === 'x' ? side.sign * (width / 2 + SIDE_LABEL_PAD) : 0
299
+ const z =
300
+ side.axis === 'z' ? side.sign * (depth / 2 + SIDE_LABEL_PAD) : 0
301
+ return (
259
302
  <Text
260
- fontSize={0.28}
303
+ key={`${side.axis}:${side.sign}`}
304
+ position={[x, -height / 2 + 0.22, z]}
305
+ rotation={[0, side.rotationY, 0]}
306
+ fontSize={0.22}
261
307
  color={labelColor}
262
308
  anchorX="center"
263
- anchorY="bottom"
264
- maxWidth={3.4}
309
+ anchorY="middle"
310
+ maxWidth={face - 0.2}
311
+ overflowWrap="break-word"
312
+ outlineWidth={0.012}
313
+ outlineColor="#11151c"
314
+ depthOffset={-1}
265
315
  >
266
316
  {label}
267
317
  </Text>
268
- </Billboard>
269
- {height >= SIDE_LABEL_MIN_HEIGHT &&
270
- SIDE_LABELS.map((side) => {
271
- const face = side.axis === 'x' ? width : depth
272
- const x =
273
- side.axis === 'x' ? side.sign * (width / 2 + SIDE_LABEL_PAD) : 0
274
- const z =
275
- side.axis === 'z' ? side.sign * (depth / 2 + SIDE_LABEL_PAD) : 0
276
- return (
277
- <Text
278
- key={`${side.axis}:${side.sign}`}
279
- position={[x, -height / 2 + 0.22, z]}
280
- rotation={[0, side.rotationY, 0]}
281
- fontSize={0.22}
282
- color={labelColor}
283
- anchorX="center"
284
- anchorY="middle"
285
- maxWidth={face - 0.2}
286
- overflowWrap="break-word"
287
- outlineWidth={0.012}
288
- outlineColor="#11151c"
289
- depthOffset={-1}
290
- >
291
- {label}
292
- </Text>
293
- )
294
- })}
295
- </>
296
- )}
318
+ )
319
+ })}
297
320
  </Suspense>
298
321
  )}
299
322
  </group>
@@ -3,6 +3,7 @@ import { Html, Text } from '@react-three/drei'
3
3
  import {
4
4
  CHANGE_HIGHLIGHT,
5
5
  CONFIG,
6
+ blueprintPalette,
6
7
  folderAisleColor,
7
8
  folderFloorColor,
8
9
  MAP_SELECTION,
@@ -11,7 +12,7 @@ import {
11
12
  import type { PlacedFolder } from '../types'
12
13
  import { MapSelectBorder } from './MapSelectBorder'
13
14
  import { NameInput } from '../ui/NameInput'
14
- import { EyeIcon } from '../ui/EyeIcon'
15
+ import { BlueprintEyes } from '../ui/EyeIcon'
15
16
 
16
17
  type FolderAreaProps = {
17
18
  folder: PlacedFolder
@@ -19,9 +20,10 @@ type FolderAreaProps = {
19
20
  selected?: boolean
20
21
  mapMode?: boolean
21
22
  highlightKind?: ChangeKind | null
22
- previewLabels?: boolean
23
23
  labelVisible?: boolean
24
24
  pointed?: boolean
25
+ pointedColors?: string[]
26
+ opacity?: number
25
27
  onCommitName?: (name: string) => void
26
28
  onCancelName?: () => void
27
29
  }
@@ -32,26 +34,35 @@ export function FolderArea({
32
34
  selected = false,
33
35
  mapMode = false,
34
36
  highlightKind = null,
35
- previewLabels = false,
36
37
  labelVisible = true,
37
38
  pointed = false,
39
+ pointedColors,
40
+ opacity = 1,
38
41
  onCommitName,
39
42
  onCancelName,
40
43
  }: FolderAreaProps) {
41
44
  const added = Boolean(folder.added)
42
45
  const highlight = highlightKind ? CHANGE_HIGHLIGHT[highlightKind] : null
43
46
  const addedOnly = added && !highlight
44
- const outline = highlight ? highlight.color : addedOnly ? '#7ec8e8' : null
47
+ const tint = addedOnly ? blueprintPalette(folder.colorHex) : null
48
+ const outline = highlight ? highlight.color : addedOnly ? tint?.color ?? '#7ec8e8' : null
45
49
  const color = highlight
46
50
  ? highlight.floor
47
51
  : addedOnly
48
- ? '#16323f'
52
+ ? tint?.floor ?? '#16323f'
49
53
  : folderFloorColor(folder.path)
50
54
  const aisle = highlight
51
55
  ? highlight.aisle
52
56
  : addedOnly
53
- ? '#23485a'
57
+ ? tint?.aisle ?? '#23485a'
54
58
  : folderAisleColor(folder.path)
59
+ const eyeColors =
60
+ pointedColors && pointedColors.length > 0
61
+ ? pointedColors
62
+ : pointed
63
+ ? [MAP_SELECTION.pointed]
64
+ : []
65
+ const pointedColor = eyeColors[eyeColors.length - 1]
55
66
  const label =
56
67
  highlightKind === 'remove'
57
68
  ? `- ${folder.name}`
@@ -59,6 +70,13 @@ export function FolderArea({
59
70
  ? `+ ${folder.name}`
60
71
  : folder.name
61
72
 
73
+ const faded = opacity < 1
74
+ const floorMaterial = {
75
+ transparent: faded,
76
+ opacity,
77
+ depthWrite: !faded,
78
+ }
79
+
62
80
  return (
63
81
  <group position={[folder.x, 0, folder.z + folder.depth / 2]}>
64
82
  {outline && (
@@ -67,12 +85,18 @@ export function FolderArea({
67
85
  <meshBasicMaterial
68
86
  color={outline}
69
87
  toneMapped={false}
88
+ {...floorMaterial}
70
89
  />
71
90
  </mesh>
72
91
  )}
73
92
  <mesh rotation={[-Math.PI / 2, 0, 0]}>
74
93
  <planeGeometry args={[folder.width, folder.depth]} />
75
- <meshBasicMaterial color={color} />
94
+ <meshBasicMaterial
95
+ color={color}
96
+ transparent={faded}
97
+ opacity={opacity}
98
+ depthWrite={!faded}
99
+ />
76
100
  </mesh>
77
101
  {selected && mapMode && (
78
102
  <MapSelectBorder
@@ -83,9 +107,18 @@ export function FolderArea({
83
107
  color={MAP_SELECTION.island}
84
108
  />
85
109
  )}
110
+ {eyeColors.length > 0 && !naming && (
111
+ <MapSelectBorder
112
+ width={folder.width}
113
+ depth={folder.depth}
114
+ y={selected && mapMode ? 0.09 : 0.05}
115
+ stroke={MAP_SELECTION.pointedPad}
116
+ color={pointedColor ?? MAP_SELECTION.pointed}
117
+ />
118
+ )}
86
119
  <mesh position={[0, 0.02, 0]} rotation={[-Math.PI / 2, 0, 0]}>
87
120
  <planeGeometry args={[CONFIG.bridgeWidth, folder.depth]} />
88
- <meshBasicMaterial color={aisle} />
121
+ <meshBasicMaterial color={aisle} {...floorMaterial} />
89
122
  </mesh>
90
123
  {folder.width > 28 && (
91
124
  <mesh
@@ -93,25 +126,18 @@ export function FolderArea({
93
126
  rotation={[-Math.PI / 2, 0, 0]}
94
127
  >
95
128
  <planeGeometry args={[folder.width, CONFIG.bridgeWidth]} />
96
- <meshBasicMaterial color={aisle} />
129
+ <meshBasicMaterial color={aisle} {...floorMaterial} />
97
130
  </mesh>
98
131
  )}
99
- {pointed && !naming && (
132
+ {eyeColors.length > 0 && !naming && !mapMode && (
100
133
  <Html
101
- position={[0, mapMode ? 1.15 : 1.45, -folder.depth / 2 + 2.2]}
134
+ position={[1.45, 1.75, -folder.depth / 2 + 1.6]}
102
135
  center
103
136
  occlude={false}
104
137
  style={{ pointerEvents: 'none' }}
105
138
  zIndexRange={[40, 0]}
106
139
  >
107
- <div
108
- className="blueprint-eye"
109
- data-map={mapMode ? 'true' : 'false'}
110
- role="img"
111
- aria-label="Keep in mind"
112
- >
113
- <EyeIcon size={mapMode ? 18 : 22} title="Keep in mind" />
114
- </div>
140
+ <BlueprintEyes colors={eyeColors} size={20} />
115
141
  </Html>
116
142
  )}
117
143
  {naming && mapMode && onCommitName && onCancelName && (
@@ -124,31 +150,28 @@ export function FolderArea({
124
150
  >
125
151
  <NameInput
126
152
  placeholder="Folder name"
153
+ fallbackName="New folder"
127
154
  onCommit={onCommitName}
128
155
  onCancel={onCancelName}
129
156
  />
130
157
  </Html>
131
158
  )}
132
159
  <Suspense fallback={null}>
133
- {!naming && previewLabels && labelVisible && (
134
- <Html
135
- position={[0, 1.35, -folder.depth / 2 + 1.6]}
136
- center
137
- occlude={false}
138
- style={{ pointerEvents: 'none' }}
139
- zIndexRange={[20, 0]}
140
- >
141
- <div className="thumbnail-folder-label">{label}</div>
142
- </Html>
143
- )}
144
- {!naming && !previewLabels && !mapMode && labelVisible && (
160
+ {!naming && !mapMode && labelVisible && (
145
161
  <Text
146
162
  position={[0, 0.05, -folder.depth / 2 + 1.6]}
147
163
  rotation={[-Math.PI / 2, 0, 0]}
148
164
  fontSize={0.55}
149
165
  color={
150
- highlight ? highlight.color : addedOnly ? '#9ad8ff' : '#8b95a5'
166
+ pointedColor
167
+ ? pointedColor
168
+ : highlight
169
+ ? highlight.color
170
+ : addedOnly
171
+ ? tint?.label ?? '#9ad8ff'
172
+ : '#8b95a5'
151
173
  }
174
+ fillOpacity={opacity}
152
175
  anchorX="center"
153
176
  anchorY="middle"
154
177
  >