@carlesandres/house 0.5.1 → 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 +26 -2
- package/README.md +1 -1
- package/dist/index.js +671 -392
- package/package.json +26 -22
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,24 +50,26 @@ 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/",
|
|
61
|
-
|
|
62
|
-
"
|
|
63
|
-
"
|
|
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",
|
|
64
65
|
release: "bun run dev/release.ts",
|
|
65
|
-
"build:cli": "bun run dev/build-cli.ts",
|
|
66
|
-
"build:standalone": "bun run dev/build-standalone.ts",
|
|
67
|
-
"build:npm-packages": "bun run dev/build-npm-packages.ts",
|
|
68
|
-
"build:themes": "bun run dev/build-themes.ts",
|
|
69
|
-
prepack: "bun run build:cli",
|
|
70
66
|
"repro:pty-codeblocks": "bun run dev/repro-pty-codeblocks.ts",
|
|
71
|
-
|
|
67
|
+
start: "bun run src/index.tsx",
|
|
68
|
+
test: "bun test",
|
|
69
|
+
"test:pty": "HOUSE_PTY=1 bun test test/pty/",
|
|
70
|
+
typecheck: "tsc --noEmit",
|
|
71
|
+
"verify:github": "bun test test/github-emulation.test.ts",
|
|
72
|
+
"version:set": "bun run dev/set-version.ts"
|
|
72
73
|
},
|
|
73
74
|
optionalDependencies: {
|
|
74
75
|
"@carlesandres/house-darwin-arm64": "0.5.1",
|
|
@@ -85,12 +86,15 @@ var package_default = {
|
|
|
85
86
|
ignore: "^7.0.5",
|
|
86
87
|
marked: "^18.0.4",
|
|
87
88
|
react: "19.2.6",
|
|
88
|
-
scheduler: "0.27.0"
|
|
89
|
+
scheduler: "0.27.0",
|
|
90
|
+
"string-width": "7.2.0",
|
|
91
|
+
"web-tree-sitter": "0.25.10"
|
|
89
92
|
},
|
|
90
93
|
devDependencies: {
|
|
91
94
|
"@effect/language-service": "0.86.2",
|
|
92
95
|
"@types/bun": "1.3.14",
|
|
93
96
|
"@types/react": "19.2.15",
|
|
97
|
+
emulate: "0.9.0",
|
|
94
98
|
oxfmt: "0.51.0",
|
|
95
99
|
oxlint: "1.66.0",
|
|
96
100
|
tuistory: "^0.8.0",
|
|
@@ -100,18 +104,424 @@ var package_default = {
|
|
|
100
104
|
|
|
101
105
|
// src/Browser.tsx
|
|
102
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
|
|
103
516
|
import { useKeyboard, useRenderer, useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
|
|
104
517
|
import { useAtomValue, useAtomSet } from "@effect/atom-react";
|
|
105
518
|
import { Effect as Effect3 } from "effect";
|
|
106
|
-
import {
|
|
519
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useReducer as useReducer2, useRef as useRef3, useState as useState4 } from "react";
|
|
107
520
|
|
|
108
521
|
// src/keymap/browser.ts
|
|
109
522
|
var JUMP = 8;
|
|
110
|
-
var clamp = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
111
|
-
var lastIndex = (c) => Math.max(0, c.files.length - 1);
|
|
112
523
|
var haveFiles = (c) => c.files.length > 0;
|
|
113
524
|
var hasSelected = (c) => c.hasSelected;
|
|
114
|
-
var stepBy = (c, delta) => c.setSelectedIndex((i) => clamp(i + delta, 0, lastIndex(c)));
|
|
115
525
|
var inSidebar = (c) => c.focus === "sidebar";
|
|
116
526
|
var filterClosed = (c) => !c.filterOpen;
|
|
117
527
|
var paletteClosed = (c) => !c.paletteOpen;
|
|
@@ -216,7 +626,7 @@ var browserBindings = [
|
|
|
216
626
|
description: "Move selection down",
|
|
217
627
|
keys: ["j", "down"],
|
|
218
628
|
when: inSidebarWithFiles,
|
|
219
|
-
run: (c) =>
|
|
629
|
+
run: (c) => c.moveSelectionBy(1)
|
|
220
630
|
},
|
|
221
631
|
{
|
|
222
632
|
id: "sidebar.up",
|
|
@@ -224,7 +634,7 @@ var browserBindings = [
|
|
|
224
634
|
description: "Move selection up",
|
|
225
635
|
keys: ["k", "up"],
|
|
226
636
|
when: inSidebarWithFiles,
|
|
227
|
-
run: (c) =>
|
|
637
|
+
run: (c) => c.moveSelectionBy(-1)
|
|
228
638
|
},
|
|
229
639
|
{
|
|
230
640
|
id: "sidebar.jumpDown",
|
|
@@ -232,7 +642,7 @@ var browserBindings = [
|
|
|
232
642
|
description: `Jump down ${JUMP}`,
|
|
233
643
|
keys: ["shift+j"],
|
|
234
644
|
when: inSidebarWithFiles,
|
|
235
|
-
run: (c) =>
|
|
645
|
+
run: (c) => c.moveSelectionBy(JUMP)
|
|
236
646
|
},
|
|
237
647
|
{
|
|
238
648
|
id: "sidebar.jumpUp",
|
|
@@ -240,7 +650,7 @@ var browserBindings = [
|
|
|
240
650
|
description: `Jump up ${JUMP}`,
|
|
241
651
|
keys: ["shift+k"],
|
|
242
652
|
when: inSidebarWithFiles,
|
|
243
|
-
run: (c) =>
|
|
653
|
+
run: (c) => c.moveSelectionBy(-JUMP)
|
|
244
654
|
},
|
|
245
655
|
{
|
|
246
656
|
id: "sidebar.pageDown",
|
|
@@ -248,7 +658,7 @@ var browserBindings = [
|
|
|
248
658
|
description: "Page down",
|
|
249
659
|
keys: ["space", "pagedown", "ctrl+d"],
|
|
250
660
|
when: inSidebarWithFiles,
|
|
251
|
-
run: (c) =>
|
|
661
|
+
run: (c) => c.moveSelectionBy(JUMP)
|
|
252
662
|
},
|
|
253
663
|
{
|
|
254
664
|
id: "sidebar.pageUp",
|
|
@@ -256,7 +666,7 @@ var browserBindings = [
|
|
|
256
666
|
description: "Page up",
|
|
257
667
|
keys: ["b", "pageup", "ctrl+u"],
|
|
258
668
|
when: inSidebarWithFiles,
|
|
259
|
-
run: (c) =>
|
|
669
|
+
run: (c) => c.moveSelectionBy(-JUMP)
|
|
260
670
|
},
|
|
261
671
|
{
|
|
262
672
|
id: "sidebar.top",
|
|
@@ -264,7 +674,7 @@ var browserBindings = [
|
|
|
264
674
|
description: "Jump to first file",
|
|
265
675
|
keys: ["g"],
|
|
266
676
|
when: inSidebarWithFiles,
|
|
267
|
-
run: (c) => c.
|
|
677
|
+
run: (c) => c.selectFirst()
|
|
268
678
|
},
|
|
269
679
|
{
|
|
270
680
|
id: "sidebar.bottom",
|
|
@@ -272,7 +682,7 @@ var browserBindings = [
|
|
|
272
682
|
description: "Jump to last file",
|
|
273
683
|
keys: ["shift+g"],
|
|
274
684
|
when: inSidebarWithFiles,
|
|
275
|
-
run: (c) => c.
|
|
685
|
+
run: (c) => c.selectLast()
|
|
276
686
|
},
|
|
277
687
|
{
|
|
278
688
|
id: "sidebar.open",
|
|
@@ -304,7 +714,7 @@ var browserBindings = [
|
|
|
304
714
|
description: "Prev file",
|
|
305
715
|
keys: ["["],
|
|
306
716
|
when: inReaderWithSibling,
|
|
307
|
-
run: (c) =>
|
|
717
|
+
run: (c) => c.moveSelectionBy(-1)
|
|
308
718
|
},
|
|
309
719
|
{
|
|
310
720
|
id: "reader.nextFile",
|
|
@@ -312,7 +722,7 @@ var browserBindings = [
|
|
|
312
722
|
description: "Next file",
|
|
313
723
|
keys: ["]"],
|
|
314
724
|
when: inReaderWithSibling,
|
|
315
|
-
run: (c) =>
|
|
725
|
+
run: (c) => c.moveSelectionBy(1)
|
|
316
726
|
},
|
|
317
727
|
{
|
|
318
728
|
id: "reader.back",
|
|
@@ -615,7 +1025,7 @@ var setActiveTheme = (definition, tone) => {
|
|
|
615
1025
|
};
|
|
616
1026
|
|
|
617
1027
|
// src/PromptRow.tsx
|
|
618
|
-
import { jsxDEV } from "@opentui/react/jsx-dev-runtime";
|
|
1028
|
+
import { jsxDEV as jsxDEV4 } from "@opentui/react/jsx-dev-runtime";
|
|
619
1029
|
var PREFIX = "> ";
|
|
620
1030
|
var CURSOR = "\u258F";
|
|
621
1031
|
var PromptRow = ({ query, editing, placeholder = "", width }) => {
|
|
@@ -624,14 +1034,14 @@ var PromptRow = ({ query, editing, placeholder = "", width }) => {
|
|
|
624
1034
|
const bodyFg = editing ? colors.primary : query.length > 0 ? colors.text : colors.textMuted;
|
|
625
1035
|
const body = rawBody.length <= bodyBudget ? rawBody : editing ? "\u2026" + rawBody.slice(rawBody.length - bodyBudget + 1) : rawBody.slice(0, bodyBudget - 1) + "\u2026";
|
|
626
1036
|
const prefixFg = editing ? colors.secondary : colors.primary;
|
|
627
|
-
return /* @__PURE__ */
|
|
1037
|
+
return /* @__PURE__ */ jsxDEV4("text", {
|
|
628
1038
|
wrapMode: "none",
|
|
629
1039
|
children: [
|
|
630
|
-
/* @__PURE__ */
|
|
1040
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
631
1041
|
style: { fg: prefixFg },
|
|
632
1042
|
children: PREFIX
|
|
633
1043
|
}, undefined, false, undefined, this),
|
|
634
|
-
/* @__PURE__ */
|
|
1044
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
635
1045
|
style: { fg: bodyFg },
|
|
636
1046
|
children: body
|
|
637
1047
|
}, undefined, false, undefined, this)
|
|
@@ -640,7 +1050,7 @@ var PromptRow = ({ query, editing, placeholder = "", width }) => {
|
|
|
640
1050
|
};
|
|
641
1051
|
|
|
642
1052
|
// src/CommandPalette.tsx
|
|
643
|
-
import { jsxDEV as
|
|
1053
|
+
import { jsxDEV as jsxDEV5 } from "@opentui/react/jsx-dev-runtime";
|
|
644
1054
|
var SCRIM = RGBA.fromInts(0, 0, 0, 150);
|
|
645
1055
|
var FOOTER_HINT = "\u2191\u2193 select enter run esc close";
|
|
646
1056
|
var CATEGORY_ORDER = ["Navigation", "View", "File", "Appearance", "App"];
|
|
@@ -710,7 +1120,7 @@ var CommandPalette = ({
|
|
|
710
1120
|
const titleWidth = Math.max(8, rowWidth - 2 - SHORTCUT_WIDTH - 1);
|
|
711
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);
|
|
712
1122
|
const fitRight = (s, width) => s.length >= width ? s.slice(0, width) : " ".repeat(width - s.length) + s;
|
|
713
|
-
return /* @__PURE__ */
|
|
1123
|
+
return /* @__PURE__ */ jsxDEV5("box", {
|
|
714
1124
|
position: "absolute",
|
|
715
1125
|
left: 0,
|
|
716
1126
|
top: 0,
|
|
@@ -718,7 +1128,7 @@ var CommandPalette = ({
|
|
|
718
1128
|
height: viewportHeight,
|
|
719
1129
|
zIndex: 20,
|
|
720
1130
|
style: { backgroundColor: SCRIM },
|
|
721
|
-
children: /* @__PURE__ */
|
|
1131
|
+
children: /* @__PURE__ */ jsxDEV5("box", {
|
|
722
1132
|
position: "absolute",
|
|
723
1133
|
left,
|
|
724
1134
|
top,
|
|
@@ -735,26 +1145,26 @@ var CommandPalette = ({
|
|
|
735
1145
|
backgroundColor: colors.backgroundPanel
|
|
736
1146
|
},
|
|
737
1147
|
children: [
|
|
738
|
-
/* @__PURE__ */
|
|
1148
|
+
/* @__PURE__ */ jsxDEV5(PromptRow, {
|
|
739
1149
|
query,
|
|
740
1150
|
editing: true,
|
|
741
1151
|
width: rowWidth
|
|
742
1152
|
}, undefined, false, undefined, this),
|
|
743
|
-
/* @__PURE__ */
|
|
1153
|
+
/* @__PURE__ */ jsxDEV5("text", {
|
|
744
1154
|
content: " "
|
|
745
1155
|
}, undefined, false, undefined, this),
|
|
746
|
-
commands.length === 0 ? /* @__PURE__ */
|
|
1156
|
+
commands.length === 0 ? /* @__PURE__ */ jsxDEV5("text", {
|
|
747
1157
|
wrapMode: "none",
|
|
748
1158
|
content: " (no matches)",
|
|
749
1159
|
style: { fg: colors.textMuted }
|
|
750
1160
|
}, undefined, false, undefined, this) : visible.map((row) => {
|
|
751
1161
|
if (row.kind === "spacer") {
|
|
752
|
-
return /* @__PURE__ */
|
|
1162
|
+
return /* @__PURE__ */ jsxDEV5("text", {
|
|
753
1163
|
content: " "
|
|
754
1164
|
}, row.key, false, undefined, this);
|
|
755
1165
|
}
|
|
756
1166
|
if (row.kind === "header") {
|
|
757
|
-
return /* @__PURE__ */
|
|
1167
|
+
return /* @__PURE__ */ jsxDEV5("text", {
|
|
758
1168
|
wrapMode: "none",
|
|
759
1169
|
content: fit(row.text, rowWidth),
|
|
760
1170
|
style: { fg: colors.textMuted, attributes: 1 }
|
|
@@ -766,25 +1176,25 @@ var CommandPalette = ({
|
|
|
766
1176
|
const titleText = fit(cmd.title, titleWidth);
|
|
767
1177
|
const shortcutText = cmd.shortcut ? fitRight(cmd.shortcut, SHORTCUT_WIDTH) : " ".repeat(SHORTCUT_WIDTH);
|
|
768
1178
|
const titleFg = isSelected ? colors.primary : colors.text;
|
|
769
|
-
return /* @__PURE__ */
|
|
1179
|
+
return /* @__PURE__ */ jsxDEV5("text", {
|
|
770
1180
|
wrapMode: "none",
|
|
771
1181
|
style: isSelected ? { bg: colors.backgroundElement } : {},
|
|
772
1182
|
children: [
|
|
773
|
-
/* @__PURE__ */
|
|
1183
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
774
1184
|
style: { fg: titleFg },
|
|
775
1185
|
children: `${selector}${titleText} `
|
|
776
1186
|
}, undefined, false, undefined, this),
|
|
777
|
-
/* @__PURE__ */
|
|
1187
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
778
1188
|
style: { fg: colors.textMuted },
|
|
779
1189
|
children: shortcutText
|
|
780
1190
|
}, undefined, false, undefined, this)
|
|
781
1191
|
]
|
|
782
1192
|
}, cmd.id, true, undefined, this);
|
|
783
1193
|
}),
|
|
784
|
-
/* @__PURE__ */
|
|
1194
|
+
/* @__PURE__ */ jsxDEV5("text", {
|
|
785
1195
|
content: " "
|
|
786
1196
|
}, undefined, false, undefined, this),
|
|
787
|
-
/* @__PURE__ */
|
|
1197
|
+
/* @__PURE__ */ jsxDEV5("text", {
|
|
788
1198
|
wrapMode: "none",
|
|
789
1199
|
content: fit(FOOTER_HINT, rowWidth),
|
|
790
1200
|
style: { fg: colors.textMuted }
|
|
@@ -952,8 +1362,8 @@ var displayKey = (raw) => {
|
|
|
952
1362
|
};
|
|
953
1363
|
|
|
954
1364
|
// src/Spinner.tsx
|
|
955
|
-
import { useEffect, useRef, useState } from "react";
|
|
956
|
-
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";
|
|
957
1367
|
var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
958
1368
|
var FRAME_COUNT = FRAMES.length;
|
|
959
1369
|
var normalizeFrameIndex = (index) => (index % FRAME_COUNT + FRAME_COUNT) % FRAME_COUNT;
|
|
@@ -963,12 +1373,12 @@ var Spinner = ({
|
|
|
963
1373
|
initialFrameIndex = 0,
|
|
964
1374
|
registerTick = null
|
|
965
1375
|
}) => {
|
|
966
|
-
const [index, setIndex] =
|
|
967
|
-
const tickRef =
|
|
1376
|
+
const [index, setIndex] = useState2(() => normalizeFrameIndex(initialFrameIndex));
|
|
1377
|
+
const tickRef = useRef2(() => {
|
|
968
1378
|
return;
|
|
969
1379
|
});
|
|
970
1380
|
tickRef.current = () => setIndex((prev) => (prev + 1) % FRAME_COUNT);
|
|
971
|
-
|
|
1381
|
+
useEffect3(() => {
|
|
972
1382
|
if (registerTick) {
|
|
973
1383
|
registerTick(() => tickRef.current());
|
|
974
1384
|
return;
|
|
@@ -978,7 +1388,7 @@ var Spinner = ({
|
|
|
978
1388
|
}, intervalMs);
|
|
979
1389
|
return () => clearInterval(id);
|
|
980
1390
|
}, [intervalMs, registerTick]);
|
|
981
|
-
return /* @__PURE__ */
|
|
1391
|
+
return /* @__PURE__ */ jsxDEV6("text", {
|
|
982
1392
|
content: FRAMES[index] ?? FRAMES[0],
|
|
983
1393
|
wrapMode: "none",
|
|
984
1394
|
style: { fg }
|
|
@@ -986,7 +1396,7 @@ var Spinner = ({
|
|
|
986
1396
|
};
|
|
987
1397
|
|
|
988
1398
|
// src/StatusIndicator.tsx
|
|
989
|
-
import { jsxDEV as
|
|
1399
|
+
import { jsxDEV as jsxDEV7 } from "@opentui/react/jsx-dev-runtime";
|
|
990
1400
|
var statusIndicatorFg = (variant) => {
|
|
991
1401
|
switch (variant) {
|
|
992
1402
|
case "info":
|
|
@@ -1007,7 +1417,7 @@ var StatusIndicator = ({
|
|
|
1007
1417
|
}) => {
|
|
1008
1418
|
const activeColor = statusIndicatorFg(variant);
|
|
1009
1419
|
const backgroundColor = active ? activeColor : colors.backgroundElement;
|
|
1010
|
-
return /* @__PURE__ */
|
|
1420
|
+
return /* @__PURE__ */ jsxDEV7("box", {
|
|
1011
1421
|
...onMouseUp === undefined ? {} : { onMouseUp },
|
|
1012
1422
|
style: {
|
|
1013
1423
|
width: 3,
|
|
@@ -1015,7 +1425,7 @@ var StatusIndicator = ({
|
|
|
1015
1425
|
flexDirection: "row",
|
|
1016
1426
|
backgroundColor
|
|
1017
1427
|
},
|
|
1018
|
-
children: /* @__PURE__ */
|
|
1428
|
+
children: /* @__PURE__ */ jsxDEV7("text", {
|
|
1019
1429
|
content: ` ${icon} `,
|
|
1020
1430
|
wrapMode: "none",
|
|
1021
1431
|
style: {
|
|
@@ -1028,7 +1438,7 @@ var StatusIndicator = ({
|
|
|
1028
1438
|
};
|
|
1029
1439
|
|
|
1030
1440
|
// src/Footer.tsx
|
|
1031
|
-
import { jsxDEV as
|
|
1441
|
+
import { jsxDEV as jsxDEV8 } from "@opentui/react/jsx-dev-runtime";
|
|
1032
1442
|
var FOOTER_HEIGHT = 1;
|
|
1033
1443
|
var normalizeStatusLine = (status) => status.replace(/\s+/g, " ").trim();
|
|
1034
1444
|
var HINT_SEPARATOR = " ";
|
|
@@ -1118,17 +1528,17 @@ var Footer = ({
|
|
|
1118
1528
|
const statusContent = status ? status.slice(0, Math.max(0, statusBudget - statusChromeWidth)) : "";
|
|
1119
1529
|
const statusSeparatorContent = status ? STATUS_SEPARATOR.slice(0, Math.max(0, statusBudget - nonWarningStatusPrefixBudget - statusContent.length)) : "";
|
|
1120
1530
|
const noticeContent = notice ? notice.length > contentBudget ? notice.slice(0, contentBudget) : notice : null;
|
|
1121
|
-
const renderIndicators = () => renderedIndicators.map(({ id, ...props }) => /* @__PURE__ */
|
|
1531
|
+
const renderIndicators = () => renderedIndicators.map(({ id, ...props }) => /* @__PURE__ */ jsxDEV8(StatusIndicator, {
|
|
1122
1532
|
...props
|
|
1123
1533
|
}, id, false, undefined, this));
|
|
1124
|
-
const renderIndicatorContentGap = () => indicatorContentGapBudget > 0 ? /* @__PURE__ */
|
|
1534
|
+
const renderIndicatorContentGap = () => indicatorContentGapBudget > 0 ? /* @__PURE__ */ jsxDEV8("text", {
|
|
1125
1535
|
content: " ",
|
|
1126
1536
|
wrapMode: "none",
|
|
1127
1537
|
style: { fg: colors.textMuted }
|
|
1128
1538
|
}, undefined, false, undefined, this) : null;
|
|
1129
1539
|
const renderHints = () => visibleHints.flatMap((h, i) => {
|
|
1130
1540
|
const sep = i > 0 ? [
|
|
1131
|
-
/* @__PURE__ */
|
|
1541
|
+
/* @__PURE__ */ jsxDEV8("text", {
|
|
1132
1542
|
content: HINT_SEPARATOR,
|
|
1133
1543
|
wrapMode: "none",
|
|
1134
1544
|
style: { fg: colors.textMuted }
|
|
@@ -1136,12 +1546,12 @@ var Footer = ({
|
|
|
1136
1546
|
] : [];
|
|
1137
1547
|
return [
|
|
1138
1548
|
...sep,
|
|
1139
|
-
/* @__PURE__ */
|
|
1549
|
+
/* @__PURE__ */ jsxDEV8("text", {
|
|
1140
1550
|
content: h.key,
|
|
1141
1551
|
wrapMode: "none",
|
|
1142
1552
|
style: { fg: colors.text }
|
|
1143
1553
|
}, `k${i}`, false, undefined, this),
|
|
1144
|
-
/* @__PURE__ */
|
|
1554
|
+
/* @__PURE__ */ jsxDEV8("text", {
|
|
1145
1555
|
content: ` ${h.label}`,
|
|
1146
1556
|
wrapMode: "none",
|
|
1147
1557
|
style: { fg: colors.textMuted }
|
|
@@ -1149,12 +1559,12 @@ var Footer = ({
|
|
|
1149
1559
|
];
|
|
1150
1560
|
});
|
|
1151
1561
|
if (noticeContent !== null) {
|
|
1152
|
-
return /* @__PURE__ */
|
|
1562
|
+
return /* @__PURE__ */ jsxDEV8("box", {
|
|
1153
1563
|
style: rowStyle,
|
|
1154
1564
|
children: [
|
|
1155
1565
|
renderIndicators(),
|
|
1156
1566
|
renderIndicatorContentGap(),
|
|
1157
|
-
/* @__PURE__ */
|
|
1567
|
+
/* @__PURE__ */ jsxDEV8("text", {
|
|
1158
1568
|
content: noticeContent,
|
|
1159
1569
|
wrapMode: "none",
|
|
1160
1570
|
style: { fg: colors.primary }
|
|
@@ -1169,25 +1579,25 @@ var Footer = ({
|
|
|
1169
1579
|
...discoverySpinnerInitialFrameIndex === undefined ? {} : { initialFrameIndex: discoverySpinnerInitialFrameIndex },
|
|
1170
1580
|
...discoverySpinnerRegisterTick === undefined ? {} : { registerTick: discoverySpinnerRegisterTick }
|
|
1171
1581
|
};
|
|
1172
|
-
return /* @__PURE__ */
|
|
1582
|
+
return /* @__PURE__ */ jsxDEV8("box", {
|
|
1173
1583
|
style: rowStyle,
|
|
1174
1584
|
children: [
|
|
1175
1585
|
renderIndicators(),
|
|
1176
1586
|
renderIndicatorContentGap(),
|
|
1177
|
-
nonWarningStatusPrefixBudget >= 1 ? /* @__PURE__ */
|
|
1587
|
+
nonWarningStatusPrefixBudget >= 1 ? /* @__PURE__ */ jsxDEV8(Spinner, {
|
|
1178
1588
|
...spinnerProps
|
|
1179
1589
|
}, undefined, false, undefined, this) : null,
|
|
1180
|
-
nonWarningStatusPrefixBudget >= 2 ? /* @__PURE__ */
|
|
1590
|
+
nonWarningStatusPrefixBudget >= 2 ? /* @__PURE__ */ jsxDEV8("text", {
|
|
1181
1591
|
content: " ",
|
|
1182
1592
|
wrapMode: "none",
|
|
1183
1593
|
style: { fg: colors.textMuted }
|
|
1184
1594
|
}, undefined, false, undefined, this) : null,
|
|
1185
|
-
isPartialWarning ? null : /* @__PURE__ */
|
|
1595
|
+
isPartialWarning ? null : /* @__PURE__ */ jsxDEV8("text", {
|
|
1186
1596
|
content: statusContent,
|
|
1187
1597
|
wrapMode: "none",
|
|
1188
1598
|
style: { fg: colors.secondary }
|
|
1189
1599
|
}, undefined, false, undefined, this),
|
|
1190
|
-
statusSeparatorContent.length > 0 && /* @__PURE__ */
|
|
1600
|
+
statusSeparatorContent.length > 0 && /* @__PURE__ */ jsxDEV8("text", {
|
|
1191
1601
|
content: statusSeparatorContent,
|
|
1192
1602
|
wrapMode: "none",
|
|
1193
1603
|
style: { fg: colors.textMuted }
|
|
@@ -1196,7 +1606,7 @@ var Footer = ({
|
|
|
1196
1606
|
]
|
|
1197
1607
|
}, undefined, true, undefined, this);
|
|
1198
1608
|
}
|
|
1199
|
-
return /* @__PURE__ */
|
|
1609
|
+
return /* @__PURE__ */ jsxDEV8("box", {
|
|
1200
1610
|
style: rowStyle,
|
|
1201
1611
|
children: [
|
|
1202
1612
|
renderIndicators(),
|
|
@@ -1207,7 +1617,7 @@ var Footer = ({
|
|
|
1207
1617
|
};
|
|
1208
1618
|
|
|
1209
1619
|
// src/ui/middleTruncate.ts
|
|
1210
|
-
var
|
|
1620
|
+
var middleTruncate2 = (value, width, options = {}) => {
|
|
1211
1621
|
const ellipsis = options.ellipsis ?? "\u2026";
|
|
1212
1622
|
if (width <= 0)
|
|
1213
1623
|
return "";
|
|
@@ -1222,7 +1632,7 @@ var middleTruncate = (value, width, options = {}) => {
|
|
|
1222
1632
|
};
|
|
1223
1633
|
|
|
1224
1634
|
// src/Header.tsx
|
|
1225
|
-
import { jsxDEV as
|
|
1635
|
+
import { jsxDEV as jsxDEV9 } from "@opentui/react/jsx-dev-runtime";
|
|
1226
1636
|
var HEADER_HEIGHT = 1;
|
|
1227
1637
|
var FILE_SEPARATOR = " \xB7 ";
|
|
1228
1638
|
var HEADER_HORIZONTAL_PADDING = 2;
|
|
@@ -1249,7 +1659,7 @@ var layoutHeaderSegments = ({
|
|
|
1249
1659
|
const rootWidth = rootSegment === null ? 0 : usableWidth - joinedLength(segments) - FILE_SEPARATOR.length - HEADER_GROUP_GAP - right.length;
|
|
1250
1660
|
if (root !== null && root.length > rootWidth && rootWidth >= MIN_TRUNCATED_ROOT_WIDTH) {
|
|
1251
1661
|
return {
|
|
1252
|
-
left: [...segments, { id: "root", text:
|
|
1662
|
+
left: [...segments, { id: "root", text: middleTruncate2(root, rootWidth), tone: "muted" }],
|
|
1253
1663
|
right
|
|
1254
1664
|
};
|
|
1255
1665
|
}
|
|
@@ -1264,7 +1674,7 @@ var layoutHeaderSegments = ({
|
|
|
1264
1674
|
const fileWidth = usableWidth - BRAND.length - FILE_SEPARATOR.length;
|
|
1265
1675
|
if (fileWidth > 0) {
|
|
1266
1676
|
return {
|
|
1267
|
-
left: [iconBrand, { id: "file", text:
|
|
1677
|
+
left: [iconBrand, { id: "file", text: middleTruncate2(file, fileWidth), tone: "primary" }],
|
|
1268
1678
|
right: null
|
|
1269
1679
|
};
|
|
1270
1680
|
}
|
|
@@ -1278,7 +1688,7 @@ var fits = (segments, right, usableWidth) => {
|
|
|
1278
1688
|
};
|
|
1279
1689
|
var Header = ({ width, currentFile, rootLabel, version = package_default.version }) => {
|
|
1280
1690
|
const layout = layoutHeaderSegments({ width, currentFile, rootLabel, version });
|
|
1281
|
-
return /* @__PURE__ */
|
|
1691
|
+
return /* @__PURE__ */ jsxDEV9("box", {
|
|
1282
1692
|
style: {
|
|
1283
1693
|
width,
|
|
1284
1694
|
height: HEADER_HEIGHT,
|
|
@@ -1290,20 +1700,20 @@ var Header = ({ width, currentFile, rootLabel, version = package_default.version
|
|
|
1290
1700
|
backgroundColor: colors.backgroundPanel
|
|
1291
1701
|
},
|
|
1292
1702
|
children: [
|
|
1293
|
-
/* @__PURE__ */
|
|
1703
|
+
/* @__PURE__ */ jsxDEV9("text", {
|
|
1294
1704
|
wrapMode: "none",
|
|
1295
1705
|
children: layout.left.map((segment, idx) => [
|
|
1296
|
-
idx > 0 ? /* @__PURE__ */
|
|
1706
|
+
idx > 0 ? /* @__PURE__ */ jsxDEV9("span", {
|
|
1297
1707
|
style: { fg: colors.textMuted },
|
|
1298
1708
|
children: FILE_SEPARATOR
|
|
1299
1709
|
}, `${segment.id}-${idx}-separator`, false, undefined, this) : null,
|
|
1300
|
-
/* @__PURE__ */
|
|
1710
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
1301
1711
|
style: { fg: segment.tone === "primary" ? colors.text : colors.textMuted },
|
|
1302
1712
|
children: segment.text
|
|
1303
1713
|
}, `${segment.id}-${idx}`, false, undefined, this)
|
|
1304
1714
|
])
|
|
1305
1715
|
}, undefined, false, undefined, this),
|
|
1306
|
-
layout.right !== null && /* @__PURE__ */
|
|
1716
|
+
layout.right !== null && /* @__PURE__ */ jsxDEV9("text", {
|
|
1307
1717
|
content: layout.right,
|
|
1308
1718
|
wrapMode: "none",
|
|
1309
1719
|
style: { fg: colors.textMuted }
|
|
@@ -1510,55 +1920,56 @@ var resolveSidebarWidth = (viewport, preferred) => {
|
|
|
1510
1920
|
var defaultPreferredWidth = (viewport) => Math.max(SIDEBAR_MIN_WIDTH, Math.min(SIDEBAR_MAX_WIDTH, Math.floor(viewport * 0.25)));
|
|
1511
1921
|
var canFitInline = (viewport) => viewport >= SIDEBAR_MIN_WIDTH + DIVIDER_WIDTH + READER_MIN_WIDTH;
|
|
1512
1922
|
|
|
1513
|
-
// src/
|
|
1514
|
-
|
|
1515
|
-
var
|
|
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
|
-
|
|
1555
|
-
|
|
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);
|
|
1556
1967
|
};
|
|
1557
1968
|
|
|
1558
1969
|
// src/StatusPopover.tsx
|
|
1559
1970
|
import { useTerminalDimensions } from "@opentui/react";
|
|
1560
|
-
import { useMemo, useState as
|
|
1561
|
-
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";
|
|
1562
1973
|
var clamp2 = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
1563
1974
|
var measureLine = (line) => line.length;
|
|
1564
1975
|
var wrapLine = (line, width) => {
|
|
@@ -1596,7 +2007,7 @@ var StatusPopoverPanel = ({
|
|
|
1596
2007
|
while (linesToRender.length < popoverHeight - 2)
|
|
1597
2008
|
linesToRender.push("");
|
|
1598
2009
|
const borderColor = statusIndicatorFg(variant);
|
|
1599
|
-
return /* @__PURE__ */
|
|
2010
|
+
return /* @__PURE__ */ jsxDEV11("box", {
|
|
1600
2011
|
position: "absolute",
|
|
1601
2012
|
left: 1,
|
|
1602
2013
|
top: Math.max(0, viewportHeight - popoverHeight - 2),
|
|
@@ -1610,15 +2021,15 @@ var StatusPopoverPanel = ({
|
|
|
1610
2021
|
flexDirection: "column"
|
|
1611
2022
|
},
|
|
1612
2023
|
children: [
|
|
1613
|
-
/* @__PURE__ */
|
|
2024
|
+
/* @__PURE__ */ jsxDEV11("text", {
|
|
1614
2025
|
content: ""
|
|
1615
2026
|
}, undefined, false, undefined, this),
|
|
1616
|
-
linesToRender.map((line, i) => /* @__PURE__ */
|
|
2027
|
+
linesToRender.map((line, i) => /* @__PURE__ */ jsxDEV11("text", {
|
|
1617
2028
|
content: line,
|
|
1618
2029
|
wrapMode: "none",
|
|
1619
2030
|
style: { fg: colors.text }
|
|
1620
2031
|
}, i, false, undefined, this)),
|
|
1621
|
-
/* @__PURE__ */
|
|
2032
|
+
/* @__PURE__ */ jsxDEV11("text", {
|
|
1622
2033
|
content: ""
|
|
1623
2034
|
}, undefined, false, undefined, this)
|
|
1624
2035
|
]
|
|
@@ -8363,8 +8774,10 @@ var saveThemePreference = async (record, path = defaultConfigPath()) => {
|
|
|
8363
8774
|
};
|
|
8364
8775
|
|
|
8365
8776
|
// src/Browser.tsx
|
|
8366
|
-
import { jsxDEV as
|
|
8777
|
+
import { jsxDEV as jsxDEV12 } from "@opentui/react/jsx-dev-runtime";
|
|
8367
8778
|
var defaultReadFile = (path) => Effect3.runPromise(readFileText(path));
|
|
8779
|
+
var getFileId = (file) => file.path;
|
|
8780
|
+
var getFilePath = (file) => file.relativePath;
|
|
8368
8781
|
var clamp3 = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
8369
8782
|
var nextReaderEmptyStateTipRotation = 0;
|
|
8370
8783
|
var FILTER_DEBOUNCE_MS = 50;
|
|
@@ -8383,43 +8796,6 @@ var floatingOverlayReducer = (state, action) => {
|
|
|
8383
8796
|
return state.kind === "status-popover" ? { kind: "status-popover", content: action.content } : state;
|
|
8384
8797
|
}
|
|
8385
8798
|
};
|
|
8386
|
-
var SidebarEmptyMessage = ({
|
|
8387
|
-
label,
|
|
8388
|
-
value,
|
|
8389
|
-
width,
|
|
8390
|
-
withTopSpacer
|
|
8391
|
-
}) => /* @__PURE__ */ jsxDEV8(Fragment2, {
|
|
8392
|
-
children: [
|
|
8393
|
-
withTopSpacer && /* @__PURE__ */ jsxDEV8("text", {
|
|
8394
|
-
content: ""
|
|
8395
|
-
}, undefined, false, undefined, this),
|
|
8396
|
-
/* @__PURE__ */ jsxDEV8("box", {
|
|
8397
|
-
style: {
|
|
8398
|
-
width,
|
|
8399
|
-
flexDirection: "row",
|
|
8400
|
-
flexWrap: "wrap",
|
|
8401
|
-
justifyContent: "center",
|
|
8402
|
-
gap: 1
|
|
8403
|
-
},
|
|
8404
|
-
children: [
|
|
8405
|
-
/* @__PURE__ */ jsxDEV8("text", {
|
|
8406
|
-
wrapMode: "none",
|
|
8407
|
-
children: /* @__PURE__ */ jsxDEV8("span", {
|
|
8408
|
-
style: { fg: colors.textMuted },
|
|
8409
|
-
children: label
|
|
8410
|
-
}, undefined, false, undefined, this)
|
|
8411
|
-
}, undefined, false, undefined, this),
|
|
8412
|
-
/* @__PURE__ */ jsxDEV8("text", {
|
|
8413
|
-
wrapMode: "none",
|
|
8414
|
-
children: /* @__PURE__ */ jsxDEV8("span", {
|
|
8415
|
-
style: { fg: colors.textMuted },
|
|
8416
|
-
children: `"${fitSidebarEmptyValue(value, width)}"`
|
|
8417
|
-
}, undefined, false, undefined, this)
|
|
8418
|
-
}, undefined, false, undefined, this)
|
|
8419
|
-
]
|
|
8420
|
-
}, undefined, true, undefined, this)
|
|
8421
|
-
]
|
|
8422
|
-
}, undefined, true, undefined, this);
|
|
8423
8799
|
var Browser = ({
|
|
8424
8800
|
files,
|
|
8425
8801
|
initialIndex = 0,
|
|
@@ -8448,20 +8824,29 @@ var Browser = ({
|
|
|
8448
8824
|
const theme = useAtomValue(themeAtom);
|
|
8449
8825
|
const setTheme = useAtomSet(themeAtom);
|
|
8450
8826
|
const syntaxStyle = useMemo2(() => SyntaxStyle.fromStyles(colors.syntax), [theme]);
|
|
8451
|
-
const [
|
|
8452
|
-
const [
|
|
8453
|
-
const [
|
|
8454
|
-
const [
|
|
8455
|
-
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);
|
|
8456
8831
|
const startInFilter = startupFocus === "filter";
|
|
8457
8832
|
const initialFocus = startupFocus === null ? shown ? "sidebar" : "reader" : startupFocus === "reader" ? "reader" : "sidebar";
|
|
8458
|
-
const [focus, setFocus] =
|
|
8459
|
-
const [
|
|
8460
|
-
const [
|
|
8461
|
-
const [
|
|
8462
|
-
const
|
|
8463
|
-
|
|
8464
|
-
|
|
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);
|
|
8465
8850
|
const dispatchFloatingOverlay = (action) => {
|
|
8466
8851
|
const next = floatingOverlayReducer(floatingOverlayRef.current, action);
|
|
8467
8852
|
floatingOverlayRef.current = next;
|
|
@@ -8471,29 +8856,27 @@ var Browser = ({
|
|
|
8471
8856
|
const paletteOpen = floatingOverlay.kind === "command-palette";
|
|
8472
8857
|
const activeStatusPopover = floatingOverlay.kind === "status-popover" ? floatingOverlay : null;
|
|
8473
8858
|
const discoveryWarningStatus = isPartialDiscoveryWarning2(discoveryStatus) ? discoveryStatus : null;
|
|
8474
|
-
const [paletteQuery, setPaletteQuery] =
|
|
8475
|
-
const [paletteIndex, setPaletteIndex] =
|
|
8476
|
-
const paletteQueryRef =
|
|
8477
|
-
const paletteIndexRef =
|
|
8478
|
-
const [readerEmptyStateTipRotation, setReaderEmptyStateTipRotation] =
|
|
8479
|
-
const readerEmptyStateVisibleRef =
|
|
8480
|
-
const filterOpenRef =
|
|
8481
|
-
const filterInputRef =
|
|
8482
|
-
const
|
|
8483
|
-
const
|
|
8484
|
-
const
|
|
8485
|
-
const restoreFilterOnSidebarFocusRef = useRef2(startInFilter);
|
|
8486
|
-
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);
|
|
8487
8870
|
const pushFooterNotice = (text, ttlMs = 2000) => setFooterNoticeState({ text, ttlMs });
|
|
8488
|
-
const serverRef =
|
|
8489
|
-
const pendingSelectionPathRef =
|
|
8490
|
-
|
|
8871
|
+
const serverRef = useRef3(null);
|
|
8872
|
+
const pendingSelectionPathRef = useRef3(null);
|
|
8873
|
+
useEffect4(() => {
|
|
8491
8874
|
return () => {
|
|
8492
8875
|
serverRef.current?.stop();
|
|
8493
8876
|
serverRef.current = null;
|
|
8494
8877
|
};
|
|
8495
8878
|
}, []);
|
|
8496
|
-
|
|
8879
|
+
useEffect4(() => {
|
|
8497
8880
|
if (footerNotice === null)
|
|
8498
8881
|
return;
|
|
8499
8882
|
closeFloatingOverlay();
|
|
@@ -8502,7 +8885,7 @@ var Browser = ({
|
|
|
8502
8885
|
const timer = setTimeout(() => setFooterNoticeState(null), footerNotice.ttlMs);
|
|
8503
8886
|
return () => clearTimeout(timer);
|
|
8504
8887
|
}, [disableFooterNoticeAutoClear, footerNotice]);
|
|
8505
|
-
|
|
8888
|
+
useEffect4(() => {
|
|
8506
8889
|
if (discoveryWarningStatus === null) {
|
|
8507
8890
|
if (floatingOverlay.kind === "status-popover")
|
|
8508
8891
|
closeFloatingOverlay();
|
|
@@ -8512,11 +8895,11 @@ var Browser = ({
|
|
|
8512
8895
|
dispatchFloatingOverlay({ type: "update-status-popover", content: discoveryWarningStatus });
|
|
8513
8896
|
}
|
|
8514
8897
|
}, [discoveryWarningStatus, floatingOverlay]);
|
|
8515
|
-
const updateNoticeSeenRef =
|
|
8516
|
-
|
|
8898
|
+
const updateNoticeSeenRef = useRef3(null);
|
|
8899
|
+
useEffect4(() => {
|
|
8517
8900
|
focusRef.current = focus;
|
|
8518
8901
|
}, [focus]);
|
|
8519
|
-
|
|
8902
|
+
useEffect4(() => {
|
|
8520
8903
|
if (!updateNotice)
|
|
8521
8904
|
return;
|
|
8522
8905
|
if (updateNoticeSeenRef.current === updateNotice)
|
|
@@ -8551,55 +8934,27 @@ var Browser = ({
|
|
|
8551
8934
|
});
|
|
8552
8935
|
pushFooterNotice(`tone: ${nextTone}`);
|
|
8553
8936
|
};
|
|
8554
|
-
useEffect2(() => {
|
|
8555
|
-
if (filterInput === filterApplied)
|
|
8556
|
-
return;
|
|
8557
|
-
const timer = setTimeout(() => {
|
|
8558
|
-
filterAppliedRef.current = filterInput;
|
|
8559
|
-
setFilterApplied(filterInput);
|
|
8560
|
-
}, filterDebounceMs);
|
|
8561
|
-
return () => clearTimeout(timer);
|
|
8562
|
-
}, [filterApplied, filterDebounceMs, filterInput]);
|
|
8563
|
-
useEffect2(() => {
|
|
8564
|
-
autoSelectForAppliedFilterRef.current = true;
|
|
8565
|
-
}, [filterApplied]);
|
|
8566
|
-
const displayedFiles = useMemo2(() => filterFiles(files, filterApplied), [files, filterApplied]);
|
|
8567
8937
|
const filterHasNoMatches = filterInput.length > 0 && displayedFiles.length === 0;
|
|
8568
|
-
|
|
8569
|
-
if (filterApplied.length === 0)
|
|
8570
|
-
return;
|
|
8571
|
-
if (!autoSelectForAppliedFilterRef.current)
|
|
8572
|
-
return;
|
|
8573
|
-
if (displayedFiles.length === 0)
|
|
8574
|
-
return;
|
|
8575
|
-
setSelectedIndex(0);
|
|
8576
|
-
autoSelectForAppliedFilterRef.current = false;
|
|
8577
|
-
}, [displayedFiles, filterApplied]);
|
|
8578
|
-
useEffect2(() => {
|
|
8579
|
-
if (selectedIndex >= displayedFiles.length) {
|
|
8580
|
-
setSelectedIndex(displayedFiles.length === 0 ? 0 : displayedFiles.length - 1);
|
|
8581
|
-
}
|
|
8582
|
-
}, [displayedFiles.length, selectedIndex]);
|
|
8583
|
-
useEffect2(() => {
|
|
8938
|
+
useEffect4(() => {
|
|
8584
8939
|
const target = pendingSelectionPathRef.current;
|
|
8585
8940
|
if (target === null)
|
|
8586
8941
|
return;
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8942
|
+
if (displayedFiles.some((file) => file.path === target)) {
|
|
8943
|
+
const snapshot = navigator.selectId(target);
|
|
8944
|
+
if (snapshot.selectedFile?.path !== target)
|
|
8945
|
+
return;
|
|
8590
8946
|
pendingSelectionPathRef.current = null;
|
|
8591
8947
|
}
|
|
8592
8948
|
}, [displayedFiles]);
|
|
8593
|
-
const
|
|
8594
|
-
|
|
8595
|
-
useEffect2(() => {
|
|
8949
|
+
const [renderedPath, setRenderedPath] = useState4(selected?.path ?? null);
|
|
8950
|
+
useEffect4(() => {
|
|
8596
8951
|
const target = selected?.path ?? null;
|
|
8597
8952
|
if (target === renderedPath)
|
|
8598
8953
|
return;
|
|
8599
8954
|
const timer = setTimeout(() => setRenderedPath(target), renderedPathDebounceMs);
|
|
8600
8955
|
return () => clearTimeout(timer);
|
|
8601
8956
|
}, [selected?.path, renderedPath, renderedPathDebounceMs]);
|
|
8602
|
-
|
|
8957
|
+
useEffect4(() => {
|
|
8603
8958
|
if (!renderedPath) {
|
|
8604
8959
|
setLoaded(null);
|
|
8605
8960
|
return;
|
|
@@ -8631,10 +8986,20 @@ var Browser = ({
|
|
|
8631
8986
|
paletteOpen,
|
|
8632
8987
|
wrapEnabled,
|
|
8633
8988
|
setFocus,
|
|
8634
|
-
|
|
8989
|
+
moveSelectionBy: (delta) => {
|
|
8990
|
+
pendingSelectionPathRef.current = null;
|
|
8991
|
+
navigator.cancelAutoSelect();
|
|
8992
|
+
navigator.moveBy(delta);
|
|
8993
|
+
},
|
|
8994
|
+
selectFirst: () => {
|
|
8995
|
+
pendingSelectionPathRef.current = null;
|
|
8996
|
+
navigator.cancelAutoSelect();
|
|
8997
|
+
navigator.selectFirst();
|
|
8998
|
+
},
|
|
8999
|
+
selectLast: () => {
|
|
8635
9000
|
pendingSelectionPathRef.current = null;
|
|
8636
|
-
|
|
8637
|
-
|
|
9001
|
+
navigator.cancelAutoSelect();
|
|
9002
|
+
navigator.selectLast();
|
|
8638
9003
|
},
|
|
8639
9004
|
toggleShown: () => {
|
|
8640
9005
|
if (!canFitInline(width)) {
|
|
@@ -8665,10 +9030,9 @@ var Browser = ({
|
|
|
8665
9030
|
clearAndOpenFilter: () => {
|
|
8666
9031
|
closeFloatingOverlay();
|
|
8667
9032
|
filterInputRef.current = "";
|
|
8668
|
-
filterAppliedRef.current = "";
|
|
8669
9033
|
setFilterInput("");
|
|
8670
|
-
|
|
8671
|
-
|
|
9034
|
+
navigator.flushSearch("");
|
|
9035
|
+
navigator.selectFirst();
|
|
8672
9036
|
focusRef.current = "sidebar";
|
|
8673
9037
|
if (focus !== "sidebar")
|
|
8674
9038
|
setFocus("sidebar");
|
|
@@ -8687,13 +9051,14 @@ var Browser = ({
|
|
|
8687
9051
|
cycleTheme,
|
|
8688
9052
|
toggleTone,
|
|
8689
9053
|
toggleAll: () => {
|
|
8690
|
-
|
|
8691
|
-
|
|
9054
|
+
const current = navigator.getSnapshot().selectedFile;
|
|
9055
|
+
if (pendingSelectionPathRef.current === null && current) {
|
|
9056
|
+
pendingSelectionPathRef.current = current.path;
|
|
8692
9057
|
}
|
|
8693
9058
|
onToggleAll?.();
|
|
8694
9059
|
},
|
|
8695
9060
|
serveCurrent: () => {
|
|
8696
|
-
const file =
|
|
9061
|
+
const file = navigator.getSnapshot().selectedFile;
|
|
8697
9062
|
if (!file)
|
|
8698
9063
|
return;
|
|
8699
9064
|
let handle = serverRef.current;
|
|
@@ -8723,7 +9088,7 @@ var Browser = ({
|
|
|
8723
9088
|
process.exit(0);
|
|
8724
9089
|
},
|
|
8725
9090
|
editCurrent: () => {
|
|
8726
|
-
const file =
|
|
9091
|
+
const file = navigator.getSnapshot().selectedFile;
|
|
8727
9092
|
if (!file)
|
|
8728
9093
|
return;
|
|
8729
9094
|
const editor = resolveEditor(process.env);
|
|
@@ -8773,7 +9138,7 @@ var Browser = ({
|
|
|
8773
9138
|
})();
|
|
8774
9139
|
},
|
|
8775
9140
|
copyCurrentContents: () => {
|
|
8776
|
-
const file =
|
|
9141
|
+
const file = navigator.getSnapshot().selectedFile;
|
|
8777
9142
|
if (!file)
|
|
8778
9143
|
return;
|
|
8779
9144
|
(async () => {
|
|
@@ -8856,9 +9221,8 @@ var Browser = ({
|
|
|
8856
9221
|
}
|
|
8857
9222
|
if (filterOpenRef.current && focusRef.current === "sidebar") {
|
|
8858
9223
|
const closeFilter = (commit) => {
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
const picked = displayedFiles[selectedIndex] ?? null;
|
|
9224
|
+
const snapshot = navigator.flushSearch(filterInputRef.current);
|
|
9225
|
+
const picked = snapshot.selectedFile;
|
|
8862
9226
|
const effectiveCommit = commit && picked !== null;
|
|
8863
9227
|
restoreFilterOnSidebarFocusRef.current = false;
|
|
8864
9228
|
filterOpenRef.current = false;
|
|
@@ -8894,10 +9258,9 @@ var Browser = ({
|
|
|
8894
9258
|
}
|
|
8895
9259
|
if (key.ctrl && key.name === "\\") {
|
|
8896
9260
|
filterInputRef.current = "";
|
|
8897
|
-
filterAppliedRef.current = "";
|
|
8898
9261
|
setFilterInput("");
|
|
8899
|
-
|
|
8900
|
-
|
|
9262
|
+
navigator.flushSearch("");
|
|
9263
|
+
navigator.selectFirst();
|
|
8901
9264
|
return;
|
|
8902
9265
|
}
|
|
8903
9266
|
if (key.name === "backspace" || key.name === "delete") {
|
|
@@ -8907,15 +9270,15 @@ var Browser = ({
|
|
|
8907
9270
|
}
|
|
8908
9271
|
filterInputRef.current = filterInputRef.current.slice(0, -1);
|
|
8909
9272
|
setFilterInput(filterInputRef.current);
|
|
8910
|
-
|
|
9273
|
+
navigator.selectIndex(0);
|
|
8911
9274
|
return;
|
|
8912
9275
|
}
|
|
8913
9276
|
if (key.name === "up") {
|
|
8914
|
-
|
|
9277
|
+
navigator.moveBy(-1);
|
|
8915
9278
|
return;
|
|
8916
9279
|
}
|
|
8917
9280
|
if (key.name === "down") {
|
|
8918
|
-
|
|
9281
|
+
navigator.moveBy(1);
|
|
8919
9282
|
return;
|
|
8920
9283
|
}
|
|
8921
9284
|
if (key.ctrl || key.meta)
|
|
@@ -8929,7 +9292,7 @@ var Browser = ({
|
|
|
8929
9292
|
if (char !== null) {
|
|
8930
9293
|
filterInputRef.current = filterInputRef.current + char;
|
|
8931
9294
|
setFilterInput(filterInputRef.current);
|
|
8932
|
-
|
|
9295
|
+
navigator.selectIndex(0);
|
|
8933
9296
|
}
|
|
8934
9297
|
return;
|
|
8935
9298
|
}
|
|
@@ -8949,7 +9312,7 @@ var Browser = ({
|
|
|
8949
9312
|
const parsedContent = useMemo2(() => parseFrontmatter(content), [content]);
|
|
8950
9313
|
const readerEmptyStateTitle = filterHasNoMatches ? `No files match: ${filterInput}` : `${BRAND} ${BRAND_NAME}`;
|
|
8951
9314
|
const readerEmptyStateVisible = error == null && renderedPath == null;
|
|
8952
|
-
|
|
9315
|
+
useEffect4(() => {
|
|
8953
9316
|
if (disableReaderEmptyStateRotation)
|
|
8954
9317
|
return;
|
|
8955
9318
|
if (readerEmptyStateVisible) {
|
|
@@ -8962,25 +9325,6 @@ var Browser = ({
|
|
|
8962
9325
|
readerEmptyStateVisibleRef.current = false;
|
|
8963
9326
|
}, [disableReaderEmptyStateRotation, readerEmptyStateVisible]);
|
|
8964
9327
|
const discoveryActive = discoveryStatus !== null && discoveryStatus.length > 0;
|
|
8965
|
-
const filterRowVisible = files.length > 0 || discoveryActive;
|
|
8966
|
-
const sidebarBodyHeight = Math.max(1, height - FOOTER_HEIGHT - HEADER_HEIGHT - 2 - (filterRowVisible ? 1 : 0));
|
|
8967
|
-
const maxScroll = Math.max(0, displayedFiles.length - sidebarBodyHeight);
|
|
8968
|
-
const desiredScroll = (() => {
|
|
8969
|
-
let s = sidebarScroll;
|
|
8970
|
-
if (selectedIndex < s)
|
|
8971
|
-
s = selectedIndex;
|
|
8972
|
-
else if (selectedIndex >= s + sidebarBodyHeight)
|
|
8973
|
-
s = selectedIndex - sidebarBodyHeight + 1;
|
|
8974
|
-
return clamp3(s, 0, maxScroll);
|
|
8975
|
-
})();
|
|
8976
|
-
useEffect2(() => {
|
|
8977
|
-
if (desiredScroll !== sidebarScroll)
|
|
8978
|
-
setSidebarScroll(desiredScroll);
|
|
8979
|
-
}, [desiredScroll, sidebarScroll]);
|
|
8980
|
-
const visibleFiles = displayedFiles.slice(desiredScroll, desiredScroll + sidebarBodyHeight);
|
|
8981
|
-
const sidebarPaneWidth = isNarrow ? width : sidebarWidth;
|
|
8982
|
-
const sidebarTextWidth = Math.max(4, sidebarPaneWidth - (isNarrow ? 1 : 2));
|
|
8983
|
-
const layoutSidebarRow = useCallback((relativePath) => formatSidebarRow(relativePath, sidebarTextWidth), [sidebarTextWidth]);
|
|
8984
9328
|
const footerProps = {
|
|
8985
9329
|
bindings: browserBindings,
|
|
8986
9330
|
ctx,
|
|
@@ -9008,74 +9352,17 @@ var Browser = ({
|
|
|
9008
9352
|
};
|
|
9009
9353
|
const readerEmptyStateTips = useMemo2(() => buildReaderEmptyStateTips(browserBindings, ctx), [ctx]);
|
|
9010
9354
|
const readerEmptyStateTip = useMemo2(() => pickTipByRotation(readerEmptyStateTips, readerEmptyStateTipRotation), [readerEmptyStateTipRotation, readerEmptyStateTips]);
|
|
9011
|
-
const sidebarBody = /* @__PURE__ */ jsxDEV8(Fragment2, {
|
|
9012
|
-
children: [
|
|
9013
|
-
filterRowVisible && /* @__PURE__ */ jsxDEV8(PromptRow, {
|
|
9014
|
-
query: filterInput,
|
|
9015
|
-
editing: filterOpen,
|
|
9016
|
-
placeholder: "type / to filter",
|
|
9017
|
-
width: sidebarTextWidth
|
|
9018
|
-
}, undefined, false, undefined, this),
|
|
9019
|
-
displayedFiles.length === 0 ? /* @__PURE__ */ jsxDEV8(SidebarEmptyMessage, {
|
|
9020
|
-
withTopSpacer: filterRowVisible,
|
|
9021
|
-
width: sidebarTextWidth,
|
|
9022
|
-
label: files.length === 0 ? discoveryActive ? "Scanning" : "No markdown files in" : "No files match",
|
|
9023
|
-
value: files.length === 0 ? discoveryActive ? "\u2026" : rootLabel : filterApplied
|
|
9024
|
-
}, undefined, false, undefined, this) : visibleFiles.map((file, idx) => {
|
|
9025
|
-
const realIdx = desiredScroll + idx;
|
|
9026
|
-
const isSelected = realIdx === selectedIndex;
|
|
9027
|
-
const { basename: basename2, separator, parent } = layoutSidebarRow(file.relativePath);
|
|
9028
|
-
const basenameFg = isSelected ? colors.selectedListItemText : colors.text;
|
|
9029
|
-
const rowStyle = {
|
|
9030
|
-
width: sidebarTextWidth,
|
|
9031
|
-
height: 1,
|
|
9032
|
-
flexDirection: "row",
|
|
9033
|
-
...isSelected ? { backgroundColor: colors.backgroundElement } : {}
|
|
9034
|
-
};
|
|
9035
|
-
return /* @__PURE__ */ jsxDEV8("box", {
|
|
9036
|
-
style: rowStyle,
|
|
9037
|
-
children: /* @__PURE__ */ jsxDEV8("text", {
|
|
9038
|
-
wrapMode: "none",
|
|
9039
|
-
children: [
|
|
9040
|
-
/* @__PURE__ */ jsxDEV8("span", {
|
|
9041
|
-
style: { fg: basenameFg },
|
|
9042
|
-
children: basename2
|
|
9043
|
-
}, undefined, false, undefined, this),
|
|
9044
|
-
parent !== "" && /* @__PURE__ */ jsxDEV8("span", {
|
|
9045
|
-
style: { fg: colors.textMuted },
|
|
9046
|
-
children: middleTruncate(`${separator}${parent}`, Math.max(0, sidebarTextWidth - basename2.length))
|
|
9047
|
-
}, undefined, false, undefined, this)
|
|
9048
|
-
]
|
|
9049
|
-
}, undefined, true, undefined, this)
|
|
9050
|
-
}, file.path, false, undefined, this);
|
|
9051
|
-
})
|
|
9052
|
-
]
|
|
9053
|
-
}, undefined, true, undefined, this);
|
|
9054
|
-
const sidebarBorderSides = ["top", "bottom", "right"];
|
|
9055
9355
|
const readerBorderSides = ["top", "bottom"];
|
|
9056
|
-
const
|
|
9057
|
-
|
|
9058
|
-
topRight: "\u252C",
|
|
9059
|
-
bottomLeft: "\u2514",
|
|
9060
|
-
bottomRight: "\u2534",
|
|
9061
|
-
horizontal: "\u2500",
|
|
9062
|
-
vertical: "\u2502",
|
|
9063
|
-
topT: "\u252C",
|
|
9064
|
-
bottomT: "\u2534",
|
|
9065
|
-
leftT: "\u251C",
|
|
9066
|
-
rightT: "\u2524",
|
|
9067
|
-
cross: "\u253C"
|
|
9068
|
-
};
|
|
9069
|
-
const INACTIVE_PANE_OPACITY = 0.62;
|
|
9070
|
-
return /* @__PURE__ */ jsxDEV8("box", {
|
|
9356
|
+
const INACTIVE_PANE_OPACITY2 = 0.62;
|
|
9357
|
+
return /* @__PURE__ */ jsxDEV12("box", {
|
|
9071
9358
|
style: { width, height, flexDirection: "column", backgroundColor: colors.backgroundPanel },
|
|
9072
9359
|
children: [
|
|
9073
|
-
/* @__PURE__ */
|
|
9360
|
+
/* @__PURE__ */ jsxDEV12(Header, {
|
|
9074
9361
|
width,
|
|
9075
9362
|
currentFile,
|
|
9076
9363
|
rootLabel
|
|
9077
9364
|
}, undefined, false, undefined, this),
|
|
9078
|
-
/* @__PURE__ */
|
|
9365
|
+
/* @__PURE__ */ jsxDEV12("box", {
|
|
9079
9366
|
style: {
|
|
9080
9367
|
flexDirection: "row",
|
|
9081
9368
|
flexGrow: 1,
|
|
@@ -9083,28 +9370,20 @@ var Browser = ({
|
|
|
9083
9370
|
backgroundColor: colors.backgroundPanel
|
|
9084
9371
|
},
|
|
9085
9372
|
children: [
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
flexShrink: 1,
|
|
9099
|
-
flexDirection: "column",
|
|
9100
|
-
paddingLeft: 1,
|
|
9101
|
-
backgroundColor: sidebarActive ? colors.background : colors.backgroundPanel,
|
|
9102
|
-
opacity: sidebarActive ? 1 : INACTIVE_PANE_OPACITY
|
|
9103
|
-
},
|
|
9104
|
-
children: sidebarBody
|
|
9105
|
-
}, 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
|
|
9106
9385
|
}, undefined, false, undefined, this),
|
|
9107
|
-
readerVisible && /* @__PURE__ */
|
|
9386
|
+
readerVisible && /* @__PURE__ */ jsxDEV12("box", {
|
|
9108
9387
|
style: {
|
|
9109
9388
|
border: readerBorderSides,
|
|
9110
9389
|
borderColor: colors.border,
|
|
@@ -9113,19 +9392,19 @@ var Browser = ({
|
|
|
9113
9392
|
flexDirection: "column",
|
|
9114
9393
|
backgroundColor: colors.backgroundPanel
|
|
9115
9394
|
},
|
|
9116
|
-
children: /* @__PURE__ */
|
|
9395
|
+
children: /* @__PURE__ */ jsxDEV12("box", {
|
|
9117
9396
|
style: {
|
|
9118
9397
|
flexGrow: 1,
|
|
9119
9398
|
flexShrink: 1,
|
|
9120
9399
|
flexDirection: "column",
|
|
9121
9400
|
padding: 1,
|
|
9122
9401
|
backgroundColor: readerActive ? colors.background : colors.backgroundPanel,
|
|
9123
|
-
opacity: readerActive ? 1 :
|
|
9402
|
+
opacity: readerActive ? 1 : INACTIVE_PANE_OPACITY2
|
|
9124
9403
|
},
|
|
9125
|
-
children: error ? /* @__PURE__ */
|
|
9404
|
+
children: error ? /* @__PURE__ */ jsxDEV12("text", {
|
|
9126
9405
|
content: error,
|
|
9127
9406
|
style: { fg: colors.error }
|
|
9128
|
-
}, undefined, false, undefined, this) : !renderedPath ? /* @__PURE__ */
|
|
9407
|
+
}, undefined, false, undefined, this) : !renderedPath ? /* @__PURE__ */ jsxDEV12("box", {
|
|
9129
9408
|
style: {
|
|
9130
9409
|
flexGrow: 1,
|
|
9131
9410
|
flexShrink: 1,
|
|
@@ -9133,22 +9412,22 @@ var Browser = ({
|
|
|
9133
9412
|
justifyContent: "center",
|
|
9134
9413
|
backgroundColor: readerActive ? colors.background : colors.backgroundPanel
|
|
9135
9414
|
},
|
|
9136
|
-
children: /* @__PURE__ */
|
|
9415
|
+
children: /* @__PURE__ */ jsxDEV12("box", {
|
|
9137
9416
|
style: { flexDirection: "column", gap: 1, alignItems: "center" },
|
|
9138
9417
|
children: [
|
|
9139
|
-
/* @__PURE__ */
|
|
9418
|
+
/* @__PURE__ */ jsxDEV12("text", {
|
|
9140
9419
|
content: readerEmptyStateTitle,
|
|
9141
9420
|
wrapMode: "none",
|
|
9142
9421
|
style: { fg: colors.textMuted }
|
|
9143
9422
|
}, undefined, false, undefined, this),
|
|
9144
|
-
readerEmptyStateTip && /* @__PURE__ */
|
|
9423
|
+
readerEmptyStateTip && /* @__PURE__ */ jsxDEV12("text", {
|
|
9145
9424
|
content: readerEmptyStateTip.text,
|
|
9146
9425
|
wrapMode: "none",
|
|
9147
9426
|
style: { fg: colors.textMuted }
|
|
9148
9427
|
}, readerEmptyStateTip.id, false, undefined, this)
|
|
9149
9428
|
]
|
|
9150
9429
|
}, undefined, true, undefined, this)
|
|
9151
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
9430
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV12("scrollbox", {
|
|
9152
9431
|
style: {
|
|
9153
9432
|
scrollY: true,
|
|
9154
9433
|
scrollX: false,
|
|
@@ -9158,17 +9437,17 @@ var Browser = ({
|
|
|
9158
9437
|
},
|
|
9159
9438
|
focused: readerActive && !paletteOpen,
|
|
9160
9439
|
children: [
|
|
9161
|
-
parsedContent.fields.length > 0 && /* @__PURE__ */
|
|
9440
|
+
parsedContent.fields.length > 0 && /* @__PURE__ */ jsxDEV12("box", {
|
|
9162
9441
|
style: { flexDirection: "column", marginBottom: 1 },
|
|
9163
|
-
children: parsedContent.fields.map((field) => /* @__PURE__ */
|
|
9442
|
+
children: parsedContent.fields.map((field) => /* @__PURE__ */ jsxDEV12("box", {
|
|
9164
9443
|
style: { flexDirection: "row", gap: 1, flexWrap: "wrap" },
|
|
9165
9444
|
children: [
|
|
9166
|
-
/* @__PURE__ */
|
|
9445
|
+
/* @__PURE__ */ jsxDEV12("text", {
|
|
9167
9446
|
content: `${field.key}:`,
|
|
9168
9447
|
wrapMode: "word",
|
|
9169
9448
|
style: { fg: colors.secondary }
|
|
9170
9449
|
}, undefined, false, undefined, this),
|
|
9171
|
-
/* @__PURE__ */
|
|
9450
|
+
/* @__PURE__ */ jsxDEV12("text", {
|
|
9172
9451
|
content: field.value,
|
|
9173
9452
|
wrapMode: "word",
|
|
9174
9453
|
style: { fg: colors.textMuted }
|
|
@@ -9176,7 +9455,7 @@ var Browser = ({
|
|
|
9176
9455
|
]
|
|
9177
9456
|
}, field.key, true, undefined, this))
|
|
9178
9457
|
}, undefined, false, undefined, this),
|
|
9179
|
-
/* @__PURE__ */
|
|
9458
|
+
/* @__PURE__ */ jsxDEV12("markdown", {
|
|
9180
9459
|
content: parsedContent.body,
|
|
9181
9460
|
syntaxStyle,
|
|
9182
9461
|
fg: colors.text,
|
|
@@ -9190,17 +9469,17 @@ var Browser = ({
|
|
|
9190
9469
|
}, undefined, false, undefined, this)
|
|
9191
9470
|
]
|
|
9192
9471
|
}, undefined, true, undefined, this),
|
|
9193
|
-
/* @__PURE__ */
|
|
9472
|
+
/* @__PURE__ */ jsxDEV12(Footer, {
|
|
9194
9473
|
...footerProps
|
|
9195
9474
|
}, undefined, false, undefined, this),
|
|
9196
|
-
paletteOpen && /* @__PURE__ */
|
|
9475
|
+
paletteOpen && /* @__PURE__ */ jsxDEV12(CommandPalette, {
|
|
9197
9476
|
commands: orderCommandsForPalette(filterCommands(buildCommands(ctx), paletteQuery)),
|
|
9198
9477
|
query: paletteQuery,
|
|
9199
9478
|
selectedIndex: paletteIndex,
|
|
9200
9479
|
viewportWidth: width,
|
|
9201
9480
|
viewportHeight: height
|
|
9202
9481
|
}, undefined, false, undefined, this),
|
|
9203
|
-
activeStatusPopover && /* @__PURE__ */
|
|
9482
|
+
activeStatusPopover && /* @__PURE__ */ jsxDEV12(StatusPopoverPanel, {
|
|
9204
9483
|
content: activeStatusPopover.content,
|
|
9205
9484
|
variant: "warning"
|
|
9206
9485
|
}, undefined, false, undefined, this)
|
|
@@ -9677,13 +9956,13 @@ var subscribeUpdateInfo = (cb) => {
|
|
|
9677
9956
|
};
|
|
9678
9957
|
|
|
9679
9958
|
// src/update/useUpdateNotice.ts
|
|
9680
|
-
import { useEffect as
|
|
9959
|
+
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
9681
9960
|
var useUpdateNotice = () => {
|
|
9682
|
-
const [text, setText] =
|
|
9961
|
+
const [text, setText] = useState5(() => {
|
|
9683
9962
|
const cur = currentUpdateInfo();
|
|
9684
9963
|
return cur ? formatFooterNotice(cur) : null;
|
|
9685
9964
|
});
|
|
9686
|
-
|
|
9965
|
+
useEffect5(() => {
|
|
9687
9966
|
const unsub = subscribeUpdateInfo((info) => setText(formatFooterNotice(info)));
|
|
9688
9967
|
return unsub;
|
|
9689
9968
|
}, []);
|
|
@@ -9691,7 +9970,7 @@ var useUpdateNotice = () => {
|
|
|
9691
9970
|
};
|
|
9692
9971
|
|
|
9693
9972
|
// src/index.tsx
|
|
9694
|
-
import { jsxDEV as
|
|
9973
|
+
import { jsxDEV as jsxDEV13 } from "@opentui/react/jsx-dev-runtime";
|
|
9695
9974
|
var pathIsDirectory = async (path) => {
|
|
9696
9975
|
try {
|
|
9697
9976
|
return (await stat(path)).isDirectory();
|
|
@@ -9755,14 +10034,14 @@ var DiscoverShell = ({
|
|
|
9755
10034
|
startupFocus
|
|
9756
10035
|
}) => {
|
|
9757
10036
|
const updateNotice = useUpdateNotice();
|
|
9758
|
-
const [show, setShow] =
|
|
9759
|
-
const [files, setFiles] =
|
|
9760
|
-
const [scanning, setScanning] =
|
|
9761
|
-
const [scanError, setScanError] =
|
|
9762
|
-
const [skippedDirCount, setSkippedDirCount] =
|
|
9763
|
-
const [lastSkippedDir, setLastSkippedDir] =
|
|
9764
|
-
const countRef =
|
|
9765
|
-
|
|
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(() => {
|
|
9766
10045
|
setFiles([]);
|
|
9767
10046
|
setScanning(true);
|
|
9768
10047
|
setScanError(null);
|
|
@@ -9801,7 +10080,7 @@ var DiscoverShell = ({
|
|
|
9801
10080
|
skippedCount: skippedDirCount,
|
|
9802
10081
|
lastSkippedPath: lastSkippedDir
|
|
9803
10082
|
}));
|
|
9804
|
-
return /* @__PURE__ */
|
|
10083
|
+
return /* @__PURE__ */ jsxDEV13(Browser, {
|
|
9805
10084
|
files,
|
|
9806
10085
|
initialQuery,
|
|
9807
10086
|
wrapWidth,
|
|
@@ -9981,9 +10260,9 @@ async function runTui({
|
|
|
9981
10260
|
console.error(`house: ${err instanceof Error ? err.message : String(err)}`);
|
|
9982
10261
|
process.exit(1);
|
|
9983
10262
|
}
|
|
9984
|
-
createRoot(renderer).render(/* @__PURE__ */
|
|
10263
|
+
createRoot(renderer).render(/* @__PURE__ */ jsxDEV13(RegistryProvider, {
|
|
9985
10264
|
initialValues: [[themeAtom, initialTheme]],
|
|
9986
|
-
children: /* @__PURE__ */
|
|
10265
|
+
children: /* @__PURE__ */ jsxDEV13(DiscoverShell, {
|
|
9987
10266
|
target: discoveryRoot,
|
|
9988
10267
|
initialQuery,
|
|
9989
10268
|
initialShow: show,
|