@tonyarbor/components 0.1.0 → 0.2.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
@@ -32,7 +32,11 @@ var src_exports = {};
32
32
  __export(src_exports, {
33
33
  Button: () => Button,
34
34
  Card: () => Card,
35
+ Checkbox: () => Checkbox,
36
+ Combobox: () => Combobox,
35
37
  Input: () => Input,
38
+ NumericInput: () => NumericInput,
39
+ Radio: () => Radio,
36
40
  Tag: () => Tag
37
41
  });
38
42
  module.exports = __toCommonJS(src_exports);
@@ -500,11 +504,842 @@ var Tag = React4.forwardRef(
500
504
  }
501
505
  );
502
506
  Tag.displayName = "Tag";
507
+
508
+ // src/Combobox/Combobox.tsx
509
+ var React5 = __toESM(require("react"));
510
+ var import_clsx5 = require("clsx");
511
+ var import_lucide_react = require("lucide-react");
512
+ var import_jsx_runtime5 = require("react/jsx-runtime");
513
+ var comboboxStyles = {
514
+ base: {
515
+ width: "100%",
516
+ height: "36px",
517
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
518
+ backgroundColor: "#ffffff",
519
+ borderRadius: "8px",
520
+ transition: "all 0.2s ease-in-out",
521
+ outline: "none",
522
+ fontSize: "13px",
523
+ padding: "8px",
524
+ paddingRight: "32px",
525
+ margin: "0",
526
+ display: "flex",
527
+ alignItems: "center",
528
+ cursor: "pointer",
529
+ position: "relative"
530
+ },
531
+ states: {
532
+ default: {
533
+ border: "1px solid #d1d1d1",
534
+ // grey-300
535
+ color: "#2f2f2f"
536
+ // grey-900
537
+ },
538
+ defaultFocus: {
539
+ borderColor: "#3cad51",
540
+ // brand-500
541
+ outline: "3px solid rgba(60, 173, 81, 0.2)"
542
+ },
543
+ error: {
544
+ border: "1px solid #c93232",
545
+ // destructive-500
546
+ color: "#2f2f2f"
547
+ },
548
+ errorFocus: {
549
+ borderColor: "#c93232",
550
+ outline: "3px solid rgba(201, 50, 50, 0.2)"
551
+ },
552
+ success: {
553
+ border: "1px solid #16a33d",
554
+ // success-500
555
+ color: "#2f2f2f"
556
+ },
557
+ successFocus: {
558
+ borderColor: "#16a33d",
559
+ outline: "3px solid rgba(22, 163, 61, 0.2)"
560
+ },
561
+ disabled: {
562
+ backgroundColor: "#f8f8f8",
563
+ // grey-050
564
+ borderColor: "#efefef",
565
+ // grey-100
566
+ color: "#7e7e7e",
567
+ // grey-500
568
+ cursor: "not-allowed"
569
+ }
570
+ }
571
+ };
572
+ var labelStyles2 = {
573
+ display: "block",
574
+ fontSize: "13px",
575
+ fontWeight: "600",
576
+ color: "#2f2f2f",
577
+ marginBottom: "4px",
578
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
579
+ };
580
+ var helperTextStyles2 = {
581
+ fontSize: "13px",
582
+ margin: "0",
583
+ marginTop: "2px",
584
+ color: "#595959",
585
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
586
+ lineHeight: "1.4"
587
+ };
588
+ var errorTextStyles2 = {
589
+ ...helperTextStyles2,
590
+ color: "#a62323",
591
+ // destructive-600
592
+ display: "flex",
593
+ alignItems: "center",
594
+ gap: "4px"
595
+ };
596
+ var dropdownStyles = {
597
+ position: "absolute",
598
+ top: "calc(100% + 4px)",
599
+ left: "0",
600
+ right: "0",
601
+ backgroundColor: "#ffffff",
602
+ border: "1px solid #d1d1d1",
603
+ borderRadius: "8px",
604
+ maxHeight: "200px",
605
+ overflowY: "auto",
606
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.1)",
607
+ zIndex: 1e3
608
+ };
609
+ var optionStyles = {
610
+ padding: "8px 12px",
611
+ fontSize: "13px",
612
+ cursor: "pointer",
613
+ display: "flex",
614
+ alignItems: "center",
615
+ justifyContent: "space-between",
616
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
617
+ color: "#2f2f2f"
618
+ // grey-900
619
+ };
620
+ var Combobox = React5.forwardRef(
621
+ ({
622
+ label,
623
+ placeholder = "default-text",
624
+ options,
625
+ value,
626
+ onChange,
627
+ state = "default",
628
+ error,
629
+ helperText,
630
+ disabled = false,
631
+ className,
632
+ style,
633
+ "data-testid": dataTestId
634
+ }, ref) => {
635
+ const [isOpen, setIsOpen] = React5.useState(false);
636
+ const [searchQuery, setSearchQuery] = React5.useState("");
637
+ const [isFocused, setIsFocused] = React5.useState(false);
638
+ const inputRef = React5.useRef(null);
639
+ const dropdownRef = React5.useRef(null);
640
+ const wrapperRef = React5.useRef(null);
641
+ const comboboxId = React5.useId();
642
+ const helperTextId = React5.useId();
643
+ const errorId = React5.useId();
644
+ const selectedOption = options.find((opt) => opt.value === value);
645
+ const filteredOptions = React5.useMemo(() => {
646
+ if (!searchQuery) return options;
647
+ return options.filter(
648
+ (option) => option.label.toLowerCase().includes(searchQuery.toLowerCase())
649
+ );
650
+ }, [options, searchQuery]);
651
+ React5.useEffect(() => {
652
+ const handleClickOutside = (event) => {
653
+ if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
654
+ setIsOpen(false);
655
+ setSearchQuery("");
656
+ }
657
+ };
658
+ document.addEventListener("mousedown", handleClickOutside);
659
+ return () => document.removeEventListener("mousedown", handleClickOutside);
660
+ }, []);
661
+ const handleInputChange = (e) => {
662
+ setSearchQuery(e.target.value);
663
+ if (!isOpen) setIsOpen(true);
664
+ };
665
+ const handleSelectOption = (optionValue) => {
666
+ onChange?.(optionValue);
667
+ setIsOpen(false);
668
+ setSearchQuery("");
669
+ inputRef.current?.blur();
670
+ };
671
+ const handleClear = (e) => {
672
+ e.stopPropagation();
673
+ onChange?.(void 0);
674
+ setSearchQuery("");
675
+ inputRef.current?.focus();
676
+ };
677
+ const handleInputFocus = () => {
678
+ setIsFocused(true);
679
+ if (!disabled) setIsOpen(true);
680
+ };
681
+ const handleInputBlur = () => {
682
+ setIsFocused(false);
683
+ setTimeout(() => {
684
+ if (!wrapperRef.current?.contains(document.activeElement)) {
685
+ setSearchQuery("");
686
+ }
687
+ }, 200);
688
+ };
689
+ const currentState = error ? "error" : state;
690
+ const stateStyles = comboboxStyles.states[currentState];
691
+ const focusStyles = currentState === "error" ? comboboxStyles.states.errorFocus : currentState === "success" ? comboboxStyles.states.successFocus : comboboxStyles.states.defaultFocus;
692
+ const inputWrapperStyle = {
693
+ ...comboboxStyles.base,
694
+ ...stateStyles,
695
+ ...isFocused && !disabled && focusStyles,
696
+ ...disabled && comboboxStyles.states.disabled
697
+ };
698
+ const displayValue = selectedOption ? selectedOption.label : "";
699
+ const showPlaceholder = !selectedOption && !searchQuery && !isFocused;
700
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: (0, import_clsx5.clsx)("arbor-combobox-wrapper", className), style, ref: wrapperRef, "data-testid": dataTestId, children: [
701
+ label && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { htmlFor: comboboxId, style: labelStyles2, children: label }),
702
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { position: "relative" }, ref, children: [
703
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: inputWrapperStyle, children: [
704
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
705
+ "input",
706
+ {
707
+ ref: inputRef,
708
+ id: comboboxId,
709
+ type: "text",
710
+ value: searchQuery || displayValue,
711
+ onChange: handleInputChange,
712
+ onFocus: handleInputFocus,
713
+ onBlur: handleInputBlur,
714
+ placeholder: showPlaceholder ? placeholder : "",
715
+ disabled,
716
+ "aria-invalid": error ? "true" : "false",
717
+ "aria-describedby": error ? errorId : helperText ? helperTextId : void 0,
718
+ "aria-expanded": isOpen,
719
+ "aria-autocomplete": "list",
720
+ role: "combobox",
721
+ style: {
722
+ border: "none",
723
+ outline: "none",
724
+ background: "transparent",
725
+ flex: 1,
726
+ fontSize: "13px",
727
+ padding: 0,
728
+ margin: 0,
729
+ color: showPlaceholder ? "#7e7e7e" : "#2f2f2f",
730
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
731
+ }
732
+ }
733
+ ),
734
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "4px", position: "absolute", right: "8px" }, children: [
735
+ selectedOption && !disabled && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
736
+ "button",
737
+ {
738
+ type: "button",
739
+ onClick: handleClear,
740
+ style: {
741
+ border: "none",
742
+ background: "transparent",
743
+ padding: "2px",
744
+ cursor: "pointer",
745
+ display: "flex",
746
+ alignItems: "center",
747
+ color: "#7e7e7e"
748
+ },
749
+ "aria-label": "Clear selection",
750
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.X, { size: 16 })
751
+ }
752
+ ),
753
+ currentState === "success" && !isOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Check, { size: 16, color: "#16a33d" }),
754
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
755
+ import_lucide_react.ChevronDown,
756
+ {
757
+ size: 16,
758
+ color: "#7e7e7e",
759
+ style: {
760
+ transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
761
+ transition: "transform 0.2s"
762
+ }
763
+ }
764
+ )
765
+ ] })
766
+ ] }),
767
+ isOpen && !disabled && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: dropdownRef, style: dropdownStyles, children: filteredOptions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { ...optionStyles, color: "#7e7e7e", cursor: "default" }, children: "No options found" }) : filteredOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
768
+ "div",
769
+ {
770
+ onClick: () => handleSelectOption(option.value),
771
+ onMouseDown: (e) => e.preventDefault(),
772
+ style: {
773
+ ...optionStyles,
774
+ backgroundColor: option.value === value ? "#f8f8f8" : "transparent"
775
+ },
776
+ onMouseEnter: (e) => {
777
+ e.currentTarget.style.backgroundColor = "#f8f8f8";
778
+ },
779
+ onMouseLeave: (e) => {
780
+ e.currentTarget.style.backgroundColor = option.value === value ? "#f8f8f8" : "transparent";
781
+ },
782
+ children: [
783
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: option.label }),
784
+ option.value === value && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Check, { size: 16, color: "#16a33d" })
785
+ ]
786
+ },
787
+ option.value
788
+ )) })
789
+ ] }),
790
+ error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { id: errorId, style: errorTextStyles2, role: "alert", children: error }),
791
+ !error && helperText && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { id: helperTextId, style: helperTextStyles2, children: helperText })
792
+ ] });
793
+ }
794
+ );
795
+ Combobox.displayName = "Combobox";
796
+
797
+ // src/NumericInput/NumericInput.tsx
798
+ var React6 = __toESM(require("react"));
799
+ var import_clsx6 = require("clsx");
800
+ var import_jsx_runtime6 = require("react/jsx-runtime");
801
+ var labelStyles3 = {
802
+ display: "block",
803
+ fontSize: "13px",
804
+ fontWeight: "600",
805
+ color: "#2f2f2f",
806
+ marginBottom: "4px",
807
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
808
+ };
809
+ var helperTextStyles3 = {
810
+ fontSize: "13px",
811
+ margin: "0",
812
+ marginTop: "2px",
813
+ color: "#595959",
814
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
815
+ lineHeight: "1.4"
816
+ };
817
+ var errorTextStyles3 = {
818
+ ...helperTextStyles3,
819
+ color: "#a62323",
820
+ // destructive-600
821
+ display: "flex",
822
+ alignItems: "center",
823
+ gap: "4px"
824
+ };
825
+ var containerStyles = {
826
+ base: {
827
+ display: "flex",
828
+ alignItems: "center",
829
+ height: "46px",
830
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
831
+ backgroundColor: "#ffffff",
832
+ borderRadius: "8px",
833
+ transition: "all 0.2s ease-in-out",
834
+ overflow: "hidden"
835
+ },
836
+ states: {
837
+ default: {
838
+ border: "1px solid #d1d1d1"
839
+ // grey-300
840
+ },
841
+ defaultFocus: {
842
+ borderColor: "#3cad51",
843
+ // brand-500
844
+ outline: "3px solid rgba(60, 173, 81, 0.2)"
845
+ },
846
+ error: {
847
+ border: "1px solid #c93232"
848
+ // destructive-500
849
+ },
850
+ errorFocus: {
851
+ borderColor: "#c93232",
852
+ outline: "3px solid rgba(201, 50, 50, 0.2)"
853
+ },
854
+ success: {
855
+ border: "1px solid #16a33d"
856
+ // success-500
857
+ },
858
+ successFocus: {
859
+ borderColor: "#16a33d",
860
+ outline: "3px solid rgba(22, 163, 61, 0.2)"
861
+ },
862
+ disabled: {
863
+ backgroundColor: "#f8f8f8",
864
+ // grey-050
865
+ borderColor: "#efefef",
866
+ // grey-100
867
+ cursor: "not-allowed"
868
+ }
869
+ }
870
+ };
871
+ var buttonStyles2 = {
872
+ width: "46px",
873
+ height: "100%",
874
+ border: "none",
875
+ background: "transparent",
876
+ cursor: "pointer",
877
+ fontSize: "16px",
878
+ color: "#2f2f2f",
879
+ display: "flex",
880
+ alignItems: "center",
881
+ justifyContent: "center",
882
+ transition: "background-color 0.2s",
883
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
884
+ userSelect: "none"
885
+ };
886
+ var inputStyles2 = {
887
+ flex: 1,
888
+ border: "none",
889
+ outline: "none",
890
+ background: "transparent",
891
+ textAlign: "center",
892
+ fontSize: "13px",
893
+ color: "#2f2f2f",
894
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
895
+ padding: "0 8px",
896
+ appearance: "textfield"
897
+ };
898
+ var NumericInput = React6.forwardRef(
899
+ ({
900
+ label,
901
+ value,
902
+ onChange,
903
+ min,
904
+ max,
905
+ step = 1,
906
+ state = "default",
907
+ error,
908
+ helperText,
909
+ disabled = false,
910
+ className,
911
+ style,
912
+ "data-testid": dataTestId
913
+ }, ref) => {
914
+ const [isFocused, setIsFocused] = React6.useState(false);
915
+ const inputRef = React6.useRef(null);
916
+ const inputId = React6.useId();
917
+ const helperTextId = React6.useId();
918
+ const errorId = React6.useId();
919
+ const clampValue = (val) => {
920
+ let clamped = val;
921
+ if (min !== void 0 && clamped < min) clamped = min;
922
+ if (max !== void 0 && clamped > max) clamped = max;
923
+ return clamped;
924
+ };
925
+ const handleIncrement = () => {
926
+ if (disabled) return;
927
+ const currentValue = value ?? 0;
928
+ const newValue = currentValue + step;
929
+ const clampedValue = clampValue(newValue);
930
+ if (clampedValue !== currentValue) {
931
+ onChange?.(clampedValue);
932
+ }
933
+ };
934
+ const handleDecrement = () => {
935
+ if (disabled) return;
936
+ const currentValue = value ?? 0;
937
+ const newValue = currentValue - step;
938
+ const clampedValue = clampValue(newValue);
939
+ if (clampedValue !== currentValue) {
940
+ onChange?.(clampedValue);
941
+ }
942
+ };
943
+ const handleInputChange = (e) => {
944
+ const inputValue = e.target.value;
945
+ if (inputValue === "" || inputValue === "-") {
946
+ onChange?.(void 0);
947
+ return;
948
+ }
949
+ const numValue = parseFloat(inputValue);
950
+ if (!isNaN(numValue)) {
951
+ const clampedValue = clampValue(numValue);
952
+ onChange?.(clampedValue);
953
+ }
954
+ };
955
+ const handleKeyDown = (e) => {
956
+ const allowedKeys = ["Backspace", "Delete", "Tab", "Escape", "Enter", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "-", "."];
957
+ if (allowedKeys.includes(e.key)) {
958
+ if (e.key === "ArrowUp") {
959
+ e.preventDefault();
960
+ handleIncrement();
961
+ } else if (e.key === "ArrowDown") {
962
+ e.preventDefault();
963
+ handleDecrement();
964
+ }
965
+ return;
966
+ }
967
+ if (!/^[0-9]$/.test(e.key)) {
968
+ e.preventDefault();
969
+ }
970
+ };
971
+ const currentState = error ? "error" : state;
972
+ const stateStyles = containerStyles.states[currentState];
973
+ const focusStyles = currentState === "error" ? containerStyles.states.errorFocus : currentState === "success" ? containerStyles.states.successFocus : containerStyles.states.defaultFocus;
974
+ const containerStyle = {
975
+ ...containerStyles.base,
976
+ ...stateStyles,
977
+ ...isFocused && !disabled && focusStyles,
978
+ ...disabled && containerStyles.states.disabled
979
+ };
980
+ const isDecrementDisabled = disabled || min !== void 0 && value !== void 0 && value <= min;
981
+ const isIncrementDisabled = disabled || max !== void 0 && value !== void 0 && value >= max;
982
+ const getButtonStyle = (isDisabled) => {
983
+ const baseStyle = {
984
+ ...buttonStyles2,
985
+ cursor: isDisabled ? "not-allowed" : "pointer",
986
+ color: isDisabled ? "#7e7e7e" : "#2f2f2f"
987
+ };
988
+ if (currentState === "success" && !isDisabled) {
989
+ return {
990
+ ...baseStyle,
991
+ color: "#16a33d",
992
+ // success-500
993
+ border: "2px solid #16a33d",
994
+ borderRadius: "50%",
995
+ width: "32px",
996
+ height: "32px"
997
+ };
998
+ }
999
+ return baseStyle;
1000
+ };
1001
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: (0, import_clsx6.clsx)("arbor-numeric-input-wrapper", className), style, ref, "data-testid": dataTestId, children: [
1002
+ label && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("label", { htmlFor: inputId, style: labelStyles3, children: label }),
1003
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: containerStyle, children: [
1004
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1005
+ "button",
1006
+ {
1007
+ type: "button",
1008
+ onClick: handleDecrement,
1009
+ disabled: isDecrementDisabled,
1010
+ style: getButtonStyle(isDecrementDisabled),
1011
+ onMouseEnter: (e) => {
1012
+ if (!isDecrementDisabled) {
1013
+ e.currentTarget.style.backgroundColor = "#f8f8f8";
1014
+ e.currentTarget.style.borderRadius = "99px";
1015
+ }
1016
+ },
1017
+ onMouseLeave: (e) => {
1018
+ e.currentTarget.style.backgroundColor = "transparent";
1019
+ e.currentTarget.style.borderRadius = currentState === "success" ? "50%" : "0";
1020
+ },
1021
+ "aria-label": "Decrement",
1022
+ children: "\u2212"
1023
+ }
1024
+ ),
1025
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1026
+ "input",
1027
+ {
1028
+ ref: inputRef,
1029
+ id: inputId,
1030
+ type: "text",
1031
+ inputMode: "numeric",
1032
+ value: value !== void 0 ? value : "",
1033
+ onChange: handleInputChange,
1034
+ onKeyDown: handleKeyDown,
1035
+ onFocus: () => setIsFocused(true),
1036
+ onBlur: () => setIsFocused(false),
1037
+ disabled,
1038
+ "aria-invalid": error ? "true" : "false",
1039
+ "aria-describedby": error ? errorId : helperText ? helperTextId : void 0,
1040
+ style: {
1041
+ ...inputStyles2,
1042
+ color: disabled ? "#7e7e7e" : "#2f2f2f",
1043
+ cursor: disabled ? "not-allowed" : "text"
1044
+ }
1045
+ }
1046
+ ),
1047
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1048
+ "button",
1049
+ {
1050
+ type: "button",
1051
+ onClick: handleIncrement,
1052
+ disabled: isIncrementDisabled,
1053
+ style: getButtonStyle(isIncrementDisabled),
1054
+ onMouseEnter: (e) => {
1055
+ if (!isIncrementDisabled) {
1056
+ e.currentTarget.style.backgroundColor = "#f8f8f8";
1057
+ e.currentTarget.style.borderRadius = "99px";
1058
+ }
1059
+ },
1060
+ onMouseLeave: (e) => {
1061
+ e.currentTarget.style.backgroundColor = "transparent";
1062
+ e.currentTarget.style.borderRadius = currentState === "success" ? "50%" : "0";
1063
+ },
1064
+ "aria-label": "Increment",
1065
+ children: "+"
1066
+ }
1067
+ )
1068
+ ] }),
1069
+ error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { id: errorId, style: errorTextStyles3, children: error }),
1070
+ helperText && !error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { id: helperTextId, style: helperTextStyles3, children: helperText })
1071
+ ] });
1072
+ }
1073
+ );
1074
+ NumericInput.displayName = "NumericInput";
1075
+
1076
+ // src/Checkbox/Checkbox.tsx
1077
+ var React7 = __toESM(require("react"));
1078
+ var import_clsx7 = require("clsx");
1079
+ var import_lucide_react2 = require("lucide-react");
1080
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1081
+ var checkboxStyles = {
1082
+ width: "20px",
1083
+ height: "20px",
1084
+ border: "2px solid #d1d1d1",
1085
+ // grey-300
1086
+ borderRadius: "4px",
1087
+ display: "flex",
1088
+ alignItems: "center",
1089
+ justifyContent: "center",
1090
+ cursor: "pointer",
1091
+ transition: "all 0.2s ease-in-out",
1092
+ flexShrink: 0,
1093
+ backgroundColor: "#ffffff"
1094
+ };
1095
+ var checkedStyles = {
1096
+ backgroundColor: "#3cad51",
1097
+ // brand-500
1098
+ borderColor: "#3cad51"
1099
+ };
1100
+ var labelStyles4 = {
1101
+ fontSize: "13px",
1102
+ color: "#2f2f2f",
1103
+ cursor: "pointer",
1104
+ userSelect: "none",
1105
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
1106
+ };
1107
+ var wrapperStyles = {
1108
+ display: "flex",
1109
+ alignItems: "center",
1110
+ gap: "8px"
1111
+ };
1112
+ var Checkbox = React7.forwardRef(
1113
+ ({
1114
+ label,
1115
+ checked = false,
1116
+ onChange,
1117
+ disabled = false,
1118
+ className,
1119
+ style,
1120
+ "data-testid": dataTestId,
1121
+ name,
1122
+ value
1123
+ }, ref) => {
1124
+ const [isFocused, setIsFocused] = React7.useState(false);
1125
+ const checkboxId = React7.useId();
1126
+ const handleChange = (e) => {
1127
+ if (!disabled) {
1128
+ onChange?.(e.target.checked);
1129
+ }
1130
+ };
1131
+ const boxStyle = {
1132
+ ...checkboxStyles,
1133
+ ...checked && !disabled && checkedStyles,
1134
+ ...disabled && !checked && { backgroundColor: "#f8f8f8", borderColor: "#efefef" },
1135
+ ...disabled && checked && { backgroundColor: "#7e7e7e", borderColor: "#7e7e7e" },
1136
+ ...isFocused && !disabled && { borderColor: "#3cad51", outline: "2px solid rgba(60, 173, 81, 0.2)" }
1137
+ };
1138
+ const checkmarkColor = disabled ? "#d1d1d1" : "#ffffff";
1139
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1140
+ "div",
1141
+ {
1142
+ className: (0, import_clsx7.clsx)("arbor-checkbox-wrapper", className),
1143
+ style: { ...wrapperStyles, ...style },
1144
+ "data-testid": dataTestId,
1145
+ children: [
1146
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1147
+ "input",
1148
+ {
1149
+ ref,
1150
+ id: checkboxId,
1151
+ type: "checkbox",
1152
+ checked,
1153
+ onChange: handleChange,
1154
+ onFocus: () => setIsFocused(true),
1155
+ onBlur: () => setIsFocused(false),
1156
+ disabled,
1157
+ name,
1158
+ value,
1159
+ style: {
1160
+ position: "absolute",
1161
+ opacity: 0,
1162
+ width: 0,
1163
+ height: 0
1164
+ },
1165
+ "aria-checked": checked
1166
+ }
1167
+ ),
1168
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1169
+ "label",
1170
+ {
1171
+ htmlFor: checkboxId,
1172
+ style: {
1173
+ display: "flex",
1174
+ alignItems: "center",
1175
+ gap: "8px",
1176
+ cursor: disabled ? "not-allowed" : "pointer"
1177
+ },
1178
+ children: [
1179
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: boxStyle, children: checked && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.Check, { size: 14, color: checkmarkColor, strokeWidth: 3 }) }),
1180
+ label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1181
+ "span",
1182
+ {
1183
+ style: {
1184
+ ...labelStyles4,
1185
+ color: disabled ? "#7e7e7e" : "#2f2f2f",
1186
+ cursor: disabled ? "not-allowed" : "pointer"
1187
+ },
1188
+ children: label
1189
+ }
1190
+ )
1191
+ ]
1192
+ }
1193
+ )
1194
+ ]
1195
+ }
1196
+ );
1197
+ }
1198
+ );
1199
+ Checkbox.displayName = "Checkbox";
1200
+
1201
+ // src/Radio/Radio.tsx
1202
+ var React8 = __toESM(require("react"));
1203
+ var import_clsx8 = require("clsx");
1204
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1205
+ var radioStyles = {
1206
+ width: "20px",
1207
+ height: "20px",
1208
+ border: "2px solid #d1d1d1",
1209
+ // grey-300
1210
+ borderRadius: "50%",
1211
+ display: "flex",
1212
+ alignItems: "center",
1213
+ justifyContent: "center",
1214
+ cursor: "pointer",
1215
+ transition: "all 0.2s ease-in-out",
1216
+ flexShrink: 0,
1217
+ backgroundColor: "#ffffff"
1218
+ };
1219
+ var checkedStyles2 = {
1220
+ borderColor: "#3cad51"
1221
+ // brand-500
1222
+ };
1223
+ var innerDotStyles = {
1224
+ width: "10px",
1225
+ height: "10px",
1226
+ borderRadius: "50%",
1227
+ backgroundColor: "#3cad51",
1228
+ // brand-500
1229
+ transition: "all 0.2s ease-in-out"
1230
+ };
1231
+ var labelStyles5 = {
1232
+ fontSize: "13px",
1233
+ color: "#2f2f2f",
1234
+ cursor: "pointer",
1235
+ userSelect: "none",
1236
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
1237
+ };
1238
+ var wrapperStyles2 = {
1239
+ display: "flex",
1240
+ alignItems: "center",
1241
+ gap: "8px"
1242
+ };
1243
+ var Radio = React8.forwardRef(
1244
+ ({
1245
+ label,
1246
+ checked = false,
1247
+ onChange,
1248
+ disabled = false,
1249
+ className,
1250
+ style,
1251
+ "data-testid": dataTestId,
1252
+ name,
1253
+ value
1254
+ }, ref) => {
1255
+ const [isFocused, setIsFocused] = React8.useState(false);
1256
+ const radioId = React8.useId();
1257
+ const handleChange = (e) => {
1258
+ if (!disabled) {
1259
+ onChange?.(e.target.checked);
1260
+ }
1261
+ };
1262
+ const circleStyle = {
1263
+ ...radioStyles,
1264
+ ...checked && !disabled && checkedStyles2,
1265
+ ...disabled && !checked && { backgroundColor: "#f8f8f8", borderColor: "#efefef" },
1266
+ ...disabled && checked && { borderColor: "#7e7e7e" },
1267
+ ...isFocused && !disabled && { borderColor: "#3cad51", outline: "2px solid rgba(60, 173, 81, 0.2)" }
1268
+ };
1269
+ const dotStyle = {
1270
+ ...innerDotStyles,
1271
+ backgroundColor: disabled ? "#7e7e7e" : "#3cad51"
1272
+ };
1273
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1274
+ "div",
1275
+ {
1276
+ className: (0, import_clsx8.clsx)("arbor-radio-wrapper", className),
1277
+ style: { ...wrapperStyles2, ...style },
1278
+ "data-testid": dataTestId,
1279
+ children: [
1280
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1281
+ "input",
1282
+ {
1283
+ ref,
1284
+ id: radioId,
1285
+ type: "radio",
1286
+ checked,
1287
+ onChange: handleChange,
1288
+ onFocus: () => setIsFocused(true),
1289
+ onBlur: () => setIsFocused(false),
1290
+ disabled,
1291
+ name,
1292
+ value,
1293
+ style: {
1294
+ position: "absolute",
1295
+ opacity: 0,
1296
+ width: 0,
1297
+ height: 0
1298
+ },
1299
+ "aria-checked": checked
1300
+ }
1301
+ ),
1302
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1303
+ "label",
1304
+ {
1305
+ htmlFor: radioId,
1306
+ style: {
1307
+ display: "flex",
1308
+ alignItems: "center",
1309
+ gap: "8px",
1310
+ cursor: disabled ? "not-allowed" : "pointer"
1311
+ },
1312
+ children: [
1313
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: circleStyle, children: checked && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: dotStyle }) }),
1314
+ label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1315
+ "span",
1316
+ {
1317
+ style: {
1318
+ ...labelStyles5,
1319
+ color: disabled ? "#7e7e7e" : "#2f2f2f",
1320
+ cursor: disabled ? "not-allowed" : "pointer"
1321
+ },
1322
+ children: label
1323
+ }
1324
+ )
1325
+ ]
1326
+ }
1327
+ )
1328
+ ]
1329
+ }
1330
+ );
1331
+ }
1332
+ );
1333
+ Radio.displayName = "Radio";
503
1334
  // Annotate the CommonJS export names for ESM import in node:
504
1335
  0 && (module.exports = {
505
1336
  Button,
506
1337
  Card,
1338
+ Checkbox,
1339
+ Combobox,
507
1340
  Input,
1341
+ NumericInput,
1342
+ Radio,
508
1343
  Tag
509
1344
  });
510
1345
  //# sourceMappingURL=index.js.map