@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
package/dist/index.js
ADDED
|
@@ -0,0 +1,1256 @@
|
|
|
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/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
Accordion: () => Accordion,
|
|
34
|
+
AccordionContent: () => AccordionContent,
|
|
35
|
+
AccordionItem: () => AccordionItem,
|
|
36
|
+
AccordionTrigger: () => AccordionTrigger,
|
|
37
|
+
BreadcrumbItem: () => BreadcrumbItem,
|
|
38
|
+
Breadcrumbs: () => Breadcrumbs,
|
|
39
|
+
Button: () => Button,
|
|
40
|
+
Checkbox: () => Checkbox,
|
|
41
|
+
Dialog: () => Dialog,
|
|
42
|
+
FormField: () => FormField,
|
|
43
|
+
Heading: () => Heading,
|
|
44
|
+
Modal: () => Modal,
|
|
45
|
+
NavigationMenu: () => NavigationMenu,
|
|
46
|
+
RadioGroup: () => RadioGroup,
|
|
47
|
+
Select: () => Select,
|
|
48
|
+
SelectContent: () => SelectContent,
|
|
49
|
+
SelectItem: () => SelectItem,
|
|
50
|
+
SelectTrigger: () => SelectTrigger,
|
|
51
|
+
SkipLink: () => SkipLink,
|
|
52
|
+
Switch: () => Switch,
|
|
53
|
+
TabTrigger: () => TabTrigger,
|
|
54
|
+
Tabs: () => Tabs,
|
|
55
|
+
TabsContent: () => TabsContent,
|
|
56
|
+
TabsList: () => TabsList,
|
|
57
|
+
ToastProvider: () => ToastProvider,
|
|
58
|
+
Tooltip: () => Tooltip,
|
|
59
|
+
TooltipContent: () => TooltipContent,
|
|
60
|
+
TooltipProvider: () => TooltipProvider,
|
|
61
|
+
TooltipTrigger: () => TooltipTrigger,
|
|
62
|
+
useToast: () => useToast
|
|
63
|
+
});
|
|
64
|
+
module.exports = __toCommonJS(index_exports);
|
|
65
|
+
|
|
66
|
+
// src/Button/Button.tsx
|
|
67
|
+
var import_react = require("react");
|
|
68
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
69
|
+
var Button = (0, import_react.forwardRef)(
|
|
70
|
+
({
|
|
71
|
+
children,
|
|
72
|
+
variant = "primary",
|
|
73
|
+
size = "medium",
|
|
74
|
+
isLoading,
|
|
75
|
+
disabled,
|
|
76
|
+
className = "",
|
|
77
|
+
...props
|
|
78
|
+
}, ref) => {
|
|
79
|
+
const baseStyles = {
|
|
80
|
+
display: "inline-flex",
|
|
81
|
+
alignItems: "center",
|
|
82
|
+
justifyContent: "center",
|
|
83
|
+
borderRadius: "4px",
|
|
84
|
+
border: "none",
|
|
85
|
+
cursor: disabled || isLoading ? "not-allowed" : "pointer",
|
|
86
|
+
fontFamily: "inherit",
|
|
87
|
+
fontWeight: "600",
|
|
88
|
+
transition: "all 0.2s ease",
|
|
89
|
+
// Garantera synlig fokusindikator (WCAG 2.4.7)
|
|
90
|
+
outlineOffset: "2px"
|
|
91
|
+
};
|
|
92
|
+
const variants = {
|
|
93
|
+
primary: {
|
|
94
|
+
background: "#0056b3",
|
|
95
|
+
// AA Large, AAA Normal mot vit text
|
|
96
|
+
color: "#ffffff"
|
|
97
|
+
},
|
|
98
|
+
secondary: {
|
|
99
|
+
background: "#f8f9fa",
|
|
100
|
+
color: "#212529",
|
|
101
|
+
border: "1px solid #dee2e6"
|
|
102
|
+
},
|
|
103
|
+
danger: {
|
|
104
|
+
background: "#dc3545",
|
|
105
|
+
color: "#ffffff"
|
|
106
|
+
},
|
|
107
|
+
ghost: {
|
|
108
|
+
background: "transparent",
|
|
109
|
+
color: "#0056b3"
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const sizes = {
|
|
113
|
+
small: {
|
|
114
|
+
padding: "0.25rem 0.5rem",
|
|
115
|
+
fontSize: "0.875rem",
|
|
116
|
+
minHeight: "32px"
|
|
117
|
+
// OBS: Kan bryta mot 44px om inte hanteras med margin
|
|
118
|
+
},
|
|
119
|
+
medium: {
|
|
120
|
+
padding: "0.5rem 1rem",
|
|
121
|
+
fontSize: "1rem",
|
|
122
|
+
minHeight: "44px"
|
|
123
|
+
// Touch target safe
|
|
124
|
+
},
|
|
125
|
+
large: {
|
|
126
|
+
padding: "0.75rem 1.5rem",
|
|
127
|
+
fontSize: "1.25rem",
|
|
128
|
+
minHeight: "56px"
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const style = {
|
|
132
|
+
...baseStyles,
|
|
133
|
+
...variants[variant],
|
|
134
|
+
...sizes[size],
|
|
135
|
+
opacity: disabled || isLoading ? 0.65 : 1
|
|
136
|
+
};
|
|
137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
138
|
+
"button",
|
|
139
|
+
{
|
|
140
|
+
ref,
|
|
141
|
+
style,
|
|
142
|
+
disabled: disabled || isLoading,
|
|
143
|
+
"aria-busy": isLoading,
|
|
144
|
+
tabIndex: props.tabIndex,
|
|
145
|
+
...props,
|
|
146
|
+
children: [
|
|
147
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", style: { marginRight: "8px" }, children: "\u23F3" }) : null,
|
|
148
|
+
children
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
Button.displayName = "Button";
|
|
155
|
+
|
|
156
|
+
// src/FormField/FormField.tsx
|
|
157
|
+
var import_react2 = require("react");
|
|
158
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
159
|
+
var FormField = (0, import_react2.forwardRef)(
|
|
160
|
+
({
|
|
161
|
+
label,
|
|
162
|
+
error,
|
|
163
|
+
helpText,
|
|
164
|
+
required,
|
|
165
|
+
id,
|
|
166
|
+
className = "",
|
|
167
|
+
style,
|
|
168
|
+
...props
|
|
169
|
+
}, ref) => {
|
|
170
|
+
const generatedId = (0, import_react2.useId)();
|
|
171
|
+
const inputId = id || `input-${generatedId}`;
|
|
172
|
+
const helpTextId = `help-${generatedId}`;
|
|
173
|
+
const errorId = `error-${generatedId}`;
|
|
174
|
+
const describedBy = [
|
|
175
|
+
helpText ? helpTextId : null,
|
|
176
|
+
error ? errorId : null
|
|
177
|
+
].filter(Boolean).join(" ");
|
|
178
|
+
const containerStyle = {
|
|
179
|
+
display: "flex",
|
|
180
|
+
flexDirection: "column",
|
|
181
|
+
marginBottom: "1rem",
|
|
182
|
+
fontFamily: "system-ui, sans-serif",
|
|
183
|
+
...style
|
|
184
|
+
};
|
|
185
|
+
const labelStyle = {
|
|
186
|
+
marginBottom: "0.5rem",
|
|
187
|
+
fontWeight: "600",
|
|
188
|
+
color: "#333"
|
|
189
|
+
};
|
|
190
|
+
const inputStyle = {
|
|
191
|
+
padding: "0.5rem",
|
|
192
|
+
borderRadius: "4px",
|
|
193
|
+
border: error ? "2px solid #dc3545" : "1px solid #ced4da",
|
|
194
|
+
fontSize: "1rem",
|
|
195
|
+
minHeight: "44px"
|
|
196
|
+
// Touch target
|
|
197
|
+
};
|
|
198
|
+
const errorStyle = {
|
|
199
|
+
color: "#dc3545",
|
|
200
|
+
fontSize: "0.875rem",
|
|
201
|
+
marginTop: "0.25rem",
|
|
202
|
+
display: "flex",
|
|
203
|
+
alignItems: "center"
|
|
204
|
+
};
|
|
205
|
+
const helpStyle = {
|
|
206
|
+
color: "#6c757d",
|
|
207
|
+
fontSize: "0.875rem",
|
|
208
|
+
marginTop: "0.25rem"
|
|
209
|
+
};
|
|
210
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: containerStyle, className, children: [
|
|
211
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { htmlFor: inputId, style: labelStyle, children: [
|
|
212
|
+
label,
|
|
213
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { "aria-hidden": "true", style: { color: "#dc3545", marginLeft: "4px" }, children: "*" }),
|
|
214
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "sr-only", children: " (obligatoriskt)" })
|
|
215
|
+
] }),
|
|
216
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
217
|
+
"input",
|
|
218
|
+
{
|
|
219
|
+
ref,
|
|
220
|
+
id: inputId,
|
|
221
|
+
"aria-invalid": !!error,
|
|
222
|
+
"aria-describedby": describedBy || void 0,
|
|
223
|
+
"aria-required": required,
|
|
224
|
+
required,
|
|
225
|
+
style: inputStyle,
|
|
226
|
+
...props
|
|
227
|
+
}
|
|
228
|
+
),
|
|
229
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { id: errorId, style: errorStyle, role: "alert", children: [
|
|
230
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { "aria-hidden": "true", style: { marginRight: "4px" }, children: "\u26A0\uFE0F" }),
|
|
231
|
+
error
|
|
232
|
+
] }),
|
|
233
|
+
helpText && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { id: helpTextId, style: helpStyle, children: helpText })
|
|
234
|
+
] });
|
|
235
|
+
}
|
|
236
|
+
);
|
|
237
|
+
FormField.displayName = "FormField";
|
|
238
|
+
|
|
239
|
+
// src/Dialog/Dialog.tsx
|
|
240
|
+
var import_react3 = require("react");
|
|
241
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
242
|
+
var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
243
|
+
"svg",
|
|
244
|
+
{
|
|
245
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
246
|
+
width: "24",
|
|
247
|
+
height: "24",
|
|
248
|
+
viewBox: "0 0 24 24",
|
|
249
|
+
fill: "none",
|
|
250
|
+
stroke: "currentColor",
|
|
251
|
+
strokeWidth: "2",
|
|
252
|
+
strokeLinecap: "round",
|
|
253
|
+
strokeLinejoin: "round",
|
|
254
|
+
className: "h-5 w-5",
|
|
255
|
+
children: [
|
|
256
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M18 6 6 18" }),
|
|
257
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m6 6 12 12" })
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
var Dialog = (0, import_react3.forwardRef)(
|
|
262
|
+
({ isOpen, onClose, title, children, variant = "default", description, className, ...props }, ref) => {
|
|
263
|
+
const dialogRef = (0, import_react3.useRef)(null);
|
|
264
|
+
(0, import_react3.useImperativeHandle)(ref, () => dialogRef.current);
|
|
265
|
+
(0, import_react3.useEffect)(() => {
|
|
266
|
+
const dialog = dialogRef.current;
|
|
267
|
+
if (!dialog) return;
|
|
268
|
+
if (isOpen) {
|
|
269
|
+
if (!dialog.open) {
|
|
270
|
+
dialog.showModal();
|
|
271
|
+
document.body.style.overflow = "hidden";
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
if (dialog.open) {
|
|
275
|
+
dialog.close();
|
|
276
|
+
document.body.style.overflow = "";
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}, [isOpen]);
|
|
280
|
+
(0, import_react3.useEffect)(() => {
|
|
281
|
+
const dialog = dialogRef.current;
|
|
282
|
+
if (!dialog) return;
|
|
283
|
+
const handleClose = () => {
|
|
284
|
+
onClose();
|
|
285
|
+
document.body.style.overflow = "";
|
|
286
|
+
};
|
|
287
|
+
dialog.addEventListener("close", handleClose);
|
|
288
|
+
const handleBackdropClick = (e) => {
|
|
289
|
+
const rect = dialog.getBoundingClientRect();
|
|
290
|
+
const isInDialog = rect.top <= e.clientY && e.clientY <= rect.top + rect.height && rect.left <= e.clientX && e.clientX <= rect.left + rect.width;
|
|
291
|
+
if (!isInDialog) {
|
|
292
|
+
dialog.close();
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
dialog.addEventListener("click", handleBackdropClick);
|
|
296
|
+
return () => {
|
|
297
|
+
dialog.removeEventListener("close", handleClose);
|
|
298
|
+
dialog.removeEventListener("click", handleBackdropClick);
|
|
299
|
+
};
|
|
300
|
+
}, [onClose]);
|
|
301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
302
|
+
"dialog",
|
|
303
|
+
{
|
|
304
|
+
ref: dialogRef,
|
|
305
|
+
className: `
|
|
306
|
+
backdrop:bg-slate-900/50 backdrop:backdrop-blur-sm
|
|
307
|
+
open:animate-in open:fade-in-0 open:zoom-in-95
|
|
308
|
+
bg-white rounded-xl shadow-2xl ring-1 ring-slate-900/5
|
|
309
|
+
w-full max-w-lg p-0
|
|
310
|
+
${className || ""}
|
|
311
|
+
`,
|
|
312
|
+
"aria-labelledby": "dialog-title",
|
|
313
|
+
"aria-describedby": description ? "dialog-desc" : void 0,
|
|
314
|
+
...props,
|
|
315
|
+
children: [
|
|
316
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-b border-slate-100", children: [
|
|
317
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { id: "dialog-title", className: `text-lg font-semibold ${variant === "alert" ? "text-red-600" : "text-slate-900"}`, children: title }),
|
|
318
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
319
|
+
"button",
|
|
320
|
+
{
|
|
321
|
+
onClick: () => {
|
|
322
|
+
dialogRef.current?.close();
|
|
323
|
+
},
|
|
324
|
+
className: "p-1 rounded-md text-slate-400 hover:text-slate-500 hover:bg-slate-100 focus:outline-none focus:ring-2 focus:ring-primary-500 transition-colors",
|
|
325
|
+
"aria-label": "Close dialog",
|
|
326
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CloseIcon, {})
|
|
327
|
+
}
|
|
328
|
+
)
|
|
329
|
+
] }),
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "px-6 py-4", children: [
|
|
331
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { id: "dialog-desc", className: "text-sm text-slate-500 mb-4", children: description }),
|
|
332
|
+
children
|
|
333
|
+
] })
|
|
334
|
+
]
|
|
335
|
+
}
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
Dialog.displayName = "Dialog";
|
|
340
|
+
|
|
341
|
+
// src/Modal/Modal.tsx
|
|
342
|
+
var import_react4 = require("react");
|
|
343
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
344
|
+
var Modal = (0, import_react4.forwardRef)((props, ref) => {
|
|
345
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
346
|
+
Dialog,
|
|
347
|
+
{
|
|
348
|
+
ref,
|
|
349
|
+
...props,
|
|
350
|
+
className: `max-w-2xl ${props.className || ""}`
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
});
|
|
354
|
+
Modal.displayName = "Modal";
|
|
355
|
+
|
|
356
|
+
// src/SkipLink/SkipLink.tsx
|
|
357
|
+
var import_react5 = require("react");
|
|
358
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
359
|
+
var SkipLink = (0, import_react5.forwardRef)(
|
|
360
|
+
({ targetId = "main", className, style, children, ...props }, ref) => {
|
|
361
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
362
|
+
"a",
|
|
363
|
+
{
|
|
364
|
+
ref,
|
|
365
|
+
href: `#${targetId}`,
|
|
366
|
+
className: `
|
|
367
|
+
fixed top-4 left-4 z-50
|
|
368
|
+
px-4 py-3
|
|
369
|
+
bg-white text-slate-900 font-medium
|
|
370
|
+
rounded-md shadow-lg ring-2 ring-slate-900
|
|
371
|
+
transition-transform duration-200
|
|
372
|
+
-translate-y-[150%] focus:translate-y-0
|
|
373
|
+
${className || ""}
|
|
374
|
+
`,
|
|
375
|
+
style: {
|
|
376
|
+
// Ensure it stays on top of everything
|
|
377
|
+
zIndex: 9999,
|
|
378
|
+
...style
|
|
379
|
+
},
|
|
380
|
+
...props,
|
|
381
|
+
children: children || "Hoppa till huvudinneh\xE5ll"
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
);
|
|
386
|
+
SkipLink.displayName = "SkipLink";
|
|
387
|
+
|
|
388
|
+
// src/NavigationMenu/NavigationMenu.tsx
|
|
389
|
+
var import_react6 = require("react");
|
|
390
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
391
|
+
var NavigationMenu = (0, import_react6.forwardRef)(
|
|
392
|
+
({ items, className, "aria-label": ariaLabel = "Main Navigation" }, ref) => {
|
|
393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
394
|
+
"nav",
|
|
395
|
+
{
|
|
396
|
+
ref,
|
|
397
|
+
className: `flex items-center ${className || ""}`,
|
|
398
|
+
"aria-label": ariaLabel,
|
|
399
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "flex flex-wrap gap-2 m-0 p-0 list-none", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MenuItem, { item }, index)) })
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
);
|
|
404
|
+
NavigationMenu.displayName = "NavigationMenu";
|
|
405
|
+
var MenuItem = ({ item }) => {
|
|
406
|
+
const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
|
|
407
|
+
const containerRef = (0, import_react6.useRef)(null);
|
|
408
|
+
const timeoutRef = (0, import_react6.useRef)();
|
|
409
|
+
const hasChildren = item.children && item.children.length > 0;
|
|
410
|
+
(0, import_react6.useEffect)(() => {
|
|
411
|
+
const handleClickOutside = (event) => {
|
|
412
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
413
|
+
setIsOpen(false);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
if (isOpen) {
|
|
417
|
+
document.addEventListener("click", handleClickOutside);
|
|
418
|
+
}
|
|
419
|
+
return () => document.removeEventListener("click", handleClickOutside);
|
|
420
|
+
}, [isOpen]);
|
|
421
|
+
const handleKeyDown = (e) => {
|
|
422
|
+
if (e.key === "Escape" && isOpen) {
|
|
423
|
+
setIsOpen(false);
|
|
424
|
+
const trigger = containerRef.current?.querySelector("button");
|
|
425
|
+
trigger?.focus();
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
const handleMouseEnter = () => {
|
|
429
|
+
clearTimeout(timeoutRef.current);
|
|
430
|
+
setIsOpen(true);
|
|
431
|
+
};
|
|
432
|
+
const handleMouseLeave = () => {
|
|
433
|
+
timeoutRef.current = setTimeout(() => setIsOpen(false), 200);
|
|
434
|
+
};
|
|
435
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
436
|
+
"li",
|
|
437
|
+
{
|
|
438
|
+
ref: containerRef,
|
|
439
|
+
className: "relative group",
|
|
440
|
+
onKeyDown: handleKeyDown,
|
|
441
|
+
onMouseEnter: hasChildren ? handleMouseEnter : void 0,
|
|
442
|
+
onMouseLeave: hasChildren ? handleMouseLeave : void 0,
|
|
443
|
+
children: hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
444
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
445
|
+
"button",
|
|
446
|
+
{
|
|
447
|
+
onClick: () => setIsOpen(!isOpen),
|
|
448
|
+
"aria-expanded": isOpen,
|
|
449
|
+
"aria-haspopup": "true",
|
|
450
|
+
className: `
|
|
451
|
+
flex items-center gap-1 px-4 py-2 rounded-md
|
|
452
|
+
text-slate-700 font-medium hover:bg-slate-100 focus:bg-slate-100
|
|
453
|
+
transition-colors focus:outline-none focus:ring-2 focus:ring-primary-500
|
|
454
|
+
`,
|
|
455
|
+
children: [
|
|
456
|
+
item.label,
|
|
457
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
458
|
+
"svg",
|
|
459
|
+
{
|
|
460
|
+
className: `w-4 h-4 transition-transform ${isOpen ? "rotate-180" : ""}`,
|
|
461
|
+
fill: "none",
|
|
462
|
+
viewBox: "0 0 24 24",
|
|
463
|
+
stroke: "currentColor",
|
|
464
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
|
|
465
|
+
}
|
|
466
|
+
)
|
|
467
|
+
]
|
|
468
|
+
}
|
|
469
|
+
),
|
|
470
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
471
|
+
"ul",
|
|
472
|
+
{
|
|
473
|
+
className: `
|
|
474
|
+
absolute top-full left-0 mt-1 min-w-[200px]
|
|
475
|
+
bg-white border border-slate-200 rounded-lg shadow-xl
|
|
476
|
+
py-2 z-50
|
|
477
|
+
transform origin-top transition-all duration-200
|
|
478
|
+
${isOpen ? "opacity-100 scale-100 visible" : "opacity-0 scale-95 invisible"}
|
|
479
|
+
`,
|
|
480
|
+
children: item.children?.map((child, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
481
|
+
"a",
|
|
482
|
+
{
|
|
483
|
+
href: child.href,
|
|
484
|
+
className: "block px-4 py-2 text-slate-700 hover:bg-slate-50 hover:text-primary-600 focus:bg-slate-50 focus:text-primary-600 focus:outline-none",
|
|
485
|
+
children: child.label
|
|
486
|
+
}
|
|
487
|
+
) }, idx))
|
|
488
|
+
}
|
|
489
|
+
)
|
|
490
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
491
|
+
"a",
|
|
492
|
+
{
|
|
493
|
+
href: item.href,
|
|
494
|
+
className: "block px-4 py-2 text-slate-700 font-medium rounded-md hover:bg-slate-100 focus:bg-slate-100 transition-colors focus:outline-none focus:ring-2 focus:ring-primary-500",
|
|
495
|
+
children: item.label
|
|
496
|
+
}
|
|
497
|
+
)
|
|
498
|
+
}
|
|
499
|
+
);
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
// src/Checkbox/Checkbox.tsx
|
|
503
|
+
var import_react7 = require("react");
|
|
504
|
+
var import_lucide_react = require("lucide-react");
|
|
505
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
506
|
+
var Checkbox = (0, import_react7.forwardRef)(
|
|
507
|
+
({ className = "", checked, onCheckedChange, onChange, label, disabled, id, ...props }, ref) => {
|
|
508
|
+
const handleChange = (e) => {
|
|
509
|
+
onCheckedChange?.(e.target.checked);
|
|
510
|
+
onChange?.(e);
|
|
511
|
+
};
|
|
512
|
+
const generatedId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
|
|
513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex items-start ${className}`, children: [
|
|
514
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center h-5", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "relative", children: [
|
|
515
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
516
|
+
"input",
|
|
517
|
+
{
|
|
518
|
+
id: generatedId,
|
|
519
|
+
type: "checkbox",
|
|
520
|
+
ref,
|
|
521
|
+
className: "peer sr-only",
|
|
522
|
+
checked,
|
|
523
|
+
onChange: handleChange,
|
|
524
|
+
disabled,
|
|
525
|
+
...props
|
|
526
|
+
}
|
|
527
|
+
),
|
|
528
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
529
|
+
"div",
|
|
530
|
+
{
|
|
531
|
+
className: `
|
|
532
|
+
h-5 w-5 rounded border border-slate-300 bg-white shadow-sm transition-all
|
|
533
|
+
peer-focus:ring-2 peer-focus:ring-primary-500 peer-focus:ring-offset-2
|
|
534
|
+
peer-checked:bg-primary-600 peer-checked:border-primary-600
|
|
535
|
+
peer-disabled:cursor-not-allowed peer-disabled:opacity-50
|
|
536
|
+
hover:border-primary-400
|
|
537
|
+
flex items-center justify-center
|
|
538
|
+
`,
|
|
539
|
+
"aria-hidden": "true",
|
|
540
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react.Check, { className: `h-3.5 w-3.5 text-white transition-opacity ${checked ? "opacity-100" : "opacity-0"}`, strokeWidth: 3 })
|
|
541
|
+
}
|
|
542
|
+
)
|
|
543
|
+
] }) }),
|
|
544
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
545
|
+
"label",
|
|
546
|
+
{
|
|
547
|
+
htmlFor: generatedId,
|
|
548
|
+
className: `ml-3 text-sm font-medium ${disabled ? "text-slate-400" : "text-slate-700"} cursor-pointer select-none`,
|
|
549
|
+
children: label
|
|
550
|
+
}
|
|
551
|
+
)
|
|
552
|
+
] });
|
|
553
|
+
}
|
|
554
|
+
);
|
|
555
|
+
Checkbox.displayName = "Checkbox";
|
|
556
|
+
|
|
557
|
+
// src/RadioGroup/RadioGroup.tsx
|
|
558
|
+
var import_react8 = require("react");
|
|
559
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
560
|
+
var RadioGroup = (0, import_react8.forwardRef)(
|
|
561
|
+
({ name, options, value, onChange, orientation = "vertical", className = "", label }, ref) => {
|
|
562
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
563
|
+
"div",
|
|
564
|
+
{
|
|
565
|
+
ref,
|
|
566
|
+
className: `${className}`,
|
|
567
|
+
role: "radiogroup",
|
|
568
|
+
"aria-labelledby": label ? `${name}-label` : void 0,
|
|
569
|
+
children: [
|
|
570
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { id: `${name}-label`, className: "text-sm font-medium text-slate-900 mb-2", children: label }),
|
|
571
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: `flex ${orientation === "vertical" ? "flex-col space-y-3" : "flex-row space-x-6"}`, children: options.map((option) => {
|
|
572
|
+
const optionId = `${name}-${option.value}`;
|
|
573
|
+
const isChecked = value === option.value;
|
|
574
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center", children: [
|
|
575
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "relative flex items-center justify-center", children: [
|
|
576
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
577
|
+
"input",
|
|
578
|
+
{
|
|
579
|
+
id: optionId,
|
|
580
|
+
name,
|
|
581
|
+
type: "radio",
|
|
582
|
+
value: option.value,
|
|
583
|
+
checked: isChecked,
|
|
584
|
+
disabled: option.disabled,
|
|
585
|
+
onChange: (e) => {
|
|
586
|
+
if (e.target.checked) {
|
|
587
|
+
onChange?.(option.value);
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
className: "peer sr-only"
|
|
591
|
+
}
|
|
592
|
+
),
|
|
593
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
594
|
+
"div",
|
|
595
|
+
{
|
|
596
|
+
className: `
|
|
597
|
+
h-5 w-5 rounded-full border border-slate-300 bg-white shadow-sm transition-all
|
|
598
|
+
peer-focus:ring-2 peer-focus:ring-primary-500 peer-focus:ring-offset-2
|
|
599
|
+
peer-checked:border-primary-600 peer-checked:bg-white
|
|
600
|
+
peer-disabled:cursor-not-allowed peer-disabled:opacity-50
|
|
601
|
+
hover:border-primary-400
|
|
602
|
+
`,
|
|
603
|
+
"aria-hidden": "true"
|
|
604
|
+
}
|
|
605
|
+
),
|
|
606
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
607
|
+
"div",
|
|
608
|
+
{
|
|
609
|
+
className: `
|
|
610
|
+
absolute h-2.5 w-2.5 rounded-full bg-primary-600 transition-transform duration-200 scale-0
|
|
611
|
+
${isChecked ? "scale-100" : ""}
|
|
612
|
+
`
|
|
613
|
+
}
|
|
614
|
+
)
|
|
615
|
+
] }),
|
|
616
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
617
|
+
"label",
|
|
618
|
+
{
|
|
619
|
+
htmlFor: optionId,
|
|
620
|
+
className: `ml-3 text-sm font-medium ${option.disabled ? "text-slate-400" : "text-slate-700"} cursor-pointer select-none`,
|
|
621
|
+
children: option.label
|
|
622
|
+
}
|
|
623
|
+
)
|
|
624
|
+
] }, option.value);
|
|
625
|
+
}) })
|
|
626
|
+
]
|
|
627
|
+
}
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
);
|
|
631
|
+
RadioGroup.displayName = "RadioGroup";
|
|
632
|
+
|
|
633
|
+
// src/Breadcrumbs/Breadcrumbs.tsx
|
|
634
|
+
var import_react9 = __toESM(require("react"));
|
|
635
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
636
|
+
var BreadcrumbItem = ({ href, isCurrent, children, className, ...props }) => {
|
|
637
|
+
if (isCurrent) {
|
|
638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { className: `flex items-center text-slate-900 font-semibold ${className || ""}`, "aria-current": "page", ...props, children });
|
|
639
|
+
}
|
|
640
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { className: `flex items-center text-slate-500 hover:text-slate-700 transition-colors ${className || ""}`, ...props, children: href ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("a", { href, className: "hover:underline focus:outline-none focus:ring-2 focus:ring-primary-500 rounded-sm", children }) : children });
|
|
641
|
+
};
|
|
642
|
+
var Breadcrumbs = ({ separator, children, className, ...props }) => {
|
|
643
|
+
const separatorIcon = separator || /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-slate-400 mx-2", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "m9 18 6-6-6-6" }) });
|
|
644
|
+
const items = import_react9.Children.toArray(children).filter(import_react9.isValidElement);
|
|
645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("nav", { "aria-label": "Breadcrumb", className, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ol", { className: "flex items-center flex-wrap", children: items.map((child, index) => {
|
|
646
|
+
const isLast = index === items.length - 1;
|
|
647
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react9.default.Fragment, { children: [
|
|
648
|
+
(0, import_react9.cloneElement)(child, {
|
|
649
|
+
isCurrent: isLast || child.props.isCurrent
|
|
650
|
+
}),
|
|
651
|
+
!isLast && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { "aria-hidden": "true", className: "flex items-center select-none", children: separatorIcon })
|
|
652
|
+
] }, index);
|
|
653
|
+
}) }) });
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
// src/Accordion/Accordion.tsx
|
|
657
|
+
var import_react10 = __toESM(require("react"));
|
|
658
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
659
|
+
var ChevronIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
660
|
+
"svg",
|
|
661
|
+
{
|
|
662
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
663
|
+
width: "24",
|
|
664
|
+
height: "24",
|
|
665
|
+
viewBox: "0 0 24 24",
|
|
666
|
+
fill: "none",
|
|
667
|
+
stroke: "currentColor",
|
|
668
|
+
strokeWidth: "2",
|
|
669
|
+
strokeLinecap: "round",
|
|
670
|
+
strokeLinejoin: "round",
|
|
671
|
+
className,
|
|
672
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "m6 9 6 6 6-6" })
|
|
673
|
+
}
|
|
674
|
+
);
|
|
675
|
+
var AccordionContext = (0, import_react10.createContext)(void 0);
|
|
676
|
+
var Accordion = ({ type = "single", defaultValue, children, className }) => {
|
|
677
|
+
const [openItems, setOpenItems] = (0, import_react10.useState)(() => {
|
|
678
|
+
if (Array.isArray(defaultValue)) return defaultValue;
|
|
679
|
+
if (defaultValue) return [defaultValue];
|
|
680
|
+
return [];
|
|
681
|
+
});
|
|
682
|
+
const toggleItem = (value) => {
|
|
683
|
+
setOpenItems((prev) => {
|
|
684
|
+
if (type === "single") {
|
|
685
|
+
return prev.includes(value) ? [] : [value];
|
|
686
|
+
}
|
|
687
|
+
return prev.includes(value) ? prev.filter((item) => item !== value) : [...prev, value];
|
|
688
|
+
});
|
|
689
|
+
};
|
|
690
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(AccordionContext.Provider, { value: { openItems, toggleItem }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `space-y-1 ${className || ""}`, children }) });
|
|
691
|
+
};
|
|
692
|
+
var AccordionItem = ({ value, children, className }) => {
|
|
693
|
+
const context = (0, import_react10.useContext)(AccordionContext);
|
|
694
|
+
if (!context) throw new Error("AccordionItem must be used within an Accordion");
|
|
695
|
+
const isOpen = context.openItems.includes(value);
|
|
696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `border border-slate-200 rounded-lg overflow-hidden ${className || ""}`, children: import_react10.default.Children.map(children, (child) => {
|
|
697
|
+
if (import_react10.default.isValidElement(child)) {
|
|
698
|
+
return import_react10.default.cloneElement(child, {
|
|
699
|
+
...child.props,
|
|
700
|
+
value,
|
|
701
|
+
// Pass value down to Trigger and Content
|
|
702
|
+
isOpen
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
return child;
|
|
706
|
+
}) });
|
|
707
|
+
};
|
|
708
|
+
var AccordionTrigger = ({ children, className, value, isOpen, ...props }) => {
|
|
709
|
+
const context = (0, import_react10.useContext)(AccordionContext);
|
|
710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
711
|
+
"button",
|
|
712
|
+
{
|
|
713
|
+
type: "button",
|
|
714
|
+
className: `w-full flex items-center justify-between px-4 py-3 text-left font-medium text-slate-900 bg-white hover:bg-slate-50 transition-colors focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-inset ${className || ""}`,
|
|
715
|
+
onClick: () => value && context?.toggleItem(value),
|
|
716
|
+
"aria-expanded": isOpen,
|
|
717
|
+
"aria-controls": `accordion-content-${value}`,
|
|
718
|
+
id: `accordion-trigger-${value}`,
|
|
719
|
+
...props,
|
|
720
|
+
children: [
|
|
721
|
+
children,
|
|
722
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChevronIcon, { className: `h-4 w-4 text-slate-500 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}` })
|
|
723
|
+
]
|
|
724
|
+
}
|
|
725
|
+
);
|
|
726
|
+
};
|
|
727
|
+
var AccordionContent = ({ children, className, value, isOpen }) => {
|
|
728
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
729
|
+
"div",
|
|
730
|
+
{
|
|
731
|
+
id: `accordion-content-${value}`,
|
|
732
|
+
role: "region",
|
|
733
|
+
"aria-labelledby": `accordion-trigger-${value}`,
|
|
734
|
+
hidden: !isOpen,
|
|
735
|
+
className: `px-4 py-3 bg-white text-slate-600 border-t border-slate-100 text-sm leading-relaxed ${!isOpen ? "hidden" : ""} ${className || ""}`,
|
|
736
|
+
children
|
|
737
|
+
}
|
|
738
|
+
);
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
// src/Tabs/Tabs.tsx
|
|
742
|
+
var import_react11 = require("react");
|
|
743
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
744
|
+
var TabsContext = (0, import_react11.createContext)(void 0);
|
|
745
|
+
var Tabs = ({
|
|
746
|
+
defaultValue,
|
|
747
|
+
value,
|
|
748
|
+
onValueChange,
|
|
749
|
+
orientation = "horizontal",
|
|
750
|
+
activationMode = "automatic",
|
|
751
|
+
children,
|
|
752
|
+
className
|
|
753
|
+
}) => {
|
|
754
|
+
const [baseId] = (0, import_react11.useState)(() => Math.random().toString(36).substr(2, 9));
|
|
755
|
+
const [internalValue, setInternalValue] = (0, import_react11.useState)(defaultValue || "");
|
|
756
|
+
const isControlled = value !== void 0;
|
|
757
|
+
const activeTab = isControlled ? value : internalValue;
|
|
758
|
+
const setActiveTab = (newValue) => {
|
|
759
|
+
if (!isControlled) {
|
|
760
|
+
setInternalValue(newValue);
|
|
761
|
+
}
|
|
762
|
+
onValueChange?.(newValue);
|
|
763
|
+
};
|
|
764
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TabsContext.Provider, { value: { activeTab, setActiveTab, orientation, activationMode, baseId }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `flex ${orientation === "vertical" ? "flex-col md:flex-row gap-4" : "flex-col"} ${className || ""}`, children }) });
|
|
765
|
+
};
|
|
766
|
+
var TabsList = ({ children, className, ariaLabel }) => {
|
|
767
|
+
const context = (0, import_react11.useContext)(TabsContext);
|
|
768
|
+
if (!context) throw new Error("TabsList must be used within Tabs");
|
|
769
|
+
const listRef = (0, import_react11.useRef)(null);
|
|
770
|
+
const handleKeyDown = (e) => {
|
|
771
|
+
const list = listRef.current;
|
|
772
|
+
if (!list) return;
|
|
773
|
+
const tabs = Array.from(list.querySelectorAll('[role="tab"]:not([disabled])'));
|
|
774
|
+
const index = tabs.indexOf(document.activeElement);
|
|
775
|
+
if (index === -1) return;
|
|
776
|
+
let nextIndex = index;
|
|
777
|
+
const lastIndex = tabs.length - 1;
|
|
778
|
+
switch (e.key) {
|
|
779
|
+
case "ArrowLeft":
|
|
780
|
+
case "ArrowUp":
|
|
781
|
+
nextIndex = index === 0 ? lastIndex : index - 1;
|
|
782
|
+
break;
|
|
783
|
+
case "ArrowRight":
|
|
784
|
+
case "ArrowDown":
|
|
785
|
+
nextIndex = index === lastIndex ? 0 : index + 1;
|
|
786
|
+
break;
|
|
787
|
+
case "Home":
|
|
788
|
+
nextIndex = 0;
|
|
789
|
+
break;
|
|
790
|
+
case "End":
|
|
791
|
+
nextIndex = lastIndex;
|
|
792
|
+
break;
|
|
793
|
+
default:
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
e.preventDefault();
|
|
797
|
+
const nextTab = tabs[nextIndex];
|
|
798
|
+
nextTab.focus();
|
|
799
|
+
if (context.activationMode === "automatic") {
|
|
800
|
+
nextTab.click();
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
804
|
+
"div",
|
|
805
|
+
{
|
|
806
|
+
ref: listRef,
|
|
807
|
+
role: "tablist",
|
|
808
|
+
"aria-orientation": context.orientation,
|
|
809
|
+
"aria-label": ariaLabel,
|
|
810
|
+
className: `flex ${context.orientation === "vertical" ? "flex-col border-r border-slate-200" : "border-b border-slate-200"} ${className || ""}`,
|
|
811
|
+
onKeyDown: handleKeyDown,
|
|
812
|
+
tabIndex: -1,
|
|
813
|
+
children
|
|
814
|
+
}
|
|
815
|
+
);
|
|
816
|
+
};
|
|
817
|
+
var TabTrigger = ({ value, children, className, ...props }) => {
|
|
818
|
+
const context = (0, import_react11.useContext)(TabsContext);
|
|
819
|
+
if (!context) throw new Error("TabTrigger must be used within Tabs");
|
|
820
|
+
const isActive = context.activeTab === value;
|
|
821
|
+
const triggerId = `tab-${context.baseId}-${value}`;
|
|
822
|
+
const contentId = `content-${context.baseId}-${value}`;
|
|
823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
824
|
+
"button",
|
|
825
|
+
{
|
|
826
|
+
id: triggerId,
|
|
827
|
+
role: "tab",
|
|
828
|
+
"aria-selected": isActive,
|
|
829
|
+
"aria-controls": contentId,
|
|
830
|
+
tabIndex: isActive ? 0 : -1,
|
|
831
|
+
onClick: () => context.setActiveTab(value),
|
|
832
|
+
className: `
|
|
833
|
+
px-4 py-2 text-sm font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500
|
|
834
|
+
${context.orientation === "horizontal" ? "border-b-2" : "border-r-2 text-left"}
|
|
835
|
+
${isActive ? `border-primary-500 text-primary-600 bg-primary-50/50` : `border-transparent text-slate-500 hover:text-slate-700 hover:bg-slate-50`}
|
|
836
|
+
${className || ""}
|
|
837
|
+
`,
|
|
838
|
+
...props,
|
|
839
|
+
children
|
|
840
|
+
}
|
|
841
|
+
);
|
|
842
|
+
};
|
|
843
|
+
var TabsContent = ({ value, children, className }) => {
|
|
844
|
+
const context = (0, import_react11.useContext)(TabsContext);
|
|
845
|
+
if (!context) throw new Error("TabsContent must be used within Tabs");
|
|
846
|
+
const isActive = context.activeTab === value;
|
|
847
|
+
const triggerId = `tab-${context.baseId}-${value}`;
|
|
848
|
+
const contentId = `content-${context.baseId}-${value}`;
|
|
849
|
+
if (!isActive) return null;
|
|
850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
851
|
+
"div",
|
|
852
|
+
{
|
|
853
|
+
id: contentId,
|
|
854
|
+
role: "tabpanel",
|
|
855
|
+
"aria-labelledby": triggerId,
|
|
856
|
+
tabIndex: 0,
|
|
857
|
+
className: `py-4 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 rounded-md ${className || ""}`,
|
|
858
|
+
children
|
|
859
|
+
}
|
|
860
|
+
);
|
|
861
|
+
};
|
|
862
|
+
|
|
863
|
+
// src/Select/Select.tsx
|
|
864
|
+
var import_react12 = require("react");
|
|
865
|
+
var import_lucide_react2 = require("lucide-react");
|
|
866
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
867
|
+
var SelectContext = (0, import_react12.createContext)(void 0);
|
|
868
|
+
var Select = ({ value, onChange, children }) => {
|
|
869
|
+
const [isOpen, setIsOpen] = (0, import_react12.useState)(false);
|
|
870
|
+
const [highlightedIndex, setHighlightedIndex] = (0, import_react12.useState)(-1);
|
|
871
|
+
const optionsRef = (0, import_react12.useRef)([]);
|
|
872
|
+
const containerRef = (0, import_react12.useRef)(null);
|
|
873
|
+
(0, import_react12.useEffect)(() => {
|
|
874
|
+
const handleClickOutside = (event) => {
|
|
875
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
876
|
+
setIsOpen(false);
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
880
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
881
|
+
}, []);
|
|
882
|
+
const handleKeyDown = (e) => {
|
|
883
|
+
if (!isOpen) {
|
|
884
|
+
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
885
|
+
e.preventDefault();
|
|
886
|
+
setIsOpen(true);
|
|
887
|
+
setHighlightedIndex(0);
|
|
888
|
+
}
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
switch (e.key) {
|
|
892
|
+
case "ArrowDown":
|
|
893
|
+
e.preventDefault();
|
|
894
|
+
setHighlightedIndex((prev) => Math.min(prev + 1, optionsRef.current.length - 1));
|
|
895
|
+
break;
|
|
896
|
+
case "ArrowUp":
|
|
897
|
+
e.preventDefault();
|
|
898
|
+
setHighlightedIndex((prev) => Math.max(prev - 1, 0));
|
|
899
|
+
break;
|
|
900
|
+
case "Enter":
|
|
901
|
+
case " ":
|
|
902
|
+
e.preventDefault();
|
|
903
|
+
if (highlightedIndex >= 0 && highlightedIndex < optionsRef.current.length) {
|
|
904
|
+
const option = optionsRef.current[highlightedIndex];
|
|
905
|
+
if (option) {
|
|
906
|
+
option.click();
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
break;
|
|
910
|
+
case "Escape":
|
|
911
|
+
e.preventDefault();
|
|
912
|
+
setIsOpen(false);
|
|
913
|
+
break;
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectContext.Provider, { value: { value, onChange, isOpen, setIsOpen, highlightedIndex, setHighlightedIndex, optionsRef }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
917
|
+
"div",
|
|
918
|
+
{
|
|
919
|
+
ref: containerRef,
|
|
920
|
+
className: "relative inline-block text-left w-full",
|
|
921
|
+
onKeyDown: handleKeyDown,
|
|
922
|
+
children
|
|
923
|
+
}
|
|
924
|
+
) });
|
|
925
|
+
};
|
|
926
|
+
var SelectTrigger = ({ children, className = "", placeholder = "Select..." }) => {
|
|
927
|
+
const context = (0, import_react12.useContext)(SelectContext);
|
|
928
|
+
if (!context) throw new Error("SelectTrigger must be used within Select");
|
|
929
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
930
|
+
"button",
|
|
931
|
+
{
|
|
932
|
+
type: "button",
|
|
933
|
+
onClick: () => context.setIsOpen(!context.isOpen),
|
|
934
|
+
"aria-haspopup": "listbox",
|
|
935
|
+
"aria-expanded": context.isOpen,
|
|
936
|
+
className: `flex items-center justify-between w-full px-4 py-2 text-sm bg-white border border-slate-300 rounded-md focus:outline-none focus:ring-2 focus:ring-slate-900 focus:border-transparent ${className}`,
|
|
937
|
+
children: [
|
|
938
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: context.value ? "text-slate-900" : "text-slate-500", children: children || placeholder }),
|
|
939
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react2.ChevronDown, { className: "w-4 h-4 ml-2 opacity-50" })
|
|
940
|
+
]
|
|
941
|
+
}
|
|
942
|
+
);
|
|
943
|
+
};
|
|
944
|
+
var SelectContent = ({ children }) => {
|
|
945
|
+
const context = (0, import_react12.useContext)(SelectContext);
|
|
946
|
+
(0, import_react12.useEffect)(() => {
|
|
947
|
+
if (context && context.isOpen) {
|
|
948
|
+
context.optionsRef.current = [];
|
|
949
|
+
}
|
|
950
|
+
}, [context?.isOpen]);
|
|
951
|
+
if (!context || !context.isOpen) return null;
|
|
952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
953
|
+
"div",
|
|
954
|
+
{
|
|
955
|
+
className: "absolute z-10 w-full mt-1 bg-white border border-slate-200 rounded-md shadow-lg max-h-60 overflow-auto focus:outline-none",
|
|
956
|
+
role: "listbox",
|
|
957
|
+
children
|
|
958
|
+
}
|
|
959
|
+
);
|
|
960
|
+
};
|
|
961
|
+
var SelectItem = ({ value, children }) => {
|
|
962
|
+
const context = (0, import_react12.useContext)(SelectContext);
|
|
963
|
+
if (!context) throw new Error("SelectItem must be used within Select");
|
|
964
|
+
const isSelected = context.value === value;
|
|
965
|
+
const index = context.optionsRef.current.length;
|
|
966
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
967
|
+
"div",
|
|
968
|
+
{
|
|
969
|
+
ref: (el) => {
|
|
970
|
+
context.optionsRef.current[index] = el;
|
|
971
|
+
},
|
|
972
|
+
role: "option",
|
|
973
|
+
"aria-selected": isSelected,
|
|
974
|
+
onClick: () => {
|
|
975
|
+
context.onChange(value);
|
|
976
|
+
context.setIsOpen(false);
|
|
977
|
+
},
|
|
978
|
+
className: `flex items-center justify-between px-4 py-2 text-sm cursor-pointer ${context.highlightedIndex === index ? "bg-slate-100" : ""} ${isSelected ? "bg-slate-50 text-slate-900 font-medium" : "text-slate-700"}`,
|
|
979
|
+
children: [
|
|
980
|
+
children,
|
|
981
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react2.Check, { className: "w-4 h-4 text-slate-900" })
|
|
982
|
+
]
|
|
983
|
+
}
|
|
984
|
+
);
|
|
985
|
+
};
|
|
986
|
+
|
|
987
|
+
// src/Switch/Switch.tsx
|
|
988
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
989
|
+
var Switch = ({ checked, onCheckedChange, disabled = false, label, id }) => {
|
|
990
|
+
const generatedId = id || `switch-${Math.random().toString(36).substr(2, 9)}`;
|
|
991
|
+
const handleClick = () => {
|
|
992
|
+
if (!disabled) {
|
|
993
|
+
onCheckedChange(!checked);
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
const handleKeyDown = (e) => {
|
|
997
|
+
if (disabled) return;
|
|
998
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
999
|
+
e.preventDefault();
|
|
1000
|
+
onCheckedChange(!checked);
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
1004
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1005
|
+
"button",
|
|
1006
|
+
{
|
|
1007
|
+
type: "button",
|
|
1008
|
+
role: "switch",
|
|
1009
|
+
"aria-checked": checked,
|
|
1010
|
+
id: generatedId,
|
|
1011
|
+
disabled,
|
|
1012
|
+
onClick: handleClick,
|
|
1013
|
+
onKeyDown: handleKeyDown,
|
|
1014
|
+
className: `
|
|
1015
|
+
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
|
|
1016
|
+
${checked ? "bg-primary-600" : "bg-slate-200"}
|
|
1017
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
1018
|
+
`,
|
|
1019
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1020
|
+
"span",
|
|
1021
|
+
{
|
|
1022
|
+
className: `
|
|
1023
|
+
inline-block h-4 w-4 transform rounded-full bg-white transition-transform
|
|
1024
|
+
${checked ? "translate-x-6" : "translate-x-1"}
|
|
1025
|
+
`
|
|
1026
|
+
}
|
|
1027
|
+
)
|
|
1028
|
+
}
|
|
1029
|
+
),
|
|
1030
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1031
|
+
"label",
|
|
1032
|
+
{
|
|
1033
|
+
htmlFor: generatedId,
|
|
1034
|
+
className: `text-sm font-medium text-slate-700 cursor-pointer ${disabled ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
1035
|
+
onClick: handleClick,
|
|
1036
|
+
children: label
|
|
1037
|
+
}
|
|
1038
|
+
)
|
|
1039
|
+
] });
|
|
1040
|
+
};
|
|
1041
|
+
|
|
1042
|
+
// src/Toast/Toast.tsx
|
|
1043
|
+
var import_react13 = require("react");
|
|
1044
|
+
var import_lucide_react3 = require("lucide-react");
|
|
1045
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1046
|
+
var ToastContext = (0, import_react13.createContext)(void 0);
|
|
1047
|
+
var ToastProvider = ({ children }) => {
|
|
1048
|
+
const [toasts, setToasts] = (0, import_react13.useState)([]);
|
|
1049
|
+
const addToast = (0, import_react13.useCallback)((toast) => {
|
|
1050
|
+
const id = Math.random().toString(36).substr(2, 9);
|
|
1051
|
+
setToasts((prev) => [...prev, { ...toast, id }]);
|
|
1052
|
+
}, []);
|
|
1053
|
+
const removeToast = (0, import_react13.useCallback)((id) => {
|
|
1054
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
1055
|
+
}, []);
|
|
1056
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [
|
|
1057
|
+
children,
|
|
1058
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToastViewport, {})
|
|
1059
|
+
] });
|
|
1060
|
+
};
|
|
1061
|
+
var useToast = () => {
|
|
1062
|
+
const context = (0, import_react13.useContext)(ToastContext);
|
|
1063
|
+
if (!context) {
|
|
1064
|
+
throw new Error("useToast must be used within a ToastProvider");
|
|
1065
|
+
}
|
|
1066
|
+
return context;
|
|
1067
|
+
};
|
|
1068
|
+
var ToastViewport = () => {
|
|
1069
|
+
const { toasts, removeToast } = useToast();
|
|
1070
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1071
|
+
"div",
|
|
1072
|
+
{
|
|
1073
|
+
className: "fixed bottom-0 right-0 z-50 p-4 w-full md:max-w-sm flex flex-col gap-2",
|
|
1074
|
+
role: "region",
|
|
1075
|
+
"aria-label": "Notifications",
|
|
1076
|
+
children: toasts.map((toast) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToastItem, { toast, onRemove: () => removeToast(toast.id) }, toast.id))
|
|
1077
|
+
}
|
|
1078
|
+
);
|
|
1079
|
+
};
|
|
1080
|
+
var ToastItem = ({ toast, onRemove }) => {
|
|
1081
|
+
(0, import_react13.useEffect)(() => {
|
|
1082
|
+
if (toast.duration === Infinity) return;
|
|
1083
|
+
const timer = setTimeout(() => {
|
|
1084
|
+
onRemove();
|
|
1085
|
+
}, toast.duration || 5e3);
|
|
1086
|
+
return () => clearTimeout(timer);
|
|
1087
|
+
}, [toast, onRemove]);
|
|
1088
|
+
const icons = {
|
|
1089
|
+
info: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react3.Info, { className: "w-5 h-5 text-blue-500" }),
|
|
1090
|
+
success: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react3.CheckCircle, { className: "w-5 h-5 text-green-500" }),
|
|
1091
|
+
warning: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react3.AlertTriangle, { className: "w-5 h-5 text-amber-500" }),
|
|
1092
|
+
error: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react3.AlertCircle, { className: "w-5 h-5 text-red-500" })
|
|
1093
|
+
};
|
|
1094
|
+
const bgColors = {
|
|
1095
|
+
info: "bg-white border-blue-100",
|
|
1096
|
+
success: "bg-white border-green-100",
|
|
1097
|
+
warning: "bg-white border-amber-100",
|
|
1098
|
+
error: "bg-white border-red-100"
|
|
1099
|
+
};
|
|
1100
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1101
|
+
"div",
|
|
1102
|
+
{
|
|
1103
|
+
role: "alert",
|
|
1104
|
+
className: `
|
|
1105
|
+
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
|
|
1106
|
+
${bgColors[toast.type || "info"]}
|
|
1107
|
+
`,
|
|
1108
|
+
children: [
|
|
1109
|
+
icons[toast.type || "info"],
|
|
1110
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex-1", children: [
|
|
1111
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h4", { className: "text-sm font-medium text-slate-900", children: toast.title }),
|
|
1112
|
+
toast.description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm text-slate-600 mt-1", children: toast.description }),
|
|
1113
|
+
toast.action && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1114
|
+
"button",
|
|
1115
|
+
{
|
|
1116
|
+
onClick: toast.action.onClick,
|
|
1117
|
+
className: "mt-2 text-sm font-medium text-slate-900 underline hover:no-underline",
|
|
1118
|
+
children: toast.action.label
|
|
1119
|
+
}
|
|
1120
|
+
)
|
|
1121
|
+
] }),
|
|
1122
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1123
|
+
"button",
|
|
1124
|
+
{
|
|
1125
|
+
onClick: onRemove,
|
|
1126
|
+
className: "text-slate-400 hover:text-slate-900 transition-colors",
|
|
1127
|
+
"aria-label": "Close",
|
|
1128
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react3.X, { className: "w-4 h-4" })
|
|
1129
|
+
}
|
|
1130
|
+
)
|
|
1131
|
+
]
|
|
1132
|
+
}
|
|
1133
|
+
);
|
|
1134
|
+
};
|
|
1135
|
+
|
|
1136
|
+
// src/Tooltip/Tooltip.tsx
|
|
1137
|
+
var import_react14 = __toESM(require("react"));
|
|
1138
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1139
|
+
var TooltipContext = (0, import_react14.createContext)(void 0);
|
|
1140
|
+
var TooltipProvider = ({ children }) => {
|
|
1141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children });
|
|
1142
|
+
};
|
|
1143
|
+
var Tooltip = ({ children }) => {
|
|
1144
|
+
const [open, setOpen] = (0, import_react14.useState)(false);
|
|
1145
|
+
const id = (0, import_react14.useRef)(`tooltip-${Math.random().toString(36).substr(2, 9)}`).current;
|
|
1146
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TooltipContext.Provider, { value: { open, setOpen, id }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "relative inline-block group", onMouseLeave: () => setOpen(false), children }) });
|
|
1147
|
+
};
|
|
1148
|
+
var TooltipTrigger = ({ children, asChild = false, ...props }) => {
|
|
1149
|
+
const context = (0, import_react14.useContext)(TooltipContext);
|
|
1150
|
+
if (!context) throw new Error("TooltipTrigger must be used within Tooltip");
|
|
1151
|
+
const { setOpen, id } = context;
|
|
1152
|
+
const handleOpen = () => setOpen(true);
|
|
1153
|
+
const handleClose = () => setOpen(false);
|
|
1154
|
+
if (import_react14.default.isValidElement(children)) {
|
|
1155
|
+
return import_react14.default.cloneElement(children, {
|
|
1156
|
+
"aria-describedby": context.open ? id : void 0,
|
|
1157
|
+
onMouseEnter: (e) => {
|
|
1158
|
+
handleOpen();
|
|
1159
|
+
children.props.onMouseEnter?.(e);
|
|
1160
|
+
},
|
|
1161
|
+
onMouseLeave: (e) => {
|
|
1162
|
+
handleClose();
|
|
1163
|
+
children.props.onMouseLeave?.(e);
|
|
1164
|
+
},
|
|
1165
|
+
onFocus: (e) => {
|
|
1166
|
+
handleOpen();
|
|
1167
|
+
children.props.onFocus?.(e);
|
|
1168
|
+
},
|
|
1169
|
+
onBlur: (e) => {
|
|
1170
|
+
handleClose();
|
|
1171
|
+
children.props.onBlur?.(e);
|
|
1172
|
+
},
|
|
1173
|
+
...props
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1177
|
+
"span",
|
|
1178
|
+
{
|
|
1179
|
+
"aria-describedby": context.open ? id : void 0,
|
|
1180
|
+
onMouseEnter: handleOpen,
|
|
1181
|
+
onMouseLeave: handleClose,
|
|
1182
|
+
onFocus: handleOpen,
|
|
1183
|
+
onBlur: handleClose,
|
|
1184
|
+
tabIndex: 0,
|
|
1185
|
+
className: "cursor-default",
|
|
1186
|
+
...props,
|
|
1187
|
+
children
|
|
1188
|
+
}
|
|
1189
|
+
);
|
|
1190
|
+
};
|
|
1191
|
+
var TooltipContent = ({ children, className = "" }) => {
|
|
1192
|
+
const context = (0, import_react14.useContext)(TooltipContext);
|
|
1193
|
+
if (!context) throw new Error("TooltipContent must be used within Tooltip");
|
|
1194
|
+
if (!context.open) return null;
|
|
1195
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1196
|
+
"div",
|
|
1197
|
+
{
|
|
1198
|
+
id: context.id,
|
|
1199
|
+
role: "tooltip",
|
|
1200
|
+
className: `
|
|
1201
|
+
absolute z-50 px-3 py-2 text-sm font-medium text-white bg-slate-900 rounded shadow-lg
|
|
1202
|
+
bottom-full left-1/2 transform -translate-x-1/2 mb-2 whitespace-nowrap
|
|
1203
|
+
animate-in fade-in zoom-in-95 duration-200
|
|
1204
|
+
${className}
|
|
1205
|
+
`,
|
|
1206
|
+
children: [
|
|
1207
|
+
children,
|
|
1208
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "absolute w-2 h-2 bg-slate-900 transform rotate-45 left-1/2 -translate-x-1/2 -bottom-1" })
|
|
1209
|
+
]
|
|
1210
|
+
}
|
|
1211
|
+
);
|
|
1212
|
+
};
|
|
1213
|
+
|
|
1214
|
+
// src/Heading/Heading.tsx
|
|
1215
|
+
var import_react15 = __toESM(require("react"));
|
|
1216
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1217
|
+
var Heading = import_react15.default.forwardRef(
|
|
1218
|
+
({ level, children, className, ...props }, ref) => {
|
|
1219
|
+
const Tag = `h${level}`;
|
|
1220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Tag, { ref, className, ...props, children });
|
|
1221
|
+
}
|
|
1222
|
+
);
|
|
1223
|
+
Heading.displayName = "Heading";
|
|
1224
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1225
|
+
0 && (module.exports = {
|
|
1226
|
+
Accordion,
|
|
1227
|
+
AccordionContent,
|
|
1228
|
+
AccordionItem,
|
|
1229
|
+
AccordionTrigger,
|
|
1230
|
+
BreadcrumbItem,
|
|
1231
|
+
Breadcrumbs,
|
|
1232
|
+
Button,
|
|
1233
|
+
Checkbox,
|
|
1234
|
+
Dialog,
|
|
1235
|
+
FormField,
|
|
1236
|
+
Heading,
|
|
1237
|
+
Modal,
|
|
1238
|
+
NavigationMenu,
|
|
1239
|
+
RadioGroup,
|
|
1240
|
+
Select,
|
|
1241
|
+
SelectContent,
|
|
1242
|
+
SelectItem,
|
|
1243
|
+
SelectTrigger,
|
|
1244
|
+
SkipLink,
|
|
1245
|
+
Switch,
|
|
1246
|
+
TabTrigger,
|
|
1247
|
+
Tabs,
|
|
1248
|
+
TabsContent,
|
|
1249
|
+
TabsList,
|
|
1250
|
+
ToastProvider,
|
|
1251
|
+
Tooltip,
|
|
1252
|
+
TooltipContent,
|
|
1253
|
+
TooltipProvider,
|
|
1254
|
+
TooltipTrigger,
|
|
1255
|
+
useToast
|
|
1256
|
+
});
|