@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.
Files changed (83) hide show
  1. package/CHANGELOG.md +161 -0
  2. package/README.md +454 -0
  3. package/dist/context/accessibility.js +141 -0
  4. package/dist/context/body-class-sync.js +22 -0
  5. package/dist/context/color-mode-context.js +61 -0
  6. package/dist/context/command-palette-context.js +28 -0
  7. package/dist/context/html-dir.js +17 -0
  8. package/dist/context/link-context.js +18 -0
  9. package/dist/context/lte-behaviors.js +52 -0
  10. package/dist/context/sidebar-context.js +87 -0
  11. package/dist/css/adminlte.css +17259 -0
  12. package/dist/form/button.js +21 -0
  13. package/dist/form/input-color.js +30 -0
  14. package/dist/form/input-file.js +29 -0
  15. package/dist/form/input-flatpickr.js +45 -0
  16. package/dist/form/input-switch.js +26 -0
  17. package/dist/form/input-tom-select.js +59 -0
  18. package/dist/form/input.js +23 -0
  19. package/dist/form/select.js +25 -0
  20. package/dist/form/textarea.js +22 -0
  21. package/dist/hooks/use-card-widget.js +44 -0
  22. package/dist/hooks/use-direct-chat.js +16 -0
  23. package/dist/hooks/use-fullscreen.js +44 -0
  24. package/dist/hooks/use-push-menu.js +54 -0
  25. package/dist/hooks/use-sortable.js +26 -0
  26. package/dist/hooks/use-treeview-animation.js +27 -0
  27. package/dist/index.d.ts +1010 -0
  28. package/dist/index.js +145 -0
  29. package/dist/layout/app-content.js +18 -0
  30. package/dist/layout/auth-layout.js +25 -0
  31. package/dist/layout/color-mode-toggle.js +67 -0
  32. package/dist/layout/dashboard-layout.js +101 -0
  33. package/dist/layout/footer.js +19 -0
  34. package/dist/layout/sidebar-brand.js +16 -0
  35. package/dist/layout/sidebar-nav-item.js +46 -0
  36. package/dist/layout/sidebar-nav.js +43 -0
  37. package/dist/layout/sidebar-overlay.js +18 -0
  38. package/dist/layout/sidebar.js +48 -0
  39. package/dist/layout/topbar.js +128 -0
  40. package/dist/lib/class-name.js +6 -0
  41. package/dist/lib/flatten-menu.js +23 -0
  42. package/dist/tool/datatable.js +45 -0
  43. package/dist/tool/editor.js +72 -0
  44. package/dist/tool/modal.js +28 -0
  45. package/dist/types/direct-chat.js +0 -0
  46. package/dist/types/layout.js +0 -0
  47. package/dist/types/menu.js +0 -0
  48. package/dist/types/theme.js +0 -0
  49. package/dist/widget/accordion.js +35 -0
  50. package/dist/widget/alert.js +18 -0
  51. package/dist/widget/apex-chart.js +40 -0
  52. package/dist/widget/avatar.js +72 -0
  53. package/dist/widget/badge.js +20 -0
  54. package/dist/widget/breadcrumb.js +26 -0
  55. package/dist/widget/callout.js +11 -0
  56. package/dist/widget/card.js +84 -0
  57. package/dist/widget/carousel.js +56 -0
  58. package/dist/widget/command-palette.js +137 -0
  59. package/dist/widget/description-block.js +19 -0
  60. package/dist/widget/direct-chat.js +96 -0
  61. package/dist/widget/dropdown.js +63 -0
  62. package/dist/widget/info-box.js +24 -0
  63. package/dist/widget/list-group.js +47 -0
  64. package/dist/widget/nav-messages.js +48 -0
  65. package/dist/widget/nav-notifications.js +40 -0
  66. package/dist/widget/nav-tasks.js +60 -0
  67. package/dist/widget/offcanvas.js +61 -0
  68. package/dist/widget/pagination.js +93 -0
  69. package/dist/widget/profile-card.js +32 -0
  70. package/dist/widget/progress-group.js +23 -0
  71. package/dist/widget/progress.js +25 -0
  72. package/dist/widget/ratings.js +20 -0
  73. package/dist/widget/small-box.js +34 -0
  74. package/dist/widget/sparkline-chart.js +43 -0
  75. package/dist/widget/spinner.js +26 -0
  76. package/dist/widget/stepper.js +57 -0
  77. package/dist/widget/table.js +50 -0
  78. package/dist/widget/tabs.js +46 -0
  79. package/dist/widget/timeline.js +15 -0
  80. package/dist/widget/toast.js +41 -0
  81. package/dist/widget/tooltip.js +30 -0
  82. package/dist/widget/world-map.js +42 -0
  83. 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,6 @@
1
+ function cn(...classes) {
2
+ return classes.filter(Boolean).join(" ");
3
+ }
4
+ export {
5
+ cn
6
+ };
@@ -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
+ };