@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 +1876 -274
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +180 -11
- package/dist/index.d.ts +180 -11
- package/dist/index.js +1875 -278
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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-
|
|
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-[
|
|
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:
|
|
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-
|
|
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
|
|
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 =
|
|
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/
|
|
13665
|
+
// src/dashboard/input/Input.tsx
|
|
13646
13666
|
var React53 = __toESM(require("react"), 1);
|
|
13647
13667
|
var import_lucide_react46 = require("lucide-react");
|
|
13648
|
-
|
|
13649
|
-
|
|
13668
|
+
|
|
13669
|
+
// src/dashboard/_fieldset/Fieldset.tsx
|
|
13650
13670
|
var import_jsx_runtime154 = require("react/jsx-runtime");
|
|
13651
|
-
|
|
13652
|
-
|
|
13653
|
-
|
|
13654
|
-
|
|
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
|
-
|
|
13676
|
+
label,
|
|
13681
13677
|
tooltip,
|
|
13682
|
-
|
|
13683
|
-
|
|
13678
|
+
legend,
|
|
13679
|
+
onClick,
|
|
13680
|
+
htmlFor,
|
|
13681
|
+
labelId,
|
|
13682
|
+
readOnly,
|
|
13683
|
+
loading,
|
|
13684
|
+
disabled,
|
|
13684
13685
|
className,
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
|
|
13694
|
-
|
|
13695
|
-
|
|
13696
|
-
|
|
13697
|
-
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13715
|
-
|
|
13716
|
-
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
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
|
-
|
|
13731
|
+
"fieldset",
|
|
13851
13732
|
{
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
13860
|
-
|
|
13861
|
-
|
|
13862
|
-
|
|
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-
|
|
13889
|
-
|
|
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
|
-
|
|
13896
|
-
|
|
13897
|
-
|
|
13898
|
-
|
|
13899
|
-
|
|
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,
|
|
13908
|
-
/* @__PURE__ */ (0,
|
|
13909
|
-
/* @__PURE__ */ (0,
|
|
13910
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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 =
|
|
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 =
|
|
13953
|
-
const lastLoadMoreOptionsLengthRef =
|
|
13954
|
-
const previousHighlightedIndexRef =
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
13981
|
-
/* @__PURE__ */ (0,
|
|
13982
|
-
/* @__PURE__ */ (0,
|
|
13983
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
14155
|
-
/* @__PURE__ */ (0,
|
|
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,
|