@parallelworks/ui 0.52.0 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -8
- package/dist/access/AccessDrawer.d.ts +55 -0
- package/dist/access/AccessDrawer.js +445 -0
- package/dist/access/AccessList.d.ts +58 -0
- package/dist/access/AccessList.js +382 -0
- package/dist/access/GrantView.d.ts +35 -0
- package/dist/access/GrantView.js +188 -0
- package/dist/access/GroupPicker.d.ts +35 -0
- package/dist/access/GroupPicker.js +336 -0
- package/dist/access/focus.d.ts +10 -0
- package/dist/access/focus.js +27 -0
- package/dist/access/index.d.ts +3 -0
- package/dist/access/index.js +3 -0
- package/dist/access/model.d.ts +49 -0
- package/dist/access/model.js +129 -0
- package/dist/access/strings.d.ts +122 -0
- package/dist/access/strings.js +151 -0
- package/dist/access/types.d.ts +56 -0
- package/dist/ai/ai.css +5 -3
- package/dist/ai/components/SlashMenu.js +1 -1
- package/dist/ai/components/agent/AgentMessageParts.js +1 -1
- package/dist/ai/strings.js +0 -1
- package/dist/ai/ui/sidebar.js +1 -1
- package/dist/components/Combobox.d.ts +19 -0
- package/dist/components/Combobox.js +101 -50
- package/dist/components/Drawer.d.ts +6 -1
- package/dist/components/Drawer.js +25 -16
- package/dist/components/Field.d.ts +5 -4
- package/dist/components/Field.js +27 -4
- package/dist/components/InfoTip.d.ts +12 -4
- package/dist/components/InfoTip.js +13 -3
- package/dist/components/MarkdownImpl.d.ts +1 -0
- package/dist/components/MarkdownImpl.js +1 -0
- package/dist/components/Menu.js +4 -4
- package/dist/components/MenuEntries.js +1 -1
- package/dist/components/OptionDescription.d.ts +7 -0
- package/dist/components/OptionDescription.js +19 -0
- package/dist/components/Popover.d.ts +4 -1
- package/dist/components/Popover.js +2 -1
- package/dist/components/Provider.d.ts +9 -0
- package/dist/components/Provider.js +4 -0
- package/dist/components/Select.js +13 -11
- package/dist/components/comboboxItems.d.ts +10 -0
- package/dist/components/comboboxItems.js +8 -1
- package/dist/components/floating.d.ts +5 -2
- package/dist/components/floating.js +2 -2
- package/dist/components/focus.d.ts +5 -0
- package/dist/components/focus.js +21 -1
- package/dist/editor/Editor.js +13 -3
- package/dist/editor/Monaco.d.ts +8 -1
- package/dist/editor/Monaco.js +16 -3
- package/dist/editor/editorModel.d.ts +1 -1
- package/dist/editor/editorModel.js +1 -1
- package/dist/editor/index.d.ts +1 -0
- package/dist/editor/index.js +2 -1
- package/dist/editor/languages.d.ts +24 -0
- package/dist/editor/languages.js +31 -0
- package/dist/editor/monacoFeatures.d.ts +7 -0
- package/dist/editor/monacoFeatures.js +19 -0
- package/dist/editor/themes.d.ts +5 -0
- package/dist/editor/themes.js +24 -4
- package/dist/editor/workers.d.ts +3 -3
- package/dist/editor/workers.js +8 -4
- package/dist/editor/yamlLanguage.js +55 -38
- package/dist/file-explorer/FileExplorer.d.ts +18 -4
- package/dist/file-explorer/FileExplorer.js +64 -20
- package/dist/file-explorer/FilePreview/Viewer.js +12 -8
- package/dist/file-explorer/FileRow.d.ts +6 -2
- package/dist/file-explorer/FileRow.js +35 -17
- package/dist/file-explorer/FileRowsWindow.d.ts +2 -1
- package/dist/file-explorer/FileRowsWindow.js +2 -1
- package/dist/file-explorer/FileTable.d.ts +3 -1
- package/dist/file-explorer/FileTable.js +3 -2
- package/dist/file-explorer/TreeView.d.ts +5 -1
- package/dist/file-explorer/TreeView.js +49 -25
- package/dist/file-explorer/helpers.js +3 -3
- package/dist/file-explorer/lib/paging.d.ts +1 -0
- package/dist/file-explorer/lib/paging.js +5 -1
- package/dist/file-explorer/lib/utils.d.ts +3 -0
- package/dist/file-explorer/lib/utils.js +6 -1
- package/dist/form/Wizard/utils.js +2 -1
- package/dist/list/ActionToolbar.js +3 -2
- package/dist/list/ListPage.js +1 -1
- package/dist/list/ListTable.d.ts +5 -0
- package/dist/list/ListTable.js +6 -2
- package/dist/styles/theme.css +82 -62
- package/dist/styles.css +1 -1
- package/dist/theme/derive.d.ts +5 -3
- package/dist/theme/derive.js +61 -3
- package/package.json +9 -2
- package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +0 -6
- package/dist/file-explorer/FilePreview/CodePreviewEditor.js +0 -64
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createYamlWorker } from "./workers.js";
|
|
2
2
|
import { onYamlSchemas } from "./yaml.js";
|
|
3
|
-
import * as monaco from "monaco-editor";
|
|
3
|
+
import * as monaco from "monaco-editor/editor/editor.api";
|
|
4
4
|
//#region src/editor/yamlLanguage.ts
|
|
5
5
|
var LANGUAGE_ID = "yaml";
|
|
6
6
|
var MARKER_OWNER = "yaml";
|
|
@@ -186,41 +186,59 @@ function answerServer(method, params) {
|
|
|
186
186
|
return null;
|
|
187
187
|
}
|
|
188
188
|
function startYamlLanguage() {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const connection = new WorkerConnection(worker, answerServer);
|
|
189
|
+
let server;
|
|
190
|
+
let schemas = [];
|
|
192
191
|
const open = /* @__PURE__ */ new Map();
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
192
|
+
function connect() {
|
|
193
|
+
if (server) return server;
|
|
194
|
+
const worker = createYamlWorker();
|
|
195
|
+
worker.postMessage({});
|
|
196
|
+
const connection = new WorkerConnection(worker, answerServer);
|
|
197
|
+
connection.onNotification("textDocument/publishDiagnostics", (params) => {
|
|
198
|
+
const { uri, diagnostics } = params;
|
|
199
|
+
const model = open.get(uri);
|
|
200
|
+
if (model && !model.isDisposed()) monaco.editor.setModelMarkers(model, MARKER_OWNER, diagnostics.map(toMarker));
|
|
201
|
+
});
|
|
202
|
+
server = {
|
|
203
|
+
connection,
|
|
204
|
+
ready: connection.request("initialize", {
|
|
205
|
+
processId: null,
|
|
206
|
+
rootUri: null,
|
|
207
|
+
capabilities: {
|
|
208
|
+
workspace: { configuration: true },
|
|
209
|
+
textDocument: {
|
|
210
|
+
synchronization: {},
|
|
211
|
+
completion: { completionItem: {
|
|
212
|
+
snippetSupport: true,
|
|
213
|
+
insertReplaceSupport: true,
|
|
214
|
+
documentationFormat: ["markdown", "plaintext"]
|
|
215
|
+
} },
|
|
216
|
+
hover: { contentFormat: ["markdown", "plaintext"] },
|
|
217
|
+
publishDiagnostics: {}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}).then(() => {
|
|
221
|
+
connection.notify("initialized", {});
|
|
222
|
+
connection.notify("workspace/didChangeConfiguration", { settings: null });
|
|
223
|
+
sendSchemas();
|
|
224
|
+
})
|
|
225
|
+
};
|
|
226
|
+
return server;
|
|
227
|
+
}
|
|
228
|
+
function notify(method, params) {
|
|
229
|
+
const { connection, ready } = connect();
|
|
230
|
+
ready.then(() => connection.notify(method, params));
|
|
231
|
+
}
|
|
232
|
+
function sendSchemas() {
|
|
233
|
+
server?.connection.notify("json/schemaAssociations", [schemas]);
|
|
234
|
+
}
|
|
235
|
+
onYamlSchemas((added) => {
|
|
236
|
+
schemas = added;
|
|
237
|
+
server?.ready.then(sendSchemas);
|
|
220
238
|
});
|
|
221
239
|
function close(uri, model) {
|
|
222
240
|
open.delete(uri);
|
|
223
|
-
|
|
241
|
+
notify("textDocument/didClose", { textDocument: { uri } });
|
|
224
242
|
if (!model.isDisposed()) monaco.editor.setModelMarkers(model, MARKER_OWNER, []);
|
|
225
243
|
}
|
|
226
244
|
function track(model) {
|
|
@@ -229,26 +247,24 @@ function startYamlLanguage() {
|
|
|
229
247
|
const isYaml = model.getLanguageId() === LANGUAGE_ID;
|
|
230
248
|
if (isYaml && !open.has(uri)) {
|
|
231
249
|
open.set(uri, model);
|
|
232
|
-
|
|
250
|
+
notify("textDocument/didOpen", { textDocument: {
|
|
233
251
|
uri,
|
|
234
252
|
languageId: LANGUAGE_ID,
|
|
235
253
|
version: model.getVersionId(),
|
|
236
254
|
text: model.getValue()
|
|
237
|
-
};
|
|
238
|
-
ready.then(() => connection.notify("textDocument/didOpen", { textDocument }));
|
|
255
|
+
} });
|
|
239
256
|
} else if (!isYaml && open.has(uri)) close(uri, model);
|
|
240
257
|
};
|
|
241
258
|
model.onDidChangeLanguage(sync);
|
|
242
259
|
model.onDidChangeContent(() => {
|
|
243
260
|
if (!open.has(uri)) return;
|
|
244
|
-
|
|
261
|
+
notify("textDocument/didChange", {
|
|
245
262
|
textDocument: {
|
|
246
263
|
uri,
|
|
247
264
|
version: model.getVersionId()
|
|
248
265
|
},
|
|
249
266
|
contentChanges: [{ text: model.getValue() }]
|
|
250
|
-
};
|
|
251
|
-
ready.then(() => connection.notify("textDocument/didChange", params));
|
|
267
|
+
});
|
|
252
268
|
});
|
|
253
269
|
model.onWillDispose(() => {
|
|
254
270
|
if (open.get(uri) === model) close(uri, model);
|
|
@@ -258,6 +274,7 @@ function startYamlLanguage() {
|
|
|
258
274
|
for (const model of monaco.editor.getModels()) track(model);
|
|
259
275
|
monaco.editor.onDidCreateModel(track);
|
|
260
276
|
async function request(method, model, params, token) {
|
|
277
|
+
const { connection, ready } = connect();
|
|
261
278
|
await ready;
|
|
262
279
|
return connection.request(method, {
|
|
263
280
|
textDocument: { uri: model.uri.toString() },
|
|
@@ -2,7 +2,22 @@ import { type ReactNode } from 'react';
|
|
|
2
2
|
import { type RowAction } from '../list/index.js';
|
|
3
3
|
import type { IFileExplorerClient, IFileExplorerProvider } from './lib/fileExplorer.js';
|
|
4
4
|
import type { ExplorerObject, TreeNode, TStorage } from './lib/types.js';
|
|
5
|
-
|
|
5
|
+
/** How the explorer moves between folders and files. */
|
|
6
|
+
type ExplorerNavigation = {
|
|
7
|
+
/** The URL of a path, for a host that keeps the path in its URL. Rows, the
|
|
8
|
+
* tree, the trail and each row menu's "Open folder" are then links through
|
|
9
|
+
* the host's router (`useLink`), so a path opens in a new tab, shows its
|
|
10
|
+
* URL and can be copied, and back and forward move between paths. */
|
|
11
|
+
pathHref: (path: string) => string;
|
|
12
|
+
/** Moves to a path without a link: from the keyboard, a delete, an upload.
|
|
13
|
+
* Absent, the explorer goes to `pathHref(path)` through the provider's
|
|
14
|
+
* `navigation.goTo`. */
|
|
15
|
+
onPathChange?: ((path: string) => void) | undefined;
|
|
16
|
+
} | {
|
|
17
|
+
pathHref?: undefined;
|
|
18
|
+
onPathChange: (path: string) => void;
|
|
19
|
+
};
|
|
20
|
+
type IFileExplorerProps = ExplorerNavigation & {
|
|
6
21
|
storages: TStorage[];
|
|
7
22
|
/** Resolves the storage's injected provider pair; the host owns caching. */
|
|
8
23
|
getProviderAndClient: (storage: TStorage) => Promise<{
|
|
@@ -21,7 +36,6 @@ interface IFileExplorerProps {
|
|
|
21
36
|
}[] | undefined;
|
|
22
37
|
groupsLoading?: boolean;
|
|
23
38
|
selectedPath: string;
|
|
24
|
-
onPathChange: (path: string) => void;
|
|
25
39
|
/** Renders only the tree, for a host that embeds it as a navigator and owns
|
|
26
40
|
* the pane beside it (the notebooks page puts its editor there). The host
|
|
27
41
|
* also owns the width, so the tree fills its container instead of carrying
|
|
@@ -48,6 +62,6 @@ interface IFileExplorerProps {
|
|
|
48
62
|
extraRowActions?: ((node: TreeNode, storage: TStorage | undefined) => RowAction[]) | undefined;
|
|
49
63
|
/** Host content for the selected folder's header, before its badges. */
|
|
50
64
|
headerAccessory?: ((node: TreeNode, storage: TStorage | undefined) => ReactNode) | undefined;
|
|
51
|
-
}
|
|
52
|
-
export default function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHierarchy, groups, groupsLoading, selectedPath, onPathChange, getProviderAndClient, treeOnly, initialExpandedPaths, onExpandedPathsChange, objectUris, downloadCommand, extraRowActions, headerAccessory, }: IFileExplorerProps): import("react").JSX.Element;
|
|
65
|
+
};
|
|
66
|
+
export default function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHierarchy, groups, groupsLoading, selectedPath, onPathChange, pathHref, getProviderAndClient, treeOnly, initialExpandedPaths, onExpandedPathsChange, objectUris, downloadCommand, extraRowActions, headerAccessory, }: IFileExplorerProps): import("react").JSX.Element;
|
|
53
67
|
export {};
|
|
@@ -7,7 +7,8 @@ import { Loader } from "../components/Loader.js";
|
|
|
7
7
|
import { toast } from "../components/Toast.js";
|
|
8
8
|
import { keyedByContent } from "../components/keys.js";
|
|
9
9
|
import { Tooltip } from "../components/Tooltip.js";
|
|
10
|
-
import { usePersistedState, useSlots, useStrings } from "../components/Provider.js";
|
|
10
|
+
import { useNavigation, usePersistedState, useSlots, useStrings } from "../components/Provider.js";
|
|
11
|
+
import { AppLink } from "../components/AppLink.js";
|
|
11
12
|
import { useCopy } from "../components/useCopy.js";
|
|
12
13
|
import { Button } from "../components/Button.js";
|
|
13
14
|
import { Callout } from "../components/Callout.js";
|
|
@@ -36,7 +37,7 @@ import { FilePreviewInline } from "./FilePreview/Inline.js";
|
|
|
36
37
|
import { UserRow } from "./FileRow.js";
|
|
37
38
|
import { FileTableHeaders } from "./FileTableHeaders.js";
|
|
38
39
|
import { FileTable } from "./FileTable.js";
|
|
39
|
-
import { advanceListing, beginLoadingMore, canAutoLoadMore, clearListingError, clearListingsUnder, hasMore, incompletePaths, isListed, isLoadingMore, loadMoreError, nextHydrationStep, recordListingError, replaceListing } from "./lib/paging.js";
|
|
40
|
+
import { advanceListing, beginLoadingMore, canAutoLoadMore, clearListingError, clearListingsUnder, hasMore, incompletePaths, isListed, isLoadingMore, loadMoreError, nextHydrationStep, recordListingError, replaceListing, retainListings } from "./lib/paging.js";
|
|
40
41
|
import { TreeView } from "./TreeView.js";
|
|
41
42
|
import { Menu } from "@base-ui/react/menu";
|
|
42
43
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -67,6 +68,13 @@ function UriCard({ value }) {
|
|
|
67
68
|
]
|
|
68
69
|
});
|
|
69
70
|
}
|
|
71
|
+
var breadcrumbClass = "max-w-[16rem] cursor-pointer truncate text-(--theme-muted-text-color) transition-colors hover:text-(--theme-app)";
|
|
72
|
+
/** `href` resolved against the page, as the browser's "Copy link" gives it. */
|
|
73
|
+
function absoluteUrl(href) {
|
|
74
|
+
const url = safeUrl(href);
|
|
75
|
+
if (!url || typeof window === "undefined") return url;
|
|
76
|
+
return new URL(url, window.location.href).href;
|
|
77
|
+
}
|
|
70
78
|
var MAX_UPLOAD_SIZE = 85899345920;
|
|
71
79
|
function isUploadSizeExceeded(size) {
|
|
72
80
|
return size > MAX_UPLOAD_SIZE;
|
|
@@ -110,12 +118,13 @@ function TreeFrame({ treeOnly, sidebarWidth, onWidthChange, children }) {
|
|
|
110
118
|
children: [children, /* @__PURE__ */ jsx("div", { ...splitter.separatorProps })]
|
|
111
119
|
});
|
|
112
120
|
}
|
|
113
|
-
function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHierarchy = false, groups = [], groupsLoading = false, selectedPath, onPathChange, getProviderAndClient, treeOnly = false, initialExpandedPaths, onExpandedPathsChange, objectUris, downloadCommand, extraRowActions, headerAccessory }) {
|
|
121
|
+
function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHierarchy = false, groups = [], groupsLoading = false, selectedPath, onPathChange, pathHref, getProviderAndClient, treeOnly = false, initialExpandedPaths, onExpandedPathsChange, objectUris, downloadCommand, extraRowActions, headerAccessory }) {
|
|
114
122
|
const copySubmenu = useCopySubmenu();
|
|
115
123
|
const t = useStrings().fileExplorer;
|
|
116
124
|
const { common } = useStrings();
|
|
117
125
|
const { copy } = useCopy();
|
|
118
126
|
const slots = useSlots();
|
|
127
|
+
const { goTo } = useNavigation();
|
|
119
128
|
const fileExplorerContext = useFileExplorer();
|
|
120
129
|
const [listings, setListings] = useState(() => /* @__PURE__ */ new Map());
|
|
121
130
|
const fetchesInFlightRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -146,7 +155,7 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
146
155
|
if (treeMap[selectedPath]) return selectedPath;
|
|
147
156
|
return `${selectedPath}/`;
|
|
148
157
|
}, [selectedPath, treeMap]);
|
|
149
|
-
const setSelectedPath = onPathChange;
|
|
158
|
+
const setSelectedPath = (path) => onPathChange ? onPathChange(path) : pathHref && goTo(pathHref(path));
|
|
150
159
|
const [expandedPaths, setExpandedPaths] = useState(() => /* @__PURE__ */ new Set(["", ...initialExpandedPaths ?? []]));
|
|
151
160
|
const onExpandedPathsChangeRef = useRef(onExpandedPathsChange);
|
|
152
161
|
onExpandedPathsChangeRef.current = onExpandedPathsChange;
|
|
@@ -161,10 +170,12 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
161
170
|
if (selectedNode?.type === "directory" && selectedNode.storageId) fetchNodeChildren(selectedNode, { replace: true });
|
|
162
171
|
}, [refreshKey, selectedNode]);
|
|
163
172
|
const [checkedItems, setCheckedItems] = useState(/* @__PURE__ */ new Set());
|
|
173
|
+
const [detailTab, setDetailTab] = useState("details");
|
|
164
174
|
const [checkedItemsPath, setCheckedItemsPath] = useState(selectedPath);
|
|
165
175
|
if (checkedItemsPath !== selectedPath) {
|
|
166
176
|
setCheckedItemsPath(selectedPath);
|
|
167
177
|
setCheckedItems(/* @__PURE__ */ new Set());
|
|
178
|
+
setDetailTab("details");
|
|
168
179
|
}
|
|
169
180
|
const selectedNodeChildren = useMemo(() => selectedNode ? getNodeChildren(parentToChildrenMap, selectedNode.path) : [], [parentToChildrenMap, selectedNode]);
|
|
170
181
|
const findStorage = (storageId) => storages.find((s) => s.id === storageId);
|
|
@@ -244,7 +255,6 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
244
255
|
const folderInputRef = useRef(null);
|
|
245
256
|
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
|
246
257
|
const [pendingDelete, setPendingDelete] = useState(null);
|
|
247
|
-
const [detailTab, setDetailTab] = useState("details");
|
|
248
258
|
useEffect(() => clearPreviewCache, []);
|
|
249
259
|
const { openMenu, contextMenu } = useContextMenu();
|
|
250
260
|
const [sidebarWidth, setSidebarWidth] = usePersistedState(SIDEBAR_WIDTH_STORAGE_KEY, 300);
|
|
@@ -568,6 +578,9 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
568
578
|
const closePreview = () => {
|
|
569
579
|
setPreviewOpen(false);
|
|
570
580
|
};
|
|
581
|
+
const openFromTree = (node) => {
|
|
582
|
+
if (treeOnly && node.type === "file") openPreview(node);
|
|
583
|
+
};
|
|
571
584
|
const openUserNode = (node) => {
|
|
572
585
|
handleSelectTreeItem(node.path, node);
|
|
573
586
|
if (!expandedPaths.has(node.path)) handleToggleExpand(node.path);
|
|
@@ -651,9 +664,16 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
651
664
|
destructive: true,
|
|
652
665
|
onClick: () => deleteNode(node)
|
|
653
666
|
});
|
|
654
|
-
const
|
|
667
|
+
const open = {
|
|
655
668
|
label: isFile ? t.preview.viewDetails : t.preview.openFolder,
|
|
656
|
-
icon: isFile ? /* @__PURE__ */ jsx(FileTextIcon, {}) : /* @__PURE__ */ jsx(FolderIcon, {})
|
|
669
|
+
icon: isFile ? /* @__PURE__ */ jsx(FileTextIcon, {}) : /* @__PURE__ */ jsx(FolderIcon, {})
|
|
670
|
+
};
|
|
671
|
+
const href = pathHref?.(node.path);
|
|
672
|
+
const lead = [href ? {
|
|
673
|
+
...open,
|
|
674
|
+
href
|
|
675
|
+
} : {
|
|
676
|
+
...open,
|
|
657
677
|
onClick: () => handleSelectTreeItem(node.path, node)
|
|
658
678
|
}];
|
|
659
679
|
const uriExtras = uris.map((value) => ({
|
|
@@ -661,6 +681,12 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
661
681
|
value,
|
|
662
682
|
icon: /* @__PURE__ */ jsx(LinkIcon, {})
|
|
663
683
|
}));
|
|
684
|
+
const pageUrl = absoluteUrl(href);
|
|
685
|
+
if (pageUrl) uriExtras.unshift({
|
|
686
|
+
label: t.preview.link,
|
|
687
|
+
value: pageUrl,
|
|
688
|
+
icon: /* @__PURE__ */ jsx(LinkIcon, {})
|
|
689
|
+
});
|
|
664
690
|
return assembleRowMenu({
|
|
665
691
|
lead,
|
|
666
692
|
actions,
|
|
@@ -705,10 +731,14 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
705
731
|
"aria-current": "location",
|
|
706
732
|
className: "truncate font-semibold text-(--theme-app)",
|
|
707
733
|
children: label
|
|
734
|
+
}) : pathHref ? /* @__PURE__ */ jsx(AppLink, {
|
|
735
|
+
href: pathHref(node.path),
|
|
736
|
+
className: breadcrumbClass,
|
|
737
|
+
children: label
|
|
708
738
|
}) : /* @__PURE__ */ jsx("button", {
|
|
709
739
|
type: "button",
|
|
710
740
|
onClick: () => handleSelectTreeItem(node.path, node),
|
|
711
|
-
className:
|
|
741
|
+
className: breadcrumbClass,
|
|
712
742
|
children: label
|
|
713
743
|
})]
|
|
714
744
|
}, node.path);
|
|
@@ -919,6 +949,7 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
919
949
|
const handleRefresh = async (opts) => {
|
|
920
950
|
const dirs = [...expandedPaths].map((path) => treeMap[path]).filter((node) => !!node && node.type === "directory" && !!node.storageId);
|
|
921
951
|
if (selectedNode?.type === "directory" && selectedNode.storageId && !dirs.some((dir) => dir.path === selectedNode.path)) dirs.push(selectedNode);
|
|
952
|
+
setListings((prev) => retainListings(prev, new Set(dirs.map((dir) => dir.path))));
|
|
922
953
|
if (dirs.length > 0) return { corsError: (await Promise.all(dirs.map((dir) => fetchNodeChildren(dir, {
|
|
923
954
|
replace: true,
|
|
924
955
|
silent: opts?.silent
|
|
@@ -965,8 +996,10 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
965
996
|
onToggleExpand: handleToggleExpand,
|
|
966
997
|
onSelect: (path, node) => {
|
|
967
998
|
handleSelectTreeItem(path, node);
|
|
968
|
-
|
|
999
|
+
openFromTree(node);
|
|
969
1000
|
},
|
|
1001
|
+
pathHref,
|
|
1002
|
+
onFollowLink: openFromTree,
|
|
970
1003
|
onDropToFolder: onDropFiles,
|
|
971
1004
|
onContextMenu: openNodeContextMenu,
|
|
972
1005
|
onPreviewFile: openPreview,
|
|
@@ -1008,18 +1041,28 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
1008
1041
|
children: t.chrome.storages
|
|
1009
1042
|
}),
|
|
1010
1043
|
/* @__PURE__ */ jsx(ListActionsHeader, { actionCount: 1 }),
|
|
1011
|
-
rootNodes.map((rootNode) =>
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
storageCount: getNodeChildren(parentToChildrenMap, rootNode.path).length,
|
|
1015
|
-
getItems: () => [{
|
|
1044
|
+
rootNodes.map((rootNode) => {
|
|
1045
|
+
const href = pathHref?.(rootNode.path);
|
|
1046
|
+
const open = {
|
|
1016
1047
|
label: t.preview.open,
|
|
1017
|
-
icon: /* @__PURE__ */ jsx(FolderIcon, {})
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1048
|
+
icon: /* @__PURE__ */ jsx(FolderIcon, {})
|
|
1049
|
+
};
|
|
1050
|
+
return /* @__PURE__ */ jsx(UserRow, {
|
|
1051
|
+
node: rootNode,
|
|
1052
|
+
icon: getNodeIcon(rootNode),
|
|
1053
|
+
href,
|
|
1054
|
+
storageCount: getNodeChildren(parentToChildrenMap, rootNode.path).length,
|
|
1055
|
+
getItems: () => [href ? {
|
|
1056
|
+
...open,
|
|
1057
|
+
href
|
|
1058
|
+
} : {
|
|
1059
|
+
...open,
|
|
1060
|
+
onClick: () => openUserNode(rootNode)
|
|
1061
|
+
}],
|
|
1062
|
+
openMenu,
|
|
1063
|
+
onOpen: openUserNode
|
|
1064
|
+
}, rootNode.path);
|
|
1065
|
+
})
|
|
1023
1066
|
]
|
|
1024
1067
|
}), rootNodes.length === 0 && /* @__PURE__ */ jsx(NoDataAvailablePreview, {
|
|
1025
1068
|
selectedStorage: null,
|
|
@@ -1206,6 +1249,7 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
|
|
|
1206
1249
|
onOpen: (n) => handleSelectTreeItem(n.path, n),
|
|
1207
1250
|
onToggleCheck: handleItemCheckbox,
|
|
1208
1251
|
onPreview: openPreview,
|
|
1252
|
+
pathHref,
|
|
1209
1253
|
loadMore: loadMoreProps
|
|
1210
1254
|
}, selectedNode.path) : /* @__PURE__ */ jsxs("div", {
|
|
1211
1255
|
className: "h-full flex flex-col",
|
|
@@ -6,6 +6,7 @@ import { useStrings } from "../../components/Provider.js";
|
|
|
6
6
|
import { Button } from "../../components/Button.js";
|
|
7
7
|
import Markdown from "../../components/Markdown.js";
|
|
8
8
|
import { formatBytes } from "../../format.js";
|
|
9
|
+
import { Editor } from "../../editor/Editor.js";
|
|
9
10
|
import { getFileExtension } from "../lib/utils.js";
|
|
10
11
|
import { getMonacoLanguage, previewLimitsFor } from "./previewType.js";
|
|
11
12
|
import { CorsIssuePreview } from "../helpers.js";
|
|
@@ -14,9 +15,8 @@ import { countLines } from "./readCappedBytes.js";
|
|
|
14
15
|
import { useObjectBlobUrl } from "./useObjectBlobUrl.js";
|
|
15
16
|
import { useObjectText } from "./useObjectText.js";
|
|
16
17
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
17
|
-
import {
|
|
18
|
+
import { useCallback, useMemo, useState } from "react";
|
|
18
19
|
//#region src/file-explorer/FilePreview/Viewer.tsx
|
|
19
|
-
var CodePreviewEditor = lazy(() => import("./CodePreviewEditor.js"));
|
|
20
20
|
var PREVIEW_MARKDOWN_CONTROLS = {
|
|
21
21
|
table: { fullscreen: false },
|
|
22
22
|
mermaid: { fullscreen: false }
|
|
@@ -279,12 +279,16 @@ function CodeView({ node, url, onDownload, storage, onCorsRetry }) {
|
|
|
279
279
|
controls: PREVIEW_MARKDOWN_CONTROLS,
|
|
280
280
|
children: text ?? ""
|
|
281
281
|
})
|
|
282
|
-
}) : /* @__PURE__ */ jsx(
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
282
|
+
}) : /* @__PURE__ */ jsx(Editor, {
|
|
283
|
+
readOnly: true,
|
|
284
|
+
value: text ?? "",
|
|
285
|
+
language,
|
|
286
|
+
ariaLabel: node.name,
|
|
287
|
+
className: "!rounded-none !border-0",
|
|
288
|
+
fontSize: 12,
|
|
289
|
+
minimap: { enabled: false },
|
|
290
|
+
overviewRulerLanes: 0,
|
|
291
|
+
wordWrap: "off"
|
|
288
292
|
})
|
|
289
293
|
})
|
|
290
294
|
})]
|
|
@@ -16,6 +16,8 @@ interface FileRowProps {
|
|
|
16
16
|
rowIndex: number;
|
|
17
17
|
/** The keyboard cursor row. Focus stays on the container, so nothing else marks it. */
|
|
18
18
|
active: boolean;
|
|
19
|
+
/** Makes the row a link to the node. */
|
|
20
|
+
href?: string | undefined;
|
|
19
21
|
checked: boolean;
|
|
20
22
|
canPreview: boolean;
|
|
21
23
|
getItems: () => MenuEntry[];
|
|
@@ -24,13 +26,15 @@ interface FileRowProps {
|
|
|
24
26
|
onToggleCheck: (node: TreeNode, checked: boolean) => void;
|
|
25
27
|
onPreview: (node: TreeNode) => void;
|
|
26
28
|
}
|
|
27
|
-
export declare function UserRow({ node, icon, storageCount, getItems, openMenu, onOpen, }: {
|
|
29
|
+
export declare function UserRow({ node, icon, href, storageCount, getItems, openMenu, onOpen, }: {
|
|
28
30
|
node: TreeNode;
|
|
29
31
|
icon: ReactNode;
|
|
32
|
+
/** Makes the row a link to the user. */
|
|
33
|
+
href?: string | undefined;
|
|
30
34
|
storageCount: number;
|
|
31
35
|
getItems: () => MenuEntry[];
|
|
32
36
|
openMenu: OpenMenu;
|
|
33
37
|
onOpen: (node: TreeNode) => void;
|
|
34
38
|
}): import("react").JSX.Element;
|
|
35
|
-
export declare function FileRow({ node, icon, rowId, rowIndex, active, checked, canPreview, getItems, openMenu, onOpen, onToggleCheck, onPreview, }: FileRowProps): import("react").JSX.Element;
|
|
39
|
+
export declare function FileRow({ node, icon, rowId, rowIndex, active, href, checked, canPreview, getItems, openMenu, onOpen, onToggleCheck, onPreview, }: FileRowProps): import("react").JSX.Element;
|
|
36
40
|
export {};
|
|
@@ -2,10 +2,11 @@ import { cx } from "../cx.js";
|
|
|
2
2
|
import { PreviewIcon } from "../icons.js";
|
|
3
3
|
import { Tooltip } from "../components/Tooltip.js";
|
|
4
4
|
import { useStrings } from "../components/Provider.js";
|
|
5
|
+
import { AppLink, isPlainClick } from "../components/AppLink.js";
|
|
5
6
|
import { formatBytes } from "../format.js";
|
|
6
7
|
import { RelativeTime } from "../components/relativeTime.js";
|
|
7
8
|
import { Table } from "../components/Table.js";
|
|
8
|
-
import { RowSelectCheckbox } from "../list/ListTable.js";
|
|
9
|
+
import { RowSelectCheckbox, STRETCHED_LINK } from "../list/ListTable.js";
|
|
9
10
|
import { MoreButton, rowContextMenuProps, useRowMenuActive } from "../list/rowMenu.js";
|
|
10
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
12
|
import { DateTime } from "luxon";
|
|
@@ -20,16 +21,31 @@ function fileRowHeight(node) {
|
|
|
20
21
|
function isInteractiveTarget(e) {
|
|
21
22
|
return !!e.target.closest("a,button,input,label");
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
+
/** Opens the row on a click its controls don't take. Beside a link, which
|
|
25
|
+
* covers the row, that is only a click on a gap the link leaves, and a
|
|
26
|
+
* modified one there asks for a new tab, which only the link can give. */
|
|
27
|
+
function rowClickHandler(onOpen, href) {
|
|
28
|
+
return (e) => {
|
|
29
|
+
if (isInteractiveTarget(e) || href && !isPlainClick(e)) return;
|
|
30
|
+
onOpen();
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** A row's name: with an href, the link that covers the row, so the whole row
|
|
34
|
+
* opens in a new tab, shows its URL and reads as a link. */
|
|
35
|
+
function RowName({ name, href }) {
|
|
36
|
+
return href ? /* @__PURE__ */ jsx(AppLink, {
|
|
37
|
+
href,
|
|
38
|
+
"data-row-link": true,
|
|
39
|
+
className: STRETCHED_LINK,
|
|
40
|
+
children: name
|
|
41
|
+
}) : name;
|
|
42
|
+
}
|
|
43
|
+
function UserRow({ node, icon, href, storageCount, getItems, openMenu, onOpen }) {
|
|
24
44
|
const t = useStrings().fileExplorer;
|
|
25
45
|
const { active: menuActive, openMenu: openRowMenu } = useRowMenuActive(openMenu);
|
|
26
|
-
const handleRowClick = (e) => {
|
|
27
|
-
if (isInteractiveTarget(e)) return;
|
|
28
|
-
onOpen(node);
|
|
29
|
-
};
|
|
30
46
|
return /* @__PURE__ */ jsxs("tr", {
|
|
31
|
-
className: cx("group cursor-pointer", menuActive ? "theme-hover" : "hover:theme-hover"),
|
|
32
|
-
onClick:
|
|
47
|
+
className: cx("group cursor-pointer", menuActive ? "theme-hover" : "hover:theme-hover", href && "relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:z-[1]"),
|
|
48
|
+
onClick: rowClickHandler(() => onOpen(node), href),
|
|
33
49
|
...rowContextMenuProps(openRowMenu, getItems),
|
|
34
50
|
children: [
|
|
35
51
|
/* @__PURE__ */ jsx(Table.Item, {
|
|
@@ -41,7 +57,10 @@ function UserRow({ node, icon, storageCount, getItems, openMenu, onOpen }) {
|
|
|
41
57
|
children: icon
|
|
42
58
|
}), /* @__PURE__ */ jsx("span", {
|
|
43
59
|
className: "truncate text-[13px] font-medium text-(--theme-app)",
|
|
44
|
-
children:
|
|
60
|
+
children: /* @__PURE__ */ jsx(RowName, {
|
|
61
|
+
name: node.displayName || node.name,
|
|
62
|
+
href
|
|
63
|
+
})
|
|
45
64
|
})]
|
|
46
65
|
})
|
|
47
66
|
}),
|
|
@@ -66,22 +85,18 @@ function UserRow({ node, icon, storageCount, getItems, openMenu, onOpen }) {
|
|
|
66
85
|
]
|
|
67
86
|
});
|
|
68
87
|
}
|
|
69
|
-
function FileRow({ node, icon, rowId, rowIndex, active, checked, canPreview, getItems, openMenu, onOpen, onToggleCheck, onPreview }) {
|
|
88
|
+
function FileRow({ node, icon, rowId, rowIndex, active, href, checked, canPreview, getItems, openMenu, onOpen, onToggleCheck, onPreview }) {
|
|
70
89
|
const t = useStrings().fileExplorer;
|
|
71
90
|
const { active: menuActive, openMenu: openRowMenu } = useRowMenuActive(openMenu);
|
|
72
91
|
const isDir = node.type === "directory";
|
|
73
92
|
const modifiedDt = node.modified ? DateTime.fromISO(node.modified) : null;
|
|
74
93
|
const typeLabel = node.root ? node.storageType ?? node.type : node.type;
|
|
75
|
-
const handleRowClick = (e) => {
|
|
76
|
-
if (isInteractiveTarget(e)) return;
|
|
77
|
-
onOpen(node);
|
|
78
|
-
};
|
|
79
94
|
return /* @__PURE__ */ jsxs("tr", {
|
|
80
95
|
id: rowId,
|
|
81
96
|
"aria-rowindex": rowIndex,
|
|
82
97
|
"aria-selected": checked,
|
|
83
|
-
className: cx("group", checked ? "bg-(--theme-accent-subtle)/60" : menuActive ? "theme-hover" : "hover:theme-hover", active && "group-focus-visible/grid:ring-1 group-focus-visible/grid:ring-inset group-focus-visible/grid:ring-(--theme-link)", "cursor-pointer"),
|
|
84
|
-
onClick:
|
|
98
|
+
className: cx("group", checked ? "bg-(--theme-accent-subtle)/60" : menuActive ? "theme-hover" : "hover:theme-hover", active && "group-focus-visible/grid:ring-1 group-focus-visible/grid:ring-inset group-focus-visible/grid:ring-(--theme-link)", "cursor-pointer", href && "relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:z-[1]"),
|
|
99
|
+
onClick: rowClickHandler(() => onOpen(node), href),
|
|
85
100
|
style: { height: fileRowHeight(node) },
|
|
86
101
|
...rowContextMenuProps(openRowMenu, getItems),
|
|
87
102
|
children: [
|
|
@@ -103,7 +118,10 @@ function FileRow({ node, icon, rowId, rowIndex, active, checked, canPreview, get
|
|
|
103
118
|
className: "min-w-0",
|
|
104
119
|
children: [/* @__PURE__ */ jsx("div", {
|
|
105
120
|
className: "truncate text-[13px] font-medium leading-tight text-(--theme-app)",
|
|
106
|
-
children:
|
|
121
|
+
children: /* @__PURE__ */ jsx(RowName, {
|
|
122
|
+
name: node.displayName || node.name,
|
|
123
|
+
href
|
|
124
|
+
})
|
|
107
125
|
}), isTwoLineRow(node) && /* @__PURE__ */ jsx("div", {
|
|
108
126
|
className: "truncate text-xs leading-tight text-(--theme-muted-text-color)",
|
|
109
127
|
children: node.contentType
|
|
@@ -30,8 +30,9 @@ interface FileRowsWindowProps {
|
|
|
30
30
|
onOpen: (node: TreeNode) => void;
|
|
31
31
|
onToggleCheck: (node: TreeNode, checked: boolean) => void;
|
|
32
32
|
onPreview: (node: TreeNode) => void;
|
|
33
|
+
pathHref?: ((path: string) => string) | undefined;
|
|
33
34
|
}
|
|
34
35
|
/** Must stay a single child of `<Table>`: Table re-keys children by traversal
|
|
35
36
|
* index, so a count that varied with scroll position would remount every row. */
|
|
36
|
-
export declare function FileRowsWindow({ items, padTop, padBottom, nodes, checkedItems, activeIndex, rowIdPrefix, scrollEl, loadMore, getItems, openMenu, onOpen, onToggleCheck, onPreview, }: FileRowsWindowProps): import("react").JSX.Element;
|
|
37
|
+
export declare function FileRowsWindow({ items, padTop, padBottom, nodes, checkedItems, activeIndex, rowIdPrefix, scrollEl, loadMore, getItems, openMenu, onOpen, onToggleCheck, onPreview, pathHref, }: FileRowsWindowProps): import("react").JSX.Element;
|
|
37
38
|
export {};
|
|
@@ -23,7 +23,7 @@ function spacerHeights(items, totalSize, scrollMargin) {
|
|
|
23
23
|
}
|
|
24
24
|
/** Must stay a single child of `<Table>`: Table re-keys children by traversal
|
|
25
25
|
* index, so a count that varied with scroll position would remount every row. */
|
|
26
|
-
function FileRowsWindow({ items, padTop, padBottom, nodes, checkedItems, activeIndex, rowIdPrefix, scrollEl, loadMore, getItems, openMenu, onOpen, onToggleCheck, onPreview }) {
|
|
26
|
+
function FileRowsWindow({ items, padTop, padBottom, nodes, checkedItems, activeIndex, rowIdPrefix, scrollEl, loadMore, getItems, openMenu, onOpen, onToggleCheck, onPreview, pathHref }) {
|
|
27
27
|
useNestedScrollerWarning(scrollEl, nodes.length);
|
|
28
28
|
useRowPitchAudit(scrollEl, nodes, items);
|
|
29
29
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -44,6 +44,7 @@ function FileRowsWindow({ items, padTop, padBottom, nodes, checkedItems, activeI
|
|
|
44
44
|
rowId: `${rowIdPrefix}-${item.index}`,
|
|
45
45
|
rowIndex: item.index + 2,
|
|
46
46
|
active: item.index === activeIndex,
|
|
47
|
+
href: pathHref?.(node.path),
|
|
47
48
|
node,
|
|
48
49
|
icon,
|
|
49
50
|
checked: checkedItems.has(node.path),
|
|
@@ -13,11 +13,13 @@ interface FileTableProps {
|
|
|
13
13
|
onOpen: (node: TreeNode) => void;
|
|
14
14
|
onToggleCheck: (node: TreeNode, checked: boolean) => void;
|
|
15
15
|
onPreview: (node: TreeNode) => void;
|
|
16
|
+
/** The URL of a path; set, each row is a link to its node. */
|
|
17
|
+
pathHref?: ((path: string) => string) | undefined;
|
|
16
18
|
/** Set when the folder has pages left to fetch. */
|
|
17
19
|
loadMore?: LoadMoreState | undefined;
|
|
18
20
|
}
|
|
19
21
|
/** The file table. Give it a `key` of the folder path: a folder change must reset
|
|
20
22
|
* the cursor, the scroll offset and the virtualizer's measurements, and a remount
|
|
21
23
|
* does all three without a synchronising effect. */
|
|
22
|
-
export declare function FileTable({ nodes, checkedItems, allSelected, someSelected, onSelectAll, getItems, openMenu, onOpen, onToggleCheck, onPreview, loadMore, }: FileTableProps): import("react").JSX.Element;
|
|
24
|
+
export declare function FileTable({ nodes, checkedItems, allSelected, someSelected, onSelectAll, getItems, openMenu, onOpen, onToggleCheck, onPreview, pathHref, loadMore, }: FileTableProps): import("react").JSX.Element;
|
|
23
25
|
export {};
|
|
@@ -12,7 +12,7 @@ import { useVirtualizer } from "@tanstack/react-virtual";
|
|
|
12
12
|
/** The file table. Give it a `key` of the folder path: a folder change must reset
|
|
13
13
|
* the cursor, the scroll offset and the virtualizer's measurements, and a remount
|
|
14
14
|
* does all three without a synchronising effect. */
|
|
15
|
-
function FileTable({ nodes, checkedItems, allSelected, someSelected, onSelectAll, getItems, openMenu, onOpen, onToggleCheck, onPreview, loadMore }) {
|
|
15
|
+
function FileTable({ nodes, checkedItems, allSelected, someSelected, onSelectAll, getItems, openMenu, onOpen, onToggleCheck, onPreview, pathHref, loadMore }) {
|
|
16
16
|
const [scrollEl, setScrollEl] = useState(null);
|
|
17
17
|
const [activeIndex, setActiveIndex] = useState(-1);
|
|
18
18
|
const [theadHeight, setTheadHeight] = useState(0);
|
|
@@ -165,7 +165,8 @@ function FileTable({ nodes, checkedItems, allSelected, someSelected, onSelectAll
|
|
|
165
165
|
openMenu,
|
|
166
166
|
onOpen: handleOpen,
|
|
167
167
|
onToggleCheck,
|
|
168
|
-
onPreview
|
|
168
|
+
onPreview,
|
|
169
|
+
pathHref
|
|
169
170
|
})]
|
|
170
171
|
})
|
|
171
172
|
});
|
|
@@ -13,6 +13,10 @@ interface TreeViewProps {
|
|
|
13
13
|
onDropToFolder: (folderPath: string, files: FileList | DataTransferItemList) => void;
|
|
14
14
|
onContextMenu: (e: React.MouseEvent, node: TreeNode) => void;
|
|
15
15
|
onPreviewFile: (node: TreeNode) => void;
|
|
16
|
+
/** The URL of a path; set, each row is a link to its path. */
|
|
17
|
+
pathHref?: ((path: string) => string) | undefined;
|
|
18
|
+
/** A plain click on a row's link, which moves to its path on its own. */
|
|
19
|
+
onFollowLink?: ((node: TreeNode) => void) | undefined;
|
|
16
20
|
/** Directories with pages left to fetch, and how to fetch them. */
|
|
17
21
|
paging?: {
|
|
18
22
|
incompletePaths: ReadonlySet<string>;
|
|
@@ -23,5 +27,5 @@ interface TreeViewProps {
|
|
|
23
27
|
}
|
|
24
28
|
/** The sidebar tree, flattened and windowed. The flat array is the single source
|
|
25
29
|
* of truth for rendering, arrow keys and ARIA. */
|
|
26
|
-
export declare function TreeView({ rootNodes, parentToChildrenMap, expandedPaths, selectedPath, loadingPaths, onToggleExpand, onSelect, onDropToFolder, onContextMenu, onPreviewFile, paging, }: TreeViewProps): import("react").JSX.Element;
|
|
30
|
+
export declare function TreeView({ rootNodes, parentToChildrenMap, expandedPaths, selectedPath, loadingPaths, onToggleExpand, onSelect, onDropToFolder, onContextMenu, onPreviewFile, pathHref, onFollowLink, paging, }: TreeViewProps): import("react").JSX.Element;
|
|
27
31
|
export {};
|