@ataraui/ataraui-react 0.3.0 → 0.5.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 }),
@@ -361,7 +362,7 @@ var selectVariants = classVarianceAuthority.cva(
361
362
  }
362
363
  }
363
364
  );
364
- var Select = React3__default.default.forwardRef(
365
+ var Select = React13__default.default.forwardRef(
365
366
  ({ className, label, error, hint, placeholder, options, selectSize, id, children, ...props }, ref) => {
366
367
  const selectId = id != null ? id : label == null ? void 0 : label.toLowerCase().replace(/\s+/g, "-");
367
368
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 w-full", children: [
@@ -401,7 +402,7 @@ var Select = React3__default.default.forwardRef(
401
402
  }
402
403
  );
403
404
  Select.displayName = "Select";
404
- var Checkbox = React3__default.default.forwardRef(
405
+ var Checkbox = React13__default.default.forwardRef(
405
406
  ({ className, label, description, error, id, disabled, ...props }, ref) => {
406
407
  const checkboxId = id != null ? id : label == null ? void 0 : label.toLowerCase().replace(/\s+/g, "-");
407
408
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
@@ -520,10 +521,10 @@ var RadioGroup = ({
520
521
  ] });
521
522
  };
522
523
  RadioGroup.displayName = "RadioGroup";
523
- var Switch = React3__default.default.forwardRef(
524
+ var Switch = React13__default.default.forwardRef(
524
525
  ({ className, label, description, error, id, disabled, checked, defaultChecked, onChange, ...props }, ref) => {
525
526
  const switchId = id != null ? id : `switch-${Math.random().toString(36).slice(2, 9)}`;
526
- const [internalChecked, setInternalChecked] = React3__default.default.useState(
527
+ const [internalChecked, setInternalChecked] = React13__default.default.useState(
527
528
  defaultChecked != null ? defaultChecked : false
528
529
  );
529
530
  const isControlled = checked !== void 0;
@@ -592,7 +593,815 @@ var Switch = React3__default.default.forwardRef(
592
593
  }
593
594
  );
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";
1119
+ var ToastContext = React13__default.default.createContext(null);
1120
+ var counter = 0;
1121
+ var genId = () => `toast-${++counter}`;
1122
+ var ToastProvider = ({ children }) => {
1123
+ const [toasts, setToasts] = React13__default.default.useState([]);
1124
+ const toast = React13__default.default.useCallback((input) => {
1125
+ const id = genId();
1126
+ setToasts((prev) => [...prev, { ...input, id }]);
1127
+ return id;
1128
+ }, []);
1129
+ const dismiss = React13__default.default.useCallback((id) => {
1130
+ setToasts((prev) => prev.filter((t) => t.id !== id));
1131
+ }, []);
1132
+ const dismissAll = React13__default.default.useCallback(() => {
1133
+ setToasts([]);
1134
+ }, []);
1135
+ return /* @__PURE__ */ jsxRuntime.jsx(ToastContext.Provider, { value: { toasts, toast, dismiss, dismissAll }, children });
1136
+ };
1137
+ var useToast = () => {
1138
+ const ctx = React13__default.default.useContext(ToastContext);
1139
+ if (!ctx) throw new Error("useToast must be used within a ToastProvider");
1140
+ return ctx;
1141
+ };
1142
+ var toastVariants = classVarianceAuthority.cva(
1143
+ "pointer-events-auto relative flex w-80 max-w-[calc(100vw-2rem)] items-start gap-3 overflow-hidden rounded-(--radius-lg) border p-4 pr-8 shadow-lg",
1144
+ {
1145
+ variants: {
1146
+ variant: {
1147
+ default: "border-(--color-neutral-200) bg-white text-(--color-neutral-800)",
1148
+ success: "border-green-200 bg-green-50 text-green-900",
1149
+ warning: "border-yellow-200 bg-yellow-50 text-yellow-900",
1150
+ destructive: "border-red-200 bg-red-50 text-red-900"
1151
+ }
1152
+ },
1153
+ defaultVariants: { variant: "default" }
1154
+ }
1155
+ );
1156
+ var positionClasses = {
1157
+ "top-left": "top-4 left-4 items-start",
1158
+ "top-center": "top-4 left-1/2 -translate-x-1/2 items-center",
1159
+ "top-right": "top-4 right-4 items-end",
1160
+ "bottom-left": "bottom-4 left-4 items-start",
1161
+ "bottom-center": "bottom-4 left-1/2 -translate-x-1/2 items-center",
1162
+ "bottom-right": "bottom-4 right-4 items-end"
1163
+ };
1164
+ var SingleToast = ({ toast, onDismiss, defaultDuration }) => {
1165
+ var _a, _b;
1166
+ const duration = (_a = toast.duration) != null ? _a : defaultDuration;
1167
+ React13__default.default.useEffect(() => {
1168
+ if (duration <= 0) return;
1169
+ const timer = setTimeout(() => onDismiss(toast.id), duration);
1170
+ return () => clearTimeout(timer);
1171
+ }, [duration, onDismiss, toast.id]);
1172
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1173
+ "div",
1174
+ {
1175
+ role: "status",
1176
+ "aria-live": "polite",
1177
+ className: toastVariants({ variant: (_b = toast.variant) != null ? _b : "default" }),
1178
+ children: [
1179
+ toast.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 shrink-0 [&>svg]:size-4", children: toast.icon }),
1180
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-1", children: [
1181
+ toast.title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold leading-none", children: toast.title }),
1182
+ toast.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs opacity-80", children: toast.description }),
1183
+ toast.action && /* @__PURE__ */ jsxRuntime.jsx(
1184
+ "button",
1185
+ {
1186
+ type: "button",
1187
+ onClick: () => {
1188
+ toast.action.onClick();
1189
+ onDismiss(toast.id);
1190
+ },
1191
+ className: "mt-1.5 text-xs font-medium underline underline-offset-2 hover:no-underline focus:outline-none",
1192
+ children: toast.action.label
1193
+ }
1194
+ )
1195
+ ] }),
1196
+ /* @__PURE__ */ jsxRuntime.jsx(
1197
+ "button",
1198
+ {
1199
+ type: "button",
1200
+ "aria-label": "Dismiss",
1201
+ onClick: () => onDismiss(toast.id),
1202
+ className: "absolute right-2 top-2 rounded opacity-50 transition-opacity hover:opacity-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-(--color-primary-500)",
1203
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1204
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18" }),
1205
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 6 12 12" })
1206
+ ] })
1207
+ }
1208
+ )
1209
+ ]
1210
+ }
1211
+ );
1212
+ };
1213
+ var Toaster = ({
1214
+ position = "bottom-right",
1215
+ defaultDuration = 4e3,
1216
+ className
1217
+ }) => {
1218
+ const { toasts, dismiss } = useToast();
1219
+ const [mounted, setMounted] = React13__default.default.useState(false);
1220
+ React13__default.default.useEffect(() => {
1221
+ setMounted(true);
1222
+ }, []);
1223
+ if (!mounted) return null;
1224
+ return reactDom.createPortal(
1225
+ /* @__PURE__ */ jsxRuntime.jsx(
1226
+ "div",
1227
+ {
1228
+ "aria-label": "Notifications",
1229
+ className: cn(
1230
+ "fixed z-[100] flex flex-col gap-2 pointer-events-none",
1231
+ positionClasses[position],
1232
+ className
1233
+ ),
1234
+ children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
1235
+ SingleToast,
1236
+ {
1237
+ toast: t,
1238
+ onDismiss: dismiss,
1239
+ defaultDuration
1240
+ },
1241
+ t.id
1242
+ ))
1243
+ }
1244
+ ),
1245
+ document.body
1246
+ );
1247
+ };
1248
+ Toaster.displayName = "Toaster";
1249
+ ToastProvider.displayName = "ToastProvider";
1250
+ var alertVariants = classVarianceAuthority.cva(
1251
+ "relative flex w-full gap-3 rounded-(--radius-lg) border p-4 text-sm",
1252
+ {
1253
+ variants: {
1254
+ variant: {
1255
+ default: "border-(--color-neutral-200) bg-(--color-neutral-50) text-(--color-neutral-700)",
1256
+ success: "border-green-200 bg-green-50 text-green-800",
1257
+ warning: "border-yellow-200 bg-yellow-50 text-yellow-800",
1258
+ destructive: "border-red-200 bg-red-50 text-red-800"
1259
+ }
1260
+ },
1261
+ defaultVariants: { variant: "default" }
1262
+ }
1263
+ );
1264
+ var Alert = ({
1265
+ variant,
1266
+ icon,
1267
+ onClose,
1268
+ className,
1269
+ children,
1270
+ ...props
1271
+ }) => {
1272
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1273
+ "div",
1274
+ {
1275
+ role: "alert",
1276
+ className: cn(alertVariants({ variant }), className),
1277
+ ...props,
1278
+ children: [
1279
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 shrink-0 [&>svg]:size-4", children: icon }),
1280
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children }),
1281
+ onClose && /* @__PURE__ */ jsxRuntime.jsx(
1282
+ "button",
1283
+ {
1284
+ type: "button",
1285
+ "aria-label": "Dismiss",
1286
+ onClick: onClose,
1287
+ className: "ml-auto shrink-0 self-start rounded opacity-60 transition-opacity hover:opacity-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-(--color-primary-500)",
1288
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1289
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18" }),
1290
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 6 12 12" })
1291
+ ] })
1292
+ }
1293
+ )
1294
+ ]
1295
+ }
1296
+ );
1297
+ };
1298
+ Alert.displayName = "Alert";
1299
+ var AlertTitle = ({
1300
+ className,
1301
+ children,
1302
+ ...props
1303
+ }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("font-semibold leading-none tracking-tight", className), ...props, children });
1304
+ AlertTitle.displayName = "AlertTitle";
1305
+ var AlertDescription = ({
1306
+ className,
1307
+ children,
1308
+ ...props
1309
+ }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-1 text-[0.8rem] opacity-80", className), ...props, children });
1310
+ AlertDescription.displayName = "AlertDescription";
1311
+ var progressVariants = classVarianceAuthority.cva(
1312
+ "w-full overflow-hidden rounded-full bg-(--color-neutral-200)",
1313
+ {
1314
+ variants: {
1315
+ size: {
1316
+ sm: "h-1",
1317
+ md: "h-2",
1318
+ lg: "h-3"
1319
+ }
1320
+ },
1321
+ defaultVariants: { size: "md" }
1322
+ }
1323
+ );
1324
+ var Progress = ({
1325
+ value,
1326
+ size,
1327
+ label,
1328
+ showLabel = false,
1329
+ className,
1330
+ ...props
1331
+ }) => {
1332
+ const isIndeterminate = value === void 0 || value === null;
1333
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
1334
+ (label || showLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1.5 flex items-center justify-between text-xs text-(--color-neutral-600)", children: [
1335
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
1336
+ showLabel && !isIndeterminate && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto font-medium", children: [
1337
+ Math.round(value),
1338
+ "%"
1339
+ ] })
1340
+ ] }),
1341
+ /* @__PURE__ */ jsxRuntime.jsx(
1342
+ "div",
1343
+ {
1344
+ role: "progressbar",
1345
+ "aria-valuemin": 0,
1346
+ "aria-valuemax": 100,
1347
+ "aria-valuenow": isIndeterminate ? void 0 : value,
1348
+ className: cn(progressVariants({ size }), className),
1349
+ ...props,
1350
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1351
+ "div",
1352
+ {
1353
+ className: cn(
1354
+ "h-full rounded-full bg-(--color-primary-500) transition-all duration-300 ease-in-out",
1355
+ isIndeterminate && "w-1/3 animate-[indeterminate_1.5s_ease-in-out_infinite]"
1356
+ ),
1357
+ style: isIndeterminate ? void 0 : { width: `${Math.min(100, Math.max(0, value))}%` }
1358
+ }
1359
+ )
1360
+ }
1361
+ )
1362
+ ] });
1363
+ };
1364
+ Progress.displayName = "Progress";
1365
+ var skeletonVariants = classVarianceAuthority.cva(
1366
+ "animate-pulse bg-(--color-neutral-200)",
1367
+ {
1368
+ variants: {
1369
+ variant: {
1370
+ text: "h-4 w-full rounded",
1371
+ circle: "rounded-full",
1372
+ rect: "rounded-(--radius-md)"
1373
+ }
1374
+ },
1375
+ defaultVariants: { variant: "rect" }
1376
+ }
1377
+ );
1378
+ var Skeleton = ({
1379
+ variant,
1380
+ width,
1381
+ height,
1382
+ className,
1383
+ style,
1384
+ ...props
1385
+ }) => {
1386
+ return /* @__PURE__ */ jsxRuntime.jsx(
1387
+ "div",
1388
+ {
1389
+ "aria-hidden": "true",
1390
+ className: cn(skeletonVariants({ variant }), className),
1391
+ style: {
1392
+ width: typeof width === "number" ? `${width}px` : width,
1393
+ height: typeof height === "number" ? `${height}px` : height,
1394
+ ...style
1395
+ },
1396
+ ...props
1397
+ }
1398
+ );
1399
+ };
1400
+ Skeleton.displayName = "Skeleton";
595
1401
 
1402
+ exports.Alert = Alert;
1403
+ exports.AlertDescription = AlertDescription;
1404
+ exports.AlertTitle = AlertTitle;
596
1405
  exports.Avatar = Avatar;
597
1406
  exports.Badge = Badge;
598
1407
  exports.Button = Button;
@@ -603,23 +1412,48 @@ exports.CardFooter = CardFooter;
603
1412
  exports.CardHeader = CardHeader;
604
1413
  exports.CardTitle = CardTitle;
605
1414
  exports.Checkbox = Checkbox;
1415
+ exports.Drawer = Drawer;
1416
+ exports.DrawerBody = DrawerBody;
1417
+ exports.DrawerDescription = DrawerDescription;
1418
+ exports.DrawerFooter = DrawerFooter;
1419
+ exports.DrawerHeader = DrawerHeader;
1420
+ exports.DrawerTitle = DrawerTitle;
606
1421
  exports.Input = Input;
1422
+ exports.Modal = Modal;
1423
+ exports.ModalBody = ModalBody;
1424
+ exports.ModalDescription = ModalDescription;
1425
+ exports.ModalFooter = ModalFooter;
1426
+ exports.ModalHeader = ModalHeader;
1427
+ exports.ModalTitle = ModalTitle;
1428
+ exports.Popover = Popover;
1429
+ exports.Progress = Progress;
607
1430
  exports.RadioGroup = RadioGroup;
608
1431
  exports.Select = Select;
609
1432
  exports.Separator = Separator;
1433
+ exports.Skeleton = Skeleton;
610
1434
  exports.Spinner = Spinner;
611
1435
  exports.Switch = Switch;
1436
+ exports.ToastProvider = ToastProvider;
1437
+ exports.Toaster = Toaster;
1438
+ exports.Tooltip = Tooltip;
1439
+ exports.alertVariants = alertVariants;
612
1440
  exports.avatarVariants = avatarVariants;
613
1441
  exports.badgeVariants = badgeVariants;
614
1442
  exports.buttonVariants = buttonVariants;
615
1443
  exports.cardVariants = cardVariants;
616
1444
  exports.cn = cn;
617
1445
  exports.colors = colors;
1446
+ exports.drawerVariants = drawerVariants;
618
1447
  exports.fontSize = fontSize;
619
1448
  exports.inputVariants = inputVariants;
1449
+ exports.modalVariants = modalVariants;
1450
+ exports.progressVariants = progressVariants;
620
1451
  exports.radius = radius;
621
1452
  exports.selectVariants = selectVariants;
622
1453
  exports.separatorVariants = separatorVariants;
1454
+ exports.skeletonVariants = skeletonVariants;
623
1455
  exports.spinnerVariants = spinnerVariants;
1456
+ exports.toastVariants = toastVariants;
1457
+ exports.useToast = useToast;
624
1458
  //# sourceMappingURL=index.js.map
625
1459
  //# sourceMappingURL=index.js.map