elysia-rack 0.1.1 → 0.1.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 +74 -24
- package/dist/Dashboard-2j561p7c.js +225 -0
- package/dist/Dashboard-5mt9hnbw.js +252 -0
- package/dist/app.html +14 -0
- package/dist/index-4wxvmd8a.js +65 -0
- package/dist/index-tgk4jt4d.js +63 -0
- package/dist/panel.css +1 -1
- package/dist/rack/dashboard.d.ts +71 -0
- package/dist/rack/index.d.ts +2 -1
- package/dist/rack/index.js +27 -3
- package/dist/rack/registry.d.ts +16 -0
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +133 -13
- package/dist/react/page/components/Sidebar.d.ts +1 -0
- package/dist/react/types.d.ts +14 -0
- package/package.json +4 -9
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// src/rack/registry.ts
|
|
2
|
+
var registrations = new Map;
|
|
3
|
+
function registerRack(reg) {
|
|
4
|
+
registrations.set(reg.path, reg);
|
|
5
|
+
}
|
|
6
|
+
function listRacks() {
|
|
7
|
+
return [...registrations.values()];
|
|
8
|
+
}
|
|
9
|
+
function getRack(id) {
|
|
10
|
+
for (const r of registrations.values())
|
|
11
|
+
if (r.metadata.id === id)
|
|
12
|
+
return r;
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
function sortTreeNodes(list) {
|
|
16
|
+
list.sort((a, b) => {
|
|
17
|
+
const orderA = a.metadata.order ?? 0;
|
|
18
|
+
const orderB = b.metadata.order ?? 0;
|
|
19
|
+
if (orderA !== orderB)
|
|
20
|
+
return orderA - orderB;
|
|
21
|
+
const labelA = a.metadata.pluralLabel ?? a.metadata.label ?? a.metadata.id;
|
|
22
|
+
const labelB = b.metadata.pluralLabel ?? b.metadata.label ?? b.metadata.id;
|
|
23
|
+
return labelA.localeCompare(labelB);
|
|
24
|
+
});
|
|
25
|
+
for (const n of list)
|
|
26
|
+
if (n.children.length)
|
|
27
|
+
sortTreeNodes(n.children);
|
|
28
|
+
}
|
|
29
|
+
function buildRackTree(racks) {
|
|
30
|
+
const nodes = new Map;
|
|
31
|
+
for (const r of racks)
|
|
32
|
+
nodes.set(r.metadata.id, { ...r, children: [] });
|
|
33
|
+
const roots = [];
|
|
34
|
+
for (const node of nodes.values()) {
|
|
35
|
+
const parentId = node.metadata.parent;
|
|
36
|
+
if (parentId && nodes.has(parentId) && parentId !== node.metadata.id) {
|
|
37
|
+
nodes.get(parentId).children.push(node);
|
|
38
|
+
} else {
|
|
39
|
+
roots.push(node);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
sortTreeNodes(roots);
|
|
43
|
+
return roots;
|
|
44
|
+
}
|
|
45
|
+
function getRackTree() {
|
|
46
|
+
return buildRackTree([...registrations.values()]);
|
|
47
|
+
}
|
|
48
|
+
function flatRackTree(tree = getRackTree()) {
|
|
49
|
+
const out = [];
|
|
50
|
+
const walk = (nodes) => {
|
|
51
|
+
for (const n of nodes) {
|
|
52
|
+
const { children, ...rest } = n;
|
|
53
|
+
out.push(rest);
|
|
54
|
+
if (children.length)
|
|
55
|
+
walk(children);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
walk(tree);
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
function clearRacks() {
|
|
62
|
+
registrations.clear();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { registerRack, listRacks, getRack, buildRackTree, getRackTree, flatRackTree, clearRacks };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// src/rack/registry.ts
|
|
2
|
+
var registrations = new Map;
|
|
3
|
+
function registerRack(reg) {
|
|
4
|
+
registrations.set(reg.path, reg);
|
|
5
|
+
}
|
|
6
|
+
function listRacks() {
|
|
7
|
+
return [...registrations.values()];
|
|
8
|
+
}
|
|
9
|
+
function getRack(id) {
|
|
10
|
+
for (const r of registrations.values())
|
|
11
|
+
if (r.metadata.id === id)
|
|
12
|
+
return r;
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
function getRackTree() {
|
|
16
|
+
const nodes = new Map;
|
|
17
|
+
for (const r of registrations.values()) {
|
|
18
|
+
nodes.set(r.metadata.id, { ...r, children: [] });
|
|
19
|
+
}
|
|
20
|
+
const roots = [];
|
|
21
|
+
for (const node of nodes.values()) {
|
|
22
|
+
const parentId = node.metadata.parent;
|
|
23
|
+
if (parentId && nodes.has(parentId) && parentId !== node.metadata.id) {
|
|
24
|
+
nodes.get(parentId).children.push(node);
|
|
25
|
+
} else {
|
|
26
|
+
roots.push(node);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const sortNodes = (list) => {
|
|
30
|
+
list.sort((a, b) => {
|
|
31
|
+
const orderA = a.metadata.order ?? 0;
|
|
32
|
+
const orderB = b.metadata.order ?? 0;
|
|
33
|
+
if (orderA !== orderB)
|
|
34
|
+
return orderA - orderB;
|
|
35
|
+
const labelA = a.metadata.pluralLabel ?? a.metadata.label ?? a.metadata.id;
|
|
36
|
+
const labelB = b.metadata.pluralLabel ?? b.metadata.label ?? b.metadata.id;
|
|
37
|
+
return labelA.localeCompare(labelB);
|
|
38
|
+
});
|
|
39
|
+
for (const n of list)
|
|
40
|
+
if (n.children.length)
|
|
41
|
+
sortNodes(n.children);
|
|
42
|
+
};
|
|
43
|
+
sortNodes(roots);
|
|
44
|
+
return roots;
|
|
45
|
+
}
|
|
46
|
+
function flatRackTree(tree = getRackTree()) {
|
|
47
|
+
const out = [];
|
|
48
|
+
const walk = (nodes) => {
|
|
49
|
+
for (const n of nodes) {
|
|
50
|
+
const { children, ...rest } = n;
|
|
51
|
+
out.push(rest);
|
|
52
|
+
if (children.length)
|
|
53
|
+
walk(children);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
walk(tree);
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
function clearRacks() {
|
|
60
|
+
registrations.clear();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { registerRack, listRacks, getRack, getRackTree, flatRackTree, clearRacks };
|
package/dist/panel.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@import "https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,500;0,700;0,900;1,500&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,600;1,8..60,400&display=swap";@layer components;@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-normal:400;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-black:900;--tracking-tight:-.025em;--tracking-wider:.05em;--tracking-widest:.1em;--radius-xs:var(--radius-xs);--radius-sm:var(--radius-sm);--radius-md:var(--radius-md);--radius-lg:var(--radius-lg);--radius-xl:var(--radius-xl);--radius-2xl:var(--radius-2xl);--radius-3xl:var(--radius-3xl);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius-full:var(--radius-full);--font-koran:"Playfair Display", Georgia, "Times New Roman", serif;--font-koran-body:"Source Serif 4", Georgia, "Times New Roman", serif}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}body{background-color:var(--background);color:var(--foreground)}::selection{background-color:var(--selection);color:var(--selection-foreground)}:focus-visible{outline:2px solid var(--focus);outline-offset:2px}}@layer utilities{.visible{visibility:visible}.mx-auto{margin-inline:auto}.mt-1{margin-top:var(--spacing)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-4{height:calc(var(--spacing) * 4)}.h-full{height:100%}.min-h-0{min-height:0}.min-h-screen{min-height:100vh}.w-4{width:calc(var(--spacing) * 4)}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.max-w-5xl{max-width:var(--container-5xl)}.min-w-0{min-width:0}.min-w-80{min-width:calc(var(--spacing) * 80)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.cursor-pointer{cursor:pointer}.list-none{list-style-type:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:var(--radius-full)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-border{border-color:var(--border)}.border-input{border-color:var(--input)}.border-sidebar-border{border-color:var(--sidebar-border)}.border-table-border{border-color:var(--table-border)}.bg-background{background-color:var(--background)}.bg-badge-background{background-color:var(--badge-background)}.bg-card{background-color:var(--card)}.bg-destructive{background-color:var(--destructive)}.bg-header{background-color:var(--header)}.bg-input-background{background-color:var(--input-background)}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-sidebar{background-color:var(--sidebar)}.bg-sidebar-primary{background-color:var(--sidebar-primary)}.bg-success-muted{background-color:var(--success-muted)}.bg-table{background-color:var(--table-background)}.bg-table-header{background-color:var(--table-header)}.bg-table-row-hover{background-color:var(--table-row-hover)}.bg-warning-muted{background-color:var(--warning-muted)}.p-0{padding:0}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-10{padding-block:calc(var(--spacing) * 10)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pb-1{padding-bottom:var(--spacing)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-10{padding-bottom:calc(var(--spacing) * 10)}.pl-2{padding-left:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-koran{font-family:var(--font-koran)}.font-koran-body{font-family:var(--font-koran-body)}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.whitespace-nowrap{white-space:nowrap}.text-badge-foreground{color:var(--badge-foreground)}.text-card-foreground{color:var(--card-foreground)}.text-destructive{color:var(--destructive)}.text-destructive-foreground{color:var(--destructive-foreground)}.text-foreground{color:var(--foreground)}.text-form-error{color:var(--form-error)}.text-form-label{color:var(--form-label)}.text-header-foreground{color:var(--header-foreground)}.text-link{color:var(--link)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-sidebar-foreground{color:var(--sidebar-foreground)}.text-sidebar-primary-foreground{color:var(--sidebar-primary-foreground)}.text-success-muted-foreground{color:var(--success-muted-foreground)}.text-text-disabled{color:var(--text-disabled)}.text-text-muted{color:var(--text-muted)}.text-warning-muted-foreground{color:var(--warning-muted-foreground)}.normal-case{text-transform:none}.uppercase{text-transform:uppercase}.underline{text-decoration-line:underline}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.group-open\:rotate-180:is(:where(.group):is([open],:popover-open,:open) *){rotate:180deg}.placeholder\:text-form-placeholder::placeholder{color:var(--form-placeholder)}@media (hover:hover){.hover\:bg-navigation-hover:hover{background-color:var(--navigation-hover)}.hover\:bg-sidebar-accent:hover{background-color:var(--sidebar-accent)}.hover\:bg-table-row-hover:hover{background-color:var(--table-row-hover)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-link-hover:hover{color:var(--link-hover)}.hover\:text-sidebar-accent-foreground:hover{color:var(--sidebar-accent-foreground)}}@media (width>=40rem){.sm\:inline{display:inline}.sm\:p-6{padding:calc(var(--spacing) * 6)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}}.\[\&\:\:-webkit-details-marker\]\:hidden::-webkit-details-marker{display:none}}:root{--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--surface:oklch(100% 0 0);--surface-foreground:oklch(14.5% 0 0);--surface-muted:oklch(98.5% 0 0);--surface-muted-foreground:oklch(55.6% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--card-muted:oklch(98.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--overlay:oklch(14.5% 0 0/.5);--overlay-foreground:oklch(100% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--destructive-foreground:oklch(98.5% 0 0);--success:oklch(59.6% .145 163.225);--success-foreground:oklch(98.5% 0 0);--success-muted:oklch(96.2% .044 156.743);--success-muted-foreground:oklch(44.8% .119 151.328);--warning:oklch(68.1% .162 75.834);--warning-foreground:oklch(20.5% 0 0);--warning-muted:oklch(98.7% .026 102.212);--warning-muted-foreground:oklch(47.6% .114 61.907);--info:oklch(62.3% .214 259.815);--info-foreground:oklch(98.5% 0 0);--info-muted:oklch(97% .014 254.604);--info-muted-foreground:oklch(48.8% .217 264.376);--border:oklch(92.2% 0 0);--border-muted:oklch(96% 0 0);--input:oklch(92.2% 0 0);--input-background:oklch(100% 0 0);--ring:oklch(70.8% 0 0);--focus:oklch(62.3% .214 259.815);--text:oklch(14.5% 0 0);--text-muted:oklch(55.6% 0 0);--text-subtle:oklch(70.8% 0 0);--text-disabled:oklch(70.8% 0 0);--text-inverse:oklch(98.5% 0 0);--selection:oklch(20.5% 0 0);--selection-foreground:oklch(98.5% 0 0);--link:oklch(48.8% .243 264.376);--link-hover:oklch(42.4% .199 265.638);--link-visited:oklch(48.8% .243 264.376);--table-background:oklch(100% 0 0);--table-header:oklch(98.5% 0 0);--table-row:oklch(100% 0 0);--table-row-hover:oklch(98.5% 0 0);--table-row-selected:oklch(97% 0 0);--table-border:oklch(92.2% 0 0);--form-label:oklch(20.5% 0 0);--form-description:oklch(55.6% 0 0);--form-placeholder:oklch(70.8% 0 0);--form-error:oklch(57.7% .245 27.325);--form-success:oklch(59.6% .145 163.225);--navigation-background:oklch(100% 0 0);--navigation-foreground:oklch(14.5% 0 0);--navigation-hover:oklch(97% 0 0);--navigation-active:oklch(97% 0 0);--navigation-active-foreground:oklch(20.5% 0 0);--navigation-border:oklch(92.2% 0 0);--sidebar:oklch(98.5% 0 0);--sidebar-foreground:oklch(14.5% 0 0);--sidebar-primary:oklch(20.5% 0 0);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(97% 0 0);--sidebar-accent-foreground:oklch(20.5% 0 0);--sidebar-muted:oklch(55.6% 0 0);--sidebar-border:oklch(92.2% 0 0);--sidebar-ring:oklch(70.8% 0 0);--header:oklch(100% 0 0);--header-foreground:oklch(14.5% 0 0);--header-border:oklch(92.2% 0 0);--breadcrumb-foreground:oklch(55.6% 0 0);--breadcrumb-current:oklch(14.5% 0 0);--breadcrumb-separator:oklch(70.8% 0 0);--badge-background:oklch(97% 0 0);--badge-foreground:oklch(20.5% 0 0);--code-background:oklch(97% 0 0);--code-foreground:oklch(20.5% 0 0);--chart-1:oklch(64.6% .222 41.116);--chart-2:oklch(60% .118 184.704);--chart-3:oklch(39.8% .07 227.392);--chart-4:oklch(82.8% .189 84.429);--chart-5:oklch(76.9% .188 70.08);--radius:.625rem;--radius-xs:calc(var(--radius) - 6px);--radius-sm:calc(var(--radius) - 4px);--radius-md:calc(var(--radius) - 2px);--radius-lg:var(--radius);--radius-xl:calc(var(--radius) + 4px);--radius-2xl:calc(var(--radius) + 8px);--radius-3xl:calc(var(--radius) + 12px);--radius-full:9999px}.dark{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--surface:oklch(20.5% 0 0);--surface-foreground:oklch(98.5% 0 0);--surface-muted:oklch(18% 0 0);--surface-muted-foreground:oklch(70.8% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--card-muted:oklch(26.9% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--overlay:oklch(0% 0 0/.65);--overlay-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--destructive-foreground:oklch(98.5% 0 0);--success:oklch(69.6% .17 162.48);--success-foreground:oklch(14.5% 0 0);--success-muted:oklch(26.9% .07 156.743);--success-muted-foreground:oklch(76.5% .13 152.461);--warning:oklch(76.9% .188 70.08);--warning-foreground:oklch(20.5% 0 0);--warning-muted:oklch(26.9% .06 85);--warning-muted-foreground:oklch(82.8% .15 84);--info:oklch(70.7% .165 254.624);--info-foreground:oklch(14.5% 0 0);--info-muted:oklch(26.9% .06 255);--info-muted-foreground:oklch(70.7% .165 254.624);--border:oklch(100% 0 0/.1);--border-muted:oklch(100% 0 0/.06);--input:oklch(100% 0 0/.15);--input-background:oklch(20.5% 0 0);--ring:oklch(55.6% 0 0);--focus:oklch(70.7% .165 254.624);--text:oklch(98.5% 0 0);--text-muted:oklch(70.8% 0 0);--text-subtle:oklch(55.6% 0 0);--text-disabled:oklch(55.6% 0 0);--text-inverse:oklch(14.5% 0 0);--selection:oklch(92.2% 0 0);--selection-foreground:oklch(20.5% 0 0);--link:oklch(70.7% .165 254.624);--link-hover:oklch(80.9% .105 251.813);--link-visited:oklch(70.7% .165 254.624);--table-background:oklch(20.5% 0 0);--table-header:oklch(18% 0 0);--table-row:oklch(20.5% 0 0);--table-row-hover:oklch(26.9% 0 0);--table-row-selected:oklch(26.9% 0 0);--table-border:oklch(100% 0 0/.1);--form-label:oklch(98.5% 0 0);--form-description:oklch(70.8% 0 0);--form-placeholder:oklch(55.6% 0 0);--form-error:oklch(70.4% .191 22.216);--form-success:oklch(69.6% .17 162.48);--navigation-background:oklch(20.5% 0 0);--navigation-foreground:oklch(98.5% 0 0);--navigation-hover:oklch(26.9% 0 0);--navigation-active:oklch(26.9% 0 0);--navigation-active-foreground:oklch(98.5% 0 0);--navigation-border:oklch(100% 0 0/.1);--sidebar:oklch(20.5% 0 0);--sidebar-foreground:oklch(98.5% 0 0);--sidebar-primary:oklch(48.8% .243 264.376);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(26.9% 0 0);--sidebar-accent-foreground:oklch(98.5% 0 0);--sidebar-muted:oklch(70.8% 0 0);--sidebar-border:oklch(100% 0 0/.1);--sidebar-ring:oklch(55.6% 0 0);--header:oklch(20.5% 0 0);--header-foreground:oklch(98.5% 0 0);--header-border:oklch(100% 0 0/.1);--breadcrumb-foreground:oklch(70.8% 0 0);--breadcrumb-current:oklch(98.5% 0 0);--breadcrumb-separator:oklch(55.6% 0 0);--badge-background:oklch(26.9% 0 0);--badge-foreground:oklch(98.5% 0 0);--code-background:oklch(26.9% 0 0);--code-foreground:oklch(98.5% 0 0);--chart-1:oklch(48.8% .243 264.376);--chart-2:oklch(69.6% .17 162.48);--chart-3:oklch(76.9% .188 70.08);--chart-4:oklch(62.7% .265 303.9);--chart-5:oklch(64.5% .246 16.439)}:root{--background:#f5f0e2;--foreground:#1c1610;--surface:#f5f0e2;--surface-foreground:#1c1610;--surface-muted:#ece4d0;--surface-muted-foreground:#6f6250;--card:#faf6ea;--card-foreground:#1c1610;--card-muted:#ece4d0;--popover:#faf6ea;--popover-foreground:#1c1610;--primary:#1c1610;--primary-foreground:#f5f0e2;--secondary:#e9e0c8;--secondary-foreground:#1c1610;--muted:#e9e0c8;--muted-foreground:#6f6250;--accent:#e9e0c8;--accent-foreground:#1c1610;--border:#d8cdae;--border-muted:#e4dabd;--input:#c9bc9c;--input-background:#faf6ea;--ring:#6f6250;--text:#1c1610;--text-muted:#6f6250;--text-subtle:#a2937a;--text-disabled:#a2937a;--text-inverse:#f5f0e2;--selection:#1c1610;--selection-foreground:#f5f0e2;--link:#9b1c1c;--link-hover:#7c1616;--link-visited:#9b1c1c;--table-background:#faf6ea;--table-header:#ece4d0;--table-row:#faf6ea;--table-row-hover:#f1e9d2;--table-row-selected:#e9e0c8;--table-border:#d8cdae;--form-label:#1c1610;--form-description:#6f6250;--form-placeholder:#a2937a;--navigation-background:#f5f0e2;--navigation-foreground:#1c1610;--navigation-hover:#e9e0c8;--navigation-active:#e9e0c8;--navigation-active-foreground:#1c1610;--navigation-border:#d8cdae;--sidebar:#ece4d0;--sidebar-foreground:#1c1610;--sidebar-primary:#1c1610;--sidebar-primary-foreground:#f5f0e2;--sidebar-accent:#e9e0c8;--sidebar-accent-foreground:#1c1610;--sidebar-muted:#6f6250;--sidebar-border:#d8cdae;--sidebar-ring:#6f6250;--header:#f5f0e2;--header-foreground:#1c1610;--header-border:#1c1610;--breadcrumb-foreground:#6f6250;--breadcrumb-current:#1c1610;--breadcrumb-separator:#a2937a;--badge-background:#e9e0c8;--badge-foreground:#1c1610;--code-background:#ece4d0;--code-foreground:#1c1610}.dark{--background:#181310;--foreground:#ece1c8;--surface:#211a13;--surface-foreground:#ece1c8;--surface-muted:#241d15;--surface-muted-foreground:#a49378;--card:#211a13;--card-foreground:#ece1c8;--card-muted:#2a2118;--popover:#211a13;--popover-foreground:#ece1c8;--primary:#ece1c8;--primary-foreground:#181310;--secondary:#2a2118;--secondary-foreground:#ece1c8;--muted:#2a2118;--muted-foreground:#a49378;--accent:#2a2118;--accent-foreground:#ece1c8;--border:#3a2f22;--border-muted:#2a2118;--input:#4a3d2c;--input-background:#211a13;--ring:#a49378;--text:#ece1c8;--text-muted:#a49378;--text-subtle:#6f6250;--text-disabled:#6f6250;--text-inverse:#181310;--selection:#ece1c8;--selection-foreground:#181310;--link:#e06552;--link-hover:#ef8267;--link-visited:#e06552;--table-background:#211a13;--table-header:#181310;--table-row:#211a13;--table-row-hover:#2a2118;--table-row-selected:#2a2118;--table-border:#3a2f22;--form-label:#ece1c8;--form-description:#a49378;--form-placeholder:#6f6250;--navigation-background:#181310;--navigation-foreground:#ece1c8;--navigation-hover:#2a2118;--navigation-active:#2a2118;--navigation-active-foreground:#ece1c8;--navigation-border:#3a2f22;--sidebar:#211a13;--sidebar-foreground:#ece1c8;--sidebar-primary:#ece1c8;--sidebar-primary-foreground:#181310;--sidebar-accent:#2a2118;--sidebar-accent-foreground:#ece1c8;--sidebar-muted:#a49378;--sidebar-border:#3a2f22;--sidebar-ring:#a49378;--header:#181310;--header-foreground:#ece1c8;--header-border:#ece1c8;--breadcrumb-foreground:#a49378;--breadcrumb-current:#ece1c8;--breadcrumb-separator:#6f6250;--badge-background:#2a2118;--badge-foreground:#ece1c8;--code-background:#2a2118;--code-foreground:#ece1c8}dialog{max-width:min(32rem,100vw - 2rem);max-height:calc(100vh - 2rem);margin:auto}dialog::backdrop{background-color:var(--overlay)}.koran-rule-double{border-top:1px solid var(--header-border);position:relative}.koran-rule-double:after{content:"";border-top:3px solid var(--header-border);margin-top:2px;display:block}.koran-paper{background-color:var(--background);background-image:radial-gradient(at top,#ffffff59,#0000 60%)}.dark .koran-paper{background-image:radial-gradient(at top,#ffffff0d,#0000 60%)}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
|
|
1
|
+
@import "https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,500;0,700;0,900;1,500&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,600;1,8..60,400&display=swap";@layer components;@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-normal:400;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-black:900;--tracking-tight:-.025em;--tracking-wider:.05em;--tracking-widest:.1em;--radius-xs:var(--radius-xs);--radius-sm:var(--radius-sm);--radius-md:var(--radius-md);--radius-lg:var(--radius-lg);--radius-xl:var(--radius-xl);--radius-2xl:var(--radius-2xl);--radius-3xl:var(--radius-3xl);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-primary:var(--primary);--radius-full:var(--radius-full);--font-koran:"Playfair Display", Georgia, "Times New Roman", serif;--font-koran-body:"Source Serif 4", Georgia, "Times New Roman", serif}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}body{background-color:var(--background);color:var(--foreground)}::selection{background-color:var(--selection);color:var(--selection-foreground)}:focus-visible{outline:2px solid var(--focus);outline-offset:2px}}@layer utilities{.visible{visibility:visible}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-4{height:calc(var(--spacing) * 4)}.h-full{height:100%}.min-h-0{min-height:0}.min-h-screen{min-height:100vh}.w-4{width:calc(var(--spacing) * 4)}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.max-w-5xl{max-width:var(--container-5xl)}.min-w-0{min-width:0}.min-w-80{min-width:calc(var(--spacing) * 80)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.cursor-pointer{cursor:pointer}.list-none{list-style-type:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:var(--radius-full)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-border{border-color:var(--border)}.border-input{border-color:var(--input)}.border-sidebar-border{border-color:var(--sidebar-border)}.border-table-border{border-color:var(--table-border)}.bg-background{background-color:var(--background)}.bg-badge-background{background-color:var(--badge-background)}.bg-card{background-color:var(--card)}.bg-destructive{background-color:var(--destructive)}.bg-header{background-color:var(--header)}.bg-input-background{background-color:var(--input-background)}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-sidebar{background-color:var(--sidebar)}.bg-sidebar-primary{background-color:var(--sidebar-primary)}.bg-success-muted{background-color:var(--success-muted)}.bg-table{background-color:var(--table-background)}.bg-table-header{background-color:var(--table-header)}.bg-table-row-hover{background-color:var(--table-row-hover)}.bg-warning-muted{background-color:var(--warning-muted)}.p-0{padding:0}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-10{padding-block:calc(var(--spacing) * 10)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pb-1{padding-bottom:var(--spacing)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-10{padding-bottom:calc(var(--spacing) * 10)}.pl-2{padding-left:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-koran{font-family:var(--font-koran)}.font-koran-body{font-family:var(--font-koran-body)}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.whitespace-nowrap{white-space:nowrap}.text-badge-foreground{color:var(--badge-foreground)}.text-card-foreground{color:var(--card-foreground)}.text-destructive{color:var(--destructive)}.text-destructive-foreground{color:var(--destructive-foreground)}.text-foreground{color:var(--foreground)}.text-form-error{color:var(--form-error)}.text-form-label{color:var(--form-label)}.text-header-foreground{color:var(--header-foreground)}.text-link{color:var(--link)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-sidebar-foreground{color:var(--sidebar-foreground)}.text-sidebar-primary-foreground{color:var(--sidebar-primary-foreground)}.text-success-muted-foreground{color:var(--success-muted-foreground)}.text-text-disabled{color:var(--text-disabled)}.text-text-muted{color:var(--text-muted)}.text-warning-muted-foreground{color:var(--warning-muted-foreground)}.normal-case{text-transform:none}.uppercase{text-transform:uppercase}.underline{text-decoration-line:underline}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.group-open\:rotate-180:is(:where(.group):is([open],:popover-open,:open) *){rotate:180deg}.placeholder\:text-form-placeholder::placeholder{color:var(--form-placeholder)}@media (hover:hover){.hover\:bg-navigation-hover:hover{background-color:var(--navigation-hover)}.hover\:bg-sidebar-accent:hover{background-color:var(--sidebar-accent)}.hover\:bg-table-row-hover:hover{background-color:var(--table-row-hover)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-link-hover:hover{color:var(--link-hover)}.hover\:text-sidebar-accent-foreground:hover{color:var(--sidebar-accent-foreground)}}@media (width>=40rem){.sm\:inline{display:inline}.sm\:p-6{padding:calc(var(--spacing) * 6)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}}.\[\&\:\:-webkit-details-marker\]\:hidden::-webkit-details-marker{display:none}}:root{--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--surface:oklch(100% 0 0);--surface-foreground:oklch(14.5% 0 0);--surface-muted:oklch(98.5% 0 0);--surface-muted-foreground:oklch(55.6% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--card-muted:oklch(98.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--overlay:oklch(14.5% 0 0/.5);--overlay-foreground:oklch(100% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--destructive-foreground:oklch(98.5% 0 0);--success:oklch(59.6% .145 163.225);--success-foreground:oklch(98.5% 0 0);--success-muted:oklch(96.2% .044 156.743);--success-muted-foreground:oklch(44.8% .119 151.328);--warning:oklch(68.1% .162 75.834);--warning-foreground:oklch(20.5% 0 0);--warning-muted:oklch(98.7% .026 102.212);--warning-muted-foreground:oklch(47.6% .114 61.907);--info:oklch(62.3% .214 259.815);--info-foreground:oklch(98.5% 0 0);--info-muted:oklch(97% .014 254.604);--info-muted-foreground:oklch(48.8% .217 264.376);--border:oklch(92.2% 0 0);--border-muted:oklch(96% 0 0);--input:oklch(92.2% 0 0);--input-background:oklch(100% 0 0);--ring:oklch(70.8% 0 0);--focus:oklch(62.3% .214 259.815);--text:oklch(14.5% 0 0);--text-muted:oklch(55.6% 0 0);--text-subtle:oklch(70.8% 0 0);--text-disabled:oklch(70.8% 0 0);--text-inverse:oklch(98.5% 0 0);--selection:oklch(20.5% 0 0);--selection-foreground:oklch(98.5% 0 0);--link:oklch(48.8% .243 264.376);--link-hover:oklch(42.4% .199 265.638);--link-visited:oklch(48.8% .243 264.376);--table-background:oklch(100% 0 0);--table-header:oklch(98.5% 0 0);--table-row:oklch(100% 0 0);--table-row-hover:oklch(98.5% 0 0);--table-row-selected:oklch(97% 0 0);--table-border:oklch(92.2% 0 0);--form-label:oklch(20.5% 0 0);--form-description:oklch(55.6% 0 0);--form-placeholder:oklch(70.8% 0 0);--form-error:oklch(57.7% .245 27.325);--form-success:oklch(59.6% .145 163.225);--navigation-background:oklch(100% 0 0);--navigation-foreground:oklch(14.5% 0 0);--navigation-hover:oklch(97% 0 0);--navigation-active:oklch(97% 0 0);--navigation-active-foreground:oklch(20.5% 0 0);--navigation-border:oklch(92.2% 0 0);--sidebar:oklch(98.5% 0 0);--sidebar-foreground:oklch(14.5% 0 0);--sidebar-primary:oklch(20.5% 0 0);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(97% 0 0);--sidebar-accent-foreground:oklch(20.5% 0 0);--sidebar-muted:oklch(55.6% 0 0);--sidebar-border:oklch(92.2% 0 0);--sidebar-ring:oklch(70.8% 0 0);--header:oklch(100% 0 0);--header-foreground:oklch(14.5% 0 0);--header-border:oklch(92.2% 0 0);--breadcrumb-foreground:oklch(55.6% 0 0);--breadcrumb-current:oklch(14.5% 0 0);--breadcrumb-separator:oklch(70.8% 0 0);--badge-background:oklch(97% 0 0);--badge-foreground:oklch(20.5% 0 0);--code-background:oklch(97% 0 0);--code-foreground:oklch(20.5% 0 0);--chart-1:oklch(64.6% .222 41.116);--chart-2:oklch(60% .118 184.704);--chart-3:oklch(39.8% .07 227.392);--chart-4:oklch(82.8% .189 84.429);--chart-5:oklch(76.9% .188 70.08);--radius:.625rem;--radius-xs:calc(var(--radius) - 6px);--radius-sm:calc(var(--radius) - 4px);--radius-md:calc(var(--radius) - 2px);--radius-lg:var(--radius);--radius-xl:calc(var(--radius) + 4px);--radius-2xl:calc(var(--radius) + 8px);--radius-3xl:calc(var(--radius) + 12px);--radius-full:9999px}.dark{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--surface:oklch(20.5% 0 0);--surface-foreground:oklch(98.5% 0 0);--surface-muted:oklch(18% 0 0);--surface-muted-foreground:oklch(70.8% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--card-muted:oklch(26.9% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--overlay:oklch(0% 0 0/.65);--overlay-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--destructive-foreground:oklch(98.5% 0 0);--success:oklch(69.6% .17 162.48);--success-foreground:oklch(14.5% 0 0);--success-muted:oklch(26.9% .07 156.743);--success-muted-foreground:oklch(76.5% .13 152.461);--warning:oklch(76.9% .188 70.08);--warning-foreground:oklch(20.5% 0 0);--warning-muted:oklch(26.9% .06 85);--warning-muted-foreground:oklch(82.8% .15 84);--info:oklch(70.7% .165 254.624);--info-foreground:oklch(14.5% 0 0);--info-muted:oklch(26.9% .06 255);--info-muted-foreground:oklch(70.7% .165 254.624);--border:oklch(100% 0 0/.1);--border-muted:oklch(100% 0 0/.06);--input:oklch(100% 0 0/.15);--input-background:oklch(20.5% 0 0);--ring:oklch(55.6% 0 0);--focus:oklch(70.7% .165 254.624);--text:oklch(98.5% 0 0);--text-muted:oklch(70.8% 0 0);--text-subtle:oklch(55.6% 0 0);--text-disabled:oklch(55.6% 0 0);--text-inverse:oklch(14.5% 0 0);--selection:oklch(92.2% 0 0);--selection-foreground:oklch(20.5% 0 0);--link:oklch(70.7% .165 254.624);--link-hover:oklch(80.9% .105 251.813);--link-visited:oklch(70.7% .165 254.624);--table-background:oklch(20.5% 0 0);--table-header:oklch(18% 0 0);--table-row:oklch(20.5% 0 0);--table-row-hover:oklch(26.9% 0 0);--table-row-selected:oklch(26.9% 0 0);--table-border:oklch(100% 0 0/.1);--form-label:oklch(98.5% 0 0);--form-description:oklch(70.8% 0 0);--form-placeholder:oklch(55.6% 0 0);--form-error:oklch(70.4% .191 22.216);--form-success:oklch(69.6% .17 162.48);--navigation-background:oklch(20.5% 0 0);--navigation-foreground:oklch(98.5% 0 0);--navigation-hover:oklch(26.9% 0 0);--navigation-active:oklch(26.9% 0 0);--navigation-active-foreground:oklch(98.5% 0 0);--navigation-border:oklch(100% 0 0/.1);--sidebar:oklch(20.5% 0 0);--sidebar-foreground:oklch(98.5% 0 0);--sidebar-primary:oklch(48.8% .243 264.376);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(26.9% 0 0);--sidebar-accent-foreground:oklch(98.5% 0 0);--sidebar-muted:oklch(70.8% 0 0);--sidebar-border:oklch(100% 0 0/.1);--sidebar-ring:oklch(55.6% 0 0);--header:oklch(20.5% 0 0);--header-foreground:oklch(98.5% 0 0);--header-border:oklch(100% 0 0/.1);--breadcrumb-foreground:oklch(70.8% 0 0);--breadcrumb-current:oklch(98.5% 0 0);--breadcrumb-separator:oklch(55.6% 0 0);--badge-background:oklch(26.9% 0 0);--badge-foreground:oklch(98.5% 0 0);--code-background:oklch(26.9% 0 0);--code-foreground:oklch(98.5% 0 0);--chart-1:oklch(48.8% .243 264.376);--chart-2:oklch(69.6% .17 162.48);--chart-3:oklch(76.9% .188 70.08);--chart-4:oklch(62.7% .265 303.9);--chart-5:oklch(64.5% .246 16.439)}:root{--background:#f5f0e2;--foreground:#1c1610;--surface:#f5f0e2;--surface-foreground:#1c1610;--surface-muted:#ece4d0;--surface-muted-foreground:#6f6250;--card:#faf6ea;--card-foreground:#1c1610;--card-muted:#ece4d0;--popover:#faf6ea;--popover-foreground:#1c1610;--primary:#1c1610;--primary-foreground:#f5f0e2;--secondary:#e9e0c8;--secondary-foreground:#1c1610;--muted:#e9e0c8;--muted-foreground:#6f6250;--accent:#e9e0c8;--accent-foreground:#1c1610;--border:#d8cdae;--border-muted:#e4dabd;--input:#c9bc9c;--input-background:#faf6ea;--ring:#6f6250;--text:#1c1610;--text-muted:#6f6250;--text-subtle:#a2937a;--text-disabled:#a2937a;--text-inverse:#f5f0e2;--selection:#1c1610;--selection-foreground:#f5f0e2;--link:#9b1c1c;--link-hover:#7c1616;--link-visited:#9b1c1c;--table-background:#faf6ea;--table-header:#ece4d0;--table-row:#faf6ea;--table-row-hover:#f1e9d2;--table-row-selected:#e9e0c8;--table-border:#d8cdae;--form-label:#1c1610;--form-description:#6f6250;--form-placeholder:#a2937a;--navigation-background:#f5f0e2;--navigation-foreground:#1c1610;--navigation-hover:#e9e0c8;--navigation-active:#e9e0c8;--navigation-active-foreground:#1c1610;--navigation-border:#d8cdae;--sidebar:#ece4d0;--sidebar-foreground:#1c1610;--sidebar-primary:#1c1610;--sidebar-primary-foreground:#f5f0e2;--sidebar-accent:#e9e0c8;--sidebar-accent-foreground:#1c1610;--sidebar-muted:#6f6250;--sidebar-border:#d8cdae;--sidebar-ring:#6f6250;--header:#f5f0e2;--header-foreground:#1c1610;--header-border:#1c1610;--breadcrumb-foreground:#6f6250;--breadcrumb-current:#1c1610;--breadcrumb-separator:#a2937a;--badge-background:#e9e0c8;--badge-foreground:#1c1610;--code-background:#ece4d0;--code-foreground:#1c1610}.dark{--background:#181310;--foreground:#ece1c8;--surface:#211a13;--surface-foreground:#ece1c8;--surface-muted:#241d15;--surface-muted-foreground:#a49378;--card:#211a13;--card-foreground:#ece1c8;--card-muted:#2a2118;--popover:#211a13;--popover-foreground:#ece1c8;--primary:#ece1c8;--primary-foreground:#181310;--secondary:#2a2118;--secondary-foreground:#ece1c8;--muted:#2a2118;--muted-foreground:#a49378;--accent:#2a2118;--accent-foreground:#ece1c8;--border:#3a2f22;--border-muted:#2a2118;--input:#4a3d2c;--input-background:#211a13;--ring:#a49378;--text:#ece1c8;--text-muted:#a49378;--text-subtle:#6f6250;--text-disabled:#6f6250;--text-inverse:#181310;--selection:#ece1c8;--selection-foreground:#181310;--link:#e06552;--link-hover:#ef8267;--link-visited:#e06552;--table-background:#211a13;--table-header:#181310;--table-row:#211a13;--table-row-hover:#2a2118;--table-row-selected:#2a2118;--table-border:#3a2f22;--form-label:#ece1c8;--form-description:#a49378;--form-placeholder:#6f6250;--navigation-background:#181310;--navigation-foreground:#ece1c8;--navigation-hover:#2a2118;--navigation-active:#2a2118;--navigation-active-foreground:#ece1c8;--navigation-border:#3a2f22;--sidebar:#211a13;--sidebar-foreground:#ece1c8;--sidebar-primary:#ece1c8;--sidebar-primary-foreground:#181310;--sidebar-accent:#2a2118;--sidebar-accent-foreground:#ece1c8;--sidebar-muted:#a49378;--sidebar-border:#3a2f22;--sidebar-ring:#a49378;--header:#181310;--header-foreground:#ece1c8;--header-border:#ece1c8;--breadcrumb-foreground:#a49378;--breadcrumb-current:#ece1c8;--breadcrumb-separator:#6f6250;--badge-background:#2a2118;--badge-foreground:#ece1c8;--code-background:#2a2118;--code-foreground:#ece1c8}dialog{max-width:min(32rem,100vw - 2rem);max-height:calc(100vh - 2rem);margin:auto}dialog::backdrop{background-color:var(--overlay)}.koran-rule-double{border-top:1px solid var(--header-border);position:relative}.koran-rule-double:after{content:"";border-top:3px solid var(--header-border);margin-top:2px;display:block}.koran-paper{background-color:var(--background);background-image:radial-gradient(at top,#ffffff59,#0000 60%)}.dark .koran-paper{background-image:radial-gradient(at top,#ffffff0d,#0000 60%)}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import Elysia from "elysia";
|
|
2
|
+
export interface DashboardOptions {
|
|
3
|
+
/** Mount path for the dashboard page (default "/") */
|
|
4
|
+
path?: string;
|
|
5
|
+
/** Dashboard title (default "Panel") */
|
|
6
|
+
title?: string;
|
|
7
|
+
/** React page registry key (default "/dashboard") */
|
|
8
|
+
pagePath?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Dashboard plugin — mounts `GET {path}` that renders
|
|
12
|
+
* `page("/dashboard")` via `reactPlugin`.
|
|
13
|
+
*
|
|
14
|
+
* Tree metadata is stored in memory by `rack()` (registry)
|
|
15
|
+
* and loaded when Dashboard renders via `getRackTree()`.
|
|
16
|
+
*
|
|
17
|
+
* Recommended setup:
|
|
18
|
+
* ```ts
|
|
19
|
+
* const app = new Elysia()
|
|
20
|
+
* .use(reactPlugin({ pages }))
|
|
21
|
+
* .use(dashboard({ title: "My Panel" }))
|
|
22
|
+
* .use(rack("/catalog/products", { model, metadata: { id: "products", group: "Catalog" } }))
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function dashboard(options?: DashboardOptions): Elysia<"", {
|
|
26
|
+
decorator: {};
|
|
27
|
+
store: {};
|
|
28
|
+
derive: {};
|
|
29
|
+
resolve: {};
|
|
30
|
+
}, {
|
|
31
|
+
typebox: {};
|
|
32
|
+
error: {};
|
|
33
|
+
}, {
|
|
34
|
+
schema: {};
|
|
35
|
+
standaloneSchema: {};
|
|
36
|
+
macro: {};
|
|
37
|
+
macroFn: {};
|
|
38
|
+
parser: {};
|
|
39
|
+
response: {};
|
|
40
|
+
}, {
|
|
41
|
+
[x: string]: {
|
|
42
|
+
get: {
|
|
43
|
+
body: unknown;
|
|
44
|
+
params: {};
|
|
45
|
+
query: unknown;
|
|
46
|
+
headers: unknown;
|
|
47
|
+
response: {
|
|
48
|
+
200: {
|
|
49
|
+
[x: symbol]: true;
|
|
50
|
+
path: string;
|
|
51
|
+
props: {
|
|
52
|
+
resource: string | undefined;
|
|
53
|
+
name?: string | undefined;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
}, {
|
|
60
|
+
derive: {};
|
|
61
|
+
resolve: {};
|
|
62
|
+
schema: {};
|
|
63
|
+
standaloneSchema: {};
|
|
64
|
+
response: {};
|
|
65
|
+
}, {
|
|
66
|
+
derive: {};
|
|
67
|
+
resolve: {};
|
|
68
|
+
schema: {};
|
|
69
|
+
standaloneSchema: {};
|
|
70
|
+
response: {};
|
|
71
|
+
}>;
|
package/dist/rack/index.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import Elysia from "elysia";
|
|
|
2
2
|
import type { Rack } from "./types";
|
|
3
3
|
export type { Rack } from "./types";
|
|
4
4
|
export type * from "./models";
|
|
5
|
-
export { clearRacks, listRacks, registerRack, type RackRegistration, } from "./registry";
|
|
5
|
+
export { buildRackTree, clearRacks, flatRackTree, getRack, getRackTree, listRacks, registerRack, type RackRegistration, type RackTreeNode, } from "./registry";
|
|
6
|
+
export { dashboard, type DashboardOptions } from "./dashboard";
|
|
6
7
|
export { resolveAdapter } from "./adapter";
|
|
7
8
|
export { getAdapter, drizzleAdapter, prismaAdapter, type AdapterOptions, type CrudAdapter, type FieldDescriptor, type FieldKind, type ListResult, } from "./adapters/index";
|
|
8
9
|
export { authorize, type AuthCheck } from "./authorization";
|
package/dist/rack/index.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
buildRackTree,
|
|
2
3
|
clearRacks,
|
|
4
|
+
flatRackTree,
|
|
5
|
+
getRack,
|
|
6
|
+
getRackTree,
|
|
3
7
|
listRacks,
|
|
4
8
|
registerRack
|
|
5
|
-
} from "../index-
|
|
9
|
+
} from "../index-4wxvmd8a.js";
|
|
6
10
|
import"../index-37x76zdn.js";
|
|
7
11
|
|
|
8
12
|
// src/rack/index.ts
|
|
9
|
-
import
|
|
13
|
+
import Elysia2, { status as status2 } from "elysia";
|
|
10
14
|
|
|
11
15
|
// src/rack/adapter.ts
|
|
12
16
|
function resolveAdapter(model) {
|
|
@@ -1122,6 +1126,21 @@ function parseListQuery(raw, queryOptions) {
|
|
|
1122
1126
|
}
|
|
1123
1127
|
return { search, filters, sort, page, limit };
|
|
1124
1128
|
}
|
|
1129
|
+
// src/rack/dashboard.ts
|
|
1130
|
+
import Elysia from "elysia";
|
|
1131
|
+
function dashboard(options) {
|
|
1132
|
+
const path = options?.path ?? "/";
|
|
1133
|
+
const pagePath = options?.pagePath ?? "/dashboard";
|
|
1134
|
+
const title = options?.title;
|
|
1135
|
+
return new Elysia({ name: "rack:dashboard" }).get(path, ({ query }) => ({
|
|
1136
|
+
[Symbol.for(PANEL_PAGE_KEY)]: true,
|
|
1137
|
+
path: pagePath,
|
|
1138
|
+
props: {
|
|
1139
|
+
...title !== undefined ? { name: title } : {},
|
|
1140
|
+
resource: typeof query.resource === "string" ? query.resource : undefined
|
|
1141
|
+
}
|
|
1142
|
+
}));
|
|
1143
|
+
}
|
|
1125
1144
|
|
|
1126
1145
|
// src/rack/index.ts
|
|
1127
1146
|
var DEFAULT_OPERATIONS = {
|
|
@@ -1150,7 +1169,7 @@ function rack(path, options) {
|
|
|
1150
1169
|
returning: options.settings?.returning,
|
|
1151
1170
|
softDelete: options.settings?.softDelete
|
|
1152
1171
|
};
|
|
1153
|
-
const app = new
|
|
1172
|
+
const app = new Elysia2({ name: `rack:${path}`, prefix: path });
|
|
1154
1173
|
const notFound = (operation, id) => status2(404, { error: "Not Found", operation, id });
|
|
1155
1174
|
const envelope = (operation) => ({
|
|
1156
1175
|
resource,
|
|
@@ -1352,11 +1371,16 @@ export {
|
|
|
1352
1371
|
parseListQuery,
|
|
1353
1372
|
panelPage,
|
|
1354
1373
|
listRacks,
|
|
1374
|
+
getRackTree,
|
|
1375
|
+
getRack,
|
|
1355
1376
|
getAdapter,
|
|
1377
|
+
flatRackTree,
|
|
1356
1378
|
drizzleAdapter,
|
|
1357
1379
|
detailFor,
|
|
1380
|
+
dashboard,
|
|
1358
1381
|
createMemoryIdempotencyStore,
|
|
1359
1382
|
clearRacks,
|
|
1383
|
+
buildRackTree,
|
|
1360
1384
|
authorize,
|
|
1361
1385
|
PANEL_PAGE_KEY
|
|
1362
1386
|
};
|
package/dist/rack/registry.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ export interface RackRegistration {
|
|
|
9
9
|
/** Resolved operations (all default `true`). */
|
|
10
10
|
operations: Required<Rack.CrudOperationsOptions>;
|
|
11
11
|
}
|
|
12
|
+
/** Tree node for sidebar/dashboard. Children are resources where `metadata.parent === node.metadata.id`. */
|
|
13
|
+
export interface RackTreeNode extends RackRegistration {
|
|
14
|
+
children: RackTreeNode[];
|
|
15
|
+
}
|
|
12
16
|
/**
|
|
13
17
|
* Register a rack resource. Called automatically by `rack()`.
|
|
14
18
|
* Re-registering the same path replaces the previous entry.
|
|
@@ -16,5 +20,17 @@ export interface RackRegistration {
|
|
|
16
20
|
export declare function registerRack(reg: RackRegistration): void;
|
|
17
21
|
/** List all registered rack resources in registration order. */
|
|
18
22
|
export declare function listRacks(): RackRegistration[];
|
|
23
|
+
/** Get a single registration by `metadata.id`. */
|
|
24
|
+
export declare function getRack(id: string): RackRegistration | undefined;
|
|
25
|
+
/** Build a tree from an explicit list (pure, reusable for props.racks). */
|
|
26
|
+
export declare function buildRackTree(racks: RackRegistration[]): RackTreeNode[];
|
|
27
|
+
/**
|
|
28
|
+
* Build a hierarchical tree from `parent` metadata.
|
|
29
|
+
* - Nodes without `parent` or with missing parent become roots.
|
|
30
|
+
* - Children are sorted by `order` then label.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getRackTree(): RackTreeNode[];
|
|
33
|
+
/** Flatten tree into a depth-first ordered list (useful for legacy dashboard). */
|
|
34
|
+
export declare function flatRackTree(tree?: RackTreeNode[]): RackRegistration[];
|
|
19
35
|
/** Clear the registry (mainly for tests). */
|
|
20
36
|
export declare function clearRacks(): void;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare function reactPlugin(options: ReactRack.ReactPluginOptions): Elys
|
|
|
33
33
|
headers: unknown;
|
|
34
34
|
response: {
|
|
35
35
|
200: Response;
|
|
36
|
-
404: "Panel asset not
|
|
36
|
+
404: "Panel asset not found";
|
|
37
37
|
422: {
|
|
38
38
|
type: "validation";
|
|
39
39
|
on: string;
|
package/dist/react/index.js
CHANGED
|
@@ -4,18 +4,66 @@ import {
|
|
|
4
4
|
|
|
5
5
|
// src/react/index.ts
|
|
6
6
|
import Elysia from "elysia";
|
|
7
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
8
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
9
|
+
import { join as join2 } from "node:path";
|
|
10
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
11
|
+
|
|
12
|
+
// src/react/render.tsx
|
|
7
13
|
import { existsSync } from "node:fs";
|
|
8
14
|
import { readFile } from "node:fs/promises";
|
|
9
15
|
import { join } from "node:path";
|
|
10
16
|
import { fileURLToPath } from "node:url";
|
|
11
|
-
|
|
12
|
-
// src/react/render.tsx
|
|
13
17
|
import { renderToReadableStream } from "react-dom/server";
|
|
14
18
|
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
15
19
|
function pageTitle(path, props) {
|
|
16
20
|
const metadata = props?.metadata;
|
|
17
21
|
return metadata?.pluralLabel ?? metadata?.label ?? path;
|
|
18
22
|
}
|
|
23
|
+
function escapeHtml(value) {
|
|
24
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25
|
+
}
|
|
26
|
+
var FALLBACK_TEMPLATE = `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>{{title}}</title><link rel="stylesheet" href="/__rack/panel.css"><script type="module" src="/__rack/panel-theme.js"></script><!--app-head--></head><body><!--app--></body></html>`;
|
|
27
|
+
var cachedTemplate = null;
|
|
28
|
+
async function loadTemplate() {
|
|
29
|
+
if (cachedTemplate !== null)
|
|
30
|
+
return cachedTemplate;
|
|
31
|
+
const candidates = [
|
|
32
|
+
join(fileURLToPath(new URL(".", import.meta.url)), "app.html"),
|
|
33
|
+
join(fileURLToPath(new URL(".", import.meta.url)), "..", "app.html"),
|
|
34
|
+
join(process.cwd(), "dist", "app.html"),
|
|
35
|
+
join(process.cwd(), "src", "react", "app.html")
|
|
36
|
+
];
|
|
37
|
+
for (const dir of [join(process.cwd(), "dist"), join(fileURLToPath(new URL(".", import.meta.url)), "..")]) {
|
|
38
|
+
const p = join(dir, "app.html");
|
|
39
|
+
if (!candidates.includes(p))
|
|
40
|
+
candidates.push(p);
|
|
41
|
+
}
|
|
42
|
+
for (const p of candidates) {
|
|
43
|
+
try {
|
|
44
|
+
if (!existsSync(p))
|
|
45
|
+
continue;
|
|
46
|
+
cachedTemplate = await readFile(p, "utf-8");
|
|
47
|
+
return cachedTemplate;
|
|
48
|
+
} catch {}
|
|
49
|
+
}
|
|
50
|
+
cachedTemplate = FALLBACK_TEMPLATE;
|
|
51
|
+
return cachedTemplate;
|
|
52
|
+
}
|
|
53
|
+
function buildShell(template, title) {
|
|
54
|
+
const safeTitle = escapeHtml(title);
|
|
55
|
+
const html = template.replaceAll("{{title}}", safeTitle);
|
|
56
|
+
for (const marker of ["<!--app-->", "{{body}}", "<!--app-html-->"]) {
|
|
57
|
+
const idx = html.indexOf(marker);
|
|
58
|
+
if (idx !== -1) {
|
|
59
|
+
return { head: html.slice(0, idx), tail: html.slice(idx + marker.length) };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const bodyClose = html.lastIndexOf("</body>");
|
|
63
|
+
if (bodyClose !== -1)
|
|
64
|
+
return { head: html.slice(0, bodyClose), tail: html.slice(bodyClose) };
|
|
65
|
+
return { head: html, tail: "" };
|
|
66
|
+
}
|
|
19
67
|
function createRenderer(pages) {
|
|
20
68
|
return async function render(path, props) {
|
|
21
69
|
const loader = pages[path];
|
|
@@ -29,7 +77,8 @@ function createRenderer(pages) {
|
|
|
29
77
|
const stream = await renderToReadableStream(/* @__PURE__ */ jsxDEV(Component, {
|
|
30
78
|
...props
|
|
31
79
|
}, undefined, false, undefined, this));
|
|
32
|
-
const
|
|
80
|
+
const template = await loadTemplate();
|
|
81
|
+
const { head, tail } = buildShell(template, pageTitle(path, props));
|
|
33
82
|
const encoder = new TextEncoder;
|
|
34
83
|
const combined = new ReadableStream({
|
|
35
84
|
async start(controller) {
|
|
@@ -45,7 +94,7 @@ function createRenderer(pages) {
|
|
|
45
94
|
} finally {
|
|
46
95
|
reader.releaseLock();
|
|
47
96
|
}
|
|
48
|
-
controller.enqueue(encoder.encode(
|
|
97
|
+
controller.enqueue(encoder.encode(tail));
|
|
49
98
|
controller.close();
|
|
50
99
|
}
|
|
51
100
|
});
|
|
@@ -70,18 +119,31 @@ var PANEL_ASSETS = {
|
|
|
70
119
|
"panel-app.js": "text/javascript; charset=utf-8"
|
|
71
120
|
};
|
|
72
121
|
function resolveDistDir() {
|
|
73
|
-
const candidates = [
|
|
74
|
-
join(process.cwd(), "dist"),
|
|
75
|
-
join(fileURLToPath(new URL(".", import.meta.url)), "..")
|
|
76
|
-
];
|
|
122
|
+
const candidates = [join2(process.cwd(), "dist"), join2(fileURLToPath2(new URL(".", import.meta.url)), "..")];
|
|
77
123
|
for (const dir of candidates) {
|
|
78
124
|
try {
|
|
79
|
-
if (
|
|
125
|
+
if (existsSync2(join2(dir, "panel-app.js")))
|
|
80
126
|
return dir;
|
|
81
127
|
} catch {}
|
|
82
128
|
}
|
|
83
129
|
return null;
|
|
84
130
|
}
|
|
131
|
+
function pickPanelCssOption(options) {
|
|
132
|
+
return options.css ?? options.panelCss;
|
|
133
|
+
}
|
|
134
|
+
function resolveCssFilePath(raw) {
|
|
135
|
+
const candidates = [raw, join2(process.cwd(), raw)];
|
|
136
|
+
const dist = resolveDistDir();
|
|
137
|
+
if (dist)
|
|
138
|
+
candidates.push(join2(dist, raw));
|
|
139
|
+
for (const p of candidates) {
|
|
140
|
+
try {
|
|
141
|
+
if (existsSync2(p))
|
|
142
|
+
return p;
|
|
143
|
+
} catch {}
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
85
147
|
function page(path, props) {
|
|
86
148
|
return {
|
|
87
149
|
[ReactRack.PAGE]: true,
|
|
@@ -90,18 +152,76 @@ function page(path, props) {
|
|
|
90
152
|
};
|
|
91
153
|
}
|
|
92
154
|
var pages = {
|
|
93
|
-
"/dashboard": () => import("../Dashboard-
|
|
155
|
+
"/dashboard": () => import("../Dashboard-2j561p7c.js"),
|
|
94
156
|
"/panel": () => import("../Panel-fbp3wrsw.js")
|
|
95
157
|
};
|
|
96
158
|
function reactPlugin(options) {
|
|
97
159
|
const render = createRenderer(options.pages);
|
|
160
|
+
const panelCssOverride = pickPanelCssOption(options);
|
|
161
|
+
let cachedCustomCss = null;
|
|
162
|
+
let cachedCustomCssLoaded = false;
|
|
163
|
+
async function loadCustomPanelCss() {
|
|
164
|
+
if (cachedCustomCssLoaded)
|
|
165
|
+
return cachedCustomCss;
|
|
166
|
+
if (!panelCssOverride) {
|
|
167
|
+
cachedCustomCssLoaded = true;
|
|
168
|
+
return cachedCustomCss = null;
|
|
169
|
+
}
|
|
170
|
+
if (typeof panelCssOverride === "object" && panelCssOverride.content !== undefined) {
|
|
171
|
+
cachedCustomCssLoaded = true;
|
|
172
|
+
return cachedCustomCss = panelCssOverride.content;
|
|
173
|
+
}
|
|
174
|
+
if (typeof panelCssOverride === "object" && panelCssOverride.path) {
|
|
175
|
+
const p = resolveCssFilePath(panelCssOverride.path);
|
|
176
|
+
if (p) {
|
|
177
|
+
try {
|
|
178
|
+
cachedCustomCssLoaded = true;
|
|
179
|
+
return cachedCustomCss = await readFile2(p);
|
|
180
|
+
} catch {}
|
|
181
|
+
}
|
|
182
|
+
cachedCustomCssLoaded = true;
|
|
183
|
+
return cachedCustomCss = null;
|
|
184
|
+
}
|
|
185
|
+
if (typeof panelCssOverride === "string") {
|
|
186
|
+
const filePath = resolveCssFilePath(panelCssOverride);
|
|
187
|
+
if (filePath) {
|
|
188
|
+
try {
|
|
189
|
+
cachedCustomCssLoaded = true;
|
|
190
|
+
return cachedCustomCss = await readFile2(filePath);
|
|
191
|
+
} catch {}
|
|
192
|
+
}
|
|
193
|
+
const looksLikeCss = panelCssOverride.includes("{") || panelCssOverride.includes(`
|
|
194
|
+
`);
|
|
195
|
+
if (looksLikeCss) {
|
|
196
|
+
cachedCustomCssLoaded = true;
|
|
197
|
+
return cachedCustomCss = panelCssOverride;
|
|
198
|
+
}
|
|
199
|
+
cachedCustomCssLoaded = true;
|
|
200
|
+
return cachedCustomCss = null;
|
|
201
|
+
}
|
|
202
|
+
cachedCustomCssLoaded = true;
|
|
203
|
+
return cachedCustomCss = null;
|
|
204
|
+
}
|
|
98
205
|
return new Elysia({ name: "@elysia-rack/react" }).decorate("react", { render }).get("/__rack/:name", async ({ params, status }) => {
|
|
99
206
|
const type = PANEL_ASSETS[params.name];
|
|
207
|
+
if (!type)
|
|
208
|
+
return status(404, "Panel asset not found");
|
|
209
|
+
if (params.name === "panel.css") {
|
|
210
|
+
const custom = await loadCustomPanelCss();
|
|
211
|
+
if (custom !== null) {
|
|
212
|
+
return new Response(custom, {
|
|
213
|
+
headers: {
|
|
214
|
+
"Content-Type": type,
|
|
215
|
+
"Cache-Control": "public, max-age=3600"
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
100
220
|
const dir = resolveDistDir();
|
|
101
|
-
if (!
|
|
102
|
-
return status(404, "Panel asset not
|
|
221
|
+
if (!dir)
|
|
222
|
+
return status(404, "Panel asset not found");
|
|
103
223
|
try {
|
|
104
|
-
const data = await
|
|
224
|
+
const data = await readFile2(join2(dir, params.name));
|
|
105
225
|
return new Response(data, {
|
|
106
226
|
headers: {
|
|
107
227
|
"Content-Type": type,
|