infinity-ui-elements 1.8.26 → 1.8.28
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/Table/Table.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.esm.js +63 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +63 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3222,8 +3222,21 @@ const defaultFilter = (item, query) => {
|
|
|
3222
3222
|
return (item.label?.toLowerCase()?.includes(searchQuery) ||
|
|
3223
3223
|
(item.description?.toLowerCase()?.includes(searchQuery) ?? false));
|
|
3224
3224
|
};
|
|
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
|
-
|
|
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, value: controlledValue, defaultValue, onChange, ...textFieldProps }, ref) => {
|
|
3226
|
+
// Find the selected item based on value/defaultValue
|
|
3227
|
+
const findSelectedItem = React__namespace.useCallback((val) => {
|
|
3228
|
+
if (val === undefined || val === "")
|
|
3229
|
+
return undefined;
|
|
3230
|
+
return items.find((item) => item.value === val);
|
|
3231
|
+
}, [items]);
|
|
3232
|
+
// Initialize uncontrolled value state
|
|
3233
|
+
const initialValue = controlledValue !== undefined ? controlledValue : defaultValue;
|
|
3234
|
+
const initialSelectedItem = findSelectedItem(initialValue);
|
|
3235
|
+
const initialSearchValue = initialSelectedItem
|
|
3236
|
+
? initialSelectedItem.label
|
|
3237
|
+
: defaultSearchValue;
|
|
3238
|
+
const [uncontrolledSearchValue, setUncontrolledSearchValue] = React__namespace.useState(initialSearchValue);
|
|
3239
|
+
const [uncontrolledValue, setUncontrolledValue] = React__namespace.useState(defaultValue);
|
|
3227
3240
|
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
|
3228
3241
|
const [focusedIndex, setFocusedIndex] = React__namespace.useState(-1);
|
|
3229
3242
|
const [isInsideModal, setIsInsideModal] = React__namespace.useState(false);
|
|
@@ -3236,6 +3249,33 @@ const SearchableDropdown = React__namespace.forwardRef(({ className, items = [],
|
|
|
3236
3249
|
width: 0,
|
|
3237
3250
|
});
|
|
3238
3251
|
React__namespace.useImperativeHandle(ref, () => inputRef.current);
|
|
3252
|
+
// Determine current value (controlled or uncontrolled)
|
|
3253
|
+
const value = controlledValue !== undefined ? controlledValue : uncontrolledValue;
|
|
3254
|
+
// Sync search value when value prop changes
|
|
3255
|
+
React__namespace.useEffect(() => {
|
|
3256
|
+
const selectedItem = findSelectedItem(value);
|
|
3257
|
+
if (selectedItem) {
|
|
3258
|
+
const newSearchValue = selectedItem.label;
|
|
3259
|
+
if (controlledSearchValue === undefined) {
|
|
3260
|
+
setUncontrolledSearchValue(newSearchValue);
|
|
3261
|
+
}
|
|
3262
|
+
// If controlled, we still need to call onSearchChange to notify parent
|
|
3263
|
+
// but only if the search value is different
|
|
3264
|
+
if (controlledSearchValue !== undefined &&
|
|
3265
|
+
controlledSearchValue !== newSearchValue) {
|
|
3266
|
+
onSearchChange?.(newSearchValue);
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
else if (value === undefined || value === "") {
|
|
3270
|
+
// If value is cleared, clear search value too
|
|
3271
|
+
if (controlledSearchValue === undefined) {
|
|
3272
|
+
setUncontrolledSearchValue("");
|
|
3273
|
+
}
|
|
3274
|
+
else {
|
|
3275
|
+
onSearchChange?.("");
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
}, [value, findSelectedItem, controlledSearchValue, onSearchChange]);
|
|
3239
3279
|
// Check if dropdown is inside a modal
|
|
3240
3280
|
React__namespace.useEffect(() => {
|
|
3241
3281
|
if (isOpen && dropdownRef.current) {
|
|
@@ -3277,6 +3317,15 @@ const SearchableDropdown = React__namespace.forwardRef(({ className, items = [],
|
|
|
3277
3317
|
setUncontrolledSearchValue(newValue);
|
|
3278
3318
|
}
|
|
3279
3319
|
onSearchChange?.(newValue);
|
|
3320
|
+
// If user is typing and the search value no longer matches the selected item's label,
|
|
3321
|
+
// clear the value to indicate no item is selected
|
|
3322
|
+
const selectedItem = findSelectedItem(value);
|
|
3323
|
+
if (selectedItem && selectedItem.label !== newValue) {
|
|
3324
|
+
if (controlledValue === undefined) {
|
|
3325
|
+
setUncontrolledValue(undefined);
|
|
3326
|
+
}
|
|
3327
|
+
onChange?.(undefined, undefined);
|
|
3328
|
+
}
|
|
3280
3329
|
// Show dropdown if minimum search length is met
|
|
3281
3330
|
if (newValue.length >= minSearchLength) {
|
|
3282
3331
|
setIsOpen(true);
|
|
@@ -3292,9 +3341,19 @@ const SearchableDropdown = React__namespace.forwardRef(({ className, items = [],
|
|
|
3292
3341
|
};
|
|
3293
3342
|
const handleItemSelect = (item) => {
|
|
3294
3343
|
onItemSelect?.(item);
|
|
3344
|
+
// Update search value
|
|
3295
3345
|
if (controlledSearchValue === undefined) {
|
|
3296
3346
|
setUncontrolledSearchValue(item.label);
|
|
3297
3347
|
}
|
|
3348
|
+
else {
|
|
3349
|
+
onSearchChange?.(item.label);
|
|
3350
|
+
}
|
|
3351
|
+
// Update value (controlled or uncontrolled)
|
|
3352
|
+
if (controlledValue === undefined) {
|
|
3353
|
+
setUncontrolledValue(item.value);
|
|
3354
|
+
}
|
|
3355
|
+
// Call onChange callback
|
|
3356
|
+
onChange?.(item.value, item);
|
|
3298
3357
|
setIsOpen(false);
|
|
3299
3358
|
inputRef.current?.focus();
|
|
3300
3359
|
};
|
|
@@ -3991,6 +4050,7 @@ function TableComponent({ className, wrapperClassName, containerClassName, varia
|
|
|
3991
4050
|
maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
|
|
3992
4051
|
};
|
|
3993
4052
|
}, [maxHeight]);
|
|
4053
|
+
// Resolve loading state: prefer 'loading' prop, fallback to 'isLoading' for backward compatibility
|
|
3994
4054
|
const resolvedLoading = typeof loading === "boolean" ? loading : Boolean(isLoading);
|
|
3995
4055
|
const skeletonRowCount = loadingSkeletonRows ?? 5;
|
|
3996
4056
|
const sizeKey = size || "medium";
|
|
@@ -4041,6 +4101,7 @@ function TableComponent({ className, wrapperClassName, containerClassName, varia
|
|
|
4041
4101
|
onRowClick(row);
|
|
4042
4102
|
}
|
|
4043
4103
|
}, [onRowClick]);
|
|
4104
|
+
// ==================== Render Helpers ====================
|
|
4044
4105
|
const renderEmptyState = () => {
|
|
4045
4106
|
if (emptyComponent)
|
|
4046
4107
|
return emptyComponent;
|