@adminlte/react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +161 -0
- package/README.md +454 -0
- package/dist/context/accessibility.js +141 -0
- package/dist/context/body-class-sync.js +22 -0
- package/dist/context/color-mode-context.js +61 -0
- package/dist/context/command-palette-context.js +28 -0
- package/dist/context/html-dir.js +17 -0
- package/dist/context/link-context.js +18 -0
- package/dist/context/lte-behaviors.js +52 -0
- package/dist/context/sidebar-context.js +87 -0
- package/dist/css/adminlte.css +17259 -0
- package/dist/form/button.js +21 -0
- package/dist/form/input-color.js +30 -0
- package/dist/form/input-file.js +29 -0
- package/dist/form/input-flatpickr.js +45 -0
- package/dist/form/input-switch.js +26 -0
- package/dist/form/input-tom-select.js +59 -0
- package/dist/form/input.js +23 -0
- package/dist/form/select.js +25 -0
- package/dist/form/textarea.js +22 -0
- package/dist/hooks/use-card-widget.js +44 -0
- package/dist/hooks/use-direct-chat.js +16 -0
- package/dist/hooks/use-fullscreen.js +44 -0
- package/dist/hooks/use-push-menu.js +54 -0
- package/dist/hooks/use-sortable.js +26 -0
- package/dist/hooks/use-treeview-animation.js +27 -0
- package/dist/index.d.ts +1010 -0
- package/dist/index.js +145 -0
- package/dist/layout/app-content.js +18 -0
- package/dist/layout/auth-layout.js +25 -0
- package/dist/layout/color-mode-toggle.js +67 -0
- package/dist/layout/dashboard-layout.js +101 -0
- package/dist/layout/footer.js +19 -0
- package/dist/layout/sidebar-brand.js +16 -0
- package/dist/layout/sidebar-nav-item.js +46 -0
- package/dist/layout/sidebar-nav.js +43 -0
- package/dist/layout/sidebar-overlay.js +18 -0
- package/dist/layout/sidebar.js +48 -0
- package/dist/layout/topbar.js +128 -0
- package/dist/lib/class-name.js +6 -0
- package/dist/lib/flatten-menu.js +23 -0
- package/dist/tool/datatable.js +45 -0
- package/dist/tool/editor.js +72 -0
- package/dist/tool/modal.js +28 -0
- package/dist/types/direct-chat.js +0 -0
- package/dist/types/layout.js +0 -0
- package/dist/types/menu.js +0 -0
- package/dist/types/theme.js +0 -0
- package/dist/widget/accordion.js +35 -0
- package/dist/widget/alert.js +18 -0
- package/dist/widget/apex-chart.js +40 -0
- package/dist/widget/avatar.js +72 -0
- package/dist/widget/badge.js +20 -0
- package/dist/widget/breadcrumb.js +26 -0
- package/dist/widget/callout.js +11 -0
- package/dist/widget/card.js +84 -0
- package/dist/widget/carousel.js +56 -0
- package/dist/widget/command-palette.js +137 -0
- package/dist/widget/description-block.js +19 -0
- package/dist/widget/direct-chat.js +96 -0
- package/dist/widget/dropdown.js +63 -0
- package/dist/widget/info-box.js +24 -0
- package/dist/widget/list-group.js +47 -0
- package/dist/widget/nav-messages.js +48 -0
- package/dist/widget/nav-notifications.js +40 -0
- package/dist/widget/nav-tasks.js +60 -0
- package/dist/widget/offcanvas.js +61 -0
- package/dist/widget/pagination.js +93 -0
- package/dist/widget/profile-card.js +32 -0
- package/dist/widget/progress-group.js +23 -0
- package/dist/widget/progress.js +25 -0
- package/dist/widget/ratings.js +20 -0
- package/dist/widget/small-box.js +34 -0
- package/dist/widget/sparkline-chart.js +43 -0
- package/dist/widget/spinner.js +26 -0
- package/dist/widget/stepper.js +57 -0
- package/dist/widget/table.js +50 -0
- package/dist/widget/tabs.js +46 -0
- package/dist/widget/timeline.js +15 -0
- package/dist/widget/toast.js +41 -0
- package/dist/widget/tooltip.js +30 -0
- package/dist/widget/world-map.js +42 -0
- package/package.json +116 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useSidebarContext } from "../context/sidebar-context.js";
|
|
4
|
+
import { useFullscreen } from "../hooks/use-fullscreen.js";
|
|
5
|
+
import { useCommandPalette } from "../context/command-palette-context.js";
|
|
6
|
+
import { ColorModeToggle } from "./color-mode-toggle.js";
|
|
7
|
+
const DEFAULT_USER = {
|
|
8
|
+
name: "Alexander Pierce",
|
|
9
|
+
image: "/assets/img/user2-160x160.jpg",
|
|
10
|
+
role: "Web Developer",
|
|
11
|
+
memberSince: "Nov. 2023"
|
|
12
|
+
};
|
|
13
|
+
function FullscreenToggle() {
|
|
14
|
+
const { isFullscreen, toggleFullscreen } = useFullscreen();
|
|
15
|
+
return /* @__PURE__ */ jsx("li", { className: "nav-item", children: /* @__PURE__ */ jsx(
|
|
16
|
+
"button",
|
|
17
|
+
{
|
|
18
|
+
type: "button",
|
|
19
|
+
className: "nav-link",
|
|
20
|
+
onClick: toggleFullscreen,
|
|
21
|
+
title: isFullscreen ? "Exit fullscreen" : "Fullscreen",
|
|
22
|
+
children: /* @__PURE__ */ jsx("i", { className: `bi ${isFullscreen ? "bi-fullscreen-exit" : "bi-arrows-fullscreen"}` })
|
|
23
|
+
}
|
|
24
|
+
) });
|
|
25
|
+
}
|
|
26
|
+
function Topbar({
|
|
27
|
+
start,
|
|
28
|
+
end,
|
|
29
|
+
colorModeToggle,
|
|
30
|
+
search = true,
|
|
31
|
+
fullscreen = true,
|
|
32
|
+
user = DEFAULT_USER,
|
|
33
|
+
navbarClass
|
|
34
|
+
}) {
|
|
35
|
+
const { toggle } = useSidebarContext();
|
|
36
|
+
const commandPalette = useCommandPalette();
|
|
37
|
+
return /* @__PURE__ */ jsx("nav", { className: `app-header navbar navbar-expand bg-body ${navbarClass || ""}`.trim(), children: /* @__PURE__ */ jsxs("div", { className: "container-fluid", children: [
|
|
38
|
+
/* @__PURE__ */ jsxs("ul", { className: "navbar-nav", children: [
|
|
39
|
+
/* @__PURE__ */ jsx("li", { className: "nav-item", children: /* @__PURE__ */ jsx(
|
|
40
|
+
"button",
|
|
41
|
+
{
|
|
42
|
+
type: "button",
|
|
43
|
+
className: "nav-link",
|
|
44
|
+
onClick: toggle,
|
|
45
|
+
title: "Toggle sidebar",
|
|
46
|
+
children: /* @__PURE__ */ jsx("i", { className: "bi bi-list" })
|
|
47
|
+
}
|
|
48
|
+
) }),
|
|
49
|
+
start
|
|
50
|
+
] }),
|
|
51
|
+
/* @__PURE__ */ jsxs("ul", { className: "navbar-nav ms-auto", children: [
|
|
52
|
+
search && /* @__PURE__ */ jsx("li", { className: "nav-item d-flex align-items-center me-2", children: /* @__PURE__ */ jsxs(
|
|
53
|
+
"button",
|
|
54
|
+
{
|
|
55
|
+
type: "button",
|
|
56
|
+
className: "btn btn-sm rounded-pill border bg-body-secondary text-secondary d-inline-flex align-items-center gap-2 px-3",
|
|
57
|
+
title: "Search (\u2318K)",
|
|
58
|
+
onClick: () => commandPalette?.open(),
|
|
59
|
+
children: [
|
|
60
|
+
/* @__PURE__ */ jsx("i", { className: "bi bi-search" }),
|
|
61
|
+
/* @__PURE__ */ jsx("span", { className: "d-none d-md-inline", children: "Search" }),
|
|
62
|
+
/* @__PURE__ */ jsx("kbd", { className: "d-none d-md-inline border rounded px-1 ms-1 fs-7 bg-body text-body-secondary", children: "\u2318K" })
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
) }),
|
|
66
|
+
end,
|
|
67
|
+
fullscreen && /* @__PURE__ */ jsx(FullscreenToggle, {}),
|
|
68
|
+
colorModeToggle && /* @__PURE__ */ jsx(ColorModeToggle, {}),
|
|
69
|
+
/* @__PURE__ */ jsxs("li", { className: "nav-item dropdown user-menu", children: [
|
|
70
|
+
/* @__PURE__ */ jsxs(
|
|
71
|
+
"button",
|
|
72
|
+
{
|
|
73
|
+
type: "button",
|
|
74
|
+
className: "nav-link dropdown-toggle d-flex align-items-center",
|
|
75
|
+
"data-bs-toggle": "dropdown",
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsx(
|
|
78
|
+
"img",
|
|
79
|
+
{
|
|
80
|
+
src: user.image,
|
|
81
|
+
alt: user.name,
|
|
82
|
+
className: "user-image rounded-circle shadow",
|
|
83
|
+
width: "32",
|
|
84
|
+
height: "32"
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
/* @__PURE__ */ jsx("span", { className: "d-none d-md-inline ms-2", children: user.name })
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
/* @__PURE__ */ jsxs("ul", { className: "dropdown-menu dropdown-menu-lg dropdown-menu-end", children: [
|
|
92
|
+
/* @__PURE__ */ jsxs("li", { className: "user-header text-bg-primary", children: [
|
|
93
|
+
/* @__PURE__ */ jsx(
|
|
94
|
+
"img",
|
|
95
|
+
{
|
|
96
|
+
src: user.image,
|
|
97
|
+
alt: user.name,
|
|
98
|
+
className: "rounded-circle shadow",
|
|
99
|
+
width: "80",
|
|
100
|
+
height: "80"
|
|
101
|
+
}
|
|
102
|
+
),
|
|
103
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
104
|
+
user.name,
|
|
105
|
+
user.role ? ` - ${user.role}` : "",
|
|
106
|
+
user.memberSince && /* @__PURE__ */ jsxs("small", { children: [
|
|
107
|
+
"Member since ",
|
|
108
|
+
user.memberSince
|
|
109
|
+
] })
|
|
110
|
+
] })
|
|
111
|
+
] }),
|
|
112
|
+
/* @__PURE__ */ jsx("li", { className: "user-body", children: /* @__PURE__ */ jsxs("div", { className: "row", children: [
|
|
113
|
+
/* @__PURE__ */ jsx("div", { className: "col-4 text-center", children: /* @__PURE__ */ jsx("a", { href: "#", children: "Followers" }) }),
|
|
114
|
+
/* @__PURE__ */ jsx("div", { className: "col-4 text-center", children: /* @__PURE__ */ jsx("a", { href: "#", children: "Sales" }) }),
|
|
115
|
+
/* @__PURE__ */ jsx("div", { className: "col-4 text-center", children: /* @__PURE__ */ jsx("a", { href: "#", children: "Friends" }) })
|
|
116
|
+
] }) }),
|
|
117
|
+
/* @__PURE__ */ jsxs("li", { className: "user-footer", children: [
|
|
118
|
+
/* @__PURE__ */ jsx("a", { href: "#", className: "btn btn-outline-secondary", children: "Profile" }),
|
|
119
|
+
/* @__PURE__ */ jsx("a", { href: "#", className: "btn btn-outline-danger float-end", children: "Sign out" })
|
|
120
|
+
] })
|
|
121
|
+
] })
|
|
122
|
+
] })
|
|
123
|
+
] })
|
|
124
|
+
] }) });
|
|
125
|
+
}
|
|
126
|
+
export {
|
|
127
|
+
Topbar
|
|
128
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
function flattenMenuToCommands(nodes) {
|
|
2
|
+
const out = [];
|
|
3
|
+
const walk = (list, section) => {
|
|
4
|
+
let sec = section;
|
|
5
|
+
for (const node of list) {
|
|
6
|
+
if (node.type === "header") {
|
|
7
|
+
sec = node.text;
|
|
8
|
+
} else if (node.type === "item") {
|
|
9
|
+
if (node.href && node.href !== "#") {
|
|
10
|
+
out.push({ label: node.text, href: node.href, icon: node.icon, section: sec });
|
|
11
|
+
}
|
|
12
|
+
} else if (node.type === "group") {
|
|
13
|
+
walk(node.children, node.text);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
walk(nodes);
|
|
18
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19
|
+
return out.filter((c) => seen.has(c.href) ? false : (seen.add(c.href), true));
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
flattenMenuToCommands
|
|
23
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useId, useRef } from "react";
|
|
4
|
+
function Datatable({
|
|
5
|
+
id,
|
|
6
|
+
columns,
|
|
7
|
+
data,
|
|
8
|
+
apiUrl,
|
|
9
|
+
tabulatorOptions,
|
|
10
|
+
className
|
|
11
|
+
}) {
|
|
12
|
+
const tableRef = useRef(null);
|
|
13
|
+
const reactId = useId();
|
|
14
|
+
const tableId = id ?? `datatable-${reactId.replace(/:/g, "")}`;
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const element = tableRef.current;
|
|
17
|
+
if (!element) return;
|
|
18
|
+
let cancelled = false;
|
|
19
|
+
let instance = null;
|
|
20
|
+
import("tabulator-tables").then(({ default: Tabulator }) => {
|
|
21
|
+
if (cancelled) return;
|
|
22
|
+
const tableOptions = {
|
|
23
|
+
columns: columns.map((col) => ({
|
|
24
|
+
title: col.title,
|
|
25
|
+
field: col.field,
|
|
26
|
+
sorter: col.sorter || "string",
|
|
27
|
+
formatter: col.formatter || "plaintext",
|
|
28
|
+
width: col.width || 150
|
|
29
|
+
})),
|
|
30
|
+
...apiUrl ? { ajaxURL: apiUrl, ajaxProgressiveLoad: "scroll" } : { data: data || [] },
|
|
31
|
+
...tabulatorOptions
|
|
32
|
+
};
|
|
33
|
+
instance = new Tabulator(element, tableOptions);
|
|
34
|
+
});
|
|
35
|
+
return () => {
|
|
36
|
+
cancelled = true;
|
|
37
|
+
instance?.destroy?.();
|
|
38
|
+
instance = null;
|
|
39
|
+
};
|
|
40
|
+
}, [columns, data, apiUrl, tabulatorOptions]);
|
|
41
|
+
return /* @__PURE__ */ jsx("div", { id: tableId, ref: tableRef, className: `datatable ${className || ""}` });
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
Datatable
|
|
45
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
function Editor({
|
|
5
|
+
name,
|
|
6
|
+
label,
|
|
7
|
+
value = "",
|
|
8
|
+
placeholder = "Enter text...",
|
|
9
|
+
quillOptions,
|
|
10
|
+
fgroupClass,
|
|
11
|
+
onChange
|
|
12
|
+
}) {
|
|
13
|
+
const editorRef = useRef(null);
|
|
14
|
+
const quillRef = useRef(null);
|
|
15
|
+
const onChangeRef = useRef(onChange);
|
|
16
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
17
|
+
const [html, setHtml] = useState(value);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
onChangeRef.current = onChange;
|
|
20
|
+
}, [onChange]);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const element = editorRef.current;
|
|
23
|
+
if (!element) return;
|
|
24
|
+
let cancelled = false;
|
|
25
|
+
import("quill").then(({ default: Quill }) => {
|
|
26
|
+
if (cancelled || quillRef.current) return;
|
|
27
|
+
const quill = new Quill(element, {
|
|
28
|
+
theme: "snow",
|
|
29
|
+
placeholder,
|
|
30
|
+
...quillOptions
|
|
31
|
+
});
|
|
32
|
+
quillRef.current = quill;
|
|
33
|
+
if (value) {
|
|
34
|
+
element.querySelector(".ql-editor").innerHTML = value;
|
|
35
|
+
}
|
|
36
|
+
quill.on("text-change", () => {
|
|
37
|
+
const current = element.querySelector(".ql-editor").innerHTML;
|
|
38
|
+
setHtml(current);
|
|
39
|
+
onChangeRef.current?.(current);
|
|
40
|
+
});
|
|
41
|
+
setIsLoading(false);
|
|
42
|
+
});
|
|
43
|
+
return () => {
|
|
44
|
+
cancelled = true;
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const element = editorRef.current;
|
|
49
|
+
if (!element || !quillRef.current) return;
|
|
50
|
+
const editorEl = element.querySelector(".ql-editor");
|
|
51
|
+
if (editorEl && editorEl.innerHTML !== value) {
|
|
52
|
+
editorEl.innerHTML = value;
|
|
53
|
+
setHtml(value);
|
|
54
|
+
}
|
|
55
|
+
}, [value]);
|
|
56
|
+
return /* @__PURE__ */ jsxs("div", { className: `mb-3 ${fgroupClass || ""}`, children: [
|
|
57
|
+
label && /* @__PURE__ */ jsx("label", { className: "form-label", children: label }),
|
|
58
|
+
isLoading && /* @__PURE__ */ jsx("div", { className: "p-3 text-muted text-center", children: /* @__PURE__ */ jsx("small", { children: "Loading editor..." }) }),
|
|
59
|
+
/* @__PURE__ */ jsx(
|
|
60
|
+
"div",
|
|
61
|
+
{
|
|
62
|
+
ref: editorRef,
|
|
63
|
+
className: "editor",
|
|
64
|
+
style: { display: isLoading ? "none" : "block" }
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
/* @__PURE__ */ jsx("input", { type: "hidden", name, value: html })
|
|
68
|
+
] });
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
Editor
|
|
72
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
function Modal({
|
|
4
|
+
id,
|
|
5
|
+
title,
|
|
6
|
+
size,
|
|
7
|
+
theme,
|
|
8
|
+
staticBackdrop,
|
|
9
|
+
scrollable,
|
|
10
|
+
centered,
|
|
11
|
+
footer,
|
|
12
|
+
children
|
|
13
|
+
}) {
|
|
14
|
+
const sizeClass = size ? `modal-${size}` : "";
|
|
15
|
+
const scrollClass = scrollable ? "modal-dialog-scrollable" : "";
|
|
16
|
+
const centeredClass = centered ? "modal-dialog-centered" : "";
|
|
17
|
+
return /* @__PURE__ */ jsx("div", { className: "modal fade", id, tabIndex: -1, children: /* @__PURE__ */ jsx("div", { className: `modal-dialog ${sizeClass} ${scrollClass} ${centeredClass}`.trim(), children: /* @__PURE__ */ jsxs("div", { className: `modal-content ${theme ? `text-bg-${theme}` : ""}`.trim(), children: [
|
|
18
|
+
title && /* @__PURE__ */ jsxs("div", { className: "modal-header", children: [
|
|
19
|
+
/* @__PURE__ */ jsx("h5", { className: "modal-title", children: title }),
|
|
20
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "btn-close", "data-bs-dismiss": "modal" })
|
|
21
|
+
] }),
|
|
22
|
+
/* @__PURE__ */ jsx("div", { className: "modal-body", children }),
|
|
23
|
+
footer && /* @__PURE__ */ jsx("div", { className: "modal-footer", children: footer })
|
|
24
|
+
] }) }) });
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
Modal
|
|
28
|
+
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
function Accordion({
|
|
5
|
+
items,
|
|
6
|
+
defaultOpen = 0,
|
|
7
|
+
alwaysOpen = false,
|
|
8
|
+
flush,
|
|
9
|
+
id = "accordion",
|
|
10
|
+
className
|
|
11
|
+
}) {
|
|
12
|
+
const [open, setOpen] = useState(defaultOpen >= 0 ? [defaultOpen] : []);
|
|
13
|
+
const toggle = (i) => setOpen(
|
|
14
|
+
(prev) => prev.includes(i) ? prev.filter((x) => x !== i) : alwaysOpen ? [...prev, i] : [i]
|
|
15
|
+
);
|
|
16
|
+
return /* @__PURE__ */ jsx("div", { className: `accordion${flush ? " accordion-flush" : ""}${className ? ` ${className}` : ""}`, id, children: items.map((item, i) => {
|
|
17
|
+
const isOpen = open.includes(i);
|
|
18
|
+
return /* @__PURE__ */ jsxs("div", { className: "accordion-item", children: [
|
|
19
|
+
/* @__PURE__ */ jsx("h2", { className: "accordion-header", children: /* @__PURE__ */ jsx(
|
|
20
|
+
"button",
|
|
21
|
+
{
|
|
22
|
+
type: "button",
|
|
23
|
+
className: `accordion-button${isOpen ? "" : " collapsed"}`,
|
|
24
|
+
"aria-expanded": isOpen,
|
|
25
|
+
onClick: () => toggle(i),
|
|
26
|
+
children: item.title
|
|
27
|
+
}
|
|
28
|
+
) }),
|
|
29
|
+
/* @__PURE__ */ jsx("div", { className: `accordion-collapse collapse${isOpen ? " show" : ""}`, children: /* @__PURE__ */ jsx("div", { className: "accordion-body", children: item.children }) })
|
|
30
|
+
] }, i);
|
|
31
|
+
}) });
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
Accordion
|
|
35
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
function Alert({
|
|
3
|
+
theme = "info",
|
|
4
|
+
title,
|
|
5
|
+
icon,
|
|
6
|
+
dismissable,
|
|
7
|
+
children
|
|
8
|
+
}) {
|
|
9
|
+
return /* @__PURE__ */ jsxs("div", { className: `alert alert-${theme}`, role: "alert", children: [
|
|
10
|
+
icon && /* @__PURE__ */ jsx("i", { className: `bi ${icon} me-2` }),
|
|
11
|
+
title && /* @__PURE__ */ jsx("strong", { children: title }),
|
|
12
|
+
children,
|
|
13
|
+
dismissable && /* @__PURE__ */ jsx("button", { type: "button", className: "btn-close", "data-bs-dismiss": "alert" })
|
|
14
|
+
] });
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
Alert
|
|
18
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
function ApexChart({ id, series, config }) {
|
|
5
|
+
const containerRef = useRef(null);
|
|
6
|
+
const chartRef = useRef(null);
|
|
7
|
+
const seriesKey = JSON.stringify(series);
|
|
8
|
+
const configKey = JSON.stringify(config);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
let cancelled = false;
|
|
11
|
+
const el = containerRef.current;
|
|
12
|
+
if (!el) return;
|
|
13
|
+
if (chartRef.current) {
|
|
14
|
+
chartRef.current.updateOptions({ ...config, series }, true, true);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const initChart = async () => {
|
|
18
|
+
const ApexCharts = (await import("apexcharts")).default;
|
|
19
|
+
if (cancelled || !containerRef.current) return;
|
|
20
|
+
const chart = new ApexCharts(el, { ...config, series });
|
|
21
|
+
chartRef.current = chart;
|
|
22
|
+
chart.render();
|
|
23
|
+
};
|
|
24
|
+
initChart().catch((err) => console.error("ApexChart init error:", err));
|
|
25
|
+
return () => {
|
|
26
|
+
cancelled = true;
|
|
27
|
+
};
|
|
28
|
+
}, [id, seriesKey, configKey]);
|
|
29
|
+
useEffect(
|
|
30
|
+
() => () => {
|
|
31
|
+
chartRef.current?.destroy();
|
|
32
|
+
chartRef.current = null;
|
|
33
|
+
},
|
|
34
|
+
[]
|
|
35
|
+
);
|
|
36
|
+
return /* @__PURE__ */ jsx("div", { id, ref: containerRef });
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
ApexChart
|
|
40
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Children, cloneElement, isValidElement } from "react";
|
|
3
|
+
import { cn } from "../lib/class-name.js";
|
|
4
|
+
const STATUS_THEME = {
|
|
5
|
+
online: "success",
|
|
6
|
+
offline: "secondary",
|
|
7
|
+
away: "warning",
|
|
8
|
+
busy: "danger"
|
|
9
|
+
};
|
|
10
|
+
function Avatar({
|
|
11
|
+
src,
|
|
12
|
+
alt = "",
|
|
13
|
+
initials,
|
|
14
|
+
size = 40,
|
|
15
|
+
rounded,
|
|
16
|
+
theme = "secondary",
|
|
17
|
+
status,
|
|
18
|
+
className
|
|
19
|
+
}) {
|
|
20
|
+
const shape = rounded ? "rounded" : "rounded-circle";
|
|
21
|
+
const dot = status && /* @__PURE__ */ jsx(
|
|
22
|
+
"span",
|
|
23
|
+
{
|
|
24
|
+
className: cn(
|
|
25
|
+
"position-absolute bottom-0 end-0 border border-2 border-white rounded-circle",
|
|
26
|
+
`bg-${STATUS_THEME[status]}`
|
|
27
|
+
),
|
|
28
|
+
style: { width: size * 0.28, height: size * 0.28 },
|
|
29
|
+
title: status
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
const inner = src ? /* @__PURE__ */ jsx(
|
|
33
|
+
"img",
|
|
34
|
+
{
|
|
35
|
+
src,
|
|
36
|
+
alt,
|
|
37
|
+
width: size,
|
|
38
|
+
height: size,
|
|
39
|
+
className: cn(shape, "object-fit-cover"),
|
|
40
|
+
style: { width: size, height: size }
|
|
41
|
+
}
|
|
42
|
+
) : /* @__PURE__ */ jsx(
|
|
43
|
+
"span",
|
|
44
|
+
{
|
|
45
|
+
className: cn("d-inline-flex align-items-center justify-content-center", shape, `text-bg-${theme}`),
|
|
46
|
+
style: { width: size, height: size, fontSize: size * 0.4 },
|
|
47
|
+
"aria-label": alt || initials,
|
|
48
|
+
children: initials
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
if (!status) return /* @__PURE__ */ jsx("span", { className: cn("d-inline-block", className), children: inner });
|
|
52
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("position-relative d-inline-block", className), style: { lineHeight: 0 }, children: [
|
|
53
|
+
inner,
|
|
54
|
+
dot
|
|
55
|
+
] });
|
|
56
|
+
}
|
|
57
|
+
function AvatarGroup({ overlap = 12, className, children }) {
|
|
58
|
+
return /* @__PURE__ */ jsx("div", { className: cn("d-inline-flex align-items-center", className), children: Children.map(
|
|
59
|
+
children,
|
|
60
|
+
(child, idx) => isValidElement(child) ? cloneElement(child, {
|
|
61
|
+
style: {
|
|
62
|
+
...child.props.style,
|
|
63
|
+
marginLeft: idx === 0 ? 0 : -overlap,
|
|
64
|
+
zIndex: idx
|
|
65
|
+
}
|
|
66
|
+
}) : child
|
|
67
|
+
) });
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
Avatar,
|
|
71
|
+
AvatarGroup
|
|
72
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/class-name.js";
|
|
3
|
+
function Badge({ theme = "secondary", pill, positioned, className, children }) {
|
|
4
|
+
return /* @__PURE__ */ jsx(
|
|
5
|
+
"span",
|
|
6
|
+
{
|
|
7
|
+
className: cn(
|
|
8
|
+
"badge",
|
|
9
|
+
`text-bg-${theme}`,
|
|
10
|
+
pill && "rounded-pill",
|
|
11
|
+
positioned && "position-absolute top-0 start-100 translate-middle",
|
|
12
|
+
className
|
|
13
|
+
),
|
|
14
|
+
children
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
Badge
|
|
20
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/class-name.js";
|
|
3
|
+
function Breadcrumb({ items, divider, className, label = "breadcrumb" }) {
|
|
4
|
+
return /* @__PURE__ */ jsx(
|
|
5
|
+
"nav",
|
|
6
|
+
{
|
|
7
|
+
"aria-label": label,
|
|
8
|
+
style: divider ? { ["--bs-breadcrumb-divider"]: `"${divider}"` } : void 0,
|
|
9
|
+
children: /* @__PURE__ */ jsx("ol", { className: cn("breadcrumb", className), children: items.map((item, idx) => {
|
|
10
|
+
const isLast = idx === items.length - 1;
|
|
11
|
+
return /* @__PURE__ */ jsx(
|
|
12
|
+
"li",
|
|
13
|
+
{
|
|
14
|
+
className: cn("breadcrumb-item", isLast && "active"),
|
|
15
|
+
"aria-current": isLast ? "page" : void 0,
|
|
16
|
+
children: item.href && !isLast ? /* @__PURE__ */ jsx("a", { href: item.href, children: item.label }) : item.label
|
|
17
|
+
},
|
|
18
|
+
idx
|
|
19
|
+
);
|
|
20
|
+
}) })
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
Breadcrumb
|
|
26
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
function Callout({ theme = "info", title, icon, children }) {
|
|
3
|
+
return /* @__PURE__ */ jsxs("div", { className: `callout callout-${theme}`, children: [
|
|
4
|
+
icon && /* @__PURE__ */ jsx("i", { className: `bi ${icon}` }),
|
|
5
|
+
title && /* @__PURE__ */ jsx("h5", { children: title }),
|
|
6
|
+
children
|
|
7
|
+
] });
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
Callout
|
|
11
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCardWidget } from "../hooks/use-card-widget.js";
|
|
4
|
+
function Card({
|
|
5
|
+
title,
|
|
6
|
+
icon,
|
|
7
|
+
theme,
|
|
8
|
+
variant = "default",
|
|
9
|
+
outline,
|
|
10
|
+
collapsible,
|
|
11
|
+
defaultCollapsed,
|
|
12
|
+
removable,
|
|
13
|
+
onRemove,
|
|
14
|
+
maximizable,
|
|
15
|
+
bodyClass,
|
|
16
|
+
headerClass,
|
|
17
|
+
footerClass,
|
|
18
|
+
tools,
|
|
19
|
+
footer,
|
|
20
|
+
children,
|
|
21
|
+
className
|
|
22
|
+
}) {
|
|
23
|
+
const { isCollapsed, isRemoved, toggleCollapse, toggleMaximize, remove } = useCardWidget(
|
|
24
|
+
defaultCollapsed
|
|
25
|
+
);
|
|
26
|
+
if (isRemoved) return null;
|
|
27
|
+
const resolvedVariant = outline ? "outline" : variant;
|
|
28
|
+
let cardClass = "card";
|
|
29
|
+
if (theme) {
|
|
30
|
+
if (resolvedVariant === "outline") cardClass = `card card-outline card-${theme}`;
|
|
31
|
+
else if (resolvedVariant === "solid") cardClass = `card text-bg-${theme}`;
|
|
32
|
+
else cardClass = `card card-${theme}`;
|
|
33
|
+
}
|
|
34
|
+
return /* @__PURE__ */ jsxs("div", { className: `${cardClass}${isCollapsed ? " collapsed-card" : ""} ${className || ""}`, children: [
|
|
35
|
+
(title || tools) && /* @__PURE__ */ jsxs("div", { className: `card-header ${headerClass || ""}`, children: [
|
|
36
|
+
/* @__PURE__ */ jsx("h3", { className: "card-title", children: title || "" }),
|
|
37
|
+
/* @__PURE__ */ jsxs("div", { className: "card-tools", children: [
|
|
38
|
+
(collapsible || removable || maximizable) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39
|
+
collapsible && /* @__PURE__ */ jsx(
|
|
40
|
+
"button",
|
|
41
|
+
{
|
|
42
|
+
type: "button",
|
|
43
|
+
className: "btn btn-tool",
|
|
44
|
+
onClick: toggleCollapse,
|
|
45
|
+
title: isCollapsed ? "Expand" : "Collapse",
|
|
46
|
+
children: /* @__PURE__ */ jsx("i", { className: `bi ${isCollapsed ? "bi-plus-lg" : "bi-dash-lg"}` })
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
removable && /* @__PURE__ */ jsx(
|
|
50
|
+
"button",
|
|
51
|
+
{
|
|
52
|
+
type: "button",
|
|
53
|
+
className: "btn btn-tool",
|
|
54
|
+
onClick: () => {
|
|
55
|
+
remove();
|
|
56
|
+
onRemove?.();
|
|
57
|
+
},
|
|
58
|
+
title: "Remove",
|
|
59
|
+
children: /* @__PURE__ */ jsx("i", { className: "bi bi-x-lg" })
|
|
60
|
+
}
|
|
61
|
+
),
|
|
62
|
+
maximizable && /* @__PURE__ */ jsx(
|
|
63
|
+
"button",
|
|
64
|
+
{
|
|
65
|
+
type: "button",
|
|
66
|
+
className: "btn btn-tool",
|
|
67
|
+
onClick: toggleMaximize,
|
|
68
|
+
title: "Maximize",
|
|
69
|
+
children: /* @__PURE__ */ jsx("i", { className: "bi bi-fullscreen" })
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
] }),
|
|
73
|
+
tools
|
|
74
|
+
] })
|
|
75
|
+
] }),
|
|
76
|
+
!isCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
77
|
+
/* @__PURE__ */ jsx("div", { className: `card-body ${bodyClass || ""}`, children }),
|
|
78
|
+
footer && /* @__PURE__ */ jsx("div", { className: `card-footer ${footerClass || ""}`, children: footer })
|
|
79
|
+
] })
|
|
80
|
+
] });
|
|
81
|
+
}
|
|
82
|
+
export {
|
|
83
|
+
Card
|
|
84
|
+
};
|