@holmdigital/components 1.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/README.md +46 -0
- package/dist/Button/Button.js +117 -0
- package/dist/Button/Button.mjs +6 -0
- package/dist/Checkbox/Checkbox.js +82 -0
- package/dist/Checkbox/Checkbox.mjs +6 -0
- package/dist/Dialog/Dialog.js +129 -0
- package/dist/Dialog/Dialog.mjs +6 -0
- package/dist/FormField/FormField.js +110 -0
- package/dist/FormField/FormField.mjs +6 -0
- package/dist/Heading/Heading.js +48 -0
- package/dist/Heading/Heading.mjs +6 -0
- package/dist/Modal/Modal.js +146 -0
- package/dist/Modal/Modal.mjs +7 -0
- package/dist/NavigationMenu/NavigationMenu.js +141 -0
- package/dist/NavigationMenu/NavigationMenu.mjs +6 -0
- package/dist/RadioGroup/RadioGroup.js +103 -0
- package/dist/RadioGroup/RadioGroup.mjs +6 -0
- package/dist/Select/Select.js +157 -0
- package/dist/Select/Select.mjs +12 -0
- package/dist/SkipLink/SkipLink.js +59 -0
- package/dist/SkipLink/SkipLink.mjs +6 -0
- package/dist/Switch/Switch.js +82 -0
- package/dist/Switch/Switch.mjs +6 -0
- package/dist/Toast/Toast.js +123 -0
- package/dist/Toast/Toast.mjs +8 -0
- package/dist/Tooltip/Tooltip.js +121 -0
- package/dist/Tooltip/Tooltip.mjs +12 -0
- package/dist/chunk-2MJRKHPL.mjs +98 -0
- package/dist/chunk-5RKBS475.mjs +58 -0
- package/dist/chunk-C5M6C7KT.mjs +84 -0
- package/dist/chunk-GK4BYT56.mjs +117 -0
- package/dist/chunk-HALLFO25.mjs +22 -0
- package/dist/chunk-LZ42XDDI.mjs +105 -0
- package/dist/chunk-MKKQLWGK.mjs +35 -0
- package/dist/chunk-NDYRGXQ6.mjs +93 -0
- package/dist/chunk-NOE5QKC2.mjs +58 -0
- package/dist/chunk-PLT5CAFO.mjs +86 -0
- package/dist/chunk-V2JYAFB7.mjs +130 -0
- package/dist/chunk-W4ZHBRFT.mjs +14 -0
- package/dist/chunk-YMSNGQN6.mjs +79 -0
- package/dist/index.js +1256 -0
- package/dist/index.mjs +308 -0
- package/package.json +113 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/Switch/Switch.tsx
|
|
21
|
+
var Switch_exports = {};
|
|
22
|
+
__export(Switch_exports, {
|
|
23
|
+
Switch: () => Switch
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(Switch_exports);
|
|
26
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
27
|
+
var Switch = ({ checked, onCheckedChange, disabled = false, label, id }) => {
|
|
28
|
+
const generatedId = id || `switch-${Math.random().toString(36).substr(2, 9)}`;
|
|
29
|
+
const handleClick = () => {
|
|
30
|
+
if (!disabled) {
|
|
31
|
+
onCheckedChange(!checked);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const handleKeyDown = (e) => {
|
|
35
|
+
if (disabled) return;
|
|
36
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
onCheckedChange(!checked);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
42
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
43
|
+
"button",
|
|
44
|
+
{
|
|
45
|
+
type: "button",
|
|
46
|
+
role: "switch",
|
|
47
|
+
"aria-checked": checked,
|
|
48
|
+
id: generatedId,
|
|
49
|
+
disabled,
|
|
50
|
+
onClick: handleClick,
|
|
51
|
+
onKeyDown: handleKeyDown,
|
|
52
|
+
className: `
|
|
53
|
+
relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-slate-900 focus:ring-offset-2
|
|
54
|
+
${checked ? "bg-primary-600" : "bg-slate-200"}
|
|
55
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
56
|
+
`,
|
|
57
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
58
|
+
"span",
|
|
59
|
+
{
|
|
60
|
+
className: `
|
|
61
|
+
inline-block h-4 w-4 transform rounded-full bg-white transition-transform
|
|
62
|
+
${checked ? "translate-x-6" : "translate-x-1"}
|
|
63
|
+
`
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
),
|
|
68
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
69
|
+
"label",
|
|
70
|
+
{
|
|
71
|
+
htmlFor: generatedId,
|
|
72
|
+
className: `text-sm font-medium text-slate-700 cursor-pointer ${disabled ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
73
|
+
onClick: handleClick,
|
|
74
|
+
children: label
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
] });
|
|
78
|
+
};
|
|
79
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
80
|
+
0 && (module.exports = {
|
|
81
|
+
Switch
|
|
82
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/Toast/Toast.tsx
|
|
21
|
+
var Toast_exports = {};
|
|
22
|
+
__export(Toast_exports, {
|
|
23
|
+
ToastProvider: () => ToastProvider,
|
|
24
|
+
useToast: () => useToast
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(Toast_exports);
|
|
27
|
+
var import_react = require("react");
|
|
28
|
+
var import_lucide_react = require("lucide-react");
|
|
29
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
30
|
+
var ToastContext = (0, import_react.createContext)(void 0);
|
|
31
|
+
var ToastProvider = ({ children }) => {
|
|
32
|
+
const [toasts, setToasts] = (0, import_react.useState)([]);
|
|
33
|
+
const addToast = (0, import_react.useCallback)((toast) => {
|
|
34
|
+
const id = Math.random().toString(36).substr(2, 9);
|
|
35
|
+
setToasts((prev) => [...prev, { ...toast, id }]);
|
|
36
|
+
}, []);
|
|
37
|
+
const removeToast = (0, import_react.useCallback)((id) => {
|
|
38
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
39
|
+
}, []);
|
|
40
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [
|
|
41
|
+
children,
|
|
42
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToastViewport, {})
|
|
43
|
+
] });
|
|
44
|
+
};
|
|
45
|
+
var useToast = () => {
|
|
46
|
+
const context = (0, import_react.useContext)(ToastContext);
|
|
47
|
+
if (!context) {
|
|
48
|
+
throw new Error("useToast must be used within a ToastProvider");
|
|
49
|
+
}
|
|
50
|
+
return context;
|
|
51
|
+
};
|
|
52
|
+
var ToastViewport = () => {
|
|
53
|
+
const { toasts, removeToast } = useToast();
|
|
54
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
55
|
+
"div",
|
|
56
|
+
{
|
|
57
|
+
className: "fixed bottom-0 right-0 z-50 p-4 w-full md:max-w-sm flex flex-col gap-2",
|
|
58
|
+
role: "region",
|
|
59
|
+
"aria-label": "Notifications",
|
|
60
|
+
children: toasts.map((toast) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToastItem, { toast, onRemove: () => removeToast(toast.id) }, toast.id))
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
var ToastItem = ({ toast, onRemove }) => {
|
|
65
|
+
(0, import_react.useEffect)(() => {
|
|
66
|
+
if (toast.duration === Infinity) return;
|
|
67
|
+
const timer = setTimeout(() => {
|
|
68
|
+
onRemove();
|
|
69
|
+
}, toast.duration || 5e3);
|
|
70
|
+
return () => clearTimeout(timer);
|
|
71
|
+
}, [toast, onRemove]);
|
|
72
|
+
const icons = {
|
|
73
|
+
info: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Info, { className: "w-5 h-5 text-blue-500" }),
|
|
74
|
+
success: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.CheckCircle, { className: "w-5 h-5 text-green-500" }),
|
|
75
|
+
warning: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.AlertTriangle, { className: "w-5 h-5 text-amber-500" }),
|
|
76
|
+
error: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.AlertCircle, { className: "w-5 h-5 text-red-500" })
|
|
77
|
+
};
|
|
78
|
+
const bgColors = {
|
|
79
|
+
info: "bg-white border-blue-100",
|
|
80
|
+
success: "bg-white border-green-100",
|
|
81
|
+
warning: "bg-white border-amber-100",
|
|
82
|
+
error: "bg-white border-red-100"
|
|
83
|
+
};
|
|
84
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
85
|
+
"div",
|
|
86
|
+
{
|
|
87
|
+
role: "alert",
|
|
88
|
+
className: `
|
|
89
|
+
flex items-start gap-3 p-4 rounded-lg shadow-lg border transition-all animate-in slide-in-from-right-full fade-in duration-300
|
|
90
|
+
${bgColors[toast.type || "info"]}
|
|
91
|
+
`,
|
|
92
|
+
children: [
|
|
93
|
+
icons[toast.type || "info"],
|
|
94
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1", children: [
|
|
95
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { className: "text-sm font-medium text-slate-900", children: toast.title }),
|
|
96
|
+
toast.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-slate-600 mt-1", children: toast.description }),
|
|
97
|
+
toast.action && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
98
|
+
"button",
|
|
99
|
+
{
|
|
100
|
+
onClick: toast.action.onClick,
|
|
101
|
+
className: "mt-2 text-sm font-medium text-slate-900 underline hover:no-underline",
|
|
102
|
+
children: toast.action.label
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
] }),
|
|
106
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
107
|
+
"button",
|
|
108
|
+
{
|
|
109
|
+
onClick: onRemove,
|
|
110
|
+
className: "text-slate-400 hover:text-slate-900 transition-colors",
|
|
111
|
+
"aria-label": "Close",
|
|
112
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.X, { className: "w-4 h-4" })
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
120
|
+
0 && (module.exports = {
|
|
121
|
+
ToastProvider,
|
|
122
|
+
useToast
|
|
123
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/Tooltip/Tooltip.tsx
|
|
31
|
+
var Tooltip_exports = {};
|
|
32
|
+
__export(Tooltip_exports, {
|
|
33
|
+
Tooltip: () => Tooltip,
|
|
34
|
+
TooltipContent: () => TooltipContent,
|
|
35
|
+
TooltipProvider: () => TooltipProvider,
|
|
36
|
+
TooltipTrigger: () => TooltipTrigger
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(Tooltip_exports);
|
|
39
|
+
var import_react = __toESM(require("react"));
|
|
40
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
41
|
+
var TooltipContext = (0, import_react.createContext)(void 0);
|
|
42
|
+
var TooltipProvider = ({ children }) => {
|
|
43
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
|
|
44
|
+
};
|
|
45
|
+
var Tooltip = ({ children }) => {
|
|
46
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
47
|
+
const id = (0, import_react.useRef)(`tooltip-${Math.random().toString(36).substr(2, 9)}`).current;
|
|
48
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipContext.Provider, { value: { open, setOpen, id }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "relative inline-block group", onMouseLeave: () => setOpen(false), children }) });
|
|
49
|
+
};
|
|
50
|
+
var TooltipTrigger = ({ children, asChild = false, ...props }) => {
|
|
51
|
+
const context = (0, import_react.useContext)(TooltipContext);
|
|
52
|
+
if (!context) throw new Error("TooltipTrigger must be used within Tooltip");
|
|
53
|
+
const { setOpen, id } = context;
|
|
54
|
+
const handleOpen = () => setOpen(true);
|
|
55
|
+
const handleClose = () => setOpen(false);
|
|
56
|
+
if (import_react.default.isValidElement(children)) {
|
|
57
|
+
return import_react.default.cloneElement(children, {
|
|
58
|
+
"aria-describedby": context.open ? id : void 0,
|
|
59
|
+
onMouseEnter: (e) => {
|
|
60
|
+
handleOpen();
|
|
61
|
+
children.props.onMouseEnter?.(e);
|
|
62
|
+
},
|
|
63
|
+
onMouseLeave: (e) => {
|
|
64
|
+
handleClose();
|
|
65
|
+
children.props.onMouseLeave?.(e);
|
|
66
|
+
},
|
|
67
|
+
onFocus: (e) => {
|
|
68
|
+
handleOpen();
|
|
69
|
+
children.props.onFocus?.(e);
|
|
70
|
+
},
|
|
71
|
+
onBlur: (e) => {
|
|
72
|
+
handleClose();
|
|
73
|
+
children.props.onBlur?.(e);
|
|
74
|
+
},
|
|
75
|
+
...props
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
79
|
+
"span",
|
|
80
|
+
{
|
|
81
|
+
"aria-describedby": context.open ? id : void 0,
|
|
82
|
+
onMouseEnter: handleOpen,
|
|
83
|
+
onMouseLeave: handleClose,
|
|
84
|
+
onFocus: handleOpen,
|
|
85
|
+
onBlur: handleClose,
|
|
86
|
+
tabIndex: 0,
|
|
87
|
+
className: "cursor-default",
|
|
88
|
+
...props,
|
|
89
|
+
children
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
var TooltipContent = ({ children, className = "" }) => {
|
|
94
|
+
const context = (0, import_react.useContext)(TooltipContext);
|
|
95
|
+
if (!context) throw new Error("TooltipContent must be used within Tooltip");
|
|
96
|
+
if (!context.open) return null;
|
|
97
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
98
|
+
"div",
|
|
99
|
+
{
|
|
100
|
+
id: context.id,
|
|
101
|
+
role: "tooltip",
|
|
102
|
+
className: `
|
|
103
|
+
absolute z-50 px-3 py-2 text-sm font-medium text-white bg-slate-900 rounded shadow-lg
|
|
104
|
+
bottom-full left-1/2 transform -translate-x-1/2 mb-2 whitespace-nowrap
|
|
105
|
+
animate-in fade-in zoom-in-95 duration-200
|
|
106
|
+
${className}
|
|
107
|
+
`,
|
|
108
|
+
children: [
|
|
109
|
+
children,
|
|
110
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute w-2 h-2 bg-slate-900 transform rotate-45 left-1/2 -translate-x-1/2 -bottom-1" })
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
116
|
+
0 && (module.exports = {
|
|
117
|
+
Tooltip,
|
|
118
|
+
TooltipContent,
|
|
119
|
+
TooltipProvider,
|
|
120
|
+
TooltipTrigger
|
|
121
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// src/Toast/Toast.tsx
|
|
2
|
+
import { createContext, useContext, useState, useEffect, useCallback } from "react";
|
|
3
|
+
import { X, Info, CheckCircle, AlertTriangle, AlertCircle } from "lucide-react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
var ToastContext = createContext(void 0);
|
|
6
|
+
var ToastProvider = ({ children }) => {
|
|
7
|
+
const [toasts, setToasts] = useState([]);
|
|
8
|
+
const addToast = useCallback((toast) => {
|
|
9
|
+
const id = Math.random().toString(36).substr(2, 9);
|
|
10
|
+
setToasts((prev) => [...prev, { ...toast, id }]);
|
|
11
|
+
}, []);
|
|
12
|
+
const removeToast = useCallback((id) => {
|
|
13
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
14
|
+
}, []);
|
|
15
|
+
return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [
|
|
16
|
+
children,
|
|
17
|
+
/* @__PURE__ */ jsx(ToastViewport, {})
|
|
18
|
+
] });
|
|
19
|
+
};
|
|
20
|
+
var useToast = () => {
|
|
21
|
+
const context = useContext(ToastContext);
|
|
22
|
+
if (!context) {
|
|
23
|
+
throw new Error("useToast must be used within a ToastProvider");
|
|
24
|
+
}
|
|
25
|
+
return context;
|
|
26
|
+
};
|
|
27
|
+
var ToastViewport = () => {
|
|
28
|
+
const { toasts, removeToast } = useToast();
|
|
29
|
+
return /* @__PURE__ */ jsx(
|
|
30
|
+
"div",
|
|
31
|
+
{
|
|
32
|
+
className: "fixed bottom-0 right-0 z-50 p-4 w-full md:max-w-sm flex flex-col gap-2",
|
|
33
|
+
role: "region",
|
|
34
|
+
"aria-label": "Notifications",
|
|
35
|
+
children: toasts.map((toast) => /* @__PURE__ */ jsx(ToastItem, { toast, onRemove: () => removeToast(toast.id) }, toast.id))
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
var ToastItem = ({ toast, onRemove }) => {
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (toast.duration === Infinity) return;
|
|
42
|
+
const timer = setTimeout(() => {
|
|
43
|
+
onRemove();
|
|
44
|
+
}, toast.duration || 5e3);
|
|
45
|
+
return () => clearTimeout(timer);
|
|
46
|
+
}, [toast, onRemove]);
|
|
47
|
+
const icons = {
|
|
48
|
+
info: /* @__PURE__ */ jsx(Info, { className: "w-5 h-5 text-blue-500" }),
|
|
49
|
+
success: /* @__PURE__ */ jsx(CheckCircle, { className: "w-5 h-5 text-green-500" }),
|
|
50
|
+
warning: /* @__PURE__ */ jsx(AlertTriangle, { className: "w-5 h-5 text-amber-500" }),
|
|
51
|
+
error: /* @__PURE__ */ jsx(AlertCircle, { className: "w-5 h-5 text-red-500" })
|
|
52
|
+
};
|
|
53
|
+
const bgColors = {
|
|
54
|
+
info: "bg-white border-blue-100",
|
|
55
|
+
success: "bg-white border-green-100",
|
|
56
|
+
warning: "bg-white border-amber-100",
|
|
57
|
+
error: "bg-white border-red-100"
|
|
58
|
+
};
|
|
59
|
+
return /* @__PURE__ */ jsxs(
|
|
60
|
+
"div",
|
|
61
|
+
{
|
|
62
|
+
role: "alert",
|
|
63
|
+
className: `
|
|
64
|
+
flex items-start gap-3 p-4 rounded-lg shadow-lg border transition-all animate-in slide-in-from-right-full fade-in duration-300
|
|
65
|
+
${bgColors[toast.type || "info"]}
|
|
66
|
+
`,
|
|
67
|
+
children: [
|
|
68
|
+
icons[toast.type || "info"],
|
|
69
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
70
|
+
/* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-slate-900", children: toast.title }),
|
|
71
|
+
toast.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-600 mt-1", children: toast.description }),
|
|
72
|
+
toast.action && /* @__PURE__ */ jsx(
|
|
73
|
+
"button",
|
|
74
|
+
{
|
|
75
|
+
onClick: toast.action.onClick,
|
|
76
|
+
className: "mt-2 text-sm font-medium text-slate-900 underline hover:no-underline",
|
|
77
|
+
children: toast.action.label
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
] }),
|
|
81
|
+
/* @__PURE__ */ jsx(
|
|
82
|
+
"button",
|
|
83
|
+
{
|
|
84
|
+
onClick: onRemove,
|
|
85
|
+
className: "text-slate-400 hover:text-slate-900 transition-colors",
|
|
86
|
+
"aria-label": "Close",
|
|
87
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export {
|
|
96
|
+
ToastProvider,
|
|
97
|
+
useToast
|
|
98
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// src/Switch/Switch.tsx
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
var Switch = ({ checked, onCheckedChange, disabled = false, label, id }) => {
|
|
4
|
+
const generatedId = id || `switch-${Math.random().toString(36).substr(2, 9)}`;
|
|
5
|
+
const handleClick = () => {
|
|
6
|
+
if (!disabled) {
|
|
7
|
+
onCheckedChange(!checked);
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const handleKeyDown = (e) => {
|
|
11
|
+
if (disabled) return;
|
|
12
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
onCheckedChange(!checked);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
18
|
+
/* @__PURE__ */ jsx(
|
|
19
|
+
"button",
|
|
20
|
+
{
|
|
21
|
+
type: "button",
|
|
22
|
+
role: "switch",
|
|
23
|
+
"aria-checked": checked,
|
|
24
|
+
id: generatedId,
|
|
25
|
+
disabled,
|
|
26
|
+
onClick: handleClick,
|
|
27
|
+
onKeyDown: handleKeyDown,
|
|
28
|
+
className: `
|
|
29
|
+
relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-slate-900 focus:ring-offset-2
|
|
30
|
+
${checked ? "bg-primary-600" : "bg-slate-200"}
|
|
31
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
32
|
+
`,
|
|
33
|
+
children: /* @__PURE__ */ jsx(
|
|
34
|
+
"span",
|
|
35
|
+
{
|
|
36
|
+
className: `
|
|
37
|
+
inline-block h-4 w-4 transform rounded-full bg-white transition-transform
|
|
38
|
+
${checked ? "translate-x-6" : "translate-x-1"}
|
|
39
|
+
`
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
),
|
|
44
|
+
label && /* @__PURE__ */ jsx(
|
|
45
|
+
"label",
|
|
46
|
+
{
|
|
47
|
+
htmlFor: generatedId,
|
|
48
|
+
className: `text-sm font-medium text-slate-700 cursor-pointer ${disabled ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
49
|
+
onClick: handleClick,
|
|
50
|
+
children: label
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
] });
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
Switch
|
|
58
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// src/Tooltip/Tooltip.tsx
|
|
2
|
+
import React, { useState, useRef, createContext, useContext } from "react";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var TooltipContext = createContext(void 0);
|
|
5
|
+
var TooltipProvider = ({ children }) => {
|
|
6
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
7
|
+
};
|
|
8
|
+
var Tooltip = ({ children }) => {
|
|
9
|
+
const [open, setOpen] = useState(false);
|
|
10
|
+
const id = useRef(`tooltip-${Math.random().toString(36).substr(2, 9)}`).current;
|
|
11
|
+
return /* @__PURE__ */ jsx(TooltipContext.Provider, { value: { open, setOpen, id }, children: /* @__PURE__ */ jsx("div", { className: "relative inline-block group", onMouseLeave: () => setOpen(false), children }) });
|
|
12
|
+
};
|
|
13
|
+
var TooltipTrigger = ({ children, asChild = false, ...props }) => {
|
|
14
|
+
const context = useContext(TooltipContext);
|
|
15
|
+
if (!context) throw new Error("TooltipTrigger must be used within Tooltip");
|
|
16
|
+
const { setOpen, id } = context;
|
|
17
|
+
const handleOpen = () => setOpen(true);
|
|
18
|
+
const handleClose = () => setOpen(false);
|
|
19
|
+
if (React.isValidElement(children)) {
|
|
20
|
+
return React.cloneElement(children, {
|
|
21
|
+
"aria-describedby": context.open ? id : void 0,
|
|
22
|
+
onMouseEnter: (e) => {
|
|
23
|
+
handleOpen();
|
|
24
|
+
children.props.onMouseEnter?.(e);
|
|
25
|
+
},
|
|
26
|
+
onMouseLeave: (e) => {
|
|
27
|
+
handleClose();
|
|
28
|
+
children.props.onMouseLeave?.(e);
|
|
29
|
+
},
|
|
30
|
+
onFocus: (e) => {
|
|
31
|
+
handleOpen();
|
|
32
|
+
children.props.onFocus?.(e);
|
|
33
|
+
},
|
|
34
|
+
onBlur: (e) => {
|
|
35
|
+
handleClose();
|
|
36
|
+
children.props.onBlur?.(e);
|
|
37
|
+
},
|
|
38
|
+
...props
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return /* @__PURE__ */ jsx(
|
|
42
|
+
"span",
|
|
43
|
+
{
|
|
44
|
+
"aria-describedby": context.open ? id : void 0,
|
|
45
|
+
onMouseEnter: handleOpen,
|
|
46
|
+
onMouseLeave: handleClose,
|
|
47
|
+
onFocus: handleOpen,
|
|
48
|
+
onBlur: handleClose,
|
|
49
|
+
tabIndex: 0,
|
|
50
|
+
className: "cursor-default",
|
|
51
|
+
...props,
|
|
52
|
+
children
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
var TooltipContent = ({ children, className = "" }) => {
|
|
57
|
+
const context = useContext(TooltipContext);
|
|
58
|
+
if (!context) throw new Error("TooltipContent must be used within Tooltip");
|
|
59
|
+
if (!context.open) return null;
|
|
60
|
+
return /* @__PURE__ */ jsxs(
|
|
61
|
+
"div",
|
|
62
|
+
{
|
|
63
|
+
id: context.id,
|
|
64
|
+
role: "tooltip",
|
|
65
|
+
className: `
|
|
66
|
+
absolute z-50 px-3 py-2 text-sm font-medium text-white bg-slate-900 rounded shadow-lg
|
|
67
|
+
bottom-full left-1/2 transform -translate-x-1/2 mb-2 whitespace-nowrap
|
|
68
|
+
animate-in fade-in zoom-in-95 duration-200
|
|
69
|
+
${className}
|
|
70
|
+
`,
|
|
71
|
+
children: [
|
|
72
|
+
children,
|
|
73
|
+
/* @__PURE__ */ jsx("div", { className: "absolute w-2 h-2 bg-slate-900 transform rotate-45 left-1/2 -translate-x-1/2 -bottom-1" })
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
TooltipProvider,
|
|
81
|
+
Tooltip,
|
|
82
|
+
TooltipTrigger,
|
|
83
|
+
TooltipContent
|
|
84
|
+
};
|