dishui 0.0.64 → 0.0.65
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/components/Badge/index.js +12 -9
- package/dist/components/Badge/index.js.map +1 -1
- package/dist/components/Button/index.js +43 -40
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Card/index.d.ts +11 -0
- package/dist/components/Card/index.js +62 -37
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/Chart/Chart.js.map +1 -1
- package/dist/components/Checkbox/index.js +32 -30
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Demo/index.js.map +1 -1
- package/dist/components/EmptyState/index.d.ts +4 -1
- package/dist/components/EmptyState/index.js +3 -3
- package/dist/components/EmptyState/index.js.map +1 -1
- package/dist/components/FileUploader/DropZone.js.map +1 -1
- package/dist/components/FileUploader/FileItem.js.map +1 -1
- package/dist/components/FileUploader/FileUploader.js.map +1 -1
- package/dist/components/FileUploader/UploadQueue.js.map +1 -1
- package/dist/components/Input/index.js +30 -30
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/Label/index.js +41 -40
- package/dist/components/Label/index.js.map +1 -1
- package/dist/components/List/index.js +47 -32
- package/dist/components/List/index.js.map +1 -1
- package/dist/components/Markdown/Markdown.js +61 -57
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Markdown/markdownComponents.js +49 -49
- package/dist/components/Markdown/markdownComponents.js.map +1 -1
- package/dist/components/Modal/index.d.ts +7 -3
- package/dist/components/Modal/index.js +77 -65
- package/dist/components/Modal/index.js.map +1 -1
- package/dist/components/Page/index.d.ts +58 -0
- package/dist/components/Page/index.js +74 -0
- package/dist/components/Page/index.js.map +1 -0
- package/dist/components/PageHeader/index.js.map +1 -1
- package/dist/components/Select/index.js +0 -3
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/SidebarToggleButton/index.js.map +1 -1
- package/dist/components/StatCard/index.d.ts +3 -1
- package/dist/components/StatCard/index.js +39 -11
- package/dist/components/StatCard/index.js.map +1 -1
- package/dist/components/Table/index.js +103 -85
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/Tabs/index.d.ts +19 -5
- package/dist/components/Tabs/index.js +32 -13
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tree/Tree.js.map +1 -1
- package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
- package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/CodeEditor.js +141 -134
- package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +81 -78
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/themes.js +59 -59
- package/dist/components/pro/CodeEditor/themes.js.map +1 -1
- package/dist/components/pro/DataTable/DataTable.js +49 -48
- package/dist/components/pro/DataTable/DataTable.js.map +1 -1
- package/dist/components/pro/DataTable/Filters.js +42 -42
- package/dist/components/pro/DataTable/Filters.js.map +1 -1
- package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
- package/dist/components/pro/DataTable/PivotView.js +35 -32
- package/dist/components/pro/DataTable/PivotView.js.map +1 -1
- package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
- package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
- package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
- package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
- package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
- package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
- package/dist/components/pro/DataTable/tanstack-table.js +37 -37
- package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
- package/dist/components/pro/FileExplorer/Breadcrumb.js +53 -53
- package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
- package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileIcon.js +22 -22
- package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
- package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
- package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
- package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
- package/dist/components/pro/Flow/Flow.js +496 -494
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/FlowCanvas.js +916 -917
- package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
- package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
- package/dist/components/pro/Flow/edges/EdgeRenderer.js +59 -59
- package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLayoutActions.js +9 -11
- package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
- package/dist/components/pro/Flow/lines/FreehandTool.js +9 -9
- package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
- package/dist/components/pro/Flow/lines/LineRenderer.js +5 -5
- package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/DataNodeView.js +113 -93
- package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
- package/dist/components/pro/Flow/nodes/Model3DView.js +1 -1
- package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/NodeRenderer.js +118 -118
- package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
- package/dist/components/pro/Flow/nodes/shapes.js +1 -3
- package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
- package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
- package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
- package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
- package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowToolbar.js +97 -97
- package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
- package/dist/components/pro/Flow/panels/InspectorPanel.js +57 -57
- package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/OutlinePanel.js +26 -22
- package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/PresentationMode.js +18 -16
- package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
- package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
- package/dist/components/pro/Flow/panels/ShapePalette.js +109 -104
- package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
- package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
- package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
- package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
- package/dist/contexts/AppContext.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/hooks/useTableColumns.js +7 -8
- package/dist/hooks/useTableColumns.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +227 -221
- package/dist/layouts/MainLayout.js +22 -22
- package/dist/layouts/MainLayout.js.map +1 -1
- package/dist/layouts/Navbar.js.map +1 -1
- package/dist/layouts/Sidebar.js +94 -73
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/layouts/headbar/Headbar.js.map +1 -1
- package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
- package/dist/layouts/headbar/HeadbarThemeSwitcher.js +11 -11
- package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
- package/dist/utils/i18n.js +10 -10
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/menu.js.map +1 -1
- package/dist/utils/routerBuilder.js +17 -15
- package/dist/utils/routerBuilder.js.map +1 -1
- package/dist/utils/themes.js.map +1 -1
- package/package.json +7 -7
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useClickOutside as L } from "../../../hooks/useClickOutside.js";
|
|
2
2
|
import S from "../../Tree/Tree.js";
|
|
3
|
-
import B, { useCallback as
|
|
3
|
+
import B, { useCallback as y, useEffect as j, useRef as R, useState as k } from "react";
|
|
4
4
|
import { jsx as e, jsxs as w } from "react/jsx-runtime";
|
|
5
|
-
var
|
|
5
|
+
var z = { root: "Root" }, D = () => /* @__PURE__ */ e("svg", {
|
|
6
6
|
xmlns: "http://www.w3.org/2000/svg",
|
|
7
7
|
className: "h-4 w-4",
|
|
8
8
|
fill: "none",
|
|
@@ -14,7 +14,7 @@ var D = { root: "Root" }, H = () => /* @__PURE__ */ e("svg", {
|
|
|
14
14
|
strokeLinejoin: "round",
|
|
15
15
|
d: "M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
|
16
16
|
})
|
|
17
|
-
}),
|
|
17
|
+
}), C = () => /* @__PURE__ */ e("svg", {
|
|
18
18
|
xmlns: "http://www.w3.org/2000/svg",
|
|
19
19
|
className: "h-3 w-3",
|
|
20
20
|
fill: "none",
|
|
@@ -26,13 +26,13 @@ var D = { root: "Root" }, H = () => /* @__PURE__ */ e("svg", {
|
|
|
26
26
|
strokeLinejoin: "round",
|
|
27
27
|
d: "M9 5l7 7-7 7"
|
|
28
28
|
})
|
|
29
|
-
}),
|
|
29
|
+
}), H = () => /* @__PURE__ */ e("svg", {
|
|
30
30
|
xmlns: "http://www.w3.org/2000/svg",
|
|
31
31
|
className: "h-4 w-4 text-blue-500 opacity-80",
|
|
32
32
|
viewBox: "0 0 20 20",
|
|
33
33
|
fill: "currentColor",
|
|
34
34
|
children: /* @__PURE__ */ e("path", { d: "M2 6a2 2 0 012-2h4l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" })
|
|
35
|
-
}),
|
|
35
|
+
}), M = () => /* @__PURE__ */ e("svg", {
|
|
36
36
|
xmlns: "http://www.w3.org/2000/svg",
|
|
37
37
|
className: "h-4 w-4 text-gray-500 opacity-80",
|
|
38
38
|
viewBox: "0 0 20 20",
|
|
@@ -42,13 +42,13 @@ var D = { root: "Root" }, H = () => /* @__PURE__ */ e("svg", {
|
|
|
42
42
|
d: "M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z",
|
|
43
43
|
clipRule: "evenodd"
|
|
44
44
|
})
|
|
45
|
-
}),
|
|
46
|
-
const [t,
|
|
45
|
+
}), P = ({ path: i, adapter: r, onNavigate: l }) => {
|
|
46
|
+
const [t, c] = k([]), [d, o] = k(!1), s = y(async (a) => {
|
|
47
47
|
try {
|
|
48
48
|
return (await r.list(a)).sort((n, m) => n.type !== m.type ? n.type === "folder" ? -1 : 1 : String(n.name).localeCompare(String(m.name))).map((n) => ({
|
|
49
49
|
id: n.path,
|
|
50
50
|
label: n.name,
|
|
51
|
-
icon: n.type === "folder" ? /* @__PURE__ */ e(
|
|
51
|
+
icon: n.type === "folder" ? /* @__PURE__ */ e(H, {}) : /* @__PURE__ */ e(M, {}),
|
|
52
52
|
meta: { type: n.type },
|
|
53
53
|
children: n.type === "folder" ? [{
|
|
54
54
|
id: `${n.path}/_dummy`,
|
|
@@ -61,41 +61,41 @@ var D = { root: "Root" }, H = () => /* @__PURE__ */ e("svg", {
|
|
|
61
61
|
}, [r]);
|
|
62
62
|
j(() => {
|
|
63
63
|
let a = !0;
|
|
64
|
-
return o(!0),
|
|
65
|
-
a && (
|
|
64
|
+
return o(!0), s(i).then((n) => {
|
|
65
|
+
a && (c(n), o(!1));
|
|
66
66
|
}), () => {
|
|
67
67
|
a = !1;
|
|
68
68
|
};
|
|
69
|
-
}, [
|
|
70
|
-
const
|
|
69
|
+
}, [i, s]);
|
|
70
|
+
const v = y(async (a, n) => {
|
|
71
71
|
if (!n) return;
|
|
72
|
-
const m = String(a),
|
|
73
|
-
for (const
|
|
74
|
-
if (
|
|
75
|
-
if (
|
|
76
|
-
const x =
|
|
72
|
+
const m = String(a), N = (g, f) => {
|
|
73
|
+
for (const h of g) {
|
|
74
|
+
if (h.id === f) return h;
|
|
75
|
+
if (h.children) {
|
|
76
|
+
const x = N(h.children, f);
|
|
77
77
|
if (x) return x;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
return null;
|
|
81
|
-
},
|
|
82
|
-
if (
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
const
|
|
81
|
+
}, b = N(t, m);
|
|
82
|
+
if (b && b.children?.length === 1 && String(b.children[0].id).endsWith("_dummy")) {
|
|
83
|
+
const g = await s(m);
|
|
84
|
+
c((f) => {
|
|
85
|
+
const h = (x) => x.map((p) => p.id === m ? {
|
|
86
86
|
...p,
|
|
87
|
-
children:
|
|
87
|
+
children: g
|
|
88
88
|
} : p.children ? {
|
|
89
89
|
...p,
|
|
90
|
-
children:
|
|
90
|
+
children: h(p.children)
|
|
91
91
|
} : p);
|
|
92
|
-
return
|
|
92
|
+
return h(f);
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
|
-
}, [t,
|
|
95
|
+
}, [t, s]), u = y((a) => {
|
|
96
96
|
String(a.id).endsWith("_dummy") || a.meta?.type !== "file" && l(String(a.id));
|
|
97
97
|
}, [l]);
|
|
98
|
-
return
|
|
98
|
+
return d ? /* @__PURE__ */ e("div", {
|
|
99
99
|
className: "px-4 py-3 w-48 text-center text-xs opacity-50",
|
|
100
100
|
children: "Loading..."
|
|
101
101
|
}) : t.length === 0 ? /* @__PURE__ */ e("div", {
|
|
@@ -105,8 +105,8 @@ var D = { root: "Root" }, H = () => /* @__PURE__ */ e("svg", {
|
|
|
105
105
|
className: "p-1 w-64 max-h-[300px] overflow-y-auto sm:min-w-[200px] max-w-[80vw]",
|
|
106
106
|
children: /* @__PURE__ */ e(S, {
|
|
107
107
|
data: t,
|
|
108
|
-
onNodeClick:
|
|
109
|
-
onNodeToggle:
|
|
108
|
+
onNodeClick: u,
|
|
109
|
+
onNodeToggle: v,
|
|
110
110
|
showSearch: !1,
|
|
111
111
|
showExpandAll: !1,
|
|
112
112
|
showLine: !1,
|
|
@@ -116,35 +116,35 @@ var D = { root: "Root" }, H = () => /* @__PURE__ */ e("svg", {
|
|
|
116
116
|
indent: 12
|
|
117
117
|
})
|
|
118
118
|
});
|
|
119
|
-
}, T = ({ path:
|
|
120
|
-
const [t,
|
|
121
|
-
return L(
|
|
119
|
+
}, T = ({ path: i, adapter: r, onNavigate: l }) => {
|
|
120
|
+
const [t, c] = k(!1), d = R(null);
|
|
121
|
+
return L(d, () => c(!1), t), /* @__PURE__ */ w("div", {
|
|
122
122
|
className: "relative flex items-center",
|
|
123
|
-
ref:
|
|
123
|
+
ref: d,
|
|
124
124
|
children: [r ? /* @__PURE__ */ e("button", {
|
|
125
125
|
className: `btn btn-ghost btn-xs px-0.5 mx-0.5 min-h-0 h-5 rounded hover:bg-base-200 transition-colors ${t ? "bg-base-200" : "opacity-50"}`,
|
|
126
126
|
onClick: (o) => {
|
|
127
|
-
o.stopPropagation(),
|
|
127
|
+
o.stopPropagation(), c(!t);
|
|
128
128
|
},
|
|
129
|
-
children: /* @__PURE__ */ e(
|
|
129
|
+
children: /* @__PURE__ */ e(C, {})
|
|
130
130
|
}) : /* @__PURE__ */ e("span", {
|
|
131
131
|
className: "opacity-40 mx-1",
|
|
132
|
-
children: /* @__PURE__ */ e(
|
|
132
|
+
children: /* @__PURE__ */ e(C, {})
|
|
133
133
|
}), t && r && /* @__PURE__ */ e("div", {
|
|
134
134
|
className: "absolute top-full left-1/2 -translate-x-1/2 mt-1 bg-base-100 shadow-2xl border border-base-200 rounded-xl z-[9999]",
|
|
135
135
|
onClick: (o) => o.stopPropagation(),
|
|
136
|
-
children: /* @__PURE__ */ e(
|
|
137
|
-
path:
|
|
136
|
+
children: /* @__PURE__ */ e(P, {
|
|
137
|
+
path: i,
|
|
138
138
|
adapter: r,
|
|
139
139
|
onNavigate: (o) => {
|
|
140
|
-
l(o),
|
|
140
|
+
l(o), c(!1);
|
|
141
141
|
}
|
|
142
142
|
})
|
|
143
143
|
})]
|
|
144
144
|
});
|
|
145
145
|
};
|
|
146
|
-
function I(
|
|
147
|
-
const r =
|
|
146
|
+
function I(i) {
|
|
147
|
+
const r = i.split("/").filter(Boolean), l = [];
|
|
148
148
|
for (let t = 0; t < r.length; t++) l.push({
|
|
149
149
|
label: r[t],
|
|
150
150
|
path: "/" + r.slice(0, t + 1).join("/"),
|
|
@@ -152,29 +152,29 @@ function I(s) {
|
|
|
152
152
|
});
|
|
153
153
|
return l;
|
|
154
154
|
}
|
|
155
|
-
var F = ({ path:
|
|
156
|
-
const
|
|
157
|
-
...
|
|
155
|
+
var F = ({ path: i, labels: r, adapter: l, onNavigate: t }) => {
|
|
156
|
+
const c = {
|
|
157
|
+
...z,
|
|
158
158
|
...r
|
|
159
|
-
},
|
|
159
|
+
}, d = I(i), o = d.length === 0;
|
|
160
160
|
return /* @__PURE__ */ w("nav", {
|
|
161
161
|
className: "flex items-center text-sm overflow-x-visible py-2 px-1 gap-0.5 min-h-[36px]",
|
|
162
162
|
children: [/* @__PURE__ */ w("button", {
|
|
163
|
-
className: `btn btn-ghost btn-xs gap-1 flex-shrink-0 ${
|
|
163
|
+
className: `btn btn-ghost btn-xs gap-1 flex-shrink-0 ${o ? "font-semibold" : ""}`,
|
|
164
164
|
onClick: () => t("/"),
|
|
165
|
-
children: [/* @__PURE__ */ e(
|
|
166
|
-
}),
|
|
167
|
-
const u =
|
|
165
|
+
children: [/* @__PURE__ */ e(D, {}), c.root]
|
|
166
|
+
}), d.map((s, v) => {
|
|
167
|
+
const u = v === d.length - 1;
|
|
168
168
|
return /* @__PURE__ */ w(B.Fragment, { children: [/* @__PURE__ */ e(T, {
|
|
169
|
-
path:
|
|
169
|
+
path: s.basePath,
|
|
170
170
|
adapter: l,
|
|
171
171
|
onNavigate: t
|
|
172
172
|
}), /* @__PURE__ */ e("button", {
|
|
173
173
|
className: `btn btn-ghost btn-xs flex-shrink-0 truncate max-w-[160px] ${u ? "font-semibold" : ""}`,
|
|
174
|
-
onClick: () => t(
|
|
174
|
+
onClick: () => t(s.path),
|
|
175
175
|
disabled: u,
|
|
176
|
-
children:
|
|
177
|
-
})] },
|
|
176
|
+
children: s.label
|
|
177
|
+
})] }, s.path);
|
|
178
178
|
})]
|
|
179
179
|
});
|
|
180
180
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Breadcrumb.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/Breadcrumb.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { BreadcrumbProps } from './types';\nimport { useClickOutside } from '../../../hooks/useClickOutside';\nimport { Tree, TreeNode } from '../../Tree';\n\nconst defaultLabels = {\n root: 'Root',\n};\n\nconst HomeIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6\" />\n </svg>\n);\n\nconst ChevronIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n);\n\nconst FolderIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4 text-blue-500 opacity-80\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M2 6a2 2 0 012-2h4l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6z\" />\n </svg>\n);\n\nconst DocumentIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4 text-gray-500 opacity-80\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z\" clipRule=\"evenodd\" />\n </svg>\n);\n\nconst BreadcrumbDropTree: React.FC<{\n path: string;\n adapter: any;\n onNavigate: (path: string) => void;\n}> = ({ path, adapter, onNavigate }) => {\n const [treeData, setTreeData] = useState<TreeNode[]>([]);\n const [loading, setLoading] = useState(false);\n\n const loadPath = useCallback(async (dirPath: string): Promise<TreeNode[]> => {\n try {\n const entries = await adapter.list(dirPath);\n return entries\n .sort((a: any, b: any) => {\n if (a.type !== b.type) return a.type === 'folder' ? -1 : 1;\n return String(a.name).localeCompare(String(b.name));\n })\n .map((e: any) => ({\n id: e.path,\n label: e.name,\n icon: e.type === 'folder' ? <FolderIcon /> : <DocumentIcon />,\n meta: { type: e.type },\n children: e.type === 'folder' ? [{ id: `${e.path}/_dummy`, label: 'Loading...' }] : undefined\n }));\n } catch (e) {\n return [];\n }\n }, [adapter]);\n\n useEffect(() => {\n let mounted = true;\n setLoading(true);\n loadPath(path).then(nodes => {\n if (mounted) {\n setTreeData(nodes);\n setLoading(false);\n }\n });\n return () => { mounted = false; };\n }, [path, loadPath]);\n\n const handleToggle = useCallback(async (nodeId: string | number, expanded: boolean) => {\n if (!expanded) return;\n const idStr = String(nodeId);\n\n const findNode = (nodes: TreeNode[], targetId: string): TreeNode | null => {\n for (const n of nodes) {\n if (n.id === targetId) return n;\n if (n.children) {\n const found = findNode(n.children, targetId);\n if (found) return found;\n }\n }\n return null;\n };\n\n const node = findNode(treeData, idStr);\n if (node && node.children?.length === 1 && String(node.children[0].id).endsWith('_dummy')) {\n const childrenNodes = await loadPath(idStr);\n setTreeData(prev => {\n const updateNodes = (nodes: TreeNode[]): TreeNode[] => {\n return nodes.map(n => {\n if (n.id === idStr) {\n return { ...n, children: childrenNodes };\n }\n if (n.children) return { ...n, children: updateNodes(n.children) };\n return n;\n });\n };\n return updateNodes(prev);\n });\n }\n }, [treeData, loadPath]);\n\n const handleClick = useCallback((node: TreeNode) => {\n if (String(node.id).endsWith('_dummy')) return;\n if (node.meta?.type === 'file') return;\n onNavigate(String(node.id));\n }, [onNavigate]);\n\n if (loading) return <div className=\"px-4 py-3 w-48 text-center text-xs opacity-50\">Loading...</div>;\n if (treeData.length === 0) return <div className=\"px-4 py-3 w-48 text-center text-xs opacity-50\">Empty Folder</div>;\n\n return (\n <div className=\"p-1 w-64 max-h-[300px] overflow-y-auto sm:min-w-[200px] max-w-[80vw]\">\n <Tree\n data={treeData}\n onNodeClick={handleClick}\n onNodeToggle={handleToggle}\n showSearch={false}\n showExpandAll={false}\n showLine={false}\n showIcon={true}\n showCount={false}\n className=\"!bg-transparent !border-none !p-1 shadow-none overflow-visible\"\n indent={12}\n />\n </div>\n );\n};\n\nconst ChevronDrop: React.FC<{\n path: string;\n adapter?: any;\n onNavigate: (p: string) => void;\n}> = ({ path, adapter, onNavigate }) => {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useClickOutside(ref, () => setOpen(false), open);\n\n return (\n <div className=\"relative flex items-center\" ref={ref}>\n {adapter ? (\n <button\n className={`btn btn-ghost btn-xs px-0.5 mx-0.5 min-h-0 h-5 rounded hover:bg-base-200 transition-colors ${open ? 'bg-base-200' : 'opacity-50'}`}\n onClick={(e) => {\n e.stopPropagation();\n setOpen(!open);\n }}\n >\n <ChevronIcon />\n </button>\n ) : (\n <span className=\"opacity-40 mx-1\"><ChevronIcon /></span>\n )}\n\n {open && adapter && (\n <div\n className=\"absolute top-full left-1/2 -translate-x-1/2 mt-1 bg-base-100 shadow-2xl border border-base-200 rounded-xl z-[9999]\"\n onClick={(e) => e.stopPropagation()}\n >\n <BreadcrumbDropTree\n path={path}\n adapter={adapter}\n onNavigate={(p) => {\n onNavigate(p);\n setOpen(false);\n }}\n />\n </div>\n )}\n </div>\n );\n};\n\n/** Split a path like \"/a/b/c\" into breadcrumb segments */\nfunction pathSegments(path: string): { label: string; path: string; basePath: string }[] {\n const parts = path.split('/').filter(Boolean);\n const segments: { label: string; path: string; basePath: string }[] = [];\n for (let i = 0; i < parts.length; i++) {\n segments.push({\n label: parts[i],\n path: '/' + parts.slice(0, i + 1).join('/'),\n basePath: i === 0 ? '/' : '/' + parts.slice(0, i).join('/')\n });\n }\n return segments;\n}\n\nexport const Breadcrumb: React.FC<BreadcrumbProps> = ({\n path,\n labels: userLabels,\n adapter,\n onNavigate,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n const segments = pathSegments(path);\n const isRoot = segments.length === 0;\n\n return (\n <nav className=\"flex items-center text-sm overflow-x-visible py-2 px-1 gap-0.5 min-h-[36px]\">\n <button\n className={`btn btn-ghost btn-xs gap-1 flex-shrink-0 ${isRoot ? 'font-semibold' : ''}`}\n onClick={() => onNavigate('/')}\n >\n <HomeIcon />\n {labels.root}\n </button>\n\n {segments.map((seg, idx) => {\n const isLast = idx === segments.length - 1;\n return (\n <React.Fragment key={seg.path}>\n <ChevronDrop path={seg.basePath} adapter={adapter} onNavigate={onNavigate} />\n <button\n className={`btn btn-ghost btn-xs flex-shrink-0 truncate max-w-[160px] ${isLast ? 'font-semibold' : ''}`}\n onClick={() => onNavigate(seg.path)}\n disabled={isLast}\n >\n {seg.label}\n </button>\n </React.Fragment>\n );\n })}\n </nav>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Breadcrumb.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/Breadcrumb.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { BreadcrumbProps } from './types';\nimport { useClickOutside } from '../../../hooks/useClickOutside';\nimport { Tree, TreeNode } from '../../Tree';\n\nconst defaultLabels = {\n root: 'Root',\n};\n\nconst HomeIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6\" />\n </svg>\n);\n\nconst ChevronIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n);\n\nconst FolderIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4 text-blue-500 opacity-80\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M2 6a2 2 0 012-2h4l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6z\" />\n </svg>\n);\n\nconst DocumentIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4 text-gray-500 opacity-80\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z\" clipRule=\"evenodd\" />\n </svg>\n);\n\nconst BreadcrumbDropTree: React.FC<{\n path: string;\n adapter: any;\n onNavigate: (path: string) => void;\n}> = ({ path, adapter, onNavigate }) => {\n const [treeData, setTreeData] = useState<TreeNode[]>([]);\n const [loading, setLoading] = useState(false);\n\n const loadPath = useCallback(async (dirPath: string): Promise<TreeNode[]> => {\n try {\n const entries = await adapter.list(dirPath);\n return entries\n .sort((a: any, b: any) => {\n if (a.type !== b.type) return a.type === 'folder' ? -1 : 1;\n return String(a.name).localeCompare(String(b.name));\n })\n .map((e: any) => ({\n id: e.path,\n label: e.name,\n icon: e.type === 'folder' ? <FolderIcon /> : <DocumentIcon />,\n meta: { type: e.type },\n children: e.type === 'folder' ? [{ id: `${e.path}/_dummy`, label: 'Loading...' }] : undefined\n }));\n } catch (e) {\n return [];\n }\n }, [adapter]);\n\n useEffect(() => {\n let mounted = true;\n setLoading(true);\n loadPath(path).then(nodes => {\n if (mounted) {\n setTreeData(nodes);\n setLoading(false);\n }\n });\n return () => { mounted = false; };\n }, [path, loadPath]);\n\n const handleToggle = useCallback(async (nodeId: string | number, expanded: boolean) => {\n if (!expanded) return;\n const idStr = String(nodeId);\n\n const findNode = (nodes: TreeNode[], targetId: string): TreeNode | null => {\n for (const n of nodes) {\n if (n.id === targetId) return n;\n if (n.children) {\n const found = findNode(n.children, targetId);\n if (found) return found;\n }\n }\n return null;\n };\n\n const node = findNode(treeData, idStr);\n if (node && node.children?.length === 1 && String(node.children[0].id).endsWith('_dummy')) {\n const childrenNodes = await loadPath(idStr);\n setTreeData(prev => {\n const updateNodes = (nodes: TreeNode[]): TreeNode[] => {\n return nodes.map(n => {\n if (n.id === idStr) {\n return { ...n, children: childrenNodes };\n }\n if (n.children) return { ...n, children: updateNodes(n.children) };\n return n;\n });\n };\n return updateNodes(prev);\n });\n }\n }, [treeData, loadPath]);\n\n const handleClick = useCallback((node: TreeNode) => {\n if (String(node.id).endsWith('_dummy')) return;\n if (node.meta?.type === 'file') return;\n onNavigate(String(node.id));\n }, [onNavigate]);\n\n if (loading) return <div className=\"px-4 py-3 w-48 text-center text-xs opacity-50\">Loading...</div>;\n if (treeData.length === 0) return <div className=\"px-4 py-3 w-48 text-center text-xs opacity-50\">Empty Folder</div>;\n\n return (\n <div className=\"p-1 w-64 max-h-[300px] overflow-y-auto sm:min-w-[200px] max-w-[80vw]\">\n <Tree\n data={treeData}\n onNodeClick={handleClick}\n onNodeToggle={handleToggle}\n showSearch={false}\n showExpandAll={false}\n showLine={false}\n showIcon={true}\n showCount={false}\n className=\"!bg-transparent !border-none !p-1 shadow-none overflow-visible\"\n indent={12}\n />\n </div>\n );\n};\n\nconst ChevronDrop: React.FC<{\n path: string;\n adapter?: any;\n onNavigate: (p: string) => void;\n}> = ({ path, adapter, onNavigate }) => {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useClickOutside(ref, () => setOpen(false), open);\n\n return (\n <div className=\"relative flex items-center\" ref={ref}>\n {adapter ? (\n <button\n className={`btn btn-ghost btn-xs px-0.5 mx-0.5 min-h-0 h-5 rounded hover:bg-base-200 transition-colors ${open ? 'bg-base-200' : 'opacity-50'}`}\n onClick={(e) => {\n e.stopPropagation();\n setOpen(!open);\n }}\n >\n <ChevronIcon />\n </button>\n ) : (\n <span className=\"opacity-40 mx-1\"><ChevronIcon /></span>\n )}\n\n {open && adapter && (\n <div\n className=\"absolute top-full left-1/2 -translate-x-1/2 mt-1 bg-base-100 shadow-2xl border border-base-200 rounded-xl z-[9999]\"\n onClick={(e) => e.stopPropagation()}\n >\n <BreadcrumbDropTree\n path={path}\n adapter={adapter}\n onNavigate={(p) => {\n onNavigate(p);\n setOpen(false);\n }}\n />\n </div>\n )}\n </div>\n );\n};\n\n/** Split a path like \"/a/b/c\" into breadcrumb segments */\nfunction pathSegments(path: string): { label: string; path: string; basePath: string }[] {\n const parts = path.split('/').filter(Boolean);\n const segments: { label: string; path: string; basePath: string }[] = [];\n for (let i = 0; i < parts.length; i++) {\n segments.push({\n label: parts[i],\n path: '/' + parts.slice(0, i + 1).join('/'),\n basePath: i === 0 ? '/' : '/' + parts.slice(0, i).join('/')\n });\n }\n return segments;\n}\n\nexport const Breadcrumb: React.FC<BreadcrumbProps> = ({\n path,\n labels: userLabels,\n adapter,\n onNavigate,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n const segments = pathSegments(path);\n const isRoot = segments.length === 0;\n\n return (\n <nav className=\"flex items-center text-sm overflow-x-visible py-2 px-1 gap-0.5 min-h-[36px]\">\n <button\n className={`btn btn-ghost btn-xs gap-1 flex-shrink-0 ${isRoot ? 'font-semibold' : ''}`}\n onClick={() => onNavigate('/')}\n >\n <HomeIcon />\n {labels.root}\n </button>\n\n {segments.map((seg, idx) => {\n const isLast = idx === segments.length - 1;\n return (\n <React.Fragment key={seg.path}>\n <ChevronDrop path={seg.basePath} adapter={adapter} onNavigate={onNavigate} />\n <button\n className={`btn btn-ghost btn-xs flex-shrink-0 truncate max-w-[160px] ${isLast ? 'font-semibold' : ''}`}\n onClick={() => onNavigate(seg.path)}\n disabled={isLast}\n >\n {seg.label}\n </button>\n </React.Fragment>\n );\n })}\n </nav>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateDialog.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/CreateDialog.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport { CreateDialogProps } from './types';\nimport Button from '../../Button';\nimport Input from '../../Input';\n\nconst defaultLabels = {\n newFolder: 'New Folder',\n newFile: 'New File',\n create: 'Create',\n cancel: 'Cancel',\n folderNamePlaceholder: 'Folder name',\n fileNamePlaceholder: 'File name',\n};\n\nexport const CreateDialog: React.FC<CreateDialogProps> = ({\n type,\n labels: userLabels,\n onConfirm,\n onCancel,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n const [name, setName] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n // Auto-focus the input with a small delay for animation\n const timer = setTimeout(() => {\n inputRef.current?.focus();\n }, 50);\n return () => clearTimeout(timer);\n }, []);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n const trimmed = name.trim();\n if (trimmed) {\n onConfirm(trimmed);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCancel();\n }\n };\n\n return (\n <div className=\"flex items-center gap-2 px-3 py-2 bg-base-200/80 rounded-lg border border-base-300 animate-in\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5 opacity-50 flex-shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n {type === 'folder' ? (\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z\" />\n ) : (\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n )}\n </svg>\n\n <form onSubmit={handleSubmit} className=\"flex items-center gap-2 flex-1\" onKeyDown={handleKeyDown}>\n <input\n ref={inputRef}\n type=\"text\"\n className=\"input input-sm input-bordered flex-1 min-w-0\"\n placeholder={type === 'folder' ? labels.folderNamePlaceholder : labels.fileNamePlaceholder}\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n <Button\n variant=\"primary\"\n size=\"xs\"\n disabled={!name.trim()}\n onClick={() => { if (name.trim()) onConfirm(name.trim()); }}\n >\n {labels.create}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n onClick={onCancel}\n >\n {labels.cancel}\n </Button>\n </form>\n </div>\n );\n};\n"],"mappings":";;;AAKA,IAAM,IAAgB;AAAA,EAClB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,uBAAuB;AAAA,EACvB,qBAAqB;AACzB,GAEa,IAAA,CAA6C,EACtD,MAAA,GACA,QAAQ,GACR,WAAA,GACA,UAAA,EAAA,MACE;AACF,QAAM,IAAS;AAAA,IAAE,GAAG;AAAA,IAAe,GAAG;AAAA,EAAW,GAC3C,CAAC,GAAM,CAAA,IAAW,EAAS,EAAE,GAC7B,IAAW,EAAyB,IAAI;AAE9C,SAAA,EAAA,MAAgB;AAEZ,UAAM,IAAQ,WAAA,MAAiB;AAC3B,MAAA,EAAS,SAAS,MAAM;AAAA,IAC5B,GAAG,EAAE;AACL,WAAA,MAAa,aAAa,CAAK;AAAA,EACnC,GAAG,CAAC,CAAC,GAiBD,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,
|
|
1
|
+
{"version":3,"file":"CreateDialog.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/CreateDialog.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport { CreateDialogProps } from './types';\nimport Button from '../../Button';\nimport Input from '../../Input';\n\nconst defaultLabels = {\n newFolder: 'New Folder',\n newFile: 'New File',\n create: 'Create',\n cancel: 'Cancel',\n folderNamePlaceholder: 'Folder name',\n fileNamePlaceholder: 'File name',\n};\n\nexport const CreateDialog: React.FC<CreateDialogProps> = ({\n type,\n labels: userLabels,\n onConfirm,\n onCancel,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n const [name, setName] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n // Auto-focus the input with a small delay for animation\n const timer = setTimeout(() => {\n inputRef.current?.focus();\n }, 50);\n return () => clearTimeout(timer);\n }, []);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n const trimmed = name.trim();\n if (trimmed) {\n onConfirm(trimmed);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCancel();\n }\n };\n\n return (\n <div className=\"flex items-center gap-2 px-3 py-2 bg-base-200/80 rounded-lg border border-base-300 animate-in\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5 opacity-50 flex-shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n {type === 'folder' ? (\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z\" />\n ) : (\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n )}\n </svg>\n\n <form onSubmit={handleSubmit} className=\"flex items-center gap-2 flex-1\" onKeyDown={handleKeyDown}>\n <input\n ref={inputRef}\n type=\"text\"\n className=\"input input-sm input-bordered flex-1 min-w-0\"\n placeholder={type === 'folder' ? labels.folderNamePlaceholder : labels.fileNamePlaceholder}\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n <Button\n variant=\"primary\"\n size=\"xs\"\n disabled={!name.trim()}\n onClick={() => { if (name.trim()) onConfirm(name.trim()); }}\n >\n {labels.create}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n onClick={onCancel}\n >\n {labels.cancel}\n </Button>\n </form>\n </div>\n );\n};\n"],"mappings":";;;AAKA,IAAM,IAAgB;AAAA,EAClB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,uBAAuB;AAAA,EACvB,qBAAqB;AACzB,GAEa,IAAA,CAA6C,EACtD,MAAA,GACA,QAAQ,GACR,WAAA,GACA,UAAA,EAAA,MACE;AACF,QAAM,IAAS;AAAA,IAAE,GAAG;AAAA,IAAe,GAAG;AAAA,EAAW,GAC3C,CAAC,GAAM,CAAA,IAAW,EAAS,EAAE,GAC7B,IAAW,EAAyB,IAAI;AAE9C,SAAA,EAAA,MAAgB;AAEZ,UAAM,IAAQ,WAAA,MAAiB;AAC3B,MAAA,EAAS,SAAS,MAAM;AAAA,IAC5B,GAAG,EAAE;AACL,WAAA,MAAa,aAAa,CAAK;AAAA,EACnC,GAAG,CAAC,CAAC,GAiBD,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,IAAf,UAAA,CACI,gBAAA,EAAC,OAAD;AAAA,MAAK,OAAM;AAAA,MAA6B,WAAU;AAAA,MAAmC,MAAK;AAAA,MAAO,SAAQ;AAAA,MAAY,QAAO;AAAA,MAAe,aAAa;AAAA,MACnJ,UAAA,MAAS,WACN,gBAAA,EAAC,QAAD;AAAA,QAAM,eAAc;AAAA,QAAQ,gBAAe;AAAA,QAAQ,GAAE;AAAA,MAAwF,CAAA,IAE7I,gBAAA,EAAC,QAAD;AAAA,QAAM,eAAc;AAAA,QAAQ,gBAAe;AAAA,QAAQ,GAAE;AAAA,MAAwH,CAAA;AAAA,IAEhL,CAAA,GAEL,gBAAA,EAAC,QAAD;AAAA,MAAM,UAxBR,CAAgB,MAAuB;AACzC,UAAE,eAAe;AACjB,cAAM,IAAU,EAAK,KAAK;AAC1B,QAAI,KACA,EAAU,CAAO;AAAA,MAEzB;AAAA,MAkBsC,WAAU;AAAA,MAAiC,WAhB3E,CAAiB,MAA2B;AAC9C,QAAI,EAAE,QAAQ,YACV,EAAS;AAAA,MAEjB;AAAA,MAYQ,UAAA;AAAA,QACI,gBAAA,EAAC,SAAD;AAAA,UACI,KAAK;AAAA,UACL,MAAK;AAAA,UACL,WAAU;AAAA,UACV,aAAa,MAAS,WAAW,EAAO,wBAAwB,EAAO;AAAA,UACvE,OAAO;AAAA,UACP,UAAA,CAAW,MAAM,EAAQ,EAAE,OAAO,KAAK;AAAA,QAC1C,CAAA;AAAA,QACD,gBAAA,EAAC,GAAD;AAAA,UACI,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,UAAU,CAAC,EAAK,KAAK;AAAA,UACrB,SAAA,MAAe;AAAE,YAAI,EAAK,KAAK,KAAG,EAAU,EAAK,KAAK,CAAC;AAAA,UAAG;AAAA,UAEzD,UAAA,EAAO;AAAA,QACJ,CAAA;AAAA,QACR,gBAAA,EAAC,GAAD;AAAA,UACI,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,SAAS;AAAA,UAER,UAAA,EAAO;AAAA,QACJ,CAAA;AAAA,MACN;AAAA,IACL,CAAA,CAAA;AAAA;AAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileExplorer.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/FileExplorer.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { FileExplorerProps, FileEntry, ViewMode, SortConfig, SortField } from './types';\nimport { Breadcrumb } from './Breadcrumb';\nimport { Toolbar } from './Toolbar';\nimport { ListView } from './ListView';\nimport { GridView } from './GridView';\nimport { CreateDialog } from './CreateDialog';\nimport { FileUploader } from '../../FileUploader/FileUploader';\nimport type { UploadResult } from '../../FileUploader/types';\n\nconst defaultLabels = {\n loading: 'Loading...',\n emptyFolder: 'This folder is empty',\n items: 'items',\n uploadFiles: 'Upload',\n};\n\n// --- Sorting ---\n\nfunction compareEntries(a: FileEntry, b: FileEntry, field: SortField, direction: 'asc' | 'desc'): number {\n // Folders always first\n if (a.type !== b.type) {\n return a.type === 'folder' ? -1 : 1;\n }\n\n let cmp = 0;\n switch (field) {\n case 'name':\n cmp = a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });\n break;\n case 'size':\n cmp = (a.size || 0) - (b.size || 0);\n break;\n case 'modifiedAt': {\n const dateA = a.modifiedAt ? new Date(a.modifiedAt).getTime() : 0;\n const dateB = b.modifiedAt ? new Date(b.modifiedAt).getTime() : 0;\n cmp = dateA - dateB;\n break;\n }\n case 'type': {\n const extA = a.name.split('.').pop()?.toLowerCase() || '';\n const extB = b.name.split('.').pop()?.toLowerCase() || '';\n cmp = extA.localeCompare(extB);\n break;\n }\n }\n\n return direction === 'desc' ? -cmp : cmp;\n}\n\nexport const FileExplorer: React.FC<FileExplorerProps> = ({\n adapter,\n uploadAdapter,\n initialPath = '/',\n viewMode: initialViewMode = 'list',\n enableCreate = false,\n enableDelete = false,\n enableRename = false,\n enableUpload = false,\n uploadAccept,\n uploadMaxFileSize,\n className = '',\n labels: userLabels,\n onFileSelect,\n onPathChange,\n onUploadComplete,\n onUploadError,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n\n // State\n const [currentPath, setCurrentPath] = useState(initialPath);\n const [entries, setEntries] = useState<FileEntry[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n const [viewMode, setViewMode] = useState<ViewMode>(initialViewMode);\n const [sortConfig, setSortConfig] = useState<SortConfig>({ field: 'name', direction: 'asc' });\n const [createType, setCreateType] = useState<'file' | 'folder' | null>(null);\n const [showUploader, setShowUploader] = useState(false);\n\n // Fetch entries when path changes\n const fetchEntries = useCallback(async (path: string) => {\n setIsLoading(true);\n try {\n const result = await adapter.list(path);\n setEntries(result);\n } catch (err) {\n console.error('Failed to list directory:', err);\n setEntries([]);\n } finally {\n setIsLoading(false);\n }\n }, [adapter]);\n\n useEffect(() => {\n fetchEntries(currentPath);\n }, [currentPath, fetchEntries]);\n\n // Navigate to a path\n const navigateTo = useCallback((path: string) => {\n setCurrentPath(path);\n setSearchQuery('');\n setCreateType(null);\n setShowUploader(false);\n onPathChange?.(path);\n }, [onPathChange]);\n\n // Filter + sort entries\n const processedEntries = useMemo(() => {\n let filtered = entries;\n\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n filtered = entries.filter(e => e.name.toLowerCase().includes(q));\n }\n\n return [...filtered].sort((a, b) => compareEntries(a, b, sortConfig.field, sortConfig.direction));\n }, [entries, searchQuery, sortConfig]);\n\n // Entry click: select file or navigate into folder\n const handleEntryClick = useCallback((entry: FileEntry) => {\n if (entry.type === 'folder') {\n navigateTo(entry.path);\n } else {\n onFileSelect?.(entry);\n }\n }, [navigateTo, onFileSelect]);\n\n const handleEntryDoubleClick = useCallback((entry: FileEntry) => {\n if (entry.type === 'folder') {\n navigateTo(entry.path);\n } else {\n onFileSelect?.(entry);\n }\n }, [navigateTo, onFileSelect]);\n\n // Delete\n const handleDelete = useCallback(async (entry: FileEntry) => {\n if (!adapter.delete) return;\n try {\n await adapter.delete(entry.path);\n setEntries(prev => prev.filter(e => e.path !== entry.path));\n } catch (err) {\n console.error('Failed to delete:', err);\n }\n }, [adapter]);\n\n // Rename\n const handleRename = useCallback(async (entry: FileEntry) => {\n if (!adapter.rename) return;\n const newName = window.prompt('New name:', entry.name);\n if (!newName || newName === entry.name) return;\n try {\n const updated = await adapter.rename(entry.path, newName);\n setEntries(prev => prev.map(e => e.path === entry.path ? updated : e));\n } catch (err) {\n console.error('Failed to rename:', err);\n }\n }, [adapter]);\n\n // Create folder / file\n const handleCreate = useCallback(async (name: string) => {\n if (!createType) return;\n\n try {\n let newEntry: FileEntry | undefined;\n if (createType === 'folder' && adapter.createFolder) {\n newEntry = await adapter.createFolder(currentPath, name);\n } else if (createType === 'file' && adapter.createFile) {\n newEntry = await adapter.createFile(currentPath, name);\n }\n if (newEntry) {\n setEntries(prev => [...prev, newEntry!]);\n }\n } catch (err) {\n console.error('Failed to create:', err);\n } finally {\n setCreateType(null);\n }\n }, [createType, currentPath, adapter]);\n\n // Upload complete: refresh listing and notify parent\n const handleUploadComplete = useCallback((results: UploadResult[]) => {\n // Refresh the current directory listing to show newly uploaded files\n fetchEntries(currentPath);\n onUploadComplete?.(results);\n }, [fetchEntries, currentPath, onUploadComplete]);\n\n const hasUpload = enableUpload && !!uploadAdapter;\n\n return (\n <div className={`flex flex-col bg-base-100 rounded-xl border border-base-300 overflow-hidden shadow-lg ${className}`}>\n {/* Breadcrumb */}\n <div className=\"border-b border-base-300 px-2\">\n <Breadcrumb\n path={currentPath}\n labels={labels}\n adapter={adapter}\n onNavigate={navigateTo}\n />\n </div>\n\n {/* Toolbar */}\n <Toolbar\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n viewMode={viewMode}\n onViewModeChange={setViewMode}\n sortConfig={sortConfig}\n onSortChange={setSortConfig}\n enableCreate={enableCreate}\n hasCreateFolder={!!adapter.createFolder}\n hasCreateFile={!!adapter.createFile}\n onCreateFolder={() => setCreateType('folder')}\n onCreateFile={() => setCreateType('file')}\n enableUpload={hasUpload}\n onUploadFiles={() => setShowUploader(prev => !prev)}\n labels={labels}\n />\n\n {/* Create dialog */}\n {createType && (\n <div className=\"px-3 py-2 border-b border-base-300\">\n <CreateDialog\n type={createType}\n labels={labels}\n onConfirm={handleCreate}\n onCancel={() => setCreateType(null)}\n />\n </div>\n )}\n\n {/* Upload panel */}\n {showUploader && uploadAdapter && (\n <div className=\"px-3 py-3 border-b border-base-300 bg-base-200/30\">\n <FileUploader\n adapter={uploadAdapter}\n accept={uploadAccept}\n maxFileSize={uploadMaxFileSize}\n multiple\n autoUpload\n labels={labels as any}\n onUploadComplete={handleUploadComplete}\n onError={onUploadError}\n />\n </div>\n )}\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto min-h-[300px]\">\n {isLoading ? (\n <div className=\"flex items-center justify-center py-16\">\n <span className=\"loading loading-spinner loading-md opacity-50\" />\n <span className=\"ml-2 text-sm opacity-50\">{labels.loading}</span>\n </div>\n ) : viewMode === 'list' ? (\n <ListView\n entries={processedEntries}\n sortConfig={sortConfig}\n onSortChange={setSortConfig}\n onEntryClick={handleEntryClick}\n onEntryDoubleClick={handleEntryDoubleClick}\n onDelete={enableDelete ? handleDelete : undefined}\n onRename={enableRename ? handleRename : undefined}\n enableDelete={enableDelete}\n enableRename={enableRename}\n labels={labels}\n />\n ) : (\n <GridView\n entries={processedEntries}\n onEntryClick={handleEntryClick}\n onEntryDoubleClick={handleEntryDoubleClick}\n onDelete={enableDelete ? handleDelete : undefined}\n onRename={enableRename ? handleRename : undefined}\n enableDelete={enableDelete}\n enableRename={enableRename}\n labels={labels}\n />\n )}\n </div>\n\n {/* Status bar */}\n <div className=\"border-t border-base-300 px-3 py-1.5 text-xs opacity-50 flex items-center justify-between\">\n <span>{processedEntries.length} {labels.items}</span>\n {searchQuery && (\n <span className=\"italic\">Filtered from {entries.length}</span>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FileExplorer.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/FileExplorer.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { FileExplorerProps, FileEntry, ViewMode, SortConfig, SortField } from './types';\nimport { Breadcrumb } from './Breadcrumb';\nimport { Toolbar } from './Toolbar';\nimport { ListView } from './ListView';\nimport { GridView } from './GridView';\nimport { CreateDialog } from './CreateDialog';\nimport { FileUploader } from '../../FileUploader/FileUploader';\nimport type { UploadResult } from '../../FileUploader/types';\n\nconst defaultLabels = {\n loading: 'Loading...',\n emptyFolder: 'This folder is empty',\n items: 'items',\n uploadFiles: 'Upload',\n};\n\n// --- Sorting ---\n\nfunction compareEntries(a: FileEntry, b: FileEntry, field: SortField, direction: 'asc' | 'desc'): number {\n // Folders always first\n if (a.type !== b.type) {\n return a.type === 'folder' ? -1 : 1;\n }\n\n let cmp = 0;\n switch (field) {\n case 'name':\n cmp = a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });\n break;\n case 'size':\n cmp = (a.size || 0) - (b.size || 0);\n break;\n case 'modifiedAt': {\n const dateA = a.modifiedAt ? new Date(a.modifiedAt).getTime() : 0;\n const dateB = b.modifiedAt ? new Date(b.modifiedAt).getTime() : 0;\n cmp = dateA - dateB;\n break;\n }\n case 'type': {\n const extA = a.name.split('.').pop()?.toLowerCase() || '';\n const extB = b.name.split('.').pop()?.toLowerCase() || '';\n cmp = extA.localeCompare(extB);\n break;\n }\n }\n\n return direction === 'desc' ? -cmp : cmp;\n}\n\nexport const FileExplorer: React.FC<FileExplorerProps> = ({\n adapter,\n uploadAdapter,\n initialPath = '/',\n viewMode: initialViewMode = 'list',\n enableCreate = false,\n enableDelete = false,\n enableRename = false,\n enableUpload = false,\n uploadAccept,\n uploadMaxFileSize,\n className = '',\n labels: userLabels,\n onFileSelect,\n onPathChange,\n onUploadComplete,\n onUploadError,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n\n // State\n const [currentPath, setCurrentPath] = useState(initialPath);\n const [entries, setEntries] = useState<FileEntry[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n const [viewMode, setViewMode] = useState<ViewMode>(initialViewMode);\n const [sortConfig, setSortConfig] = useState<SortConfig>({ field: 'name', direction: 'asc' });\n const [createType, setCreateType] = useState<'file' | 'folder' | null>(null);\n const [showUploader, setShowUploader] = useState(false);\n\n // Fetch entries when path changes\n const fetchEntries = useCallback(async (path: string) => {\n setIsLoading(true);\n try {\n const result = await adapter.list(path);\n setEntries(result);\n } catch (err) {\n console.error('Failed to list directory:', err);\n setEntries([]);\n } finally {\n setIsLoading(false);\n }\n }, [adapter]);\n\n useEffect(() => {\n fetchEntries(currentPath);\n }, [currentPath, fetchEntries]);\n\n // Navigate to a path\n const navigateTo = useCallback((path: string) => {\n setCurrentPath(path);\n setSearchQuery('');\n setCreateType(null);\n setShowUploader(false);\n onPathChange?.(path);\n }, [onPathChange]);\n\n // Filter + sort entries\n const processedEntries = useMemo(() => {\n let filtered = entries;\n\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n filtered = entries.filter(e => e.name.toLowerCase().includes(q));\n }\n\n return [...filtered].sort((a, b) => compareEntries(a, b, sortConfig.field, sortConfig.direction));\n }, [entries, searchQuery, sortConfig]);\n\n // Entry click: select file or navigate into folder\n const handleEntryClick = useCallback((entry: FileEntry) => {\n if (entry.type === 'folder') {\n navigateTo(entry.path);\n } else {\n onFileSelect?.(entry);\n }\n }, [navigateTo, onFileSelect]);\n\n const handleEntryDoubleClick = useCallback((entry: FileEntry) => {\n if (entry.type === 'folder') {\n navigateTo(entry.path);\n } else {\n onFileSelect?.(entry);\n }\n }, [navigateTo, onFileSelect]);\n\n // Delete\n const handleDelete = useCallback(async (entry: FileEntry) => {\n if (!adapter.delete) return;\n try {\n await adapter.delete(entry.path);\n setEntries(prev => prev.filter(e => e.path !== entry.path));\n } catch (err) {\n console.error('Failed to delete:', err);\n }\n }, [adapter]);\n\n // Rename\n const handleRename = useCallback(async (entry: FileEntry) => {\n if (!adapter.rename) return;\n const newName = window.prompt('New name:', entry.name);\n if (!newName || newName === entry.name) return;\n try {\n const updated = await adapter.rename(entry.path, newName);\n setEntries(prev => prev.map(e => e.path === entry.path ? updated : e));\n } catch (err) {\n console.error('Failed to rename:', err);\n }\n }, [adapter]);\n\n // Create folder / file\n const handleCreate = useCallback(async (name: string) => {\n if (!createType) return;\n\n try {\n let newEntry: FileEntry | undefined;\n if (createType === 'folder' && adapter.createFolder) {\n newEntry = await adapter.createFolder(currentPath, name);\n } else if (createType === 'file' && adapter.createFile) {\n newEntry = await adapter.createFile(currentPath, name);\n }\n if (newEntry) {\n setEntries(prev => [...prev, newEntry!]);\n }\n } catch (err) {\n console.error('Failed to create:', err);\n } finally {\n setCreateType(null);\n }\n }, [createType, currentPath, adapter]);\n\n // Upload complete: refresh listing and notify parent\n const handleUploadComplete = useCallback((results: UploadResult[]) => {\n // Refresh the current directory listing to show newly uploaded files\n fetchEntries(currentPath);\n onUploadComplete?.(results);\n }, [fetchEntries, currentPath, onUploadComplete]);\n\n const hasUpload = enableUpload && !!uploadAdapter;\n\n return (\n <div className={`flex flex-col bg-base-100 rounded-xl border border-base-300 overflow-hidden shadow-lg ${className}`}>\n {/* Breadcrumb */}\n <div className=\"border-b border-base-300 px-2\">\n <Breadcrumb\n path={currentPath}\n labels={labels}\n adapter={adapter}\n onNavigate={navigateTo}\n />\n </div>\n\n {/* Toolbar */}\n <Toolbar\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n viewMode={viewMode}\n onViewModeChange={setViewMode}\n sortConfig={sortConfig}\n onSortChange={setSortConfig}\n enableCreate={enableCreate}\n hasCreateFolder={!!adapter.createFolder}\n hasCreateFile={!!adapter.createFile}\n onCreateFolder={() => setCreateType('folder')}\n onCreateFile={() => setCreateType('file')}\n enableUpload={hasUpload}\n onUploadFiles={() => setShowUploader(prev => !prev)}\n labels={labels}\n />\n\n {/* Create dialog */}\n {createType && (\n <div className=\"px-3 py-2 border-b border-base-300\">\n <CreateDialog\n type={createType}\n labels={labels}\n onConfirm={handleCreate}\n onCancel={() => setCreateType(null)}\n />\n </div>\n )}\n\n {/* Upload panel */}\n {showUploader && uploadAdapter && (\n <div className=\"px-3 py-3 border-b border-base-300 bg-base-200/30\">\n <FileUploader\n adapter={uploadAdapter}\n accept={uploadAccept}\n maxFileSize={uploadMaxFileSize}\n multiple\n autoUpload\n labels={labels as any}\n onUploadComplete={handleUploadComplete}\n onError={onUploadError}\n />\n </div>\n )}\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto min-h-[300px]\">\n {isLoading ? (\n <div className=\"flex items-center justify-center py-16\">\n <span className=\"loading loading-spinner loading-md opacity-50\" />\n <span className=\"ml-2 text-sm opacity-50\">{labels.loading}</span>\n </div>\n ) : viewMode === 'list' ? (\n <ListView\n entries={processedEntries}\n sortConfig={sortConfig}\n onSortChange={setSortConfig}\n onEntryClick={handleEntryClick}\n onEntryDoubleClick={handleEntryDoubleClick}\n onDelete={enableDelete ? handleDelete : undefined}\n onRename={enableRename ? handleRename : undefined}\n enableDelete={enableDelete}\n enableRename={enableRename}\n labels={labels}\n />\n ) : (\n <GridView\n entries={processedEntries}\n onEntryClick={handleEntryClick}\n onEntryDoubleClick={handleEntryDoubleClick}\n onDelete={enableDelete ? handleDelete : undefined}\n onRename={enableRename ? handleRename : undefined}\n enableDelete={enableDelete}\n enableRename={enableRename}\n labels={labels}\n />\n )}\n </div>\n\n {/* Status bar */}\n <div className=\"border-t border-base-300 px-3 py-1.5 text-xs opacity-50 flex items-center justify-between\">\n <span>{processedEntries.length} {labels.items}</span>\n {searchQuery && (\n <span className=\"italic\">Filtered from {entries.length}</span>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import "react";
|
|
2
2
|
import { jsx as o } from "react/jsx-runtime";
|
|
3
|
-
var
|
|
3
|
+
var c = {
|
|
4
4
|
sm: "h-4 w-4",
|
|
5
5
|
md: "h-5 w-5",
|
|
6
6
|
lg: "h-8 w-8"
|
|
7
|
-
},
|
|
7
|
+
}, l = ({ sizeClass: e }) => /* @__PURE__ */ o("svg", {
|
|
8
8
|
xmlns: "http://www.w3.org/2000/svg",
|
|
9
9
|
className: `${e} text-warning`,
|
|
10
10
|
fill: "none",
|
|
@@ -16,7 +16,7 @@ var a = {
|
|
|
16
16
|
strokeLinejoin: "round",
|
|
17
17
|
d: "M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
|
|
18
18
|
})
|
|
19
|
-
}),
|
|
19
|
+
}), d = ({ sizeClass: e }) => /* @__PURE__ */ o("svg", {
|
|
20
20
|
xmlns: "http://www.w3.org/2000/svg",
|
|
21
21
|
className: `${e} text-success`,
|
|
22
22
|
fill: "none",
|
|
@@ -28,7 +28,7 @@ var a = {
|
|
|
28
28
|
strokeLinejoin: "round",
|
|
29
29
|
d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
30
30
|
})
|
|
31
|
-
}),
|
|
31
|
+
}), h = ({ sizeClass: e }) => /* @__PURE__ */ o("svg", {
|
|
32
32
|
xmlns: "http://www.w3.org/2000/svg",
|
|
33
33
|
className: `${e} text-error`,
|
|
34
34
|
fill: "none",
|
|
@@ -40,7 +40,7 @@ var a = {
|
|
|
40
40
|
strokeLinejoin: "round",
|
|
41
41
|
d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"
|
|
42
42
|
})
|
|
43
|
-
}),
|
|
43
|
+
}), m = ({ sizeClass: e }) => /* @__PURE__ */ o("svg", {
|
|
44
44
|
xmlns: "http://www.w3.org/2000/svg",
|
|
45
45
|
className: `${e} text-secondary`,
|
|
46
46
|
fill: "none",
|
|
@@ -52,7 +52,7 @@ var a = {
|
|
|
52
52
|
strokeLinejoin: "round",
|
|
53
53
|
d: "M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3"
|
|
54
54
|
})
|
|
55
|
-
}),
|
|
55
|
+
}), p = ({ sizeClass: e }) => /* @__PURE__ */ o("svg", {
|
|
56
56
|
xmlns: "http://www.w3.org/2000/svg",
|
|
57
57
|
className: `${e} text-info`,
|
|
58
58
|
fill: "none",
|
|
@@ -76,7 +76,7 @@ var a = {
|
|
|
76
76
|
strokeLinejoin: "round",
|
|
77
77
|
d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
|
78
78
|
})
|
|
79
|
-
}),
|
|
79
|
+
}), w = ({ sizeClass: e }) => /* @__PURE__ */ o("svg", {
|
|
80
80
|
xmlns: "http://www.w3.org/2000/svg",
|
|
81
81
|
className: `${e} text-accent`,
|
|
82
82
|
fill: "none",
|
|
@@ -101,7 +101,7 @@ var a = {
|
|
|
101
101
|
d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"
|
|
102
102
|
})
|
|
103
103
|
});
|
|
104
|
-
function
|
|
104
|
+
function u(e) {
|
|
105
105
|
const t = e.mimeType || "", r = e.name.split(".").pop()?.toLowerCase() || "";
|
|
106
106
|
return t.startsWith("image/") || [
|
|
107
107
|
"png",
|
|
@@ -169,28 +169,28 @@ function w(e) {
|
|
|
169
169
|
"xz"
|
|
170
170
|
].includes(r) ? "archive" : "generic";
|
|
171
171
|
}
|
|
172
|
-
var
|
|
173
|
-
const n =
|
|
172
|
+
var f = ({ entry: e, size: t = "sm", className: r = "" }) => {
|
|
173
|
+
const n = c[t];
|
|
174
174
|
if (e.type === "folder") return /* @__PURE__ */ o("span", {
|
|
175
175
|
className: r,
|
|
176
|
-
children: /* @__PURE__ */ o(
|
|
176
|
+
children: /* @__PURE__ */ o(l, { sizeClass: n })
|
|
177
177
|
});
|
|
178
|
-
const i =
|
|
178
|
+
const i = u(e), a = {
|
|
179
|
+
image: d,
|
|
180
|
+
video: h,
|
|
181
|
+
audio: m,
|
|
182
|
+
code: p,
|
|
183
|
+
document: v,
|
|
184
|
+
archive: w,
|
|
185
|
+
generic: s
|
|
186
|
+
}[i] || s;
|
|
179
187
|
return /* @__PURE__ */ o("span", {
|
|
180
188
|
className: r,
|
|
181
|
-
children: /* @__PURE__ */ o({
|
|
182
|
-
image: l,
|
|
183
|
-
video: d,
|
|
184
|
-
audio: h,
|
|
185
|
-
code: m,
|
|
186
|
-
document: v,
|
|
187
|
-
archive: p,
|
|
188
|
-
generic: s
|
|
189
|
-
}[i] || s, { sizeClass: n })
|
|
189
|
+
children: /* @__PURE__ */ o(a, { sizeClass: n })
|
|
190
190
|
});
|
|
191
191
|
};
|
|
192
192
|
export {
|
|
193
|
-
|
|
193
|
+
f as FileIcon
|
|
194
194
|
};
|
|
195
195
|
|
|
196
196
|
//# sourceMappingURL=FileIcon.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileIcon.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/FileIcon.tsx"],"sourcesContent":["import React from 'react';\nimport { FileIconProps } from './types';\n\nconst sizeMap = {\n sm: 'h-4 w-4',\n md: 'h-5 w-5',\n lg: 'h-8 w-8',\n};\n\n// --- Icon components ---\n\nconst FolderIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-warning`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z\" />\n </svg>\n);\n\nconst ImageIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-success`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\" />\n </svg>\n);\n\nconst VideoIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-error`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n);\n\nconst AudioIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-secondary`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3\" />\n </svg>\n);\n\nconst CodeIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-info`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4\" />\n </svg>\n);\n\nconst DocIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-primary`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n);\n\nconst ArchiveIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-accent`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4\" />\n </svg>\n);\n\nconst GenericFileIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} opacity-60`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z\" />\n </svg>\n);\n\n// --- MIME / extension to category mapping ---\n\nfunction getFileCategory(entry: { name: string; mimeType?: string }): string {\n const mime = entry.mimeType || '';\n const ext = entry.name.split('.').pop()?.toLowerCase() || '';\n\n if (mime.startsWith('image/') || ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'ico'].includes(ext)) return 'image';\n if (mime.startsWith('video/') || ['mp4', 'webm', 'avi', 'mov', 'mkv'].includes(ext)) return 'video';\n if (mime.startsWith('audio/') || ['mp3', 'wav', 'flac', 'aac', 'ogg', 'm4a'].includes(ext)) return 'audio';\n if (['js', 'ts', 'tsx', 'jsx', 'py', 'rs', 'go', 'java', 'c', 'cpp', 'h', 'css', 'html', 'json', 'xml', 'yaml', 'yml', 'toml', 'sh', 'bash', 'sql'].includes(ext)) return 'code';\n if (['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'md', 'rtf', 'csv'].includes(ext)) return 'document';\n if (['zip', 'tar', 'gz', 'bz2', 'rar', '7z', 'xz'].includes(ext)) return 'archive';\n\n return 'generic';\n}\n\n// --- Main component ---\n\nexport const FileIcon: React.FC<FileIconProps> = ({\n entry,\n size = 'sm',\n className = '',\n}) => {\n const sizeClass = sizeMap[size];\n\n if (entry.type === 'folder') {\n return <span className={className}><FolderIcon sizeClass={sizeClass} /></span>;\n }\n\n const category = getFileCategory(entry);\n\n const IconComponent = {\n image: ImageIcon,\n video: VideoIcon,\n audio: AudioIcon,\n code: CodeIcon,\n document: DocIcon,\n archive: ArchiveIcon,\n generic: GenericFileIcon,\n }[category] || GenericFileIcon;\n\n return <span className={className}><IconComponent sizeClass={sizeClass} /></span>;\n};\n"],"mappings":";;AAGA,IAAM,IAAU;AAAA,EACZ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACR,GAIM,IAAA,CAA+C,EAAE,WAAA,EAAA,MACnD,gBAAA,EAAC,OAAD;AAAA,EAAK,OAAM;AAAA,EAA6B,WAAW,GAAG,CAAA;AAAA,EAA0B,MAAK;AAAA,EAAO,SAAQ;AAAA,EAAY,QAAO;AAAA,EAAe,aAAa;AAAA,
|
|
1
|
+
{"version":3,"file":"FileIcon.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/FileIcon.tsx"],"sourcesContent":["import React from 'react';\nimport { FileIconProps } from './types';\n\nconst sizeMap = {\n sm: 'h-4 w-4',\n md: 'h-5 w-5',\n lg: 'h-8 w-8',\n};\n\n// --- Icon components ---\n\nconst FolderIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-warning`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z\" />\n </svg>\n);\n\nconst ImageIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-success`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\" />\n </svg>\n);\n\nconst VideoIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-error`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n);\n\nconst AudioIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-secondary`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3\" />\n </svg>\n);\n\nconst CodeIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-info`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4\" />\n </svg>\n);\n\nconst DocIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-primary`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n);\n\nconst ArchiveIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} text-accent`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4\" />\n </svg>\n);\n\nconst GenericFileIcon: React.FC<{ sizeClass: string }> = ({ sizeClass }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className={`${sizeClass} opacity-60`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z\" />\n </svg>\n);\n\n// --- MIME / extension to category mapping ---\n\nfunction getFileCategory(entry: { name: string; mimeType?: string }): string {\n const mime = entry.mimeType || '';\n const ext = entry.name.split('.').pop()?.toLowerCase() || '';\n\n if (mime.startsWith('image/') || ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'ico'].includes(ext)) return 'image';\n if (mime.startsWith('video/') || ['mp4', 'webm', 'avi', 'mov', 'mkv'].includes(ext)) return 'video';\n if (mime.startsWith('audio/') || ['mp3', 'wav', 'flac', 'aac', 'ogg', 'm4a'].includes(ext)) return 'audio';\n if (['js', 'ts', 'tsx', 'jsx', 'py', 'rs', 'go', 'java', 'c', 'cpp', 'h', 'css', 'html', 'json', 'xml', 'yaml', 'yml', 'toml', 'sh', 'bash', 'sql'].includes(ext)) return 'code';\n if (['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'md', 'rtf', 'csv'].includes(ext)) return 'document';\n if (['zip', 'tar', 'gz', 'bz2', 'rar', '7z', 'xz'].includes(ext)) return 'archive';\n\n return 'generic';\n}\n\n// --- Main component ---\n\nexport const FileIcon: React.FC<FileIconProps> = ({\n entry,\n size = 'sm',\n className = '',\n}) => {\n const sizeClass = sizeMap[size];\n\n if (entry.type === 'folder') {\n return <span className={className}><FolderIcon sizeClass={sizeClass} /></span>;\n }\n\n const category = getFileCategory(entry);\n\n const IconComponent = {\n image: ImageIcon,\n video: VideoIcon,\n audio: AudioIcon,\n code: CodeIcon,\n document: DocIcon,\n archive: ArchiveIcon,\n generic: GenericFileIcon,\n }[category] || GenericFileIcon;\n\n return <span className={className}><IconComponent sizeClass={sizeClass} /></span>;\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GridView.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/GridView.tsx"],"sourcesContent":["import React from 'react';\nimport { GridViewProps } from './types';\nimport { FileIcon } from './FileIcon';\nimport Button from '../../Button';\nimport { formatFileSize } from '../../FileUploader/DropZone';\n\nconst defaultLabels = {\n emptyFolder: 'This folder is empty',\n noResults: 'No files match your search',\n delete: 'Delete',\n rename: 'Rename',\n};\n\nconst TrashIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\" />\n </svg>\n);\n\nconst EditIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\" />\n </svg>\n);\n\nexport const GridView: React.FC<GridViewProps> = ({\n entries,\n onEntryClick,\n onEntryDoubleClick,\n onDelete,\n onRename,\n enableDelete = false,\n enableRename = false,\n labels: userLabels,\n className = '',\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n\n if (entries.length === 0) {\n return (\n <div className={`flex items-center justify-center py-16 opacity-50 text-sm ${className}`}>\n {labels.emptyFolder}\n </div>\n );\n }\n\n return (\n <div className={`grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-2 p-3 ${className}`}>\n {entries.map(entry => (\n <div\n key={entry.path}\n className=\"relative group flex flex-col items-center p-3 rounded-xl hover:bg-base-200/60 cursor-pointer transition-colors min-h-[100px]\"\n onClick={() => onEntryClick(entry)}\n onDoubleClick={() => onEntryDoubleClick(entry)}\n >\n {/* Thumbnail or icon */}\n {entry.thumbnail ? (\n <div className=\"w-12 h-12 rounded-lg overflow-hidden bg-base-200 flex items-center justify-center mb-2\">\n <img\n src={entry.thumbnail}\n alt={entry.name}\n className=\"w-full h-full object-cover\"\n />\n </div>\n ) : (\n <div className=\"mb-2\">\n <FileIcon entry={entry} size=\"lg\" />\n </div>\n )}\n\n {/* Name */}\n <span className={`text-xs text-center truncate w-full ${entry.type === 'folder' ? 'font-medium' : ''}`} title={entry.name}>\n {entry.name}\n </span>\n\n {/* Size for files */}\n {entry.type === 'file' && entry.size != null && (\n <span className=\"text-[10px] opacity-40 mt-0.5\">\n {formatFileSize(entry.size)}\n </span>\n )}\n\n {/* Hover actions */}\n {(enableDelete || enableRename) && (\n <div className=\"absolute top-1 right-1 flex gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity\">\n {enableRename && onRename && (\n <span onClick={(e) => e.stopPropagation()}>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n onClick={() => onRename(entry)}\n >\n <EditIcon />\n </Button>\n </span>\n )}\n {enableDelete && onDelete && (\n <span onClick={(e) => e.stopPropagation()}>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n className=\"text-error\"\n onClick={() => onDelete(entry)}\n >\n <TrashIcon />\n </Button>\n </span>\n )}\n </div>\n )}\n </div>\n ))}\n </div>\n );\n};\n"],"mappings":";;;;;AAMA,IAAM,IAAgB;AAAA,EAClB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AACZ,GAEM,IAAA,MACF,gBAAA,EAAC,OAAD;AAAA,EAAK,OAAM;AAAA,EAA6B,WAAU;AAAA,EAAc,MAAK;AAAA,EAAO,SAAQ;AAAA,EAAY,QAAO;AAAA,EAAe,aAAa;AAAA,
|
|
1
|
+
{"version":3,"file":"GridView.js","names":[],"sources":["../../../../src/components/pro/FileExplorer/GridView.tsx"],"sourcesContent":["import React from 'react';\nimport { GridViewProps } from './types';\nimport { FileIcon } from './FileIcon';\nimport Button from '../../Button';\nimport { formatFileSize } from '../../FileUploader/DropZone';\n\nconst defaultLabels = {\n emptyFolder: 'This folder is empty',\n noResults: 'No files match your search',\n delete: 'Delete',\n rename: 'Rename',\n};\n\nconst TrashIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\" />\n </svg>\n);\n\nconst EditIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\" />\n </svg>\n);\n\nexport const GridView: React.FC<GridViewProps> = ({\n entries,\n onEntryClick,\n onEntryDoubleClick,\n onDelete,\n onRename,\n enableDelete = false,\n enableRename = false,\n labels: userLabels,\n className = '',\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n\n if (entries.length === 0) {\n return (\n <div className={`flex items-center justify-center py-16 opacity-50 text-sm ${className}`}>\n {labels.emptyFolder}\n </div>\n );\n }\n\n return (\n <div className={`grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-2 p-3 ${className}`}>\n {entries.map(entry => (\n <div\n key={entry.path}\n className=\"relative group flex flex-col items-center p-3 rounded-xl hover:bg-base-200/60 cursor-pointer transition-colors min-h-[100px]\"\n onClick={() => onEntryClick(entry)}\n onDoubleClick={() => onEntryDoubleClick(entry)}\n >\n {/* Thumbnail or icon */}\n {entry.thumbnail ? (\n <div className=\"w-12 h-12 rounded-lg overflow-hidden bg-base-200 flex items-center justify-center mb-2\">\n <img\n src={entry.thumbnail}\n alt={entry.name}\n className=\"w-full h-full object-cover\"\n />\n </div>\n ) : (\n <div className=\"mb-2\">\n <FileIcon entry={entry} size=\"lg\" />\n </div>\n )}\n\n {/* Name */}\n <span className={`text-xs text-center truncate w-full ${entry.type === 'folder' ? 'font-medium' : ''}`} title={entry.name}>\n {entry.name}\n </span>\n\n {/* Size for files */}\n {entry.type === 'file' && entry.size != null && (\n <span className=\"text-[10px] opacity-40 mt-0.5\">\n {formatFileSize(entry.size)}\n </span>\n )}\n\n {/* Hover actions */}\n {(enableDelete || enableRename) && (\n <div className=\"absolute top-1 right-1 flex gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity\">\n {enableRename && onRename && (\n <span onClick={(e) => e.stopPropagation()}>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n onClick={() => onRename(entry)}\n >\n <EditIcon />\n </Button>\n </span>\n )}\n {enableDelete && onDelete && (\n <span onClick={(e) => e.stopPropagation()}>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n className=\"text-error\"\n onClick={() => onDelete(entry)}\n >\n <TrashIcon />\n </Button>\n </span>\n )}\n </div>\n )}\n </div>\n ))}\n </div>\n );\n};\n"],"mappings":";;;;;AAMA,IAAM,IAAgB;AAAA,EAClB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AACZ,GAEM,IAAA,MACF,gBAAA,EAAC,OAAD;AAAA,EAAK,OAAM;AAAA,EAA6B,WAAU;AAAA,EAAc,MAAK;AAAA,EAAO,SAAQ;AAAA,EAAY,QAAO;AAAA,EAAe,aAAa;AAAA,EAC/H,UAAA,gBAAA,EAAC,QAAD;AAAA,IAAM,eAAc;AAAA,IAAQ,gBAAe;AAAA,IAAQ,GAAE;AAAA,EAAgI,CAAA;AACpL,CAAA,GAGH,IAAA,MACF,gBAAA,EAAC,OAAD;AAAA,EAAK,OAAM;AAAA,EAA6B,WAAU;AAAA,EAAc,MAAK;AAAA,EAAO,SAAQ;AAAA,EAAY,QAAO;AAAA,EAAe,aAAa;AAAA,EAC/H,UAAA,gBAAA,EAAC,QAAD;AAAA,IAAM,eAAc;AAAA,IAAQ,gBAAe;AAAA,IAAQ,GAAE;AAAA,EAA0H,CAAA;AAC9K,CAAA,GAGI,IAAA,CAAqC,EAC9C,SAAA,GACA,cAAA,GACA,oBAAA,GACA,UAAA,GACA,UAAA,GACA,cAAA,IAAe,IACf,cAAA,IAAe,IACf,QAAQ,GACR,WAAA,IAAY,GAAA,MACV;AACF,QAAM,IAAS;AAAA,IAAE,GAAG;AAAA,IAAe,GAAG;AAAA,EAAW;AAEjD,SAAI,EAAQ,WAAW,IAEf,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,6DAA6D,CAAA;AAAA,IACxE,UAAA,EAAO;AAAA,EACP,CAAA,IAKT,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,2EAA2E,CAAA;AAAA,IACtF,UAAA,EAAQ,IAAA,CAAI,MACT,gBAAA,EAAC,OAAD;AAAA,MAEI,WAAU;AAAA,MACV,SAAA,MAAe,EAAa,CAAK;AAAA,MACjC,eAAA,MAAqB,EAAmB,CAAK;AAAA,MAJjD,UAAA;AAAA,QAOK,EAAM,YACH,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UACX,UAAA,gBAAA,EAAC,OAAD;AAAA,YACI,KAAK,EAAM;AAAA,YACX,KAAK,EAAM;AAAA,YACX,WAAU;AAAA,UACb,CAAA;AAAA,QACA,CAAA,IAEL,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UACX,UAAA,gBAAA,EAAC,GAAD;AAAA,YAAiB,OAAA;AAAA,YAAO,MAAK;AAAA,UAAM,CAAA;AAAA,QAClC,CAAA;AAAA,QAIT,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAW,uCAAuC,EAAM,SAAS,WAAW,gBAAgB,EAAA;AAAA,UAAM,OAAO,EAAM;AAAA,UAChH,UAAA,EAAM;AAAA,QACL,CAAA;AAAA,QAGL,EAAM,SAAS,UAAU,EAAM,QAAQ,QACpC,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAU;AAAA,UACX,UAAA,EAAe,EAAM,IAAI;AAAA,QACxB,CAAA;AAAA,SAIR,KAAgB,MACd,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAf,UAAA,CACK,KAAgB,KACb,gBAAA,EAAC,QAAD;AAAA,YAAM,SAAA,CAAU,MAAM,EAAE,gBAAgB;AAAA,YACpC,UAAA,gBAAA,EAAC,GAAD;AAAA,cACI,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAA;AAAA,cACA,SAAA,MAAe,EAAS,CAAK;AAAA,cAE7B,UAAA,gBAAA,EAAC,GAAD,CAAW,CAAA;AAAA,YACP,CAAA;AAAA,UACN,CAAA,GAET,KAAgB,KACb,gBAAA,EAAC,QAAD;AAAA,YAAM,SAAA,CAAU,MAAM,EAAE,gBAAgB;AAAA,YACpC,UAAA,gBAAA,EAAC,GAAD;AAAA,cACI,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAA;AAAA,cACA,WAAU;AAAA,cACV,SAAA,MAAe,EAAS,CAAK;AAAA,cAE7B,UAAA,gBAAA,EAAC,GAAD,CAAY,CAAA;AAAA,YACR,CAAA;AAAA,UACN,CAAA,CAET;AAAA;MAER;AAAA,IA9DI,GAAA,EAAM,IA8DV,CACR;AAAA,EACA,CAAA;AAEb"}
|