@ataraui/ataraui-react 0.2.0 → 0.4.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 CHANGED
@@ -2,13 +2,14 @@
2
2
 
3
3
  var clsx = require('clsx');
4
4
  var tailwindMerge = require('tailwind-merge');
5
- var React3 = require('react');
5
+ var React13 = require('react');
6
6
  var classVarianceAuthority = require('class-variance-authority');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
+ var reactDom = require('react-dom');
8
9
 
9
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
11
 
11
- var React3__default = /*#__PURE__*/_interopDefault(React3);
12
+ var React13__default = /*#__PURE__*/_interopDefault(React13);
12
13
 
13
14
  // src/utils/cn.ts
14
15
  function cn(...inputs) {
@@ -94,7 +95,7 @@ var buttonVariants = classVarianceAuthority.cva(
94
95
  }
95
96
  }
96
97
  );
97
- var Button = React3__default.default.forwardRef(
98
+ var Button = React13__default.default.forwardRef(
98
99
  ({ className, variant, size, isLoading, children, disabled, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
99
100
  "button",
100
101
  {
@@ -133,7 +134,7 @@ var inputVariants = classVarianceAuthority.cva(
133
134
  }
134
135
  }
135
136
  );
136
- var Input = React3__default.default.forwardRef(
137
+ var Input = React13__default.default.forwardRef(
137
138
  ({ className, label, error, hint, id, inputSize, ...props }, ref) => {
138
139
  const inputId = id != null ? id : label == null ? void 0 : label.toLowerCase().replace(/\s+/g, "-");
139
140
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 w-full", children: [
@@ -200,7 +201,7 @@ var cardVariants = classVarianceAuthority.cva(
200
201
  }
201
202
  }
202
203
  );
203
- var Card = React3__default.default.forwardRef(
204
+ var Card = React13__default.default.forwardRef(
204
205
  ({ className, variant, padding, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
205
206
  "div",
206
207
  {
@@ -211,23 +212,23 @@ var Card = React3__default.default.forwardRef(
211
212
  )
212
213
  );
213
214
  Card.displayName = "Card";
214
- var CardHeader = React3__default.default.forwardRef(
215
+ var CardHeader = React13__default.default.forwardRef(
215
216
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col gap-1.5 mb-4", className), ...props })
216
217
  );
217
218
  CardHeader.displayName = "CardHeader";
218
- var CardTitle = React3__default.default.forwardRef(
219
+ var CardTitle = React13__default.default.forwardRef(
219
220
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("text-lg font-semibold text-(--color-neutral-900)", className), ...props })
220
221
  );
221
222
  CardTitle.displayName = "CardTitle";
222
- var CardDescription = React3__default.default.forwardRef(
223
+ var CardDescription = React13__default.default.forwardRef(
223
224
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("text-sm text-(--color-neutral-500)", className), ...props })
224
225
  );
225
226
  CardDescription.displayName = "CardDescription";
226
- var CardContent = React3__default.default.forwardRef(
227
+ var CardContent = React13__default.default.forwardRef(
227
228
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("text-sm text-(--color-neutral-700)", className), ...props })
228
229
  );
229
230
  CardContent.displayName = "CardContent";
230
- var CardFooter = React3__default.default.forwardRef(
231
+ var CardFooter = React13__default.default.forwardRef(
231
232
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex items-center gap-2 mt-4", className), ...props })
232
233
  );
233
234
  CardFooter.displayName = "CardFooter";
@@ -248,9 +249,9 @@ var avatarVariants = classVarianceAuthority.cva(
248
249
  }
249
250
  }
250
251
  );
251
- var Avatar = React3__default.default.forwardRef(
252
+ var Avatar = React13__default.default.forwardRef(
252
253
  ({ className, size, src, alt, fallback, ...props }, ref) => {
253
- const [imgError, setImgError] = React3__default.default.useState(false);
254
+ const [imgError, setImgError] = React13__default.default.useState(false);
254
255
  const initials = fallback == null ? void 0 : fallback.split(" ").map((word) => word[0]).slice(0, 2).join("").toUpperCase();
255
256
  return /* @__PURE__ */ jsxRuntime.jsx(
256
257
  "span",
@@ -294,7 +295,7 @@ var separatorVariants = classVarianceAuthority.cva(
294
295
  }
295
296
  }
296
297
  );
297
- var Separator = React3__default.default.forwardRef(
298
+ var Separator = React13__default.default.forwardRef(
298
299
  ({ className, orientation, label, ...props }, ref) => {
299
300
  if (label && orientation !== "vertical") {
300
301
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("flex items-center gap-3", className), ...props, children: [
@@ -333,7 +334,7 @@ var spinnerVariants = classVarianceAuthority.cva(
333
334
  }
334
335
  }
335
336
  );
336
- var Spinner = React3__default.default.forwardRef(
337
+ var Spinner = React13__default.default.forwardRef(
337
338
  ({ className, size, label, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, role: "status", className: cn("inline-flex flex-col items-center gap-2", className), ...props, children: [
338
339
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(spinnerVariants({ size })) }),
339
340
  label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-(--color-neutral-500)", children: label }),
@@ -341,6 +342,780 @@ var Spinner = React3__default.default.forwardRef(
341
342
  ] })
342
343
  );
343
344
  Spinner.displayName = "Spinner";
345
+ var selectVariants = classVarianceAuthority.cva(
346
+ "w-full appearance-none bg-white border rounded-(--radius-md) px-3 py-2 text-sm transition-colors cursor-pointer focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-(--color-neutral-50)",
347
+ {
348
+ variants: {
349
+ state: {
350
+ default: "border-(--color-neutral-300) text-(--color-neutral-900) focus:border-(--color-primary-500) focus:ring-(--color-primary-500)/20",
351
+ error: "border-(--color-danger-500) text-(--color-neutral-900) focus:border-(--color-danger-500) focus:ring-(--color-danger-500)/20"
352
+ },
353
+ selectSize: {
354
+ sm: "h-8 text-xs pr-8",
355
+ md: "h-10 text-sm pr-8",
356
+ lg: "h-12 text-base pr-10"
357
+ }
358
+ },
359
+ defaultVariants: {
360
+ state: "default",
361
+ selectSize: "md"
362
+ }
363
+ }
364
+ );
365
+ var Select = React13__default.default.forwardRef(
366
+ ({ className, label, error, hint, placeholder, options, selectSize, id, children, ...props }, ref) => {
367
+ const selectId = id != null ? id : label == null ? void 0 : label.toLowerCase().replace(/\s+/g, "-");
368
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 w-full", children: [
369
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: selectId, className: "text-sm font-medium text-(--color-neutral-700)", children: label }),
370
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
371
+ /* @__PURE__ */ jsxRuntime.jsxs(
372
+ "select",
373
+ {
374
+ ref,
375
+ id: selectId,
376
+ className: cn(selectVariants({ state: error ? "error" : "default", selectSize }), className),
377
+ ...props,
378
+ children: [
379
+ placeholder && /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: placeholder }),
380
+ options ? options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.value, disabled: opt.disabled, children: opt.label }, opt.value)) : children
381
+ ]
382
+ }
383
+ ),
384
+ /* @__PURE__ */ jsxRuntime.jsx(
385
+ "svg",
386
+ {
387
+ className: "pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-(--color-neutral-400)",
388
+ xmlns: "http://www.w3.org/2000/svg",
389
+ viewBox: "0 0 24 24",
390
+ fill: "none",
391
+ stroke: "currentColor",
392
+ strokeWidth: "2",
393
+ strokeLinecap: "round",
394
+ strokeLinejoin: "round",
395
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
396
+ }
397
+ )
398
+ ] }),
399
+ hint && !error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--color-neutral-500)", children: hint }),
400
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--color-danger-500)", children: error })
401
+ ] });
402
+ }
403
+ );
404
+ Select.displayName = "Select";
405
+ var Checkbox = React13__default.default.forwardRef(
406
+ ({ className, label, description, error, id, disabled, ...props }, ref) => {
407
+ const checkboxId = id != null ? id : label == null ? void 0 : label.toLowerCase().replace(/\s+/g, "-");
408
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
409
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2.5", children: [
410
+ /* @__PURE__ */ jsxRuntime.jsx(
411
+ "input",
412
+ {
413
+ ref,
414
+ type: "checkbox",
415
+ id: checkboxId,
416
+ disabled,
417
+ className: cn(
418
+ "h-4 w-4 shrink-0 mt-0.5 rounded-(--radius-sm) border cursor-pointer transition-colors appearance-none",
419
+ "border-(--color-neutral-300) bg-white",
420
+ "checked:bg-(--color-primary-500) checked:border-(--color-primary-500)",
421
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--color-primary-500)/20",
422
+ "disabled:cursor-not-allowed disabled:opacity-50",
423
+ error && "border-(--color-danger-500)",
424
+ className
425
+ ),
426
+ style: {
427
+ backgroundImage: `url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")`,
428
+ backgroundRepeat: "no-repeat",
429
+ backgroundPosition: "center"
430
+ },
431
+ ...props
432
+ }
433
+ ),
434
+ (label || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
435
+ label && /* @__PURE__ */ jsxRuntime.jsx(
436
+ "label",
437
+ {
438
+ htmlFor: checkboxId,
439
+ className: cn(
440
+ "text-sm font-medium cursor-pointer text-(--color-neutral-900)",
441
+ disabled && "cursor-not-allowed opacity-50"
442
+ ),
443
+ children: label
444
+ }
445
+ ),
446
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--color-neutral-500)", children: description })
447
+ ] })
448
+ ] }),
449
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--color-danger-500) ml-6", children: error })
450
+ ] });
451
+ }
452
+ );
453
+ Checkbox.displayName = "Checkbox";
454
+ var RadioGroup = ({
455
+ options,
456
+ value,
457
+ onChange,
458
+ name,
459
+ label,
460
+ error,
461
+ hint,
462
+ orientation = "vertical"
463
+ }) => {
464
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
465
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-(--color-neutral-700)", children: label }),
466
+ /* @__PURE__ */ jsxRuntime.jsx(
467
+ "div",
468
+ {
469
+ className: cn(
470
+ "flex gap-3",
471
+ orientation === "vertical" ? "flex-col" : "flex-row flex-wrap"
472
+ ),
473
+ children: options.map((option) => {
474
+ const optionId = `${name}-${option.value}`;
475
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2.5", children: [
476
+ /* @__PURE__ */ jsxRuntime.jsx(
477
+ "input",
478
+ {
479
+ type: "radio",
480
+ id: optionId,
481
+ name,
482
+ value: option.value,
483
+ checked: value === option.value,
484
+ disabled: option.disabled,
485
+ onChange: () => onChange == null ? void 0 : onChange(option.value),
486
+ className: cn(
487
+ "h-4 w-4 shrink-0 mt-0.5 cursor-pointer appearance-none rounded-full border-2 transition-colors",
488
+ "border-(--color-neutral-300) bg-white",
489
+ "checked:border-(--color-primary-500) checked:bg-(--color-primary-500)",
490
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--color-primary-500)/20",
491
+ "disabled:cursor-not-allowed disabled:opacity-50",
492
+ error && "border-(--color-danger-500)"
493
+ ),
494
+ style: {
495
+ backgroundImage: value === option.value ? `url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")` : "none",
496
+ backgroundRepeat: "no-repeat",
497
+ backgroundPosition: "center"
498
+ }
499
+ }
500
+ ),
501
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
502
+ /* @__PURE__ */ jsxRuntime.jsx(
503
+ "label",
504
+ {
505
+ htmlFor: optionId,
506
+ className: cn(
507
+ "text-sm font-medium cursor-pointer text-(--color-neutral-900)",
508
+ option.disabled && "cursor-not-allowed opacity-50"
509
+ ),
510
+ children: option.label
511
+ }
512
+ ),
513
+ option.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--color-neutral-500)", children: option.description })
514
+ ] })
515
+ ] }, option.value);
516
+ })
517
+ }
518
+ ),
519
+ hint && !error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--color-neutral-500)", children: hint }),
520
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--color-danger-500)", children: error })
521
+ ] });
522
+ };
523
+ RadioGroup.displayName = "RadioGroup";
524
+ var Switch = React13__default.default.forwardRef(
525
+ ({ className, label, description, error, id, disabled, checked, defaultChecked, onChange, ...props }, ref) => {
526
+ const switchId = id != null ? id : `switch-${Math.random().toString(36).slice(2, 9)}`;
527
+ const [internalChecked, setInternalChecked] = React13__default.default.useState(
528
+ defaultChecked != null ? defaultChecked : false
529
+ );
530
+ const isControlled = checked !== void 0;
531
+ const isChecked = isControlled ? checked : internalChecked;
532
+ const handleChange = (e) => {
533
+ if (!isControlled) setInternalChecked(e.target.checked);
534
+ onChange == null ? void 0 : onChange(e);
535
+ };
536
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
537
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
538
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative inline-flex shrink-0 mt-0.5", children: [
539
+ /* @__PURE__ */ jsxRuntime.jsx(
540
+ "input",
541
+ {
542
+ ref,
543
+ type: "checkbox",
544
+ role: "switch",
545
+ id: switchId,
546
+ disabled,
547
+ checked: isChecked,
548
+ onChange: handleChange,
549
+ className: "sr-only peer",
550
+ ...props
551
+ }
552
+ ),
553
+ /* @__PURE__ */ jsxRuntime.jsx(
554
+ "label",
555
+ {
556
+ htmlFor: switchId,
557
+ className: cn(
558
+ "relative flex h-5 w-9 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors",
559
+ "bg-(--color-neutral-200) peer-checked:bg-(--color-primary-500)",
560
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-(--color-primary-500)/20",
561
+ "peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
562
+ error && "ring-2 ring-(--color-danger-500)/20",
563
+ className
564
+ ),
565
+ children: /* @__PURE__ */ jsxRuntime.jsx(
566
+ "span",
567
+ {
568
+ className: "pointer-events-none block h-3.5 w-3.5 rounded-full bg-white shadow transition-transform",
569
+ style: {
570
+ transform: isChecked ? "translateX(18px)" : "translateX(2px)"
571
+ }
572
+ }
573
+ )
574
+ }
575
+ )
576
+ ] }),
577
+ (label || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
578
+ label && /* @__PURE__ */ jsxRuntime.jsx(
579
+ "span",
580
+ {
581
+ className: cn(
582
+ "text-sm font-medium text-(--color-neutral-900)",
583
+ disabled && "opacity-50"
584
+ ),
585
+ children: label
586
+ }
587
+ ),
588
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--color-neutral-500)", children: description })
589
+ ] })
590
+ ] }),
591
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--color-danger-500) ml-12", children: error })
592
+ ] });
593
+ }
594
+ );
595
+ Switch.displayName = "Switch";
596
+ var modalVariants = classVarianceAuthority.cva(
597
+ "relative bg-white rounded-(--radius-xl) shadow-lg w-full mx-4 transition-all",
598
+ {
599
+ variants: {
600
+ size: {
601
+ sm: "max-w-sm",
602
+ md: "max-w-md",
603
+ lg: "max-w-lg",
604
+ xl: "max-w-xl",
605
+ full: "max-w-full mx-4"
606
+ }
607
+ },
608
+ defaultVariants: {
609
+ size: "md"
610
+ }
611
+ }
612
+ );
613
+ var Modal = ({
614
+ open,
615
+ onClose,
616
+ children,
617
+ size,
618
+ className,
619
+ closeOnOverlayClick = true
620
+ }) => {
621
+ React13__default.default.useEffect(() => {
622
+ if (open) {
623
+ const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
624
+ document.body.style.overflow = "hidden";
625
+ document.body.style.paddingRight = `${scrollbarWidth}px`;
626
+ } else {
627
+ document.body.style.overflow = "";
628
+ document.body.style.paddingRight = "";
629
+ }
630
+ return () => {
631
+ document.body.style.overflow = "";
632
+ document.body.style.paddingRight = "";
633
+ };
634
+ }, [open]);
635
+ React13__default.default.useEffect(() => {
636
+ const handleKey = (e) => {
637
+ if (e.key === "Escape") onClose();
638
+ };
639
+ if (open) document.addEventListener("keydown", handleKey);
640
+ return () => document.removeEventListener("keydown", handleKey);
641
+ }, [open, onClose]);
642
+ if (!open) return null;
643
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
644
+ /* @__PURE__ */ jsxRuntime.jsx(
645
+ "div",
646
+ {
647
+ className: "absolute inset-0 bg-black/50",
648
+ onClick: closeOnOverlayClick ? onClose : void 0
649
+ }
650
+ ),
651
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(modalVariants({ size }), className), children })
652
+ ] });
653
+ };
654
+ Modal.displayName = "Modal";
655
+ var ModalHeader = ({
656
+ className,
657
+ children,
658
+ onClose,
659
+ ...props
660
+ }) => /* @__PURE__ */ jsxRuntime.jsxs(
661
+ "div",
662
+ {
663
+ className: cn("flex items-start justify-between p-6 pb-4", className),
664
+ ...props,
665
+ children: [
666
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children }),
667
+ onClose && /* @__PURE__ */ jsxRuntime.jsx(
668
+ "button",
669
+ {
670
+ type: "button",
671
+ onClick: onClose,
672
+ className: "ml-4 shrink-0 rounded-(--radius-md) p-1 text-(--color-neutral-400) hover:bg-(--color-neutral-100) hover:text-(--color-neutral-700) transition-colors",
673
+ children: /* @__PURE__ */ jsxRuntime.jsx(
674
+ "svg",
675
+ {
676
+ xmlns: "http://www.w3.org/2000/svg",
677
+ className: "h-4 w-4",
678
+ viewBox: "0 0 24 24",
679
+ fill: "none",
680
+ stroke: "currentColor",
681
+ strokeWidth: "2",
682
+ strokeLinecap: "round",
683
+ strokeLinejoin: "round",
684
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" })
685
+ }
686
+ )
687
+ }
688
+ )
689
+ ]
690
+ }
691
+ );
692
+ ModalHeader.displayName = "ModalHeader";
693
+ var ModalTitle = ({
694
+ className,
695
+ ...props
696
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
697
+ "h2",
698
+ {
699
+ className: cn(
700
+ "text-lg font-semibold text-(--color-neutral-900)",
701
+ className
702
+ ),
703
+ ...props
704
+ }
705
+ );
706
+ ModalTitle.displayName = "ModalTitle";
707
+ var ModalDescription = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
708
+ "p",
709
+ {
710
+ className: cn("text-sm text-(--color-neutral-500)", className),
711
+ ...props
712
+ }
713
+ );
714
+ ModalDescription.displayName = "ModalDescription";
715
+ var ModalBody = ({
716
+ className,
717
+ ...props
718
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
719
+ "div",
720
+ {
721
+ className: cn("px-6 py-2 text-sm text-(--color-neutral-700)", className),
722
+ ...props
723
+ }
724
+ );
725
+ ModalBody.displayName = "ModalBody";
726
+ var ModalFooter = ({
727
+ className,
728
+ ...props
729
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
730
+ "div",
731
+ {
732
+ className: cn("flex items-center justify-end gap-2 p-6 pt-4", className),
733
+ ...props
734
+ }
735
+ );
736
+ ModalFooter.displayName = "ModalFooter";
737
+ var drawerVariants = classVarianceAuthority.cva(
738
+ "fixed z-50 bg-white shadow-xl transition-transform duration-300 ease-in-out",
739
+ {
740
+ variants: {
741
+ side: {
742
+ left: "inset-y-0 left-0 h-full",
743
+ right: "inset-y-0 right-0 h-full",
744
+ top: "inset-x-0 top-0 w-full",
745
+ bottom: "inset-x-0 bottom-0 w-full"
746
+ }
747
+ },
748
+ defaultVariants: {
749
+ side: "right"
750
+ }
751
+ }
752
+ );
753
+ var sizeStyle = {
754
+ sm: { width: "20rem" },
755
+ md: { width: "24rem" },
756
+ lg: { width: "32rem" },
757
+ full: { width: "100%" }
758
+ };
759
+ var translateMap = {
760
+ left: { closed: "translateX(-100%)", open: "translateX(0)" },
761
+ right: { closed: "translateX(100%)", open: "translateX(0)" },
762
+ top: { closed: "translateY(-100%)", open: "translateY(0)" },
763
+ bottom: { closed: "translateY(100%)", open: "translateY(0)" }
764
+ };
765
+ var Drawer = ({
766
+ open,
767
+ onClose,
768
+ children,
769
+ side = "right",
770
+ size = "md",
771
+ className,
772
+ closeOnOverlayClick = true
773
+ }) => {
774
+ React13__default.default.useEffect(() => {
775
+ if (open) {
776
+ const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
777
+ document.body.style.overflow = "hidden";
778
+ document.body.style.paddingRight = `${scrollbarWidth}px`;
779
+ } else {
780
+ document.body.style.overflow = "";
781
+ document.body.style.paddingRight = "";
782
+ }
783
+ return () => {
784
+ document.body.style.overflow = "";
785
+ document.body.style.paddingRight = "";
786
+ };
787
+ }, [open]);
788
+ React13__default.default.useEffect(() => {
789
+ const handleKey = (e) => {
790
+ if (e.key === "Escape") onClose();
791
+ };
792
+ if (open) document.addEventListener("keydown", handleKey);
793
+ return () => document.removeEventListener("keydown", handleKey);
794
+ }, [open, onClose]);
795
+ const resolvedSide = side != null ? side : "right";
796
+ const transform = open ? translateMap[resolvedSide].open : translateMap[resolvedSide].closed;
797
+ const isHorizontal = resolvedSide === "left" || resolvedSide === "right";
798
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("fixed inset-0 z-50", !open && "pointer-events-none"), children: [
799
+ /* @__PURE__ */ jsxRuntime.jsx(
800
+ "div",
801
+ {
802
+ className: cn(
803
+ "absolute inset-0 bg-black/50 transition-opacity duration-300",
804
+ open ? "opacity-100" : "opacity-0"
805
+ ),
806
+ onClick: closeOnOverlayClick ? onClose : void 0
807
+ }
808
+ ),
809
+ /* @__PURE__ */ jsxRuntime.jsx(
810
+ "div",
811
+ {
812
+ className: cn(drawerVariants({ side }), className),
813
+ style: {
814
+ transform,
815
+ ...isHorizontal ? sizeStyle[size] : { height: "auto", maxHeight: "80vh" }
816
+ },
817
+ children
818
+ }
819
+ )
820
+ ] });
821
+ };
822
+ Drawer.displayName = "Drawer";
823
+ var DrawerHeader = ({
824
+ className,
825
+ children,
826
+ onClose,
827
+ ...props
828
+ }) => /* @__PURE__ */ jsxRuntime.jsxs(
829
+ "div",
830
+ {
831
+ className: cn("flex items-start justify-between p-6 pb-4 border-b border-(--color-neutral-200)", className),
832
+ ...props,
833
+ children: [
834
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children }),
835
+ onClose && /* @__PURE__ */ jsxRuntime.jsx(
836
+ "button",
837
+ {
838
+ type: "button",
839
+ onClick: onClose,
840
+ className: "ml-4 shrink-0 rounded-(--radius-md) p-1 text-(--color-neutral-400) hover:bg-(--color-neutral-100) hover:text-(--color-neutral-700) transition-colors",
841
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
842
+ }
843
+ )
844
+ ]
845
+ }
846
+ );
847
+ DrawerHeader.displayName = "DrawerHeader";
848
+ var DrawerTitle = ({
849
+ className,
850
+ ...props
851
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
852
+ "h2",
853
+ {
854
+ className: cn("text-lg font-semibold text-(--color-neutral-900)", className),
855
+ ...props
856
+ }
857
+ );
858
+ DrawerTitle.displayName = "DrawerTitle";
859
+ var DrawerDescription = ({
860
+ className,
861
+ ...props
862
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
863
+ "p",
864
+ {
865
+ className: cn("text-sm text-(--color-neutral-500)", className),
866
+ ...props
867
+ }
868
+ );
869
+ DrawerDescription.displayName = "DrawerDescription";
870
+ var DrawerBody = ({
871
+ className,
872
+ ...props
873
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
874
+ "div",
875
+ {
876
+ className: cn("flex-1 overflow-y-auto p-6 text-sm text-(--color-neutral-700)", className),
877
+ ...props
878
+ }
879
+ );
880
+ DrawerBody.displayName = "DrawerBody";
881
+ var DrawerFooter = ({
882
+ className,
883
+ ...props
884
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
885
+ "div",
886
+ {
887
+ className: cn("flex items-center justify-end gap-2 p-6 pt-4 border-t border-(--color-neutral-200)", className),
888
+ ...props
889
+ }
890
+ );
891
+ DrawerFooter.displayName = "DrawerFooter";
892
+ var Tooltip = ({
893
+ content,
894
+ children,
895
+ side = "top",
896
+ delay = 300,
897
+ className
898
+ }) => {
899
+ var _a, _b;
900
+ const [visible, setVisible] = React13__default.default.useState(false);
901
+ const [coords, setCoords] = React13__default.default.useState(null);
902
+ const triggerRef = React13__default.default.useRef(null);
903
+ const tooltipRef = React13__default.default.useRef(null);
904
+ const timerRef = React13__default.default.useRef(null);
905
+ const computeCoords = React13__default.default.useCallback(() => {
906
+ if (!triggerRef.current || !tooltipRef.current) return;
907
+ const t = triggerRef.current.getBoundingClientRect();
908
+ const tt = tooltipRef.current.getBoundingClientRect();
909
+ const offset = 8;
910
+ switch (side) {
911
+ case "top":
912
+ setCoords({
913
+ top: t.top - tt.height - offset,
914
+ left: t.left + t.width / 2 - tt.width / 2
915
+ });
916
+ break;
917
+ case "bottom":
918
+ setCoords({
919
+ top: t.bottom + offset,
920
+ left: t.left + t.width / 2 - tt.width / 2
921
+ });
922
+ break;
923
+ case "left":
924
+ setCoords({
925
+ top: t.top + t.height / 2 - tt.height / 2,
926
+ left: t.left - tt.width - offset
927
+ });
928
+ break;
929
+ case "right":
930
+ setCoords({
931
+ top: t.top + t.height / 2 - tt.height / 2,
932
+ left: t.right + offset
933
+ });
934
+ break;
935
+ }
936
+ }, [side]);
937
+ React13__default.default.useLayoutEffect(() => {
938
+ if (!visible) return;
939
+ computeCoords();
940
+ }, [computeCoords, content, visible]);
941
+ React13__default.default.useEffect(() => {
942
+ if (!visible) return;
943
+ window.addEventListener("resize", computeCoords);
944
+ window.addEventListener("scroll", computeCoords, true);
945
+ return () => {
946
+ window.removeEventListener("resize", computeCoords);
947
+ window.removeEventListener("scroll", computeCoords, true);
948
+ };
949
+ }, [computeCoords, visible]);
950
+ const show = () => {
951
+ if (timerRef.current) clearTimeout(timerRef.current);
952
+ timerRef.current = setTimeout(() => {
953
+ setCoords(null);
954
+ setVisible(true);
955
+ }, delay);
956
+ };
957
+ const hide = () => {
958
+ if (timerRef.current) clearTimeout(timerRef.current);
959
+ setVisible(false);
960
+ setCoords(null);
961
+ };
962
+ React13__default.default.useEffect(() => {
963
+ return () => {
964
+ if (timerRef.current) clearTimeout(timerRef.current);
965
+ };
966
+ }, []);
967
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
968
+ /* @__PURE__ */ jsxRuntime.jsx(
969
+ "div",
970
+ {
971
+ ref: triggerRef,
972
+ className: "inline-flex",
973
+ onMouseEnter: show,
974
+ onMouseLeave: hide,
975
+ onFocus: show,
976
+ onBlur: hide,
977
+ children
978
+ }
979
+ ),
980
+ visible && /* @__PURE__ */ jsxRuntime.jsx(
981
+ "div",
982
+ {
983
+ ref: tooltipRef,
984
+ role: "tooltip",
985
+ className: cn(
986
+ "fixed z-50 px-2.5 py-1.5 text-xs font-medium text-white rounded-(--radius-md) shadow-md pointer-events-none whitespace-nowrap transition-opacity",
987
+ coords ? "opacity-100" : "opacity-0",
988
+ className
989
+ ),
990
+ style: {
991
+ top: (_a = coords == null ? void 0 : coords.top) != null ? _a : 0,
992
+ left: (_b = coords == null ? void 0 : coords.left) != null ? _b : 0,
993
+ backgroundColor: "var(--color-neutral-900)"
994
+ },
995
+ children: content
996
+ }
997
+ )
998
+ ] });
999
+ };
1000
+ Tooltip.displayName = "Tooltip";
1001
+ var Popover = ({
1002
+ content,
1003
+ children,
1004
+ side = "bottom",
1005
+ align = "center",
1006
+ open,
1007
+ defaultOpen = false,
1008
+ onOpenChange,
1009
+ className,
1010
+ closeOnOutsideClick = true
1011
+ }) => {
1012
+ var _a, _b;
1013
+ const [uncontrolledOpen, setUncontrolledOpen] = React13__default.default.useState(defaultOpen);
1014
+ const [coords, setCoords] = React13__default.default.useState(null);
1015
+ const [mounted, setMounted] = React13__default.default.useState(false);
1016
+ const triggerRef = React13__default.default.useRef(null);
1017
+ const popoverRef = React13__default.default.useRef(null);
1018
+ const isControlled = open !== void 0;
1019
+ const isOpen = isControlled ? open : uncontrolledOpen;
1020
+ const setOpen = React13__default.default.useCallback((nextOpen) => {
1021
+ if (!isControlled) setUncontrolledOpen(nextOpen);
1022
+ onOpenChange == null ? void 0 : onOpenChange(nextOpen);
1023
+ }, [isControlled, onOpenChange]);
1024
+ const close = React13__default.default.useCallback(() => setOpen(false), [setOpen]);
1025
+ const openPopover = React13__default.default.useCallback(() => setOpen(true), [setOpen]);
1026
+ const controls = React13__default.default.useMemo(() => ({
1027
+ close,
1028
+ open: openPopover,
1029
+ setOpen
1030
+ }), [close, openPopover, setOpen]);
1031
+ const computeCoords = React13__default.default.useCallback(() => {
1032
+ if (!triggerRef.current || !popoverRef.current) return;
1033
+ const trigger = triggerRef.current.getBoundingClientRect();
1034
+ const popover2 = popoverRef.current.getBoundingClientRect();
1035
+ const offset = 8;
1036
+ let top = 0;
1037
+ let left = 0;
1038
+ if (side === "top") top = trigger.top - popover2.height - offset;
1039
+ if (side === "bottom") top = trigger.bottom + offset;
1040
+ if (side === "left") left = trigger.left - popover2.width - offset;
1041
+ if (side === "right") left = trigger.right + offset;
1042
+ if (side === "top" || side === "bottom") {
1043
+ if (align === "start") left = trigger.left;
1044
+ if (align === "center") left = trigger.left + trigger.width / 2 - popover2.width / 2;
1045
+ if (align === "end") left = trigger.right - popover2.width;
1046
+ }
1047
+ if (side === "left" || side === "right") {
1048
+ if (align === "start") top = trigger.top;
1049
+ if (align === "center") top = trigger.top + trigger.height / 2 - popover2.height / 2;
1050
+ if (align === "end") top = trigger.bottom - popover2.height;
1051
+ }
1052
+ setCoords({
1053
+ top: Math.max(8, Math.min(top, window.innerHeight - popover2.height - 8)),
1054
+ left: Math.max(8, Math.min(left, window.innerWidth - popover2.width - 8))
1055
+ });
1056
+ }, [align, side]);
1057
+ React13__default.default.useEffect(() => {
1058
+ setMounted(true);
1059
+ }, []);
1060
+ React13__default.default.useLayoutEffect(() => {
1061
+ if (!isOpen) return;
1062
+ computeCoords();
1063
+ }, [computeCoords, content, isOpen]);
1064
+ React13__default.default.useEffect(() => {
1065
+ if (!isOpen) return;
1066
+ const handleKeyDown = (event) => {
1067
+ if (event.key === "Escape") close();
1068
+ };
1069
+ const handlePointerDown = (event) => {
1070
+ var _a2, _b2;
1071
+ const target = event.target;
1072
+ const clickedTrigger = (_a2 = triggerRef.current) == null ? void 0 : _a2.contains(target);
1073
+ const clickedPopover = (_b2 = popoverRef.current) == null ? void 0 : _b2.contains(target);
1074
+ if (!clickedTrigger && !clickedPopover) close();
1075
+ };
1076
+ document.addEventListener("keydown", handleKeyDown);
1077
+ if (closeOnOutsideClick) document.addEventListener("pointerdown", handlePointerDown);
1078
+ window.addEventListener("resize", computeCoords);
1079
+ window.addEventListener("scroll", computeCoords, true);
1080
+ return () => {
1081
+ document.removeEventListener("keydown", handleKeyDown);
1082
+ document.removeEventListener("pointerdown", handlePointerDown);
1083
+ window.removeEventListener("resize", computeCoords);
1084
+ window.removeEventListener("scroll", computeCoords, true);
1085
+ };
1086
+ }, [close, closeOnOutsideClick, computeCoords, isOpen]);
1087
+ const popover = isOpen ? /* @__PURE__ */ jsxRuntime.jsx(
1088
+ "div",
1089
+ {
1090
+ ref: popoverRef,
1091
+ role: "dialog",
1092
+ className: cn(
1093
+ "fixed z-50 min-w-48 rounded-(--radius-lg) border border-(--color-neutral-200) bg-white p-4 text-sm text-(--color-neutral-700) shadow-lg outline-none transition-opacity",
1094
+ coords ? "opacity-100" : "opacity-0",
1095
+ className
1096
+ ),
1097
+ style: {
1098
+ top: (_a = coords == null ? void 0 : coords.top) != null ? _a : 0,
1099
+ left: (_b = coords == null ? void 0 : coords.left) != null ? _b : 0
1100
+ },
1101
+ children: typeof content === "function" ? content(controls) : content
1102
+ }
1103
+ ) : null;
1104
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1105
+ /* @__PURE__ */ jsxRuntime.jsx(
1106
+ "div",
1107
+ {
1108
+ ref: triggerRef,
1109
+ className: "inline-flex",
1110
+ "aria-expanded": isOpen,
1111
+ onClick: () => setOpen(!isOpen),
1112
+ children
1113
+ }
1114
+ ),
1115
+ mounted && popover ? reactDom.createPortal(popover, document.body) : null
1116
+ ] });
1117
+ };
1118
+ Popover.displayName = "Popover";
344
1119
 
345
1120
  exports.Avatar = Avatar;
346
1121
  exports.Badge = Badge;
@@ -351,18 +1126,39 @@ exports.CardDescription = CardDescription;
351
1126
  exports.CardFooter = CardFooter;
352
1127
  exports.CardHeader = CardHeader;
353
1128
  exports.CardTitle = CardTitle;
1129
+ exports.Checkbox = Checkbox;
1130
+ exports.Drawer = Drawer;
1131
+ exports.DrawerBody = DrawerBody;
1132
+ exports.DrawerDescription = DrawerDescription;
1133
+ exports.DrawerFooter = DrawerFooter;
1134
+ exports.DrawerHeader = DrawerHeader;
1135
+ exports.DrawerTitle = DrawerTitle;
354
1136
  exports.Input = Input;
1137
+ exports.Modal = Modal;
1138
+ exports.ModalBody = ModalBody;
1139
+ exports.ModalDescription = ModalDescription;
1140
+ exports.ModalFooter = ModalFooter;
1141
+ exports.ModalHeader = ModalHeader;
1142
+ exports.ModalTitle = ModalTitle;
1143
+ exports.Popover = Popover;
1144
+ exports.RadioGroup = RadioGroup;
1145
+ exports.Select = Select;
355
1146
  exports.Separator = Separator;
356
1147
  exports.Spinner = Spinner;
1148
+ exports.Switch = Switch;
1149
+ exports.Tooltip = Tooltip;
357
1150
  exports.avatarVariants = avatarVariants;
358
1151
  exports.badgeVariants = badgeVariants;
359
1152
  exports.buttonVariants = buttonVariants;
360
1153
  exports.cardVariants = cardVariants;
361
1154
  exports.cn = cn;
362
1155
  exports.colors = colors;
1156
+ exports.drawerVariants = drawerVariants;
363
1157
  exports.fontSize = fontSize;
364
1158
  exports.inputVariants = inputVariants;
1159
+ exports.modalVariants = modalVariants;
365
1160
  exports.radius = radius;
1161
+ exports.selectVariants = selectVariants;
366
1162
  exports.separatorVariants = separatorVariants;
367
1163
  exports.spinnerVariants = spinnerVariants;
368
1164
  //# sourceMappingURL=index.js.map