infinity-ui-elements 1.8.27 → 1.8.29
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/components/SearchableDropdown/SearchableDropdown.d.ts +14 -0
- package/dist/components/SearchableDropdown/SearchableDropdown.d.ts.map +1 -1
- package/dist/components/SearchableDropdown/SearchableDropdown.stories.d.ts +5 -1
- package/dist/components/SearchableDropdown/SearchableDropdown.stories.d.ts.map +1 -1
- package/dist/components/Select/Select.d.ts +5 -0
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.stories.d.ts +1 -0
- package/dist/components/Select/Select.stories.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.esm.js +70 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +70 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2618,7 +2618,7 @@ const selectVariants = classVarianceAuthority.cva("relative flex items-center ga
|
|
|
2618
2618
|
isDisabled: false,
|
|
2619
2619
|
},
|
|
2620
2620
|
});
|
|
2621
|
-
const Select = React__namespace.forwardRef(({ className, options = [], value: controlledValue, defaultValue, onChange, placeholder = "Select an option", label, helperText, errorText, successText, validationState = "none", isDisabled = false, isRequired = false, isOptional = false, isLoading = false, size = "medium", prefix, suffix, showClearButton = false, onClear, containerClassName, labelClassName, triggerClassName, menuClassName, menuWidth = "full", sectionHeading, emptyTitle = "No options available", emptyDescription = "There are no options to select from.", emptyIcon, infoHeading, infoDescription, LinkComponent, linkText, linkHref, onLinkClick, ...props }, ref) => {
|
|
2621
|
+
const Select = React__namespace.forwardRef(({ className, options = [], value: controlledValue, defaultValue, onChange, placeholder = "Select an option", label, helperText, errorText, successText, validationState = "none", isDisabled = false, isRequired = false, isOptional = false, isLoading = false, size = "medium", prefix, suffix, showClearButton = false, onClear, showLeadingIcon = false, containerClassName, labelClassName, triggerClassName, menuClassName, menuWidth = "full", sectionHeading, emptyTitle = "No options available", emptyDescription = "There are no options to select from.", emptyIcon, infoHeading, infoDescription, LinkComponent, linkText, linkHref, onLinkClick, ...props }, ref) => {
|
|
2622
2622
|
const [uncontrolledValue, setUncontrolledValue] = React__namespace.useState(defaultValue);
|
|
2623
2623
|
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
|
2624
2624
|
const [dropdownPlacement, setDropdownPlacement] = React__namespace.useState("bottom");
|
|
@@ -2797,13 +2797,19 @@ const Select = React__namespace.forwardRef(({ className, options = [], value: co
|
|
|
2797
2797
|
size,
|
|
2798
2798
|
validationState: currentValidationState,
|
|
2799
2799
|
isDisabled,
|
|
2800
|
-
}), "relative w-full cursor-pointer", className), onClick: !isDisabled && !isLoading ? toggleOpen : undefined, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-disabled": isDisabled, ...props, children: [prefix
|
|
2800
|
+
}), "relative w-full cursor-pointer", className), onClick: !isDisabled && !isLoading ? toggleOpen : undefined, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-disabled": isDisabled, ...props, children: [prefix ? (jsxRuntime.jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
2801
2801
|
? "text-surface-ink-neutral-disabled"
|
|
2802
2802
|
: currentValidationState === "positive"
|
|
2803
2803
|
? "text-feedback-ink-positive-intense"
|
|
2804
2804
|
: currentValidationState === "negative"
|
|
2805
2805
|
? "text-feedback-ink-negative-subtle"
|
|
2806
|
-
: "text-surface-ink-neutral-muted"), children: prefix }))
|
|
2806
|
+
: "text-surface-ink-neutral-muted"), children: prefix })) : showLeadingIcon && selectedOption?.leadingIcon ? (jsxRuntime.jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
2807
|
+
? "text-surface-ink-neutral-disabled"
|
|
2808
|
+
: currentValidationState === "positive"
|
|
2809
|
+
? "text-feedback-ink-positive-intense"
|
|
2810
|
+
: currentValidationState === "negative"
|
|
2811
|
+
? "text-feedback-ink-negative-subtle"
|
|
2812
|
+
: "text-surface-ink-neutral-muted"), children: selectedOption.leadingIcon })) : null, jsxRuntime.jsx("span", { className: cn("flex-1 text-left truncate", !selectedOption && "text-surface-ink-neutral-muted", isDisabled && "text-surface-ink-neutral-disabled"), children: isLoading ? "Loading..." : selectedOption?.label || placeholder }), showClearButton && hasValue && !isDisabled && !isLoading && (jsxRuntime.jsx("button", { type: "button", onClick: handleClear, className: "shrink-0 flex items-center justify-center text-surface-ink-neutral-muted hover:text-surface-ink-neutral-normal transition-colors", tabIndex: -1, children: jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsxRuntime.jsx("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })), suffix && !showClearButton && (jsxRuntime.jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
|
|
2807
2813
|
? "text-surface-ink-neutral-disabled"
|
|
2808
2814
|
: currentValidationState === "positive"
|
|
2809
2815
|
? "text-feedback-ink-positive-intense"
|
|
@@ -3222,8 +3228,21 @@ const defaultFilter = (item, query) => {
|
|
|
3222
3228
|
return (item.label?.toLowerCase()?.includes(searchQuery) ||
|
|
3223
3229
|
(item.description?.toLowerCase()?.includes(searchQuery) ?? false));
|
|
3224
3230
|
};
|
|
3225
|
-
const SearchableDropdown = React__namespace.forwardRef(({ className, items = [], sectionHeading, isLoading = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText, secondaryButtonText, onPrimaryClick, onSecondaryClick, dropdownWidth = "full", showChevron = false, emptyIcon, disableFooter = false, footerLayout = "horizontal", onSearchChange, onItemSelect, filterFunction = defaultFilter, searchValue: controlledSearchValue, defaultSearchValue = "", dropdownClassName, minSearchLength = 0, showOnFocus = true, showAddNew = false, showAddNewIfDoesNotMatch = true, onAddNew, containerClassName, ...textFieldProps }, ref) => {
|
|
3226
|
-
|
|
3231
|
+
const SearchableDropdown = React__namespace.forwardRef(({ className, items = [], sectionHeading, isLoading = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText, secondaryButtonText, onPrimaryClick, onSecondaryClick, dropdownWidth = "full", showChevron = false, emptyIcon, disableFooter = false, footerLayout = "horizontal", onSearchChange, onItemSelect, filterFunction = defaultFilter, searchValue: controlledSearchValue, defaultSearchValue = "", dropdownClassName, minSearchLength = 0, showOnFocus = true, showAddNew = false, showAddNewIfDoesNotMatch = true, onAddNew, containerClassName, value: controlledValue, defaultValue, onChange, ...textFieldProps }, ref) => {
|
|
3232
|
+
// Find the selected item based on value/defaultValue
|
|
3233
|
+
const findSelectedItem = React__namespace.useCallback((val) => {
|
|
3234
|
+
if (val === undefined || val === "")
|
|
3235
|
+
return undefined;
|
|
3236
|
+
return items.find((item) => item.value === val);
|
|
3237
|
+
}, [items]);
|
|
3238
|
+
// Initialize uncontrolled value state
|
|
3239
|
+
const initialValue = controlledValue !== undefined ? controlledValue : defaultValue;
|
|
3240
|
+
const initialSelectedItem = findSelectedItem(initialValue);
|
|
3241
|
+
const initialSearchValue = initialSelectedItem
|
|
3242
|
+
? initialSelectedItem.label
|
|
3243
|
+
: defaultSearchValue;
|
|
3244
|
+
const [uncontrolledSearchValue, setUncontrolledSearchValue] = React__namespace.useState(initialSearchValue);
|
|
3245
|
+
const [uncontrolledValue, setUncontrolledValue] = React__namespace.useState(defaultValue);
|
|
3227
3246
|
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
|
3228
3247
|
const [focusedIndex, setFocusedIndex] = React__namespace.useState(-1);
|
|
3229
3248
|
const [isInsideModal, setIsInsideModal] = React__namespace.useState(false);
|
|
@@ -3236,6 +3255,33 @@ const SearchableDropdown = React__namespace.forwardRef(({ className, items = [],
|
|
|
3236
3255
|
width: 0,
|
|
3237
3256
|
});
|
|
3238
3257
|
React__namespace.useImperativeHandle(ref, () => inputRef.current);
|
|
3258
|
+
// Determine current value (controlled or uncontrolled)
|
|
3259
|
+
const value = controlledValue !== undefined ? controlledValue : uncontrolledValue;
|
|
3260
|
+
// Sync search value when value prop changes
|
|
3261
|
+
React__namespace.useEffect(() => {
|
|
3262
|
+
const selectedItem = findSelectedItem(value);
|
|
3263
|
+
if (selectedItem) {
|
|
3264
|
+
const newSearchValue = selectedItem.label;
|
|
3265
|
+
if (controlledSearchValue === undefined) {
|
|
3266
|
+
setUncontrolledSearchValue(newSearchValue);
|
|
3267
|
+
}
|
|
3268
|
+
// If controlled, we still need to call onSearchChange to notify parent
|
|
3269
|
+
// but only if the search value is different
|
|
3270
|
+
if (controlledSearchValue !== undefined &&
|
|
3271
|
+
controlledSearchValue !== newSearchValue) {
|
|
3272
|
+
onSearchChange?.(newSearchValue);
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
else if (value === undefined || value === "") {
|
|
3276
|
+
// If value is cleared, clear search value too
|
|
3277
|
+
if (controlledSearchValue === undefined) {
|
|
3278
|
+
setUncontrolledSearchValue("");
|
|
3279
|
+
}
|
|
3280
|
+
else {
|
|
3281
|
+
onSearchChange?.("");
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
}, [value, findSelectedItem, controlledSearchValue, onSearchChange]);
|
|
3239
3285
|
// Check if dropdown is inside a modal
|
|
3240
3286
|
React__namespace.useEffect(() => {
|
|
3241
3287
|
if (isOpen && dropdownRef.current) {
|
|
@@ -3277,6 +3323,15 @@ const SearchableDropdown = React__namespace.forwardRef(({ className, items = [],
|
|
|
3277
3323
|
setUncontrolledSearchValue(newValue);
|
|
3278
3324
|
}
|
|
3279
3325
|
onSearchChange?.(newValue);
|
|
3326
|
+
// If user is typing and the search value no longer matches the selected item's label,
|
|
3327
|
+
// clear the value to indicate no item is selected
|
|
3328
|
+
const selectedItem = findSelectedItem(value);
|
|
3329
|
+
if (selectedItem && selectedItem.label !== newValue) {
|
|
3330
|
+
if (controlledValue === undefined) {
|
|
3331
|
+
setUncontrolledValue(undefined);
|
|
3332
|
+
}
|
|
3333
|
+
onChange?.(undefined, undefined);
|
|
3334
|
+
}
|
|
3280
3335
|
// Show dropdown if minimum search length is met
|
|
3281
3336
|
if (newValue.length >= minSearchLength) {
|
|
3282
3337
|
setIsOpen(true);
|
|
@@ -3292,9 +3347,19 @@ const SearchableDropdown = React__namespace.forwardRef(({ className, items = [],
|
|
|
3292
3347
|
};
|
|
3293
3348
|
const handleItemSelect = (item) => {
|
|
3294
3349
|
onItemSelect?.(item);
|
|
3350
|
+
// Update search value
|
|
3295
3351
|
if (controlledSearchValue === undefined) {
|
|
3296
3352
|
setUncontrolledSearchValue(item.label);
|
|
3297
3353
|
}
|
|
3354
|
+
else {
|
|
3355
|
+
onSearchChange?.(item.label);
|
|
3356
|
+
}
|
|
3357
|
+
// Update value (controlled or uncontrolled)
|
|
3358
|
+
if (controlledValue === undefined) {
|
|
3359
|
+
setUncontrolledValue(item.value);
|
|
3360
|
+
}
|
|
3361
|
+
// Call onChange callback
|
|
3362
|
+
onChange?.(item.value, item);
|
|
3298
3363
|
setIsOpen(false);
|
|
3299
3364
|
inputRef.current?.focus();
|
|
3300
3365
|
};
|