agentic-drive 0.8.0 → 0.9.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/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/{chunk-6UQ6CDLJ.js → chunk-IMWV5QEH.js} +1 -1
- package/dist/cli.js +1 -1
- package/dist/embed.css +137 -0
- package/dist/embed.js +231 -96
- package/dist/index.js +1 -1
- package/dist/mcp.js +1 -1
- package/package.json +1 -1
- package/ui-dist/assets/{index-GxwjdcYH.css → index-Cb1lY2Sf.css} +1 -1
- package/ui-dist/assets/index-Dg9jF2oJ.js +49 -0
- package/ui-dist/index.html +2 -2
- package/ui-dist/assets/index-mHs8RJgV.js +0 -49
package/dist/embed.js
CHANGED
|
@@ -4,28 +4,28 @@ import {
|
|
|
4
4
|
} from "./chunk-LELTSSZF.js";
|
|
5
5
|
|
|
6
6
|
// ui/embed.tsx
|
|
7
|
-
import { useEffect as
|
|
7
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
8
8
|
import { createRoot } from "react-dom/client";
|
|
9
|
-
import { FolderIcon as
|
|
9
|
+
import { FolderIcon as FolderIcon3, SidebarNav as SidebarNav2, ToastProvider, TooltipProvider } from "agentic-design/react";
|
|
10
10
|
|
|
11
11
|
// ui/App.tsx
|
|
12
|
-
import { useEffect, useMemo, useRef, useState } from "react";
|
|
12
|
+
import { useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
13
13
|
import {
|
|
14
14
|
AppShell,
|
|
15
|
-
Button,
|
|
15
|
+
Button as Button2,
|
|
16
16
|
Dialog,
|
|
17
17
|
DialogClose,
|
|
18
18
|
EmptyState,
|
|
19
|
-
FileIcon,
|
|
19
|
+
FileIcon as FileIcon2,
|
|
20
20
|
FileList,
|
|
21
21
|
FileRow,
|
|
22
|
-
FolderIcon,
|
|
22
|
+
FolderIcon as FolderIcon2,
|
|
23
23
|
IconButton,
|
|
24
24
|
Input,
|
|
25
25
|
Menu,
|
|
26
26
|
MoreIcon,
|
|
27
27
|
PlusIcon,
|
|
28
|
-
PresenceChip,
|
|
28
|
+
PresenceChip as PresenceChip2,
|
|
29
29
|
Select,
|
|
30
30
|
ShareDialog,
|
|
31
31
|
SidebarNav,
|
|
@@ -34,15 +34,121 @@ import {
|
|
|
34
34
|
useTheme,
|
|
35
35
|
useToast
|
|
36
36
|
} from "agentic-design/react";
|
|
37
|
-
|
|
37
|
+
|
|
38
|
+
// ui/browse.tsx
|
|
39
|
+
import { useEffect, useRef, useState } from "react";
|
|
40
|
+
import { Button, FileIcon, FolderIcon, PresenceChip } from "agentic-design/react";
|
|
41
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
42
|
+
function sortItems(items, { key, dir }, dateOf = (i) => i.updatedAt) {
|
|
43
|
+
const sign = dir === "asc" ? 1 : -1;
|
|
44
|
+
const by = key === "name" ? (a, b) => a.name.localeCompare(b.name, void 0, { numeric: true }) : (a, b) => dateOf(a) - dateOf(b);
|
|
45
|
+
return [...items].sort((a, b) => (a.kind === "folder" ? 0 : 1) - (b.kind === "folder" ? 0 : 1) || sign * by(a, b) || a.name.localeCompare(b.name));
|
|
46
|
+
}
|
|
47
|
+
function Stamp({ at }) {
|
|
48
|
+
const d = new Date(at);
|
|
49
|
+
return Number.isFinite(d.getTime()) ? /* @__PURE__ */ jsx("time", { dateTime: d.toISOString(), children: dateFormat.format(d) }) : /* @__PURE__ */ jsx("span", { children: "\u2014" });
|
|
50
|
+
}
|
|
51
|
+
var dateFormat = new Intl.DateTimeFormat(void 0, { dateStyle: "medium", timeStyle: "short" });
|
|
52
|
+
function ExpandableSearch({ value, onChange }) {
|
|
53
|
+
const [open, setOpen] = useState(false);
|
|
54
|
+
const input = useRef(null);
|
|
55
|
+
const trigger = useRef(null);
|
|
56
|
+
const restore = useRef(false);
|
|
57
|
+
const shown = open || !!value;
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (shown) input.current?.focus();
|
|
60
|
+
else if (restore.current) {
|
|
61
|
+
restore.current = false;
|
|
62
|
+
trigger.current?.focus();
|
|
63
|
+
}
|
|
64
|
+
}, [shown]);
|
|
65
|
+
const close = () => {
|
|
66
|
+
restore.current = true;
|
|
67
|
+
onChange("");
|
|
68
|
+
setOpen(false);
|
|
69
|
+
};
|
|
70
|
+
if (!shown) {
|
|
71
|
+
return /* @__PURE__ */ jsx(Button, { ref: trigger, variant: "ghost", size: "sm", onClick: () => setOpen(true), children: "Search" });
|
|
72
|
+
}
|
|
73
|
+
return /* @__PURE__ */ jsxs("div", { className: "drive-search", role: "search", children: [
|
|
74
|
+
/* @__PURE__ */ jsx(
|
|
75
|
+
"input",
|
|
76
|
+
{
|
|
77
|
+
ref: input,
|
|
78
|
+
type: "search",
|
|
79
|
+
className: "drive-search__input",
|
|
80
|
+
"aria-label": "Search this folder",
|
|
81
|
+
placeholder: "Search this folder",
|
|
82
|
+
value,
|
|
83
|
+
onChange: (e) => onChange(e.target.value),
|
|
84
|
+
onKeyDown: (e) => {
|
|
85
|
+
if (e.key === "Escape") close();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: close, children: "Close search" })
|
|
90
|
+
] });
|
|
91
|
+
}
|
|
92
|
+
function ItemTable({ label, items, sort, onSort, selected = /* @__PURE__ */ new Set(), onSelect, href, who: who2, actions, dateOf = (i) => i.updatedAt }) {
|
|
93
|
+
const all = items.length > 0 && items.every((i) => selected.has(i.id));
|
|
94
|
+
const some = !all && items.some((i) => selected.has(i.id));
|
|
95
|
+
const head = useRef(null);
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (head.current) head.current.indeterminate = some;
|
|
98
|
+
}, [some]);
|
|
99
|
+
const toggle = (id, on) => {
|
|
100
|
+
if (!onSelect) return;
|
|
101
|
+
const next = new Set(selected);
|
|
102
|
+
if (on) next.add(id);
|
|
103
|
+
else next.delete(id);
|
|
104
|
+
onSelect(next);
|
|
105
|
+
};
|
|
106
|
+
const th = (key, text, cls) => /* @__PURE__ */ jsx("th", { scope: "col", className: cls, "aria-sort": sort.key === key ? sort.dir === "asc" ? "ascending" : "descending" : "none", children: /* @__PURE__ */ jsxs("button", { type: "button", className: "drive-sort", onClick: () => onSort(key), children: [
|
|
107
|
+
text,
|
|
108
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: sort.key === key ? sort.dir === "asc" ? " \u2191" : " \u2193" : "" })
|
|
109
|
+
] }) });
|
|
110
|
+
return /* @__PURE__ */ jsxs("table", { className: "drive-table", "aria-label": label, children: [
|
|
111
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
112
|
+
onSelect && /* @__PURE__ */ jsx("th", { scope: "col", className: "drive-table__check", children: /* @__PURE__ */ jsx("input", { ref: head, type: "checkbox", className: "agd-checkbox", "aria-label": "Select all items", checked: all, onChange: (e) => onSelect(e.target.checked ? new Set(items.map((i) => i.id)) : /* @__PURE__ */ new Set()) }) }),
|
|
113
|
+
th("name", "Name"),
|
|
114
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "drive-table__who", children: "Edited by" }),
|
|
115
|
+
th("modified", "Modified", "drive-table__date"),
|
|
116
|
+
/* @__PURE__ */ jsx("th", { scope: "col", children: /* @__PURE__ */ jsx("span", { className: "drive-sr", children: "Actions" }) })
|
|
117
|
+
] }) }),
|
|
118
|
+
/* @__PURE__ */ jsx("tbody", { children: items.map((i) => /* @__PURE__ */ jsxs("tr", { className: "drive-row", "data-selected": selected.has(i.id) || void 0, children: [
|
|
119
|
+
onSelect && /* @__PURE__ */ jsx("td", { className: "drive-table__check", children: /* @__PURE__ */ jsx("input", { type: "checkbox", className: "agd-checkbox", "aria-label": `Select ${i.name}`, checked: selected.has(i.id), onChange: (e) => toggle(i.id, e.target.checked) }) }),
|
|
120
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("div", { className: "drive-table__name", children: [
|
|
121
|
+
/* @__PURE__ */ jsx("span", { className: "drive-table__icon", "aria-hidden": "true", children: i.kind === "folder" ? /* @__PURE__ */ jsx(FolderIcon, {}) : /* @__PURE__ */ jsx(FileIcon, {}) }),
|
|
122
|
+
/* @__PURE__ */ jsx("a", { href: href(i), children: i.name })
|
|
123
|
+
] }) }),
|
|
124
|
+
/* @__PURE__ */ jsx("td", { className: "drive-table__who", children: /* @__PURE__ */ jsx(PresenceChip, { entry: who2(i.updatedBy, i.owner) }) }),
|
|
125
|
+
/* @__PURE__ */ jsx("td", { className: "drive-table__date", children: /* @__PURE__ */ jsx(Stamp, { at: dateOf(i) }) }),
|
|
126
|
+
/* @__PURE__ */ jsx("td", { className: "drive-table__actions", children: actions(i) })
|
|
127
|
+
] }, i.id)) })
|
|
128
|
+
] });
|
|
129
|
+
}
|
|
130
|
+
function BulkBar({ count, busy, onTrash, onClear }) {
|
|
131
|
+
if (count === 0) return null;
|
|
132
|
+
return /* @__PURE__ */ jsxs("div", { role: "region", "aria-label": "Selected items", className: "drive-bulk", children: [
|
|
133
|
+
/* @__PURE__ */ jsxs("span", { role: "status", children: [
|
|
134
|
+
count,
|
|
135
|
+
" selected"
|
|
136
|
+
] }),
|
|
137
|
+
/* @__PURE__ */ jsx(Button, { variant: "danger", size: "sm", onClick: onTrash, disabled: busy, children: "Move to trash" }),
|
|
138
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClear, children: "Clear selection" })
|
|
139
|
+
] });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ui/App.tsx
|
|
143
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
38
144
|
var errorText = (e) => e instanceof DriveApiError ? `${e.message} (${e.code})` : e instanceof Error ? e.message : "Something went wrong";
|
|
39
145
|
var byName = (a, b) => (a.kind === "folder" ? 0 : 1) - (b.kind === "folder" ? 0 : 1) || a.name.localeCompare(b.name);
|
|
40
146
|
var who = (a, owner) => a.kind === "human" ? { id: a.id, name: a.id, kind: "person" } : { id: a.id, name: a.id, kind: "agent", actingFor: owner };
|
|
41
|
-
var MachineLabel = ({ item }) => item.machineMade ? /* @__PURE__ */
|
|
147
|
+
var MachineLabel = ({ item }) => item.machineMade ? /* @__PURE__ */ jsx2("span", { className: "agd-pill", children: "Created by agent" }) : null;
|
|
42
148
|
function useLoad(fn) {
|
|
43
|
-
const [state, set] =
|
|
44
|
-
const [tick, setTick] =
|
|
45
|
-
|
|
149
|
+
const [state, set] = useState2({ status: "loading" });
|
|
150
|
+
const [tick, setTick] = useState2(0);
|
|
151
|
+
useEffect2(() => {
|
|
46
152
|
let live = true;
|
|
47
153
|
fn().then((data) => live && set({ status: "ok", data }), (e) => live && set({ status: "error", error: errorText(e) }));
|
|
48
154
|
return () => {
|
|
@@ -52,27 +158,30 @@ function useLoad(fn) {
|
|
|
52
158
|
return [state, () => setTick((n) => n + 1)];
|
|
53
159
|
}
|
|
54
160
|
function Status({ state, retry, children }) {
|
|
55
|
-
if (state.status === "loading") return /* @__PURE__ */
|
|
56
|
-
/* @__PURE__ */
|
|
161
|
+
if (state.status === "loading") return /* @__PURE__ */ jsxs2("p", { role: "status", className: "drive-status", children: [
|
|
162
|
+
/* @__PURE__ */ jsx2("span", { className: "agd-spinner", "aria-hidden": "true" }),
|
|
57
163
|
" Loading\u2026"
|
|
58
164
|
] });
|
|
59
|
-
if (state.status === "error") return /* @__PURE__ */
|
|
60
|
-
return /* @__PURE__ */
|
|
165
|
+
if (state.status === "error") return /* @__PURE__ */ jsx2("div", { role: "alert", children: /* @__PURE__ */ jsx2(EmptyState, { title: "Could not load this page", description: state.error, action: /* @__PURE__ */ jsx2(Button2, { onClick: retry, children: "Try again" }) }) });
|
|
166
|
+
return /* @__PURE__ */ jsx2(Fragment, { children });
|
|
61
167
|
}
|
|
62
168
|
var routeParts = (hash) => hash.replace(/^#\/?/, "").split("/");
|
|
63
169
|
function Routes({ hash, client, origin, go }) {
|
|
64
170
|
const parts = routeParts(hash);
|
|
65
|
-
if (parts[0] === "trash") return /* @__PURE__ */
|
|
66
|
-
if (parts[0] === "f" && parts[1]) return /* @__PURE__ */
|
|
67
|
-
return /* @__PURE__ */
|
|
171
|
+
if (parts[0] === "trash") return /* @__PURE__ */ jsx2(TrashView, { client }, "trash");
|
|
172
|
+
if (parts[0] === "f" && parts[1]) return /* @__PURE__ */ jsx2(Download, { client, id: parts[1], origin, go }, hash);
|
|
173
|
+
return /* @__PURE__ */ jsx2(Browser, { client, loc: parts[0] || "/", origin }, hash);
|
|
68
174
|
}
|
|
69
175
|
function Browser({ client, loc, origin }) {
|
|
70
176
|
const toast = useToast();
|
|
71
|
-
const [view, setView] =
|
|
72
|
-
const [dlg, setDlg] =
|
|
73
|
-
const [drag, setDrag] =
|
|
74
|
-
const [busy, setBusy] =
|
|
75
|
-
const
|
|
177
|
+
const [view, setView] = useState2(() => localStorage.getItem("agentic-drive-view") === "grid" ? "grid" : "list");
|
|
178
|
+
const [dlg, setDlg] = useState2(null);
|
|
179
|
+
const [drag, setDrag] = useState2(false);
|
|
180
|
+
const [busy, setBusy] = useState2(false);
|
|
181
|
+
const [query, setQuery] = useState2("");
|
|
182
|
+
const [sort, setSort] = useState2({ key: "name", dir: "asc" });
|
|
183
|
+
const [selected, setSelected] = useState2(/* @__PURE__ */ new Set());
|
|
184
|
+
const input = useRef2(null);
|
|
76
185
|
const [state, reload] = useLoad(async () => {
|
|
77
186
|
const root = await client.stat("/");
|
|
78
187
|
const folder = loc === "/" ? root : await client.stat(loc);
|
|
@@ -116,20 +225,35 @@ function Browser({ client, loc, origin }) {
|
|
|
116
225
|
setDrag(false);
|
|
117
226
|
if (e.dataTransfer.files.length) void upload(e.dataTransfer.files);
|
|
118
227
|
};
|
|
228
|
+
const onSort = (key) => setSort((s) => ({ key, dir: s.key === key && s.dir === "asc" ? "desc" : "asc" }));
|
|
229
|
+
const trashSelected = async (ids) => {
|
|
230
|
+
setBusy(true);
|
|
231
|
+
const results = await Promise.allSettled(ids.map((id) => client.trash(id)));
|
|
232
|
+
const failed = results.filter((r) => r.status === "rejected");
|
|
233
|
+
if (failed.length) toast({ title: `${failed.length} of ${ids.length} items did not move`, description: errorText(failed[0].reason), tone: "danger" });
|
|
234
|
+
else toast({ title: `Moved ${ids.length} ${ids.length === 1 ? "item" : "items"} to trash`, tone: "success" });
|
|
235
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
236
|
+
setBusy(false);
|
|
237
|
+
reload();
|
|
238
|
+
};
|
|
119
239
|
const setViewMode = (v) => {
|
|
240
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
120
241
|
localStorage.setItem("agentic-drive-view", v);
|
|
121
242
|
setView(v);
|
|
122
243
|
};
|
|
123
|
-
return /* @__PURE__ */
|
|
244
|
+
return /* @__PURE__ */ jsx2("section", { onDragOver: (e) => {
|
|
124
245
|
e.preventDefault();
|
|
125
246
|
setDrag(true);
|
|
126
247
|
}, onDragLeave: (e) => {
|
|
127
248
|
if (!e.currentTarget.contains(e.relatedTarget)) setDrag(false);
|
|
128
|
-
}, onDrop, className: drag ? "
|
|
129
|
-
const { folder, root, crumbs,
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
249
|
+
}, onDrop, className: `drive-drop${drag ? " drive-drop--over" : ""}${view === "list" && selected.size ? " drive-drop--bulk" : ""}`, "aria-label": "Files", children: /* @__PURE__ */ jsx2(Status, { state, retry: reload, children: state.status === "ok" && (() => {
|
|
250
|
+
const { folder, root, crumbs, tree } = state.data;
|
|
251
|
+
const needle = query.trim().toLowerCase();
|
|
252
|
+
const items = sortItems(state.data.items.filter((i) => i.name.toLowerCase().includes(needle)), sort);
|
|
253
|
+
const picked = items.filter((i) => selected.has(i.id)).map((i) => i.id);
|
|
254
|
+
const actions = (item) => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
255
|
+
/* @__PURE__ */ jsx2(MachineLabel, { item }),
|
|
256
|
+
/* @__PURE__ */ jsx2(Menu, { align: "end", trigger: /* @__PURE__ */ jsx2(IconButton, { label: `Actions for ${item.name}`, icon: /* @__PURE__ */ jsx2(MoreIcon, {}), variant: "ghost" }), items: [
|
|
133
257
|
{ label: "Rename", onSelect: () => setDlg({ kind: "rename", item }) },
|
|
134
258
|
{ label: "Move", onSelect: () => setDlg({ kind: "move", item }) },
|
|
135
259
|
{ label: "Share", onSelect: () => setDlg({ kind: "share", item }) },
|
|
@@ -138,55 +262,63 @@ function Browser({ client, loc, origin }) {
|
|
|
138
262
|
] })
|
|
139
263
|
] });
|
|
140
264
|
const href = (i) => i.kind === "folder" ? `#/${i.id}` : `#/f/${i.id}`;
|
|
141
|
-
const level = (id) => /* @__PURE__ */
|
|
142
|
-
/* @__PURE__ */
|
|
143
|
-
/* @__PURE__ */
|
|
265
|
+
const level = (id) => /* @__PURE__ */ jsx2("ul", { className: "drive-tree", children: (tree.get(id) ?? []).map((n) => /* @__PURE__ */ jsxs2("li", { children: [
|
|
266
|
+
/* @__PURE__ */ jsxs2("a", { href: `#/${n.id}`, "aria-current": n.id === folder.id ? "page" : void 0, children: [
|
|
267
|
+
/* @__PURE__ */ jsx2(FolderIcon2, { "aria-hidden": "true" }),
|
|
144
268
|
" ",
|
|
145
269
|
n.name
|
|
146
270
|
] }),
|
|
147
271
|
tree.has(n.id) && level(n.id)
|
|
148
272
|
] }, n.id)) });
|
|
149
|
-
return /* @__PURE__ */
|
|
150
|
-
/* @__PURE__ */
|
|
151
|
-
/* @__PURE__ */
|
|
152
|
-
crumbs.map((c, i) => /* @__PURE__ */
|
|
273
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
274
|
+
/* @__PURE__ */ jsx2("nav", { "aria-label": "Breadcrumb", className: "drive-crumbs", children: /* @__PURE__ */ jsxs2("ol", { children: [
|
|
275
|
+
/* @__PURE__ */ jsx2("li", { children: crumbs.length ? /* @__PURE__ */ jsx2("a", { href: "#/", children: "My files" }) : /* @__PURE__ */ jsx2("span", { "aria-current": "page", children: "My files" }) }),
|
|
276
|
+
crumbs.map((c, i) => /* @__PURE__ */ jsx2("li", { children: i === crumbs.length - 1 ? /* @__PURE__ */ jsx2("span", { "aria-current": "page", children: c.name }) : /* @__PURE__ */ jsx2("a", { href: `#/${c.id}`, children: c.name }) }, c.id))
|
|
153
277
|
] }) }),
|
|
154
|
-
/* @__PURE__ */
|
|
155
|
-
/* @__PURE__ */
|
|
156
|
-
|
|
157
|
-
/* @__PURE__ */
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
/* @__PURE__ */
|
|
278
|
+
/* @__PURE__ */ jsxs2("div", { className: "drive-bar", children: [
|
|
279
|
+
/* @__PURE__ */ jsxs2("div", { className: "drive-title", children: [
|
|
280
|
+
/* @__PURE__ */ jsx2("h1", { children: folder.id === root.id ? "My files" : folder.name }),
|
|
281
|
+
folder.id !== root.id && /* @__PURE__ */ jsx2(Button2, { variant: "secondary", size: "sm", onClick: () => setDlg({ kind: "share", item: folder }), children: "Share" })
|
|
282
|
+
] }),
|
|
283
|
+
/* @__PURE__ */ jsxs2(Toolbar, { label: "Folder actions", children: [
|
|
284
|
+
/* @__PURE__ */ jsx2(ToolbarButton, { label: "New folder", icon: /* @__PURE__ */ jsx2(PlusIcon, {}), onClick: () => setDlg({ kind: "mkdir" }) }),
|
|
285
|
+
/* @__PURE__ */ jsx2(ToolbarButton, { label: "Upload files", icon: /* @__PURE__ */ jsx2(FileIcon2, {}), onClick: () => input.current?.click(), disabled: busy }),
|
|
286
|
+
/* @__PURE__ */ jsx2(ToolbarButton, { label: "List view", icon: /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: "\u2630" }), pressed: view === "list", onClick: () => setViewMode("list") }),
|
|
287
|
+
/* @__PURE__ */ jsx2(ToolbarButton, { label: "Grid view", icon: /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: "\u25A6" }), pressed: view === "grid", onClick: () => setViewMode("grid") })
|
|
161
288
|
] }),
|
|
162
|
-
/* @__PURE__ */
|
|
289
|
+
/* @__PURE__ */ jsx2("input", { ref: input, type: "file", multiple: true, hidden: true, "aria-label": "Choose files to upload", onChange: (e) => {
|
|
163
290
|
if (e.target.files) void upload(e.target.files);
|
|
164
291
|
e.target.value = "";
|
|
165
292
|
} })
|
|
166
293
|
] }),
|
|
167
|
-
/* @__PURE__ */
|
|
168
|
-
/* @__PURE__ */
|
|
169
|
-
/* @__PURE__ */
|
|
170
|
-
/* @__PURE__ */
|
|
171
|
-
/* @__PURE__ */
|
|
172
|
-
/* @__PURE__ */
|
|
173
|
-
"
|
|
174
|
-
/* @__PURE__ */
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
294
|
+
/* @__PURE__ */ jsxs2("div", { className: "drive-split", children: [
|
|
295
|
+
/* @__PURE__ */ jsx2("nav", { "aria-label": "Folders", className: "drive-folders", children: level(root.id) }),
|
|
296
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
297
|
+
/* @__PURE__ */ jsx2("div", { className: "drive-tools", children: /* @__PURE__ */ jsx2(ExpandableSearch, { value: query, onChange: setQuery }) }),
|
|
298
|
+
/* @__PURE__ */ jsx2("p", { role: "status", className: "drive-sr", children: needle ? `${items.length} of ${state.data.items.length} items match` : "" }),
|
|
299
|
+
state.data.items.length === 0 ? /* @__PURE__ */ jsx2(EmptyState, { title: "This folder is empty", description: "Drop files here, or use Upload files.", action: /* @__PURE__ */ jsx2(Button2, { onClick: () => input.current?.click(), disabled: busy, children: "Upload files" }) }) : items.length === 0 ? /* @__PURE__ */ jsx2(EmptyState, { title: "Nothing matches", description: `No item in this folder has \u201C${query.trim()}\u201D in its name.`, action: /* @__PURE__ */ jsx2(Button2, { onClick: () => setQuery(""), children: "Clear search" }) }) : view === "list" ? /* @__PURE__ */ jsx2(ItemTable, { label: `Items in ${folder.name || "My files"}`, items, sort, onSort, selected, onSelect: setSelected, href, who, actions }) : /* @__PURE__ */ jsx2("ul", { className: "drive-grid", "aria-label": `Items in ${folder.name || "My files"}`, children: items.map((i) => /* @__PURE__ */ jsxs2("li", { className: "drive-card", children: [
|
|
300
|
+
/* @__PURE__ */ jsx2("span", { className: "drive-card__icon", "aria-hidden": "true", children: i.kind === "folder" ? /* @__PURE__ */ jsx2(FolderIcon2, {}) : /* @__PURE__ */ jsx2(FileIcon2, {}) }),
|
|
301
|
+
/* @__PURE__ */ jsx2("a", { href: href(i), className: "drive-card__name", children: i.name }),
|
|
302
|
+
/* @__PURE__ */ jsxs2("span", { className: "drive-card__meta", children: [
|
|
303
|
+
"Edited by ",
|
|
304
|
+
/* @__PURE__ */ jsx2(PresenceChip2, { entry: who(i.updatedBy, i.owner) })
|
|
305
|
+
] }),
|
|
306
|
+
/* @__PURE__ */ jsx2("span", { className: "drive-card__actions", children: actions(i) })
|
|
307
|
+
] }, i.id)) })
|
|
308
|
+
] })
|
|
178
309
|
] }),
|
|
179
|
-
|
|
180
|
-
dlg?.kind === "
|
|
181
|
-
dlg?.kind === "
|
|
182
|
-
dlg?.kind === "
|
|
310
|
+
view === "list" && /* @__PURE__ */ jsx2(BulkBar, { count: picked.length, busy, onTrash: () => void trashSelected(picked), onClear: () => setSelected(/* @__PURE__ */ new Set()) }),
|
|
311
|
+
dlg?.kind === "mkdir" && /* @__PURE__ */ jsx2(Prompt, { open: true, title: "New folder", label: "Folder name", initial: "", submit: "Create", onClose: () => setDlg(null), onSubmit: (name) => act(() => client.mkdir(folder.id === root.id ? `/${name}` : `${folder.id}/${name}`), `Created ${name}`) }),
|
|
312
|
+
dlg?.kind === "rename" && /* @__PURE__ */ jsx2(Prompt, { open: true, title: "Rename", label: "New name", initial: dlg.item.name, submit: "Rename", onClose: () => setDlg(null), onSubmit: (name) => act(() => client.move(dlg.item.id, dlg.item.parentId, { name }), `Renamed to ${name}`) }),
|
|
313
|
+
dlg?.kind === "move" && /* @__PURE__ */ jsx2(MoveDialog, { client, item: dlg.item, onClose: () => setDlg(null), onMove: (to) => act(() => client.move(dlg.item.id, to), `Moved ${dlg.item.name}`) }),
|
|
314
|
+
dlg?.kind === "share" && /* @__PURE__ */ jsx2(Sharing, { client, item: dlg.item, origin, onClose: () => setDlg(null) })
|
|
183
315
|
] });
|
|
184
316
|
})() }) });
|
|
185
317
|
}
|
|
186
318
|
function Prompt({ open, title, label, initial, submit, onClose, onSubmit }) {
|
|
187
|
-
const [value, setValue] =
|
|
188
|
-
const sent =
|
|
189
|
-
const [problem, setProblem] =
|
|
319
|
+
const [value, setValue] = useState2(initial);
|
|
320
|
+
const sent = useRef2(false);
|
|
321
|
+
const [problem, setProblem] = useState2();
|
|
190
322
|
const send = (name) => {
|
|
191
323
|
if (!name) return;
|
|
192
324
|
if (name.includes("/")) return setProblem("A name cannot have a slash.");
|
|
@@ -196,16 +328,16 @@ function Prompt({ open, title, label, initial, submit, onClose, onSubmit }) {
|
|
|
196
328
|
sent.current = false;
|
|
197
329
|
});
|
|
198
330
|
};
|
|
199
|
-
return /* @__PURE__ */
|
|
331
|
+
return /* @__PURE__ */ jsx2(Dialog, { open: !!open, onOpenChange: (o) => {
|
|
200
332
|
if (!o) onClose();
|
|
201
|
-
}, title, children: /* @__PURE__ */
|
|
333
|
+
}, title, children: /* @__PURE__ */ jsxs2("form", { onSubmit: (e) => {
|
|
202
334
|
e.preventDefault();
|
|
203
335
|
if (!sent.current) send(value.trim());
|
|
204
336
|
}, className: "drive-form", children: [
|
|
205
|
-
/* @__PURE__ */
|
|
206
|
-
/* @__PURE__ */
|
|
207
|
-
/* @__PURE__ */
|
|
208
|
-
/* @__PURE__ */
|
|
337
|
+
/* @__PURE__ */ jsx2(Input, { label, value, onChange: (e) => setValue(e.target.value), error: problem, required: true }),
|
|
338
|
+
/* @__PURE__ */ jsxs2("div", { className: "drive-form__actions", children: [
|
|
339
|
+
/* @__PURE__ */ jsx2(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx2(Button2, { variant: "ghost", type: "button", children: "Cancel" }) }),
|
|
340
|
+
/* @__PURE__ */ jsx2(Button2, { type: "submit", children: submit })
|
|
209
341
|
] })
|
|
210
342
|
] }) });
|
|
211
343
|
}
|
|
@@ -216,11 +348,11 @@ function MoveDialog({ client, item, onClose, onMove }) {
|
|
|
216
348
|
const own = all.find((x) => x.id === item.id)?.path;
|
|
217
349
|
return [{ id: "/", path: "/", name: "My files" }, ...all.filter((x) => x.id !== root.id && !(own && (x.path === own || x.path.startsWith(`${own}/`))))];
|
|
218
350
|
});
|
|
219
|
-
const [to, setTo] =
|
|
220
|
-
const sent =
|
|
221
|
-
return /* @__PURE__ */
|
|
351
|
+
const [to, setTo] = useState2("/");
|
|
352
|
+
const sent = useRef2(false);
|
|
353
|
+
return /* @__PURE__ */ jsx2(Dialog, { open: true, onOpenChange: (o) => {
|
|
222
354
|
if (!o) onClose();
|
|
223
|
-
}, title: `Move ${item.name}`, children: /* @__PURE__ */
|
|
355
|
+
}, title: `Move ${item.name}`, children: /* @__PURE__ */ jsx2(Status, { state: folders, retry, children: folders.status === "ok" && /* @__PURE__ */ jsxs2("form", { onSubmit: (e) => {
|
|
224
356
|
e.preventDefault();
|
|
225
357
|
if (sent.current) return;
|
|
226
358
|
sent.current = true;
|
|
@@ -228,10 +360,10 @@ function MoveDialog({ client, item, onClose, onMove }) {
|
|
|
228
360
|
sent.current = false;
|
|
229
361
|
});
|
|
230
362
|
}, className: "drive-form", children: [
|
|
231
|
-
/* @__PURE__ */
|
|
232
|
-
/* @__PURE__ */
|
|
233
|
-
/* @__PURE__ */
|
|
234
|
-
/* @__PURE__ */
|
|
363
|
+
/* @__PURE__ */ jsx2(Select, { label: "Move to", value: to, onChange: (e) => setTo(e.target.value), children: folders.data.map((x) => /* @__PURE__ */ jsx2("option", { value: x.id, children: x.path === "/" ? "My files" : x.path }, x.id)) }),
|
|
364
|
+
/* @__PURE__ */ jsxs2("div", { className: "drive-form__actions", children: [
|
|
365
|
+
/* @__PURE__ */ jsx2(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx2(Button2, { variant: "ghost", type: "button", children: "Cancel" }) }),
|
|
366
|
+
/* @__PURE__ */ jsx2(Button2, { type: "submit", children: "Move" })
|
|
235
367
|
] })
|
|
236
368
|
] }) }) });
|
|
237
369
|
}
|
|
@@ -239,7 +371,7 @@ var EXPIRY_MS = { never: void 0, "1d": 864e5, "7d": 7 * 864e5, "30d": 30 * 864e5
|
|
|
239
371
|
function Sharing({ client, item, origin, onClose }) {
|
|
240
372
|
const toast = useToast();
|
|
241
373
|
const [state, reload] = useLoad(() => client.shares(item.id));
|
|
242
|
-
const [link, setLink] =
|
|
374
|
+
const [link, setLink] = useState2({ role: "viewer", expiry: "never", signedInOnly: false });
|
|
243
375
|
const liveLinks = state.status === "ok" ? state.data.links.filter((l) => !l.revoked && (l.expiresAt === null || l.expiresAt > Date.now())) : [];
|
|
244
376
|
const live = liveLinks[0];
|
|
245
377
|
const current = link.id ? link : live ? { ...link, id: live.id, role: live.role === "owner" ? "editor" : live.role, signedInOnly: live.signedInOnly } : link;
|
|
@@ -270,7 +402,7 @@ function Sharing({ client, item, origin, onClose }) {
|
|
|
270
402
|
url: current.token ? `${origin}/#/s/${item.id}/${current.token}` : "Turn the link off and on to make a new one. The address shows once.",
|
|
271
403
|
expiresAt: live?.expiresAt ? new Date(live.expiresAt) : null
|
|
272
404
|
};
|
|
273
|
-
return /* @__PURE__ */
|
|
405
|
+
return /* @__PURE__ */ jsx2(
|
|
274
406
|
ShareDialog,
|
|
275
407
|
{
|
|
276
408
|
open: true,
|
|
@@ -298,9 +430,12 @@ function Sharing({ client, item, origin, onClose }) {
|
|
|
298
430
|
}
|
|
299
431
|
);
|
|
300
432
|
}
|
|
433
|
+
var trashedAt = (i) => i.trashedAt ?? i.updatedAt;
|
|
301
434
|
function TrashView({ client }) {
|
|
302
435
|
const toast = useToast();
|
|
303
436
|
const [state, reload] = useLoad(() => client.listTrash());
|
|
437
|
+
const [sort, setSort] = useState2({ key: "name", dir: "asc" });
|
|
438
|
+
const onSort = (key) => setSort((s) => ({ key, dir: s.key === key && s.dir === "asc" ? "desc" : "asc" }));
|
|
304
439
|
const restore = async (i) => {
|
|
305
440
|
try {
|
|
306
441
|
await client.restore(i.id, { onConflict: "rename" });
|
|
@@ -310,12 +445,12 @@ function TrashView({ client }) {
|
|
|
310
445
|
}
|
|
311
446
|
reload();
|
|
312
447
|
};
|
|
313
|
-
return /* @__PURE__ */
|
|
314
|
-
/* @__PURE__ */
|
|
315
|
-
/* @__PURE__ */
|
|
316
|
-
/* @__PURE__ */
|
|
317
|
-
/* @__PURE__ */
|
|
318
|
-
] }) }
|
|
448
|
+
return /* @__PURE__ */ jsxs2("section", { "aria-label": "Trash", children: [
|
|
449
|
+
/* @__PURE__ */ jsx2("h1", { children: "Trash" }),
|
|
450
|
+
/* @__PURE__ */ jsx2(Status, { state, retry: reload, children: state.status === "ok" && (state.data.length === 0 ? /* @__PURE__ */ jsx2(EmptyState, { title: "The trash is empty", description: "Items you move to the trash show up here." }) : /* @__PURE__ */ jsx2(ItemTable, { label: "Items in the trash", items: sortItems(state.data, sort, trashedAt), dateOf: trashedAt, sort, onSort, href: () => "#/trash", who, actions: (i) => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
451
|
+
/* @__PURE__ */ jsx2(MachineLabel, { item: i }),
|
|
452
|
+
/* @__PURE__ */ jsx2(Button2, { size: "sm", onClick: () => void restore(i), children: `Restore ${i.name}` })
|
|
453
|
+
] }) })) })
|
|
319
454
|
] });
|
|
320
455
|
}
|
|
321
456
|
function Download({ client, id, origin, go }) {
|
|
@@ -330,11 +465,11 @@ function Download({ client, id, origin, go }) {
|
|
|
330
465
|
go(item.parentId);
|
|
331
466
|
return item;
|
|
332
467
|
});
|
|
333
|
-
return /* @__PURE__ */
|
|
468
|
+
return /* @__PURE__ */ jsx2(Status, { state, retry, children: null });
|
|
334
469
|
}
|
|
335
470
|
|
|
336
471
|
// ui/embed.tsx
|
|
337
|
-
import { jsx as
|
|
472
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
338
473
|
var PLACEHOLDER = "from-get-token";
|
|
339
474
|
function makeClient({ baseUrl, getToken }) {
|
|
340
475
|
if (typeof getToken !== "function") throw new TypeError("getToken must be a function");
|
|
@@ -354,16 +489,16 @@ function makeClient({ baseUrl, getToken }) {
|
|
|
354
489
|
}
|
|
355
490
|
var clients = 0;
|
|
356
491
|
function DriveBrowser({ baseUrl, getToken }) {
|
|
357
|
-
const [made, setMade] =
|
|
358
|
-
|
|
492
|
+
const [made, setMade] = useState3();
|
|
493
|
+
useEffect3(() => {
|
|
359
494
|
const next = makeClient({ baseUrl, getToken });
|
|
360
495
|
setMade({ id: ++clients, client: next.client, origin: new URL(baseUrl).origin });
|
|
361
496
|
return () => next.close();
|
|
362
497
|
}, [baseUrl, getToken]);
|
|
363
|
-
return made ? /* @__PURE__ */
|
|
498
|
+
return made ? /* @__PURE__ */ jsx3(DriveView, { client: made.client, origin: made.origin }, made.id) : null;
|
|
364
499
|
}
|
|
365
500
|
function DriveView({ client, origin }) {
|
|
366
|
-
const [hash, setHash] =
|
|
501
|
+
const [hash, setHash] = useState3("#/");
|
|
367
502
|
const go = (loc) => setHash(`#/${loc === "/" ? "" : loc}`);
|
|
368
503
|
const follow = (e) => {
|
|
369
504
|
if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
@@ -373,12 +508,12 @@ function DriveView({ client, origin }) {
|
|
|
373
508
|
setHash(link.getAttribute("href"));
|
|
374
509
|
};
|
|
375
510
|
const place = hash.startsWith("#/trash") ? "trash" : "files";
|
|
376
|
-
return /* @__PURE__ */
|
|
377
|
-
/* @__PURE__ */
|
|
378
|
-
{ href: "#/", label: "My files", icon: /* @__PURE__ */
|
|
511
|
+
return /* @__PURE__ */ jsxs3("div", { className: "drive-root", onClick: follow, children: [
|
|
512
|
+
/* @__PURE__ */ jsx3(SidebarNav2, { label: "Places", items: [
|
|
513
|
+
{ href: "#/", label: "My files", icon: /* @__PURE__ */ jsx3(FolderIcon3, { "aria-hidden": "true" }), current: place === "files" },
|
|
379
514
|
{ href: "#/trash", label: "Trash", current: place === "trash" }
|
|
380
515
|
] }),
|
|
381
|
-
/* @__PURE__ */
|
|
516
|
+
/* @__PURE__ */ jsx3("div", { className: "drive-main", children: /* @__PURE__ */ jsx3(Routes, { hash, client, origin, go }) })
|
|
382
517
|
] });
|
|
383
518
|
}
|
|
384
519
|
function mount(element, options) {
|
|
@@ -387,7 +522,7 @@ function mount(element, options) {
|
|
|
387
522
|
let open = true;
|
|
388
523
|
let version = 0;
|
|
389
524
|
const render = (next, client) => root.render(
|
|
390
|
-
/* @__PURE__ */
|
|
525
|
+
/* @__PURE__ */ jsx3(TooltipProvider, { children: /* @__PURE__ */ jsx3(ToastProvider, { children: /* @__PURE__ */ jsx3(DriveView, { client, origin: new URL(next.baseUrl).origin }, version++) }) })
|
|
391
526
|
);
|
|
392
527
|
render(options, current.client);
|
|
393
528
|
return {
|
package/dist/index.js
CHANGED
package/dist/mcp.js
CHANGED