infinity-ui-elements 1.8.11 → 1.8.13
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 +5 -0
- package/dist/components/SearchableDropdown/SearchableDropdown.d.ts.map +1 -1
- package/dist/components/SearchableDropdown/SearchableDropdown.stories.d.ts +1 -0
- package/dist/components/SearchableDropdown/SearchableDropdown.stories.d.ts.map +1 -1
- package/dist/components/SelectTextField/SelectTextField.d.ts +73 -0
- package/dist/components/SelectTextField/SelectTextField.d.ts.map +1 -0
- package/dist/components/SelectTextField/SelectTextField.stories.d.ts +21 -0
- package/dist/components/SelectTextField/SelectTextField.stories.d.ts.map +1 -0
- package/dist/components/SelectTextField/index.d.ts +3 -0
- package/dist/components/SelectTextField/index.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +218 -10
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +219 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3214,7 +3214,7 @@ const defaultFilter = (item, query) => {
|
|
|
3214
3214
|
return (item.label.toLowerCase().includes(searchQuery) ||
|
|
3215
3215
|
(item.description?.toLowerCase().includes(searchQuery) ?? false));
|
|
3216
3216
|
};
|
|
3217
|
-
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, containerClassName, ...textFieldProps }, ref) => {
|
|
3217
|
+
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, onAddNew, containerClassName, ...textFieldProps }, ref) => {
|
|
3218
3218
|
const [uncontrolledSearchValue, setUncontrolledSearchValue] = React__namespace.useState(defaultSearchValue);
|
|
3219
3219
|
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
|
3220
3220
|
const [focusedIndex, setFocusedIndex] = React__namespace.useState(-1);
|
|
@@ -3281,16 +3281,21 @@ const SearchableDropdown = React__namespace.forwardRef(({ className, items = [],
|
|
|
3281
3281
|
}
|
|
3282
3282
|
const addNewItem = {
|
|
3283
3283
|
value: searchValue,
|
|
3284
|
-
label: `+ Add ${searchValue}`,
|
|
3284
|
+
label: `+ Add "${searchValue}"`,
|
|
3285
3285
|
variant: "primary",
|
|
3286
3286
|
onClick: () => {
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3287
|
+
if (onAddNew) {
|
|
3288
|
+
onAddNew(searchValue);
|
|
3289
|
+
}
|
|
3290
|
+
else {
|
|
3291
|
+
const newItem = {
|
|
3292
|
+
value: searchValue,
|
|
3293
|
+
label: searchValue,
|
|
3294
|
+
};
|
|
3295
|
+
onItemSelect?.(newItem);
|
|
3296
|
+
if (controlledSearchValue === undefined) {
|
|
3297
|
+
setUncontrolledSearchValue(searchValue);
|
|
3298
|
+
}
|
|
3294
3299
|
}
|
|
3295
3300
|
setIsOpen(false);
|
|
3296
3301
|
inputRef.current?.focus();
|
|
@@ -3302,6 +3307,7 @@ const SearchableDropdown = React__namespace.forwardRef(({ className, items = [],
|
|
|
3302
3307
|
searchValue,
|
|
3303
3308
|
filteredItems,
|
|
3304
3309
|
onItemSelect,
|
|
3310
|
+
onAddNew,
|
|
3305
3311
|
controlledSearchValue,
|
|
3306
3312
|
]);
|
|
3307
3313
|
// Reset focused index when items change
|
|
@@ -3436,6 +3442,208 @@ const Skeleton = React__namespace.forwardRef(({ className, containerClassName, c
|
|
|
3436
3442
|
});
|
|
3437
3443
|
Skeleton.displayName = "Skeleton";
|
|
3438
3444
|
|
|
3445
|
+
const selectTriggerVariants = classVarianceAuthority.cva("flex items-center gap-1 transition-all font-display font-size-100 leading-100", {
|
|
3446
|
+
variants: {
|
|
3447
|
+
size: {
|
|
3448
|
+
small: "px-2 text-xs",
|
|
3449
|
+
medium: "px-2 text-sm",
|
|
3450
|
+
large: "px-3 text-base",
|
|
3451
|
+
},
|
|
3452
|
+
validationState: {
|
|
3453
|
+
none: "",
|
|
3454
|
+
positive: "",
|
|
3455
|
+
negative: "",
|
|
3456
|
+
},
|
|
3457
|
+
isDisabled: {
|
|
3458
|
+
true: "opacity-60 cursor-not-allowed",
|
|
3459
|
+
false: "cursor-pointer hover:opacity-80",
|
|
3460
|
+
},
|
|
3461
|
+
},
|
|
3462
|
+
defaultVariants: {
|
|
3463
|
+
size: "medium",
|
|
3464
|
+
validationState: "none",
|
|
3465
|
+
isDisabled: false,
|
|
3466
|
+
},
|
|
3467
|
+
});
|
|
3468
|
+
const SelectTextField = React__namespace.forwardRef(({ textValue: controlledTextValue, defaultTextValue, onTextChange, selectOptions = [], selectValue: controlledSelectValue, defaultSelectValue, onSelectChange, selectPlaceholder = "Select", selectTriggerClassName, selectMenuClassName, selectMenuWidth = "auto", selectSectionHeading, selectEmptyTitle = "No options available", selectEmptyDescription = "There are no options to select from.", selectEmptyIcon, label, helperText, errorText, successText, validationState = "none", isDisabled = false, isRequired = false, isOptional = false, size = "medium", containerClassName, labelClassName, inputClassName, className, ...textFieldProps }, ref) => {
|
|
3469
|
+
const [uncontrolledTextValue, setUncontrolledTextValue] = React__namespace.useState(defaultTextValue || "");
|
|
3470
|
+
const [uncontrolledSelectValue, setUncontrolledSelectValue] = React__namespace.useState(defaultSelectValue);
|
|
3471
|
+
const [isSelectOpen, setIsSelectOpen] = React__namespace.useState(false);
|
|
3472
|
+
const [dropdownPlacement, setDropdownPlacement] = React__namespace.useState("bottom");
|
|
3473
|
+
const selectRef = React__namespace.useRef(null);
|
|
3474
|
+
const dropdownContainerRef = React__namespace.useRef(null);
|
|
3475
|
+
const componentRef = React__namespace.useRef(null);
|
|
3476
|
+
const textValue = controlledTextValue !== undefined
|
|
3477
|
+
? controlledTextValue
|
|
3478
|
+
: uncontrolledTextValue;
|
|
3479
|
+
const selectValue = controlledSelectValue !== undefined
|
|
3480
|
+
? controlledSelectValue
|
|
3481
|
+
: uncontrolledSelectValue;
|
|
3482
|
+
// Find the selected option
|
|
3483
|
+
const selectedOption = selectOptions.find((opt) => opt.value === selectValue);
|
|
3484
|
+
// Determine which helper text to show
|
|
3485
|
+
const displayHelperText = errorText || successText || helperText;
|
|
3486
|
+
const currentValidationState = errorText
|
|
3487
|
+
? "negative"
|
|
3488
|
+
: successText
|
|
3489
|
+
? "positive"
|
|
3490
|
+
: validationState;
|
|
3491
|
+
const handleTextChange = (e) => {
|
|
3492
|
+
const newValue = e.target.value;
|
|
3493
|
+
if (onTextChange) {
|
|
3494
|
+
onTextChange(newValue);
|
|
3495
|
+
}
|
|
3496
|
+
else {
|
|
3497
|
+
setUncontrolledTextValue(newValue);
|
|
3498
|
+
}
|
|
3499
|
+
};
|
|
3500
|
+
const handleSelectOpenChange = (newOpen) => {
|
|
3501
|
+
if (!isDisabled) {
|
|
3502
|
+
setIsSelectOpen(newOpen);
|
|
3503
|
+
}
|
|
3504
|
+
};
|
|
3505
|
+
const toggleSelectOpen = () => {
|
|
3506
|
+
handleSelectOpenChange(!isSelectOpen);
|
|
3507
|
+
};
|
|
3508
|
+
const handleSelect = (option) => {
|
|
3509
|
+
if (controlledSelectValue === undefined) {
|
|
3510
|
+
setUncontrolledSelectValue(option.value);
|
|
3511
|
+
}
|
|
3512
|
+
onSelectChange?.(option.value, option);
|
|
3513
|
+
setIsSelectOpen(false);
|
|
3514
|
+
};
|
|
3515
|
+
const updateDropdownPlacement = React__namespace.useCallback(() => {
|
|
3516
|
+
if (typeof window === "undefined")
|
|
3517
|
+
return;
|
|
3518
|
+
const trigger = selectRef.current;
|
|
3519
|
+
if (!trigger)
|
|
3520
|
+
return;
|
|
3521
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
3522
|
+
const spaceBelow = window.innerHeight - triggerRect.bottom;
|
|
3523
|
+
const spaceAbove = triggerRect.top;
|
|
3524
|
+
const dropdownHeight = dropdownContainerRef.current
|
|
3525
|
+
? dropdownContainerRef.current.offsetHeight
|
|
3526
|
+
: 0;
|
|
3527
|
+
if (dropdownHeight === 0) {
|
|
3528
|
+
setDropdownPlacement(spaceBelow >= spaceAbove ? "bottom" : "top");
|
|
3529
|
+
return;
|
|
3530
|
+
}
|
|
3531
|
+
if (spaceBelow >= dropdownHeight || spaceBelow >= spaceAbove) {
|
|
3532
|
+
setDropdownPlacement("bottom");
|
|
3533
|
+
}
|
|
3534
|
+
else {
|
|
3535
|
+
setDropdownPlacement("top");
|
|
3536
|
+
}
|
|
3537
|
+
}, []);
|
|
3538
|
+
const attachDropdownListeners = React__namespace.useCallback(() => {
|
|
3539
|
+
if (!isSelectOpen)
|
|
3540
|
+
return;
|
|
3541
|
+
if (typeof window === "undefined")
|
|
3542
|
+
return;
|
|
3543
|
+
let rafId = requestAnimationFrame(updateDropdownPlacement);
|
|
3544
|
+
const handleUpdate = () => updateDropdownPlacement();
|
|
3545
|
+
window.addEventListener("resize", handleUpdate);
|
|
3546
|
+
window.addEventListener("scroll", handleUpdate, true);
|
|
3547
|
+
return () => {
|
|
3548
|
+
cancelAnimationFrame(rafId);
|
|
3549
|
+
window.removeEventListener("resize", handleUpdate);
|
|
3550
|
+
window.removeEventListener("scroll", handleUpdate, true);
|
|
3551
|
+
};
|
|
3552
|
+
}, [isSelectOpen, updateDropdownPlacement]);
|
|
3553
|
+
React__namespace.useEffect(() => {
|
|
3554
|
+
const detach = attachDropdownListeners();
|
|
3555
|
+
return () => {
|
|
3556
|
+
detach?.();
|
|
3557
|
+
};
|
|
3558
|
+
}, [attachDropdownListeners]);
|
|
3559
|
+
React__namespace.useEffect(() => {
|
|
3560
|
+
if (isSelectOpen) {
|
|
3561
|
+
updateDropdownPlacement();
|
|
3562
|
+
}
|
|
3563
|
+
}, [isSelectOpen, selectOptions.length, updateDropdownPlacement]);
|
|
3564
|
+
// Close dropdown when clicking outside
|
|
3565
|
+
React__namespace.useEffect(() => {
|
|
3566
|
+
const handleClickOutside = (event) => {
|
|
3567
|
+
const target = event.target;
|
|
3568
|
+
if (selectRef.current &&
|
|
3569
|
+
!selectRef.current.contains(target) &&
|
|
3570
|
+
dropdownContainerRef.current &&
|
|
3571
|
+
!dropdownContainerRef.current.contains(target)) {
|
|
3572
|
+
handleSelectOpenChange(false);
|
|
3573
|
+
}
|
|
3574
|
+
};
|
|
3575
|
+
if (isSelectOpen) {
|
|
3576
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
3577
|
+
return () => {
|
|
3578
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
3579
|
+
};
|
|
3580
|
+
}
|
|
3581
|
+
}, [isSelectOpen]);
|
|
3582
|
+
// Close on escape key
|
|
3583
|
+
React__namespace.useEffect(() => {
|
|
3584
|
+
const handleEscape = (event) => {
|
|
3585
|
+
if (event.key === "Escape") {
|
|
3586
|
+
handleSelectOpenChange(false);
|
|
3587
|
+
}
|
|
3588
|
+
};
|
|
3589
|
+
if (isSelectOpen) {
|
|
3590
|
+
document.addEventListener("keydown", handleEscape);
|
|
3591
|
+
return () => {
|
|
3592
|
+
document.removeEventListener("keydown", handleEscape);
|
|
3593
|
+
};
|
|
3594
|
+
}
|
|
3595
|
+
}, [isSelectOpen]);
|
|
3596
|
+
// Transform options to dropdown menu items
|
|
3597
|
+
const menuItems = selectOptions.map((option) => ({
|
|
3598
|
+
value: option.value,
|
|
3599
|
+
label: option.label ?? String(option.value),
|
|
3600
|
+
description: option.description,
|
|
3601
|
+
leadingIcon: option.leadingIcon,
|
|
3602
|
+
trailingIcon: option.trailingIcon,
|
|
3603
|
+
isDisabled: option.isDisabled,
|
|
3604
|
+
variant: option.variant,
|
|
3605
|
+
onClick: () => handleSelect(option),
|
|
3606
|
+
}));
|
|
3607
|
+
const widthStyle = selectMenuWidth === "full"
|
|
3608
|
+
? "100%"
|
|
3609
|
+
: selectMenuWidth === "auto"
|
|
3610
|
+
? "auto"
|
|
3611
|
+
: selectMenuWidth;
|
|
3612
|
+
const sizeConfig = {
|
|
3613
|
+
small: {
|
|
3614
|
+
gap: "gap-2",
|
|
3615
|
+
},
|
|
3616
|
+
medium: {
|
|
3617
|
+
gap: "gap-2",
|
|
3618
|
+
},
|
|
3619
|
+
large: {
|
|
3620
|
+
gap: "gap-3",
|
|
3621
|
+
},
|
|
3622
|
+
};
|
|
3623
|
+
// Create the select suffix component
|
|
3624
|
+
const selectSuffix = (jsxRuntime.jsxs("div", { className: "relative flex items-center h-full", children: [jsxRuntime.jsxs("div", { ref: selectRef, className: cn(selectTriggerVariants({
|
|
3625
|
+
size,
|
|
3626
|
+
validationState: currentValidationState,
|
|
3627
|
+
isDisabled,
|
|
3628
|
+
}), "border-l border-action-outline-neutral-faded pl-2 ml-2 h-full flex items-center", selectTriggerClassName), onClick: !isDisabled ? toggleSelectOpen : undefined, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isSelectOpen, "aria-disabled": isDisabled, children: [jsxRuntime.jsx("span", { className: cn("text-left truncate max-w-[120px] whitespace-nowrap", !selectedOption && "text-surface-ink-neutral-muted", isDisabled && "text-surface-ink-neutral-disabled"), children: selectedOption?.label || selectPlaceholder }), jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn("shrink-0 transition-transform", size === "small"
|
|
3629
|
+
? "w-3 h-3"
|
|
3630
|
+
: size === "medium"
|
|
3631
|
+
? "w-3.5 h-3.5"
|
|
3632
|
+
: "w-4 h-4", isDisabled
|
|
3633
|
+
? "text-surface-ink-neutral-disabled"
|
|
3634
|
+
: currentValidationState === "positive"
|
|
3635
|
+
? "text-feedback-ink-positive-intense"
|
|
3636
|
+
: currentValidationState === "negative"
|
|
3637
|
+
? "text-feedback-ink-negative-subtle"
|
|
3638
|
+
: "text-surface-ink-neutral-muted", isSelectOpen && "transform rotate-180") })] }), isSelectOpen && !isDisabled && (jsxRuntime.jsx("div", { ref: dropdownContainerRef, className: cn("absolute z-50 right-0", dropdownPlacement === "bottom"
|
|
3639
|
+
? "top-full mt-1"
|
|
3640
|
+
: "bottom-full mb-1"), children: jsxRuntime.jsx(DropdownMenu, { items: menuItems, sectionHeading: selectSectionHeading, isEmpty: selectOptions.length === 0, emptyTitle: selectEmptyTitle, emptyDescription: selectEmptyDescription, emptyIcon: selectEmptyIcon, disableFooter: true, onClose: () => handleSelectOpenChange(false), className: selectMenuClassName, width: widthStyle }) }))] }));
|
|
3641
|
+
return (jsxRuntime.jsxs("div", { ref: componentRef, className: cn("w-full flex flex-col", sizeConfig[size].gap, containerClassName), children: [label && (jsxRuntime.jsx(FormHeader, { label: label, size: size, isRequired: isRequired, isOptional: isOptional, infoHeading: textFieldProps.infoHeading, infoDescription: textFieldProps.infoDescription, LinkComponent: textFieldProps.LinkComponent, linkText: textFieldProps.linkText, linkHref: textFieldProps.linkHref, onLinkClick: textFieldProps.onLinkClick, htmlFor: textFieldProps.id, className: "mb-2", labelClassName: labelClassName })), jsxRuntime.jsx(TextField, { ref: ref, value: textValue, onChange: handleTextChange, suffix: selectSuffix, size: size, validationState: currentValidationState, isDisabled: isDisabled, isRequired: isRequired, isOptional: isOptional, containerClassName: "gap-0", className: className, inputClassName: inputClassName, ...textFieldProps }), jsxRuntime.jsx(FormFooter, { helperText: displayHelperText, validationState: currentValidationState === "none"
|
|
3642
|
+
? "default"
|
|
3643
|
+
: currentValidationState, size: size, isDisabled: isDisabled, className: "mt-1" })] }));
|
|
3644
|
+
});
|
|
3645
|
+
SelectTextField.displayName = "SelectTextField";
|
|
3646
|
+
|
|
3439
3647
|
const switchVariants = classVarianceAuthority.cva("relative inline-flex items-center shrink-0 cursor-pointer rounded-full transition-all duration-200", {
|
|
3440
3648
|
variants: {
|
|
3441
3649
|
size: {
|
|
@@ -4054,6 +4262,7 @@ exports.Pagination = Pagination;
|
|
|
4054
4262
|
exports.Radio = Radio;
|
|
4055
4263
|
exports.SearchableDropdown = SearchableDropdown;
|
|
4056
4264
|
exports.Select = Select;
|
|
4265
|
+
exports.SelectTextField = SelectTextField;
|
|
4057
4266
|
exports.Skeleton = Skeleton;
|
|
4058
4267
|
exports.SlotCell = SlotCell;
|
|
4059
4268
|
exports.SpacerCell = SpacerCell;
|
|
@@ -4084,6 +4293,7 @@ exports.linkVariants = linkVariants;
|
|
|
4084
4293
|
exports.listItemVariants = listItemVariants;
|
|
4085
4294
|
exports.paginationVariants = paginationVariants;
|
|
4086
4295
|
exports.radioVariants = radioVariants;
|
|
4296
|
+
exports.selectTriggerVariants = selectTriggerVariants;
|
|
4087
4297
|
exports.selectVariants = selectVariants;
|
|
4088
4298
|
exports.switchVariants = switchVariants;
|
|
4089
4299
|
exports.tableCellVariants = tableCellVariants;
|