@dynamicnorway/react 1.0.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/dist/index.js ADDED
@@ -0,0 +1,1705 @@
1
+ // src/lib/utils.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ // src/components/button.tsx
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ var buttonVariantClasses = {
11
+ primary: "bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500 border-transparent",
12
+ secondary: "bg-background-secondary text-text-primary hover:bg-background-tertiary focus:ring-primary-500 border-border-primary",
13
+ outline: "bg-transparent text-text-primary hover:bg-background-tertiary focus:ring-primary-500 border-border-primary",
14
+ danger: "bg-red-600 text-white hover:bg-red-700 focus:ring-red-500 border-transparent",
15
+ destructive: "bg-red-600 text-white hover:bg-red-700 focus:ring-red-500 border-transparent",
16
+ ghost: "bg-transparent text-text-primary hover:bg-background-tertiary focus:ring-primary-500 border-transparent"
17
+ };
18
+ var buttonSizeClasses = {
19
+ sm: "px-3 py-1.5 text-sm",
20
+ md: "px-4 py-2 text-sm",
21
+ lg: "px-6 py-3 text-base"
22
+ };
23
+ var Button = ({
24
+ className = "",
25
+ variant = "primary",
26
+ size = "md",
27
+ loading = false,
28
+ fullWidth = false,
29
+ disabled,
30
+ children,
31
+ ref,
32
+ ...props
33
+ }) => {
34
+ return /* @__PURE__ */ jsxs(
35
+ "button",
36
+ {
37
+ ref,
38
+ disabled: disabled || loading,
39
+ className: `
40
+ inline-flex items-center justify-center
41
+ font-medium rounded-md border
42
+ focus:outline-none focus:ring-2 focus:ring-offset-2
43
+ cursor-pointer
44
+ disabled:opacity-50 disabled:cursor-not-allowed
45
+ transition-colors
46
+ ${buttonVariantClasses[variant]}
47
+ ${buttonSizeClasses[size]}
48
+ ${fullWidth ? "w-full" : ""}
49
+ ${className}
50
+ `.trim().replace(/\s+/g, " "),
51
+ ...props,
52
+ children: [
53
+ loading && /* @__PURE__ */ jsxs(
54
+ "svg",
55
+ {
56
+ className: "animate-spin -ml-1 mr-2 h-4 w-4",
57
+ fill: "none",
58
+ viewBox: "0 0 24 24",
59
+ children: [
60
+ /* @__PURE__ */ jsx(
61
+ "circle",
62
+ {
63
+ className: "opacity-25",
64
+ cx: "12",
65
+ cy: "12",
66
+ r: "10",
67
+ stroke: "currentColor",
68
+ strokeWidth: "4"
69
+ }
70
+ ),
71
+ /* @__PURE__ */ jsx(
72
+ "path",
73
+ {
74
+ className: "opacity-75",
75
+ fill: "currentColor",
76
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
77
+ }
78
+ )
79
+ ]
80
+ }
81
+ ),
82
+ children
83
+ ]
84
+ }
85
+ );
86
+ };
87
+ Button.displayName = "Button";
88
+
89
+ // src/components/form-field.tsx
90
+ import React, { useId } from "react";
91
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
92
+ function FormField({
93
+ label,
94
+ required = false,
95
+ error,
96
+ helperText,
97
+ className = "",
98
+ children,
99
+ htmlFor
100
+ }) {
101
+ const generatedId = useId();
102
+ const inputId = htmlFor || generatedId;
103
+ return /* @__PURE__ */ jsxs2("div", { className: `space-y-1 ${className}`, children: [
104
+ label && /* @__PURE__ */ jsxs2(
105
+ "label",
106
+ {
107
+ htmlFor: inputId,
108
+ className: "block text-sm font-medium text-text-primary",
109
+ children: [
110
+ label,
111
+ required && /* @__PURE__ */ jsx2("span", { className: "text-red-500 ml-1", children: "*" })
112
+ ]
113
+ }
114
+ ),
115
+ React.isValidElement(children) ? React.cloneElement(children, {
116
+ id: inputId,
117
+ "aria-invalid": !!error,
118
+ "aria-describedby": error ? `${inputId}-error` : helperText ? `${inputId}-helper` : void 0
119
+ }) : children,
120
+ error && /* @__PURE__ */ jsx2(
121
+ "p",
122
+ {
123
+ id: `${inputId}-error`,
124
+ className: "text-sm text-red-600 dark:text-red-400",
125
+ role: "alert",
126
+ children: error
127
+ }
128
+ ),
129
+ !error && helperText && /* @__PURE__ */ jsx2(
130
+ "p",
131
+ {
132
+ id: `${inputId}-helper`,
133
+ className: "text-sm text-text-secondary",
134
+ children: helperText
135
+ }
136
+ )
137
+ ] });
138
+ }
139
+
140
+ // src/components/input-styles.ts
141
+ var baseInputClasses = `
142
+ w-full px-3 py-2
143
+ border rounded-md
144
+ text-text-primary
145
+ bg-background-secondary
146
+ border-border-primary
147
+ placeholder-text-tertiary
148
+ focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500
149
+ disabled:bg-background-tertiary disabled:cursor-not-allowed disabled:opacity-60
150
+ transition-colors
151
+ `.trim().replace(/\s+/g, " ");
152
+ var errorInputClasses = `
153
+ border-red-500 dark:border-red-500
154
+ focus:ring-red-500 focus:border-red-500
155
+ `.trim().replace(/\s+/g, " ");
156
+
157
+ // src/components/input.tsx
158
+ import { jsx as jsx3 } from "react/jsx-runtime";
159
+ var Input = ({
160
+ className = "",
161
+ hasError = false,
162
+ onKeyDown,
163
+ ref,
164
+ ...props
165
+ }) => {
166
+ const handleKeyDown = (e) => {
167
+ if ((e.metaKey || e.ctrlKey) && e.key === "a") {
168
+ e.preventDefault();
169
+ e.currentTarget.select();
170
+ }
171
+ onKeyDown?.(e);
172
+ };
173
+ return /* @__PURE__ */ jsx3(
174
+ "input",
175
+ {
176
+ ref,
177
+ className: `${baseInputClasses} ${hasError ? errorInputClasses : ""} ${className}`,
178
+ onKeyDown: handleKeyDown,
179
+ ...props
180
+ }
181
+ );
182
+ };
183
+ Input.displayName = "Input";
184
+
185
+ // src/components/textarea.tsx
186
+ import { jsx as jsx4 } from "react/jsx-runtime";
187
+ var Textarea = ({
188
+ className = "",
189
+ hasError = false,
190
+ autoResize = false,
191
+ onChange,
192
+ onKeyDown,
193
+ ref,
194
+ ...props
195
+ }) => {
196
+ const handleChange = (e) => {
197
+ if (autoResize) {
198
+ e.target.style.height = "auto";
199
+ e.target.style.height = `${e.target.scrollHeight}px`;
200
+ }
201
+ onChange?.(e);
202
+ };
203
+ const handleKeyDown = (e) => {
204
+ if ((e.metaKey || e.ctrlKey) && e.key === "a") {
205
+ e.preventDefault();
206
+ e.currentTarget.select();
207
+ }
208
+ onKeyDown?.(e);
209
+ };
210
+ return /* @__PURE__ */ jsx4(
211
+ "textarea",
212
+ {
213
+ ref,
214
+ className: `${baseInputClasses} ${hasError ? errorInputClasses : ""} ${autoResize ? "resize-none overflow-hidden" : ""} ${className}`,
215
+ onChange: handleChange,
216
+ onKeyDown: handleKeyDown,
217
+ ...props
218
+ }
219
+ );
220
+ };
221
+ Textarea.displayName = "Textarea";
222
+
223
+ // src/components/select.tsx
224
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
225
+ var Select = ({
226
+ className = "",
227
+ hasError = false,
228
+ placeholder,
229
+ options,
230
+ children,
231
+ ref,
232
+ ...props
233
+ }) => {
234
+ return /* @__PURE__ */ jsxs3(
235
+ "select",
236
+ {
237
+ ref,
238
+ className: `${baseInputClasses} ${hasError ? errorInputClasses : ""} ${className}`,
239
+ ...props,
240
+ children: [
241
+ placeholder && /* @__PURE__ */ jsx5("option", { value: "", disabled: true, children: placeholder }),
242
+ options ? options.map((option) => /* @__PURE__ */ jsx5(
243
+ "option",
244
+ {
245
+ value: option.value,
246
+ disabled: option.disabled,
247
+ children: option.label
248
+ },
249
+ option.value
250
+ )) : children
251
+ ]
252
+ }
253
+ );
254
+ };
255
+ Select.displayName = "Select";
256
+
257
+ // src/components/checkbox.tsx
258
+ import { useId as useId2 } from "react";
259
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
260
+ var Checkbox = ({
261
+ className = "",
262
+ label,
263
+ id,
264
+ ref,
265
+ ...props
266
+ }) => {
267
+ const generatedId = useId2();
268
+ const checkboxId = id || generatedId;
269
+ return /* @__PURE__ */ jsxs4("div", { className: `flex items-center ${className}`, children: [
270
+ /* @__PURE__ */ jsx6(
271
+ "input",
272
+ {
273
+ ref,
274
+ type: "checkbox",
275
+ id: checkboxId,
276
+ className: "h-4 w-4 rounded border-border-primary text-primary-600 focus:ring-primary-500 bg-background-secondary",
277
+ ...props
278
+ }
279
+ ),
280
+ label && /* @__PURE__ */ jsx6("label", { htmlFor: checkboxId, className: "ml-2 text-sm text-text-primary", children: label })
281
+ ] });
282
+ };
283
+ Checkbox.displayName = "Checkbox";
284
+
285
+ // src/components/dialog.tsx
286
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
287
+ import { X } from "lucide-react";
288
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
289
+ var Dialog = DialogPrimitive.Root;
290
+ var DialogTrigger = DialogPrimitive.Trigger;
291
+ var DialogPortal = DialogPrimitive.Portal;
292
+ var DialogClose = DialogPrimitive.Close;
293
+ var DialogOverlay = ({ className, ref, ...props }) => /* @__PURE__ */ jsx7(
294
+ DialogPrimitive.Overlay,
295
+ {
296
+ ref,
297
+ className: cn(
298
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
299
+ className
300
+ ),
301
+ ...props
302
+ }
303
+ );
304
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
305
+ var DialogContent = ({
306
+ className,
307
+ children,
308
+ closeLabel = "Close",
309
+ ref,
310
+ ...props
311
+ }) => /* @__PURE__ */ jsxs5(DialogPortal, { children: [
312
+ /* @__PURE__ */ jsx7(DialogOverlay, {}),
313
+ /* @__PURE__ */ jsxs5(
314
+ DialogPrimitive.Content,
315
+ {
316
+ ref,
317
+ className: cn(
318
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-full data-[state=open]:slide-in-from-left-full sm:rounded-lg",
319
+ className
320
+ ),
321
+ ...props,
322
+ children: [
323
+ children,
324
+ /* @__PURE__ */ jsxs5(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
325
+ /* @__PURE__ */ jsx7(X, { className: "h-4 w-4" }),
326
+ /* @__PURE__ */ jsx7("span", { className: "sr-only", children: closeLabel })
327
+ ] })
328
+ ]
329
+ }
330
+ )
331
+ ] });
332
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
333
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx7("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
334
+ DialogHeader.displayName = "DialogHeader";
335
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx7(
336
+ "div",
337
+ {
338
+ className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
339
+ ...props
340
+ }
341
+ );
342
+ DialogFooter.displayName = "DialogFooter";
343
+ var DialogTitle = ({ className, ref, ...props }) => /* @__PURE__ */ jsx7(
344
+ DialogPrimitive.Title,
345
+ {
346
+ ref,
347
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
348
+ ...props
349
+ }
350
+ );
351
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
352
+ var DialogDescription = ({ className, ref, ...props }) => /* @__PURE__ */ jsx7(
353
+ DialogPrimitive.Description,
354
+ {
355
+ ref,
356
+ className: cn("text-sm text-muted-foreground", className),
357
+ ...props
358
+ }
359
+ );
360
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
361
+ var ConfirmDialog = ({
362
+ open,
363
+ onClose,
364
+ onConfirm,
365
+ title,
366
+ message,
367
+ confirmText = "Confirm",
368
+ cancelText = "Cancel",
369
+ variant = "default",
370
+ loading = false,
371
+ loadingText = "Loading..."
372
+ }) => /* @__PURE__ */ jsx7(Dialog, { open, onOpenChange: (isOpen) => !isOpen && onClose(), children: /* @__PURE__ */ jsxs5(DialogContent, { className: "sm:max-w-[500px]", children: [
373
+ /* @__PURE__ */ jsxs5(DialogHeader, { children: [
374
+ /* @__PURE__ */ jsx7(DialogTitle, { children: title }),
375
+ /* @__PURE__ */ jsx7(DialogDescription, { children: message })
376
+ ] }),
377
+ /* @__PURE__ */ jsxs5(DialogFooter, { children: [
378
+ /* @__PURE__ */ jsx7(
379
+ "button",
380
+ {
381
+ onClick: onClose,
382
+ disabled: loading,
383
+ className: "px-4 py-2 text-sm font-medium text-text-primary bg-background-secondary border border-border-primary rounded-md hover:bg-background-tertiary focus:outline-none focus:ring-2 focus:ring-primary-500 disabled:opacity-50 disabled:cursor-not-allowed",
384
+ children: cancelText
385
+ }
386
+ ),
387
+ /* @__PURE__ */ jsx7(
388
+ "button",
389
+ {
390
+ onClick: onConfirm,
391
+ disabled: loading,
392
+ className: `px-4 py-2 text-sm font-medium text-white rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed ${variant === "danger" ? "bg-red-600 hover:bg-red-700 focus:ring-red-500" : "bg-primary-600 hover:bg-primary-700 focus:ring-primary-500"}`,
393
+ children: loading ? loadingText : confirmText
394
+ }
395
+ )
396
+ ] })
397
+ ] }) });
398
+
399
+ // src/components/card.tsx
400
+ import React3 from "react";
401
+ import { jsx as jsx8 } from "react/jsx-runtime";
402
+ var Card = React3.forwardRef(
403
+ ({ children, variant = "default", className = "", onClick }, ref) => {
404
+ const baseStyles = "bg-background-secondary rounded-lg shadow-sm border border-border-primary transition-all duration-150";
405
+ const variantStyles = {
406
+ default: "",
407
+ interactive: "cursor-pointer hover:shadow-md hover:border-primary-300 dark:hover:border-primary-600"
408
+ };
409
+ const buttonResetStyles = onClick ? "w-full text-left p-0 m-0 font-inherit block appearance-none flex flex-col cursor-pointer" : "";
410
+ const Component = onClick ? "button" : "div";
411
+ return /* @__PURE__ */ jsx8(
412
+ Component,
413
+ {
414
+ ref,
415
+ className: `${baseStyles} ${variantStyles[variant]} ${buttonResetStyles} ${className}`,
416
+ onClick,
417
+ children
418
+ }
419
+ );
420
+ }
421
+ );
422
+ Card.displayName = "Card";
423
+ var CardHeader = ({ children, className = "" }) => /* @__PURE__ */ jsx8("div", { className: `px-6 py-4 border-b border-border-primary ${className}`, children });
424
+ var CardBody = ({ children, className = "" }) => /* @__PURE__ */ jsx8("div", { className: `px-6 py-4 flex flex-col ${className}`, children });
425
+ var CardFooter = ({ children, className = "" }) => /* @__PURE__ */ jsx8("div", { className: `px-6 py-4 border-t border-border-primary ${className}`, children });
426
+
427
+ // src/components/loading-spinner.tsx
428
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
429
+ var LoadingSpinner = ({
430
+ size = "md",
431
+ className = ""
432
+ }) => {
433
+ const sizeStyles = {
434
+ sm: "w-4 h-4",
435
+ md: "w-8 h-8",
436
+ lg: "w-12 h-12"
437
+ };
438
+ return /* @__PURE__ */ jsxs6(
439
+ "svg",
440
+ {
441
+ className: `animate-spin ${sizeStyles[size]} text-primary-600 dark:text-primary-400 ${className}`,
442
+ fill: "none",
443
+ viewBox: "0 0 24 24",
444
+ children: [
445
+ /* @__PURE__ */ jsx9(
446
+ "circle",
447
+ {
448
+ className: "opacity-25",
449
+ cx: "12",
450
+ cy: "12",
451
+ r: "10",
452
+ stroke: "currentColor",
453
+ strokeWidth: "4"
454
+ }
455
+ ),
456
+ /* @__PURE__ */ jsx9(
457
+ "path",
458
+ {
459
+ className: "opacity-75",
460
+ fill: "currentColor",
461
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
462
+ }
463
+ )
464
+ ]
465
+ }
466
+ );
467
+ };
468
+ var LoadingScreen = ({
469
+ message = "Loading..."
470
+ }) => /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center justify-center min-h-[400px] space-y-4", children: [
471
+ /* @__PURE__ */ jsx9(LoadingSpinner, { size: "lg" }),
472
+ /* @__PURE__ */ jsx9("p", { className: "text-text-secondary", children: message })
473
+ ] });
474
+
475
+ // src/components/badge.tsx
476
+ import { jsx as jsx10 } from "react/jsx-runtime";
477
+ var Badge = ({
478
+ children,
479
+ variant = "default",
480
+ size = "md",
481
+ className = ""
482
+ }) => {
483
+ const baseStyles = "inline-flex items-center justify-center font-medium rounded-full whitespace-nowrap";
484
+ const variantStyles = {
485
+ default: "bg-background-tertiary text-text-primary",
486
+ success: "bg-primary-100 dark:bg-primary-900 text-primary-700 dark:text-primary-300",
487
+ warning: "bg-amber-100 dark:bg-amber-900 text-amber-700 dark:text-amber-300",
488
+ error: "bg-red-100 dark:bg-red-900 text-red-700 dark:text-red-300",
489
+ info: "bg-blue-100 dark:bg-blue-900 text-blue-700 dark:text-blue-300"
490
+ };
491
+ const sizeStyles = {
492
+ sm: "text-xs px-2 py-0.5",
493
+ md: "text-sm px-2.5 py-1"
494
+ };
495
+ return /* @__PURE__ */ jsx10(
496
+ "span",
497
+ {
498
+ className: `${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${className}`,
499
+ children
500
+ }
501
+ );
502
+ };
503
+
504
+ // src/components/empty-state.tsx
505
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
506
+ var EmptyState = ({
507
+ icon,
508
+ title,
509
+ description,
510
+ action,
511
+ className = ""
512
+ }) => /* @__PURE__ */ jsxs7(
513
+ "div",
514
+ {
515
+ className: `flex flex-col items-center justify-center py-12 px-4 text-center ${className}`,
516
+ children: [
517
+ icon && /* @__PURE__ */ jsx11("div", { className: "mb-4 text-text-tertiary", children: icon }),
518
+ /* @__PURE__ */ jsx11("h3", { className: "text-lg font-semibold text-text-primary mb-2", children: title }),
519
+ description && /* @__PURE__ */ jsx11("p", { className: "text-sm text-text-secondary mb-6 max-w-md", children: description }),
520
+ action && /* @__PURE__ */ jsx11(
521
+ "button",
522
+ {
523
+ onClick: action.onClick,
524
+ className: "px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 transition-colors cursor-pointer",
525
+ children: action.label
526
+ }
527
+ )
528
+ ]
529
+ }
530
+ );
531
+
532
+ // src/components/slide-over.tsx
533
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
534
+ var sizeClasses = {
535
+ sm: "max-w-sm",
536
+ md: "max-w-md",
537
+ lg: "max-w-lg",
538
+ xl: "max-w-4xl",
539
+ full: "max-w-full"
540
+ };
541
+ function SlideOver({
542
+ open,
543
+ onClose,
544
+ title,
545
+ description,
546
+ children,
547
+ footer,
548
+ size = "md",
549
+ closeLabel = "Close"
550
+ }) {
551
+ return /* @__PURE__ */ jsx12(Dialog, { open, onOpenChange: (isOpen) => !isOpen && onClose(), children: /* @__PURE__ */ jsxs8(DialogContent, { className: cn(sizeClasses[size], "max-h-[90vh] flex flex-col"), closeLabel, children: [
552
+ /* @__PURE__ */ jsxs8(DialogHeader, { children: [
553
+ /* @__PURE__ */ jsx12(DialogTitle, { children: title }),
554
+ description && /* @__PURE__ */ jsx12(DialogDescription, { children: description })
555
+ ] }),
556
+ /* @__PURE__ */ jsx12("div", { className: "flex-1 overflow-y-auto min-h-0 px-1", children }),
557
+ footer && /* @__PURE__ */ jsx12(DialogFooter, { className: "mt-4", children: footer })
558
+ ] }) });
559
+ }
560
+ function FormSlideOver({
561
+ open,
562
+ onClose,
563
+ title,
564
+ description,
565
+ children,
566
+ submitText = "Save changes",
567
+ cancelText = "Cancel",
568
+ deleteText = "Delete",
569
+ savingText = "Saving...",
570
+ deletingText = "Deleting...",
571
+ unsavedChangesConfirm = "You have unsaved changes. Are you sure you want to close?",
572
+ onSubmit,
573
+ onDelete,
574
+ isSubmitting = false,
575
+ isDeleting = false,
576
+ hasChanges = false,
577
+ size = "md",
578
+ closeLabel
579
+ }) {
580
+ const handleClose = () => {
581
+ if (hasChanges) {
582
+ if (confirm(unsavedChangesConfirm)) {
583
+ onClose();
584
+ }
585
+ } else {
586
+ onClose();
587
+ }
588
+ };
589
+ return /* @__PURE__ */ jsx12(
590
+ SlideOver,
591
+ {
592
+ open,
593
+ onClose: handleClose,
594
+ title,
595
+ description,
596
+ size,
597
+ closeLabel,
598
+ footer: /* @__PURE__ */ jsxs8("div", { className: "flex flex-col-reverse sm:flex-row sm:justify-between w-full gap-2", children: [
599
+ onDelete && /* @__PURE__ */ jsx12(
600
+ "button",
601
+ {
602
+ type: "button",
603
+ onClick: onDelete,
604
+ disabled: isDeleting || isSubmitting,
605
+ className: "w-full sm:w-auto px-4 py-2 text-sm font-medium text-white bg-red-600 rounded-md hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 disabled:opacity-50",
606
+ children: isDeleting ? deletingText : deleteText
607
+ }
608
+ ),
609
+ /* @__PURE__ */ jsxs8("div", { className: "flex flex-col-reverse sm:flex-row gap-2 sm:ml-auto", children: [
610
+ /* @__PURE__ */ jsx12(
611
+ "button",
612
+ {
613
+ type: "button",
614
+ onClick: handleClose,
615
+ disabled: isSubmitting || isDeleting,
616
+ className: "w-full sm:w-auto px-4 py-2 text-sm font-medium text-text-primary bg-background-secondary border border-border-primary rounded-md hover:bg-background-tertiary focus:outline-none focus:ring-2 focus:ring-primary-500 disabled:opacity-50",
617
+ children: cancelText
618
+ }
619
+ ),
620
+ /* @__PURE__ */ jsx12(
621
+ "button",
622
+ {
623
+ type: "button",
624
+ onClick: onSubmit,
625
+ disabled: isSubmitting || isDeleting,
626
+ className: "w-full sm:w-auto px-4 py-2 text-sm font-medium text-white bg-primary-600 rounded-md hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 disabled:opacity-50",
627
+ children: isSubmitting ? savingText : submitText
628
+ }
629
+ )
630
+ ] })
631
+ ] }),
632
+ children
633
+ }
634
+ );
635
+ }
636
+
637
+ // src/components/entity-form.tsx
638
+ import { useRef, useEffect, useCallback } from "react";
639
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
640
+ var EntityForm = ({
641
+ isEdit = false,
642
+ isSaving = false,
643
+ error,
644
+ onSave,
645
+ onCancel,
646
+ onDelete,
647
+ saveLabel = "Save",
648
+ cancelLabel = "Cancel",
649
+ deleteLabel = "Delete",
650
+ savingLabel = "Saving...",
651
+ deleteConfirmMessage = "Are you sure you want to delete this?",
652
+ showDelete = true,
653
+ autoFocus = true,
654
+ className = "",
655
+ children
656
+ }) => {
657
+ const formRef = useRef(null);
658
+ useEffect(() => {
659
+ if (autoFocus && formRef.current) {
660
+ const firstInput = formRef.current.querySelector(
661
+ 'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled])'
662
+ );
663
+ if (firstInput) {
664
+ setTimeout(() => {
665
+ firstInput.focus();
666
+ }, 50);
667
+ }
668
+ }
669
+ }, [autoFocus]);
670
+ const handleKeyDown = useCallback(
671
+ (e) => {
672
+ if (isSaving) return;
673
+ if (e.key === "Escape") {
674
+ e.preventDefault();
675
+ onCancel();
676
+ return;
677
+ }
678
+ if (e.key === "Enter" && !(e.target instanceof HTMLTextAreaElement)) {
679
+ if (e.ctrlKey || e.metaKey) {
680
+ e.preventDefault();
681
+ onSave();
682
+ }
683
+ }
684
+ },
685
+ [isSaving, onSave, onCancel]
686
+ );
687
+ const handleDelete = () => {
688
+ if (onDelete && window.confirm(deleteConfirmMessage)) {
689
+ onDelete();
690
+ }
691
+ };
692
+ return /* @__PURE__ */ jsxs9(
693
+ "div",
694
+ {
695
+ ref: formRef,
696
+ className: `bg-background-secondary border border-border-primary rounded-lg p-4 ${className}`,
697
+ onKeyDown: handleKeyDown,
698
+ children: [
699
+ /* @__PURE__ */ jsx13("div", { className: "space-y-4", children }),
700
+ error && /* @__PURE__ */ jsx13("div", { className: "mt-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-md", children: /* @__PURE__ */ jsx13("p", { className: "text-sm text-red-600 dark:text-red-400", children: error }) }),
701
+ /* @__PURE__ */ jsxs9("div", { className: "mt-6 flex items-center justify-between", children: [
702
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
703
+ /* @__PURE__ */ jsx13(Button, { type: "button", variant: "primary", onClick: onSave, loading: isSaving, disabled: isSaving, children: isSaving ? savingLabel : saveLabel }),
704
+ /* @__PURE__ */ jsx13(Button, { type: "button", variant: "secondary", onClick: onCancel, disabled: isSaving, children: cancelLabel })
705
+ ] }),
706
+ isEdit && showDelete && onDelete && /* @__PURE__ */ jsx13(Button, { type: "button", variant: "danger", onClick: handleDelete, disabled: isSaving, children: deleteLabel })
707
+ ] }),
708
+ /* @__PURE__ */ jsxs9("div", { className: "mt-3 text-xs text-text-tertiary", children: [
709
+ /* @__PURE__ */ jsx13("kbd", { className: "px-1.5 py-0.5 bg-background-primary rounded", children: "Esc" }),
710
+ " to cancel",
711
+ /* @__PURE__ */ jsx13("span", { className: "mx-2", children: "\xB7" }),
712
+ /* @__PURE__ */ jsx13("kbd", { className: "px-1.5 py-0.5 bg-background-primary rounded", children: "\u2318" }),
713
+ "+",
714
+ /* @__PURE__ */ jsx13("kbd", { className: "px-1.5 py-0.5 bg-background-primary rounded", children: "Enter" }),
715
+ " to save"
716
+ ] })
717
+ ]
718
+ }
719
+ );
720
+ };
721
+
722
+ // src/components/search-input.tsx
723
+ import { useState, useRef as useRef2, useEffect as useEffect2, useCallback as useCallback2 } from "react";
724
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
725
+ var sizeClasses2 = {
726
+ sm: {
727
+ input: "h-8 text-sm",
728
+ icon: "w-4 h-4",
729
+ padding: "pl-8 pr-8",
730
+ collapsedWidth: "w-8",
731
+ expandedWidth: "w-48 sm:w-64"
732
+ },
733
+ md: {
734
+ input: "h-10 text-sm",
735
+ icon: "w-5 h-5",
736
+ padding: "pl-10 pr-10",
737
+ collapsedWidth: "w-10",
738
+ expandedWidth: "w-56 sm:w-72"
739
+ },
740
+ lg: {
741
+ input: "h-12 text-base",
742
+ icon: "w-6 h-6",
743
+ padding: "pl-12 pr-12",
744
+ collapsedWidth: "w-12",
745
+ expandedWidth: "w-64 sm:w-80"
746
+ }
747
+ };
748
+ function SearchInput({
749
+ value,
750
+ onChange,
751
+ placeholder,
752
+ debounceMs = 300,
753
+ expandable = false,
754
+ className = "",
755
+ autoFocus = false,
756
+ size = "md",
757
+ labels = {}
758
+ }) {
759
+ const resolvedPlaceholder = placeholder ?? labels.placeholder ?? "Search";
760
+ const searchHotkeyHint = labels.searchHotkeyHint ?? "Press / to search";
761
+ const openSearchLabel = labels.openSearch ?? "Open search";
762
+ const searchAriaLabel = labels.search ?? "Search";
763
+ const clearSearchLabel = labels.clearSearch ?? "Clear search";
764
+ const [internalValue, setInternalValue] = useState(value);
765
+ const [isExpanded, setIsExpanded] = useState(!expandable || !!value);
766
+ const [isFocused, setIsFocused] = useState(false);
767
+ const inputRef = useRef2(null);
768
+ const debounceTimerRef = useRef2(null);
769
+ const sizes = sizeClasses2[size];
770
+ useEffect2(() => {
771
+ setInternalValue(value);
772
+ if (value && expandable) {
773
+ setIsExpanded(true);
774
+ }
775
+ }, [value, expandable]);
776
+ const debouncedOnChange = useCallback2(
777
+ (newValue) => {
778
+ if (debounceTimerRef.current) {
779
+ clearTimeout(debounceTimerRef.current);
780
+ }
781
+ if (debounceMs > 0) {
782
+ debounceTimerRef.current = setTimeout(() => {
783
+ onChange(newValue);
784
+ }, debounceMs);
785
+ } else {
786
+ onChange(newValue);
787
+ }
788
+ },
789
+ [onChange, debounceMs]
790
+ );
791
+ useEffect2(() => {
792
+ return () => {
793
+ if (debounceTimerRef.current) {
794
+ clearTimeout(debounceTimerRef.current);
795
+ }
796
+ };
797
+ }, []);
798
+ const handleChange = (e) => {
799
+ const newValue = e.target.value;
800
+ setInternalValue(newValue);
801
+ debouncedOnChange(newValue);
802
+ };
803
+ const handleClear = () => {
804
+ setInternalValue("");
805
+ onChange("");
806
+ inputRef.current?.focus();
807
+ };
808
+ const handleExpandClick = () => {
809
+ setIsExpanded(true);
810
+ requestAnimationFrame(() => {
811
+ inputRef.current?.focus();
812
+ });
813
+ };
814
+ const handleBlur = () => {
815
+ setIsFocused(false);
816
+ if (expandable && !internalValue) {
817
+ setTimeout(() => {
818
+ if (document.activeElement !== inputRef.current) {
819
+ setIsExpanded(false);
820
+ }
821
+ }, 150);
822
+ }
823
+ };
824
+ useEffect2(() => {
825
+ const handleKeyDown = (e) => {
826
+ if (e.key === "/" && !["INPUT", "TEXTAREA", "SELECT"].includes(e.target.tagName)) {
827
+ e.preventDefault();
828
+ if (expandable && !isExpanded) {
829
+ setIsExpanded(true);
830
+ }
831
+ requestAnimationFrame(() => {
832
+ inputRef.current?.focus();
833
+ });
834
+ }
835
+ if (e.key === "Escape" && document.activeElement === inputRef.current) {
836
+ if (internalValue) {
837
+ handleClear();
838
+ } else {
839
+ inputRef.current?.blur();
840
+ }
841
+ }
842
+ };
843
+ document.addEventListener("keydown", handleKeyDown);
844
+ return () => document.removeEventListener("keydown", handleKeyDown);
845
+ }, [expandable, isExpanded, internalValue]);
846
+ useEffect2(() => {
847
+ if (autoFocus && inputRef.current) {
848
+ inputRef.current.focus();
849
+ }
850
+ }, [autoFocus]);
851
+ if (expandable && !isExpanded) {
852
+ return /* @__PURE__ */ jsx14(
853
+ "button",
854
+ {
855
+ type: "button",
856
+ onClick: handleExpandClick,
857
+ className: `
858
+ ${sizes.collapsedWidth} ${sizes.input}
859
+ flex items-center justify-center
860
+ rounded-md border border-border-primary
861
+ bg-background-secondary
862
+ text-text-tertiary hover:text-text-secondary
863
+ hover:bg-background-tertiary
864
+ focus:outline-none focus:ring-2 focus:ring-primary-500
865
+ transition-all duration-200
866
+ ${className}
867
+ `,
868
+ title: searchHotkeyHint,
869
+ "aria-label": openSearchLabel,
870
+ children: /* @__PURE__ */ jsx14("svg", { className: sizes.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx14(
871
+ "path",
872
+ {
873
+ strokeLinecap: "round",
874
+ strokeLinejoin: "round",
875
+ strokeWidth: 2,
876
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
877
+ }
878
+ ) })
879
+ }
880
+ );
881
+ }
882
+ return /* @__PURE__ */ jsxs10(
883
+ "div",
884
+ {
885
+ className: `
886
+ relative
887
+ ${expandable ? `transition-all duration-200 ${isExpanded ? sizes.expandedWidth : sizes.collapsedWidth}` : "w-full"}
888
+ ${className}
889
+ `,
890
+ children: [
891
+ /* @__PURE__ */ jsx14("div", { className: "absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none", children: /* @__PURE__ */ jsx14(
892
+ "svg",
893
+ {
894
+ className: `${sizes.icon} text-text-tertiary`,
895
+ fill: "none",
896
+ stroke: "currentColor",
897
+ viewBox: "0 0 24 24",
898
+ children: /* @__PURE__ */ jsx14(
899
+ "path",
900
+ {
901
+ strokeLinecap: "round",
902
+ strokeLinejoin: "round",
903
+ strokeWidth: 2,
904
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
905
+ }
906
+ )
907
+ }
908
+ ) }),
909
+ /* @__PURE__ */ jsx14(
910
+ "input",
911
+ {
912
+ ref: inputRef,
913
+ type: "text",
914
+ value: internalValue,
915
+ onChange: handleChange,
916
+ onFocus: () => setIsFocused(true),
917
+ onBlur: handleBlur,
918
+ placeholder: resolvedPlaceholder,
919
+ className: `
920
+ w-full ${sizes.input} ${sizes.padding}
921
+ rounded-md border
922
+ bg-background-secondary
923
+ text-text-primary
924
+ placeholder-text-tertiary
925
+ ${isFocused ? "border-primary-500 ring-2 ring-primary-500" : "border-border-primary"}
926
+ focus:outline-none
927
+ transition-colors
928
+ `,
929
+ "aria-label": searchAriaLabel
930
+ }
931
+ ),
932
+ internalValue && /* @__PURE__ */ jsx14(
933
+ "button",
934
+ {
935
+ type: "button",
936
+ onClick: handleClear,
937
+ className: "absolute inset-y-0 right-0 flex items-center pr-3 text-text-tertiary hover:text-text-secondary",
938
+ "aria-label": clearSearchLabel,
939
+ children: /* @__PURE__ */ jsx14("svg", { className: sizes.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx14(
940
+ "path",
941
+ {
942
+ strokeLinecap: "round",
943
+ strokeLinejoin: "round",
944
+ strokeWidth: 2,
945
+ d: "M6 18L18 6M6 6l12 12"
946
+ }
947
+ ) })
948
+ }
949
+ ),
950
+ !internalValue && !isFocused && /* @__PURE__ */ jsx14("div", { className: "absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none", children: /* @__PURE__ */ jsx14("kbd", { className: "hidden sm:inline-flex items-center px-1.5 py-0.5 text-xs font-medium text-text-tertiary bg-background-tertiary rounded border border-border-primary", children: "/" }) })
951
+ ]
952
+ }
953
+ );
954
+ }
955
+
956
+ // src/components/search-bar.tsx
957
+ import { useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
958
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
959
+ var SearchBar = ({
960
+ value,
961
+ onChange,
962
+ onClear,
963
+ placeholder = "Search",
964
+ autoFocus = false,
965
+ className = "",
966
+ showShortcutHint = true,
967
+ clearSearchLabel = "Clear search"
968
+ }) => {
969
+ const inputRef = useRef3(null);
970
+ const [isFocused, setIsFocused] = useState2(false);
971
+ useEffect3(() => {
972
+ const handleKeyDown2 = (e) => {
973
+ if ((e.metaKey || e.ctrlKey) && e.key === "k") {
974
+ e.preventDefault();
975
+ inputRef.current?.focus();
976
+ }
977
+ };
978
+ window.addEventListener("keydown", handleKeyDown2);
979
+ return () => window.removeEventListener("keydown", handleKeyDown2);
980
+ }, []);
981
+ const handleKeyDown = (e) => {
982
+ if ((e.metaKey || e.ctrlKey) && e.key === "a") {
983
+ e.preventDefault();
984
+ inputRef.current?.select();
985
+ }
986
+ };
987
+ const handleClear = () => {
988
+ onChange("");
989
+ onClear?.();
990
+ inputRef.current?.focus();
991
+ };
992
+ const hasWhiteBackground = isFocused || value.length > 0;
993
+ return /* @__PURE__ */ jsxs11("div", { className: `relative ${className}`, children: [
994
+ /* @__PURE__ */ jsx15("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsx15(
995
+ "svg",
996
+ {
997
+ className: "h-5 w-5 text-text-tertiary",
998
+ fill: "none",
999
+ stroke: "currentColor",
1000
+ viewBox: "0 0 24 24",
1001
+ children: /* @__PURE__ */ jsx15(
1002
+ "path",
1003
+ {
1004
+ strokeLinecap: "round",
1005
+ strokeLinejoin: "round",
1006
+ strokeWidth: 2,
1007
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
1008
+ }
1009
+ )
1010
+ }
1011
+ ) }),
1012
+ /* @__PURE__ */ jsx15(
1013
+ "input",
1014
+ {
1015
+ ref: inputRef,
1016
+ type: "text",
1017
+ value,
1018
+ onChange: (e) => onChange(e.target.value),
1019
+ onKeyDown: handleKeyDown,
1020
+ onFocus: () => setIsFocused(true),
1021
+ onBlur: () => setIsFocused(false),
1022
+ placeholder,
1023
+ autoFocus,
1024
+ className: `
1025
+ w-full
1026
+ pl-10
1027
+ pr-24
1028
+ py-2
1029
+ ${hasWhiteBackground ? "bg-background-tertiary" : "bg-background-secondary"}
1030
+ text-text-primary
1031
+ border
1032
+ border-border-primary
1033
+ rounded-md
1034
+ transition-all
1035
+ duration-150
1036
+ focus:outline-none
1037
+ focus:ring-2
1038
+ focus:ring-primary-500
1039
+ focus:border-primary-500
1040
+ placeholder:text-text-tertiary
1041
+ `
1042
+ }
1043
+ ),
1044
+ /* @__PURE__ */ jsxs11("div", { className: "absolute inset-y-0 right-0 flex items-center pr-3 gap-2", children: [
1045
+ showShortcutHint && !value && /* @__PURE__ */ jsx15("kbd", { className: "hidden sm:inline-block px-2 py-1 text-xs text-text-tertiary bg-background-secondary border border-border-primary rounded", children: "\u2318K" }),
1046
+ value && /* @__PURE__ */ jsx15(
1047
+ "button",
1048
+ {
1049
+ type: "button",
1050
+ onClick: handleClear,
1051
+ className: "text-text-tertiary hover:text-text-secondary transition-colors",
1052
+ "aria-label": clearSearchLabel,
1053
+ children: /* @__PURE__ */ jsx15("svg", { className: "h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx15(
1054
+ "path",
1055
+ {
1056
+ strokeLinecap: "round",
1057
+ strokeLinejoin: "round",
1058
+ strokeWidth: 2,
1059
+ d: "M6 18L18 6M6 6l12 12"
1060
+ }
1061
+ ) })
1062
+ }
1063
+ )
1064
+ ] })
1065
+ ] });
1066
+ };
1067
+
1068
+ // src/components/breadcrumbs.tsx
1069
+ import React7 from "react";
1070
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
1071
+ var Breadcrumbs = ({
1072
+ items,
1073
+ className = "",
1074
+ ariaLabel = "Breadcrumb",
1075
+ renderLink
1076
+ }) => {
1077
+ const linkClassName = "hover:text-primary-600 cursor-pointer inline-block";
1078
+ const renderItemLink = (href, label) => {
1079
+ if (renderLink) {
1080
+ return renderLink({ href, children: label, className: linkClassName });
1081
+ }
1082
+ return /* @__PURE__ */ jsx16("a", { href, className: linkClassName, children: label });
1083
+ };
1084
+ return /* @__PURE__ */ jsx16("nav", { className: `mb-4 text-sm text-text-secondary ${className}`, "aria-label": ariaLabel, children: items.map((item, index) => {
1085
+ const isLast = index === items.length - 1;
1086
+ return /* @__PURE__ */ jsxs12(React7.Fragment, { children: [
1087
+ item.href && !isLast ? renderItemLink(item.href, item.label) : /* @__PURE__ */ jsx16("span", { className: isLast ? "text-text-primary" : "", children: item.label }),
1088
+ !isLast && /* @__PURE__ */ jsx16("span", { className: "mx-2", children: "/" })
1089
+ ] }, index);
1090
+ }) });
1091
+ };
1092
+
1093
+ // src/components/table.tsx
1094
+ import { jsx as jsx17 } from "react/jsx-runtime";
1095
+ var Table = ({ children, className = "" }) => {
1096
+ return /* @__PURE__ */ jsx17("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsx17(
1097
+ "table",
1098
+ {
1099
+ className: `w-full divide-y divide-border-primary ${className}`,
1100
+ children
1101
+ }
1102
+ ) });
1103
+ };
1104
+ var TableHeader = ({
1105
+ children,
1106
+ className = ""
1107
+ }) => {
1108
+ return /* @__PURE__ */ jsx17("thead", { className: `bg-background-tertiary ${className}`, children });
1109
+ };
1110
+ var TableBody = ({
1111
+ children,
1112
+ className = ""
1113
+ }) => {
1114
+ return /* @__PURE__ */ jsx17(
1115
+ "tbody",
1116
+ {
1117
+ className: `bg-background-secondary divide-y divide-border-primary ${className}`,
1118
+ children
1119
+ }
1120
+ );
1121
+ };
1122
+ var TableRow = ({
1123
+ children,
1124
+ className = "",
1125
+ onClick,
1126
+ ...props
1127
+ }) => {
1128
+ return /* @__PURE__ */ jsx17(
1129
+ "tr",
1130
+ {
1131
+ className: `${onClick ? "cursor-pointer hover:bg-background-tertiary" : ""} ${className}`,
1132
+ onClick,
1133
+ ...props,
1134
+ children
1135
+ }
1136
+ );
1137
+ };
1138
+ var TableHead = ({
1139
+ children,
1140
+ className = ""
1141
+ }) => {
1142
+ return /* @__PURE__ */ jsx17(
1143
+ "th",
1144
+ {
1145
+ className: `px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider align-top ${className}`,
1146
+ children
1147
+ }
1148
+ );
1149
+ };
1150
+ var TableCell = ({
1151
+ children,
1152
+ className = "",
1153
+ onClick,
1154
+ colSpan
1155
+ }) => {
1156
+ return /* @__PURE__ */ jsx17(
1157
+ "td",
1158
+ {
1159
+ className: `px-4 py-4 text-sm text-text-primary align-top ${onClick ? "cursor-pointer" : ""} ${className}`,
1160
+ onClick,
1161
+ colSpan,
1162
+ children
1163
+ }
1164
+ );
1165
+ };
1166
+
1167
+ // src/components/tabs.tsx
1168
+ import React8, { useState as useState3, useRef as useRef4 } from "react";
1169
+ import { jsx as jsx18 } from "react/jsx-runtime";
1170
+ var TabsContext = React8.createContext({
1171
+ value: "",
1172
+ onValueChange: () => {
1173
+ }
1174
+ });
1175
+ var Tabs = ({
1176
+ children,
1177
+ defaultValue = "",
1178
+ value: controlledValue,
1179
+ onValueChange,
1180
+ className = ""
1181
+ }) => {
1182
+ const [internalValue, setInternalValue] = useState3(defaultValue);
1183
+ const isControlled = controlledValue !== void 0;
1184
+ const value = isControlled ? controlledValue : internalValue;
1185
+ const handleValueChange = (newValue) => {
1186
+ if (!isControlled) {
1187
+ setInternalValue(newValue);
1188
+ }
1189
+ onValueChange?.(newValue);
1190
+ };
1191
+ return /* @__PURE__ */ jsx18(TabsContext.Provider, { value: { value, onValueChange: handleValueChange }, children: /* @__PURE__ */ jsx18("div", { className, children }) });
1192
+ };
1193
+ var TabsList = ({
1194
+ children,
1195
+ className = ""
1196
+ }) => {
1197
+ return /* @__PURE__ */ jsx18(
1198
+ "div",
1199
+ {
1200
+ className: `flex ${className}`,
1201
+ role: "tablist",
1202
+ children
1203
+ }
1204
+ );
1205
+ };
1206
+ var TabsTrigger = ({
1207
+ value,
1208
+ children,
1209
+ className = ""
1210
+ }) => {
1211
+ const context = React8.useContext(TabsContext);
1212
+ const isActive = context.value === value;
1213
+ const buttonRef = useRef4(null);
1214
+ const handleClick = () => {
1215
+ context.onValueChange(value);
1216
+ };
1217
+ const handleKeyDown = (e) => {
1218
+ if (e.key === "Enter" || e.key === " ") {
1219
+ e.preventDefault();
1220
+ context.onValueChange(value);
1221
+ }
1222
+ };
1223
+ return /* @__PURE__ */ jsx18(
1224
+ "button",
1225
+ {
1226
+ ref: buttonRef,
1227
+ role: "tab",
1228
+ "aria-selected": isActive,
1229
+ "aria-controls": `tab-content-${value}`,
1230
+ id: `tab-trigger-${value}`,
1231
+ onClick: handleClick,
1232
+ onKeyDown: handleKeyDown,
1233
+ className: `
1234
+ px-4 py-2 text-sm font-medium transition-colors duration-150
1235
+ border-b-2 -mb-px
1236
+ focus:outline-none
1237
+ cursor-pointer
1238
+ ${isActive ? "border-primary-600 text-primary-600" : "border-transparent text-text-secondary hover:text-text-primary hover:border-border-secondary"}
1239
+ ${className}
1240
+ `,
1241
+ children
1242
+ }
1243
+ );
1244
+ };
1245
+ var TabsContent = ({
1246
+ value,
1247
+ children,
1248
+ className = ""
1249
+ }) => {
1250
+ const context = React8.useContext(TabsContext);
1251
+ const isActive = context.value === value;
1252
+ if (!isActive) {
1253
+ return null;
1254
+ }
1255
+ return /* @__PURE__ */ jsx18(
1256
+ "div",
1257
+ {
1258
+ role: "tabpanel",
1259
+ id: `tab-content-${value}`,
1260
+ "aria-labelledby": `tab-trigger-${value}`,
1261
+ className: `mt-6 ${className}`,
1262
+ children
1263
+ }
1264
+ );
1265
+ };
1266
+
1267
+ // src/components/avatar.tsx
1268
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
1269
+ import { jsx as jsx19 } from "react/jsx-runtime";
1270
+ var Avatar = ({ className, ref, ...props }) => /* @__PURE__ */ jsx19(
1271
+ AvatarPrimitive.Root,
1272
+ {
1273
+ ref,
1274
+ className: cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className),
1275
+ ...props
1276
+ }
1277
+ );
1278
+ Avatar.displayName = AvatarPrimitive.Root.displayName;
1279
+ var AvatarImage = ({ className, ref, ...props }) => /* @__PURE__ */ jsx19(
1280
+ AvatarPrimitive.Image,
1281
+ {
1282
+ ref,
1283
+ className: cn("aspect-square h-full w-full", className),
1284
+ ...props
1285
+ }
1286
+ );
1287
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName;
1288
+ var AvatarFallback = ({ className, ref, ...props }) => /* @__PURE__ */ jsx19(
1289
+ AvatarPrimitive.Fallback,
1290
+ {
1291
+ ref,
1292
+ className: cn("flex h-full w-full items-center justify-center rounded-full bg-muted", className),
1293
+ ...props
1294
+ }
1295
+ );
1296
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
1297
+
1298
+ // src/components/dropdown-menu.tsx
1299
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
1300
+ import { Check, ChevronRight, Circle } from "lucide-react";
1301
+ import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
1302
+ var DropdownMenu = DropdownMenuPrimitive.Root;
1303
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
1304
+ var DropdownMenuGroup = DropdownMenuPrimitive.Group;
1305
+ var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
1306
+ var DropdownMenuSub = DropdownMenuPrimitive.Sub;
1307
+ var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
1308
+ var DropdownMenuSubTrigger = ({ className, inset, children, ref, ...props }) => /* @__PURE__ */ jsxs13(
1309
+ DropdownMenuPrimitive.SubTrigger,
1310
+ {
1311
+ ref,
1312
+ className: cn(
1313
+ "flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1314
+ inset && "pl-8",
1315
+ className
1316
+ ),
1317
+ ...props,
1318
+ children: [
1319
+ children,
1320
+ /* @__PURE__ */ jsx20(ChevronRight, { className: "ml-auto" })
1321
+ ]
1322
+ }
1323
+ );
1324
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
1325
+ var DropdownMenuSubContent = ({ className, ref, ...props }) => /* @__PURE__ */ jsx20(
1326
+ DropdownMenuPrimitive.SubContent,
1327
+ {
1328
+ ref,
1329
+ className: cn(
1330
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
1331
+ className
1332
+ ),
1333
+ ...props
1334
+ }
1335
+ );
1336
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
1337
+ var DropdownMenuContent = ({ className, sideOffset = 4, ref, ...props }) => /* @__PURE__ */ jsx20(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx20(
1338
+ DropdownMenuPrimitive.Content,
1339
+ {
1340
+ ref,
1341
+ sideOffset,
1342
+ className: cn(
1343
+ "z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
1344
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
1345
+ className
1346
+ ),
1347
+ ...props
1348
+ }
1349
+ ) });
1350
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
1351
+ var DropdownMenuItem = ({ className, inset, ref, ...props }) => /* @__PURE__ */ jsx20(
1352
+ DropdownMenuPrimitive.Item,
1353
+ {
1354
+ ref,
1355
+ className: cn(
1356
+ "relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
1357
+ inset && "pl-8",
1358
+ className
1359
+ ),
1360
+ ...props
1361
+ }
1362
+ );
1363
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
1364
+ var DropdownMenuCheckboxItem = ({ className, children, checked, ref, ...props }) => /* @__PURE__ */ jsxs13(
1365
+ DropdownMenuPrimitive.CheckboxItem,
1366
+ {
1367
+ ref,
1368
+ className: cn(
1369
+ "relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1370
+ className
1371
+ ),
1372
+ checked,
1373
+ ...props,
1374
+ children: [
1375
+ /* @__PURE__ */ jsx20("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx20(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx20(Check, { className: "h-4 w-4" }) }) }),
1376
+ children
1377
+ ]
1378
+ }
1379
+ );
1380
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
1381
+ var DropdownMenuRadioItem = ({ className, children, ref, ...props }) => /* @__PURE__ */ jsxs13(
1382
+ DropdownMenuPrimitive.RadioItem,
1383
+ {
1384
+ ref,
1385
+ className: cn(
1386
+ "relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1387
+ className
1388
+ ),
1389
+ ...props,
1390
+ children: [
1391
+ /* @__PURE__ */ jsx20("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx20(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx20(Circle, { className: "h-2 w-2 fill-current" }) }) }),
1392
+ children
1393
+ ]
1394
+ }
1395
+ );
1396
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
1397
+ var DropdownMenuLabel = ({ className, inset, ref, ...props }) => /* @__PURE__ */ jsx20(
1398
+ DropdownMenuPrimitive.Label,
1399
+ {
1400
+ ref,
1401
+ className: cn(
1402
+ "px-2 py-1.5 text-sm font-semibold",
1403
+ inset && "pl-8",
1404
+ className
1405
+ ),
1406
+ ...props
1407
+ }
1408
+ );
1409
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
1410
+ var DropdownMenuSeparator = ({ className, ref, ...props }) => /* @__PURE__ */ jsx20(
1411
+ DropdownMenuPrimitive.Separator,
1412
+ {
1413
+ ref,
1414
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
1415
+ ...props
1416
+ }
1417
+ );
1418
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
1419
+ var DropdownMenuShortcut = ({
1420
+ className,
1421
+ ...props
1422
+ }) => {
1423
+ return /* @__PURE__ */ jsx20(
1424
+ "span",
1425
+ {
1426
+ className: cn("ml-auto text-xs tracking-widest opacity-60", className),
1427
+ ...props
1428
+ }
1429
+ );
1430
+ };
1431
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
1432
+
1433
+ // src/components/collapsible.tsx
1434
+ import { useState as useState4, useEffect as useEffect4, useRef as useRef5, useCallback as useCallback3 } from "react";
1435
+ import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
1436
+ function Collapsible({
1437
+ defaultOpen = false,
1438
+ open: controlledOpen,
1439
+ onOpenChange,
1440
+ trigger,
1441
+ children,
1442
+ className = "",
1443
+ storageKey,
1444
+ disabled = false
1445
+ }) {
1446
+ const isControlled = controlledOpen !== void 0;
1447
+ const [internalOpen, setInternalOpen] = useState4(() => {
1448
+ if (storageKey && typeof window !== "undefined") {
1449
+ const stored = localStorage.getItem(`collapsible-${storageKey}`);
1450
+ if (stored !== null) {
1451
+ return stored === "true";
1452
+ }
1453
+ }
1454
+ return defaultOpen;
1455
+ });
1456
+ const isOpen = isControlled ? controlledOpen : internalOpen;
1457
+ const contentRef = useRef5(null);
1458
+ const [contentHeight, setContentHeight] = useState4(void 0);
1459
+ useEffect4(() => {
1460
+ if (contentRef.current) {
1461
+ setContentHeight(contentRef.current.scrollHeight);
1462
+ }
1463
+ }, [children, isOpen]);
1464
+ useEffect4(() => {
1465
+ if (storageKey && !isControlled) {
1466
+ localStorage.setItem(`collapsible-${storageKey}`, String(internalOpen));
1467
+ }
1468
+ }, [storageKey, internalOpen, isControlled]);
1469
+ const handleToggle = useCallback3(() => {
1470
+ if (disabled) return;
1471
+ const newState = !isOpen;
1472
+ if (!isControlled) {
1473
+ setInternalOpen(newState);
1474
+ }
1475
+ onOpenChange?.(newState);
1476
+ }, [disabled, isOpen, isControlled, onOpenChange]);
1477
+ return /* @__PURE__ */ jsxs14("div", { className, children: [
1478
+ /* @__PURE__ */ jsx21(
1479
+ "div",
1480
+ {
1481
+ onClick: handleToggle,
1482
+ onKeyDown: (e) => {
1483
+ if (e.key === "Enter" || e.key === " ") {
1484
+ e.preventDefault();
1485
+ handleToggle();
1486
+ }
1487
+ },
1488
+ role: "button",
1489
+ tabIndex: disabled ? -1 : 0,
1490
+ "aria-expanded": isOpen,
1491
+ "aria-disabled": disabled,
1492
+ className: disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer",
1493
+ children: trigger
1494
+ }
1495
+ ),
1496
+ /* @__PURE__ */ jsx21(
1497
+ "div",
1498
+ {
1499
+ ref: contentRef,
1500
+ className: "overflow-hidden transition-all duration-300 ease-in-out",
1501
+ style: {
1502
+ maxHeight: isOpen ? contentHeight : 0,
1503
+ opacity: isOpen ? 1 : 0
1504
+ },
1505
+ "aria-hidden": !isOpen,
1506
+ children
1507
+ }
1508
+ )
1509
+ ] });
1510
+ }
1511
+ function CollapsibleTrigger({
1512
+ title,
1513
+ subtitle,
1514
+ isOpen,
1515
+ className = "",
1516
+ icon
1517
+ }) {
1518
+ return /* @__PURE__ */ jsxs14(
1519
+ "div",
1520
+ {
1521
+ className: `flex items-center justify-between p-4 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors ${className}`,
1522
+ children: [
1523
+ /* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
1524
+ /* @__PURE__ */ jsx21("h3", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: title }),
1525
+ subtitle && /* @__PURE__ */ jsx21("p", { className: "text-sm text-gray-500 dark:text-gray-400 truncate", children: subtitle })
1526
+ ] }),
1527
+ /* @__PURE__ */ jsx21("div", { className: "ml-4 flex-shrink-0", children: icon || /* @__PURE__ */ jsx21(
1528
+ "svg",
1529
+ {
1530
+ className: `w-5 h-5 text-gray-400 transition-transform duration-300 ${isOpen ? "rotate-180" : ""}`,
1531
+ fill: "none",
1532
+ stroke: "currentColor",
1533
+ viewBox: "0 0 24 24",
1534
+ children: /* @__PURE__ */ jsx21(
1535
+ "path",
1536
+ {
1537
+ strokeLinecap: "round",
1538
+ strokeLinejoin: "round",
1539
+ strokeWidth: 2,
1540
+ d: "M19 9l-7 7-7-7"
1541
+ }
1542
+ )
1543
+ }
1544
+ ) })
1545
+ ]
1546
+ }
1547
+ );
1548
+ }
1549
+ var bannerVariantClasses = {
1550
+ info: "bg-gradient-to-r from-primary-50 to-blue-50 dark:from-primary-900/20 dark:to-blue-900/20 border-primary-200 dark:border-primary-700",
1551
+ success: "bg-gradient-to-r from-primary-50 to-primary-100 dark:from-primary-900/20 dark:to-primary-800/20 border-primary-200 dark:border-primary-700",
1552
+ warning: "bg-gradient-to-r from-yellow-50 to-amber-50 dark:from-yellow-900/20 dark:to-amber-900/20 border-yellow-200 dark:border-yellow-700",
1553
+ neutral: "bg-gradient-to-r from-gray-50 to-slate-50 dark:from-gray-800 dark:to-slate-800 border-gray-200 dark:border-gray-700",
1554
+ hero: "bg-gradient-to-r from-accent-50 to-accent-100 dark:from-accent-800 dark:to-accent-900 border-accent-200 dark:border-accent-600"
1555
+ };
1556
+ function DismissibleBanner({
1557
+ storageKey,
1558
+ children,
1559
+ dismissText = "Got it",
1560
+ onDismiss,
1561
+ className = "",
1562
+ variant = "info"
1563
+ }) {
1564
+ const [isDismissed, setIsDismissed] = useState4(() => {
1565
+ if (typeof window !== "undefined") {
1566
+ return localStorage.getItem(`banner-${storageKey}-dismissed`) === "true";
1567
+ }
1568
+ return false;
1569
+ });
1570
+ const [isAnimatingOut, setIsAnimatingOut] = useState4(false);
1571
+ const handleDismiss = useCallback3(() => {
1572
+ setIsAnimatingOut(true);
1573
+ setTimeout(() => {
1574
+ setIsDismissed(true);
1575
+ localStorage.setItem(`banner-${storageKey}-dismissed`, "true");
1576
+ onDismiss?.();
1577
+ }, 300);
1578
+ }, [storageKey, onDismiss]);
1579
+ if (isDismissed) {
1580
+ return null;
1581
+ }
1582
+ return /* @__PURE__ */ jsx21(
1583
+ "div",
1584
+ {
1585
+ className: `
1586
+ border rounded-lg p-6 shadow-sm
1587
+ transition-all duration-300 ease-out
1588
+ ${isAnimatingOut ? "opacity-0 -translate-y-4 h-0 p-0 overflow-hidden" : "opacity-100 translate-y-0"}
1589
+ ${bannerVariantClasses[variant]}
1590
+ ${className}
1591
+ `,
1592
+ children: /* @__PURE__ */ jsxs14("div", { className: "flex flex-col", children: [
1593
+ /* @__PURE__ */ jsx21("div", { className: "flex-1", children }),
1594
+ /* @__PURE__ */ jsx21("div", { className: "flex justify-end mt-4", children: /* @__PURE__ */ jsx21(
1595
+ "button",
1596
+ {
1597
+ onClick: handleDismiss,
1598
+ className: `px-4 py-2 text-sm font-medium text-white rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 transition-colors cursor-pointer ${variant === "hero" ? "bg-accent-600 hover:bg-accent-700 focus:ring-accent-500" : "bg-primary-600 hover:bg-primary-700 focus:ring-primary-500"}`,
1599
+ children: dismissText
1600
+ }
1601
+ ) })
1602
+ ] })
1603
+ }
1604
+ );
1605
+ }
1606
+ function useCollapsible(options = {}) {
1607
+ const { defaultOpen = false, storageKey } = options;
1608
+ const [isOpen, setIsOpen] = useState4(() => {
1609
+ if (storageKey && typeof window !== "undefined") {
1610
+ const stored = localStorage.getItem(`collapsible-${storageKey}`);
1611
+ if (stored !== null) {
1612
+ return stored === "true";
1613
+ }
1614
+ }
1615
+ return defaultOpen;
1616
+ });
1617
+ useEffect4(() => {
1618
+ if (storageKey) {
1619
+ localStorage.setItem(`collapsible-${storageKey}`, String(isOpen));
1620
+ }
1621
+ }, [storageKey, isOpen]);
1622
+ const toggle = useCallback3(() => {
1623
+ setIsOpen((prev) => !prev);
1624
+ }, []);
1625
+ const open = useCallback3(() => {
1626
+ setIsOpen(true);
1627
+ }, []);
1628
+ const close = useCallback3(() => {
1629
+ setIsOpen(false);
1630
+ }, []);
1631
+ return {
1632
+ isOpen,
1633
+ toggle,
1634
+ open,
1635
+ close,
1636
+ setIsOpen
1637
+ };
1638
+ }
1639
+ export {
1640
+ Avatar,
1641
+ AvatarFallback,
1642
+ AvatarImage,
1643
+ Badge,
1644
+ Breadcrumbs,
1645
+ Button,
1646
+ Card,
1647
+ CardBody,
1648
+ CardFooter,
1649
+ CardHeader,
1650
+ Checkbox,
1651
+ Collapsible,
1652
+ CollapsibleTrigger,
1653
+ ConfirmDialog,
1654
+ Dialog,
1655
+ DialogClose,
1656
+ DialogContent,
1657
+ DialogDescription,
1658
+ DialogFooter,
1659
+ DialogHeader,
1660
+ DialogOverlay,
1661
+ DialogPortal,
1662
+ DialogTitle,
1663
+ DialogTrigger,
1664
+ DismissibleBanner,
1665
+ DropdownMenu,
1666
+ DropdownMenuCheckboxItem,
1667
+ DropdownMenuContent,
1668
+ DropdownMenuGroup,
1669
+ DropdownMenuItem,
1670
+ DropdownMenuLabel,
1671
+ DropdownMenuPortal,
1672
+ DropdownMenuRadioGroup,
1673
+ DropdownMenuRadioItem,
1674
+ DropdownMenuSeparator,
1675
+ DropdownMenuShortcut,
1676
+ DropdownMenuSub,
1677
+ DropdownMenuSubContent,
1678
+ DropdownMenuSubTrigger,
1679
+ DropdownMenuTrigger,
1680
+ EmptyState,
1681
+ EntityForm,
1682
+ FormField,
1683
+ FormSlideOver,
1684
+ Input,
1685
+ LoadingScreen,
1686
+ LoadingSpinner,
1687
+ SearchBar,
1688
+ SearchInput,
1689
+ Select,
1690
+ SlideOver,
1691
+ Table,
1692
+ TableBody,
1693
+ TableCell,
1694
+ TableHead,
1695
+ TableHeader,
1696
+ TableRow,
1697
+ Tabs,
1698
+ TabsContent,
1699
+ TabsList,
1700
+ TabsTrigger,
1701
+ Textarea,
1702
+ cn,
1703
+ useCollapsible
1704
+ };
1705
+ //# sourceMappingURL=index.js.map