@chekinapp/ui 0.0.67 → 0.0.69

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.cjs CHANGED
@@ -77,6 +77,11 @@ __export(index_exports, {
77
77
  CopyString: () => CopyString,
78
78
  CustomCheckboxDropdownGroup: () => CustomCheckboxDropdownGroup,
79
79
  DEVICE_BREAKPOINTS: () => DEVICE_BREAKPOINTS,
80
+ DashboardCreatableMultiSelect: () => DashboardCreatableMultiSelect,
81
+ DashboardInfiniteScrollSelect: () => DashboardInfiniteScrollSelect,
82
+ DashboardInput: () => DashboardInput,
83
+ DashboardMultiSelect: () => DashboardMultiSelect,
84
+ DashboardSelect: () => DashboardSelect,
80
85
  DataTable: () => DataTable,
81
86
  DatePicker: () => DatePicker,
82
87
  DateTableFilter: () => DateTableFilter,
@@ -4894,8 +4899,9 @@ var iconButtonVariants = (0, import_class_variance_authority10.cva)(
4894
4899
  variants: {
4895
4900
  size: {
4896
4901
  s: "w-8 h-8",
4897
- m: "w-10 h-10",
4898
- l: "w-[43px] h-[43px]"
4902
+ m: "w-8 h-8",
4903
+ l: "w-[43px] h-[43px]",
4904
+ default: "w-8 h-8"
4899
4905
  },
4900
4906
  shape: {
4901
4907
  rounded: "rounded-[var(--chekin-radius-input)]",
@@ -7407,13 +7413,13 @@ function SearchButton({ onClick, className, icon, ariaLabel }) {
7407
7413
  {
7408
7414
  onClick,
7409
7415
  className: cn(
7410
- "p-1.5 text-[var(--chekin-color-gray-1)] hover:text-[var(--chekin-color-brand-blue)]",
7416
+ "p-1.5 text-[#9696b9] hover:text-[var(--chekin-color-brand-blue)]",
7411
7417
  className
7412
7418
  ),
7413
7419
  "data-testid": "search-button",
7414
7420
  "aria-label": ariaLabel,
7415
7421
  type: "button",
7416
- children: icon || /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(import_lucide_react26.Search, { size: 14, strokeWidth: 4 })
7422
+ children: icon || /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(import_lucide_react26.Search, { size: 12, strokeWidth: 4 })
7417
7423
  }
7418
7424
  );
7419
7425
  }
@@ -7702,7 +7708,7 @@ var SectionGroupItem = ({
7702
7708
  return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("section", { className: cn("flex flex-col gap-5", className), children: [
7703
7709
  divider && /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("div", { className: cn("h-px w-full bg-[var(--section-group-divider-bg)]") }),
7704
7710
  (title || subtitle) && /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "flex flex-col gap-1 px-8", children: [
7705
- title && /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("h3", { className: "text-sm font-semibold leading-6 text-[var(--section-group-muted-text)]", children: title }),
7711
+ title && /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("h3", { className: "text-base font-semibold leading-6 text-[var(--section-group-muted-text)]", children: title }),
7706
7712
  subtitle && /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("p", { className: "text-sm font-medium leading-6 text-[var(--section-group-muted-text)]", children: subtitle })
7707
7713
  ] }),
7708
7714
  /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("div", { className: cn("flex flex-col gap-4 px-8", contentClassName), children })
@@ -9747,11 +9753,24 @@ ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
9747
9753
  var import_react76 = require("react");
9748
9754
  var import_jsx_runtime127 = require("react/jsx-runtime");
9749
9755
  var getValueArray = (value) => {
9750
- if (value) {
9756
+ if (value !== void 0 && value !== null) {
9751
9757
  return Array.isArray(value) ? value : [value];
9752
9758
  }
9753
9759
  return [];
9754
9760
  };
9761
+ var convertStringToValue = (stringValue, option) => {
9762
+ debugger;
9763
+ if (option) {
9764
+ return option.value;
9765
+ }
9766
+ if (stringValue === "true") return true;
9767
+ if (stringValue === "false") return false;
9768
+ const numValue = Number(stringValue);
9769
+ if (!isNaN(numValue) && stringValue !== "") {
9770
+ return numValue;
9771
+ }
9772
+ return stringValue;
9773
+ };
9755
9774
  function getToggleContent(label, disabled, readOnly, active) {
9756
9775
  if ((0, import_react76.isValidElement)(label)) {
9757
9776
  return (0, import_react76.cloneElement)(label, {
@@ -9788,8 +9807,9 @@ function TogglesInternal({
9788
9807
  const newValueArray = Array.isArray(newValue) ? newValue : [newValue];
9789
9808
  const typedValues = newValueArray.map((item) => {
9790
9809
  const option2 = options.find((opt) => String(opt.value) === item);
9791
- return option2 ? option2.value : item;
9810
+ return convertStringToValue(item, option2);
9792
9811
  });
9812
+ debugger;
9793
9813
  onChange?.(
9794
9814
  typedValues,
9795
9815
  {}
@@ -9798,7 +9818,7 @@ function TogglesInternal({
9798
9818
  }
9799
9819
  const singleValue = Array.isArray(newValue) ? newValue[0] : newValue;
9800
9820
  const option = options.find((opt) => String(opt.value) === singleValue);
9801
- const typedValue = option ? option.value : singleValue;
9821
+ const typedValue = convertStringToValue(singleValue, option);
9802
9822
  onChange?.(
9803
9823
  typedValue,
9804
9824
  {}
@@ -13642,261 +13662,1838 @@ var AirbnbSearchInput = React52.forwardRef(({ onReset, placeholder, wrapperClass
13642
13662
  });
13643
13663
  AirbnbSearchInput.displayName = "SearchInput";
13644
13664
 
13645
- // src/searchable-select/SearchableSelect.tsx
13665
+ // src/dashboard/input/Input.tsx
13646
13666
  var React53 = __toESM(require("react"), 1);
13647
13667
  var import_lucide_react46 = require("lucide-react");
13648
- var import_react_virtual2 = require("@tanstack/react-virtual");
13649
- var import_react82 = require("react");
13668
+
13669
+ // src/dashboard/_fieldset/Fieldset.tsx
13650
13670
  var import_jsx_runtime154 = require("react/jsx-runtime");
13651
- var ROW_HEIGHT = 48;
13652
- var DESKTOP_LIST_HEIGHT = 280;
13653
- var MOBILE_LIST_HEIGHT = 420;
13654
- var LOAD_MORE_THRESHOLD = 6;
13655
- function defaultFilter(option, searchValue) {
13656
- return String(option.label).toLowerCase().includes(searchValue.trim().toLowerCase());
13657
- }
13658
- var SearchableSelectInternal = ({
13659
- options,
13660
- value,
13661
- onChange,
13662
- onBlur,
13663
- onOpenChange,
13664
- searchValue,
13665
- onSearchChange,
13666
- filterOption = defaultFilter,
13667
- loading,
13668
- hasNextPage,
13669
- onLoadMore,
13670
- variant = "default",
13671
- label,
13672
- topLabel,
13673
- placeholder,
13674
- searchPlaceholder = "Search...",
13675
- mobileTitle,
13676
- getValueLabel,
13677
- disabled,
13678
- error,
13671
+ function Fieldset({
13672
+ isActivated,
13673
+ isFocused,
13674
+ isEmpty,
13679
13675
  invalid,
13680
- optional,
13676
+ label,
13681
13677
  tooltip,
13682
- hideErrorMessage,
13683
- name,
13678
+ legend,
13679
+ onClick,
13680
+ htmlFor,
13681
+ labelId,
13682
+ readOnly,
13683
+ loading,
13684
+ disabled,
13684
13685
  className,
13685
- dropdownClassName,
13686
- menuClassName,
13687
- noOptionsMessage,
13688
- loadingMessage
13689
- }, ref) => {
13690
- const { isMatch: isMobile2 } = useScreenResize(DEVICE.mobileXL);
13691
- const reactId = React53.useId();
13692
- const [open, setOpen] = React53.useState(false);
13693
- const [internalSearchValue, setInternalSearchValue] = React53.useState("");
13694
- const [highlightedIndex, setHighlightedIndex] = React53.useState(-1);
13695
- const containerRef = React53.useRef(null);
13696
- const triggerRef = React53.useRef(null);
13697
- const inputRef = React53.useRef(null);
13698
- const listboxId = `${reactId}-listbox`;
13699
- const labelId = `${reactId}-label`;
13700
- const valueId = `${reactId}-value`;
13701
- const helperTextId = `${reactId}-helper`;
13702
- const errorId = `${reactId}-error`;
13703
- const searchInputId = `${reactId}-search`;
13704
- const effectiveSearchValue = searchValue ?? internalSearchValue;
13705
- const shouldFilterLocally = !onSearchChange && filterOption !== null;
13706
- const visibleOptions = React53.useMemo(() => {
13707
- if (!shouldFilterLocally || !effectiveSearchValue) {
13708
- return options;
13709
- }
13710
- return options.filter((option) => filterOption(option, effectiveSearchValue));
13711
- }, [effectiveSearchValue, filterOption, options, shouldFilterLocally]);
13712
- const selectedIndex = React53.useMemo(
13713
- () => visibleOptions.findIndex((option) => option.value === value?.value),
13714
- [value?.value, visibleOptions]
13715
- );
13716
- const helperText = placeholder ?? label;
13717
- const valueLabel = value ? getValueLabel?.(value) ?? String(value.label) : void 0;
13718
- const isBlocked = Boolean(disabled) || Boolean(loading);
13719
- const triggerError = error ?? invalid;
13720
- const describedBy = error && !hideErrorMessage ? errorId : void 0;
13721
- const activeOptionId = highlightedIndex >= 0 ? getOptionId(reactId, highlightedIndex) : void 0;
13722
- useOutsideClick({
13723
- elementRef: containerRef,
13724
- onOutsideClick: () => closeSelect(),
13725
- isDisabled: !open || isMobile2
13726
- });
13727
- const handleOnOpenChange = useEvent(onOpenChange);
13728
- const setSelectOpen = (0, import_react82.useCallback)(
13729
- (nextOpen, options2) => {
13730
- setOpen(nextOpen);
13731
- handleOnOpenChange?.(nextOpen);
13732
- if (!nextOpen && options2?.restoreFocus) {
13733
- triggerRef.current?.focus();
13734
- }
13735
- },
13736
- [handleOnOpenChange]
13737
- );
13738
- React53.useEffect(() => {
13739
- if (isBlocked) {
13740
- setSelectOpen(false);
13741
- return;
13742
- }
13743
- if (!open) return;
13744
- const frameId = window.requestAnimationFrame(() => {
13745
- inputRef.current?.focus();
13746
- });
13747
- return () => {
13748
- window.cancelAnimationFrame(frameId);
13749
- };
13750
- }, [isBlocked, open, setSelectOpen]);
13751
- React53.useEffect(() => {
13752
- if (!open) {
13753
- setHighlightedIndex(-1);
13754
- return;
13755
- }
13756
- setHighlightedIndex((currentIndex) => {
13757
- if (currentIndex >= 0 && currentIndex < visibleOptions.length && !visibleOptions[currentIndex]?.isDisabled) {
13758
- return currentIndex;
13759
- }
13760
- return selectedIndex >= 0 ? selectedIndex : getFirstEnabledIndex(visibleOptions);
13761
- });
13762
- }, [open, selectedIndex, visibleOptions]);
13763
- function openSelect() {
13764
- if (isBlocked) return;
13765
- setSelectOpen(true);
13766
- }
13767
- function closeSelect() {
13768
- setSelectOpen(false, { restoreFocus: true });
13769
- }
13770
- function handleSearchChange(nextValue) {
13771
- if (!onSearchChange) {
13772
- setInternalSearchValue(nextValue);
13773
- }
13774
- onSearchChange?.(nextValue);
13775
- }
13776
- function handleSelect(option) {
13777
- if (isBlocked || option.isDisabled) return;
13778
- onChange(option);
13779
- setSelectOpen(false, { restoreFocus: true });
13780
- }
13781
- function moveHighlight(step) {
13782
- const startIndex = highlightedIndex >= 0 ? highlightedIndex + step : step === 1 ? 0 : visibleOptions.length - 1;
13783
- const nextIndex = getNextEnabledIndex(visibleOptions, startIndex, step);
13784
- if (nextIndex >= 0) {
13785
- setHighlightedIndex(nextIndex);
13786
- }
13787
- }
13788
- function handleTriggerKeyDown(event) {
13789
- if (isBlocked) return;
13790
- if (event.key === "Enter" || event.key === " " || event.key === "ArrowDown" || event.key === "ArrowUp") {
13791
- event.preventDefault();
13792
- openSelect();
13793
- }
13794
- }
13795
- function handleSearchKeyDown(event) {
13796
- if (event.key === "Escape") {
13797
- event.preventDefault();
13798
- closeSelect();
13799
- return;
13800
- }
13801
- if (event.key === "ArrowDown") {
13802
- event.preventDefault();
13803
- moveHighlight(1);
13804
- return;
13805
- }
13806
- if (event.key === "ArrowUp") {
13807
- event.preventDefault();
13808
- moveHighlight(-1);
13809
- return;
13810
- }
13811
- if (event.key === "Enter") {
13812
- event.preventDefault();
13813
- const option = visibleOptions[highlightedIndex];
13814
- if (option) {
13815
- handleSelect(option);
13686
+ labelClassName
13687
+ }) {
13688
+ const showLegendText = Boolean(legend || typeof label === "string");
13689
+ const raised = !isEmpty || isFocused;
13690
+ return /* @__PURE__ */ (0, import_jsx_runtime154.jsxs)(import_jsx_runtime154.Fragment, { children: [
13691
+ /* @__PURE__ */ (0, import_jsx_runtime154.jsxs)(
13692
+ "div",
13693
+ {
13694
+ onClick,
13695
+ className: cn(
13696
+ "absolute box-border inline-flex max-w-full cursor-text items-center pl-[3px] pr-5 transition-all duration-100 ease-in",
13697
+ "left-[13px] text-[var(--chekin-color-gray-1)]",
13698
+ isEmpty && !isFocused ? "top-[14px]" : "top-[-10px] !pl-1 !pr-[22px]",
13699
+ isFocused && "text-[var(--chekin-color-brand-blue)]",
13700
+ raised && invalid && "text-[var(--error-message-color)]",
13701
+ readOnly && "cursor-default",
13702
+ disabled && "pointer-events-none cursor-not-allowed",
13703
+ loading && "cursor-progress",
13704
+ labelClassName
13705
+ ),
13706
+ children: [
13707
+ /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
13708
+ "label",
13709
+ {
13710
+ id: labelId,
13711
+ htmlFor,
13712
+ className: cn(
13713
+ "block cursor-[inherit] truncate font-medium transition-all duration-100 ease-in",
13714
+ raised ? "text-[14px]" : "text-[16px]"
13715
+ ),
13716
+ children: label
13717
+ }
13718
+ ),
13719
+ tooltip && /* @__PURE__ */ (0, import_jsx_runtime154.jsx)("span", { className: "ml-1 inline-flex", children: /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
13720
+ HelpTooltip,
13721
+ {
13722
+ content: tooltip,
13723
+ size: 16,
13724
+ className: cn(isFocused && "text-[var(--chekin-color-brand-blue)]")
13725
+ }
13726
+ ) })
13727
+ ]
13816
13728
  }
13817
- }
13818
- }
13819
- const content = /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
13820
- SearchableSelectContent,
13821
- {
13822
- inputId: searchInputId,
13823
- listboxId,
13824
- labelId,
13825
- activeOptionId,
13826
- inputRef,
13827
- options: visibleOptions,
13828
- value,
13829
- searchValue: effectiveSearchValue,
13830
- searchPlaceholder,
13831
- highlightedIndex,
13832
- loading,
13833
- hasNextPage,
13834
- onLoadMore,
13835
- menuClassName,
13836
- noOptionsMessage,
13837
- loadingMessage,
13838
- height: isMobile2 ? MOBILE_LIST_HEIGHT : DESKTOP_LIST_HEIGHT,
13839
- idPrefix: reactId,
13840
- onSearchChange: handleSearchChange,
13841
- onSearchKeyDown: handleSearchKeyDown,
13842
- onOptionClick: handleSelect,
13843
- onOptionHover: setHighlightedIndex
13844
- }
13845
- );
13846
- React53.useImperativeHandle(ref, () => triggerRef.current, []);
13847
- return /* @__PURE__ */ (0, import_jsx_runtime154.jsxs)("div", { ref: containerRef, className: cn("relative w-full max-w-[425px]", className), children: [
13848
- name && /* @__PURE__ */ (0, import_jsx_runtime154.jsx)("input", { type: "hidden", name, value: value ? String(value.value) : "" }),
13729
+ ),
13849
13730
  /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
13850
- FieldTrigger,
13731
+ "fieldset",
13851
13732
  {
13852
- id: `${reactId}-trigger`,
13853
- ref: triggerRef,
13854
- variant,
13855
- "aria-haspopup": "listbox",
13856
- "aria-expanded": open,
13857
- "aria-controls": listboxId,
13858
- label,
13859
- topLabel,
13860
- labelId,
13861
- valueId,
13862
- helperTextId,
13863
- errorId: error ? errorId : void 0,
13864
- labelText: topLabel ? helperText : void 0,
13865
- valueText: valueLabel,
13866
- placeholder: helperText,
13867
- describedBy,
13868
- error: triggerError,
13869
- loading,
13870
- optional,
13871
- tooltip,
13872
- forceLabelText: Boolean(optional) || Boolean(tooltip),
13873
- hideErrorMessage,
13874
- disabled,
13875
- onClick: () => {
13876
- if (open) {
13877
- closeSelect();
13878
- return;
13879
- }
13880
- openSelect();
13881
- },
13882
- onKeyDown: handleTriggerKeyDown,
13883
- onBlur,
13884
- trailingAdornment: /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
13885
- import_lucide_react46.ChevronDown,
13733
+ "aria-hidden": "true",
13734
+ className: cn(
13735
+ "pointer-events-none absolute -top-[5px] bottom-0 left-0 right-0 m-0 min-w-0 rounded-[6px] border px-[13px] transition-colors duration-75",
13736
+ "border-[var(--chekin-color-gray-3)]",
13737
+ isActivated && "border-[var(--chekin-color-gray-2)]",
13738
+ isFocused && "border-[var(--chekin-color-brand-blue)]",
13739
+ invalid && "border-[var(--error-message-color)]",
13740
+ className
13741
+ ),
13742
+ children: /* @__PURE__ */ (0, import_jsx_runtime154.jsxs)(
13743
+ "legend",
13886
13744
  {
13887
13745
  className: cn(
13888
- "h-6 w-6 text-[#1F1F1B] transition-transform",
13889
- open && "rotate-180"
13890
- )
13746
+ "invisible float-none block h-[11px] max-w-[0.01px] whitespace-nowrap p-0 text-[0.75em]",
13747
+ "transition-[max-width] duration-[50ms] ease-out",
13748
+ raised && "max-w-full !duration-100 !delay-[50ms]",
13749
+ !label && "w-0"
13750
+ ),
13751
+ children: [
13752
+ showLegendText && /* @__PURE__ */ (0, import_jsx_runtime154.jsx)("span", { className: "visible inline-block pr-[6px] text-[14px] font-medium opacity-0", children: legend || label }),
13753
+ tooltip && /* @__PURE__ */ (0, import_jsx_runtime154.jsx)("span", { className: "visible inline-block w-[20px] opacity-0", children: /* @__PURE__ */ (0, import_jsx_runtime154.jsx)("span", { className: "inline-block h-4 w-4" }) })
13754
+ ]
13891
13755
  }
13892
13756
  )
13893
13757
  }
13894
- ),
13895
- isMobile2 ? /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
13896
- Drawer,
13897
- {
13898
- open,
13899
- onOpenChange: (nextOpen) => {
13758
+ )
13759
+ ] });
13760
+ }
13761
+
13762
+ // src/dashboard/input/Input.tsx
13763
+ var import_jsx_runtime155 = require("react/jsx-runtime");
13764
+ var checkIfEmpty = ({
13765
+ empty,
13766
+ defaultValue,
13767
+ value
13768
+ }) => {
13769
+ if (typeof empty !== "undefined") return empty;
13770
+ if (value === 0 || defaultValue === 0) return false;
13771
+ return !value && !defaultValue;
13772
+ };
13773
+ var DashboardInput = React53.forwardRef(
13774
+ ({
13775
+ value,
13776
+ defaultValue,
13777
+ className,
13778
+ wrapperClassName,
13779
+ fieldClassName,
13780
+ contentClassName,
13781
+ inputClassName,
13782
+ label,
13783
+ topLabel,
13784
+ tooltip,
13785
+ disabled,
13786
+ loading,
13787
+ readOnly,
13788
+ name,
13789
+ id,
13790
+ type,
13791
+ error,
13792
+ optional = false,
13793
+ invalid,
13794
+ empty,
13795
+ showNumberButtons,
13796
+ onIncrement,
13797
+ onDecrement,
13798
+ sign,
13799
+ footer,
13800
+ width,
13801
+ onReset,
13802
+ onChange,
13803
+ onFocus,
13804
+ onBlur,
13805
+ helperText,
13806
+ placeholder,
13807
+ leftIcon,
13808
+ trailingAdornment,
13809
+ renderErrorMessage = true,
13810
+ ...props
13811
+ }, ref) => {
13812
+ const generatedId = React53.useId();
13813
+ const inputId = id ?? name ?? generatedId;
13814
+ const errorId = `${inputId}-error`;
13815
+ const isEmpty = checkIfEmpty({ empty, value, defaultValue });
13816
+ const [inputType, setInputType] = React53.useState(type);
13817
+ const [isPasswordRevealed, setIsPasswordRevealed] = React53.useState(false);
13818
+ const [isFocused, setIsFocused] = React53.useState(false);
13819
+ const prevInputType = usePrevious(inputType);
13820
+ const isPasswordReveal = (prevInputType === "password" || type === "password") && !isEmpty;
13821
+ const hasInvalidState = Boolean(invalid) || Boolean(error) && error !== "NONE";
13822
+ const errorMessage = typeof error === "string" && error !== "NONE" ? error : void 0;
13823
+ const wrapperWidth = toCssSize(width);
13824
+ const togglePasswordReveal = () => {
13825
+ if (isPasswordRevealed) {
13826
+ setInputType("password");
13827
+ setIsPasswordRevealed(false);
13828
+ } else {
13829
+ setInputType("text");
13830
+ setIsPasswordRevealed(true);
13831
+ }
13832
+ };
13833
+ React53.useEffect(() => {
13834
+ setInputType(type);
13835
+ }, [type]);
13836
+ const handleChange = (event) => {
13837
+ if (readOnly || disabled || !onChange) return;
13838
+ onChange(event);
13839
+ };
13840
+ const handleLabelClick = () => {
13841
+ if (readOnly || disabled) return;
13842
+ setIsFocused(true);
13843
+ };
13844
+ const handleFocus = (event) => {
13845
+ if (readOnly || disabled) return;
13846
+ onFocus?.(event);
13847
+ setIsFocused(true);
13848
+ };
13849
+ const handleBlur = (event) => {
13850
+ onBlur?.(event);
13851
+ setIsFocused(false);
13852
+ };
13853
+ const showRightPaddingForReset = Boolean(onReset);
13854
+ const showRightPaddingForReveal = isPasswordReveal;
13855
+ return /* @__PURE__ */ (0, import_jsx_runtime155.jsxs)(
13856
+ "div",
13857
+ {
13858
+ className: cn(
13859
+ "relative block min-h-[68px]",
13860
+ disabled && "cursor-not-allowed opacity-50",
13861
+ loading && "cursor-progress opacity-50",
13862
+ wrapperClassName,
13863
+ className
13864
+ ),
13865
+ style: wrapperWidth ? { width: wrapperWidth } : void 0,
13866
+ children: [
13867
+ topLabel && /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
13868
+ "label",
13869
+ {
13870
+ htmlFor: inputId,
13871
+ className: "mb-2 block text-[14px] font-medium text-[var(--chekin-color-brand-navy)]",
13872
+ children: topLabel
13873
+ }
13874
+ ),
13875
+ /* @__PURE__ */ (0, import_jsx_runtime155.jsxs)(
13876
+ "div",
13877
+ {
13878
+ className: cn(
13879
+ "relative block w-full",
13880
+ readOnly && "bg-[var(--chekin-color-surface-input-empty)]",
13881
+ fieldClassName
13882
+ ),
13883
+ children: [
13884
+ /* @__PURE__ */ (0, import_jsx_runtime155.jsxs)("div", { className: cn("relative w-full cursor-text", contentClassName), children: [
13885
+ /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
13886
+ Fieldset,
13887
+ {
13888
+ isFocused: isFocused && !readOnly,
13889
+ invalid: hasInvalidState,
13890
+ isEmpty,
13891
+ onClick: handleLabelClick,
13892
+ isActivated: !isEmpty || isFocused,
13893
+ readOnly,
13894
+ loading,
13895
+ disabled,
13896
+ htmlFor: inputId,
13897
+ labelId: `${inputId}-label`,
13898
+ legend: typeof label === "string" ? label : void 0,
13899
+ label,
13900
+ tooltip,
13901
+ labelClassName: cn({
13902
+ "pl-[28px]": !!leftIcon
13903
+ })
13904
+ }
13905
+ ),
13906
+ leftIcon && /* @__PURE__ */ (0, import_jsx_runtime155.jsx)("span", { className: "pointer-events-none absolute left-0 top-0 flex h-full max-w-10 items-center justify-center text-[var(--chekin-color-gray-2)]", children: /* @__PURE__ */ (0, import_jsx_runtime155.jsx)("span", { className: "flex h-full w-10 items-center justify-center", children: leftIcon }) }),
13907
+ /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
13908
+ "input",
13909
+ {
13910
+ ...props,
13911
+ ref,
13912
+ id: inputId,
13913
+ name,
13914
+ type: inputType,
13915
+ "data-testid": "input",
13916
+ value,
13917
+ defaultValue,
13918
+ disabled: disabled || loading,
13919
+ readOnly,
13920
+ required: !optional,
13921
+ "aria-label": typeof label === "string" ? label : void 0,
13922
+ "aria-invalid": hasInvalidState,
13923
+ "aria-busy": loading,
13924
+ "aria-describedby": errorMessage && renderErrorMessage ? errorId : void 0,
13925
+ placeholder: isFocused || !label ? placeholder : void 0,
13926
+ onChange: handleChange,
13927
+ onFocus: handleFocus,
13928
+ onBlur: handleBlur,
13929
+ className: cn(
13930
+ "m-0 box-border h-12 w-full rounded-[6px] border-0 px-4 text-[16px] font-medium leading-5 text-[var(--chekin-color-brand-navy)] outline-none transition-colors duration-200 [text-overflow:ellipsis] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none",
13931
+ "placeholder:font-medium placeholder:text-[var(--chekin-color-gray-1)] placeholder:opacity-100",
13932
+ isEmpty && !isFocused ? "bg-[var(--chekin-color-surface-input-empty)]" : "bg-transparent",
13933
+ isEmpty && "text-[var(--chekin-color-gray-1)]",
13934
+ inputType === "password" && "[&:not(:placeholder-shown)]:font-bold [&:not(:placeholder-shown)]:tracking-[2px]",
13935
+ (disabled || readOnly) && "cursor-not-allowed",
13936
+ loading && "cursor-progress",
13937
+ leftIcon && "pl-10",
13938
+ (showRightPaddingForReset || showRightPaddingForReveal) && "pr-10",
13939
+ sign && "pr-10",
13940
+ inputClassName
13941
+ )
13942
+ }
13943
+ ),
13944
+ sign && /* @__PURE__ */ (0, import_jsx_runtime155.jsx)("span", { className: "pointer-events-none absolute right-[14px] top-0 flex h-full items-center text-[18px] font-medium leading-6 text-[var(--chekin-color-brand-navy)]", children: sign }),
13945
+ trailingAdornment && /* @__PURE__ */ (0, import_jsx_runtime155.jsx)("span", { className: "pointer-events-none absolute right-[14px] top-0 flex h-full items-center", children: trailingAdornment }),
13946
+ onReset && !isEmpty && /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
13947
+ "button",
13948
+ {
13949
+ type: "button",
13950
+ onClick: onReset,
13951
+ disabled,
13952
+ className: "absolute right-0 top-0 flex h-full w-10 items-center justify-center border-0 bg-transparent p-0 text-[#9696b9] hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-50",
13953
+ "aria-label": "Reset",
13954
+ children: /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(import_lucide_react46.X, { size: 14 })
13955
+ }
13956
+ ),
13957
+ isPasswordReveal && /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
13958
+ "button",
13959
+ {
13960
+ type: "button",
13961
+ onClick: togglePasswordReveal,
13962
+ className: "absolute right-[14px] top-[18px] flex h-[13px] w-[21px] cursor-pointer items-center justify-center border-0 bg-transparent p-0 hover:opacity-85",
13963
+ "aria-label": isPasswordRevealed ? "Hide password" : "Show password",
13964
+ children: /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
13965
+ import_lucide_react46.Eye,
13966
+ {
13967
+ size: 20,
13968
+ className: cn(
13969
+ isPasswordRevealed ? "text-[#fc98dd]" : "text-[var(--chekin-color-gray-2)]"
13970
+ )
13971
+ }
13972
+ )
13973
+ }
13974
+ )
13975
+ ] }),
13976
+ type === "number" && showNumberButtons && /* @__PURE__ */ (0, import_jsx_runtime155.jsxs)("div", { className: "absolute right-[18px] top-[13px] inline-flex items-center text-right", children: [
13977
+ /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
13978
+ "button",
13979
+ {
13980
+ type: "button",
13981
+ onClick: onDecrement,
13982
+ className: "mr-2 inline-flex h-[23px] w-8 cursor-pointer items-center justify-center rounded-[3px] border-0 bg-[var(--chekin-color-brand-blue)] p-0 text-[20px] font-bold text-white outline-none hover:opacity-90 active:opacity-100",
13983
+ "aria-label": "Decrement",
13984
+ children: /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(import_lucide_react46.Minus, { size: 16, strokeWidth: 3, "aria-hidden": true })
13985
+ }
13986
+ ),
13987
+ /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
13988
+ "button",
13989
+ {
13990
+ type: "button",
13991
+ onClick: onIncrement,
13992
+ className: "inline-flex h-[23px] w-8 cursor-pointer items-center justify-center rounded-[3px] border-0 bg-[var(--chekin-color-brand-blue)] p-0 text-[20px] font-bold text-white outline-none hover:opacity-90 active:opacity-100",
13993
+ "aria-label": "Increment",
13994
+ children: /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(import_lucide_react46.Plus, { size: 16, strokeWidth: 3, "aria-hidden": true })
13995
+ }
13996
+ )
13997
+ ] })
13998
+ ]
13999
+ }
14000
+ ),
14001
+ !errorMessage && optional && /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
14002
+ "span",
14003
+ {
14004
+ "data-testid": `${name}-optional`,
14005
+ className: "mt-[1px] block text-left text-[14px] font-medium text-[var(--chekin-color-gray-1)]",
14006
+ children: typeof optional === "string" ? optional : "optional"
14007
+ }
14008
+ ),
14009
+ !errorMessage && helperText && /* @__PURE__ */ (0, import_jsx_runtime155.jsx)("span", { className: "mt-[1px] block text-[12px] font-normal text-[var(--chekin-color-gray-1)]", children: helperText }),
14010
+ errorMessage && renderErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
14011
+ FieldErrorMessage,
14012
+ {
14013
+ id: errorId,
14014
+ message: errorMessage,
14015
+ "data-testid": name ? `${name}-error` : void 0,
14016
+ className: "mt-[1px] text-[14px]"
14017
+ }
14018
+ ),
14019
+ footer
14020
+ ]
14021
+ }
14022
+ );
14023
+ }
14024
+ );
14025
+ DashboardInput.displayName = "DashboardInput";
14026
+
14027
+ // src/dashboard/select/Select.tsx
14028
+ var React55 = __toESM(require("react"), 1);
14029
+ var import_lucide_react47 = require("lucide-react");
14030
+
14031
+ // src/dashboard/_select-internals/utils.ts
14032
+ function getOptionIndex2(options, option) {
14033
+ if (!option) return -1;
14034
+ return options.findIndex((item) => item.value === option.value);
14035
+ }
14036
+ function getFirstEnabledOptionIndex2(options) {
14037
+ return options.findIndex((option) => !option.isDisabled);
14038
+ }
14039
+ function getNextEnabledOptionIndex2(options, startIndex, step) {
14040
+ let nextIndex = startIndex;
14041
+ while (nextIndex >= 0 && nextIndex < options.length) {
14042
+ if (!options[nextIndex]?.isDisabled) return nextIndex;
14043
+ nextIndex += step;
14044
+ }
14045
+ return -1;
14046
+ }
14047
+ function defaultFilterOption(option, input) {
14048
+ if (!input) return true;
14049
+ const text = typeof option.label === "string" ? option.label : String(option.value);
14050
+ return text.toLowerCase().includes(input.toLowerCase());
14051
+ }
14052
+ function isOptionSelected(option, selectedValue, selectedValues) {
14053
+ if (selectedValues?.length) {
14054
+ return selectedValues.some((item) => item.value === option.value);
14055
+ }
14056
+ return selectedValue?.value === option.value;
14057
+ }
14058
+
14059
+ // src/dashboard/_select-internals/SelectMenu.tsx
14060
+ var import_jsx_runtime156 = require("react/jsx-runtime");
14061
+ function SelectMenu({
14062
+ id,
14063
+ options,
14064
+ labelledBy,
14065
+ describedBy,
14066
+ selectedValue,
14067
+ selectedValues,
14068
+ highlightedIndex,
14069
+ onOptionClick,
14070
+ onOptionHover,
14071
+ onKeyDown,
14072
+ disabled,
14073
+ menuClassName,
14074
+ listRef,
14075
+ selectedOptionRef,
14076
+ getOptionId: getOptionId2,
14077
+ noOptionsMessage,
14078
+ isMulti,
14079
+ emptyContent,
14080
+ footer
14081
+ }) {
14082
+ const emptyMessage = noOptionsMessage?.();
14083
+ const hasOptions = options.length > 0;
14084
+ return /* @__PURE__ */ (0, import_jsx_runtime156.jsxs)(
14085
+ "div",
14086
+ {
14087
+ id,
14088
+ ref: listRef,
14089
+ role: "listbox",
14090
+ tabIndex: -1,
14091
+ "aria-labelledby": labelledBy,
14092
+ "aria-describedby": describedBy,
14093
+ "aria-multiselectable": isMulti,
14094
+ "aria-activedescendant": highlightedIndex !== void 0 && highlightedIndex >= 0 ? getOptionId2(highlightedIndex) : void 0,
14095
+ onKeyDown,
14096
+ className: cn(
14097
+ "h-auto max-h-[322px] min-h-[75px] overflow-y-auto px-4 pb-[19px] pt-[17px] outline-none",
14098
+ menuClassName
14099
+ ),
14100
+ children: [
14101
+ !hasOptions && emptyMessage && /* @__PURE__ */ (0, import_jsx_runtime156.jsx)("div", { className: "mt-[10px] text-left text-[16px] text-[var(--chekin-color-brand-navy)]", children: emptyMessage }),
14102
+ !hasOptions && !emptyMessage && emptyContent,
14103
+ options.map((option, index) => {
14104
+ const isSelected = isOptionSelected(option, selectedValue, selectedValues);
14105
+ const isHighlighted = index === highlightedIndex;
14106
+ const optionKey = `${String(option.value)}-${index}`;
14107
+ const isOptionDisabled = Boolean(disabled || option.isDisabled);
14108
+ return /* @__PURE__ */ (0, import_jsx_runtime156.jsxs)(
14109
+ "button",
14110
+ {
14111
+ id: getOptionId2(index),
14112
+ ref: (node) => {
14113
+ selectedOptionRef?.(index, node);
14114
+ },
14115
+ type: "button",
14116
+ role: "option",
14117
+ "aria-selected": isSelected,
14118
+ "aria-disabled": isOptionDisabled,
14119
+ tabIndex: -1,
14120
+ disabled: isOptionDisabled,
14121
+ onClick: () => onOptionClick(option),
14122
+ onMouseMove: () => onOptionHover?.(index),
14123
+ className: cn(
14124
+ "flex w-full items-start justify-between border-0 border-b border-[#f2f4f8] bg-white px-4 py-[20px] text-left text-[16px] font-medium leading-5 text-[var(--chekin-color-brand-navy)] outline-none transition-colors",
14125
+ "last:border-b-transparent",
14126
+ isHighlighted && !isSelected && "cursor-pointer text-[var(--chekin-color-brand-blue)]",
14127
+ isSelected && "cursor-default font-bold text-[var(--chekin-color-brand-navy)]",
14128
+ isOptionDisabled && "cursor-default opacity-30"
14129
+ ),
14130
+ children: [
14131
+ /* @__PURE__ */ (0, import_jsx_runtime156.jsx)("span", { className: "block break-words", children: option.label }),
14132
+ option.description && /* @__PURE__ */ (0, import_jsx_runtime156.jsx)("span", { className: "ml-2 mt-[3px] shrink-0 text-[12px] font-bold italic text-[#777e91]", children: option.description })
14133
+ ]
14134
+ },
14135
+ optionKey
14136
+ );
14137
+ }),
14138
+ footer
14139
+ ]
14140
+ }
14141
+ );
14142
+ }
14143
+
14144
+ // src/dashboard/_select-internals/useSelectIds.ts
14145
+ var React54 = __toESM(require("react"), 1);
14146
+ function useSelectIds2({
14147
+ name,
14148
+ hasValue,
14149
+ error,
14150
+ hideErrorMessage
14151
+ }) {
14152
+ const reactId = React54.useId().replace(/:/g, "");
14153
+ const baseId = name ? `dash-select-${name}` : `dash-select-${reactId}`;
14154
+ const triggerId = `${baseId}-trigger`;
14155
+ const labelId = `${baseId}-label`;
14156
+ const valueId = `${baseId}-value`;
14157
+ const helperTextId = `${baseId}-helper`;
14158
+ const errorId = `${baseId}-error`;
14159
+ const listboxId = `${baseId}-listbox`;
14160
+ const describedErrorId = error && !hideErrorMessage ? errorId : void 0;
14161
+ const describedBy = [!hasValue ? helperTextId : null, describedErrorId].filter(Boolean).join(" ") || void 0;
14162
+ const getOptionId2 = React54.useCallback(
14163
+ (index) => `${baseId}-option-${index}`,
14164
+ [baseId]
14165
+ );
14166
+ return {
14167
+ triggerId,
14168
+ labelId,
14169
+ valueId,
14170
+ helperTextId,
14171
+ errorId,
14172
+ describedErrorId,
14173
+ listboxId,
14174
+ describedBy,
14175
+ getOptionId: getOptionId2
14176
+ };
14177
+ }
14178
+
14179
+ // src/dashboard/select/Select.tsx
14180
+ var import_jsx_runtime157 = require("react/jsx-runtime");
14181
+ function DashboardSelectInternal({
14182
+ options = [],
14183
+ value,
14184
+ onChange,
14185
+ onBlur,
14186
+ label,
14187
+ topLabel,
14188
+ placeholder,
14189
+ getValueLabel,
14190
+ disabled,
14191
+ loading,
14192
+ optional,
14193
+ tooltip,
14194
+ error,
14195
+ invalid,
14196
+ hideErrorMessage,
14197
+ className,
14198
+ menuClassName,
14199
+ dropdownClassName,
14200
+ name,
14201
+ width,
14202
+ noOptionsMessage,
14203
+ searchable = true,
14204
+ searchPlaceholder,
14205
+ filterOption = defaultFilterOption,
14206
+ helperText
14207
+ }, ref) {
14208
+ const containerRef = React55.useRef(null);
14209
+ const triggerRef = React55.useRef(null);
14210
+ const searchInputRef = React55.useRef(null);
14211
+ const listRef = React55.useRef(null);
14212
+ const optionRefs = React55.useRef([]);
14213
+ const [isOpen, setIsOpen] = React55.useState(false);
14214
+ const [searchValue, setSearchValue] = React55.useState("");
14215
+ const [highlightedIndex, setHighlightedIndex] = React55.useState(-1);
14216
+ const hasValue = Boolean(value);
14217
+ const isEmpty = !hasValue;
14218
+ const isBlocked = Boolean(disabled) || Boolean(loading);
14219
+ const triggerError = error ?? invalid;
14220
+ const hasInvalidState = Boolean(triggerError);
14221
+ const errorMessage = typeof error === "string" ? error : void 0;
14222
+ const wrapperWidth = toCssSize(width);
14223
+ const valueLabel = value ? getValueLabel?.(value) ?? String(value.label) : void 0;
14224
+ const { triggerId, labelId, valueId, listboxId, describedErrorId, errorId, getOptionId: getOptionId2 } = useSelectIds2({ name, hasValue, error, hideErrorMessage });
14225
+ const filteredOptions = React55.useMemo(() => {
14226
+ if (!searchable || !searchValue) return options;
14227
+ return options.filter((option) => filterOption(option, searchValue));
14228
+ }, [options, searchable, searchValue, filterOption]);
14229
+ React55.useImperativeHandle(ref, () => triggerRef.current, []);
14230
+ useOutsideClick({
14231
+ elementRef: containerRef,
14232
+ onOutsideClick: () => setIsOpen(false),
14233
+ isDisabled: !isOpen
14234
+ });
14235
+ React55.useEffect(() => {
14236
+ if (isBlocked) setIsOpen(false);
14237
+ }, [isBlocked]);
14238
+ React55.useEffect(() => {
14239
+ if (!isOpen) {
14240
+ setSearchValue("");
14241
+ setHighlightedIndex(-1);
14242
+ return;
14243
+ }
14244
+ const selectedIndex = getOptionIndex2(filteredOptions, value);
14245
+ setHighlightedIndex(
14246
+ selectedIndex >= 0 ? selectedIndex : getFirstEnabledOptionIndex2(filteredOptions)
14247
+ );
14248
+ if (searchable) {
14249
+ const frame = window.requestAnimationFrame(() => searchInputRef.current?.focus());
14250
+ return () => window.cancelAnimationFrame(frame);
14251
+ }
14252
+ }, [isOpen, filteredOptions, searchable, value]);
14253
+ React55.useEffect(() => {
14254
+ if (!isOpen || highlightedIndex < 0) return;
14255
+ optionRefs.current[highlightedIndex]?.scrollIntoView({ block: "nearest" });
14256
+ }, [highlightedIndex, isOpen]);
14257
+ React55.useEffect(
14258
+ function setCorrectOptionIfThereIsOnlyValue() {
14259
+ if (value?.value === void 0 || value.value === null || value.label !== "")
14260
+ return;
14261
+ const validOption = options.find((option) => option.value === value.value);
14262
+ if (validOption) onChange(validOption);
14263
+ },
14264
+ [onChange, options, value]
14265
+ );
14266
+ const toggleMenu = () => {
14267
+ if (isBlocked) return;
14268
+ setIsOpen((prev) => !prev);
14269
+ };
14270
+ const handleSelect = (option) => {
14271
+ if (option.isDisabled) return;
14272
+ onChange(option);
14273
+ setIsOpen(false);
14274
+ triggerRef.current?.focus();
14275
+ };
14276
+ const handleTriggerKeyDown = (event) => {
14277
+ if (isBlocked) return;
14278
+ if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Enter" || event.key === " ") {
14279
+ event.preventDefault();
14280
+ setIsOpen(true);
14281
+ }
14282
+ };
14283
+ const handleSearchKeyDown = (event) => {
14284
+ if (event.key === "ArrowDown") {
14285
+ event.preventDefault();
14286
+ const next = getNextEnabledOptionIndex2(filteredOptions, highlightedIndex + 1, 1);
14287
+ if (next >= 0) setHighlightedIndex(next);
14288
+ return;
14289
+ }
14290
+ if (event.key === "ArrowUp") {
14291
+ event.preventDefault();
14292
+ const next = getNextEnabledOptionIndex2(filteredOptions, highlightedIndex - 1, -1);
14293
+ if (next >= 0) setHighlightedIndex(next);
14294
+ return;
14295
+ }
14296
+ if (event.key === "Enter") {
14297
+ event.preventDefault();
14298
+ const option = filteredOptions[highlightedIndex];
14299
+ if (option && !option.isDisabled) handleSelect(option);
14300
+ return;
14301
+ }
14302
+ if (event.key === "Escape") {
14303
+ event.preventDefault();
14304
+ setIsOpen(false);
14305
+ triggerRef.current?.focus();
14306
+ return;
14307
+ }
14308
+ if (event.key === "Tab") {
14309
+ setIsOpen(false);
14310
+ }
14311
+ };
14312
+ return /* @__PURE__ */ (0, import_jsx_runtime157.jsxs)(
14313
+ "div",
14314
+ {
14315
+ ref: containerRef,
14316
+ className: cn(
14317
+ "relative w-full max-w-[var(--max-field-width)]",
14318
+ disabled && "cursor-not-allowed opacity-50",
14319
+ loading && "cursor-progress",
14320
+ className
14321
+ ),
14322
+ style: wrapperWidth ? { width: wrapperWidth } : void 0,
14323
+ children: [
14324
+ name && /* @__PURE__ */ (0, import_jsx_runtime157.jsx)("input", { type: "hidden", name, value: value ? String(value.value) : "" }),
14325
+ /* @__PURE__ */ (0, import_jsx_runtime157.jsxs)("div", { className: "relative w-full min-h-[68px]", children: [
14326
+ topLabel && /* @__PURE__ */ (0, import_jsx_runtime157.jsx)(
14327
+ "label",
14328
+ {
14329
+ htmlFor: triggerId,
14330
+ className: "mb-2 block text-[14px] font-medium text-[var(--chekin-color-brand-navy)]",
14331
+ children: topLabel
14332
+ }
14333
+ ),
14334
+ /* @__PURE__ */ (0, import_jsx_runtime157.jsxs)("div", { className: "relative w-full", children: [
14335
+ /* @__PURE__ */ (0, import_jsx_runtime157.jsxs)(
14336
+ "button",
14337
+ {
14338
+ id: triggerId,
14339
+ ref: triggerRef,
14340
+ type: "button",
14341
+ "aria-haspopup": "listbox",
14342
+ "aria-expanded": isOpen,
14343
+ "aria-controls": listboxId,
14344
+ "aria-labelledby": hasValue && valueId ? `${labelId} ${valueId}` : labelId,
14345
+ "aria-describedby": describedErrorId,
14346
+ "aria-invalid": hasInvalidState,
14347
+ "aria-busy": loading,
14348
+ disabled: isBlocked,
14349
+ onClick: toggleMenu,
14350
+ onKeyDown: handleTriggerKeyDown,
14351
+ onBlur,
14352
+ className: cn(
14353
+ "relative m-0 box-border flex h-12 w-full cursor-pointer items-center justify-between gap-2 rounded-[6px] border-0 px-4 text-left text-[16px] font-medium leading-5 outline-none transition-colors duration-200",
14354
+ isEmpty ? "bg-[var(--chekin-color-surface-input-empty)] text-[var(--chekin-color-gray-1)]" : "bg-transparent text-[var(--chekin-color-brand-navy)]",
14355
+ disabled && "cursor-not-allowed opacity-50",
14356
+ loading && "cursor-progress"
14357
+ ),
14358
+ children: [
14359
+ /* @__PURE__ */ (0, import_jsx_runtime157.jsx)("span", { id: valueId, className: "block min-w-0 flex-1 truncate text-left", children: valueLabel ?? placeholder ?? label }),
14360
+ /* @__PURE__ */ (0, import_jsx_runtime157.jsxs)("span", { className: "pointer-events-none flex items-center gap-2 text-[var(--chekin-color-gray-2)]", children: [
14361
+ loading && /* @__PURE__ */ (0, import_jsx_runtime157.jsx)(ThreeDotsLoader, { height: 18, width: 18 }),
14362
+ /* @__PURE__ */ (0, import_jsx_runtime157.jsx)(
14363
+ import_lucide_react47.ChevronDown,
14364
+ {
14365
+ size: 16,
14366
+ className: cn(
14367
+ "transition-transform duration-200",
14368
+ isOpen && "rotate-180 text-[var(--chekin-color-brand-blue)]"
14369
+ )
14370
+ }
14371
+ )
14372
+ ] })
14373
+ ]
14374
+ }
14375
+ ),
14376
+ /* @__PURE__ */ (0, import_jsx_runtime157.jsx)(
14377
+ Fieldset,
14378
+ {
14379
+ isFocused: isOpen,
14380
+ invalid: hasInvalidState,
14381
+ isEmpty,
14382
+ isActivated: !isEmpty || isOpen,
14383
+ disabled,
14384
+ loading,
14385
+ htmlFor: triggerId,
14386
+ labelId,
14387
+ legend: typeof label === "string" ? label : void 0,
14388
+ label,
14389
+ tooltip,
14390
+ onClick: !isBlocked ? toggleMenu : void 0
14391
+ }
14392
+ ),
14393
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime157.jsxs)(
14394
+ "div",
14395
+ {
14396
+ className: cn(
14397
+ "absolute left-0 right-0 top-full z-20 overflow-hidden rounded-b-lg bg-white shadow-[0_30px_30px_0_rgba(33,72,255,0.2)]",
14398
+ dropdownClassName
14399
+ ),
14400
+ children: [
14401
+ searchable && /* @__PURE__ */ (0, import_jsx_runtime157.jsx)("div", { className: "border-b border-[#f2f4f8] px-4 pb-2 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime157.jsx)(
14402
+ "input",
14403
+ {
14404
+ ref: searchInputRef,
14405
+ type: "text",
14406
+ value: searchValue,
14407
+ placeholder: searchPlaceholder,
14408
+ onChange: (event) => setSearchValue(event.target.value),
14409
+ onKeyDown: handleSearchKeyDown,
14410
+ autoComplete: "off",
14411
+ "aria-controls": listboxId,
14412
+ "aria-activedescendant": highlightedIndex >= 0 ? getOptionId2(highlightedIndex) : void 0,
14413
+ className: "m-0 box-border h-9 w-full rounded-md border border-[var(--chekin-color-gray-3)] bg-white px-3 text-[16px] font-medium text-[var(--chekin-color-brand-navy)] outline-none transition-colors placeholder:text-[var(--chekin-color-gray-1)] focus:border-[var(--chekin-color-brand-blue)]"
14414
+ }
14415
+ ) }),
14416
+ /* @__PURE__ */ (0, import_jsx_runtime157.jsx)(
14417
+ SelectMenu,
14418
+ {
14419
+ id: listboxId,
14420
+ options: filteredOptions,
14421
+ labelledBy: labelId,
14422
+ describedBy: describedErrorId,
14423
+ selectedValue: value,
14424
+ highlightedIndex,
14425
+ onOptionClick: handleSelect,
14426
+ onOptionHover: setHighlightedIndex,
14427
+ disabled: isBlocked,
14428
+ menuClassName,
14429
+ listRef,
14430
+ selectedOptionRef: (index, node) => {
14431
+ optionRefs.current[index] = node;
14432
+ },
14433
+ getOptionId: getOptionId2,
14434
+ noOptionsMessage
14435
+ }
14436
+ )
14437
+ ]
14438
+ }
14439
+ )
14440
+ ] }),
14441
+ !errorMessage && optional && /* @__PURE__ */ (0, import_jsx_runtime157.jsx)("span", { className: "mt-[1px] block text-left text-[14px] font-medium text-[var(--chekin-color-gray-1)]", children: typeof optional === "string" ? optional : "optional" }),
14442
+ !errorMessage && helperText && /* @__PURE__ */ (0, import_jsx_runtime157.jsx)("span", { className: "mt-[1px] block text-[12px] font-normal text-[var(--chekin-color-gray-1)]", children: helperText }),
14443
+ errorMessage && !hideErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime157.jsx)(
14444
+ FieldErrorMessage,
14445
+ {
14446
+ id: errorId,
14447
+ message: errorMessage,
14448
+ className: "mt-[1px] text-[14px]"
14449
+ }
14450
+ )
14451
+ ] })
14452
+ ]
14453
+ }
14454
+ );
14455
+ }
14456
+ var DashboardSelect = React55.forwardRef(
14457
+ DashboardSelectInternal
14458
+ );
14459
+
14460
+ // src/dashboard/multi-select/MultiSelect.tsx
14461
+ var React56 = __toESM(require("react"), 1);
14462
+ var import_lucide_react48 = require("lucide-react");
14463
+ var import_jsx_runtime158 = require("react/jsx-runtime");
14464
+ var isValueSelected = (selected, option) => selected.some((item) => item.value === option.value);
14465
+ function DashboardMultiSelectInternal({
14466
+ options = [],
14467
+ value,
14468
+ onChange,
14469
+ onBlur,
14470
+ label,
14471
+ topLabel,
14472
+ placeholder,
14473
+ disabled,
14474
+ readOnly,
14475
+ loading,
14476
+ optional,
14477
+ tooltip,
14478
+ error,
14479
+ invalid,
14480
+ hideErrorMessage,
14481
+ className,
14482
+ menuClassName,
14483
+ dropdownClassName,
14484
+ name,
14485
+ width,
14486
+ noOptionsMessage,
14487
+ filterOption = defaultFilterOption,
14488
+ closeMenuOnSelect = false,
14489
+ renderChip,
14490
+ helperText,
14491
+ isCreatable = false,
14492
+ onCreateOption,
14493
+ formatCreateLabel = (input) => `Create "${input}"`,
14494
+ isValidNewOption
14495
+ }, ref) {
14496
+ const containerRef = React56.useRef(null);
14497
+ const inputRef = React56.useRef(null);
14498
+ const listRef = React56.useRef(null);
14499
+ const optionRefs = React56.useRef([]);
14500
+ const [isOpen, setIsOpen] = React56.useState(false);
14501
+ const [searchValue, setSearchValue] = React56.useState("");
14502
+ const [isFocused, setIsFocused] = React56.useState(false);
14503
+ const [highlightedIndex, setHighlightedIndex] = React56.useState(-1);
14504
+ const selectedValues = React56.useMemo(() => value ?? [], [value]);
14505
+ const hasValue = selectedValues.length > 0;
14506
+ const isEmpty = !hasValue;
14507
+ const isBlocked = Boolean(disabled) || Boolean(loading) || Boolean(readOnly);
14508
+ const triggerError = error ?? invalid;
14509
+ const hasInvalidState = Boolean(triggerError);
14510
+ const errorMessage = typeof error === "string" ? error : void 0;
14511
+ const wrapperWidth = toCssSize(width);
14512
+ const { triggerId, labelId, valueId, listboxId, describedErrorId, errorId, getOptionId: getOptionId2 } = useSelectIds2({ name, hasValue, error, hideErrorMessage });
14513
+ const filteredOptions = React56.useMemo(
14514
+ () => options.filter((option) => filterOption(option, searchValue)),
14515
+ [options, searchValue, filterOption]
14516
+ );
14517
+ const trimmedSearch = searchValue.trim();
14518
+ const canCreateNewOption = React56.useMemo(() => {
14519
+ if (!isCreatable || !trimmedSearch) return false;
14520
+ if (isValidNewOption) return isValidNewOption(trimmedSearch, selectedValues, options);
14521
+ const lower = trimmedSearch.toLowerCase();
14522
+ const existsInOptions = options.some(
14523
+ (option) => typeof option.label === "string" && option.label.toLowerCase() === lower
14524
+ );
14525
+ const existsInSelected = selectedValues.some(
14526
+ (option) => typeof option.label === "string" && option.label.toLowerCase() === lower
14527
+ );
14528
+ return !existsInOptions && !existsInSelected;
14529
+ }, [isCreatable, trimmedSearch, isValidNewOption, options, selectedValues]);
14530
+ React56.useImperativeHandle(
14531
+ ref,
14532
+ () => containerRef.current
14533
+ );
14534
+ useOutsideClick({
14535
+ elementRef: containerRef,
14536
+ onOutsideClick: () => {
14537
+ setIsOpen(false);
14538
+ setIsFocused(false);
14539
+ },
14540
+ isDisabled: !isOpen
14541
+ });
14542
+ React56.useEffect(() => {
14543
+ if (isBlocked) setIsOpen(false);
14544
+ }, [isBlocked]);
14545
+ React56.useEffect(() => {
14546
+ if (!isOpen) {
14547
+ setSearchValue("");
14548
+ setHighlightedIndex(-1);
14549
+ }
14550
+ }, [isOpen]);
14551
+ React56.useEffect(() => {
14552
+ if (!isOpen || filteredOptions.length === 0) {
14553
+ setHighlightedIndex(-1);
14554
+ return;
14555
+ }
14556
+ setHighlightedIndex((current) => {
14557
+ if (current >= 0 && current < filteredOptions.length) return current;
14558
+ return getFirstEnabledOptionIndex2(filteredOptions);
14559
+ });
14560
+ }, [isOpen, filteredOptions]);
14561
+ const openMenu = () => {
14562
+ if (isBlocked) return;
14563
+ setIsOpen(true);
14564
+ setIsFocused(true);
14565
+ };
14566
+ const toggleOption = (option) => {
14567
+ if (option.isDisabled) return;
14568
+ const exists = isValueSelected(selectedValues, option);
14569
+ const next = exists ? selectedValues.filter((item) => item.value !== option.value) : [...selectedValues, option];
14570
+ onChange(next);
14571
+ setSearchValue("");
14572
+ if (closeMenuOnSelect) {
14573
+ setIsOpen(false);
14574
+ } else {
14575
+ inputRef.current?.focus();
14576
+ }
14577
+ };
14578
+ const removeOption = (option) => {
14579
+ if (isBlocked) return;
14580
+ onChange(selectedValues.filter((item) => item.value !== option.value));
14581
+ inputRef.current?.focus();
14582
+ };
14583
+ const clearAll = () => {
14584
+ if (isBlocked) return;
14585
+ onChange([]);
14586
+ inputRef.current?.focus();
14587
+ };
14588
+ const createOption = React56.useCallback(() => {
14589
+ if (!canCreateNewOption) return;
14590
+ const newOption = onCreateOption?.(trimmedSearch) ?? { value: trimmedSearch, label: trimmedSearch };
14591
+ onChange([...selectedValues, newOption]);
14592
+ setSearchValue("");
14593
+ inputRef.current?.focus();
14594
+ if (closeMenuOnSelect) setIsOpen(false);
14595
+ }, [
14596
+ canCreateNewOption,
14597
+ closeMenuOnSelect,
14598
+ onChange,
14599
+ onCreateOption,
14600
+ selectedValues,
14601
+ trimmedSearch
14602
+ ]);
14603
+ const handleInputKeyDown = (event) => {
14604
+ if (event.key === "Backspace" && !searchValue && selectedValues.length > 0) {
14605
+ event.preventDefault();
14606
+ onChange(selectedValues.slice(0, -1));
14607
+ return;
14608
+ }
14609
+ if (event.key === "ArrowDown") {
14610
+ event.preventDefault();
14611
+ if (!isOpen) {
14612
+ openMenu();
14613
+ return;
14614
+ }
14615
+ const next = getNextEnabledOptionIndex2(filteredOptions, highlightedIndex + 1, 1);
14616
+ if (next >= 0) setHighlightedIndex(next);
14617
+ return;
14618
+ }
14619
+ if (event.key === "ArrowUp") {
14620
+ event.preventDefault();
14621
+ if (!isOpen) {
14622
+ openMenu();
14623
+ return;
14624
+ }
14625
+ const next = getNextEnabledOptionIndex2(filteredOptions, highlightedIndex - 1, -1);
14626
+ if (next >= 0) setHighlightedIndex(next);
14627
+ return;
14628
+ }
14629
+ if (event.key === "Enter") {
14630
+ if (!isOpen) return;
14631
+ event.preventDefault();
14632
+ const option = filteredOptions[highlightedIndex];
14633
+ if (option && !option.isDisabled) {
14634
+ toggleOption(option);
14635
+ } else if (canCreateNewOption) {
14636
+ createOption();
14637
+ }
14638
+ return;
14639
+ }
14640
+ if (event.key === "Escape") {
14641
+ event.preventDefault();
14642
+ setIsOpen(false);
14643
+ }
14644
+ };
14645
+ const handleContainerClick = () => {
14646
+ if (isBlocked) return;
14647
+ inputRef.current?.focus();
14648
+ setIsOpen(true);
14649
+ };
14650
+ const handleInputBlur = (event) => {
14651
+ if (containerRef.current?.contains(event.relatedTarget)) return;
14652
+ setIsFocused(false);
14653
+ onBlur?.(event);
14654
+ };
14655
+ return /* @__PURE__ */ (0, import_jsx_runtime158.jsxs)(
14656
+ "div",
14657
+ {
14658
+ ref: containerRef,
14659
+ onBlur: handleInputBlur,
14660
+ className: cn(
14661
+ "relative min-h-[68px] w-full max-w-[var(--max-field-width)]",
14662
+ disabled && "cursor-not-allowed opacity-50",
14663
+ loading && "cursor-progress",
14664
+ className
14665
+ ),
14666
+ style: wrapperWidth ? { width: wrapperWidth } : void 0,
14667
+ children: [
14668
+ topLabel && /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14669
+ "label",
14670
+ {
14671
+ htmlFor: triggerId,
14672
+ className: "mb-2 block text-[14px] font-medium text-[var(--chekin-color-brand-navy)]",
14673
+ children: topLabel
14674
+ }
14675
+ ),
14676
+ name && /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14677
+ "input",
14678
+ {
14679
+ type: "hidden",
14680
+ name,
14681
+ value: selectedValues.map((item) => String(item.value)).join(",")
14682
+ }
14683
+ ),
14684
+ /* @__PURE__ */ (0, import_jsx_runtime158.jsxs)("div", { className: "relative w-full", children: [
14685
+ /* @__PURE__ */ (0, import_jsx_runtime158.jsxs)(
14686
+ "div",
14687
+ {
14688
+ id: triggerId,
14689
+ role: "combobox",
14690
+ "aria-haspopup": "listbox",
14691
+ "aria-expanded": isOpen,
14692
+ "aria-controls": listboxId,
14693
+ "aria-labelledby": hasValue && valueId ? `${labelId} ${valueId}` : labelId,
14694
+ "aria-describedby": describedErrorId,
14695
+ "aria-invalid": hasInvalidState,
14696
+ "aria-busy": loading,
14697
+ "aria-disabled": isBlocked,
14698
+ onClick: handleContainerClick,
14699
+ className: cn(
14700
+ "relative box-border flex w-full cursor-text flex-wrap items-center gap-2 rounded-[6px] border-0 px-4 py-[10px] text-left text-[16px] font-medium leading-5 outline-none transition-colors duration-200",
14701
+ "min-h-12",
14702
+ isEmpty && !isFocused ? "bg-[var(--chekin-color-surface-input-empty)]" : "bg-transparent",
14703
+ disabled && "cursor-not-allowed",
14704
+ loading && "cursor-progress"
14705
+ ),
14706
+ children: [
14707
+ selectedValues.map(
14708
+ (option) => renderChip ? /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(React56.Fragment, { children: renderChip(option, () => removeOption(option)) }, String(option.value)) : /* @__PURE__ */ (0, import_jsx_runtime158.jsxs)(
14709
+ "span",
14710
+ {
14711
+ className: "inline-flex items-center gap-2 rounded-[4px] border border-[#acacd5] bg-[#f0f0f8] py-[2px] pl-[10px] pr-1 text-[12px] font-medium text-[var(--chekin-color-brand-navy)]",
14712
+ children: [
14713
+ /* @__PURE__ */ (0, import_jsx_runtime158.jsx)("span", { className: "whitespace-nowrap", children: option.label }),
14714
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14715
+ "button",
14716
+ {
14717
+ type: "button",
14718
+ onClick: (event) => {
14719
+ event.stopPropagation();
14720
+ removeOption(option);
14721
+ },
14722
+ className: "flex h-[15px] w-[15px] items-center justify-center rounded-[3px] border-0 bg-transparent p-0 text-[#9696b9] hover:shadow-[0_3px_3px_#0f477734]",
14723
+ "aria-label": `Remove ${typeof option.label === "string" ? option.label : String(option.value)}`,
14724
+ children: /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(import_lucide_react48.SquareX, { size: 15, fill: "#9696b9", color: "#f8f8f8", strokeWidth: 1.8 })
14725
+ }
14726
+ )
14727
+ ]
14728
+ },
14729
+ String(option.value)
14730
+ )
14731
+ ),
14732
+ /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14733
+ "input",
14734
+ {
14735
+ ref: inputRef,
14736
+ type: "text",
14737
+ id: `${triggerId}-input`,
14738
+ value: searchValue,
14739
+ onChange: (event) => {
14740
+ setSearchValue(event.target.value);
14741
+ if (!isOpen) setIsOpen(true);
14742
+ },
14743
+ onFocus: () => {
14744
+ setIsFocused(true);
14745
+ if (!isBlocked) setIsOpen(true);
14746
+ },
14747
+ onKeyDown: handleInputKeyDown,
14748
+ disabled: isBlocked,
14749
+ readOnly,
14750
+ placeholder: hasValue ? "" : placeholder ?? "",
14751
+ autoComplete: "off",
14752
+ className: cn(
14753
+ "m-0 box-border min-w-[40px] flex-1 border-0 bg-transparent p-0 text-[16px] font-medium leading-5 text-[var(--chekin-color-brand-navy)] outline-none placeholder:text-[var(--chekin-color-gray-1)]",
14754
+ isBlocked && "cursor-not-allowed"
14755
+ ),
14756
+ "aria-autocomplete": "list",
14757
+ "aria-controls": listboxId,
14758
+ "aria-activedescendant": isOpen && highlightedIndex >= 0 ? getOptionId2(highlightedIndex) : void 0
14759
+ }
14760
+ ),
14761
+ /* @__PURE__ */ (0, import_jsx_runtime158.jsxs)("span", { className: "ml-auto flex items-center gap-2 pl-2 text-[var(--chekin-color-gray-2)]", children: [
14762
+ loading && /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(ThreeDotsLoader, { height: 18, width: 18 }),
14763
+ hasValue && !readOnly && /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14764
+ "button",
14765
+ {
14766
+ type: "button",
14767
+ onClick: (event) => {
14768
+ event.stopPropagation();
14769
+ clearAll();
14770
+ },
14771
+ className: "flex h-5 w-5 items-center justify-center rounded-[3px] border-0 bg-transparent p-0 text-[#9696b9] hover:shadow-[0_3px_3px_#0f477734]",
14772
+ "aria-label": "Clear all",
14773
+ children: /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(import_lucide_react48.SquareX, { size: 15, fill: "#9696b9", color: "#f8f8f8", strokeWidth: 1.8 })
14774
+ }
14775
+ ),
14776
+ /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14777
+ RotateArrow,
14778
+ {
14779
+ shouldRotate: isOpen,
14780
+ className: cn(
14781
+ isFocused || isOpen ? "text-[var(--chekin-color-brand-blue)]" : "text-[var(--chekin-color-gray-2)]"
14782
+ )
14783
+ }
14784
+ )
14785
+ ] })
14786
+ ]
14787
+ }
14788
+ ),
14789
+ /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14790
+ Fieldset,
14791
+ {
14792
+ isFocused: isFocused || isOpen,
14793
+ invalid: hasInvalidState,
14794
+ isEmpty: isEmpty && !searchValue,
14795
+ isActivated: !isEmpty || isFocused || isOpen || Boolean(searchValue),
14796
+ disabled,
14797
+ loading,
14798
+ readOnly,
14799
+ htmlFor: `${triggerId}-input`,
14800
+ labelId,
14801
+ legend: typeof label === "string" ? label : void 0,
14802
+ label,
14803
+ tooltip,
14804
+ onClick: handleContainerClick
14805
+ }
14806
+ ),
14807
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime158.jsxs)(
14808
+ "div",
14809
+ {
14810
+ className: cn(
14811
+ "absolute left-0 right-0 top-full z-20 overflow-hidden rounded-b-lg bg-white shadow-[0_30px_30px_0_rgba(33,72,255,0.2)]",
14812
+ dropdownClassName
14813
+ ),
14814
+ children: [
14815
+ /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14816
+ SelectMenu,
14817
+ {
14818
+ id: listboxId,
14819
+ options: filteredOptions,
14820
+ labelledBy: labelId,
14821
+ describedBy: describedErrorId,
14822
+ selectedValues,
14823
+ highlightedIndex,
14824
+ onOptionClick: toggleOption,
14825
+ onOptionHover: setHighlightedIndex,
14826
+ disabled: isBlocked,
14827
+ menuClassName,
14828
+ listRef,
14829
+ selectedOptionRef: (index, node) => {
14830
+ optionRefs.current[index] = node;
14831
+ },
14832
+ getOptionId: getOptionId2,
14833
+ noOptionsMessage,
14834
+ isMulti: true
14835
+ }
14836
+ ),
14837
+ canCreateNewOption && /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14838
+ "button",
14839
+ {
14840
+ type: "button",
14841
+ onClick: createOption,
14842
+ className: "flex w-full items-center justify-start border-0 border-t border-[#f2f4f8] bg-white px-4 py-[16px] text-left text-[16px] font-medium leading-5 text-[var(--chekin-color-brand-blue)] outline-none hover:bg-[var(--chekin-color-surface-pressed)]",
14843
+ children: formatCreateLabel(trimmedSearch)
14844
+ }
14845
+ )
14846
+ ]
14847
+ }
14848
+ )
14849
+ ] }),
14850
+ !errorMessage && optional && /* @__PURE__ */ (0, import_jsx_runtime158.jsx)("span", { className: "mt-[1px] block text-left text-[14px] font-medium text-[var(--chekin-color-gray-1)]", children: typeof optional === "string" ? optional : "optional" }),
14851
+ !errorMessage && helperText && /* @__PURE__ */ (0, import_jsx_runtime158.jsx)("span", { className: "mt-[1px] block text-[12px] font-normal text-[var(--chekin-color-gray-1)]", children: helperText }),
14852
+ errorMessage && !hideErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
14853
+ FieldErrorMessage,
14854
+ {
14855
+ id: errorId,
14856
+ message: errorMessage,
14857
+ className: "mt-[1px] text-[14px]"
14858
+ }
14859
+ )
14860
+ ]
14861
+ }
14862
+ );
14863
+ }
14864
+ var DashboardMultiSelect = React56.forwardRef(
14865
+ DashboardMultiSelectInternal
14866
+ );
14867
+
14868
+ // src/dashboard/creatable-multi-select/CreatableMultiSelect.tsx
14869
+ var React57 = __toESM(require("react"), 1);
14870
+ var import_jsx_runtime159 = require("react/jsx-runtime");
14871
+ var DashboardCreatableMultiSelect = React57.forwardRef(
14872
+ function DashboardCreatableMultiSelect2(props, ref) {
14873
+ return /* @__PURE__ */ (0, import_jsx_runtime159.jsx)(DashboardMultiSelect, { ref, ...props, isCreatable: true });
14874
+ }
14875
+ );
14876
+
14877
+ // src/dashboard/infinite-scroll-select/InfiniteScrollSelect.tsx
14878
+ var React58 = __toESM(require("react"), 1);
14879
+ var import_lucide_react49 = require("lucide-react");
14880
+ var import_react_virtual2 = require("@tanstack/react-virtual");
14881
+ var import_jsx_runtime160 = require("react/jsx-runtime");
14882
+ var DEFAULT_ITEM_HEIGHT = 60;
14883
+ var DEFAULT_LIST_HEIGHT = 322;
14884
+ var DEFAULT_OVERSCAN = 5;
14885
+ var DEFAULT_LOAD_MORE_THRESHOLD = 5;
14886
+ function DashboardInfiniteScrollSelectInternal({
14887
+ options = [],
14888
+ value,
14889
+ onChange,
14890
+ onBlur,
14891
+ label,
14892
+ topLabel,
14893
+ placeholder,
14894
+ getValueLabel,
14895
+ disabled,
14896
+ loading,
14897
+ optional,
14898
+ tooltip,
14899
+ error,
14900
+ invalid,
14901
+ hideErrorMessage,
14902
+ className,
14903
+ menuClassName,
14904
+ dropdownClassName,
14905
+ name,
14906
+ width,
14907
+ noOptionsMessage,
14908
+ searchable = true,
14909
+ searchPlaceholder,
14910
+ filterOption = defaultFilterOption,
14911
+ helperText,
14912
+ canLoadMore,
14913
+ isLoadingMore,
14914
+ loadMoreItems,
14915
+ loadingMoreText = "Loading\u2026",
14916
+ onSearchChange,
14917
+ itemHeight = DEFAULT_ITEM_HEIGHT,
14918
+ listHeight = DEFAULT_LIST_HEIGHT,
14919
+ overscan = DEFAULT_OVERSCAN,
14920
+ loadMoreThreshold = DEFAULT_LOAD_MORE_THRESHOLD
14921
+ }, ref) {
14922
+ const containerRef = React58.useRef(null);
14923
+ const triggerRef = React58.useRef(null);
14924
+ const searchInputRef = React58.useRef(null);
14925
+ const scrollRef = React58.useRef(null);
14926
+ const [isOpen, setIsOpen] = React58.useState(false);
14927
+ const [searchValue, setSearchValue] = React58.useState("");
14928
+ const [highlightedIndex, setHighlightedIndex] = React58.useState(-1);
14929
+ const hasValue = Boolean(value);
14930
+ const isEmpty = !hasValue;
14931
+ const isBlocked = Boolean(disabled) || Boolean(loading);
14932
+ const triggerError = error ?? invalid;
14933
+ const hasInvalidState = Boolean(triggerError);
14934
+ const errorMessage = typeof error === "string" ? error : void 0;
14935
+ const wrapperWidth = toCssSize(width);
14936
+ const valueLabel = value ? getValueLabel?.(value) ?? String(value.label) : void 0;
14937
+ const { triggerId, labelId, valueId, listboxId, describedErrorId, errorId, getOptionId: getOptionId2 } = useSelectIds2({ name, hasValue, error, hideErrorMessage });
14938
+ const filteredOptions = React58.useMemo(() => {
14939
+ if (!searchable || !searchValue) return options;
14940
+ return options.filter((option) => filterOption(option, searchValue));
14941
+ }, [options, searchable, searchValue, filterOption]);
14942
+ const itemCount = filteredOptions.length + (canLoadMore || isLoadingMore ? 1 : 0);
14943
+ const virtualizer = (0, import_react_virtual2.useVirtualizer)({
14944
+ count: itemCount,
14945
+ getScrollElement: () => scrollRef.current,
14946
+ estimateSize: () => itemHeight,
14947
+ overscan
14948
+ });
14949
+ React58.useImperativeHandle(ref, () => triggerRef.current, []);
14950
+ useOutsideClick({
14951
+ elementRef: containerRef,
14952
+ onOutsideClick: () => setIsOpen(false),
14953
+ isDisabled: !isOpen
14954
+ });
14955
+ React58.useEffect(() => {
14956
+ if (isBlocked) setIsOpen(false);
14957
+ }, [isBlocked]);
14958
+ React58.useEffect(() => {
14959
+ if (!isOpen) {
14960
+ setSearchValue("");
14961
+ setHighlightedIndex(-1);
14962
+ return;
14963
+ }
14964
+ const selectedIndex = getOptionIndex2(filteredOptions, value);
14965
+ setHighlightedIndex(
14966
+ selectedIndex >= 0 ? selectedIndex : getFirstEnabledOptionIndex2(filteredOptions)
14967
+ );
14968
+ if (searchable) {
14969
+ const frame = window.requestAnimationFrame(() => searchInputRef.current?.focus());
14970
+ return () => window.cancelAnimationFrame(frame);
14971
+ }
14972
+ }, [isOpen, filteredOptions, searchable, value]);
14973
+ const virtualItems = virtualizer.getVirtualItems();
14974
+ React58.useEffect(() => {
14975
+ if (!isOpen || !canLoadMore || isLoadingMore || !loadMoreItems) return;
14976
+ if (virtualItems.length === 0) return;
14977
+ const lastItem = virtualItems[virtualItems.length - 1];
14978
+ if (lastItem && lastItem.index >= filteredOptions.length - loadMoreThreshold) {
14979
+ loadMoreItems();
14980
+ }
14981
+ }, [
14982
+ canLoadMore,
14983
+ filteredOptions.length,
14984
+ isLoadingMore,
14985
+ isOpen,
14986
+ loadMoreItems,
14987
+ loadMoreThreshold,
14988
+ virtualItems
14989
+ ]);
14990
+ React58.useEffect(() => {
14991
+ if (!isOpen || highlightedIndex < 0) return;
14992
+ virtualizer.scrollToIndex(highlightedIndex, { align: "auto" });
14993
+ }, [highlightedIndex, isOpen, virtualizer]);
14994
+ const toggleMenu = () => {
14995
+ if (isBlocked) return;
14996
+ setIsOpen((prev) => !prev);
14997
+ };
14998
+ const handleSelect = (option) => {
14999
+ if (option.isDisabled) return;
15000
+ onChange(option);
15001
+ setIsOpen(false);
15002
+ triggerRef.current?.focus();
15003
+ };
15004
+ const handleTriggerKeyDown = (event) => {
15005
+ if (isBlocked) return;
15006
+ if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Enter" || event.key === " ") {
15007
+ event.preventDefault();
15008
+ setIsOpen(true);
15009
+ }
15010
+ };
15011
+ const handleSearchKeyDown = (event) => {
15012
+ if (event.key === "ArrowDown") {
15013
+ event.preventDefault();
15014
+ const next = getNextEnabledOptionIndex2(filteredOptions, highlightedIndex + 1, 1);
15015
+ if (next >= 0) setHighlightedIndex(next);
15016
+ return;
15017
+ }
15018
+ if (event.key === "ArrowUp") {
15019
+ event.preventDefault();
15020
+ const next = getNextEnabledOptionIndex2(filteredOptions, highlightedIndex - 1, -1);
15021
+ if (next >= 0) setHighlightedIndex(next);
15022
+ return;
15023
+ }
15024
+ if (event.key === "Enter") {
15025
+ event.preventDefault();
15026
+ const option = filteredOptions[highlightedIndex];
15027
+ if (option && !option.isDisabled) handleSelect(option);
15028
+ return;
15029
+ }
15030
+ if (event.key === "Escape") {
15031
+ event.preventDefault();
15032
+ setIsOpen(false);
15033
+ triggerRef.current?.focus();
15034
+ return;
15035
+ }
15036
+ if (event.key === "Tab") {
15037
+ setIsOpen(false);
15038
+ }
15039
+ };
15040
+ const handleSearchChange = (event) => {
15041
+ const next = event.target.value;
15042
+ setSearchValue(next);
15043
+ onSearchChange?.(next);
15044
+ };
15045
+ const emptyMessage = noOptionsMessage?.();
15046
+ const totalSize = virtualizer.getTotalSize();
15047
+ const measuredListHeight = Math.min(listHeight, Math.max(totalSize, itemHeight));
15048
+ return /* @__PURE__ */ (0, import_jsx_runtime160.jsxs)(
15049
+ "div",
15050
+ {
15051
+ ref: containerRef,
15052
+ className: cn(
15053
+ "relative w-full max-w-[var(--max-field-width)]",
15054
+ disabled && "cursor-not-allowed opacity-50",
15055
+ loading && "cursor-progress",
15056
+ className
15057
+ ),
15058
+ style: wrapperWidth ? { width: wrapperWidth } : void 0,
15059
+ children: [
15060
+ name && /* @__PURE__ */ (0, import_jsx_runtime160.jsx)("input", { type: "hidden", name, value: value ? String(value.value) : "" }),
15061
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsxs)("div", { className: "relative min-h-[68px] w-full", children: [
15062
+ topLabel && /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(
15063
+ "label",
15064
+ {
15065
+ htmlFor: triggerId,
15066
+ className: "mb-2 block text-[14px] font-medium text-[var(--chekin-color-brand-navy)]",
15067
+ children: topLabel
15068
+ }
15069
+ ),
15070
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsxs)("div", { className: "relative w-full", children: [
15071
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsxs)(
15072
+ "button",
15073
+ {
15074
+ id: triggerId,
15075
+ ref: triggerRef,
15076
+ type: "button",
15077
+ "aria-haspopup": "listbox",
15078
+ "aria-expanded": isOpen,
15079
+ "aria-controls": listboxId,
15080
+ "aria-labelledby": hasValue && valueId ? `${labelId} ${valueId}` : labelId,
15081
+ "aria-describedby": describedErrorId,
15082
+ "aria-invalid": hasInvalidState,
15083
+ "aria-busy": loading,
15084
+ disabled: isBlocked,
15085
+ onClick: toggleMenu,
15086
+ onKeyDown: handleTriggerKeyDown,
15087
+ onBlur,
15088
+ className: cn(
15089
+ "relative m-0 box-border flex h-12 w-full cursor-pointer items-center justify-between gap-2 rounded-[6px] border-0 px-4 text-left text-[16px] font-medium leading-5 outline-none transition-colors duration-200",
15090
+ isEmpty ? "bg-[var(--chekin-color-surface-input-empty)] text-[var(--chekin-color-gray-1)]" : "bg-transparent text-[var(--chekin-color-brand-navy)]",
15091
+ disabled && "cursor-not-allowed opacity-50",
15092
+ loading && "cursor-progress"
15093
+ ),
15094
+ children: [
15095
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsx)("span", { id: valueId, className: "block min-w-0 flex-1 truncate text-left", children: valueLabel ?? placeholder ?? label }),
15096
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsxs)("span", { className: "pointer-events-none flex items-center gap-2 text-[var(--chekin-color-gray-2)]", children: [
15097
+ loading && /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(ThreeDotsLoader, { height: 18, width: 18 }),
15098
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(
15099
+ import_lucide_react49.ChevronDown,
15100
+ {
15101
+ size: 16,
15102
+ className: cn(
15103
+ "transition-transform duration-200",
15104
+ isOpen && "rotate-180 text-[var(--chekin-color-brand-blue)]"
15105
+ )
15106
+ }
15107
+ )
15108
+ ] })
15109
+ ]
15110
+ }
15111
+ ),
15112
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(
15113
+ Fieldset,
15114
+ {
15115
+ isFocused: isOpen,
15116
+ invalid: hasInvalidState,
15117
+ isEmpty,
15118
+ isActivated: !isEmpty || isOpen,
15119
+ disabled,
15120
+ loading,
15121
+ htmlFor: triggerId,
15122
+ labelId,
15123
+ legend: typeof label === "string" ? label : void 0,
15124
+ label,
15125
+ tooltip,
15126
+ onClick: !isBlocked ? toggleMenu : void 0
15127
+ }
15128
+ ),
15129
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime160.jsxs)(
15130
+ "div",
15131
+ {
15132
+ className: cn(
15133
+ "absolute left-0 right-0 top-full z-20 overflow-hidden rounded-b-lg bg-white shadow-[0_30px_30px_0_rgba(33,72,255,0.2)]",
15134
+ dropdownClassName
15135
+ ),
15136
+ children: [
15137
+ searchable && /* @__PURE__ */ (0, import_jsx_runtime160.jsx)("div", { className: "border-b border-[#f2f4f8] px-4 pb-2 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(
15138
+ "input",
15139
+ {
15140
+ ref: searchInputRef,
15141
+ type: "text",
15142
+ value: searchValue,
15143
+ placeholder: searchPlaceholder,
15144
+ onChange: handleSearchChange,
15145
+ onKeyDown: handleSearchKeyDown,
15146
+ autoComplete: "off",
15147
+ "aria-controls": listboxId,
15148
+ "aria-activedescendant": highlightedIndex >= 0 ? getOptionId2(highlightedIndex) : void 0,
15149
+ className: "m-0 box-border h-9 w-full rounded-md border border-[var(--chekin-color-gray-3)] bg-white px-3 text-[16px] font-medium text-[var(--chekin-color-brand-navy)] outline-none transition-colors placeholder:text-[var(--chekin-color-gray-1)] focus:border-[var(--chekin-color-brand-blue)]"
15150
+ }
15151
+ ) }),
15152
+ itemCount === 0 ? /* @__PURE__ */ (0, import_jsx_runtime160.jsx)("div", { className: "px-4 py-[20px] text-left text-[16px] text-[var(--chekin-color-brand-navy)]", children: emptyMessage ?? "No options" }) : /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(
15153
+ "div",
15154
+ {
15155
+ ref: scrollRef,
15156
+ className: cn("overflow-y-auto", menuClassName),
15157
+ style: { height: `${measuredListHeight}px` },
15158
+ children: /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(
15159
+ "div",
15160
+ {
15161
+ id: listboxId,
15162
+ role: "listbox",
15163
+ tabIndex: -1,
15164
+ "aria-labelledby": labelId,
15165
+ "aria-describedby": describedErrorId,
15166
+ "aria-activedescendant": highlightedIndex >= 0 ? getOptionId2(highlightedIndex) : void 0,
15167
+ className: "relative w-full",
15168
+ style: { height: `${totalSize}px` },
15169
+ children: virtualItems.map((virtualItem) => {
15170
+ const isLoaderRow = virtualItem.index >= filteredOptions.length;
15171
+ const option = filteredOptions[virtualItem.index];
15172
+ const isSelected = !isLoaderRow && option ? option.value === value?.value : false;
15173
+ const isHighlighted = virtualItem.index === highlightedIndex;
15174
+ const isOptionDisabled = Boolean(isBlocked || option?.isDisabled);
15175
+ return /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(
15176
+ "div",
15177
+ {
15178
+ "data-index": virtualItem.index,
15179
+ className: "absolute left-0 top-0 w-full",
15180
+ style: {
15181
+ height: `${virtualItem.size}px`,
15182
+ transform: `translateY(${virtualItem.start}px)`
15183
+ },
15184
+ children: isLoaderRow ? /* @__PURE__ */ (0, import_jsx_runtime160.jsxs)("div", { className: "flex h-full items-center justify-center gap-2 px-4 text-[14px] font-medium text-[var(--chekin-color-gray-1)]", children: [
15185
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(ThreeDotsLoader, { height: 18, width: 18 }),
15186
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsx)("span", { children: loadingMoreText })
15187
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime160.jsxs)(
15188
+ "button",
15189
+ {
15190
+ id: getOptionId2(virtualItem.index),
15191
+ type: "button",
15192
+ role: "option",
15193
+ "aria-selected": isSelected,
15194
+ "aria-disabled": isOptionDisabled,
15195
+ tabIndex: -1,
15196
+ disabled: isOptionDisabled,
15197
+ onClick: () => option && handleSelect(option),
15198
+ onMouseMove: () => setHighlightedIndex(virtualItem.index),
15199
+ className: cn(
15200
+ "flex h-full w-full items-start justify-between border-0 border-b border-[#f2f4f8] bg-white px-4 text-left text-[16px] font-medium leading-5 text-[var(--chekin-color-brand-navy)] outline-none transition-colors",
15201
+ isHighlighted && !isSelected && "cursor-pointer text-[var(--chekin-color-brand-blue)]",
15202
+ isSelected && "cursor-default font-bold text-[var(--chekin-color-brand-navy)]",
15203
+ isOptionDisabled && "cursor-default opacity-30"
15204
+ ),
15205
+ children: [
15206
+ /* @__PURE__ */ (0, import_jsx_runtime160.jsx)("span", { className: "block break-words", children: option?.label }),
15207
+ option?.description && /* @__PURE__ */ (0, import_jsx_runtime160.jsx)("span", { className: "ml-2 mt-[3px] shrink-0 text-[12px] font-bold italic text-[#777e91]", children: option.description })
15208
+ ]
15209
+ }
15210
+ )
15211
+ },
15212
+ virtualItem.key
15213
+ );
15214
+ })
15215
+ }
15216
+ )
15217
+ }
15218
+ )
15219
+ ]
15220
+ }
15221
+ )
15222
+ ] }),
15223
+ !errorMessage && optional && /* @__PURE__ */ (0, import_jsx_runtime160.jsx)("span", { className: "mt-[1px] block text-left text-[14px] font-medium text-[var(--chekin-color-gray-1)]", children: typeof optional === "string" ? optional : "optional" }),
15224
+ !errorMessage && helperText && /* @__PURE__ */ (0, import_jsx_runtime160.jsx)("span", { className: "mt-[1px] block text-[12px] font-normal text-[var(--chekin-color-gray-1)]", children: helperText }),
15225
+ errorMessage && !hideErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime160.jsx)(
15226
+ FieldErrorMessage,
15227
+ {
15228
+ id: errorId,
15229
+ message: errorMessage,
15230
+ className: "mt-[1px] text-[14px]"
15231
+ }
15232
+ )
15233
+ ] })
15234
+ ]
15235
+ }
15236
+ );
15237
+ }
15238
+ var DashboardInfiniteScrollSelect = React58.forwardRef(
15239
+ DashboardInfiniteScrollSelectInternal
15240
+ );
15241
+
15242
+ // src/searchable-select/SearchableSelect.tsx
15243
+ var React59 = __toESM(require("react"), 1);
15244
+ var import_lucide_react50 = require("lucide-react");
15245
+ var import_react_virtual3 = require("@tanstack/react-virtual");
15246
+ var import_react82 = require("react");
15247
+ var import_jsx_runtime161 = require("react/jsx-runtime");
15248
+ var ROW_HEIGHT = 48;
15249
+ var DESKTOP_LIST_HEIGHT = 280;
15250
+ var MOBILE_LIST_HEIGHT = 420;
15251
+ var LOAD_MORE_THRESHOLD = 6;
15252
+ function defaultFilter(option, searchValue) {
15253
+ return String(option.label).toLowerCase().includes(searchValue.trim().toLowerCase());
15254
+ }
15255
+ var SearchableSelectInternal = ({
15256
+ options,
15257
+ value,
15258
+ onChange,
15259
+ onBlur,
15260
+ onOpenChange,
15261
+ searchValue,
15262
+ onSearchChange,
15263
+ filterOption = defaultFilter,
15264
+ loading,
15265
+ hasNextPage,
15266
+ onLoadMore,
15267
+ variant = "default",
15268
+ label,
15269
+ topLabel,
15270
+ placeholder,
15271
+ searchPlaceholder = "Search...",
15272
+ mobileTitle,
15273
+ getValueLabel,
15274
+ disabled,
15275
+ error,
15276
+ invalid,
15277
+ optional,
15278
+ tooltip,
15279
+ hideErrorMessage,
15280
+ name,
15281
+ className,
15282
+ dropdownClassName,
15283
+ menuClassName,
15284
+ noOptionsMessage,
15285
+ loadingMessage
15286
+ }, ref) => {
15287
+ const { isMatch: isMobile2 } = useScreenResize(DEVICE.mobileXL);
15288
+ const reactId = React59.useId();
15289
+ const [open, setOpen] = React59.useState(false);
15290
+ const [internalSearchValue, setInternalSearchValue] = React59.useState("");
15291
+ const [highlightedIndex, setHighlightedIndex] = React59.useState(-1);
15292
+ const containerRef = React59.useRef(null);
15293
+ const triggerRef = React59.useRef(null);
15294
+ const inputRef = React59.useRef(null);
15295
+ const listboxId = `${reactId}-listbox`;
15296
+ const labelId = `${reactId}-label`;
15297
+ const valueId = `${reactId}-value`;
15298
+ const helperTextId = `${reactId}-helper`;
15299
+ const errorId = `${reactId}-error`;
15300
+ const searchInputId = `${reactId}-search`;
15301
+ const effectiveSearchValue = searchValue ?? internalSearchValue;
15302
+ const shouldFilterLocally = !onSearchChange && filterOption !== null;
15303
+ const visibleOptions = React59.useMemo(() => {
15304
+ if (!shouldFilterLocally || !effectiveSearchValue) {
15305
+ return options;
15306
+ }
15307
+ return options.filter((option) => filterOption(option, effectiveSearchValue));
15308
+ }, [effectiveSearchValue, filterOption, options, shouldFilterLocally]);
15309
+ const selectedIndex = React59.useMemo(
15310
+ () => visibleOptions.findIndex((option) => option.value === value?.value),
15311
+ [value?.value, visibleOptions]
15312
+ );
15313
+ const helperText = placeholder ?? label;
15314
+ const valueLabel = value ? getValueLabel?.(value) ?? String(value.label) : void 0;
15315
+ const isBlocked = Boolean(disabled) || Boolean(loading);
15316
+ const triggerError = error ?? invalid;
15317
+ const describedBy = error && !hideErrorMessage ? errorId : void 0;
15318
+ const activeOptionId = highlightedIndex >= 0 ? getOptionId(reactId, highlightedIndex) : void 0;
15319
+ useOutsideClick({
15320
+ elementRef: containerRef,
15321
+ onOutsideClick: () => closeSelect(),
15322
+ isDisabled: !open || isMobile2
15323
+ });
15324
+ const handleOnOpenChange = useEvent(onOpenChange);
15325
+ const setSelectOpen = (0, import_react82.useCallback)(
15326
+ (nextOpen, options2) => {
15327
+ setOpen(nextOpen);
15328
+ handleOnOpenChange?.(nextOpen);
15329
+ if (!nextOpen && options2?.restoreFocus) {
15330
+ triggerRef.current?.focus();
15331
+ }
15332
+ },
15333
+ [handleOnOpenChange]
15334
+ );
15335
+ React59.useEffect(() => {
15336
+ if (isBlocked) {
15337
+ setSelectOpen(false);
15338
+ return;
15339
+ }
15340
+ if (!open) return;
15341
+ const frameId = window.requestAnimationFrame(() => {
15342
+ inputRef.current?.focus();
15343
+ });
15344
+ return () => {
15345
+ window.cancelAnimationFrame(frameId);
15346
+ };
15347
+ }, [isBlocked, open, setSelectOpen]);
15348
+ React59.useEffect(() => {
15349
+ if (!open) {
15350
+ setHighlightedIndex(-1);
15351
+ return;
15352
+ }
15353
+ setHighlightedIndex((currentIndex) => {
15354
+ if (currentIndex >= 0 && currentIndex < visibleOptions.length && !visibleOptions[currentIndex]?.isDisabled) {
15355
+ return currentIndex;
15356
+ }
15357
+ return selectedIndex >= 0 ? selectedIndex : getFirstEnabledIndex(visibleOptions);
15358
+ });
15359
+ }, [open, selectedIndex, visibleOptions]);
15360
+ function openSelect() {
15361
+ if (isBlocked) return;
15362
+ setSelectOpen(true);
15363
+ }
15364
+ function closeSelect() {
15365
+ setSelectOpen(false, { restoreFocus: true });
15366
+ }
15367
+ function handleSearchChange(nextValue) {
15368
+ if (!onSearchChange) {
15369
+ setInternalSearchValue(nextValue);
15370
+ }
15371
+ onSearchChange?.(nextValue);
15372
+ }
15373
+ function handleSelect(option) {
15374
+ if (isBlocked || option.isDisabled) return;
15375
+ onChange(option);
15376
+ setSelectOpen(false, { restoreFocus: true });
15377
+ }
15378
+ function moveHighlight(step) {
15379
+ const startIndex = highlightedIndex >= 0 ? highlightedIndex + step : step === 1 ? 0 : visibleOptions.length - 1;
15380
+ const nextIndex = getNextEnabledIndex(visibleOptions, startIndex, step);
15381
+ if (nextIndex >= 0) {
15382
+ setHighlightedIndex(nextIndex);
15383
+ }
15384
+ }
15385
+ function handleTriggerKeyDown(event) {
15386
+ if (isBlocked) return;
15387
+ if (event.key === "Enter" || event.key === " " || event.key === "ArrowDown" || event.key === "ArrowUp") {
15388
+ event.preventDefault();
15389
+ openSelect();
15390
+ }
15391
+ }
15392
+ function handleSearchKeyDown(event) {
15393
+ if (event.key === "Escape") {
15394
+ event.preventDefault();
15395
+ closeSelect();
15396
+ return;
15397
+ }
15398
+ if (event.key === "ArrowDown") {
15399
+ event.preventDefault();
15400
+ moveHighlight(1);
15401
+ return;
15402
+ }
15403
+ if (event.key === "ArrowUp") {
15404
+ event.preventDefault();
15405
+ moveHighlight(-1);
15406
+ return;
15407
+ }
15408
+ if (event.key === "Enter") {
15409
+ event.preventDefault();
15410
+ const option = visibleOptions[highlightedIndex];
15411
+ if (option) {
15412
+ handleSelect(option);
15413
+ }
15414
+ }
15415
+ }
15416
+ const content = /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
15417
+ SearchableSelectContent,
15418
+ {
15419
+ inputId: searchInputId,
15420
+ listboxId,
15421
+ labelId,
15422
+ activeOptionId,
15423
+ inputRef,
15424
+ options: visibleOptions,
15425
+ value,
15426
+ searchValue: effectiveSearchValue,
15427
+ searchPlaceholder,
15428
+ highlightedIndex,
15429
+ loading,
15430
+ hasNextPage,
15431
+ onLoadMore,
15432
+ menuClassName,
15433
+ noOptionsMessage,
15434
+ loadingMessage,
15435
+ height: isMobile2 ? MOBILE_LIST_HEIGHT : DESKTOP_LIST_HEIGHT,
15436
+ idPrefix: reactId,
15437
+ onSearchChange: handleSearchChange,
15438
+ onSearchKeyDown: handleSearchKeyDown,
15439
+ onOptionClick: handleSelect,
15440
+ onOptionHover: setHighlightedIndex
15441
+ }
15442
+ );
15443
+ React59.useImperativeHandle(ref, () => triggerRef.current, []);
15444
+ return /* @__PURE__ */ (0, import_jsx_runtime161.jsxs)("div", { ref: containerRef, className: cn("relative w-full max-w-[425px]", className), children: [
15445
+ name && /* @__PURE__ */ (0, import_jsx_runtime161.jsx)("input", { type: "hidden", name, value: value ? String(value.value) : "" }),
15446
+ /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
15447
+ FieldTrigger,
15448
+ {
15449
+ id: `${reactId}-trigger`,
15450
+ ref: triggerRef,
15451
+ variant,
15452
+ "aria-haspopup": "listbox",
15453
+ "aria-expanded": open,
15454
+ "aria-controls": listboxId,
15455
+ label,
15456
+ topLabel,
15457
+ labelId,
15458
+ valueId,
15459
+ helperTextId,
15460
+ errorId: error ? errorId : void 0,
15461
+ labelText: topLabel ? helperText : void 0,
15462
+ valueText: valueLabel,
15463
+ placeholder: helperText,
15464
+ describedBy,
15465
+ error: triggerError,
15466
+ loading,
15467
+ optional,
15468
+ tooltip,
15469
+ forceLabelText: Boolean(optional) || Boolean(tooltip),
15470
+ hideErrorMessage,
15471
+ disabled,
15472
+ onClick: () => {
15473
+ if (open) {
15474
+ closeSelect();
15475
+ return;
15476
+ }
15477
+ openSelect();
15478
+ },
15479
+ onKeyDown: handleTriggerKeyDown,
15480
+ onBlur,
15481
+ trailingAdornment: /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
15482
+ import_lucide_react50.ChevronDown,
15483
+ {
15484
+ className: cn(
15485
+ "h-6 w-6 text-[#1F1F1B] transition-transform",
15486
+ open && "rotate-180"
15487
+ )
15488
+ }
15489
+ )
15490
+ }
15491
+ ),
15492
+ isMobile2 ? /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
15493
+ Drawer,
15494
+ {
15495
+ open,
15496
+ onOpenChange: (nextOpen) => {
13900
15497
  if (isBlocked && nextOpen) return;
13901
15498
  if (nextOpen) {
13902
15499
  setSelectOpen(true);
@@ -13904,13 +15501,13 @@ var SearchableSelectInternal = ({
13904
15501
  }
13905
15502
  closeSelect();
13906
15503
  },
13907
- children: /* @__PURE__ */ (0, import_jsx_runtime154.jsxs)(DrawerContent, { onClose: closeSelect, lockScroll: false, children: [
13908
- /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(DrawerTitle, { className: "sr-only", children: mobileTitle ?? label }),
13909
- /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(DrawerDescription, { className: "sr-only", children: label }),
13910
- /* @__PURE__ */ (0, import_jsx_runtime154.jsx)("div", { className: "px-5 pb-5 pt-1", children: content })
15504
+ children: /* @__PURE__ */ (0, import_jsx_runtime161.jsxs)(DrawerContent, { onClose: closeSelect, lockScroll: false, children: [
15505
+ /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(DrawerTitle, { className: "sr-only", children: mobileTitle ?? label }),
15506
+ /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(DrawerDescription, { className: "sr-only", children: label }),
15507
+ /* @__PURE__ */ (0, import_jsx_runtime161.jsx)("div", { className: "px-5 pb-5 pt-1", children: content })
13911
15508
  ] })
13912
15509
  }
13913
- ) : open ? /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
15510
+ ) : open ? /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
13914
15511
  "div",
13915
15512
  {
13916
15513
  className: cn(
@@ -13922,7 +15519,7 @@ var SearchableSelectInternal = ({
13922
15519
  ) : null
13923
15520
  ] });
13924
15521
  };
13925
- var SearchableSelect = React53.forwardRef(
15522
+ var SearchableSelect = React59.forwardRef(
13926
15523
  SearchableSelectInternal
13927
15524
  );
13928
15525
  function SearchableSelectContent({
@@ -13949,11 +15546,11 @@ function SearchableSelectContent({
13949
15546
  onOptionClick,
13950
15547
  onOptionHover
13951
15548
  }) {
13952
- const listRef = React53.useRef(null);
13953
- const lastLoadMoreOptionsLengthRef = React53.useRef(null);
13954
- const previousHighlightedIndexRef = React53.useRef(highlightedIndex);
15549
+ const listRef = React59.useRef(null);
15550
+ const lastLoadMoreOptionsLengthRef = React59.useRef(null);
15551
+ const previousHighlightedIndexRef = React59.useRef(highlightedIndex);
13955
15552
  const rowCount = options.length + (loading && options.length > 0 ? 1 : 0);
13956
- const virtualizer = (0, import_react_virtual2.useVirtualizer)({
15553
+ const virtualizer = (0, import_react_virtual3.useVirtualizer)({
13957
15554
  count: rowCount,
13958
15555
  getScrollElement: () => listRef.current,
13959
15556
  estimateSize: () => ROW_HEIGHT,
@@ -13962,7 +15559,7 @@ function SearchableSelectContent({
13962
15559
  const virtualItems = virtualizer.getVirtualItems();
13963
15560
  const emptyMessage = noOptionsMessage?.() ?? "No matches found";
13964
15561
  const loadingText = loadingMessage?.() ?? "Loading...";
13965
- React53.useEffect(() => {
15562
+ React59.useEffect(() => {
13966
15563
  const lastItem = virtualItems[virtualItems.length - 1];
13967
15564
  const shouldLoadMore = !!lastItem && hasNextPage && !loading && lastItem.index >= options.length - LOAD_MORE_THRESHOLD;
13968
15565
  if (shouldLoadMore && lastLoadMoreOptionsLengthRef.current !== options.length) {
@@ -13970,23 +15567,23 @@ function SearchableSelectContent({
13970
15567
  onLoadMore?.();
13971
15568
  }
13972
15569
  }, [hasNextPage, loading, onLoadMore, options.length, virtualItems]);
13973
- React53.useEffect(() => {
15570
+ React59.useEffect(() => {
13974
15571
  const hasHighlightedIndexChanged = previousHighlightedIndexRef.current !== highlightedIndex;
13975
15572
  previousHighlightedIndexRef.current = highlightedIndex;
13976
15573
  if (highlightedIndex >= 0 && hasHighlightedIndexChanged) {
13977
15574
  virtualizer.scrollToIndex(highlightedIndex, { align: "auto" });
13978
15575
  }
13979
15576
  }, [highlightedIndex, virtualizer]);
13980
- return /* @__PURE__ */ (0, import_jsx_runtime154.jsxs)("div", { className: "p-2", children: [
13981
- /* @__PURE__ */ (0, import_jsx_runtime154.jsxs)("div", { className: "relative mb-2", children: [
13982
- /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
13983
- import_lucide_react46.Search,
15577
+ return /* @__PURE__ */ (0, import_jsx_runtime161.jsxs)("div", { className: "p-2", children: [
15578
+ /* @__PURE__ */ (0, import_jsx_runtime161.jsxs)("div", { className: "relative mb-2", children: [
15579
+ /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
15580
+ import_lucide_react50.Search,
13984
15581
  {
13985
15582
  "aria-hidden": "true",
13986
15583
  className: "absolute left-4 top-1/2 h-5 w-5 -translate-y-1/2 text-[#9696B9]"
13987
15584
  }
13988
15585
  ),
13989
- /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
15586
+ /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
13990
15587
  "input",
13991
15588
  {
13992
15589
  id: inputId,
@@ -14005,7 +15602,7 @@ function SearchableSelectContent({
14005
15602
  }
14006
15603
  )
14007
15604
  ] }),
14008
- loading && options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime154.jsx)("div", { className: "px-4 py-5 text-center text-base leading-6 text-[#6C6C6C]", children: loadingText }) : options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime154.jsx)("div", { className: "px-4 py-5 text-center text-base leading-6 text-[#6C6C6C]", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
15605
+ loading && options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime161.jsx)("div", { className: "px-4 py-5 text-center text-base leading-6 text-[#6C6C6C]", children: loadingText }) : options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime161.jsx)("div", { className: "px-4 py-5 text-center text-base leading-6 text-[#6C6C6C]", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
14009
15606
  "div",
14010
15607
  {
14011
15608
  id: listboxId,
@@ -14014,7 +15611,7 @@ function SearchableSelectContent({
14014
15611
  "aria-labelledby": labelId,
14015
15612
  className: cn("overflow-y-auto outline-none", menuClassName),
14016
15613
  style: { height: Math.min(height, rowCount * ROW_HEIGHT) },
14017
- children: /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
15614
+ children: /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
14018
15615
  "div",
14019
15616
  {
14020
15617
  className: "relative w-full",
@@ -14022,7 +15619,7 @@ function SearchableSelectContent({
14022
15619
  children: virtualItems.map((virtualItem) => {
14023
15620
  const option = options[virtualItem.index];
14024
15621
  if (!option) {
14025
- return /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
15622
+ return /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
14026
15623
  "div",
14027
15624
  {
14028
15625
  className: "absolute left-0 top-0 flex w-full items-center px-4 text-base leading-6 text-[#6C6C6C]",
@@ -14037,7 +15634,7 @@ function SearchableSelectContent({
14037
15634
  }
14038
15635
  const isSelected = value?.value === option.value;
14039
15636
  const isHighlighted = virtualItem.index === highlightedIndex;
14040
- return /* @__PURE__ */ (0, import_jsx_runtime154.jsx)(
15637
+ return /* @__PURE__ */ (0, import_jsx_runtime161.jsx)(
14041
15638
  "button",
14042
15639
  {
14043
15640
  id: getOptionId(idPrefix, virtualItem.index),
@@ -14059,7 +15656,7 @@ function SearchableSelectContent({
14059
15656
  height: `${virtualItem.size}px`,
14060
15657
  transform: `translateY(${virtualItem.start}px)`
14061
15658
  },
14062
- children: /* @__PURE__ */ (0, import_jsx_runtime154.jsx)("span", { className: "truncate text-center", children: String(option.label) })
15659
+ children: /* @__PURE__ */ (0, import_jsx_runtime161.jsx)("span", { className: "truncate text-center", children: String(option.label) })
14063
15660
  },
14064
15661
  `${String(option.value)}-${virtualItem.index}`
14065
15662
  );
@@ -14145,14 +15742,14 @@ function getErrorMessage(error) {
14145
15742
 
14146
15743
  // src/lib/toastResponseError.tsx
14147
15744
  var import_i18next = __toESM(require("i18next"), 1);
14148
- var import_jsx_runtime155 = require("react/jsx-runtime");
15745
+ var import_jsx_runtime162 = require("react/jsx-runtime");
14149
15746
  function addSupportEmailToMessage(message, prefixText) {
14150
15747
  if (typeof message !== "string") {
14151
15748
  return message;
14152
15749
  }
14153
15750
  const builtMessage = `${prefixText ? `${prefixText} ` : ""}${message}`;
14154
- return /* @__PURE__ */ (0, import_jsx_runtime155.jsxs)("div", { children: [
14155
- /* @__PURE__ */ (0, import_jsx_runtime155.jsx)("div", { children: builtMessage }),
15751
+ return /* @__PURE__ */ (0, import_jsx_runtime162.jsxs)("div", { children: [
15752
+ /* @__PURE__ */ (0, import_jsx_runtime162.jsx)("div", { children: builtMessage }),
14156
15753
  import_i18next.default.t("reach_us_at_email")
14157
15754
  ] });
14158
15755
  }
@@ -14214,6 +15811,11 @@ function toastResponseError(error, options = {}) {
14214
15811
  CopyString,
14215
15812
  CustomCheckboxDropdownGroup,
14216
15813
  DEVICE_BREAKPOINTS,
15814
+ DashboardCreatableMultiSelect,
15815
+ DashboardInfiniteScrollSelect,
15816
+ DashboardInput,
15817
+ DashboardMultiSelect,
15818
+ DashboardSelect,
14217
15819
  DataTable,
14218
15820
  DatePicker,
14219
15821
  DateTableFilter,