@halazv2/react-file-manager 0.1.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/dist/index.js ADDED
@@ -0,0 +1,839 @@
1
+ import { Fragment as e, jsx as t, jsxs as n } from "react/jsx-runtime";
2
+ import { createContext as r, useCallback as i, useContext as a, useDeferredValue as o, useEffect as s, useMemo as c, useRef as l, useState as u } from "react";
3
+ //#region src/icons.tsx
4
+ function d({ size: e = 16, className: t, ...n }) {
5
+ return {
6
+ viewBox: "0 0 24 24",
7
+ fill: "none",
8
+ stroke: "currentColor",
9
+ strokeWidth: 1.8,
10
+ strokeLinecap: "round",
11
+ strokeLinejoin: "round",
12
+ width: e,
13
+ height: e,
14
+ className: t,
15
+ "aria-hidden": !0,
16
+ ...n
17
+ };
18
+ }
19
+ function f(e) {
20
+ return /* @__PURE__ */ t("svg", {
21
+ ...d(e),
22
+ children: /* @__PURE__ */ t("path", { d: "M3 7.5A1.5 1.5 0 0 1 4.5 6h4.2l1.8 1.8H19.5A1.5 1.5 0 0 1 21 9.3v7.2A1.5 1.5 0 0 1 19.5 18h-15A1.5 1.5 0 0 1 3 16.5z" })
23
+ });
24
+ }
25
+ function p(e) {
26
+ return /* @__PURE__ */ n("svg", {
27
+ ...d(e),
28
+ children: [/* @__PURE__ */ t("path", { d: "M7 3.5h7l5 5V20a1.5 1.5 0 0 1-1.5 1.5h-10.5A1.5 1.5 0 0 1 5.5 20V5A1.5 1.5 0 0 1 7 3.5z" }), /* @__PURE__ */ t("path", { d: "M14 3.5V9h5.5" })]
29
+ });
30
+ }
31
+ function m(e) {
32
+ return /* @__PURE__ */ n("svg", {
33
+ ...d(e),
34
+ children: [/* @__PURE__ */ t("path", { d: "M4 11.5 12 4.5l8 7" }), /* @__PURE__ */ t("path", { d: "M6.5 10.5V19h11v-8.5" })]
35
+ });
36
+ }
37
+ function h(e) {
38
+ return /* @__PURE__ */ t("svg", {
39
+ ...d(e),
40
+ children: /* @__PURE__ */ t("path", { d: "m9 6 6 6-6 6" })
41
+ });
42
+ }
43
+ function g(e) {
44
+ return /* @__PURE__ */ n("svg", {
45
+ ...d(e),
46
+ children: [/* @__PURE__ */ t("path", { d: "M8 7h12M8 12h12M8 17h12" }), /* @__PURE__ */ t("path", { d: "M4 7h.01M4 12h.01M4 17h.01" })]
47
+ });
48
+ }
49
+ function _(e) {
50
+ return /* @__PURE__ */ t("svg", {
51
+ ...d(e),
52
+ children: /* @__PURE__ */ t("path", { d: "M4 5h7v7H4zM13 5h7v7h-7zM4 14h7v6H4zM13 14h7v6h-7z" })
53
+ });
54
+ }
55
+ function v(e) {
56
+ return /* @__PURE__ */ n("svg", {
57
+ ...d(e),
58
+ children: [/* @__PURE__ */ t("path", { d: "M8 4H4v4M16 4h4v4M8 20H4v-4M16 20h4v-4" }), /* @__PURE__ */ t("path", { d: "m14 10-4 4m0-4 4 4" })]
59
+ });
60
+ }
61
+ function y(e) {
62
+ return /* @__PURE__ */ n("svg", {
63
+ ...d(e),
64
+ children: [/* @__PURE__ */ t("circle", {
65
+ cx: "11",
66
+ cy: "11",
67
+ r: "6.5"
68
+ }), /* @__PURE__ */ t("path", { d: "m16 16 4 4" })]
69
+ });
70
+ }
71
+ function b(e) {
72
+ return /* @__PURE__ */ n("svg", {
73
+ ...d(e),
74
+ children: [
75
+ /* @__PURE__ */ t("path", { d: "M12 16V5" }),
76
+ /* @__PURE__ */ t("path", { d: "m8 9 4-4 4 4" }),
77
+ /* @__PURE__ */ t("path", { d: "M5 19h14" })
78
+ ]
79
+ });
80
+ }
81
+ //#endregion
82
+ //#region src/context.ts
83
+ var x = r(null);
84
+ function S() {
85
+ let e = a(x);
86
+ if (!e) throw Error("FileManager components must be used inside <FileManager>");
87
+ return e;
88
+ }
89
+ //#endregion
90
+ //#region src/styles.ts
91
+ function C(...e) {
92
+ return e.filter(Boolean).join(" ");
93
+ }
94
+ var w = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rfm-primary", T = "transition-colors duration-150";
95
+ C("inline-flex shrink-0 items-center justify-center rounded-md border-0 bg-transparent text-gray-500 hover:bg-black/[0.06] hover:text-gray-900", T, w);
96
+ var E = "bg-rfm-hover outline-dashed outline-2 outline-rfm-primary";
97
+ //#endregion
98
+ //#region src/components/Breadcrumbs.tsx
99
+ function ee() {
100
+ let { breadcrumbs: e, dropTargetId: r, rootLabel: i, openFolder: a, folderDropHandlers: o } = S();
101
+ return /* @__PURE__ */ n("nav", {
102
+ className: "flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto overflow-y-hidden text-[13px] [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden",
103
+ "aria-label": "Breadcrumb",
104
+ children: [/* @__PURE__ */ t("button", {
105
+ type: "button",
106
+ className: C("cursor-pointer whitespace-nowrap rounded-sm border-0 bg-transparent p-0 text-gray-700 hover:text-rfm-primary", r === "root" ? E : ""),
107
+ onClick: () => a(null),
108
+ ...o("root"),
109
+ children: i
110
+ }), e.map((e) => /* @__PURE__ */ n("span", {
111
+ className: "inline-flex items-center gap-1",
112
+ children: [/* @__PURE__ */ t(h, {
113
+ className: "text-gray-400",
114
+ size: 14
115
+ }), /* @__PURE__ */ t("button", {
116
+ type: "button",
117
+ className: C("cursor-pointer whitespace-nowrap rounded-sm border-0 bg-transparent p-0 text-gray-700 hover:text-rfm-primary", r === e.id ? E : ""),
118
+ onClick: () => a(e.id),
119
+ ...o(e.id),
120
+ children: e.name
121
+ })]
122
+ }, e.id))]
123
+ });
124
+ }
125
+ //#endregion
126
+ //#region src/tree.ts
127
+ function D(e, t) {
128
+ for (let n of e) {
129
+ if (n.id === t) return n;
130
+ if (n.children?.length) {
131
+ let e = D(n.children, t);
132
+ if (e) return e;
133
+ }
134
+ }
135
+ return null;
136
+ }
137
+ function O(e, t) {
138
+ return e.id === t || (e.children ?? []).some((e) => O(e, t));
139
+ }
140
+ function k(e) {
141
+ return (e.children ?? []).some((e) => e.kind === "folder");
142
+ }
143
+ function A(e, t) {
144
+ return t ? D(e, t)?.children ?? [] : e;
145
+ }
146
+ function te(e, t) {
147
+ return [...A(e, t)].sort((e, t) => e.kind === t.kind ? e.name.localeCompare(t.name) : e.kind === "folder" ? -1 : 1);
148
+ }
149
+ function ne(e, t) {
150
+ if (!t) return [];
151
+ let n = [], r = (e) => {
152
+ for (let i of e) {
153
+ if (i.id === t) return n.push(i), !0;
154
+ if (i.kind === "folder" && r(i.children ?? [])) return n.unshift(i), !0;
155
+ }
156
+ return !1;
157
+ };
158
+ return r(e), n;
159
+ }
160
+ function j(e, t) {
161
+ return [t, ...e].join(" / ");
162
+ }
163
+ function re(e, t, n = "My files") {
164
+ let r = t.trim().toLowerCase();
165
+ if (!r) return [];
166
+ let i = [], a = (e, t) => {
167
+ let o = j(t, n);
168
+ for (let n of e) n.name.toLowerCase().includes(r) && i.push({
169
+ ...n,
170
+ path: o
171
+ }), n.kind === "folder" && a(n.children ?? [], [...t, n.name]);
172
+ };
173
+ return a(e, []), i;
174
+ }
175
+ function M(e) {
176
+ if (e.kind !== "folder") return e.extension ? e.extension.replace(/^\./, "").toLowerCase() : e.name.match(/\.([^.]+)$/)?.[1]?.toLowerCase();
177
+ }
178
+ function N(e, t, n) {
179
+ let r = new Set(t), i = [];
180
+ for (let r of t) {
181
+ let t = D(e, r);
182
+ if (t && t.kind === "folder" && n && O(t, n)) return e;
183
+ }
184
+ let a = (e) => e.flatMap((e) => r.has(e.id) ? (i.push(e), []) : e.children ? [{
185
+ ...e,
186
+ children: a(e.children)
187
+ }] : [e]), o = a(e);
188
+ if (!i.length) return e;
189
+ if (!n) return [...o, ...i];
190
+ let s = (e) => e.map((e) => e.id === n ? {
191
+ ...e,
192
+ children: [...e.children ?? [], ...i]
193
+ } : e.children ? {
194
+ ...e,
195
+ children: s(e.children)
196
+ } : e);
197
+ return s(o);
198
+ }
199
+ //#endregion
200
+ //#region src/components/Item.tsx
201
+ function P({ item: e, index: r }) {
202
+ let { view: i, selectedIds: a, focusedIndex: o, dropTargetId: s, canManage: c, selectItem: l, activateItem: u, onDragStart: d, folderDropHandlers: m, renderIcon: h, renderActions: g } = S(), _ = a.includes(e.id), v = o === r, y = e.kind === "folder", b = s === e.id && y, x = y ? e.children?.length ?? 0 : null, w = M(e);
203
+ return /* @__PURE__ */ t("div", {
204
+ className: "rfm-row min-w-0",
205
+ children: /* @__PURE__ */ n("div", {
206
+ draggable: c,
207
+ role: "option",
208
+ "aria-selected": _,
209
+ "aria-label": e.name,
210
+ className: C("cursor-pointer", i === "cards" ? "group/card relative flex min-h-[116px] flex-col items-center justify-center gap-2 overflow-hidden rounded-xl border border-gray-200 p-3 text-center shadow-[0_1px_2px_rgba(16,24,40,0.05)] transition duration-150 hover:-translate-y-px hover:border-gray-300 hover:shadow-[0_4px_12px_rgba(16,24,40,0.08)]" : C("group/row grid grid-cols-[22px_minmax(0,1fr)_auto_auto] items-center gap-2 rounded-lg px-2.5 py-2", T), _ ? "bg-rfm-hover" : i === "list" ? "hover:bg-gray-100" : "bg-white", v && i === "list" ? "outline outline-1 outline-rfm-primary" : "", b ? E : ""),
211
+ onDragStart: (t) => d(e, t),
212
+ ...y ? m(e.id) : {},
213
+ onClick: (t) => l(e, t),
214
+ onDoubleClick: () => u(e),
215
+ children: [
216
+ h?.(e) ?? t(y ? f : p, { size: i === "cards" ? 36 : 18 }),
217
+ /* @__PURE__ */ n("span", {
218
+ className: "flex min-w-0 flex-col gap-px",
219
+ children: [/* @__PURE__ */ t("span", {
220
+ className: C("min-w-0 text-[13px] text-gray-900", i === "cards" ? "line-clamp-2 w-full break-words text-center" : "truncate"),
221
+ children: e.name
222
+ }), e.path && /* @__PURE__ */ t("span", {
223
+ className: "min-w-0 truncate text-[11px] text-gray-500",
224
+ children: e.path
225
+ })]
226
+ }),
227
+ i === "list" && /* @__PURE__ */ t("span", {
228
+ className: "text-[11px] text-gray-500",
229
+ children: y ? `${x} item${x === 1 ? "" : "s"}` : (w || "file").toUpperCase()
230
+ }),
231
+ g && /* @__PURE__ */ t("span", {
232
+ className: C("rfm-more", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rfm-primary", _ || v ? "opacity-100" : "", i === "cards" ? "absolute right-1.5 top-1.5" : ""),
233
+ children: g(e)
234
+ })
235
+ ]
236
+ })
237
+ });
238
+ }
239
+ function ie({ folders: r, depth: i = 0 }) {
240
+ let { viewFolderId: a, dropTargetId: o, expandedIds: s, openFolder: c, toggleExpanded: l, folderDropHandlers: u, renderIcon: d, renderActions: p } = S();
241
+ return /* @__PURE__ */ t(e, { children: r.filter((e) => e.kind === "folder").map((e) => {
242
+ let r = k(e), m = s.has(e.id), h = a === e.id, g = o === e.id;
243
+ return /* @__PURE__ */ n("div", {
244
+ className: "min-w-0",
245
+ children: [/* @__PURE__ */ n("div", {
246
+ role: "treeitem",
247
+ "aria-selected": h,
248
+ "aria-label": e.name,
249
+ tabIndex: 0,
250
+ className: C("rfm-tree-row group/tree mb-0.5 flex w-full cursor-pointer items-center gap-1 rounded-md py-1 pr-1 text-left text-[13px]", h ? "bg-rfm-hover font-semibold text-rfm-primary" : "text-gray-900 hover:bg-black/[0.04]", g ? E : "", T, w),
251
+ style: { paddingLeft: 6 + i * 12 },
252
+ onClick: () => c(e.id),
253
+ ...u(e.id),
254
+ children: [
255
+ /* @__PURE__ */ t("button", {
256
+ type: "button",
257
+ className: C("inline-flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded border-0 bg-transparent p-0 text-gray-500", m ? "rotate-90" : "", r ? "cursor-pointer hover:bg-black/[0.06] hover:text-gray-900" : "invisible pointer-events-none", T, w),
258
+ "aria-label": m ? "Collapse folder" : "Expand folder",
259
+ disabled: !r,
260
+ onClick: (t) => {
261
+ r && l(t, e.id);
262
+ },
263
+ children: /* @__PURE__ */ t(F, {})
264
+ }),
265
+ d?.(e) ?? /* @__PURE__ */ t(f, { size: 16 }),
266
+ /* @__PURE__ */ t("span", {
267
+ className: "min-w-0 flex-1 truncate",
268
+ title: e.name,
269
+ children: e.name
270
+ }),
271
+ p && /* @__PURE__ */ t("span", {
272
+ className: "rfm-more",
273
+ children: p(e)
274
+ })
275
+ ]
276
+ }), r && m && /* @__PURE__ */ t("div", {
277
+ className: "min-w-0",
278
+ children: /* @__PURE__ */ t(ie, {
279
+ folders: e.children ?? [],
280
+ depth: i + 1
281
+ })
282
+ })]
283
+ }, e.id);
284
+ }) });
285
+ }
286
+ function F() {
287
+ return /* @__PURE__ */ t("svg", {
288
+ viewBox: "0 0 24 24",
289
+ width: 14,
290
+ height: 14,
291
+ fill: "none",
292
+ stroke: "currentColor",
293
+ strokeWidth: "1.8",
294
+ "aria-hidden": !0,
295
+ children: /* @__PURE__ */ t("path", { d: "m9 6 6 6-6 6" })
296
+ });
297
+ }
298
+ //#endregion
299
+ //#region src/components/Browser.tsx
300
+ function I() {
301
+ let { view: e, searchQuery: r, canManage: i, isBusy: a, items: o, viewItems: s, viewFolderId: c, folderId: l, selectedIds: u, setView: d, setSearchQuery: f, onDropOnFolder: p, onUpload: m, fileInputRef: h } = S(), v = e === "cards" ? "grid grid-cols-[repeat(auto-fill,minmax(160px,1fr))] content-start gap-2.5 p-3" : "flex flex-col gap-0.5 px-2.5 pb-4 pt-2", b = s !== o, x = b ? s : o;
302
+ return /* @__PURE__ */ n("section", {
303
+ className: "relative flex min-h-0 min-w-0 flex-col overflow-hidden bg-white",
304
+ onDragOver: (e) => {
305
+ i && (e.preventDefault(), e.dataTransfer.dropEffect = "move");
306
+ },
307
+ onDrop: (e) => {
308
+ i && p(e, c);
309
+ },
310
+ children: [
311
+ /* @__PURE__ */ n("div", {
312
+ className: "flex shrink-0 flex-wrap items-center justify-between gap-2 border-b border-black/[0.06] px-3 py-2.5",
313
+ children: [/* @__PURE__ */ t(ee, {}), /* @__PURE__ */ n("div", {
314
+ className: "ml-auto flex items-center gap-2",
315
+ children: [/* @__PURE__ */ n("label", {
316
+ className: "relative",
317
+ children: [/* @__PURE__ */ t(y, {
318
+ className: "pointer-events-none absolute top-1/2 left-2 -translate-y-1/2 text-gray-400",
319
+ size: 14
320
+ }), /* @__PURE__ */ t("input", {
321
+ type: "search",
322
+ value: r,
323
+ placeholder: "Search",
324
+ "aria-label": "Search files",
325
+ className: C("h-7 w-40 rounded-md border border-gray-200 bg-gray-50 pr-2 pl-7 text-[13px] text-gray-900 outline-none placeholder:text-gray-400 focus:border-rfm-primary", w),
326
+ onChange: (e) => f(e.target.value)
327
+ })]
328
+ }), /* @__PURE__ */ n("div", {
329
+ className: "flex gap-1",
330
+ children: [/* @__PURE__ */ t(ae, {
331
+ label: "List view",
332
+ pressed: e === "list",
333
+ onClick: () => d("list"),
334
+ children: /* @__PURE__ */ t(g, { size: 16 })
335
+ }), /* @__PURE__ */ t(ae, {
336
+ label: "Card view",
337
+ pressed: e === "cards",
338
+ onClick: () => d("cards"),
339
+ children: /* @__PURE__ */ t(_, { size: 16 })
340
+ })]
341
+ })]
342
+ })]
343
+ }),
344
+ /* @__PURE__ */ n("div", {
345
+ className: "relative min-h-0 flex-1 overflow-hidden",
346
+ children: [/* @__PURE__ */ t(L, {
347
+ items: x,
348
+ className: v,
349
+ emptyLabel: r.trim() && !b ? "No matching files" : "This folder is empty",
350
+ showEmptyActions: !r.trim() || b,
351
+ folderId: b ? c : l,
352
+ isBusy: a
353
+ }), u.length > 1 && /* @__PURE__ */ n("div", {
354
+ className: "pointer-events-none absolute bottom-4 left-1/2 z-10 flex -translate-x-1/2 items-center gap-2 rounded-full bg-gray-900 py-1.5 px-4 text-xs text-white shadow-[0_12px_32px_rgba(15,23,42,0.35)]",
355
+ children: [u.length, " selected"]
356
+ })]
357
+ }),
358
+ i && m && /* @__PURE__ */ t("input", {
359
+ ref: h,
360
+ type: "file",
361
+ multiple: !0,
362
+ className: "hidden",
363
+ "aria-label": "Upload files",
364
+ onChange: (e) => {
365
+ e.target.files?.length && (m(Array.from(e.target.files), l), e.target.value = "");
366
+ }
367
+ })
368
+ ]
369
+ });
370
+ }
371
+ function L({ items: e, className: r, emptyLabel: i, showEmptyActions: a, folderId: o, isBusy: s }) {
372
+ let { view: c, canManage: l, onCreateFolder: u, fileInputRef: d } = S();
373
+ return /* @__PURE__ */ n("div", {
374
+ className: "relative h-full overflow-y-auto overscroll-contain",
375
+ children: [s && /* @__PURE__ */ t("div", {
376
+ className: "absolute inset-0 z-20 bg-white/50",
377
+ "aria-busy": "true"
378
+ }), /* @__PURE__ */ t("div", {
379
+ className: r,
380
+ role: "listbox",
381
+ "aria-label": "Folder contents",
382
+ children: e.length === 0 ? /* @__PURE__ */ n("div", {
383
+ className: C("flex min-h-[240px] flex-col items-center justify-center gap-3 p-6 text-center text-[13px] text-gray-500", c === "cards" ? "col-span-full" : ""),
384
+ children: [/* @__PURE__ */ t("p", {
385
+ className: "m-0",
386
+ children: i
387
+ }), a && l && /* @__PURE__ */ n("div", {
388
+ className: "flex flex-wrap justify-center gap-2",
389
+ children: [/* @__PURE__ */ n("button", {
390
+ type: "button",
391
+ className: C("inline-flex cursor-pointer items-center gap-1.5 rounded-lg border-0 bg-gray-900 px-3 py-2 text-[13px] font-semibold text-white hover:bg-gray-700", "transition-colors duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rfm-primary"),
392
+ onClick: () => d.current?.click(),
393
+ children: [/* @__PURE__ */ t(b, { size: 16 }), "Upload files"]
394
+ }), u && /* @__PURE__ */ n("button", {
395
+ type: "button",
396
+ className: C("inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-gray-200 bg-white px-3 py-2 text-[13px] font-semibold text-gray-700 hover:border-gray-300 hover:bg-gray-50", "transition-colors duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rfm-primary"),
397
+ onClick: () => u(o),
398
+ children: [/* @__PURE__ */ t(f, { size: 16 }), "Create folder"]
399
+ })]
400
+ })]
401
+ }) : e.map((e, n) => /* @__PURE__ */ t(P, {
402
+ item: e,
403
+ index: n
404
+ }, e.id))
405
+ })]
406
+ });
407
+ }
408
+ function ae({ label: e, pressed: n, onClick: r, children: i }) {
409
+ return /* @__PURE__ */ t("button", {
410
+ type: "button",
411
+ className: C("inline-flex h-7 w-7 cursor-pointer items-center justify-center rounded-md border-0", n ? "bg-rfm-primary text-white" : "bg-transparent text-gray-500 hover:bg-black/5", T, w),
412
+ "aria-label": e,
413
+ "aria-pressed": n,
414
+ onClick: r,
415
+ children: i
416
+ });
417
+ }
418
+ //#endregion
419
+ //#region src/components/DetailsPane.tsx
420
+ function R() {
421
+ let { selectedNode: e, renderIcon: r, renderPreview: i, renderActions: a } = S();
422
+ if (i) return /* @__PURE__ */ t("aside", {
423
+ className: "flex min-h-0 flex-col overflow-hidden border-l border-black/[0.06] bg-gray-50",
424
+ children: /* @__PURE__ */ t("div", {
425
+ className: "flex min-h-0 flex-1 flex-col overflow-y-auto overscroll-contain p-4",
426
+ children: i(e)
427
+ })
428
+ });
429
+ if (!e) return /* @__PURE__ */ t("aside", {
430
+ className: "flex min-h-0 flex-col overflow-hidden border-l border-black/[0.06] bg-gray-50",
431
+ children: /* @__PURE__ */ n("div", {
432
+ className: "flex h-full flex-col items-center justify-center gap-3 px-2 text-center text-[13px] text-gray-500",
433
+ children: [
434
+ /* @__PURE__ */ t(f, { size: 56 }),
435
+ /* @__PURE__ */ t("p", {
436
+ className: "m-0",
437
+ children: "Select a file or folder to view details"
438
+ }),
439
+ /* @__PURE__ */ t("p", {
440
+ className: "m-0 max-w-[180px] text-[11px] leading-snug text-gray-400",
441
+ children: "↑↓ navigate · Shift range · ⌘/Ctrl toggle · Enter open · Esc clear"
442
+ })
443
+ ]
444
+ })
445
+ });
446
+ let o = e.kind === "folder", s = M(e), c = e.children?.length ?? 0;
447
+ return /* @__PURE__ */ t("aside", {
448
+ className: "flex min-h-0 flex-col overflow-hidden border-l border-black/[0.06] bg-gray-50",
449
+ children: /* @__PURE__ */ n("div", {
450
+ className: "flex min-h-0 flex-1 flex-col overflow-y-auto overscroll-contain p-4",
451
+ children: [/* @__PURE__ */ n("div", {
452
+ className: "relative flex min-h-[220px] flex-1 flex-col items-center justify-center rounded-lg bg-gray-100/80 px-4 py-5",
453
+ children: [r?.(e) ?? t(o ? f : p, { size: 64 }), /* @__PURE__ */ t("span", {
454
+ className: "mt-2 text-xs text-gray-500",
455
+ children: o ? `${c} item${c === 1 ? "" : "s"}` : (s || "file").toUpperCase()
456
+ })]
457
+ }), /* @__PURE__ */ n("div", {
458
+ className: "mt-3",
459
+ children: [
460
+ /* @__PURE__ */ t("h3", {
461
+ className: "m-0 mb-2.5 break-words text-sm font-semibold text-gray-900",
462
+ children: e.name
463
+ }),
464
+ e.path && /* @__PURE__ */ t("p", {
465
+ className: "m-0 -mt-1.5 mb-2.5 break-words text-xs text-gray-500",
466
+ children: e.path
467
+ }),
468
+ /* @__PURE__ */ n("dl", {
469
+ className: "m-0",
470
+ children: [/* @__PURE__ */ n("div", {
471
+ className: "flex justify-between gap-3 border-b border-gray-200/70 py-2 text-xs",
472
+ children: [/* @__PURE__ */ t("dt", {
473
+ className: "text-gray-500",
474
+ children: "Type"
475
+ }), /* @__PURE__ */ t("dd", {
476
+ className: "m-0 font-medium text-gray-900",
477
+ children: o ? "Folder" : (s || "file").toUpperCase()
478
+ })]
479
+ }), o && /* @__PURE__ */ n("div", {
480
+ className: "flex justify-between gap-3 py-2 text-xs",
481
+ children: [/* @__PURE__ */ t("dt", {
482
+ className: "text-gray-500",
483
+ children: "Items"
484
+ }), /* @__PURE__ */ t("dd", {
485
+ className: "m-0 font-medium text-gray-900",
486
+ children: c
487
+ })]
488
+ })]
489
+ }),
490
+ a && /* @__PURE__ */ t("div", {
491
+ className: C("mt-3", "transition-colors duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rfm-primary"),
492
+ children: a(e)
493
+ })
494
+ ]
495
+ })]
496
+ })
497
+ });
498
+ }
499
+ //#endregion
500
+ //#region src/components/Sidebar.tsx
501
+ function z() {
502
+ let { nodes: e, viewFolderId: r, dropTargetId: i, canManage: a, rootLabel: o, openFolder: s, collapseAll: c, folderDropHandlers: l, onCreateFolder: u } = S();
503
+ return /* @__PURE__ */ n("aside", {
504
+ className: "flex min-h-0 flex-col gap-2 overflow-hidden border-r border-black/[0.06] bg-gray-100/80 p-3",
505
+ children: [
506
+ a && u && /* @__PURE__ */ t("button", {
507
+ type: "button",
508
+ className: C("flex h-9 w-full shrink-0 cursor-pointer items-center justify-center gap-1.5 rounded-lg border-0 bg-rfm-primary text-sm font-semibold text-white hover:brightness-95", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rfm-primary"),
509
+ onClick: () => u(r),
510
+ children: "New folder"
511
+ }),
512
+ /* @__PURE__ */ t("div", {
513
+ className: "flex shrink-0 justify-end",
514
+ children: /* @__PURE__ */ n("button", {
515
+ type: "button",
516
+ className: C("inline-flex cursor-pointer items-center gap-1 rounded-md border-0 bg-transparent px-1.5 py-1 text-[11px] font-semibold text-gray-500 hover:bg-black/5 hover:text-gray-900", T, w),
517
+ onClick: c,
518
+ children: [/* @__PURE__ */ t(v, { size: 14 }), "Collapse all"]
519
+ })
520
+ }),
521
+ /* @__PURE__ */ n("div", {
522
+ className: "min-h-0 flex-1 overflow-y-auto overscroll-contain",
523
+ children: [/* @__PURE__ */ n("button", {
524
+ type: "button",
525
+ className: C("flex w-full cursor-pointer items-center gap-1 rounded-md border-0 bg-transparent py-1 text-left text-[13px]", r === null ? "bg-rfm-hover font-semibold text-rfm-primary" : "text-gray-900 hover:bg-black/[0.04]", i === "root" ? E : "", T, w),
526
+ style: { paddingLeft: 8 },
527
+ onClick: () => s(null),
528
+ ...l("root"),
529
+ children: [
530
+ /* @__PURE__ */ t("span", { className: "invisible inline-block h-[18px] w-[18px] shrink-0" }),
531
+ /* @__PURE__ */ t(m, {
532
+ className: "h-4 w-4 shrink-0",
533
+ size: 16
534
+ }),
535
+ /* @__PURE__ */ t("span", {
536
+ className: "min-w-0 flex-1 truncate",
537
+ children: o
538
+ })
539
+ ]
540
+ }), /* @__PURE__ */ t("div", {
541
+ role: "tree",
542
+ children: /* @__PURE__ */ t(ie, { folders: e })
543
+ })]
544
+ })
545
+ ]
546
+ });
547
+ }
548
+ //#endregion
549
+ //#region src/dropTarget.ts
550
+ function B(e) {
551
+ let t = e.relatedTarget;
552
+ return !(t && e.currentTarget.contains(t));
553
+ }
554
+ function oe({ canManage: e, targetId: t, setDropTargetId: n, onDropOnFolder: r, onHoverExpand: i, clearExpandTimer: a }) {
555
+ let o = t === "root" ? null : t;
556
+ return {
557
+ onDragEnter: (r) => {
558
+ e && B(r) && (r.preventDefault(), n(t), i?.());
559
+ },
560
+ onDragOver: (r) => {
561
+ e && (r.preventDefault(), r.dataTransfer.dropEffect = "move", n(t));
562
+ },
563
+ onDragLeave: (e) => {
564
+ B(e) && (n((e) => e === t ? null : e), a?.());
565
+ },
566
+ onDrop: (e) => {
567
+ r(e, o);
568
+ }
569
+ };
570
+ }
571
+ //#endregion
572
+ //#region src/selection.ts
573
+ function se(e, t, n) {
574
+ let r = Math.min(t, n), i = Math.max(t, n);
575
+ return e.slice(r, i + 1).map((e) => e.id);
576
+ }
577
+ //#endregion
578
+ //#region src/useFileManagerController.ts
579
+ var ce = "application/x-file-manager-item";
580
+ function V(e, t, n) {
581
+ let [r, a] = u(t), o = e !== void 0;
582
+ return [o ? e : r, i((e) => {
583
+ o || a(e), n?.(e);
584
+ }, [o, n])];
585
+ }
586
+ function le(e) {
587
+ let { nodes: t, canManage: n = !0, rootLabel: r = "My files", showDetails: a = !0, springLoadDelay: d = 500, isBusy: f = !1, onMove: p, onOpenFile: m, onOpenFolder: h, onUpload: g, onCreateFolder: _, onDelete: v, renderIcon: y, renderPreview: b, renderActions: x } = e, [S, C] = V(e.folderId, e.defaultFolderId ?? null, e.onFolderChange), [w, T] = V(e.selectedIds, e.defaultSelectedIds ?? [], e.onSelectionChange), [E, ee] = V(e.view, e.defaultView ?? "list", e.onViewChange), [A, j] = V(e.searchQuery, e.defaultSearchQuery ?? "", e.onSearchChange), M = o(A), [N, P] = u(() => /* @__PURE__ */ new Set()), [ie, F] = u(null), [I, L] = u(-1), [ae, R] = u(null), [z, B] = u(void 0), le = l(null), H = l(null), U = l([]), W = l(!1), G = l(0), K = l(null), q = l(null), J = l(null), Y = l(null), X = l(!1);
588
+ U.current = w;
589
+ let ue = z === void 0 ? S : z, Z = c(() => M.trim() && z === void 0 ? re(t, M, r) : te(t, S), [
590
+ M,
591
+ S,
592
+ t,
593
+ r,
594
+ z
595
+ ]), de = c(() => z === void 0 ? Z : te(t, z), [
596
+ Z,
597
+ t,
598
+ z
599
+ ]), fe = c(() => ne(t, ue), [t, ue]);
600
+ s(() => {
601
+ let e = fe.map((e) => e.id);
602
+ e.length && P((t) => {
603
+ let n = new Set(t), r = !1;
604
+ for (let t of e) n.has(t) || (n.add(t), r = !0);
605
+ return r ? n : t;
606
+ });
607
+ }, [fe]), s(() => {
608
+ L(-1), G.current = 0;
609
+ }, [
610
+ S,
611
+ M,
612
+ E
613
+ ]), s(() => () => {
614
+ K.current && clearTimeout(K.current), J.current && clearTimeout(J.current);
615
+ }, []);
616
+ let Q = i(() => {
617
+ j("");
618
+ }, [j]), pe = i((e) => {
619
+ C(e), F(null), T([]), Q(), h?.(e);
620
+ }, [
621
+ Q,
622
+ h,
623
+ C,
624
+ T
625
+ ]), $ = i(() => {
626
+ K.current &&= (clearTimeout(K.current), null), q.current = null, J.current &&= (clearTimeout(J.current), null), Y.current = null;
627
+ }, []), me = i((e) => {
628
+ N.has(e) || (H.current?.kind !== "folder" || H.current.id !== e) && q.current !== e && (K.current && clearTimeout(K.current), q.current = e, K.current = setTimeout(() => {
629
+ q.current = null, P((t) => {
630
+ if (t.has(e)) return t;
631
+ let n = new Set(t);
632
+ return n.add(e), n;
633
+ });
634
+ }, d));
635
+ }, [N, d]), he = i((e) => {
636
+ if (!H.current || (z === void 0 ? S : z) === e) return;
637
+ if (e !== null && H.current.kind === "folder") {
638
+ if (H.current.id === e) return;
639
+ let n = D(t, H.current.id);
640
+ if (n && O(n, e)) return;
641
+ }
642
+ let n = e === null ? "root" : `folder-${e}`;
643
+ Y.current !== n && (J.current && clearTimeout(J.current), Y.current = n, J.current = setTimeout(() => {
644
+ Y.current = null, B(e), R(null);
645
+ }, d));
646
+ }, [
647
+ S,
648
+ t,
649
+ z,
650
+ d
651
+ ]), ge = i((e, t) => {
652
+ n && (W.current = !0, X.current = !1, t.dataTransfer.effectAllowed = "move", t.dataTransfer.setData(ce, JSON.stringify({
653
+ id: e.id,
654
+ kind: e.kind
655
+ })), t.dataTransfer.setData("text/plain", `${e.kind}:${e.id}`), H.current = {
656
+ id: e.id,
657
+ kind: e.kind
658
+ }, U.current.includes(e.id) || (T([e.id]), F(e)));
659
+ }, [n, T]), _e = i(async (e, t) => {
660
+ if (e.preventDefault(), e.stopPropagation(), X.current = !0, R(null), $(), B(void 0), C(t), e.dataTransfer.files.length) {
661
+ await g?.(Array.from(e.dataTransfer.files), t);
662
+ return;
663
+ }
664
+ let r = H.current;
665
+ if (H.current = null, !r || !n) return;
666
+ let i = U.current, a = i.length > 1 && i.includes(r.id) ? i : [r.id];
667
+ await p?.(a, t), T([]), F(null);
668
+ }, [
669
+ n,
670
+ $,
671
+ p,
672
+ g,
673
+ C,
674
+ T
675
+ ]), ve = i(() => {
676
+ $(), R(null), X.current || B(void 0), X.current = !1, H.current = null;
677
+ }, [$]), ye = i((e) => {
678
+ let r = e === "root" ? null : e, i = e === "root" ? null : D(t, e);
679
+ return oe({
680
+ canManage: n,
681
+ targetId: e,
682
+ setDropTargetId: R,
683
+ onDropOnFolder: _e,
684
+ onHoverExpand: () => {
685
+ i && k(i) && me(e), he(r);
686
+ },
687
+ clearExpandTimer: $
688
+ });
689
+ }, [
690
+ n,
691
+ $,
692
+ t,
693
+ _e,
694
+ me,
695
+ he
696
+ ]), be = i((e, t) => {
697
+ e.stopPropagation(), P((e) => {
698
+ let n = new Set(e);
699
+ return n.has(t) ? n.delete(t) : n.add(t), n;
700
+ });
701
+ }, []), xe = i(() => {
702
+ P(/* @__PURE__ */ new Set());
703
+ }, []), Se = i((e, t) => {
704
+ if (W.current) {
705
+ W.current = !1;
706
+ return;
707
+ }
708
+ let n = Z.findIndex((t) => t.id === e.id);
709
+ if (t?.shiftKey && n >= 0) {
710
+ let t = se(Z, G.current, n);
711
+ L(n), T(t), F(e);
712
+ return;
713
+ }
714
+ if (t?.metaKey || t?.ctrlKey) {
715
+ n >= 0 && (L(n), G.current = n), T(U.current.includes(e.id) ? U.current.filter((t) => t !== e.id) : [...U.current, e.id]), F(e);
716
+ return;
717
+ }
718
+ n >= 0 && (L(n), G.current = n), T([e.id]), F(e);
719
+ }, [Z, T]), Ce = i((e) => {
720
+ e.kind === "folder" ? pe(e.id) : m?.(e.id);
721
+ }, [m, pe]);
722
+ return {
723
+ nodes: t,
724
+ folderId: S,
725
+ viewFolderId: ue,
726
+ expandedIds: N,
727
+ dropTargetId: ae,
728
+ selectedIds: w,
729
+ selectedNode: ie,
730
+ focusedIndex: I,
731
+ view: E,
732
+ searchQuery: A,
733
+ canManage: n,
734
+ rootLabel: r,
735
+ isBusy: f,
736
+ items: Z,
737
+ viewItems: de,
738
+ breadcrumbs: fe,
739
+ showDetails: a,
740
+ fileInputRef: le,
741
+ folderDropHandlers: ye,
742
+ openFolder: pe,
743
+ toggleExpanded: be,
744
+ collapseAll: xe,
745
+ selectItem: Se,
746
+ activateItem: Ce,
747
+ onDragStart: ge,
748
+ onInternalDragEnd: ve,
749
+ onDropOnFolder: _e,
750
+ setView: ee,
751
+ setSearchQuery: j,
752
+ handleKeyDown: i((e) => {
753
+ let t = e.target;
754
+ if (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable) {
755
+ e.key === "Escape" && Q();
756
+ return;
757
+ }
758
+ let r = z === void 0 ? Z : de;
759
+ if (!r.length) {
760
+ e.key === "Escape" && A && Q();
761
+ return;
762
+ }
763
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
764
+ e.preventDefault();
765
+ let t = e.key === "ArrowDown" ? 1 : -1, n = Math.min(Math.max((I < 0 ? t > 0 ? -1 : 0 : I) + t, 0), r.length - 1);
766
+ L(n), e.shiftKey || (G.current = n);
767
+ let i = r[n];
768
+ if (!i) return;
769
+ e.shiftKey && T(se(r, G.current, n)), F(i);
770
+ return;
771
+ }
772
+ if (e.key === "Enter") {
773
+ e.preventDefault();
774
+ let t = r[I];
775
+ t && Ce(t);
776
+ return;
777
+ }
778
+ if (e.key === " ") {
779
+ e.preventDefault();
780
+ let t = r[I];
781
+ t && Se(t);
782
+ return;
783
+ }
784
+ if (e.key === "Escape") {
785
+ if (A) {
786
+ Q();
787
+ return;
788
+ }
789
+ F(null), T([]);
790
+ return;
791
+ }
792
+ if ((e.key === "Delete" || e.key === "Backspace") && n) {
793
+ let t = w.length > 0 ? w : r[I] ? [r[I].id] : [];
794
+ if (!t.length) return;
795
+ e.preventDefault(), v?.(t);
796
+ }
797
+ }, [
798
+ Ce,
799
+ n,
800
+ Q,
801
+ I,
802
+ Z,
803
+ v,
804
+ A,
805
+ Se,
806
+ w,
807
+ T,
808
+ z,
809
+ de
810
+ ]),
811
+ renderIcon: y,
812
+ renderPreview: b,
813
+ renderActions: x,
814
+ onCreateFolder: _,
815
+ onUpload: g
816
+ };
817
+ }
818
+ //#endregion
819
+ //#region src/FileManager.tsx
820
+ function H(e) {
821
+ let r = le(e), i = r.showDetails ? "grid-cols-[216px_minmax(0,1fr)_280px]" : "grid-cols-[216px_minmax(0,1fr)]";
822
+ return /* @__PURE__ */ t(x.Provider, {
823
+ value: r,
824
+ children: /* @__PURE__ */ n("div", {
825
+ className: C("rfm-root relative grid h-full min-h-0 overflow-hidden outline-none", i, e.className),
826
+ tabIndex: 0,
827
+ "aria-label": "File manager",
828
+ onKeyDown: r.handleKeyDown,
829
+ onDragEnd: r.onInternalDragEnd,
830
+ children: [
831
+ /* @__PURE__ */ t(z, {}),
832
+ /* @__PURE__ */ t(I, {}),
833
+ r.showDetails && /* @__PURE__ */ t(R, {})
834
+ ]
835
+ })
836
+ });
837
+ }
838
+ //#endregion
839
+ export { H as FileManager, O as folderContainsId, oe as folderDropTargetHandlers, k as folderHasChildFolders, ne as getBreadcrumbs, M as getExtension, A as getFolderContents, D as getNodeById, te as listFolder, N as moveNodes, re as searchNodes };