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
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/react/donate.ts
|
|
2
|
+
var DEFAULT_DONATE_URL = "https://ko-fi.com/notoofly_manu";
|
|
3
|
+
var DEFAULT_DONATE_LABEL = "☕ Donate";
|
|
4
|
+
var globalDonate = { enabled: true, url: DEFAULT_DONATE_URL, label: DEFAULT_DONATE_LABEL };
|
|
5
|
+
function setGlobalDonate(enabled) {
|
|
6
|
+
globalDonate = { enabled: enabled !== false, url: DEFAULT_DONATE_URL, label: DEFAULT_DONATE_LABEL };
|
|
7
|
+
}
|
|
8
|
+
function getGlobalDonate() {
|
|
9
|
+
return globalDonate;
|
|
10
|
+
}
|
|
11
|
+
function resolveDonateProp(prop) {
|
|
12
|
+
if (prop === false)
|
|
13
|
+
return { enabled: false, url: DEFAULT_DONATE_URL, label: DEFAULT_DONATE_LABEL };
|
|
14
|
+
if (prop === true || prop === undefined)
|
|
15
|
+
return getGlobalDonate();
|
|
16
|
+
return getGlobalDonate();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { setGlobalDonate, resolveDonateProp };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/react/donate.ts
|
|
2
|
+
var DEFAULT_DONATE_URL = "https://ko-fi.com/notoofly_manu";
|
|
3
|
+
var DEFAULT_DONATE_LABEL = "☕ Donate";
|
|
4
|
+
var globalDonate = { enabled: true, url: DEFAULT_DONATE_URL, label: DEFAULT_DONATE_LABEL };
|
|
5
|
+
function setGlobalDonate(cfg) {
|
|
6
|
+
if (cfg === false) {
|
|
7
|
+
globalDonate = { enabled: false, url: DEFAULT_DONATE_URL, label: DEFAULT_DONATE_LABEL };
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (!cfg) {
|
|
11
|
+
globalDonate = { enabled: true, url: DEFAULT_DONATE_URL, label: DEFAULT_DONATE_LABEL };
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
globalDonate = {
|
|
15
|
+
enabled: cfg.enabled !== false,
|
|
16
|
+
url: cfg.url ?? DEFAULT_DONATE_URL,
|
|
17
|
+
label: cfg.label ?? DEFAULT_DONATE_LABEL
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function getGlobalDonate() {
|
|
21
|
+
return globalDonate;
|
|
22
|
+
}
|
|
23
|
+
function resolveDonateProp(prop) {
|
|
24
|
+
if (prop === false)
|
|
25
|
+
return { enabled: false, url: DEFAULT_DONATE_URL, label: DEFAULT_DONATE_LABEL };
|
|
26
|
+
if (prop === undefined)
|
|
27
|
+
return getGlobalDonate();
|
|
28
|
+
if (typeof prop === "object" && prop !== null) {
|
|
29
|
+
const base = getGlobalDonate();
|
|
30
|
+
return {
|
|
31
|
+
enabled: prop.enabled !== false,
|
|
32
|
+
url: prop.url ?? base.url,
|
|
33
|
+
label: prop.label ?? base.label
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return getGlobalDonate();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { setGlobalDonate, resolveDonateProp };
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// src/react/page/components/Breadcrumb.tsx
|
|
2
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
3
|
+
function Breadcrumb({ trail }) {
|
|
4
|
+
return /* @__PURE__ */ jsxDEV("nav", {
|
|
5
|
+
"aria-label": "Breadcrumb",
|
|
6
|
+
className: "pb-3 text-sm",
|
|
7
|
+
children: /* @__PURE__ */ jsxDEV("ol", {
|
|
8
|
+
className: "flex flex-wrap items-center gap-1.5",
|
|
9
|
+
children: trail.map((item, i) => {
|
|
10
|
+
const last = i === trail.length - 1;
|
|
11
|
+
return /* @__PURE__ */ jsxDEV("li", {
|
|
12
|
+
className: "flex items-center gap-1.5",
|
|
13
|
+
children: [
|
|
14
|
+
i > 0 ? /* @__PURE__ */ jsxDEV("span", {
|
|
15
|
+
"aria-hidden": "true",
|
|
16
|
+
className: "text-text-muted",
|
|
17
|
+
children: "/"
|
|
18
|
+
}, undefined, false, undefined, this) : null,
|
|
19
|
+
item.href && !last ? /* @__PURE__ */ jsxDEV("a", {
|
|
20
|
+
href: item.href,
|
|
21
|
+
className: "text-text-muted hover:text-foreground",
|
|
22
|
+
children: item.label
|
|
23
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV("span", {
|
|
24
|
+
"aria-current": last ? "page" : undefined,
|
|
25
|
+
className: last ? "text-foreground font-semibold" : "text-text-muted",
|
|
26
|
+
children: item.label
|
|
27
|
+
}, undefined, false, undefined, this)
|
|
28
|
+
]
|
|
29
|
+
}, `${item.label}-${i}`, true, undefined, this);
|
|
30
|
+
})
|
|
31
|
+
}, undefined, false, undefined, this)
|
|
32
|
+
}, undefined, false, undefined, this);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/react/page/components/Sidebar.tsx
|
|
36
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
37
|
+
function SidebarItemView({ item, depth = 0 }) {
|
|
38
|
+
const hasChildren = item.children && item.children.length > 0;
|
|
39
|
+
return /* @__PURE__ */ jsxDEV2("li", {
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ jsxDEV2("a", {
|
|
42
|
+
href: item.href,
|
|
43
|
+
"aria-current": item.active ? "page" : undefined,
|
|
44
|
+
className: item.active ? "bg-sidebar-primary text-sidebar-primary-foreground flex items-center gap-2 rounded-md px-2 py-1.5 text-sm font-semibold" : "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground flex items-center gap-2 rounded-md px-2 py-1.5 text-sm",
|
|
45
|
+
style: depth > 0 ? { paddingLeft: `${8 + depth * 12}px` } : undefined,
|
|
46
|
+
children: [
|
|
47
|
+
item.icon ? /* @__PURE__ */ jsxDEV2("span", {
|
|
48
|
+
"aria-hidden": "true",
|
|
49
|
+
children: item.icon
|
|
50
|
+
}, undefined, false, undefined, this) : null,
|
|
51
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
52
|
+
children: item.label
|
|
53
|
+
}, undefined, false, undefined, this)
|
|
54
|
+
]
|
|
55
|
+
}, undefined, true, undefined, this),
|
|
56
|
+
hasChildren ? /* @__PURE__ */ jsxDEV2("ul", {
|
|
57
|
+
className: "border-sidebar-border mt-0.5 ml-2 flex flex-col gap-0.5 border-l py-1 pl-2",
|
|
58
|
+
children: item.children.map((child) => /* @__PURE__ */ jsxDEV2(SidebarItemView, {
|
|
59
|
+
item: child,
|
|
60
|
+
depth: depth + 1
|
|
61
|
+
}, child.id, false, undefined, this))
|
|
62
|
+
}, undefined, false, undefined, this) : null
|
|
63
|
+
]
|
|
64
|
+
}, undefined, true, undefined, this);
|
|
65
|
+
}
|
|
66
|
+
function hasActive(items) {
|
|
67
|
+
for (const it of items) {
|
|
68
|
+
if (it.active)
|
|
69
|
+
return true;
|
|
70
|
+
if (it.children && hasActive(it.children))
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
function Sidebar({ title, groups }) {
|
|
76
|
+
return /* @__PURE__ */ jsxDEV2("aside", {
|
|
77
|
+
className: "bg-sidebar text-sidebar-foreground border-sidebar-border min-h-0 w-64 shrink-0 overflow-y-auto rounded-lg border",
|
|
78
|
+
children: [
|
|
79
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
80
|
+
className: "border-sidebar-border border-b px-4 py-3",
|
|
81
|
+
children: /* @__PURE__ */ jsxDEV2("p", {
|
|
82
|
+
className: "font-koran text-xl font-black tracking-tight",
|
|
83
|
+
children: title
|
|
84
|
+
}, undefined, false, undefined, this)
|
|
85
|
+
}, undefined, false, undefined, this),
|
|
86
|
+
/* @__PURE__ */ jsxDEV2("nav", {
|
|
87
|
+
className: "flex flex-col gap-4 p-3",
|
|
88
|
+
children: groups.map((group) => /* @__PURE__ */ jsxDEV2("section", {
|
|
89
|
+
children: /* @__PURE__ */ jsxDEV2("details", {
|
|
90
|
+
className: "group",
|
|
91
|
+
open: hasActive(group.items) || undefined,
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ jsxDEV2("summary", {
|
|
94
|
+
className: "font-koran border-sidebar-border flex cursor-pointer list-none items-center justify-between border-b px-2 pb-1 text-base font-bold tracking-tight [&::-webkit-details-marker]:hidden",
|
|
95
|
+
children: [
|
|
96
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
97
|
+
children: group.name
|
|
98
|
+
}, undefined, false, undefined, this),
|
|
99
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
100
|
+
"aria-hidden": "true",
|
|
101
|
+
className: "text-text-muted text-xs transition group-open:rotate-180",
|
|
102
|
+
children: "▾"
|
|
103
|
+
}, undefined, false, undefined, this)
|
|
104
|
+
]
|
|
105
|
+
}, undefined, true, undefined, this),
|
|
106
|
+
/* @__PURE__ */ jsxDEV2("ul", {
|
|
107
|
+
className: "border-sidebar-border mt-1 ml-2 flex flex-col gap-0.5 border-l py-1 pl-2",
|
|
108
|
+
children: group.items.map((item) => /* @__PURE__ */ jsxDEV2(SidebarItemView, {
|
|
109
|
+
item
|
|
110
|
+
}, item.id, false, undefined, this))
|
|
111
|
+
}, undefined, false, undefined, this)
|
|
112
|
+
]
|
|
113
|
+
}, undefined, true, undefined, this)
|
|
114
|
+
}, group.name, false, undefined, this))
|
|
115
|
+
}, undefined, false, undefined, this)
|
|
116
|
+
]
|
|
117
|
+
}, undefined, true, undefined, this);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/react/page/components/Masthead.tsx
|
|
121
|
+
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
122
|
+
function Masthead({ title, group, resource, total }) {
|
|
123
|
+
const today = new Date().toLocaleDateString("en-US", {
|
|
124
|
+
weekday: "long",
|
|
125
|
+
day: "numeric",
|
|
126
|
+
month: "long",
|
|
127
|
+
year: "numeric"
|
|
128
|
+
});
|
|
129
|
+
return /* @__PURE__ */ jsxDEV3("header", {
|
|
130
|
+
className: "bg-header text-header-foreground",
|
|
131
|
+
children: [
|
|
132
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
133
|
+
className: "flex items-center justify-between gap-4 py-2 text-xs tracking-widest text-text-muted uppercase",
|
|
134
|
+
children: [
|
|
135
|
+
/* @__PURE__ */ jsxDEV3("span", {
|
|
136
|
+
children: today
|
|
137
|
+
}, undefined, false, undefined, this),
|
|
138
|
+
/* @__PURE__ */ jsxDEV3("span", {
|
|
139
|
+
className: "hidden sm:inline",
|
|
140
|
+
children: "Daily Edition"
|
|
141
|
+
}, undefined, false, undefined, this),
|
|
142
|
+
/* @__PURE__ */ jsxDEV3("button", {
|
|
143
|
+
id: "koran-theme-toggle",
|
|
144
|
+
type: "button",
|
|
145
|
+
className: "border-border hover:bg-navigation-hover rounded-full border px-3 py-1 tracking-widest uppercase",
|
|
146
|
+
children: "◐ Theme"
|
|
147
|
+
}, undefined, false, undefined, this)
|
|
148
|
+
]
|
|
149
|
+
}, undefined, true, undefined, this),
|
|
150
|
+
/* @__PURE__ */ jsxDEV3("h1", {
|
|
151
|
+
className: "font-koran py-2 text-center text-5xl font-black tracking-tight",
|
|
152
|
+
children: title
|
|
153
|
+
}, undefined, false, undefined, this),
|
|
154
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
155
|
+
className: "flex items-center justify-center gap-2 pb-3 text-sm text-text-muted",
|
|
156
|
+
children: [
|
|
157
|
+
group ? /* @__PURE__ */ jsxDEV3("span", {
|
|
158
|
+
className: "uppercase",
|
|
159
|
+
children: group
|
|
160
|
+
}, undefined, false, undefined, this) : null,
|
|
161
|
+
group && (resource || total !== undefined) ? /* @__PURE__ */ jsxDEV3("span", {
|
|
162
|
+
"aria-hidden": "true",
|
|
163
|
+
children: "·"
|
|
164
|
+
}, undefined, false, undefined, this) : null,
|
|
165
|
+
resource ? /* @__PURE__ */ jsxDEV3("span", {
|
|
166
|
+
className: "font-mono text-xs",
|
|
167
|
+
children: [
|
|
168
|
+
"/",
|
|
169
|
+
resource
|
|
170
|
+
]
|
|
171
|
+
}, undefined, true, undefined, this) : null,
|
|
172
|
+
total !== undefined ? /* @__PURE__ */ jsxDEV3("span", {
|
|
173
|
+
children: [
|
|
174
|
+
total,
|
|
175
|
+
" records"
|
|
176
|
+
]
|
|
177
|
+
}, undefined, true, undefined, this) : null
|
|
178
|
+
]
|
|
179
|
+
}, undefined, true, undefined, this),
|
|
180
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
181
|
+
className: "koran-rule-double"
|
|
182
|
+
}, undefined, false, undefined, this)
|
|
183
|
+
]
|
|
184
|
+
}, undefined, true, undefined, this);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export { Breadcrumb, Sidebar, Masthead };
|
package/dist/rack/dashboard.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface DashboardOptions {
|
|
|
6
6
|
title?: string;
|
|
7
7
|
/** React page registry key (default "/dashboard") */
|
|
8
8
|
pagePath?: string;
|
|
9
|
+
/** Donate badge — false to hide, true/undefined to show */
|
|
10
|
+
donate?: boolean;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
13
|
* Dashboard plugin — mounts `GET {path}` that renders
|
|
@@ -50,6 +52,7 @@ export declare function dashboard(options?: DashboardOptions): Elysia<"", {
|
|
|
50
52
|
path: string;
|
|
51
53
|
props: {
|
|
52
54
|
resource: string | undefined;
|
|
55
|
+
donate?: boolean | undefined;
|
|
53
56
|
name?: string | undefined;
|
|
54
57
|
};
|
|
55
58
|
};
|
package/dist/rack/index.js
CHANGED
|
@@ -1149,6 +1149,7 @@ function dashboard(options) {
|
|
|
1149
1149
|
path: pagePath,
|
|
1150
1150
|
props: {
|
|
1151
1151
|
...title !== undefined ? { name: title } : {},
|
|
1152
|
+
...options?.donate !== undefined ? { donate: options.donate } : {},
|
|
1152
1153
|
resource: typeof query.resource === "string" ? query.resource : undefined
|
|
1153
1154
|
}
|
|
1154
1155
|
}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const DEFAULT_DONATE_URL = "https://ko-fi.com/notoofly_manu";
|
|
2
|
+
export declare const DEFAULT_DONATE_LABEL = "\u2615 Donate";
|
|
3
|
+
export type ResolvedDonate = {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
url: string;
|
|
6
|
+
label: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function setGlobalDonate(enabled?: boolean): void;
|
|
9
|
+
export declare function getGlobalDonate(): ResolvedDonate;
|
|
10
|
+
export declare function resolveDonateProp(prop?: boolean): ResolvedDonate;
|
package/dist/react/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
setGlobalDonate
|
|
3
|
+
} from "../index-6v0ns1xn.js";
|
|
1
4
|
import {
|
|
2
5
|
__require
|
|
3
6
|
} from "../index-37x76zdn.js";
|
|
@@ -152,8 +155,8 @@ function page(path, props) {
|
|
|
152
155
|
};
|
|
153
156
|
}
|
|
154
157
|
var pages = {
|
|
155
|
-
"/dashboard": () => import("../Dashboard-
|
|
156
|
-
"/panel": () => import("../Panel-
|
|
158
|
+
"/dashboard": () => import("../Dashboard-7gmx8c9y.js"),
|
|
159
|
+
"/panel": () => import("../Panel-wjxjtbmr.js")
|
|
157
160
|
};
|
|
158
161
|
var defaultPages = pages;
|
|
159
162
|
function mergeRegistries(base, extra) {
|
|
@@ -163,6 +166,7 @@ function mergeRegistries(base, extra) {
|
|
|
163
166
|
return list.reduce((acc, r) => ({ ...acc, ...r }), { ...base });
|
|
164
167
|
}
|
|
165
168
|
function reactPlugin(options = {}) {
|
|
169
|
+
setGlobalDonate(options.donate);
|
|
166
170
|
const registry = mergeRegistries(defaultPages, options.pages);
|
|
167
171
|
const render = createRenderer(registry);
|
|
168
172
|
const panelCssOverride = pickPanelCssOption(options);
|
package/dist/react/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elysia-rack",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Model-driven CRUD rack for Elysia: REST + QUERY routes, validation, authorization, OpenAPI metadata, and React panel rendering.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -81,5 +81,9 @@
|
|
|
81
81
|
"react": "^19.2.8",
|
|
82
82
|
"react-dom": "^19.2.8",
|
|
83
83
|
"typescript": "^5"
|
|
84
|
+
},
|
|
85
|
+
"funding": {
|
|
86
|
+
"type": "ko-fi",
|
|
87
|
+
"url": "https://ko-fi.com/notoofly_manu"
|
|
84
88
|
}
|
|
85
89
|
}
|