@carlesandres/house 0.5.0 → 0.5.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.
- package/CHANGELOG.md +33 -1
- package/README.md +1 -1
- package/dist/index.js +675 -395
- package/package.json +26 -21
package/dist/index.js
CHANGED
|
@@ -9,17 +9,18 @@ import { createCliRenderer } from "@opentui/core";
|
|
|
9
9
|
import { createRoot } from "@opentui/react";
|
|
10
10
|
import { RegistryProvider } from "@effect/atom-react";
|
|
11
11
|
import { Cause, Duration, Effect as Effect5, Fiber, Stream as Stream2 } from "effect";
|
|
12
|
-
import { useEffect as
|
|
12
|
+
import { useEffect as useEffect6, useRef as useRef4, useState as useState6 } from "react";
|
|
13
13
|
// package.json
|
|
14
14
|
var package_default = {
|
|
15
15
|
name: "@carlesandres/house",
|
|
16
|
-
version: "0.5.
|
|
16
|
+
version: "0.5.2",
|
|
17
17
|
description: "TUI-first markdown reader on opentui",
|
|
18
18
|
type: "module",
|
|
19
19
|
license: "MIT",
|
|
20
20
|
repository: {
|
|
21
21
|
type: "git",
|
|
22
|
-
url: "git+https://github.com/carlesandres/house.git"
|
|
22
|
+
url: "git+https://github.com/carlesandres/house.git",
|
|
23
|
+
directory: "apps/house"
|
|
23
24
|
},
|
|
24
25
|
bugs: {
|
|
25
26
|
url: "https://github.com/carlesandres/house/issues"
|
|
@@ -38,8 +39,6 @@ var package_default = {
|
|
|
38
39
|
files: [
|
|
39
40
|
"dist/bin.js",
|
|
40
41
|
"dist/index.js",
|
|
41
|
-
"README.md",
|
|
42
|
-
"LICENSE",
|
|
43
42
|
"CHANGELOG.md"
|
|
44
43
|
],
|
|
45
44
|
publishConfig: {
|
|
@@ -51,29 +50,32 @@ var package_default = {
|
|
|
51
50
|
house: "dist/bin.js"
|
|
52
51
|
},
|
|
53
52
|
scripts: {
|
|
53
|
+
build: "bun run build:cli",
|
|
54
|
+
"build:cli": "bun run dev/build-cli.ts",
|
|
55
|
+
"build:npm-main": "bun run dev/build-npm-main.ts",
|
|
56
|
+
"build:npm-packages": "bun run dev/build-npm-packages.ts",
|
|
57
|
+
"build:standalone": "bun run dev/build-standalone.ts",
|
|
58
|
+
"build:themes": "bun run dev/build-themes.ts",
|
|
54
59
|
dev: "bun --watch src/index.tsx",
|
|
55
|
-
start: "bun run src/index.tsx",
|
|
56
|
-
"record-demo": "bash recordings/record-demo.sh",
|
|
57
|
-
typecheck: "tsc --noEmit",
|
|
58
|
-
lint: "oxlint --tsconfig tsconfig.json src/",
|
|
59
60
|
format: "oxfmt src/",
|
|
60
61
|
"format:check": "oxfmt --check src/",
|
|
62
|
+
lint: "oxlint --tsconfig tsconfig.json src/ test/ dev/",
|
|
63
|
+
"npm:pack": "bun run build:npm-main && npm pack --dry-run dist/npm/main",
|
|
64
|
+
"record-demo": "bash recordings/record-demo.sh",
|
|
65
|
+
release: "bun run dev/release.ts",
|
|
66
|
+
"repro:pty-codeblocks": "bun run dev/repro-pty-codeblocks.ts",
|
|
67
|
+
start: "bun run src/index.tsx",
|
|
61
68
|
test: "bun test",
|
|
62
69
|
"test:pty": "HOUSE_PTY=1 bun test test/pty/",
|
|
63
|
-
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"build:npm-packages": "bun run dev/build-npm-packages.ts",
|
|
67
|
-
"build:themes": "bun run dev/build-themes.ts",
|
|
68
|
-
prepack: "bun run build:cli",
|
|
69
|
-
"repro:pty-codeblocks": "bun run dev/repro-pty-codeblocks.ts",
|
|
70
|
-
prepare: "git config core.hooksPath .githooks 2>/dev/null || true"
|
|
70
|
+
typecheck: "tsc --noEmit",
|
|
71
|
+
"verify:github": "bun test test/github-emulation.test.ts",
|
|
72
|
+
"version:set": "bun run dev/set-version.ts"
|
|
71
73
|
},
|
|
72
74
|
optionalDependencies: {
|
|
73
|
-
"@carlesandres/house-darwin-arm64": "0.5.
|
|
74
|
-
"@carlesandres/house-darwin-x64": "0.5.
|
|
75
|
-
"@carlesandres/house-linux-arm64": "0.5.
|
|
76
|
-
"@carlesandres/house-linux-x64": "0.5.
|
|
75
|
+
"@carlesandres/house-darwin-arm64": "0.5.1",
|
|
76
|
+
"@carlesandres/house-darwin-x64": "0.5.1",
|
|
77
|
+
"@carlesandres/house-linux-arm64": "0.5.1",
|
|
78
|
+
"@carlesandres/house-linux-x64": "0.5.1"
|
|
77
79
|
},
|
|
78
80
|
dependencies: {
|
|
79
81
|
"@effect/atom-react": "4.0.0-beta.60",
|
|
@@ -84,12 +86,15 @@ var package_default = {
|
|
|
84
86
|
ignore: "^7.0.5",
|
|
85
87
|
marked: "^18.0.4",
|
|
86
88
|
react: "19.2.6",
|
|
87
|
-
scheduler: "0.27.0"
|
|
89
|
+
scheduler: "0.27.0",
|
|
90
|
+
"string-width": "7.2.0",
|
|
91
|
+
"web-tree-sitter": "0.25.10"
|
|
88
92
|
},
|
|
89
93
|
devDependencies: {
|
|
90
94
|
"@effect/language-service": "0.86.2",
|
|
91
95
|
"@types/bun": "1.3.14",
|
|
92
96
|
"@types/react": "19.2.15",
|
|
97
|
+
emulate: "0.9.0",
|
|
93
98
|
oxfmt: "0.51.0",
|
|
94
99
|
oxlint: "1.66.0",
|
|
95
100
|
tuistory: "^0.8.0",
|
|
@@ -99,18 +104,424 @@ var package_default = {
|
|
|
99
104
|
|
|
100
105
|
// src/Browser.tsx
|
|
101
106
|
import { SyntaxStyle } from "@opentui/core";
|
|
107
|
+
|
|
108
|
+
// ../../packages/ui/src/file-navigator/FileNavigator.tsx
|
|
109
|
+
import { useEffect, useState } from "react";
|
|
110
|
+
|
|
111
|
+
// ../../packages/ui/src/file-navigator/emptyState.tsx
|
|
112
|
+
import { jsxDEV, Fragment } from "@opentui/react/jsx-dev-runtime";
|
|
113
|
+
var fitValue = (value, width) => {
|
|
114
|
+
if (value.length <= width)
|
|
115
|
+
return value;
|
|
116
|
+
if (width <= 1)
|
|
117
|
+
return value.slice(value.length - 1);
|
|
118
|
+
return "\u2026" + value.slice(value.length - width + 1);
|
|
119
|
+
};
|
|
120
|
+
var NavigatorEmptyState = ({
|
|
121
|
+
emptyState,
|
|
122
|
+
width,
|
|
123
|
+
theme,
|
|
124
|
+
withTopSpacer
|
|
125
|
+
}) => /* @__PURE__ */ jsxDEV(Fragment, {
|
|
126
|
+
children: [
|
|
127
|
+
withTopSpacer && /* @__PURE__ */ jsxDEV("text", {
|
|
128
|
+
content: ""
|
|
129
|
+
}, undefined, false, undefined, this),
|
|
130
|
+
/* @__PURE__ */ jsxDEV("box", {
|
|
131
|
+
style: {
|
|
132
|
+
width,
|
|
133
|
+
flexDirection: "row",
|
|
134
|
+
flexWrap: "wrap",
|
|
135
|
+
justifyContent: "center",
|
|
136
|
+
gap: 1
|
|
137
|
+
},
|
|
138
|
+
children: [
|
|
139
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
140
|
+
content: emptyState.label,
|
|
141
|
+
wrapMode: "none",
|
|
142
|
+
style: { fg: theme.textMuted }
|
|
143
|
+
}, undefined, false, undefined, this),
|
|
144
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
145
|
+
content: `"${fitValue(emptyState.value, width)}"`,
|
|
146
|
+
wrapMode: "none",
|
|
147
|
+
style: { fg: theme.textMuted }
|
|
148
|
+
}, undefined, false, undefined, this)
|
|
149
|
+
]
|
|
150
|
+
}, undefined, true, undefined, this)
|
|
151
|
+
]
|
|
152
|
+
}, undefined, true, undefined, this);
|
|
153
|
+
|
|
154
|
+
// ../../packages/ui/src/file-navigator/row.tsx
|
|
155
|
+
import { jsxDEV as jsxDEV2 } from "@opentui/react/jsx-dev-runtime";
|
|
156
|
+
var SEPARATOR = " ";
|
|
157
|
+
var MIN_PARENT_BUDGET = 3;
|
|
158
|
+
var middleTruncate = (value, width) => {
|
|
159
|
+
if (width <= 0)
|
|
160
|
+
return "";
|
|
161
|
+
if (value.length <= width)
|
|
162
|
+
return value;
|
|
163
|
+
if (width <= 1)
|
|
164
|
+
return value.slice(0, width);
|
|
165
|
+
const available = width - 1;
|
|
166
|
+
const left = Math.ceil(available / 2);
|
|
167
|
+
const right = Math.floor(available / 2);
|
|
168
|
+
return value.slice(0, left) + "\u2026" + value.slice(value.length - right);
|
|
169
|
+
};
|
|
170
|
+
var fitTail = (value, width) => {
|
|
171
|
+
if (value.length <= width)
|
|
172
|
+
return value;
|
|
173
|
+
if (width <= 1)
|
|
174
|
+
return value.slice(0, 1);
|
|
175
|
+
return value.slice(0, width - 1) + "\u2026";
|
|
176
|
+
};
|
|
177
|
+
var formatFileRow = (path, width) => {
|
|
178
|
+
const slash = path.lastIndexOf("/");
|
|
179
|
+
if (slash < 0)
|
|
180
|
+
return { basename: fitTail(path, width), parent: "", separator: "" };
|
|
181
|
+
const basename = path.slice(slash + 1);
|
|
182
|
+
const parent = path.slice(0, slash);
|
|
183
|
+
if (basename.length >= width) {
|
|
184
|
+
return { basename: fitTail(basename, width), parent: "", separator: "" };
|
|
185
|
+
}
|
|
186
|
+
const remaining = width - basename.length - SEPARATOR.length;
|
|
187
|
+
if (remaining < MIN_PARENT_BUDGET || parent.length === 0) {
|
|
188
|
+
return { basename, parent: "", separator: "" };
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
basename,
|
|
192
|
+
parent: middleTruncate(parent, remaining),
|
|
193
|
+
separator: SEPARATOR
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
var DefaultFileRow = ({
|
|
197
|
+
path,
|
|
198
|
+
selected,
|
|
199
|
+
width,
|
|
200
|
+
theme
|
|
201
|
+
}) => {
|
|
202
|
+
const { basename, parent, separator } = formatFileRow(path, width);
|
|
203
|
+
return /* @__PURE__ */ jsxDEV2("text", {
|
|
204
|
+
wrapMode: "none",
|
|
205
|
+
children: [
|
|
206
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
207
|
+
style: { fg: selected ? theme.selectedListItemText : theme.text },
|
|
208
|
+
children: basename
|
|
209
|
+
}, undefined, false, undefined, this),
|
|
210
|
+
parent !== "" && /* @__PURE__ */ jsxDEV2("span", {
|
|
211
|
+
style: { fg: theme.textMuted },
|
|
212
|
+
children: `${separator}${parent}`
|
|
213
|
+
}, undefined, false, undefined, this)
|
|
214
|
+
]
|
|
215
|
+
}, undefined, true, undefined, this);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// ../../packages/ui/src/file-navigator/FileNavigator.tsx
|
|
219
|
+
import { jsxDEV as jsxDEV3 } from "@opentui/react/jsx-dev-runtime";
|
|
220
|
+
var INLINE_BORDER_SIDES = ["top", "bottom", "right"];
|
|
221
|
+
var STACKED_BORDER_SIDES = ["top", "bottom"];
|
|
222
|
+
var INLINE_BORDER_CHARS = {
|
|
223
|
+
topLeft: "\u250C",
|
|
224
|
+
topRight: "\u252C",
|
|
225
|
+
bottomLeft: "\u2514",
|
|
226
|
+
bottomRight: "\u2534",
|
|
227
|
+
horizontal: "\u2500",
|
|
228
|
+
vertical: "\u2502",
|
|
229
|
+
topT: "\u252C",
|
|
230
|
+
bottomT: "\u2534",
|
|
231
|
+
leftT: "\u251C",
|
|
232
|
+
rightT: "\u2524",
|
|
233
|
+
cross: "\u253C"
|
|
234
|
+
};
|
|
235
|
+
var INACTIVE_PANE_OPACITY = 0.62;
|
|
236
|
+
var FileNavigator = ({
|
|
237
|
+
controller,
|
|
238
|
+
width,
|
|
239
|
+
paneHeight,
|
|
240
|
+
variant,
|
|
241
|
+
active,
|
|
242
|
+
visible,
|
|
243
|
+
theme,
|
|
244
|
+
header,
|
|
245
|
+
emptyState,
|
|
246
|
+
renderFile
|
|
247
|
+
}) => {
|
|
248
|
+
const [scroll, setScroll] = useState(0);
|
|
249
|
+
const hasHeader = header !== undefined && header !== null && header !== false;
|
|
250
|
+
const visibleRows = Math.max(1, paneHeight - 2 - (hasHeader ? 1 : 0));
|
|
251
|
+
const maxScroll = Math.max(0, controller.filteredFiles.length - visibleRows);
|
|
252
|
+
const selectedIndex = controller.selectedIndex;
|
|
253
|
+
const desiredScroll = (() => {
|
|
254
|
+
let next = scroll;
|
|
255
|
+
if (selectedIndex !== null) {
|
|
256
|
+
if (selectedIndex < next)
|
|
257
|
+
next = selectedIndex;
|
|
258
|
+
else if (selectedIndex >= next + visibleRows)
|
|
259
|
+
next = selectedIndex - visibleRows + 1;
|
|
260
|
+
}
|
|
261
|
+
return Math.max(0, Math.min(maxScroll, next));
|
|
262
|
+
})();
|
|
263
|
+
useEffect(() => {
|
|
264
|
+
if (desiredScroll !== scroll)
|
|
265
|
+
setScroll(desiredScroll);
|
|
266
|
+
}, [desiredScroll, scroll]);
|
|
267
|
+
const rowWidth = Math.max(4, width - (variant === "inline" ? 2 : 1));
|
|
268
|
+
const visibleFiles = controller.filteredFiles.slice(desiredScroll, desiredScroll + visibleRows);
|
|
269
|
+
if (!visible)
|
|
270
|
+
return null;
|
|
271
|
+
return /* @__PURE__ */ jsxDEV3("box", {
|
|
272
|
+
style: {
|
|
273
|
+
border: variant === "inline" ? INLINE_BORDER_SIDES : STACKED_BORDER_SIDES,
|
|
274
|
+
borderColor: theme.border,
|
|
275
|
+
width,
|
|
276
|
+
height: paneHeight,
|
|
277
|
+
...variant === "inline" ? { flexShrink: 0 } : { flexGrow: 1, flexShrink: 1 },
|
|
278
|
+
flexDirection: "column",
|
|
279
|
+
backgroundColor: theme.backgroundPanel
|
|
280
|
+
},
|
|
281
|
+
...variant === "inline" ? { customBorderChars: INLINE_BORDER_CHARS } : {},
|
|
282
|
+
children: /* @__PURE__ */ jsxDEV3("box", {
|
|
283
|
+
style: {
|
|
284
|
+
flexGrow: 1,
|
|
285
|
+
flexShrink: 1,
|
|
286
|
+
flexDirection: "column",
|
|
287
|
+
paddingLeft: 1,
|
|
288
|
+
backgroundColor: active ? theme.background : theme.backgroundPanel,
|
|
289
|
+
opacity: active ? 1 : INACTIVE_PANE_OPACITY
|
|
290
|
+
},
|
|
291
|
+
children: [
|
|
292
|
+
header,
|
|
293
|
+
controller.filteredFiles.length === 0 ? emptyState && /* @__PURE__ */ jsxDEV3(NavigatorEmptyState, {
|
|
294
|
+
emptyState,
|
|
295
|
+
width: rowWidth,
|
|
296
|
+
theme,
|
|
297
|
+
withTopSpacer: hasHeader
|
|
298
|
+
}, undefined, false, undefined, this) : visibleFiles.map((file, offset) => {
|
|
299
|
+
const index = desiredScroll + offset;
|
|
300
|
+
const selected = index === controller.selectedIndex;
|
|
301
|
+
return /* @__PURE__ */ jsxDEV3("box", {
|
|
302
|
+
style: {
|
|
303
|
+
width: rowWidth,
|
|
304
|
+
height: 1,
|
|
305
|
+
flexDirection: "row",
|
|
306
|
+
...selected ? { backgroundColor: theme.backgroundElement } : {}
|
|
307
|
+
},
|
|
308
|
+
children: renderFile ? renderFile({ file, index, selected, width: rowWidth, theme }) : /* @__PURE__ */ jsxDEV3(DefaultFileRow, {
|
|
309
|
+
path: controller.getPath(file),
|
|
310
|
+
selected,
|
|
311
|
+
width: rowWidth,
|
|
312
|
+
theme
|
|
313
|
+
}, undefined, false, undefined, this)
|
|
314
|
+
}, controller.getId(file), false, undefined, this);
|
|
315
|
+
})
|
|
316
|
+
]
|
|
317
|
+
}, undefined, true, undefined, this)
|
|
318
|
+
}, undefined, false, undefined, this);
|
|
319
|
+
};
|
|
320
|
+
// ../../packages/ui/src/file-navigator/useFileNavigator.ts
|
|
321
|
+
import { useEffect as useEffect2, useLayoutEffect, useReducer, useRef } from "react";
|
|
322
|
+
var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
323
|
+
var assertUniqueIds = (files, getId) => {
|
|
324
|
+
const ids = new Set;
|
|
325
|
+
for (const file of files) {
|
|
326
|
+
const id = getId(file);
|
|
327
|
+
if (ids.has(id)) {
|
|
328
|
+
throw new Error(`useFileNavigator: duplicate file ID ${JSON.stringify(id)}`);
|
|
329
|
+
}
|
|
330
|
+
ids.add(id);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
var indexOfId = (files, id, getId) => files.findIndex((file) => getId(file) === id);
|
|
334
|
+
var reconcile = (state, filteredFiles, getId) => {
|
|
335
|
+
if (filteredFiles.length === 0) {
|
|
336
|
+
return { ...state, filteredFiles, selectedId: null };
|
|
337
|
+
}
|
|
338
|
+
if (state.autoSelect) {
|
|
339
|
+
return {
|
|
340
|
+
...state,
|
|
341
|
+
filteredFiles,
|
|
342
|
+
selectedId: getId(filteredFiles[0]),
|
|
343
|
+
priorIndex: 0,
|
|
344
|
+
autoSelect: false
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
if (state.selectedId !== null) {
|
|
348
|
+
const retainedIndex = indexOfId(filteredFiles, state.selectedId, getId);
|
|
349
|
+
if (retainedIndex >= 0) {
|
|
350
|
+
return { ...state, filteredFiles, priorIndex: retainedIndex };
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const nextIndex = state.selectedId === null ? 0 : clamp(state.priorIndex, 0, Math.max(0, filteredFiles.length - 1));
|
|
354
|
+
return {
|
|
355
|
+
...state,
|
|
356
|
+
filteredFiles,
|
|
357
|
+
selectedId: getId(filteredFiles[nextIndex]),
|
|
358
|
+
priorIndex: nextIndex
|
|
359
|
+
};
|
|
360
|
+
};
|
|
361
|
+
var snapshotOf = (state, getId) => {
|
|
362
|
+
if (state.selectedId === null) {
|
|
363
|
+
return {
|
|
364
|
+
appliedQuery: state.appliedQuery,
|
|
365
|
+
filteredFiles: state.filteredFiles,
|
|
366
|
+
selectedFile: null,
|
|
367
|
+
selectedIndex: null
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
const selectedIndex = indexOfId(state.filteredFiles, state.selectedId, getId);
|
|
371
|
+
const selectedFile = selectedIndex < 0 ? null : state.filteredFiles[selectedIndex] ?? null;
|
|
372
|
+
return {
|
|
373
|
+
appliedQuery: state.appliedQuery,
|
|
374
|
+
filteredFiles: state.filteredFiles,
|
|
375
|
+
selectedFile,
|
|
376
|
+
selectedIndex: selectedFile === null ? null : selectedIndex
|
|
377
|
+
};
|
|
378
|
+
};
|
|
379
|
+
var initialState = (options) => {
|
|
380
|
+
assertUniqueIds(options.files, options.getId);
|
|
381
|
+
const filteredFiles = options.filter(options.files, options.query);
|
|
382
|
+
if (filteredFiles.length === 0) {
|
|
383
|
+
return {
|
|
384
|
+
appliedQuery: options.query,
|
|
385
|
+
filteredFiles,
|
|
386
|
+
selectedId: null,
|
|
387
|
+
priorIndex: 0,
|
|
388
|
+
autoSelect: options.query.length > 0
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
const initialIndex = options.query.length === 0 && options.initialSelectedId != null ? indexOfId(filteredFiles, options.initialSelectedId, options.getId) : -1;
|
|
392
|
+
const selectedIndex = initialIndex >= 0 ? initialIndex : 0;
|
|
393
|
+
return {
|
|
394
|
+
appliedQuery: options.query,
|
|
395
|
+
filteredFiles,
|
|
396
|
+
selectedId: options.getId(filteredFiles[selectedIndex]),
|
|
397
|
+
priorIndex: selectedIndex,
|
|
398
|
+
autoSelect: false
|
|
399
|
+
};
|
|
400
|
+
};
|
|
401
|
+
var useFileNavigator = ({
|
|
402
|
+
files,
|
|
403
|
+
query,
|
|
404
|
+
getId,
|
|
405
|
+
getPath,
|
|
406
|
+
filter,
|
|
407
|
+
initialSelectedId,
|
|
408
|
+
debounceMs = 50
|
|
409
|
+
}) => {
|
|
410
|
+
const stateRef = useRef(null);
|
|
411
|
+
let currentState = stateRef.current;
|
|
412
|
+
if (currentState === null) {
|
|
413
|
+
currentState = initialState({
|
|
414
|
+
files,
|
|
415
|
+
query,
|
|
416
|
+
getId,
|
|
417
|
+
getPath,
|
|
418
|
+
filter,
|
|
419
|
+
...initialSelectedId === undefined ? {} : { initialSelectedId },
|
|
420
|
+
debounceMs
|
|
421
|
+
});
|
|
422
|
+
stateRef.current = currentState;
|
|
423
|
+
}
|
|
424
|
+
const [, render] = useReducer((version) => version + 1, 0);
|
|
425
|
+
const timerRef = useRef(null);
|
|
426
|
+
const filesRef = useRef(files);
|
|
427
|
+
const getIdRef = useRef(getId);
|
|
428
|
+
const getPathRef = useRef(getPath);
|
|
429
|
+
const filterRef = useRef(filter);
|
|
430
|
+
const revisionRef = useRef(0);
|
|
431
|
+
const renderRevision = revisionRef.current;
|
|
432
|
+
assertUniqueIds(files, getId);
|
|
433
|
+
const renderCandidate = reconcile(currentState, filter(files, currentState.appliedQuery), getId);
|
|
434
|
+
const cancelTimer = () => {
|
|
435
|
+
if (timerRef.current === null)
|
|
436
|
+
return;
|
|
437
|
+
clearTimeout(timerRef.current);
|
|
438
|
+
timerRef.current = null;
|
|
439
|
+
};
|
|
440
|
+
const getSnapshot = () => snapshotOf(stateRef.current, getIdRef.current);
|
|
441
|
+
const applySearch = (nextQuery) => {
|
|
442
|
+
cancelTimer();
|
|
443
|
+
assertUniqueIds(filesRef.current, getIdRef.current);
|
|
444
|
+
const current = stateRef.current;
|
|
445
|
+
const queryChanged = current.appliedQuery !== nextQuery;
|
|
446
|
+
stateRef.current = reconcile({
|
|
447
|
+
...current,
|
|
448
|
+
appliedQuery: nextQuery,
|
|
449
|
+
autoSelect: queryChanged ? true : current.autoSelect
|
|
450
|
+
}, filterRef.current(filesRef.current, nextQuery), getIdRef.current);
|
|
451
|
+
revisionRef.current += 1;
|
|
452
|
+
render();
|
|
453
|
+
return getSnapshot();
|
|
454
|
+
};
|
|
455
|
+
const selectIndex = (index) => {
|
|
456
|
+
const current = stateRef.current;
|
|
457
|
+
if (current.filteredFiles.length === 0) {
|
|
458
|
+
stateRef.current = { ...current, selectedId: null };
|
|
459
|
+
} else {
|
|
460
|
+
const nextIndex = clamp(index, 0, current.filteredFiles.length - 1);
|
|
461
|
+
stateRef.current = {
|
|
462
|
+
...current,
|
|
463
|
+
selectedId: getIdRef.current(current.filteredFiles[nextIndex]),
|
|
464
|
+
priorIndex: nextIndex
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
revisionRef.current += 1;
|
|
468
|
+
render();
|
|
469
|
+
return getSnapshot();
|
|
470
|
+
};
|
|
471
|
+
const selectId = (id) => {
|
|
472
|
+
const current = stateRef.current;
|
|
473
|
+
const index = indexOfId(current.filteredFiles, id, getIdRef.current);
|
|
474
|
+
if (index < 0)
|
|
475
|
+
return getSnapshot();
|
|
476
|
+
stateRef.current = { ...current, selectedId: id, priorIndex: index };
|
|
477
|
+
revisionRef.current += 1;
|
|
478
|
+
render();
|
|
479
|
+
return getSnapshot();
|
|
480
|
+
};
|
|
481
|
+
useLayoutEffect(() => {
|
|
482
|
+
filesRef.current = files;
|
|
483
|
+
getIdRef.current = getId;
|
|
484
|
+
getPathRef.current = getPath;
|
|
485
|
+
filterRef.current = filter;
|
|
486
|
+
stateRef.current = revisionRef.current === renderRevision ? renderCandidate : reconcile(stateRef.current, filter(files, stateRef.current.appliedQuery), getId);
|
|
487
|
+
revisionRef.current += 1;
|
|
488
|
+
});
|
|
489
|
+
useEffect2(() => {
|
|
490
|
+
cancelTimer();
|
|
491
|
+
if (query === stateRef.current.appliedQuery)
|
|
492
|
+
return;
|
|
493
|
+
timerRef.current = setTimeout(() => applySearch(query), debounceMs);
|
|
494
|
+
return cancelTimer;
|
|
495
|
+
}, [debounceMs, query]);
|
|
496
|
+
useEffect2(() => cancelTimer, []);
|
|
497
|
+
const snapshot = snapshotOf(renderCandidate, getId);
|
|
498
|
+
return {
|
|
499
|
+
...snapshot,
|
|
500
|
+
getId,
|
|
501
|
+
getPath,
|
|
502
|
+
getSnapshot,
|
|
503
|
+
flushSearch: applySearch,
|
|
504
|
+
cancelAutoSelect: () => {
|
|
505
|
+
stateRef.current = { ...stateRef.current, autoSelect: false };
|
|
506
|
+
revisionRef.current += 1;
|
|
507
|
+
},
|
|
508
|
+
selectIndex,
|
|
509
|
+
selectId,
|
|
510
|
+
moveBy: (delta) => selectIndex((getSnapshot().selectedIndex ?? 0) + delta),
|
|
511
|
+
selectFirst: () => selectIndex(0),
|
|
512
|
+
selectLast: () => selectIndex(stateRef.current.filteredFiles.length - 1)
|
|
513
|
+
};
|
|
514
|
+
};
|
|
515
|
+
// src/Browser.tsx
|
|
102
516
|
import { useKeyboard, useRenderer, useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
|
|
103
517
|
import { useAtomValue, useAtomSet } from "@effect/atom-react";
|
|
104
518
|
import { Effect as Effect3 } from "effect";
|
|
105
|
-
import {
|
|
519
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useReducer as useReducer2, useRef as useRef3, useState as useState4 } from "react";
|
|
106
520
|
|
|
107
521
|
// src/keymap/browser.ts
|
|
108
522
|
var JUMP = 8;
|
|
109
|
-
var clamp = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
110
|
-
var lastIndex = (c) => Math.max(0, c.files.length - 1);
|
|
111
523
|
var haveFiles = (c) => c.files.length > 0;
|
|
112
524
|
var hasSelected = (c) => c.hasSelected;
|
|
113
|
-
var stepBy = (c, delta) => c.setSelectedIndex((i) => clamp(i + delta, 0, lastIndex(c)));
|
|
114
525
|
var inSidebar = (c) => c.focus === "sidebar";
|
|
115
526
|
var filterClosed = (c) => !c.filterOpen;
|
|
116
527
|
var paletteClosed = (c) => !c.paletteOpen;
|
|
@@ -215,7 +626,7 @@ var browserBindings = [
|
|
|
215
626
|
description: "Move selection down",
|
|
216
627
|
keys: ["j", "down"],
|
|
217
628
|
when: inSidebarWithFiles,
|
|
218
|
-
run: (c) =>
|
|
629
|
+
run: (c) => c.moveSelectionBy(1)
|
|
219
630
|
},
|
|
220
631
|
{
|
|
221
632
|
id: "sidebar.up",
|
|
@@ -223,7 +634,7 @@ var browserBindings = [
|
|
|
223
634
|
description: "Move selection up",
|
|
224
635
|
keys: ["k", "up"],
|
|
225
636
|
when: inSidebarWithFiles,
|
|
226
|
-
run: (c) =>
|
|
637
|
+
run: (c) => c.moveSelectionBy(-1)
|
|
227
638
|
},
|
|
228
639
|
{
|
|
229
640
|
id: "sidebar.jumpDown",
|
|
@@ -231,7 +642,7 @@ var browserBindings = [
|
|
|
231
642
|
description: `Jump down ${JUMP}`,
|
|
232
643
|
keys: ["shift+j"],
|
|
233
644
|
when: inSidebarWithFiles,
|
|
234
|
-
run: (c) =>
|
|
645
|
+
run: (c) => c.moveSelectionBy(JUMP)
|
|
235
646
|
},
|
|
236
647
|
{
|
|
237
648
|
id: "sidebar.jumpUp",
|
|
@@ -239,7 +650,7 @@ var browserBindings = [
|
|
|
239
650
|
description: `Jump up ${JUMP}`,
|
|
240
651
|
keys: ["shift+k"],
|
|
241
652
|
when: inSidebarWithFiles,
|
|
242
|
-
run: (c) =>
|
|
653
|
+
run: (c) => c.moveSelectionBy(-JUMP)
|
|
243
654
|
},
|
|
244
655
|
{
|
|
245
656
|
id: "sidebar.pageDown",
|
|
@@ -247,7 +658,7 @@ var browserBindings = [
|
|
|
247
658
|
description: "Page down",
|
|
248
659
|
keys: ["space", "pagedown", "ctrl+d"],
|
|
249
660
|
when: inSidebarWithFiles,
|
|
250
|
-
run: (c) =>
|
|
661
|
+
run: (c) => c.moveSelectionBy(JUMP)
|
|
251
662
|
},
|
|
252
663
|
{
|
|
253
664
|
id: "sidebar.pageUp",
|
|
@@ -255,7 +666,7 @@ var browserBindings = [
|
|
|
255
666
|
description: "Page up",
|
|
256
667
|
keys: ["b", "pageup", "ctrl+u"],
|
|
257
668
|
when: inSidebarWithFiles,
|
|
258
|
-
run: (c) =>
|
|
669
|
+
run: (c) => c.moveSelectionBy(-JUMP)
|
|
259
670
|
},
|
|
260
671
|
{
|
|
261
672
|
id: "sidebar.top",
|
|
@@ -263,7 +674,7 @@ var browserBindings = [
|
|
|
263
674
|
description: "Jump to first file",
|
|
264
675
|
keys: ["g"],
|
|
265
676
|
when: inSidebarWithFiles,
|
|
266
|
-
run: (c) => c.
|
|
677
|
+
run: (c) => c.selectFirst()
|
|
267
678
|
},
|
|
268
679
|
{
|
|
269
680
|
id: "sidebar.bottom",
|
|
@@ -271,7 +682,7 @@ var browserBindings = [
|
|
|
271
682
|
description: "Jump to last file",
|
|
272
683
|
keys: ["shift+g"],
|
|
273
684
|
when: inSidebarWithFiles,
|
|
274
|
-
run: (c) => c.
|
|
685
|
+
run: (c) => c.selectLast()
|
|
275
686
|
},
|
|
276
687
|
{
|
|
277
688
|
id: "sidebar.open",
|
|
@@ -303,7 +714,7 @@ var browserBindings = [
|
|
|
303
714
|
description: "Prev file",
|
|
304
715
|
keys: ["["],
|
|
305
716
|
when: inReaderWithSibling,
|
|
306
|
-
run: (c) =>
|
|
717
|
+
run: (c) => c.moveSelectionBy(-1)
|
|
307
718
|
},
|
|
308
719
|
{
|
|
309
720
|
id: "reader.nextFile",
|
|
@@ -311,7 +722,7 @@ var browserBindings = [
|
|
|
311
722
|
description: "Next file",
|
|
312
723
|
keys: ["]"],
|
|
313
724
|
when: inReaderWithSibling,
|
|
314
|
-
run: (c) =>
|
|
725
|
+
run: (c) => c.moveSelectionBy(1)
|
|
315
726
|
},
|
|
316
727
|
{
|
|
317
728
|
id: "reader.back",
|
|
@@ -614,7 +1025,7 @@ var setActiveTheme = (definition, tone) => {
|
|
|
614
1025
|
};
|
|
615
1026
|
|
|
616
1027
|
// src/PromptRow.tsx
|
|
617
|
-
import { jsxDEV } from "@opentui/react/jsx-dev-runtime";
|
|
1028
|
+
import { jsxDEV as jsxDEV4 } from "@opentui/react/jsx-dev-runtime";
|
|
618
1029
|
var PREFIX = "> ";
|
|
619
1030
|
var CURSOR = "\u258F";
|
|
620
1031
|
var PromptRow = ({ query, editing, placeholder = "", width }) => {
|
|
@@ -623,14 +1034,14 @@ var PromptRow = ({ query, editing, placeholder = "", width }) => {
|
|
|
623
1034
|
const bodyFg = editing ? colors.primary : query.length > 0 ? colors.text : colors.textMuted;
|
|
624
1035
|
const body = rawBody.length <= bodyBudget ? rawBody : editing ? "\u2026" + rawBody.slice(rawBody.length - bodyBudget + 1) : rawBody.slice(0, bodyBudget - 1) + "\u2026";
|
|
625
1036
|
const prefixFg = editing ? colors.secondary : colors.primary;
|
|
626
|
-
return /* @__PURE__ */
|
|
1037
|
+
return /* @__PURE__ */ jsxDEV4("text", {
|
|
627
1038
|
wrapMode: "none",
|
|
628
1039
|
children: [
|
|
629
|
-
/* @__PURE__ */
|
|
1040
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
630
1041
|
style: { fg: prefixFg },
|
|
631
1042
|
children: PREFIX
|
|
632
1043
|
}, undefined, false, undefined, this),
|
|
633
|
-
/* @__PURE__ */
|
|
1044
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
634
1045
|
style: { fg: bodyFg },
|
|
635
1046
|
children: body
|
|
636
1047
|
}, undefined, false, undefined, this)
|
|
@@ -639,7 +1050,7 @@ var PromptRow = ({ query, editing, placeholder = "", width }) => {
|
|
|
639
1050
|
};
|
|
640
1051
|
|
|
641
1052
|
// src/CommandPalette.tsx
|
|
642
|
-
import { jsxDEV as
|
|
1053
|
+
import { jsxDEV as jsxDEV5 } from "@opentui/react/jsx-dev-runtime";
|
|
643
1054
|
var SCRIM = RGBA.fromInts(0, 0, 0, 150);
|
|
644
1055
|
var FOOTER_HINT = "\u2191\u2193 select enter run esc close";
|
|
645
1056
|
var CATEGORY_ORDER = ["Navigation", "View", "File", "Appearance", "App"];
|
|
@@ -709,7 +1120,7 @@ var CommandPalette = ({
|
|
|
709
1120
|
const titleWidth = Math.max(8, rowWidth - 2 - SHORTCUT_WIDTH - 1);
|
|
710
1121
|
const fit = (s, width) => s.length === width ? s : s.length > width ? s.slice(0, Math.max(0, width - 1)) + "\u2026" : s + " ".repeat(width - s.length);
|
|
711
1122
|
const fitRight = (s, width) => s.length >= width ? s.slice(0, width) : " ".repeat(width - s.length) + s;
|
|
712
|
-
return /* @__PURE__ */
|
|
1123
|
+
return /* @__PURE__ */ jsxDEV5("box", {
|
|
713
1124
|
position: "absolute",
|
|
714
1125
|
left: 0,
|
|
715
1126
|
top: 0,
|
|
@@ -717,7 +1128,7 @@ var CommandPalette = ({
|
|
|
717
1128
|
height: viewportHeight,
|
|
718
1129
|
zIndex: 20,
|
|
719
1130
|
style: { backgroundColor: SCRIM },
|
|
720
|
-
children: /* @__PURE__ */
|
|
1131
|
+
children: /* @__PURE__ */ jsxDEV5("box", {
|
|
721
1132
|
position: "absolute",
|
|
722
1133
|
left,
|
|
723
1134
|
top,
|
|
@@ -734,26 +1145,26 @@ var CommandPalette = ({
|
|
|
734
1145
|
backgroundColor: colors.backgroundPanel
|
|
735
1146
|
},
|
|
736
1147
|
children: [
|
|
737
|
-
/* @__PURE__ */
|
|
1148
|
+
/* @__PURE__ */ jsxDEV5(PromptRow, {
|
|
738
1149
|
query,
|
|
739
1150
|
editing: true,
|
|
740
1151
|
width: rowWidth
|
|
741
1152
|
}, undefined, false, undefined, this),
|
|
742
|
-
/* @__PURE__ */
|
|
1153
|
+
/* @__PURE__ */ jsxDEV5("text", {
|
|
743
1154
|
content: " "
|
|
744
1155
|
}, undefined, false, undefined, this),
|
|
745
|
-
commands.length === 0 ? /* @__PURE__ */
|
|
1156
|
+
commands.length === 0 ? /* @__PURE__ */ jsxDEV5("text", {
|
|
746
1157
|
wrapMode: "none",
|
|
747
1158
|
content: " (no matches)",
|
|
748
1159
|
style: { fg: colors.textMuted }
|
|
749
1160
|
}, undefined, false, undefined, this) : visible.map((row) => {
|
|
750
1161
|
if (row.kind === "spacer") {
|
|
751
|
-
return /* @__PURE__ */
|
|
1162
|
+
return /* @__PURE__ */ jsxDEV5("text", {
|
|
752
1163
|
content: " "
|
|
753
1164
|
}, row.key, false, undefined, this);
|
|
754
1165
|
}
|
|
755
1166
|
if (row.kind === "header") {
|
|
756
|
-
return /* @__PURE__ */
|
|
1167
|
+
return /* @__PURE__ */ jsxDEV5("text", {
|
|
757
1168
|
wrapMode: "none",
|
|
758
1169
|
content: fit(row.text, rowWidth),
|
|
759
1170
|
style: { fg: colors.textMuted, attributes: 1 }
|
|
@@ -765,25 +1176,25 @@ var CommandPalette = ({
|
|
|
765
1176
|
const titleText = fit(cmd.title, titleWidth);
|
|
766
1177
|
const shortcutText = cmd.shortcut ? fitRight(cmd.shortcut, SHORTCUT_WIDTH) : " ".repeat(SHORTCUT_WIDTH);
|
|
767
1178
|
const titleFg = isSelected ? colors.primary : colors.text;
|
|
768
|
-
return /* @__PURE__ */
|
|
1179
|
+
return /* @__PURE__ */ jsxDEV5("text", {
|
|
769
1180
|
wrapMode: "none",
|
|
770
1181
|
style: isSelected ? { bg: colors.backgroundElement } : {},
|
|
771
1182
|
children: [
|
|
772
|
-
/* @__PURE__ */
|
|
1183
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
773
1184
|
style: { fg: titleFg },
|
|
774
1185
|
children: `${selector}${titleText} `
|
|
775
1186
|
}, undefined, false, undefined, this),
|
|
776
|
-
/* @__PURE__ */
|
|
1187
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
777
1188
|
style: { fg: colors.textMuted },
|
|
778
1189
|
children: shortcutText
|
|
779
1190
|
}, undefined, false, undefined, this)
|
|
780
1191
|
]
|
|
781
1192
|
}, cmd.id, true, undefined, this);
|
|
782
1193
|
}),
|
|
783
|
-
/* @__PURE__ */
|
|
1194
|
+
/* @__PURE__ */ jsxDEV5("text", {
|
|
784
1195
|
content: " "
|
|
785
1196
|
}, undefined, false, undefined, this),
|
|
786
|
-
/* @__PURE__ */
|
|
1197
|
+
/* @__PURE__ */ jsxDEV5("text", {
|
|
787
1198
|
wrapMode: "none",
|
|
788
1199
|
content: fit(FOOTER_HINT, rowWidth),
|
|
789
1200
|
style: { fg: colors.textMuted }
|
|
@@ -951,8 +1362,8 @@ var displayKey = (raw) => {
|
|
|
951
1362
|
};
|
|
952
1363
|
|
|
953
1364
|
// src/Spinner.tsx
|
|
954
|
-
import { useEffect, useRef, useState } from "react";
|
|
955
|
-
import { jsxDEV as
|
|
1365
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState2 } from "react";
|
|
1366
|
+
import { jsxDEV as jsxDEV6 } from "@opentui/react/jsx-dev-runtime";
|
|
956
1367
|
var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
957
1368
|
var FRAME_COUNT = FRAMES.length;
|
|
958
1369
|
var normalizeFrameIndex = (index) => (index % FRAME_COUNT + FRAME_COUNT) % FRAME_COUNT;
|
|
@@ -962,12 +1373,12 @@ var Spinner = ({
|
|
|
962
1373
|
initialFrameIndex = 0,
|
|
963
1374
|
registerTick = null
|
|
964
1375
|
}) => {
|
|
965
|
-
const [index, setIndex] =
|
|
966
|
-
const tickRef =
|
|
1376
|
+
const [index, setIndex] = useState2(() => normalizeFrameIndex(initialFrameIndex));
|
|
1377
|
+
const tickRef = useRef2(() => {
|
|
967
1378
|
return;
|
|
968
1379
|
});
|
|
969
1380
|
tickRef.current = () => setIndex((prev) => (prev + 1) % FRAME_COUNT);
|
|
970
|
-
|
|
1381
|
+
useEffect3(() => {
|
|
971
1382
|
if (registerTick) {
|
|
972
1383
|
registerTick(() => tickRef.current());
|
|
973
1384
|
return;
|
|
@@ -977,7 +1388,7 @@ var Spinner = ({
|
|
|
977
1388
|
}, intervalMs);
|
|
978
1389
|
return () => clearInterval(id);
|
|
979
1390
|
}, [intervalMs, registerTick]);
|
|
980
|
-
return /* @__PURE__ */
|
|
1391
|
+
return /* @__PURE__ */ jsxDEV6("text", {
|
|
981
1392
|
content: FRAMES[index] ?? FRAMES[0],
|
|
982
1393
|
wrapMode: "none",
|
|
983
1394
|
style: { fg }
|
|
@@ -985,7 +1396,7 @@ var Spinner = ({
|
|
|
985
1396
|
};
|
|
986
1397
|
|
|
987
1398
|
// src/StatusIndicator.tsx
|
|
988
|
-
import { jsxDEV as
|
|
1399
|
+
import { jsxDEV as jsxDEV7 } from "@opentui/react/jsx-dev-runtime";
|
|
989
1400
|
var statusIndicatorFg = (variant) => {
|
|
990
1401
|
switch (variant) {
|
|
991
1402
|
case "info":
|
|
@@ -1006,7 +1417,7 @@ var StatusIndicator = ({
|
|
|
1006
1417
|
}) => {
|
|
1007
1418
|
const activeColor = statusIndicatorFg(variant);
|
|
1008
1419
|
const backgroundColor = active ? activeColor : colors.backgroundElement;
|
|
1009
|
-
return /* @__PURE__ */
|
|
1420
|
+
return /* @__PURE__ */ jsxDEV7("box", {
|
|
1010
1421
|
...onMouseUp === undefined ? {} : { onMouseUp },
|
|
1011
1422
|
style: {
|
|
1012
1423
|
width: 3,
|
|
@@ -1014,7 +1425,7 @@ var StatusIndicator = ({
|
|
|
1014
1425
|
flexDirection: "row",
|
|
1015
1426
|
backgroundColor
|
|
1016
1427
|
},
|
|
1017
|
-
children: /* @__PURE__ */
|
|
1428
|
+
children: /* @__PURE__ */ jsxDEV7("text", {
|
|
1018
1429
|
content: ` ${icon} `,
|
|
1019
1430
|
wrapMode: "none",
|
|
1020
1431
|
style: {
|
|
@@ -1027,7 +1438,7 @@ var StatusIndicator = ({
|
|
|
1027
1438
|
};
|
|
1028
1439
|
|
|
1029
1440
|
// src/Footer.tsx
|
|
1030
|
-
import { jsxDEV as
|
|
1441
|
+
import { jsxDEV as jsxDEV8 } from "@opentui/react/jsx-dev-runtime";
|
|
1031
1442
|
var FOOTER_HEIGHT = 1;
|
|
1032
1443
|
var normalizeStatusLine = (status) => status.replace(/\s+/g, " ").trim();
|
|
1033
1444
|
var HINT_SEPARATOR = " ";
|
|
@@ -1117,17 +1528,17 @@ var Footer = ({
|
|
|
1117
1528
|
const statusContent = status ? status.slice(0, Math.max(0, statusBudget - statusChromeWidth)) : "";
|
|
1118
1529
|
const statusSeparatorContent = status ? STATUS_SEPARATOR.slice(0, Math.max(0, statusBudget - nonWarningStatusPrefixBudget - statusContent.length)) : "";
|
|
1119
1530
|
const noticeContent = notice ? notice.length > contentBudget ? notice.slice(0, contentBudget) : notice : null;
|
|
1120
|
-
const renderIndicators = () => renderedIndicators.map(({ id, ...props }) => /* @__PURE__ */
|
|
1531
|
+
const renderIndicators = () => renderedIndicators.map(({ id, ...props }) => /* @__PURE__ */ jsxDEV8(StatusIndicator, {
|
|
1121
1532
|
...props
|
|
1122
1533
|
}, id, false, undefined, this));
|
|
1123
|
-
const renderIndicatorContentGap = () => indicatorContentGapBudget > 0 ? /* @__PURE__ */
|
|
1534
|
+
const renderIndicatorContentGap = () => indicatorContentGapBudget > 0 ? /* @__PURE__ */ jsxDEV8("text", {
|
|
1124
1535
|
content: " ",
|
|
1125
1536
|
wrapMode: "none",
|
|
1126
1537
|
style: { fg: colors.textMuted }
|
|
1127
1538
|
}, undefined, false, undefined, this) : null;
|
|
1128
1539
|
const renderHints = () => visibleHints.flatMap((h, i) => {
|
|
1129
1540
|
const sep = i > 0 ? [
|
|
1130
|
-
/* @__PURE__ */
|
|
1541
|
+
/* @__PURE__ */ jsxDEV8("text", {
|
|
1131
1542
|
content: HINT_SEPARATOR,
|
|
1132
1543
|
wrapMode: "none",
|
|
1133
1544
|
style: { fg: colors.textMuted }
|
|
@@ -1135,12 +1546,12 @@ var Footer = ({
|
|
|
1135
1546
|
] : [];
|
|
1136
1547
|
return [
|
|
1137
1548
|
...sep,
|
|
1138
|
-
/* @__PURE__ */
|
|
1549
|
+
/* @__PURE__ */ jsxDEV8("text", {
|
|
1139
1550
|
content: h.key,
|
|
1140
1551
|
wrapMode: "none",
|
|
1141
1552
|
style: { fg: colors.text }
|
|
1142
1553
|
}, `k${i}`, false, undefined, this),
|
|
1143
|
-
/* @__PURE__ */
|
|
1554
|
+
/* @__PURE__ */ jsxDEV8("text", {
|
|
1144
1555
|
content: ` ${h.label}`,
|
|
1145
1556
|
wrapMode: "none",
|
|
1146
1557
|
style: { fg: colors.textMuted }
|
|
@@ -1148,12 +1559,12 @@ var Footer = ({
|
|
|
1148
1559
|
];
|
|
1149
1560
|
});
|
|
1150
1561
|
if (noticeContent !== null) {
|
|
1151
|
-
return /* @__PURE__ */
|
|
1562
|
+
return /* @__PURE__ */ jsxDEV8("box", {
|
|
1152
1563
|
style: rowStyle,
|
|
1153
1564
|
children: [
|
|
1154
1565
|
renderIndicators(),
|
|
1155
1566
|
renderIndicatorContentGap(),
|
|
1156
|
-
/* @__PURE__ */
|
|
1567
|
+
/* @__PURE__ */ jsxDEV8("text", {
|
|
1157
1568
|
content: noticeContent,
|
|
1158
1569
|
wrapMode: "none",
|
|
1159
1570
|
style: { fg: colors.primary }
|
|
@@ -1168,25 +1579,25 @@ var Footer = ({
|
|
|
1168
1579
|
...discoverySpinnerInitialFrameIndex === undefined ? {} : { initialFrameIndex: discoverySpinnerInitialFrameIndex },
|
|
1169
1580
|
...discoverySpinnerRegisterTick === undefined ? {} : { registerTick: discoverySpinnerRegisterTick }
|
|
1170
1581
|
};
|
|
1171
|
-
return /* @__PURE__ */
|
|
1582
|
+
return /* @__PURE__ */ jsxDEV8("box", {
|
|
1172
1583
|
style: rowStyle,
|
|
1173
1584
|
children: [
|
|
1174
1585
|
renderIndicators(),
|
|
1175
1586
|
renderIndicatorContentGap(),
|
|
1176
|
-
nonWarningStatusPrefixBudget >= 1 ? /* @__PURE__ */
|
|
1587
|
+
nonWarningStatusPrefixBudget >= 1 ? /* @__PURE__ */ jsxDEV8(Spinner, {
|
|
1177
1588
|
...spinnerProps
|
|
1178
1589
|
}, undefined, false, undefined, this) : null,
|
|
1179
|
-
nonWarningStatusPrefixBudget >= 2 ? /* @__PURE__ */
|
|
1590
|
+
nonWarningStatusPrefixBudget >= 2 ? /* @__PURE__ */ jsxDEV8("text", {
|
|
1180
1591
|
content: " ",
|
|
1181
1592
|
wrapMode: "none",
|
|
1182
1593
|
style: { fg: colors.textMuted }
|
|
1183
1594
|
}, undefined, false, undefined, this) : null,
|
|
1184
|
-
isPartialWarning ? null : /* @__PURE__ */
|
|
1595
|
+
isPartialWarning ? null : /* @__PURE__ */ jsxDEV8("text", {
|
|
1185
1596
|
content: statusContent,
|
|
1186
1597
|
wrapMode: "none",
|
|
1187
1598
|
style: { fg: colors.secondary }
|
|
1188
1599
|
}, undefined, false, undefined, this),
|
|
1189
|
-
statusSeparatorContent.length > 0 && /* @__PURE__ */
|
|
1600
|
+
statusSeparatorContent.length > 0 && /* @__PURE__ */ jsxDEV8("text", {
|
|
1190
1601
|
content: statusSeparatorContent,
|
|
1191
1602
|
wrapMode: "none",
|
|
1192
1603
|
style: { fg: colors.textMuted }
|
|
@@ -1195,7 +1606,7 @@ var Footer = ({
|
|
|
1195
1606
|
]
|
|
1196
1607
|
}, undefined, true, undefined, this);
|
|
1197
1608
|
}
|
|
1198
|
-
return /* @__PURE__ */
|
|
1609
|
+
return /* @__PURE__ */ jsxDEV8("box", {
|
|
1199
1610
|
style: rowStyle,
|
|
1200
1611
|
children: [
|
|
1201
1612
|
renderIndicators(),
|
|
@@ -1206,7 +1617,7 @@ var Footer = ({
|
|
|
1206
1617
|
};
|
|
1207
1618
|
|
|
1208
1619
|
// src/ui/middleTruncate.ts
|
|
1209
|
-
var
|
|
1620
|
+
var middleTruncate2 = (value, width, options = {}) => {
|
|
1210
1621
|
const ellipsis = options.ellipsis ?? "\u2026";
|
|
1211
1622
|
if (width <= 0)
|
|
1212
1623
|
return "";
|
|
@@ -1221,7 +1632,7 @@ var middleTruncate = (value, width, options = {}) => {
|
|
|
1221
1632
|
};
|
|
1222
1633
|
|
|
1223
1634
|
// src/Header.tsx
|
|
1224
|
-
import { jsxDEV as
|
|
1635
|
+
import { jsxDEV as jsxDEV9 } from "@opentui/react/jsx-dev-runtime";
|
|
1225
1636
|
var HEADER_HEIGHT = 1;
|
|
1226
1637
|
var FILE_SEPARATOR = " \xB7 ";
|
|
1227
1638
|
var HEADER_HORIZONTAL_PADDING = 2;
|
|
@@ -1248,7 +1659,7 @@ var layoutHeaderSegments = ({
|
|
|
1248
1659
|
const rootWidth = rootSegment === null ? 0 : usableWidth - joinedLength(segments) - FILE_SEPARATOR.length - HEADER_GROUP_GAP - right.length;
|
|
1249
1660
|
if (root !== null && root.length > rootWidth && rootWidth >= MIN_TRUNCATED_ROOT_WIDTH) {
|
|
1250
1661
|
return {
|
|
1251
|
-
left: [...segments, { id: "root", text:
|
|
1662
|
+
left: [...segments, { id: "root", text: middleTruncate2(root, rootWidth), tone: "muted" }],
|
|
1252
1663
|
right
|
|
1253
1664
|
};
|
|
1254
1665
|
}
|
|
@@ -1263,7 +1674,7 @@ var layoutHeaderSegments = ({
|
|
|
1263
1674
|
const fileWidth = usableWidth - BRAND.length - FILE_SEPARATOR.length;
|
|
1264
1675
|
if (fileWidth > 0) {
|
|
1265
1676
|
return {
|
|
1266
|
-
left: [iconBrand, { id: "file", text:
|
|
1677
|
+
left: [iconBrand, { id: "file", text: middleTruncate2(file, fileWidth), tone: "primary" }],
|
|
1267
1678
|
right: null
|
|
1268
1679
|
};
|
|
1269
1680
|
}
|
|
@@ -1277,7 +1688,7 @@ var fits = (segments, right, usableWidth) => {
|
|
|
1277
1688
|
};
|
|
1278
1689
|
var Header = ({ width, currentFile, rootLabel, version = package_default.version }) => {
|
|
1279
1690
|
const layout = layoutHeaderSegments({ width, currentFile, rootLabel, version });
|
|
1280
|
-
return /* @__PURE__ */
|
|
1691
|
+
return /* @__PURE__ */ jsxDEV9("box", {
|
|
1281
1692
|
style: {
|
|
1282
1693
|
width,
|
|
1283
1694
|
height: HEADER_HEIGHT,
|
|
@@ -1289,20 +1700,20 @@ var Header = ({ width, currentFile, rootLabel, version = package_default.version
|
|
|
1289
1700
|
backgroundColor: colors.backgroundPanel
|
|
1290
1701
|
},
|
|
1291
1702
|
children: [
|
|
1292
|
-
/* @__PURE__ */
|
|
1703
|
+
/* @__PURE__ */ jsxDEV9("text", {
|
|
1293
1704
|
wrapMode: "none",
|
|
1294
1705
|
children: layout.left.map((segment, idx) => [
|
|
1295
|
-
idx > 0 ? /* @__PURE__ */
|
|
1706
|
+
idx > 0 ? /* @__PURE__ */ jsxDEV9("span", {
|
|
1296
1707
|
style: { fg: colors.textMuted },
|
|
1297
1708
|
children: FILE_SEPARATOR
|
|
1298
1709
|
}, `${segment.id}-${idx}-separator`, false, undefined, this) : null,
|
|
1299
|
-
/* @__PURE__ */
|
|
1710
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
1300
1711
|
style: { fg: segment.tone === "primary" ? colors.text : colors.textMuted },
|
|
1301
1712
|
children: segment.text
|
|
1302
1713
|
}, `${segment.id}-${idx}`, false, undefined, this)
|
|
1303
1714
|
])
|
|
1304
1715
|
}, undefined, false, undefined, this),
|
|
1305
|
-
layout.right !== null && /* @__PURE__ */
|
|
1716
|
+
layout.right !== null && /* @__PURE__ */ jsxDEV9("text", {
|
|
1306
1717
|
content: layout.right,
|
|
1307
1718
|
wrapMode: "none",
|
|
1308
1719
|
style: { fg: colors.textMuted }
|
|
@@ -1509,55 +1920,56 @@ var resolveSidebarWidth = (viewport, preferred) => {
|
|
|
1509
1920
|
var defaultPreferredWidth = (viewport) => Math.max(SIDEBAR_MIN_WIDTH, Math.min(SIDEBAR_MAX_WIDTH, Math.floor(viewport * 0.25)));
|
|
1510
1921
|
var canFitInline = (viewport) => viewport >= SIDEBAR_MIN_WIDTH + DIVIDER_WIDTH + READER_MIN_WIDTH;
|
|
1511
1922
|
|
|
1512
|
-
// src/
|
|
1513
|
-
|
|
1514
|
-
var
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1923
|
+
// src/Sidebar.tsx
|
|
1924
|
+
import { jsxDEV as jsxDEV10 } from "@opentui/react/jsx-dev-runtime";
|
|
1925
|
+
var Sidebar = ({
|
|
1926
|
+
files,
|
|
1927
|
+
controller,
|
|
1928
|
+
filterInput,
|
|
1929
|
+
filterOpen,
|
|
1930
|
+
discoveryActive,
|
|
1931
|
+
rootLabel,
|
|
1932
|
+
viewportHeight,
|
|
1933
|
+
paneWidth,
|
|
1934
|
+
narrow,
|
|
1935
|
+
active,
|
|
1936
|
+
visible
|
|
1937
|
+
}) => {
|
|
1938
|
+
const headerVisible = files.length > 0 || discoveryActive;
|
|
1939
|
+
const emptyState = controller.filteredFiles.length > 0 ? undefined : files.length === 0 ? discoveryActive ? { label: "Scanning", value: "\u2026" } : { label: "No markdown files in", value: rootLabel } : { label: "No files match", value: controller.appliedQuery };
|
|
1940
|
+
const rowWidth = Math.max(4, paneWidth - (narrow ? 1 : 2));
|
|
1941
|
+
return /* @__PURE__ */ jsxDEV10(FileNavigator, {
|
|
1942
|
+
controller,
|
|
1943
|
+
width: paneWidth,
|
|
1944
|
+
paneHeight: Math.max(1, viewportHeight - HEADER_HEIGHT - FOOTER_HEIGHT),
|
|
1945
|
+
variant: narrow ? "stacked" : "inline",
|
|
1946
|
+
active,
|
|
1947
|
+
visible,
|
|
1948
|
+
theme: {
|
|
1949
|
+
background: colors.background,
|
|
1950
|
+
backgroundPanel: colors.backgroundPanel,
|
|
1951
|
+
backgroundElement: colors.backgroundElement,
|
|
1952
|
+
text: colors.text,
|
|
1953
|
+
textMuted: colors.textMuted,
|
|
1954
|
+
border: colors.border,
|
|
1955
|
+
selectedListItemText: colors.selectedListItemText
|
|
1956
|
+
},
|
|
1957
|
+
...headerVisible ? {
|
|
1958
|
+
header: /* @__PURE__ */ jsxDEV10(PromptRow, {
|
|
1959
|
+
query: filterInput,
|
|
1960
|
+
editing: filterOpen,
|
|
1961
|
+
placeholder: "type / to filter",
|
|
1962
|
+
width: rowWidth
|
|
1963
|
+
}, undefined, false, undefined, this)
|
|
1964
|
+
} : {},
|
|
1965
|
+
...emptyState === undefined ? {} : { emptyState }
|
|
1966
|
+
}, undefined, false, undefined, this);
|
|
1555
1967
|
};
|
|
1556
1968
|
|
|
1557
1969
|
// src/StatusPopover.tsx
|
|
1558
1970
|
import { useTerminalDimensions } from "@opentui/react";
|
|
1559
|
-
import { useMemo, useState as
|
|
1560
|
-
import { jsxDEV as
|
|
1971
|
+
import { useMemo, useState as useState3 } from "react";
|
|
1972
|
+
import { jsxDEV as jsxDEV11, Fragment as Fragment2 } from "@opentui/react/jsx-dev-runtime";
|
|
1561
1973
|
var clamp2 = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
1562
1974
|
var measureLine = (line) => line.length;
|
|
1563
1975
|
var wrapLine = (line, width) => {
|
|
@@ -1595,7 +2007,7 @@ var StatusPopoverPanel = ({
|
|
|
1595
2007
|
while (linesToRender.length < popoverHeight - 2)
|
|
1596
2008
|
linesToRender.push("");
|
|
1597
2009
|
const borderColor = statusIndicatorFg(variant);
|
|
1598
|
-
return /* @__PURE__ */
|
|
2010
|
+
return /* @__PURE__ */ jsxDEV11("box", {
|
|
1599
2011
|
position: "absolute",
|
|
1600
2012
|
left: 1,
|
|
1601
2013
|
top: Math.max(0, viewportHeight - popoverHeight - 2),
|
|
@@ -1609,15 +2021,15 @@ var StatusPopoverPanel = ({
|
|
|
1609
2021
|
flexDirection: "column"
|
|
1610
2022
|
},
|
|
1611
2023
|
children: [
|
|
1612
|
-
/* @__PURE__ */
|
|
2024
|
+
/* @__PURE__ */ jsxDEV11("text", {
|
|
1613
2025
|
content: ""
|
|
1614
2026
|
}, undefined, false, undefined, this),
|
|
1615
|
-
linesToRender.map((line, i) => /* @__PURE__ */
|
|
2027
|
+
linesToRender.map((line, i) => /* @__PURE__ */ jsxDEV11("text", {
|
|
1616
2028
|
content: line,
|
|
1617
2029
|
wrapMode: "none",
|
|
1618
2030
|
style: { fg: colors.text }
|
|
1619
2031
|
}, i, false, undefined, this)),
|
|
1620
|
-
/* @__PURE__ */
|
|
2032
|
+
/* @__PURE__ */ jsxDEV11("text", {
|
|
1621
2033
|
content: ""
|
|
1622
2034
|
}, undefined, false, undefined, this)
|
|
1623
2035
|
]
|
|
@@ -8362,8 +8774,10 @@ var saveThemePreference = async (record, path = defaultConfigPath()) => {
|
|
|
8362
8774
|
};
|
|
8363
8775
|
|
|
8364
8776
|
// src/Browser.tsx
|
|
8365
|
-
import { jsxDEV as
|
|
8777
|
+
import { jsxDEV as jsxDEV12 } from "@opentui/react/jsx-dev-runtime";
|
|
8366
8778
|
var defaultReadFile = (path) => Effect3.runPromise(readFileText(path));
|
|
8779
|
+
var getFileId = (file) => file.path;
|
|
8780
|
+
var getFilePath = (file) => file.relativePath;
|
|
8367
8781
|
var clamp3 = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
8368
8782
|
var nextReaderEmptyStateTipRotation = 0;
|
|
8369
8783
|
var FILTER_DEBOUNCE_MS = 50;
|
|
@@ -8382,43 +8796,6 @@ var floatingOverlayReducer = (state, action) => {
|
|
|
8382
8796
|
return state.kind === "status-popover" ? { kind: "status-popover", content: action.content } : state;
|
|
8383
8797
|
}
|
|
8384
8798
|
};
|
|
8385
|
-
var SidebarEmptyMessage = ({
|
|
8386
|
-
label,
|
|
8387
|
-
value,
|
|
8388
|
-
width,
|
|
8389
|
-
withTopSpacer
|
|
8390
|
-
}) => /* @__PURE__ */ jsxDEV8(Fragment2, {
|
|
8391
|
-
children: [
|
|
8392
|
-
withTopSpacer && /* @__PURE__ */ jsxDEV8("text", {
|
|
8393
|
-
content: ""
|
|
8394
|
-
}, undefined, false, undefined, this),
|
|
8395
|
-
/* @__PURE__ */ jsxDEV8("box", {
|
|
8396
|
-
style: {
|
|
8397
|
-
width,
|
|
8398
|
-
flexDirection: "row",
|
|
8399
|
-
flexWrap: "wrap",
|
|
8400
|
-
justifyContent: "center",
|
|
8401
|
-
gap: 1
|
|
8402
|
-
},
|
|
8403
|
-
children: [
|
|
8404
|
-
/* @__PURE__ */ jsxDEV8("text", {
|
|
8405
|
-
wrapMode: "none",
|
|
8406
|
-
children: /* @__PURE__ */ jsxDEV8("span", {
|
|
8407
|
-
style: { fg: colors.textMuted },
|
|
8408
|
-
children: label
|
|
8409
|
-
}, undefined, false, undefined, this)
|
|
8410
|
-
}, undefined, false, undefined, this),
|
|
8411
|
-
/* @__PURE__ */ jsxDEV8("text", {
|
|
8412
|
-
wrapMode: "none",
|
|
8413
|
-
children: /* @__PURE__ */ jsxDEV8("span", {
|
|
8414
|
-
style: { fg: colors.textMuted },
|
|
8415
|
-
children: `"${fitSidebarEmptyValue(value, width)}"`
|
|
8416
|
-
}, undefined, false, undefined, this)
|
|
8417
|
-
}, undefined, false, undefined, this)
|
|
8418
|
-
]
|
|
8419
|
-
}, undefined, true, undefined, this)
|
|
8420
|
-
]
|
|
8421
|
-
}, undefined, true, undefined, this);
|
|
8422
8799
|
var Browser = ({
|
|
8423
8800
|
files,
|
|
8424
8801
|
initialIndex = 0,
|
|
@@ -8447,20 +8824,29 @@ var Browser = ({
|
|
|
8447
8824
|
const theme = useAtomValue(themeAtom);
|
|
8448
8825
|
const setTheme = useAtomSet(themeAtom);
|
|
8449
8826
|
const syntaxStyle = useMemo2(() => SyntaxStyle.fromStyles(colors.syntax), [theme]);
|
|
8450
|
-
const [
|
|
8451
|
-
const [
|
|
8452
|
-
const [
|
|
8453
|
-
const [
|
|
8454
|
-
const [shown, setShown] = useState3(true);
|
|
8827
|
+
const [wrapEnabled, setWrapEnabled] = useState4(initialWrap);
|
|
8828
|
+
const [loaded, setLoaded] = useState4(null);
|
|
8829
|
+
const [error, setError] = useState4(null);
|
|
8830
|
+
const [shown, setShown] = useState4(true);
|
|
8455
8831
|
const startInFilter = startupFocus === "filter";
|
|
8456
8832
|
const initialFocus = startupFocus === null ? shown ? "sidebar" : "reader" : startupFocus === "reader" ? "reader" : "sidebar";
|
|
8457
|
-
const [focus, setFocus] =
|
|
8458
|
-
const [
|
|
8459
|
-
const [
|
|
8460
|
-
const [
|
|
8461
|
-
const
|
|
8462
|
-
|
|
8463
|
-
|
|
8833
|
+
const [focus, setFocus] = useState4(() => initialFocus);
|
|
8834
|
+
const [filterOpen, setFilterOpen] = useState4(startInFilter);
|
|
8835
|
+
const [filterInput, setFilterInput] = useState4(initialQuery);
|
|
8836
|
+
const initialSelectedIdRef = useRef3(files.length === 0 ? null : files[clamp3(initialIndex, 0, Math.max(0, files.length - 1))]?.path ?? null);
|
|
8837
|
+
const navigator = useFileNavigator({
|
|
8838
|
+
files,
|
|
8839
|
+
query: filterInput,
|
|
8840
|
+
getId: getFileId,
|
|
8841
|
+
getPath: getFilePath,
|
|
8842
|
+
filter: filterFiles,
|
|
8843
|
+
initialSelectedId: initialSelectedIdRef.current,
|
|
8844
|
+
debounceMs: filterDebounceMs
|
|
8845
|
+
});
|
|
8846
|
+
const displayedFiles = navigator.filteredFiles;
|
|
8847
|
+
const selected = navigator.selectedFile;
|
|
8848
|
+
const [floatingOverlay, dispatchFloatingOverlayState] = useReducer2(floatingOverlayReducer, noFloatingOverlay);
|
|
8849
|
+
const floatingOverlayRef = useRef3(noFloatingOverlay);
|
|
8464
8850
|
const dispatchFloatingOverlay = (action) => {
|
|
8465
8851
|
const next = floatingOverlayReducer(floatingOverlayRef.current, action);
|
|
8466
8852
|
floatingOverlayRef.current = next;
|
|
@@ -8470,29 +8856,27 @@ var Browser = ({
|
|
|
8470
8856
|
const paletteOpen = floatingOverlay.kind === "command-palette";
|
|
8471
8857
|
const activeStatusPopover = floatingOverlay.kind === "status-popover" ? floatingOverlay : null;
|
|
8472
8858
|
const discoveryWarningStatus = isPartialDiscoveryWarning2(discoveryStatus) ? discoveryStatus : null;
|
|
8473
|
-
const [paletteQuery, setPaletteQuery] =
|
|
8474
|
-
const [paletteIndex, setPaletteIndex] =
|
|
8475
|
-
const paletteQueryRef =
|
|
8476
|
-
const paletteIndexRef =
|
|
8477
|
-
const [readerEmptyStateTipRotation, setReaderEmptyStateTipRotation] =
|
|
8478
|
-
const readerEmptyStateVisibleRef =
|
|
8479
|
-
const filterOpenRef =
|
|
8480
|
-
const filterInputRef =
|
|
8481
|
-
const
|
|
8482
|
-
const
|
|
8483
|
-
const
|
|
8484
|
-
const restoreFilterOnSidebarFocusRef = useRef2(startInFilter);
|
|
8485
|
-
const [footerNotice, setFooterNoticeState] = useState3(null);
|
|
8859
|
+
const [paletteQuery, setPaletteQuery] = useState4("");
|
|
8860
|
+
const [paletteIndex, setPaletteIndex] = useState4(0);
|
|
8861
|
+
const paletteQueryRef = useRef3("");
|
|
8862
|
+
const paletteIndexRef = useRef3(0);
|
|
8863
|
+
const [readerEmptyStateTipRotation, setReaderEmptyStateTipRotation] = useState4(() => nextReaderEmptyStateTipRotation);
|
|
8864
|
+
const readerEmptyStateVisibleRef = useRef3(false);
|
|
8865
|
+
const filterOpenRef = useRef3(startInFilter);
|
|
8866
|
+
const filterInputRef = useRef3(initialQuery);
|
|
8867
|
+
const focusRef = useRef3(focus);
|
|
8868
|
+
const restoreFilterOnSidebarFocusRef = useRef3(startInFilter);
|
|
8869
|
+
const [footerNotice, setFooterNoticeState] = useState4(null);
|
|
8486
8870
|
const pushFooterNotice = (text, ttlMs = 2000) => setFooterNoticeState({ text, ttlMs });
|
|
8487
|
-
const serverRef =
|
|
8488
|
-
const pendingSelectionPathRef =
|
|
8489
|
-
|
|
8871
|
+
const serverRef = useRef3(null);
|
|
8872
|
+
const pendingSelectionPathRef = useRef3(null);
|
|
8873
|
+
useEffect4(() => {
|
|
8490
8874
|
return () => {
|
|
8491
8875
|
serverRef.current?.stop();
|
|
8492
8876
|
serverRef.current = null;
|
|
8493
8877
|
};
|
|
8494
8878
|
}, []);
|
|
8495
|
-
|
|
8879
|
+
useEffect4(() => {
|
|
8496
8880
|
if (footerNotice === null)
|
|
8497
8881
|
return;
|
|
8498
8882
|
closeFloatingOverlay();
|
|
@@ -8501,7 +8885,7 @@ var Browser = ({
|
|
|
8501
8885
|
const timer = setTimeout(() => setFooterNoticeState(null), footerNotice.ttlMs);
|
|
8502
8886
|
return () => clearTimeout(timer);
|
|
8503
8887
|
}, [disableFooterNoticeAutoClear, footerNotice]);
|
|
8504
|
-
|
|
8888
|
+
useEffect4(() => {
|
|
8505
8889
|
if (discoveryWarningStatus === null) {
|
|
8506
8890
|
if (floatingOverlay.kind === "status-popover")
|
|
8507
8891
|
closeFloatingOverlay();
|
|
@@ -8511,11 +8895,11 @@ var Browser = ({
|
|
|
8511
8895
|
dispatchFloatingOverlay({ type: "update-status-popover", content: discoveryWarningStatus });
|
|
8512
8896
|
}
|
|
8513
8897
|
}, [discoveryWarningStatus, floatingOverlay]);
|
|
8514
|
-
const updateNoticeSeenRef =
|
|
8515
|
-
|
|
8898
|
+
const updateNoticeSeenRef = useRef3(null);
|
|
8899
|
+
useEffect4(() => {
|
|
8516
8900
|
focusRef.current = focus;
|
|
8517
8901
|
}, [focus]);
|
|
8518
|
-
|
|
8902
|
+
useEffect4(() => {
|
|
8519
8903
|
if (!updateNotice)
|
|
8520
8904
|
return;
|
|
8521
8905
|
if (updateNoticeSeenRef.current === updateNotice)
|
|
@@ -8550,55 +8934,27 @@ var Browser = ({
|
|
|
8550
8934
|
});
|
|
8551
8935
|
pushFooterNotice(`tone: ${nextTone}`);
|
|
8552
8936
|
};
|
|
8553
|
-
useEffect2(() => {
|
|
8554
|
-
if (filterInput === filterApplied)
|
|
8555
|
-
return;
|
|
8556
|
-
const timer = setTimeout(() => {
|
|
8557
|
-
filterAppliedRef.current = filterInput;
|
|
8558
|
-
setFilterApplied(filterInput);
|
|
8559
|
-
}, filterDebounceMs);
|
|
8560
|
-
return () => clearTimeout(timer);
|
|
8561
|
-
}, [filterApplied, filterDebounceMs, filterInput]);
|
|
8562
|
-
useEffect2(() => {
|
|
8563
|
-
autoSelectForAppliedFilterRef.current = true;
|
|
8564
|
-
}, [filterApplied]);
|
|
8565
|
-
const displayedFiles = useMemo2(() => filterFiles(files, filterApplied), [files, filterApplied]);
|
|
8566
8937
|
const filterHasNoMatches = filterInput.length > 0 && displayedFiles.length === 0;
|
|
8567
|
-
|
|
8568
|
-
if (filterApplied.length === 0)
|
|
8569
|
-
return;
|
|
8570
|
-
if (!autoSelectForAppliedFilterRef.current)
|
|
8571
|
-
return;
|
|
8572
|
-
if (displayedFiles.length === 0)
|
|
8573
|
-
return;
|
|
8574
|
-
setSelectedIndex(0);
|
|
8575
|
-
autoSelectForAppliedFilterRef.current = false;
|
|
8576
|
-
}, [displayedFiles, filterApplied]);
|
|
8577
|
-
useEffect2(() => {
|
|
8578
|
-
if (selectedIndex >= displayedFiles.length) {
|
|
8579
|
-
setSelectedIndex(displayedFiles.length === 0 ? 0 : displayedFiles.length - 1);
|
|
8580
|
-
}
|
|
8581
|
-
}, [displayedFiles.length, selectedIndex]);
|
|
8582
|
-
useEffect2(() => {
|
|
8938
|
+
useEffect4(() => {
|
|
8583
8939
|
const target = pendingSelectionPathRef.current;
|
|
8584
8940
|
if (target === null)
|
|
8585
8941
|
return;
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8942
|
+
if (displayedFiles.some((file) => file.path === target)) {
|
|
8943
|
+
const snapshot = navigator.selectId(target);
|
|
8944
|
+
if (snapshot.selectedFile?.path !== target)
|
|
8945
|
+
return;
|
|
8589
8946
|
pendingSelectionPathRef.current = null;
|
|
8590
8947
|
}
|
|
8591
8948
|
}, [displayedFiles]);
|
|
8592
|
-
const
|
|
8593
|
-
|
|
8594
|
-
useEffect2(() => {
|
|
8949
|
+
const [renderedPath, setRenderedPath] = useState4(selected?.path ?? null);
|
|
8950
|
+
useEffect4(() => {
|
|
8595
8951
|
const target = selected?.path ?? null;
|
|
8596
8952
|
if (target === renderedPath)
|
|
8597
8953
|
return;
|
|
8598
8954
|
const timer = setTimeout(() => setRenderedPath(target), renderedPathDebounceMs);
|
|
8599
8955
|
return () => clearTimeout(timer);
|
|
8600
8956
|
}, [selected?.path, renderedPath, renderedPathDebounceMs]);
|
|
8601
|
-
|
|
8957
|
+
useEffect4(() => {
|
|
8602
8958
|
if (!renderedPath) {
|
|
8603
8959
|
setLoaded(null);
|
|
8604
8960
|
return;
|
|
@@ -8630,10 +8986,20 @@ var Browser = ({
|
|
|
8630
8986
|
paletteOpen,
|
|
8631
8987
|
wrapEnabled,
|
|
8632
8988
|
setFocus,
|
|
8633
|
-
|
|
8989
|
+
moveSelectionBy: (delta) => {
|
|
8990
|
+
pendingSelectionPathRef.current = null;
|
|
8991
|
+
navigator.cancelAutoSelect();
|
|
8992
|
+
navigator.moveBy(delta);
|
|
8993
|
+
},
|
|
8994
|
+
selectFirst: () => {
|
|
8634
8995
|
pendingSelectionPathRef.current = null;
|
|
8635
|
-
|
|
8636
|
-
|
|
8996
|
+
navigator.cancelAutoSelect();
|
|
8997
|
+
navigator.selectFirst();
|
|
8998
|
+
},
|
|
8999
|
+
selectLast: () => {
|
|
9000
|
+
pendingSelectionPathRef.current = null;
|
|
9001
|
+
navigator.cancelAutoSelect();
|
|
9002
|
+
navigator.selectLast();
|
|
8637
9003
|
},
|
|
8638
9004
|
toggleShown: () => {
|
|
8639
9005
|
if (!canFitInline(width)) {
|
|
@@ -8664,10 +9030,9 @@ var Browser = ({
|
|
|
8664
9030
|
clearAndOpenFilter: () => {
|
|
8665
9031
|
closeFloatingOverlay();
|
|
8666
9032
|
filterInputRef.current = "";
|
|
8667
|
-
filterAppliedRef.current = "";
|
|
8668
9033
|
setFilterInput("");
|
|
8669
|
-
|
|
8670
|
-
|
|
9034
|
+
navigator.flushSearch("");
|
|
9035
|
+
navigator.selectFirst();
|
|
8671
9036
|
focusRef.current = "sidebar";
|
|
8672
9037
|
if (focus !== "sidebar")
|
|
8673
9038
|
setFocus("sidebar");
|
|
@@ -8686,13 +9051,14 @@ var Browser = ({
|
|
|
8686
9051
|
cycleTheme,
|
|
8687
9052
|
toggleTone,
|
|
8688
9053
|
toggleAll: () => {
|
|
8689
|
-
|
|
8690
|
-
|
|
9054
|
+
const current = navigator.getSnapshot().selectedFile;
|
|
9055
|
+
if (pendingSelectionPathRef.current === null && current) {
|
|
9056
|
+
pendingSelectionPathRef.current = current.path;
|
|
8691
9057
|
}
|
|
8692
9058
|
onToggleAll?.();
|
|
8693
9059
|
},
|
|
8694
9060
|
serveCurrent: () => {
|
|
8695
|
-
const file =
|
|
9061
|
+
const file = navigator.getSnapshot().selectedFile;
|
|
8696
9062
|
if (!file)
|
|
8697
9063
|
return;
|
|
8698
9064
|
let handle = serverRef.current;
|
|
@@ -8722,7 +9088,7 @@ var Browser = ({
|
|
|
8722
9088
|
process.exit(0);
|
|
8723
9089
|
},
|
|
8724
9090
|
editCurrent: () => {
|
|
8725
|
-
const file =
|
|
9091
|
+
const file = navigator.getSnapshot().selectedFile;
|
|
8726
9092
|
if (!file)
|
|
8727
9093
|
return;
|
|
8728
9094
|
const editor = resolveEditor(process.env);
|
|
@@ -8772,7 +9138,7 @@ var Browser = ({
|
|
|
8772
9138
|
})();
|
|
8773
9139
|
},
|
|
8774
9140
|
copyCurrentContents: () => {
|
|
8775
|
-
const file =
|
|
9141
|
+
const file = navigator.getSnapshot().selectedFile;
|
|
8776
9142
|
if (!file)
|
|
8777
9143
|
return;
|
|
8778
9144
|
(async () => {
|
|
@@ -8855,9 +9221,8 @@ var Browser = ({
|
|
|
8855
9221
|
}
|
|
8856
9222
|
if (filterOpenRef.current && focusRef.current === "sidebar") {
|
|
8857
9223
|
const closeFilter = (commit) => {
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
const picked = displayedFiles[selectedIndex] ?? null;
|
|
9224
|
+
const snapshot = navigator.flushSearch(filterInputRef.current);
|
|
9225
|
+
const picked = snapshot.selectedFile;
|
|
8861
9226
|
const effectiveCommit = commit && picked !== null;
|
|
8862
9227
|
restoreFilterOnSidebarFocusRef.current = false;
|
|
8863
9228
|
filterOpenRef.current = false;
|
|
@@ -8893,10 +9258,9 @@ var Browser = ({
|
|
|
8893
9258
|
}
|
|
8894
9259
|
if (key.ctrl && key.name === "\\") {
|
|
8895
9260
|
filterInputRef.current = "";
|
|
8896
|
-
filterAppliedRef.current = "";
|
|
8897
9261
|
setFilterInput("");
|
|
8898
|
-
|
|
8899
|
-
|
|
9262
|
+
navigator.flushSearch("");
|
|
9263
|
+
navigator.selectFirst();
|
|
8900
9264
|
return;
|
|
8901
9265
|
}
|
|
8902
9266
|
if (key.name === "backspace" || key.name === "delete") {
|
|
@@ -8906,15 +9270,15 @@ var Browser = ({
|
|
|
8906
9270
|
}
|
|
8907
9271
|
filterInputRef.current = filterInputRef.current.slice(0, -1);
|
|
8908
9272
|
setFilterInput(filterInputRef.current);
|
|
8909
|
-
|
|
9273
|
+
navigator.selectIndex(0);
|
|
8910
9274
|
return;
|
|
8911
9275
|
}
|
|
8912
9276
|
if (key.name === "up") {
|
|
8913
|
-
|
|
9277
|
+
navigator.moveBy(-1);
|
|
8914
9278
|
return;
|
|
8915
9279
|
}
|
|
8916
9280
|
if (key.name === "down") {
|
|
8917
|
-
|
|
9281
|
+
navigator.moveBy(1);
|
|
8918
9282
|
return;
|
|
8919
9283
|
}
|
|
8920
9284
|
if (key.ctrl || key.meta)
|
|
@@ -8928,7 +9292,7 @@ var Browser = ({
|
|
|
8928
9292
|
if (char !== null) {
|
|
8929
9293
|
filterInputRef.current = filterInputRef.current + char;
|
|
8930
9294
|
setFilterInput(filterInputRef.current);
|
|
8931
|
-
|
|
9295
|
+
navigator.selectIndex(0);
|
|
8932
9296
|
}
|
|
8933
9297
|
return;
|
|
8934
9298
|
}
|
|
@@ -8948,7 +9312,7 @@ var Browser = ({
|
|
|
8948
9312
|
const parsedContent = useMemo2(() => parseFrontmatter(content), [content]);
|
|
8949
9313
|
const readerEmptyStateTitle = filterHasNoMatches ? `No files match: ${filterInput}` : `${BRAND} ${BRAND_NAME}`;
|
|
8950
9314
|
const readerEmptyStateVisible = error == null && renderedPath == null;
|
|
8951
|
-
|
|
9315
|
+
useEffect4(() => {
|
|
8952
9316
|
if (disableReaderEmptyStateRotation)
|
|
8953
9317
|
return;
|
|
8954
9318
|
if (readerEmptyStateVisible) {
|
|
@@ -8961,25 +9325,6 @@ var Browser = ({
|
|
|
8961
9325
|
readerEmptyStateVisibleRef.current = false;
|
|
8962
9326
|
}, [disableReaderEmptyStateRotation, readerEmptyStateVisible]);
|
|
8963
9327
|
const discoveryActive = discoveryStatus !== null && discoveryStatus.length > 0;
|
|
8964
|
-
const filterRowVisible = files.length > 0 || discoveryActive;
|
|
8965
|
-
const sidebarBodyHeight = Math.max(1, height - FOOTER_HEIGHT - HEADER_HEIGHT - 2 - (filterRowVisible ? 1 : 0));
|
|
8966
|
-
const maxScroll = Math.max(0, displayedFiles.length - sidebarBodyHeight);
|
|
8967
|
-
const desiredScroll = (() => {
|
|
8968
|
-
let s = sidebarScroll;
|
|
8969
|
-
if (selectedIndex < s)
|
|
8970
|
-
s = selectedIndex;
|
|
8971
|
-
else if (selectedIndex >= s + sidebarBodyHeight)
|
|
8972
|
-
s = selectedIndex - sidebarBodyHeight + 1;
|
|
8973
|
-
return clamp3(s, 0, maxScroll);
|
|
8974
|
-
})();
|
|
8975
|
-
useEffect2(() => {
|
|
8976
|
-
if (desiredScroll !== sidebarScroll)
|
|
8977
|
-
setSidebarScroll(desiredScroll);
|
|
8978
|
-
}, [desiredScroll, sidebarScroll]);
|
|
8979
|
-
const visibleFiles = displayedFiles.slice(desiredScroll, desiredScroll + sidebarBodyHeight);
|
|
8980
|
-
const sidebarPaneWidth = isNarrow ? width : sidebarWidth;
|
|
8981
|
-
const sidebarTextWidth = Math.max(4, sidebarPaneWidth - (isNarrow ? 1 : 2));
|
|
8982
|
-
const layoutSidebarRow = useCallback((relativePath) => formatSidebarRow(relativePath, sidebarTextWidth), [sidebarTextWidth]);
|
|
8983
9328
|
const footerProps = {
|
|
8984
9329
|
bindings: browserBindings,
|
|
8985
9330
|
ctx,
|
|
@@ -9007,74 +9352,17 @@ var Browser = ({
|
|
|
9007
9352
|
};
|
|
9008
9353
|
const readerEmptyStateTips = useMemo2(() => buildReaderEmptyStateTips(browserBindings, ctx), [ctx]);
|
|
9009
9354
|
const readerEmptyStateTip = useMemo2(() => pickTipByRotation(readerEmptyStateTips, readerEmptyStateTipRotation), [readerEmptyStateTipRotation, readerEmptyStateTips]);
|
|
9010
|
-
const sidebarBody = /* @__PURE__ */ jsxDEV8(Fragment2, {
|
|
9011
|
-
children: [
|
|
9012
|
-
filterRowVisible && /* @__PURE__ */ jsxDEV8(PromptRow, {
|
|
9013
|
-
query: filterInput,
|
|
9014
|
-
editing: filterOpen,
|
|
9015
|
-
placeholder: "type / to filter",
|
|
9016
|
-
width: sidebarTextWidth
|
|
9017
|
-
}, undefined, false, undefined, this),
|
|
9018
|
-
displayedFiles.length === 0 ? /* @__PURE__ */ jsxDEV8(SidebarEmptyMessage, {
|
|
9019
|
-
withTopSpacer: filterRowVisible,
|
|
9020
|
-
width: sidebarTextWidth,
|
|
9021
|
-
label: files.length === 0 ? discoveryActive ? "Scanning" : "No markdown files in" : "No files match",
|
|
9022
|
-
value: files.length === 0 ? discoveryActive ? "\u2026" : rootLabel : filterApplied
|
|
9023
|
-
}, undefined, false, undefined, this) : visibleFiles.map((file, idx) => {
|
|
9024
|
-
const realIdx = desiredScroll + idx;
|
|
9025
|
-
const isSelected = realIdx === selectedIndex;
|
|
9026
|
-
const { basename: basename2, separator, parent } = layoutSidebarRow(file.relativePath);
|
|
9027
|
-
const basenameFg = isSelected ? colors.selectedListItemText : colors.text;
|
|
9028
|
-
const rowStyle = {
|
|
9029
|
-
width: sidebarTextWidth,
|
|
9030
|
-
height: 1,
|
|
9031
|
-
flexDirection: "row",
|
|
9032
|
-
...isSelected ? { backgroundColor: colors.backgroundElement } : {}
|
|
9033
|
-
};
|
|
9034
|
-
return /* @__PURE__ */ jsxDEV8("box", {
|
|
9035
|
-
style: rowStyle,
|
|
9036
|
-
children: /* @__PURE__ */ jsxDEV8("text", {
|
|
9037
|
-
wrapMode: "none",
|
|
9038
|
-
children: [
|
|
9039
|
-
/* @__PURE__ */ jsxDEV8("span", {
|
|
9040
|
-
style: { fg: basenameFg },
|
|
9041
|
-
children: basename2
|
|
9042
|
-
}, undefined, false, undefined, this),
|
|
9043
|
-
parent !== "" && /* @__PURE__ */ jsxDEV8("span", {
|
|
9044
|
-
style: { fg: colors.textMuted },
|
|
9045
|
-
children: middleTruncate(`${separator}${parent}`, Math.max(0, sidebarTextWidth - basename2.length))
|
|
9046
|
-
}, undefined, false, undefined, this)
|
|
9047
|
-
]
|
|
9048
|
-
}, undefined, true, undefined, this)
|
|
9049
|
-
}, file.path, false, undefined, this);
|
|
9050
|
-
})
|
|
9051
|
-
]
|
|
9052
|
-
}, undefined, true, undefined, this);
|
|
9053
|
-
const sidebarBorderSides = ["top", "bottom", "right"];
|
|
9054
9355
|
const readerBorderSides = ["top", "bottom"];
|
|
9055
|
-
const
|
|
9056
|
-
|
|
9057
|
-
topRight: "\u252C",
|
|
9058
|
-
bottomLeft: "\u2514",
|
|
9059
|
-
bottomRight: "\u2534",
|
|
9060
|
-
horizontal: "\u2500",
|
|
9061
|
-
vertical: "\u2502",
|
|
9062
|
-
topT: "\u252C",
|
|
9063
|
-
bottomT: "\u2534",
|
|
9064
|
-
leftT: "\u251C",
|
|
9065
|
-
rightT: "\u2524",
|
|
9066
|
-
cross: "\u253C"
|
|
9067
|
-
};
|
|
9068
|
-
const INACTIVE_PANE_OPACITY = 0.62;
|
|
9069
|
-
return /* @__PURE__ */ jsxDEV8("box", {
|
|
9356
|
+
const INACTIVE_PANE_OPACITY2 = 0.62;
|
|
9357
|
+
return /* @__PURE__ */ jsxDEV12("box", {
|
|
9070
9358
|
style: { width, height, flexDirection: "column", backgroundColor: colors.backgroundPanel },
|
|
9071
9359
|
children: [
|
|
9072
|
-
/* @__PURE__ */
|
|
9360
|
+
/* @__PURE__ */ jsxDEV12(Header, {
|
|
9073
9361
|
width,
|
|
9074
9362
|
currentFile,
|
|
9075
9363
|
rootLabel
|
|
9076
9364
|
}, undefined, false, undefined, this),
|
|
9077
|
-
/* @__PURE__ */
|
|
9365
|
+
/* @__PURE__ */ jsxDEV12("box", {
|
|
9078
9366
|
style: {
|
|
9079
9367
|
flexDirection: "row",
|
|
9080
9368
|
flexGrow: 1,
|
|
@@ -9082,28 +9370,20 @@ var Browser = ({
|
|
|
9082
9370
|
backgroundColor: colors.backgroundPanel
|
|
9083
9371
|
},
|
|
9084
9372
|
children: [
|
|
9085
|
-
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
flexShrink: 1,
|
|
9098
|
-
flexDirection: "column",
|
|
9099
|
-
paddingLeft: 1,
|
|
9100
|
-
backgroundColor: sidebarActive ? colors.background : colors.backgroundPanel,
|
|
9101
|
-
opacity: sidebarActive ? 1 : INACTIVE_PANE_OPACITY
|
|
9102
|
-
},
|
|
9103
|
-
children: sidebarBody
|
|
9104
|
-
}, undefined, false, undefined, this)
|
|
9373
|
+
/* @__PURE__ */ jsxDEV12(Sidebar, {
|
|
9374
|
+
files,
|
|
9375
|
+
controller: navigator,
|
|
9376
|
+
filterInput,
|
|
9377
|
+
filterOpen,
|
|
9378
|
+
discoveryActive,
|
|
9379
|
+
rootLabel,
|
|
9380
|
+
viewportHeight: height,
|
|
9381
|
+
paneWidth: isNarrow ? width : sidebarWidth,
|
|
9382
|
+
narrow: isNarrow,
|
|
9383
|
+
active: sidebarActive,
|
|
9384
|
+
visible: sidebarInline
|
|
9105
9385
|
}, undefined, false, undefined, this),
|
|
9106
|
-
readerVisible && /* @__PURE__ */
|
|
9386
|
+
readerVisible && /* @__PURE__ */ jsxDEV12("box", {
|
|
9107
9387
|
style: {
|
|
9108
9388
|
border: readerBorderSides,
|
|
9109
9389
|
borderColor: colors.border,
|
|
@@ -9112,19 +9392,19 @@ var Browser = ({
|
|
|
9112
9392
|
flexDirection: "column",
|
|
9113
9393
|
backgroundColor: colors.backgroundPanel
|
|
9114
9394
|
},
|
|
9115
|
-
children: /* @__PURE__ */
|
|
9395
|
+
children: /* @__PURE__ */ jsxDEV12("box", {
|
|
9116
9396
|
style: {
|
|
9117
9397
|
flexGrow: 1,
|
|
9118
9398
|
flexShrink: 1,
|
|
9119
9399
|
flexDirection: "column",
|
|
9120
9400
|
padding: 1,
|
|
9121
9401
|
backgroundColor: readerActive ? colors.background : colors.backgroundPanel,
|
|
9122
|
-
opacity: readerActive ? 1 :
|
|
9402
|
+
opacity: readerActive ? 1 : INACTIVE_PANE_OPACITY2
|
|
9123
9403
|
},
|
|
9124
|
-
children: error ? /* @__PURE__ */
|
|
9404
|
+
children: error ? /* @__PURE__ */ jsxDEV12("text", {
|
|
9125
9405
|
content: error,
|
|
9126
9406
|
style: { fg: colors.error }
|
|
9127
|
-
}, undefined, false, undefined, this) : !renderedPath ? /* @__PURE__ */
|
|
9407
|
+
}, undefined, false, undefined, this) : !renderedPath ? /* @__PURE__ */ jsxDEV12("box", {
|
|
9128
9408
|
style: {
|
|
9129
9409
|
flexGrow: 1,
|
|
9130
9410
|
flexShrink: 1,
|
|
@@ -9132,22 +9412,22 @@ var Browser = ({
|
|
|
9132
9412
|
justifyContent: "center",
|
|
9133
9413
|
backgroundColor: readerActive ? colors.background : colors.backgroundPanel
|
|
9134
9414
|
},
|
|
9135
|
-
children: /* @__PURE__ */
|
|
9415
|
+
children: /* @__PURE__ */ jsxDEV12("box", {
|
|
9136
9416
|
style: { flexDirection: "column", gap: 1, alignItems: "center" },
|
|
9137
9417
|
children: [
|
|
9138
|
-
/* @__PURE__ */
|
|
9418
|
+
/* @__PURE__ */ jsxDEV12("text", {
|
|
9139
9419
|
content: readerEmptyStateTitle,
|
|
9140
9420
|
wrapMode: "none",
|
|
9141
9421
|
style: { fg: colors.textMuted }
|
|
9142
9422
|
}, undefined, false, undefined, this),
|
|
9143
|
-
readerEmptyStateTip && /* @__PURE__ */
|
|
9423
|
+
readerEmptyStateTip && /* @__PURE__ */ jsxDEV12("text", {
|
|
9144
9424
|
content: readerEmptyStateTip.text,
|
|
9145
9425
|
wrapMode: "none",
|
|
9146
9426
|
style: { fg: colors.textMuted }
|
|
9147
9427
|
}, readerEmptyStateTip.id, false, undefined, this)
|
|
9148
9428
|
]
|
|
9149
9429
|
}, undefined, true, undefined, this)
|
|
9150
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
9430
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV12("scrollbox", {
|
|
9151
9431
|
style: {
|
|
9152
9432
|
scrollY: true,
|
|
9153
9433
|
scrollX: false,
|
|
@@ -9157,17 +9437,17 @@ var Browser = ({
|
|
|
9157
9437
|
},
|
|
9158
9438
|
focused: readerActive && !paletteOpen,
|
|
9159
9439
|
children: [
|
|
9160
|
-
parsedContent.fields.length > 0 && /* @__PURE__ */
|
|
9440
|
+
parsedContent.fields.length > 0 && /* @__PURE__ */ jsxDEV12("box", {
|
|
9161
9441
|
style: { flexDirection: "column", marginBottom: 1 },
|
|
9162
|
-
children: parsedContent.fields.map((field) => /* @__PURE__ */
|
|
9442
|
+
children: parsedContent.fields.map((field) => /* @__PURE__ */ jsxDEV12("box", {
|
|
9163
9443
|
style: { flexDirection: "row", gap: 1, flexWrap: "wrap" },
|
|
9164
9444
|
children: [
|
|
9165
|
-
/* @__PURE__ */
|
|
9445
|
+
/* @__PURE__ */ jsxDEV12("text", {
|
|
9166
9446
|
content: `${field.key}:`,
|
|
9167
9447
|
wrapMode: "word",
|
|
9168
9448
|
style: { fg: colors.secondary }
|
|
9169
9449
|
}, undefined, false, undefined, this),
|
|
9170
|
-
/* @__PURE__ */
|
|
9450
|
+
/* @__PURE__ */ jsxDEV12("text", {
|
|
9171
9451
|
content: field.value,
|
|
9172
9452
|
wrapMode: "word",
|
|
9173
9453
|
style: { fg: colors.textMuted }
|
|
@@ -9175,7 +9455,7 @@ var Browser = ({
|
|
|
9175
9455
|
]
|
|
9176
9456
|
}, field.key, true, undefined, this))
|
|
9177
9457
|
}, undefined, false, undefined, this),
|
|
9178
|
-
/* @__PURE__ */
|
|
9458
|
+
/* @__PURE__ */ jsxDEV12("markdown", {
|
|
9179
9459
|
content: parsedContent.body,
|
|
9180
9460
|
syntaxStyle,
|
|
9181
9461
|
fg: colors.text,
|
|
@@ -9189,17 +9469,17 @@ var Browser = ({
|
|
|
9189
9469
|
}, undefined, false, undefined, this)
|
|
9190
9470
|
]
|
|
9191
9471
|
}, undefined, true, undefined, this),
|
|
9192
|
-
/* @__PURE__ */
|
|
9472
|
+
/* @__PURE__ */ jsxDEV12(Footer, {
|
|
9193
9473
|
...footerProps
|
|
9194
9474
|
}, undefined, false, undefined, this),
|
|
9195
|
-
paletteOpen && /* @__PURE__ */
|
|
9475
|
+
paletteOpen && /* @__PURE__ */ jsxDEV12(CommandPalette, {
|
|
9196
9476
|
commands: orderCommandsForPalette(filterCommands(buildCommands(ctx), paletteQuery)),
|
|
9197
9477
|
query: paletteQuery,
|
|
9198
9478
|
selectedIndex: paletteIndex,
|
|
9199
9479
|
viewportWidth: width,
|
|
9200
9480
|
viewportHeight: height
|
|
9201
9481
|
}, undefined, false, undefined, this),
|
|
9202
|
-
activeStatusPopover && /* @__PURE__ */
|
|
9482
|
+
activeStatusPopover && /* @__PURE__ */ jsxDEV12(StatusPopoverPanel, {
|
|
9203
9483
|
content: activeStatusPopover.content,
|
|
9204
9484
|
variant: "warning"
|
|
9205
9485
|
}, undefined, false, undefined, this)
|
|
@@ -9676,13 +9956,13 @@ var subscribeUpdateInfo = (cb) => {
|
|
|
9676
9956
|
};
|
|
9677
9957
|
|
|
9678
9958
|
// src/update/useUpdateNotice.ts
|
|
9679
|
-
import { useEffect as
|
|
9959
|
+
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
9680
9960
|
var useUpdateNotice = () => {
|
|
9681
|
-
const [text, setText] =
|
|
9961
|
+
const [text, setText] = useState5(() => {
|
|
9682
9962
|
const cur = currentUpdateInfo();
|
|
9683
9963
|
return cur ? formatFooterNotice(cur) : null;
|
|
9684
9964
|
});
|
|
9685
|
-
|
|
9965
|
+
useEffect5(() => {
|
|
9686
9966
|
const unsub = subscribeUpdateInfo((info) => setText(formatFooterNotice(info)));
|
|
9687
9967
|
return unsub;
|
|
9688
9968
|
}, []);
|
|
@@ -9690,7 +9970,7 @@ var useUpdateNotice = () => {
|
|
|
9690
9970
|
};
|
|
9691
9971
|
|
|
9692
9972
|
// src/index.tsx
|
|
9693
|
-
import { jsxDEV as
|
|
9973
|
+
import { jsxDEV as jsxDEV13 } from "@opentui/react/jsx-dev-runtime";
|
|
9694
9974
|
var pathIsDirectory = async (path) => {
|
|
9695
9975
|
try {
|
|
9696
9976
|
return (await stat(path)).isDirectory();
|
|
@@ -9754,14 +10034,14 @@ var DiscoverShell = ({
|
|
|
9754
10034
|
startupFocus
|
|
9755
10035
|
}) => {
|
|
9756
10036
|
const updateNotice = useUpdateNotice();
|
|
9757
|
-
const [show, setShow] =
|
|
9758
|
-
const [files, setFiles] =
|
|
9759
|
-
const [scanning, setScanning] =
|
|
9760
|
-
const [scanError, setScanError] =
|
|
9761
|
-
const [skippedDirCount, setSkippedDirCount] =
|
|
9762
|
-
const [lastSkippedDir, setLastSkippedDir] =
|
|
9763
|
-
const countRef =
|
|
9764
|
-
|
|
10037
|
+
const [show, setShow] = useState6(initialShow);
|
|
10038
|
+
const [files, setFiles] = useState6([]);
|
|
10039
|
+
const [scanning, setScanning] = useState6(true);
|
|
10040
|
+
const [scanError, setScanError] = useState6(null);
|
|
10041
|
+
const [skippedDirCount, setSkippedDirCount] = useState6(0);
|
|
10042
|
+
const [lastSkippedDir, setLastSkippedDir] = useState6(null);
|
|
10043
|
+
const countRef = useRef4(0);
|
|
10044
|
+
useEffect6(() => {
|
|
9765
10045
|
setFiles([]);
|
|
9766
10046
|
setScanning(true);
|
|
9767
10047
|
setScanError(null);
|
|
@@ -9800,7 +10080,7 @@ var DiscoverShell = ({
|
|
|
9800
10080
|
skippedCount: skippedDirCount,
|
|
9801
10081
|
lastSkippedPath: lastSkippedDir
|
|
9802
10082
|
}));
|
|
9803
|
-
return /* @__PURE__ */
|
|
10083
|
+
return /* @__PURE__ */ jsxDEV13(Browser, {
|
|
9804
10084
|
files,
|
|
9805
10085
|
initialQuery,
|
|
9806
10086
|
wrapWidth,
|
|
@@ -9980,9 +10260,9 @@ async function runTui({
|
|
|
9980
10260
|
console.error(`house: ${err instanceof Error ? err.message : String(err)}`);
|
|
9981
10261
|
process.exit(1);
|
|
9982
10262
|
}
|
|
9983
|
-
createRoot(renderer).render(/* @__PURE__ */
|
|
10263
|
+
createRoot(renderer).render(/* @__PURE__ */ jsxDEV13(RegistryProvider, {
|
|
9984
10264
|
initialValues: [[themeAtom, initialTheme]],
|
|
9985
|
-
children: /* @__PURE__ */
|
|
10265
|
+
children: /* @__PURE__ */ jsxDEV13(DiscoverShell, {
|
|
9986
10266
|
target: discoveryRoot,
|
|
9987
10267
|
initialQuery,
|
|
9988
10268
|
initialShow: show,
|