@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,93 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/class-name.js";
3
+ function buildRange(page, total, sibling) {
4
+ const tokens = /* @__PURE__ */ new Set([1, total]);
5
+ for (let p = page - sibling; p <= page + sibling; p++) {
6
+ if (p >= 1 && p <= total) tokens.add(p);
7
+ }
8
+ const sorted = [...tokens].sort((a, b) => a - b);
9
+ const out = [];
10
+ let prev = 0;
11
+ for (const p of sorted) {
12
+ if (prev && p - prev > 1) out.push("ellipsis");
13
+ out.push(p);
14
+ prev = p;
15
+ }
16
+ return out;
17
+ }
18
+ function Pagination({
19
+ page,
20
+ totalPages,
21
+ onPageChange,
22
+ size,
23
+ siblingCount = 1,
24
+ align = "start",
25
+ hideControls,
26
+ label = "Pagination",
27
+ className
28
+ }) {
29
+ if (totalPages < 1) return null;
30
+ const tokens = buildRange(page, totalPages, siblingCount);
31
+ const item = (key, content, target, opts = {}) => {
32
+ const { active, disabled, ariaLabel } = opts;
33
+ const go = (e) => {
34
+ if (disabled || active) return;
35
+ if (onPageChange) {
36
+ e.preventDefault();
37
+ onPageChange(target);
38
+ }
39
+ };
40
+ return /* @__PURE__ */ jsx("li", { className: cn("page-item", active && "active", disabled && "disabled"), children: onPageChange ? /* @__PURE__ */ jsx(
41
+ "button",
42
+ {
43
+ type: "button",
44
+ className: "page-link",
45
+ onClick: go,
46
+ "aria-label": ariaLabel,
47
+ "aria-current": active ? "page" : void 0,
48
+ disabled,
49
+ children: content
50
+ }
51
+ ) : /* @__PURE__ */ jsx(
52
+ "a",
53
+ {
54
+ className: "page-link",
55
+ href: "#",
56
+ onClick: go,
57
+ "aria-label": ariaLabel,
58
+ "aria-current": active ? "page" : void 0,
59
+ "aria-disabled": disabled,
60
+ tabIndex: disabled ? -1 : void 0,
61
+ children: content
62
+ }
63
+ ) }, key);
64
+ };
65
+ return /* @__PURE__ */ jsx("nav", { "aria-label": label, children: /* @__PURE__ */ jsxs(
66
+ "ul",
67
+ {
68
+ className: cn(
69
+ "pagination mb-0",
70
+ size && `pagination-${size}`,
71
+ align === "center" && "justify-content-center",
72
+ align === "end" && "justify-content-end",
73
+ className
74
+ ),
75
+ children: [
76
+ !hideControls && item("prev", /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2039" }), page - 1, {
77
+ disabled: page <= 1,
78
+ ariaLabel: "Previous page"
79
+ }),
80
+ tokens.map(
81
+ (t, i) => t === "ellipsis" ? /* @__PURE__ */ jsx("li", { className: "page-item disabled", children: /* @__PURE__ */ jsx("span", { className: "page-link", children: "\u2026" }) }, `e${i}`) : item(t, t, t, { active: t === page })
82
+ ),
83
+ !hideControls && item("next", /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u203A" }), page + 1, {
84
+ disabled: page >= totalPages,
85
+ ariaLabel: "Next page"
86
+ })
87
+ ]
88
+ }
89
+ ) });
90
+ }
91
+ export {
92
+ Pagination
93
+ };
@@ -0,0 +1,32 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ function ProfileCard({
3
+ name,
4
+ title,
5
+ image,
6
+ imageAlt = "User",
7
+ socials,
8
+ description,
9
+ className,
10
+ children
11
+ }) {
12
+ return /* @__PURE__ */ jsx("div", { className: `card ${className || ""}`, children: /* @__PURE__ */ jsxs("div", { className: "card-body text-center", children: [
13
+ image && /* @__PURE__ */ jsx("img", { src: image, alt: imageAlt, className: "img-fluid rounded-circle mb-3" }),
14
+ /* @__PURE__ */ jsx("h5", { className: "card-title", children: name }),
15
+ title && /* @__PURE__ */ jsx("p", { className: "text-muted", children: title }),
16
+ description && /* @__PURE__ */ jsx("p", { className: "card-text small", children: description }),
17
+ socials && socials.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-3", children: socials.map((link, idx) => /* @__PURE__ */ jsx(
18
+ "a",
19
+ {
20
+ href: link.url,
21
+ className: "btn btn-sm btn-outline-secondary me-1",
22
+ title: link.label,
23
+ children: /* @__PURE__ */ jsx("i", { className: `bi ${link.icon}` })
24
+ },
25
+ idx
26
+ )) }),
27
+ children
28
+ ] }) });
29
+ }
30
+ export {
31
+ ProfileCard
32
+ };
@@ -0,0 +1,23 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ function ProgressGroup({
3
+ label,
4
+ value,
5
+ color = "primary",
6
+ max = 100,
7
+ showPercentage = true
8
+ }) {
9
+ const percentage = Math.round(value / max * 100);
10
+ return /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
11
+ /* @__PURE__ */ jsxs("div", { className: "d-flex justify-content-between mb-1", children: [
12
+ /* @__PURE__ */ jsx("span", { children: label }),
13
+ showPercentage && /* @__PURE__ */ jsxs("span", { className: "text-muted", children: [
14
+ percentage,
15
+ "%"
16
+ ] })
17
+ ] }),
18
+ /* @__PURE__ */ jsx("div", { className: "progress", children: /* @__PURE__ */ jsx("div", { className: `progress-bar bg-${color}`, style: { width: `${percentage}%` } }) })
19
+ ] });
20
+ }
21
+ export {
22
+ ProgressGroup
23
+ };
@@ -0,0 +1,25 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ function Progress({
3
+ value = 0,
4
+ theme = "primary",
5
+ striped,
6
+ animated,
7
+ height,
8
+ showLabel
9
+ }) {
10
+ return /* @__PURE__ */ jsx("div", { className: "progress", style: height ? { height } : {}, children: /* @__PURE__ */ jsx(
11
+ "div",
12
+ {
13
+ className: `progress-bar bg-${theme} ${striped ? "progress-bar-striped" : ""} ${animated ? "progress-bar-animated" : ""}`,
14
+ role: "progressbar",
15
+ style: { width: `${value}%` },
16
+ "aria-valuenow": value,
17
+ "aria-valuemin": 0,
18
+ "aria-valuemax": 100,
19
+ children: showLabel && `${value}%`
20
+ }
21
+ ) });
22
+ }
23
+ export {
24
+ Progress
25
+ };
@@ -0,0 +1,20 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ function Ratings({
3
+ value,
4
+ max = 5,
5
+ color = "warning",
6
+ readonly = true,
7
+ className
8
+ }) {
9
+ return /* @__PURE__ */ jsx("div", { className, children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsx(
10
+ "i",
11
+ {
12
+ className: `bi bi-star${i < value ? "-fill" : ""} text-${color}`,
13
+ style: { cursor: readonly ? "default" : "pointer" }
14
+ },
15
+ i
16
+ )) });
17
+ }
18
+ export {
19
+ Ratings
20
+ };
@@ -0,0 +1,34 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ const DARK_LINK_THEMES = ["warning", "light"];
3
+ function SmallBox({
4
+ title,
5
+ text,
6
+ icon,
7
+ theme = "primary",
8
+ url,
9
+ urlText = "More info"
10
+ }) {
11
+ const linkColor = DARK_LINK_THEMES.includes(theme) ? "link-dark" : "link-light";
12
+ return /* @__PURE__ */ jsxs("div", { className: `small-box text-bg-${theme}`, children: [
13
+ /* @__PURE__ */ jsxs("div", { className: "inner", children: [
14
+ /* @__PURE__ */ jsx("h3", { children: title }),
15
+ text && /* @__PURE__ */ jsx("p", { children: text })
16
+ ] }),
17
+ icon,
18
+ url && /* @__PURE__ */ jsxs(
19
+ "a",
20
+ {
21
+ href: url,
22
+ className: `small-box-footer ${linkColor} link-underline-opacity-0 link-underline-opacity-50-hover`,
23
+ children: [
24
+ urlText,
25
+ " ",
26
+ /* @__PURE__ */ jsx("i", { className: "bi bi-link-45deg" })
27
+ ]
28
+ }
29
+ )
30
+ ] });
31
+ }
32
+ export {
33
+ SmallBox
34
+ };
@@ -0,0 +1,43 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useRef } from "react";
4
+ function SparklineChart({ id, data }) {
5
+ const containerRef = useRef(null);
6
+ const chartRef = useRef(null);
7
+ useEffect(() => {
8
+ let cancelled = false;
9
+ const el = containerRef.current;
10
+ if (!el) return;
11
+ const initChart = async () => {
12
+ const ApexCharts = (await import("apexcharts")).default;
13
+ if (cancelled || !containerRef.current) return;
14
+ const options = {
15
+ series: [{ data }],
16
+ chart: {
17
+ type: "area",
18
+ height: 50,
19
+ sparkline: { enabled: true }
20
+ },
21
+ stroke: { curve: "straight" },
22
+ fill: { opacity: 0.3 },
23
+ yaxis: { min: 0 },
24
+ colors: ["#DCE6EC"]
25
+ };
26
+ const chart = new ApexCharts(el, options);
27
+ chartRef.current = chart;
28
+ chart.render();
29
+ };
30
+ initChart().catch((err) => console.error("SparklineChart init error:", err));
31
+ return () => {
32
+ cancelled = true;
33
+ if (chartRef.current) {
34
+ chartRef.current.destroy();
35
+ chartRef.current = null;
36
+ }
37
+ };
38
+ }, [id, data]);
39
+ return /* @__PURE__ */ jsx("div", { id, ref: containerRef });
40
+ }
41
+ export {
42
+ SparklineChart
43
+ };
@@ -0,0 +1,26 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { cn } from "../lib/class-name.js";
3
+ function Spinner({
4
+ theme,
5
+ variant = "border",
6
+ small,
7
+ label = "Loading\u2026",
8
+ className
9
+ }) {
10
+ return /* @__PURE__ */ jsx(
11
+ "div",
12
+ {
13
+ className: cn(
14
+ `spinner-${variant}`,
15
+ small && `spinner-${variant}-sm`,
16
+ theme && `text-${theme}`,
17
+ className
18
+ ),
19
+ role: "status",
20
+ children: /* @__PURE__ */ jsx("span", { className: "visually-hidden", children: label })
21
+ }
22
+ );
23
+ }
24
+ export {
25
+ Spinner
26
+ };
@@ -0,0 +1,57 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/class-name.js";
3
+ function Stepper({ steps, active, orientation = "horizontal", onStepClick, className }) {
4
+ const vertical = orientation === "vertical";
5
+ const marker = (state, index, icon) => {
6
+ const bg = state === "complete" ? "text-bg-success" : state === "active" ? "text-bg-primary" : "text-bg-secondary";
7
+ const content = icon ? /* @__PURE__ */ jsx("i", { className: cn("bi", icon), "aria-hidden": "true" }) : state === "complete" ? /* @__PURE__ */ jsx("i", { className: "bi bi-check-lg", "aria-hidden": "true" }) : index + 1;
8
+ const cls = cn(
9
+ "d-inline-flex align-items-center justify-content-center rounded-circle flex-shrink-0 fw-semibold",
10
+ bg,
11
+ state === "upcoming" && "opacity-75"
12
+ );
13
+ const style = { width: 38, height: 38 };
14
+ return onStepClick ? /* @__PURE__ */ jsx(
15
+ "button",
16
+ {
17
+ type: "button",
18
+ className: cn(cls, "border-0"),
19
+ style,
20
+ onClick: () => onStepClick(index),
21
+ "aria-label": `Go to step ${index + 1}`,
22
+ children: content
23
+ }
24
+ ) : /* @__PURE__ */ jsx("span", { className: cls, style, children: content });
25
+ };
26
+ return /* @__PURE__ */ jsx(
27
+ "ol",
28
+ {
29
+ className: cn(
30
+ "list-unstyled d-flex mb-0",
31
+ vertical ? "flex-column gap-3" : "flex-row align-items-start",
32
+ className
33
+ ),
34
+ children: steps.map((step, idx) => {
35
+ const state = idx < active ? "complete" : idx === active ? "active" : "upcoming";
36
+ return /* @__PURE__ */ jsxs(
37
+ "li",
38
+ {
39
+ className: cn("d-flex", vertical ? "flex-row gap-3" : "flex-column align-items-center text-center flex-fill"),
40
+ "aria-current": state === "active" ? "step" : void 0,
41
+ children: [
42
+ /* @__PURE__ */ jsx("div", { className: cn("d-flex align-items-center", !vertical && "w-100 justify-content-center"), children: marker(state, idx, step.icon) }),
43
+ /* @__PURE__ */ jsxs("div", { className: cn(vertical ? "" : "mt-2"), children: [
44
+ /* @__PURE__ */ jsx("div", { className: cn("fw-semibold", state === "upcoming" && "text-secondary"), children: step.label }),
45
+ step.description && /* @__PURE__ */ jsx("div", { className: "small text-secondary", children: step.description })
46
+ ] })
47
+ ]
48
+ },
49
+ idx
50
+ );
51
+ })
52
+ }
53
+ );
54
+ }
55
+ export {
56
+ Stepper
57
+ };
@@ -0,0 +1,50 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/class-name.js";
3
+ function Table({
4
+ columns,
5
+ data,
6
+ rowKey,
7
+ striped,
8
+ hover,
9
+ bordered,
10
+ borderless,
11
+ small,
12
+ responsive,
13
+ theme,
14
+ caption,
15
+ emptyMessage = "No data",
16
+ className
17
+ }) {
18
+ const table = /* @__PURE__ */ jsxs(
19
+ "table",
20
+ {
21
+ className: cn(
22
+ "table",
23
+ striped && "table-striped",
24
+ hover && "table-hover",
25
+ bordered && "table-bordered",
26
+ borderless && "table-borderless",
27
+ small && "table-sm",
28
+ theme && `table-${theme}`,
29
+ className
30
+ ),
31
+ children: [
32
+ caption && /* @__PURE__ */ jsx("caption", { children: caption }),
33
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsx(
34
+ "th",
35
+ {
36
+ scope: "col",
37
+ className: cn(col.align && `text-${col.align}`, col.headerClassName),
38
+ children: col.header
39
+ },
40
+ col.key
41
+ )) }) }),
42
+ /* @__PURE__ */ jsx("tbody", { children: data.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: columns.length, className: "text-center text-secondary py-3", children: emptyMessage }) }) : data.map((row, i) => /* @__PURE__ */ jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsx("td", { className: cn(col.align && `text-${col.align}`, col.className), children: col.render ? col.render(row, i) : String(row[col.key] ?? "") }, col.key)) }, rowKey ? rowKey(row, i) : i)) })
43
+ ]
44
+ }
45
+ );
46
+ return responsive ? /* @__PURE__ */ jsx("div", { className: "table-responsive", children: table }) : table;
47
+ }
48
+ export {
49
+ Table
50
+ };
@@ -0,0 +1,46 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ function Tabs({
5
+ items,
6
+ defaultIndex = 0,
7
+ variant = "tabs",
8
+ fill,
9
+ justified,
10
+ className
11
+ }) {
12
+ const [active, setActive] = useState(defaultIndex);
13
+ return /* @__PURE__ */ jsxs("div", { className, children: [
14
+ /* @__PURE__ */ jsx(
15
+ "ul",
16
+ {
17
+ className: `nav nav-${variant}${fill ? " nav-fill" : ""}${justified ? " nav-justified" : ""}`,
18
+ role: "tablist",
19
+ children: items.map((item, i) => /* @__PURE__ */ jsx("li", { className: "nav-item", role: "presentation", children: /* @__PURE__ */ jsx(
20
+ "button",
21
+ {
22
+ type: "button",
23
+ className: `nav-link${i === active ? " active" : ""}`,
24
+ role: "tab",
25
+ "aria-selected": i === active,
26
+ onClick: () => setActive(i),
27
+ children: item.label
28
+ }
29
+ ) }, i))
30
+ }
31
+ ),
32
+ /* @__PURE__ */ jsx("div", { className: "tab-content pt-3", children: items.map((item, i) => /* @__PURE__ */ jsx(
33
+ "div",
34
+ {
35
+ role: "tabpanel",
36
+ className: `tab-pane fade${i === active ? " show active" : ""}`,
37
+ hidden: i !== active,
38
+ children: item.children
39
+ },
40
+ i
41
+ )) })
42
+ ] });
43
+ }
44
+ export {
45
+ Tabs
46
+ };
@@ -0,0 +1,15 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ function Timeline({ items, className }) {
3
+ return /* @__PURE__ */ jsx("div", { className: `timeline ${className || ""}`, children: items.map((item, idx) => /* @__PURE__ */ jsxs("div", { className: "timeline-item", children: [
4
+ item.icon && /* @__PURE__ */ jsx("span", { className: `timeline-icon bg-${item.iconTheme || "primary"}`, children: /* @__PURE__ */ jsx("i", { className: `bi ${item.icon}` }) }),
5
+ /* @__PURE__ */ jsxs("div", { className: "timeline-content", children: [
6
+ /* @__PURE__ */ jsx("h3", { className: "timeline-header", children: item.title }),
7
+ item.body && /* @__PURE__ */ jsx("p", { children: item.body }),
8
+ item.footer && /* @__PURE__ */ jsx("div", { className: "timeline-footer", children: item.footer }),
9
+ /* @__PURE__ */ jsx("div", { className: "timeline-time", children: item.time })
10
+ ] })
11
+ ] }, idx)) });
12
+ }
13
+ export {
14
+ Timeline
15
+ };
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect } from "react";
4
+ function Toast({ show, onClose, title, theme, autohideMs = 4e3, children }) {
5
+ useEffect(() => {
6
+ if (!show || !autohideMs) return;
7
+ const t = setTimeout(onClose, autohideMs);
8
+ return () => clearTimeout(t);
9
+ }, [show, autohideMs, onClose]);
10
+ if (!show) return null;
11
+ return /* @__PURE__ */ jsxs(
12
+ "div",
13
+ {
14
+ className: `toast show${theme ? ` text-bg-${theme} border-0` : ""}`,
15
+ role: "alert",
16
+ "aria-live": "assertive",
17
+ "aria-atomic": "true",
18
+ children: [
19
+ title && /* @__PURE__ */ jsxs("div", { className: "toast-header", children: [
20
+ /* @__PURE__ */ jsx("strong", { className: "me-auto", children: title }),
21
+ /* @__PURE__ */ jsx("button", { type: "button", className: "btn-close", "aria-label": "Close", onClick: onClose })
22
+ ] }),
23
+ /* @__PURE__ */ jsxs("div", { className: "d-flex", children: [
24
+ /* @__PURE__ */ jsx("div", { className: "toast-body", children }),
25
+ !title && /* @__PURE__ */ jsx(
26
+ "button",
27
+ {
28
+ type: "button",
29
+ className: `btn-close me-2 m-auto${theme ? " btn-close-white" : ""}`,
30
+ "aria-label": "Close",
31
+ onClick: onClose
32
+ }
33
+ )
34
+ ] })
35
+ ]
36
+ }
37
+ );
38
+ }
39
+ export {
40
+ Toast
41
+ };
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ const POS = {
5
+ top: { cls: "bs-tooltip-top", style: { bottom: "100%", left: "50%", transform: "translateX(-50%)", marginBottom: 6 } },
6
+ bottom: { cls: "bs-tooltip-bottom", style: { top: "100%", left: "50%", transform: "translateX(-50%)", marginTop: 6 } },
7
+ left: { cls: "bs-tooltip-start", style: { right: "100%", top: "50%", transform: "translateY(-50%)", marginRight: 6 } },
8
+ right: { cls: "bs-tooltip-end", style: { left: "100%", top: "50%", transform: "translateY(-50%)", marginLeft: 6 } }
9
+ };
10
+ function Tooltip({ title, placement = "top", children }) {
11
+ const [show, setShow] = useState(false);
12
+ const { cls, style } = POS[placement];
13
+ return /* @__PURE__ */ jsxs(
14
+ "span",
15
+ {
16
+ style: { position: "relative", display: "inline-block" },
17
+ onMouseEnter: () => setShow(true),
18
+ onMouseLeave: () => setShow(false),
19
+ onFocus: () => setShow(true),
20
+ onBlur: () => setShow(false),
21
+ children: [
22
+ children,
23
+ show && /* @__PURE__ */ jsx("span", { className: `tooltip ${cls} show`, role: "tooltip", style: { position: "absolute", zIndex: 1080, ...style }, children: /* @__PURE__ */ jsx("span", { className: "tooltip-inner", children: title }) })
24
+ ]
25
+ }
26
+ );
27
+ }
28
+ export {
29
+ Tooltip
30
+ };
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useRef } from "react";
4
+ function WorldMap({ id, height = 220 }) {
5
+ const containerRef = useRef(null);
6
+ const mapRef = useRef(null);
7
+ useEffect(() => {
8
+ let cancelled = false;
9
+ const el = containerRef.current;
10
+ if (!el) return;
11
+ const initMap = async () => {
12
+ try {
13
+ const mod = await import("jsvectormap");
14
+ await import("jsvectormap/dist/maps/world.js");
15
+ if (cancelled || !containerRef.current) return;
16
+ const JsVectorMap = mod.default ?? mod.jsVectorMap ?? mod;
17
+ if (typeof JsVectorMap !== "function") return;
18
+ mapRef.current = new JsVectorMap({
19
+ selector: el,
20
+ map: "world"
21
+ });
22
+ } catch (error) {
23
+ console.error("WorldMap init error:", error);
24
+ }
25
+ };
26
+ initMap();
27
+ return () => {
28
+ cancelled = true;
29
+ if (mapRef.current) {
30
+ if (typeof mapRef.current.destroy === "function") {
31
+ mapRef.current.destroy();
32
+ }
33
+ mapRef.current = null;
34
+ if (containerRef.current) containerRef.current.innerHTML = "";
35
+ }
36
+ };
37
+ }, [id]);
38
+ return /* @__PURE__ */ jsx("div", { id, ref: containerRef, style: { height: `${height}px` } });
39
+ }
40
+ export {
41
+ WorldMap
42
+ };