elysia-rack 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/Dashboard-0da8dvbv.js +225 -0
- package/dist/Dashboard-7gmx8c9y.js +248 -0
- package/dist/Dashboard-xkh2g9f7.js +248 -0
- package/dist/Panel-n0kstkyw.js +735 -0
- package/dist/Panel-wjxjtbmr.js +753 -0
- package/dist/Panel-za4av616.js +753 -0
- package/dist/index-6v0ns1xn.js +19 -0
- package/dist/index-h3zbq796.js +39 -0
- package/dist/index-xsfqad54.js +187 -0
- package/dist/rack/dashboard.d.ts +3 -0
- package/dist/rack/index.js +1 -0
- package/dist/react/donate.d.ts +10 -0
- package/dist/react/index.js +6 -2
- package/dist/react/page/Dashboard.d.ts +2 -0
- package/dist/react/page/Panel.d.ts +1 -0
- package/dist/react/types.d.ts +5 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# elysia-rack
|
|
2
2
|
|
|
3
|
+
[](https://ko-fi.com/notoofly_manu) [](https://www.npmjs.com/package/elysia-rack)
|
|
4
|
+
|
|
3
5
|
Model-driven CRUD rack for [Elysia](https://elysiajs.com): declare a resource once, get REST + `QUERY` routes, validation, authorization, query engine, OpenAPI metadata, and a React panel — running on [Bun](https://bun.com) or Node.js 20+.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
@@ -180,6 +182,9 @@ rack("/catalog/variants", { metadata: { id: "variants", parent: "products", grou
|
|
|
180
182
|
|
|
181
183
|
Helpers: `listRacks()`, `getRack(id)`, `getRackTree()`, `flatRackTree()`, `buildRackTree(racks)`, `clearRacks()` from `elysia-rack`.
|
|
182
184
|
|
|
185
|
+
### Donate — disable on website
|
|
186
|
+
Donate link (Ko-fi) tampil di Dashboard & Panel footer. Disable via `dashboard({ donate: false })` atau global `reactPlugin({ donate: false })` (default `true`).
|
|
187
|
+
|
|
183
188
|
You can still render the dashboard manually:
|
|
184
189
|
|
|
185
190
|
```ts
|
|
@@ -442,6 +447,16 @@ bun run typecheck # tsc --noEmit
|
|
|
442
447
|
bun run build # dist/ (js via bun build + .d.ts via tsc)
|
|
443
448
|
```
|
|
444
449
|
|
|
450
|
+
## Donate
|
|
451
|
+
|
|
452
|
+
Support pengembangan elysia-rack — traktir kopi via Ko-fi:
|
|
453
|
+
|
|
454
|
+
[](https://ko-fi.com/notoofly_manu)
|
|
455
|
+
|
|
456
|
+
> https://ko-fi.com/notoofly_manu
|
|
457
|
+
|
|
458
|
+
Terima kasih sudah mendukung open-source!
|
|
459
|
+
|
|
445
460
|
## License
|
|
446
461
|
|
|
447
462
|
MIT © notoofly
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Breadcrumb,
|
|
3
|
+
Masthead,
|
|
4
|
+
Sidebar
|
|
5
|
+
} from "./index-xsfqad54.js";
|
|
6
|
+
import {
|
|
7
|
+
getRackTree
|
|
8
|
+
} from "./index-4wxvmd8a.js";
|
|
9
|
+
import"./index-37x76zdn.js";
|
|
10
|
+
|
|
11
|
+
// src/react/page/Dashboard.tsx
|
|
12
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
13
|
+
function itemLabel(r) {
|
|
14
|
+
return r.metadata.pluralLabel ?? r.metadata.label ?? r.metadata.id;
|
|
15
|
+
}
|
|
16
|
+
function toSidebarItem(node, activeId) {
|
|
17
|
+
return {
|
|
18
|
+
id: node.metadata.id,
|
|
19
|
+
label: itemLabel(node),
|
|
20
|
+
icon: node.metadata.icon,
|
|
21
|
+
href: node.path,
|
|
22
|
+
active: node.metadata.id === activeId,
|
|
23
|
+
children: node.children.filter((c) => !c.metadata.hidden).map((c) => toSidebarItem(c, activeId))
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function buildGroupsFromTree(tree, activeId) {
|
|
27
|
+
const byGroup = new Map;
|
|
28
|
+
for (const root of tree) {
|
|
29
|
+
if (root.metadata.hidden)
|
|
30
|
+
continue;
|
|
31
|
+
const name = root.metadata.group ?? "General";
|
|
32
|
+
let group = byGroup.get(name);
|
|
33
|
+
if (!group) {
|
|
34
|
+
group = { name, items: [] };
|
|
35
|
+
byGroup.set(name, group);
|
|
36
|
+
}
|
|
37
|
+
group.items.push(toSidebarItem(root, activeId));
|
|
38
|
+
}
|
|
39
|
+
return [...byGroup.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
40
|
+
}
|
|
41
|
+
async function Dashboard(props) {
|
|
42
|
+
const tree = getRackTree().filter((r) => !r.metadata.hidden);
|
|
43
|
+
const groups = buildGroupsFromTree(tree, props.resource);
|
|
44
|
+
const totalResources = tree.length + tree.reduce((a, n) => a + n.children.length, 0);
|
|
45
|
+
const totalGroups = groups.length;
|
|
46
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
47
|
+
className: "koran-paper font-koran-body text-foreground flex min-h-screen flex-col",
|
|
48
|
+
children: /* @__PURE__ */ jsxDEV("div", {
|
|
49
|
+
className: "flex flex-1 gap-6 p-4 sm:p-6",
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ jsxDEV(Sidebar, {
|
|
52
|
+
title: props.name ?? "Panel",
|
|
53
|
+
groups
|
|
54
|
+
}, undefined, false, undefined, this),
|
|
55
|
+
/* @__PURE__ */ jsxDEV("main", {
|
|
56
|
+
className: "flex min-w-0 flex-1 flex-col",
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsxDEV(Breadcrumb, {
|
|
59
|
+
trail: [{ label: "Dashboard" }]
|
|
60
|
+
}, undefined, false, undefined, this),
|
|
61
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
62
|
+
className: "mx-auto w-full max-w-5xl px-4 pb-10 sm:px-6",
|
|
63
|
+
children: [
|
|
64
|
+
/* @__PURE__ */ jsxDEV(Masthead, {
|
|
65
|
+
title: props.name ?? "ERP Demo",
|
|
66
|
+
group: "Dashboard",
|
|
67
|
+
resource: "dashboard",
|
|
68
|
+
total: totalResources
|
|
69
|
+
}, undefined, false, undefined, this),
|
|
70
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
71
|
+
className: "grid grid-cols-2 gap-3 pb-6 lg:grid-cols-4",
|
|
72
|
+
children: [
|
|
73
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
74
|
+
className: "bg-card border-border rounded-lg border px-4 py-3",
|
|
75
|
+
children: [
|
|
76
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
77
|
+
className: "text-text-muted text-xs font-semibold tracking-widest uppercase",
|
|
78
|
+
children: "Resources"
|
|
79
|
+
}, undefined, false, undefined, this),
|
|
80
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
81
|
+
className: "font-koran text-2xl font-black",
|
|
82
|
+
children: totalResources
|
|
83
|
+
}, undefined, false, undefined, this),
|
|
84
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
85
|
+
className: "text-text-muted text-xs",
|
|
86
|
+
children: [
|
|
87
|
+
totalGroups,
|
|
88
|
+
" groups"
|
|
89
|
+
]
|
|
90
|
+
}, undefined, true, undefined, this)
|
|
91
|
+
]
|
|
92
|
+
}, undefined, true, undefined, this),
|
|
93
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
94
|
+
className: "bg-card border-border rounded-lg border px-4 py-3",
|
|
95
|
+
children: [
|
|
96
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
97
|
+
className: "text-text-muted text-xs font-semibold tracking-widest uppercase",
|
|
98
|
+
children: "Modules"
|
|
99
|
+
}, undefined, false, undefined, this),
|
|
100
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
101
|
+
className: "font-koran text-2xl font-black",
|
|
102
|
+
children: totalGroups
|
|
103
|
+
}, undefined, false, undefined, this),
|
|
104
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
105
|
+
className: "text-text-muted text-xs",
|
|
106
|
+
children: "Core → Governance"
|
|
107
|
+
}, undefined, false, undefined, this)
|
|
108
|
+
]
|
|
109
|
+
}, undefined, true, undefined, this),
|
|
110
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
111
|
+
className: "bg-card border-border rounded-lg border px-4 py-3",
|
|
112
|
+
children: [
|
|
113
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
114
|
+
className: "text-text-muted text-xs font-semibold tracking-widest uppercase",
|
|
115
|
+
children: "Status"
|
|
116
|
+
}, undefined, false, undefined, this),
|
|
117
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
118
|
+
className: "font-koran text-2xl font-black",
|
|
119
|
+
children: "Ready"
|
|
120
|
+
}, undefined, false, undefined, this),
|
|
121
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
122
|
+
className: "text-text-muted text-xs",
|
|
123
|
+
children: "PGlite in-memory"
|
|
124
|
+
}, undefined, false, undefined, this)
|
|
125
|
+
]
|
|
126
|
+
}, undefined, true, undefined, this),
|
|
127
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
128
|
+
className: "bg-card border-border rounded-lg border px-4 py-3",
|
|
129
|
+
children: [
|
|
130
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
131
|
+
className: "text-text-muted text-xs font-semibold tracking-widest uppercase",
|
|
132
|
+
children: "Tree"
|
|
133
|
+
}, undefined, false, undefined, this),
|
|
134
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
135
|
+
className: "font-koran text-2xl font-black",
|
|
136
|
+
children: tree.length
|
|
137
|
+
}, undefined, false, undefined, this),
|
|
138
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
139
|
+
className: "text-text-muted text-xs",
|
|
140
|
+
children: "root nodes"
|
|
141
|
+
}, undefined, false, undefined, this)
|
|
142
|
+
]
|
|
143
|
+
}, undefined, true, undefined, this)
|
|
144
|
+
]
|
|
145
|
+
}, undefined, true, undefined, this),
|
|
146
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
147
|
+
className: "border-border bg-card rounded-lg border",
|
|
148
|
+
children: [
|
|
149
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
150
|
+
className: "border-border flex items-center justify-between border-b px-4 py-3",
|
|
151
|
+
children: [
|
|
152
|
+
/* @__PURE__ */ jsxDEV("h2", {
|
|
153
|
+
className: "text-sm font-semibold tracking-widest uppercase",
|
|
154
|
+
children: "Resource Tree"
|
|
155
|
+
}, undefined, false, undefined, this),
|
|
156
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
157
|
+
className: "text-text-muted text-xs",
|
|
158
|
+
children: [
|
|
159
|
+
totalResources,
|
|
160
|
+
" resources"
|
|
161
|
+
]
|
|
162
|
+
}, undefined, true, undefined, this)
|
|
163
|
+
]
|
|
164
|
+
}, undefined, true, undefined, this),
|
|
165
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
166
|
+
className: "divide-border divide-y",
|
|
167
|
+
children: [
|
|
168
|
+
groups.map((g) => /* @__PURE__ */ jsxDEV("div", {
|
|
169
|
+
className: "px-4 py-3",
|
|
170
|
+
children: [
|
|
171
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
172
|
+
className: "text-xs font-semibold tracking-widest uppercase text-form-label",
|
|
173
|
+
children: g.name
|
|
174
|
+
}, undefined, false, undefined, this),
|
|
175
|
+
/* @__PURE__ */ jsxDEV("ul", {
|
|
176
|
+
className: "mt-2 flex flex-wrap gap-2",
|
|
177
|
+
children: g.items.map((it) => /* @__PURE__ */ jsxDEV("li", {
|
|
178
|
+
children: [
|
|
179
|
+
/* @__PURE__ */ jsxDEV("a", {
|
|
180
|
+
href: it.href,
|
|
181
|
+
className: "bg-secondary text-secondary-foreground inline-flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs font-medium hover:underline",
|
|
182
|
+
children: [
|
|
183
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
184
|
+
children: it.icon ?? "•"
|
|
185
|
+
}, undefined, false, undefined, this),
|
|
186
|
+
" ",
|
|
187
|
+
it.label
|
|
188
|
+
]
|
|
189
|
+
}, undefined, true, undefined, this),
|
|
190
|
+
(it.children?.length ?? 0) > 0 && /* @__PURE__ */ jsxDEV("span", {
|
|
191
|
+
className: "text-text-muted ml-1 text-xs",
|
|
192
|
+
children: [
|
|
193
|
+
"+",
|
|
194
|
+
it.children?.length ?? 0,
|
|
195
|
+
" child"
|
|
196
|
+
]
|
|
197
|
+
}, undefined, true, undefined, this)
|
|
198
|
+
]
|
|
199
|
+
}, it.id, true, undefined, this))
|
|
200
|
+
}, undefined, false, undefined, this)
|
|
201
|
+
]
|
|
202
|
+
}, g.name, true, undefined, this)),
|
|
203
|
+
groups.length === 0 && /* @__PURE__ */ jsxDEV("p", {
|
|
204
|
+
className: "text-text-muted px-4 py-6 text-center text-sm",
|
|
205
|
+
children: "Belum ada resource terdaftar — pastikan rack() sudah dipanggil sebelum dashboard render."
|
|
206
|
+
}, undefined, false, undefined, this)
|
|
207
|
+
]
|
|
208
|
+
}, undefined, true, undefined, this)
|
|
209
|
+
]
|
|
210
|
+
}, undefined, true, undefined, this),
|
|
211
|
+
/* @__PURE__ */ jsxDEV("footer", {
|
|
212
|
+
className: "border-border text-text-muted mt-6 border-t pt-3 text-center text-xs tracking-widest uppercase",
|
|
213
|
+
children: "Printed by elysia-rack — ERP blueprint"
|
|
214
|
+
}, undefined, false, undefined, this)
|
|
215
|
+
]
|
|
216
|
+
}, undefined, true, undefined, this)
|
|
217
|
+
]
|
|
218
|
+
}, undefined, true, undefined, this)
|
|
219
|
+
]
|
|
220
|
+
}, undefined, true, undefined, this)
|
|
221
|
+
}, undefined, false, undefined, this);
|
|
222
|
+
}
|
|
223
|
+
export {
|
|
224
|
+
Dashboard as default
|
|
225
|
+
};
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Breadcrumb,
|
|
3
|
+
Masthead,
|
|
4
|
+
Sidebar
|
|
5
|
+
} from "./index-xsfqad54.js";
|
|
6
|
+
import {
|
|
7
|
+
getRackTree
|
|
8
|
+
} from "./index-4wxvmd8a.js";
|
|
9
|
+
import {
|
|
10
|
+
resolveDonateProp
|
|
11
|
+
} from "./index-6v0ns1xn.js";
|
|
12
|
+
import"./index-37x76zdn.js";
|
|
13
|
+
|
|
14
|
+
// src/react/page/Dashboard.tsx
|
|
15
|
+
import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
|
|
16
|
+
function itemLabel(r) {
|
|
17
|
+
return r.metadata.pluralLabel ?? r.metadata.label ?? r.metadata.id;
|
|
18
|
+
}
|
|
19
|
+
function toSidebarItem(node, activeId) {
|
|
20
|
+
return {
|
|
21
|
+
id: node.metadata.id,
|
|
22
|
+
label: itemLabel(node),
|
|
23
|
+
icon: node.metadata.icon,
|
|
24
|
+
href: node.path,
|
|
25
|
+
active: node.metadata.id === activeId,
|
|
26
|
+
children: node.children.filter((c) => !c.metadata.hidden).map((c) => toSidebarItem(c, activeId))
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function buildGroupsFromTree(tree, activeId) {
|
|
30
|
+
const byGroup = new Map;
|
|
31
|
+
for (const root of tree) {
|
|
32
|
+
if (root.metadata.hidden)
|
|
33
|
+
continue;
|
|
34
|
+
const name = root.metadata.group ?? "General";
|
|
35
|
+
let group = byGroup.get(name);
|
|
36
|
+
if (!group) {
|
|
37
|
+
group = { name, items: [] };
|
|
38
|
+
byGroup.set(name, group);
|
|
39
|
+
}
|
|
40
|
+
group.items.push(toSidebarItem(root, activeId));
|
|
41
|
+
}
|
|
42
|
+
return [...byGroup.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
43
|
+
}
|
|
44
|
+
async function Dashboard(props) {
|
|
45
|
+
const tree = getRackTree().filter((r) => !r.metadata.hidden);
|
|
46
|
+
const groups = buildGroupsFromTree(tree, props.resource);
|
|
47
|
+
const totalResources = tree.length + tree.reduce((a, n) => a + n.children.length, 0);
|
|
48
|
+
const totalGroups = groups.length;
|
|
49
|
+
const donate = resolveDonateProp(props.donate);
|
|
50
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
51
|
+
className: "koran-paper font-koran-body text-foreground flex min-h-screen flex-col",
|
|
52
|
+
children: /* @__PURE__ */ jsxDEV("div", {
|
|
53
|
+
className: "flex flex-1 gap-6 p-4 sm:p-6",
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ jsxDEV(Sidebar, {
|
|
56
|
+
title: props.name ?? "Panel",
|
|
57
|
+
groups
|
|
58
|
+
}, undefined, false, undefined, this),
|
|
59
|
+
/* @__PURE__ */ jsxDEV("main", {
|
|
60
|
+
className: "flex min-w-0 flex-1 flex-col",
|
|
61
|
+
children: [
|
|
62
|
+
/* @__PURE__ */ jsxDEV(Breadcrumb, {
|
|
63
|
+
trail: [{ label: "Dashboard" }]
|
|
64
|
+
}, undefined, false, undefined, this),
|
|
65
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
66
|
+
className: "mx-auto w-full max-w-5xl px-4 pb-10 sm:px-6",
|
|
67
|
+
children: [
|
|
68
|
+
/* @__PURE__ */ jsxDEV(Masthead, {
|
|
69
|
+
title: props.name ?? "ERP Demo",
|
|
70
|
+
group: "Dashboard",
|
|
71
|
+
resource: "dashboard",
|
|
72
|
+
total: totalResources
|
|
73
|
+
}, undefined, false, undefined, this),
|
|
74
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
75
|
+
className: "grid grid-cols-2 gap-3 pb-6 lg:grid-cols-4",
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
78
|
+
className: "bg-card border-border rounded-lg border px-4 py-3",
|
|
79
|
+
children: [
|
|
80
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
81
|
+
className: "text-text-muted text-xs font-semibold tracking-widest uppercase",
|
|
82
|
+
children: "Resources"
|
|
83
|
+
}, undefined, false, undefined, this),
|
|
84
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
85
|
+
className: "font-koran text-2xl font-black",
|
|
86
|
+
children: totalResources
|
|
87
|
+
}, undefined, false, undefined, this),
|
|
88
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
89
|
+
className: "text-text-muted text-xs",
|
|
90
|
+
children: [
|
|
91
|
+
totalGroups,
|
|
92
|
+
" groups"
|
|
93
|
+
]
|
|
94
|
+
}, undefined, true, undefined, this)
|
|
95
|
+
]
|
|
96
|
+
}, undefined, true, undefined, this),
|
|
97
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
98
|
+
className: "bg-card border-border rounded-lg border px-4 py-3",
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
101
|
+
className: "text-text-muted text-xs font-semibold tracking-widest uppercase",
|
|
102
|
+
children: "Modules"
|
|
103
|
+
}, undefined, false, undefined, this),
|
|
104
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
105
|
+
className: "font-koran text-2xl font-black",
|
|
106
|
+
children: totalGroups
|
|
107
|
+
}, undefined, false, undefined, this),
|
|
108
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
109
|
+
className: "text-text-muted text-xs",
|
|
110
|
+
children: "Core → Governance"
|
|
111
|
+
}, undefined, false, undefined, this)
|
|
112
|
+
]
|
|
113
|
+
}, undefined, true, undefined, this),
|
|
114
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
115
|
+
className: "bg-card border-border rounded-lg border px-4 py-3",
|
|
116
|
+
children: [
|
|
117
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
118
|
+
className: "text-text-muted text-xs font-semibold tracking-widest uppercase",
|
|
119
|
+
children: "Status"
|
|
120
|
+
}, undefined, false, undefined, this),
|
|
121
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
122
|
+
className: "font-koran text-2xl font-black",
|
|
123
|
+
children: "Ready"
|
|
124
|
+
}, undefined, false, undefined, this),
|
|
125
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
126
|
+
className: "text-text-muted text-xs",
|
|
127
|
+
children: "PGlite in-memory"
|
|
128
|
+
}, undefined, false, undefined, this)
|
|
129
|
+
]
|
|
130
|
+
}, undefined, true, undefined, this),
|
|
131
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
132
|
+
className: "bg-card border-border rounded-lg border px-4 py-3",
|
|
133
|
+
children: [
|
|
134
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
135
|
+
className: "text-text-muted text-xs font-semibold tracking-widest uppercase",
|
|
136
|
+
children: "Tree"
|
|
137
|
+
}, undefined, false, undefined, this),
|
|
138
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
139
|
+
className: "font-koran text-2xl font-black",
|
|
140
|
+
children: tree.length
|
|
141
|
+
}, undefined, false, undefined, this),
|
|
142
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
143
|
+
className: "text-text-muted text-xs",
|
|
144
|
+
children: "root nodes"
|
|
145
|
+
}, undefined, false, undefined, this)
|
|
146
|
+
]
|
|
147
|
+
}, undefined, true, undefined, this)
|
|
148
|
+
]
|
|
149
|
+
}, undefined, true, undefined, this),
|
|
150
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
151
|
+
className: "border-border bg-card rounded-lg border",
|
|
152
|
+
children: [
|
|
153
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
154
|
+
className: "border-border flex items-center justify-between border-b px-4 py-3",
|
|
155
|
+
children: [
|
|
156
|
+
/* @__PURE__ */ jsxDEV("h2", {
|
|
157
|
+
className: "text-sm font-semibold tracking-widest uppercase",
|
|
158
|
+
children: "Resource Tree"
|
|
159
|
+
}, undefined, false, undefined, this),
|
|
160
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
161
|
+
className: "text-text-muted text-xs",
|
|
162
|
+
children: [
|
|
163
|
+
totalResources,
|
|
164
|
+
" resources"
|
|
165
|
+
]
|
|
166
|
+
}, undefined, true, undefined, this)
|
|
167
|
+
]
|
|
168
|
+
}, undefined, true, undefined, this),
|
|
169
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
170
|
+
className: "divide-border divide-y",
|
|
171
|
+
children: [
|
|
172
|
+
groups.map((g) => /* @__PURE__ */ jsxDEV("div", {
|
|
173
|
+
className: "px-4 py-3",
|
|
174
|
+
children: [
|
|
175
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
176
|
+
className: "text-xs font-semibold tracking-widest uppercase text-form-label",
|
|
177
|
+
children: g.name
|
|
178
|
+
}, undefined, false, undefined, this),
|
|
179
|
+
/* @__PURE__ */ jsxDEV("ul", {
|
|
180
|
+
className: "mt-2 flex flex-wrap gap-2",
|
|
181
|
+
children: g.items.map((it) => /* @__PURE__ */ jsxDEV("li", {
|
|
182
|
+
children: [
|
|
183
|
+
/* @__PURE__ */ jsxDEV("a", {
|
|
184
|
+
href: it.href,
|
|
185
|
+
className: "bg-secondary text-secondary-foreground inline-flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs font-medium hover:underline",
|
|
186
|
+
children: [
|
|
187
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
188
|
+
children: it.icon ?? "•"
|
|
189
|
+
}, undefined, false, undefined, this),
|
|
190
|
+
" ",
|
|
191
|
+
it.label
|
|
192
|
+
]
|
|
193
|
+
}, undefined, true, undefined, this),
|
|
194
|
+
(it.children?.length ?? 0) > 0 && /* @__PURE__ */ jsxDEV("span", {
|
|
195
|
+
className: "text-text-muted ml-1 text-xs",
|
|
196
|
+
children: [
|
|
197
|
+
"+",
|
|
198
|
+
it.children?.length ?? 0,
|
|
199
|
+
" child"
|
|
200
|
+
]
|
|
201
|
+
}, undefined, true, undefined, this)
|
|
202
|
+
]
|
|
203
|
+
}, it.id, true, undefined, this))
|
|
204
|
+
}, undefined, false, undefined, this)
|
|
205
|
+
]
|
|
206
|
+
}, g.name, true, undefined, this)),
|
|
207
|
+
groups.length === 0 && /* @__PURE__ */ jsxDEV("p", {
|
|
208
|
+
className: "text-text-muted px-4 py-6 text-center text-sm",
|
|
209
|
+
children: "Belum ada resource terdaftar — pastikan rack() sudah dipanggil sebelum dashboard render."
|
|
210
|
+
}, undefined, false, undefined, this)
|
|
211
|
+
]
|
|
212
|
+
}, undefined, true, undefined, this)
|
|
213
|
+
]
|
|
214
|
+
}, undefined, true, undefined, this),
|
|
215
|
+
/* @__PURE__ */ jsxDEV("footer", {
|
|
216
|
+
className: "border-border text-text-muted mt-6 border-t pt-3 text-center text-xs tracking-widest uppercase",
|
|
217
|
+
children: [
|
|
218
|
+
donate.enabled ? /* @__PURE__ */ jsxDEV(Fragment, {
|
|
219
|
+
children: [
|
|
220
|
+
/* @__PURE__ */ jsxDEV("a", {
|
|
221
|
+
href: donate.url,
|
|
222
|
+
target: "_blank",
|
|
223
|
+
rel: "noopener noreferrer",
|
|
224
|
+
className: "hover:text-foreground underline decoration-dotted underline-offset-4",
|
|
225
|
+
children: [
|
|
226
|
+
donate.label,
|
|
227
|
+
" — ",
|
|
228
|
+
donate.url.replace("https://", "")
|
|
229
|
+
]
|
|
230
|
+
}, undefined, true, undefined, this),
|
|
231
|
+
" ·",
|
|
232
|
+
" "
|
|
233
|
+
]
|
|
234
|
+
}, undefined, true, undefined, this) : null,
|
|
235
|
+
"Printed by elysia-rack — ERP blueprint"
|
|
236
|
+
]
|
|
237
|
+
}, undefined, true, undefined, this)
|
|
238
|
+
]
|
|
239
|
+
}, undefined, true, undefined, this)
|
|
240
|
+
]
|
|
241
|
+
}, undefined, true, undefined, this)
|
|
242
|
+
]
|
|
243
|
+
}, undefined, true, undefined, this)
|
|
244
|
+
}, undefined, false, undefined, this);
|
|
245
|
+
}
|
|
246
|
+
export {
|
|
247
|
+
Dashboard as default
|
|
248
|
+
};
|