infinity-ui-elements 1.8.12 → 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/index.esm.js CHANGED
@@ -3421,6 +3421,208 @@ const Skeleton = React.forwardRef(({ className, containerClassName, containerSty
3421
3421
  });
3422
3422
  Skeleton.displayName = "Skeleton";
3423
3423
 
3424
+ const selectTriggerVariants = cva("flex items-center gap-1 transition-all font-display font-size-100 leading-100", {
3425
+ variants: {
3426
+ size: {
3427
+ small: "px-2 text-xs",
3428
+ medium: "px-2 text-sm",
3429
+ large: "px-3 text-base",
3430
+ },
3431
+ validationState: {
3432
+ none: "",
3433
+ positive: "",
3434
+ negative: "",
3435
+ },
3436
+ isDisabled: {
3437
+ true: "opacity-60 cursor-not-allowed",
3438
+ false: "cursor-pointer hover:opacity-80",
3439
+ },
3440
+ },
3441
+ defaultVariants: {
3442
+ size: "medium",
3443
+ validationState: "none",
3444
+ isDisabled: false,
3445
+ },
3446
+ });
3447
+ const SelectTextField = React.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) => {
3448
+ const [uncontrolledTextValue, setUncontrolledTextValue] = React.useState(defaultTextValue || "");
3449
+ const [uncontrolledSelectValue, setUncontrolledSelectValue] = React.useState(defaultSelectValue);
3450
+ const [isSelectOpen, setIsSelectOpen] = React.useState(false);
3451
+ const [dropdownPlacement, setDropdownPlacement] = React.useState("bottom");
3452
+ const selectRef = React.useRef(null);
3453
+ const dropdownContainerRef = React.useRef(null);
3454
+ const componentRef = React.useRef(null);
3455
+ const textValue = controlledTextValue !== undefined
3456
+ ? controlledTextValue
3457
+ : uncontrolledTextValue;
3458
+ const selectValue = controlledSelectValue !== undefined
3459
+ ? controlledSelectValue
3460
+ : uncontrolledSelectValue;
3461
+ // Find the selected option
3462
+ const selectedOption = selectOptions.find((opt) => opt.value === selectValue);
3463
+ // Determine which helper text to show
3464
+ const displayHelperText = errorText || successText || helperText;
3465
+ const currentValidationState = errorText
3466
+ ? "negative"
3467
+ : successText
3468
+ ? "positive"
3469
+ : validationState;
3470
+ const handleTextChange = (e) => {
3471
+ const newValue = e.target.value;
3472
+ if (onTextChange) {
3473
+ onTextChange(newValue);
3474
+ }
3475
+ else {
3476
+ setUncontrolledTextValue(newValue);
3477
+ }
3478
+ };
3479
+ const handleSelectOpenChange = (newOpen) => {
3480
+ if (!isDisabled) {
3481
+ setIsSelectOpen(newOpen);
3482
+ }
3483
+ };
3484
+ const toggleSelectOpen = () => {
3485
+ handleSelectOpenChange(!isSelectOpen);
3486
+ };
3487
+ const handleSelect = (option) => {
3488
+ if (controlledSelectValue === undefined) {
3489
+ setUncontrolledSelectValue(option.value);
3490
+ }
3491
+ onSelectChange?.(option.value, option);
3492
+ setIsSelectOpen(false);
3493
+ };
3494
+ const updateDropdownPlacement = React.useCallback(() => {
3495
+ if (typeof window === "undefined")
3496
+ return;
3497
+ const trigger = selectRef.current;
3498
+ if (!trigger)
3499
+ return;
3500
+ const triggerRect = trigger.getBoundingClientRect();
3501
+ const spaceBelow = window.innerHeight - triggerRect.bottom;
3502
+ const spaceAbove = triggerRect.top;
3503
+ const dropdownHeight = dropdownContainerRef.current
3504
+ ? dropdownContainerRef.current.offsetHeight
3505
+ : 0;
3506
+ if (dropdownHeight === 0) {
3507
+ setDropdownPlacement(spaceBelow >= spaceAbove ? "bottom" : "top");
3508
+ return;
3509
+ }
3510
+ if (spaceBelow >= dropdownHeight || spaceBelow >= spaceAbove) {
3511
+ setDropdownPlacement("bottom");
3512
+ }
3513
+ else {
3514
+ setDropdownPlacement("top");
3515
+ }
3516
+ }, []);
3517
+ const attachDropdownListeners = React.useCallback(() => {
3518
+ if (!isSelectOpen)
3519
+ return;
3520
+ if (typeof window === "undefined")
3521
+ return;
3522
+ let rafId = requestAnimationFrame(updateDropdownPlacement);
3523
+ const handleUpdate = () => updateDropdownPlacement();
3524
+ window.addEventListener("resize", handleUpdate);
3525
+ window.addEventListener("scroll", handleUpdate, true);
3526
+ return () => {
3527
+ cancelAnimationFrame(rafId);
3528
+ window.removeEventListener("resize", handleUpdate);
3529
+ window.removeEventListener("scroll", handleUpdate, true);
3530
+ };
3531
+ }, [isSelectOpen, updateDropdownPlacement]);
3532
+ React.useEffect(() => {
3533
+ const detach = attachDropdownListeners();
3534
+ return () => {
3535
+ detach?.();
3536
+ };
3537
+ }, [attachDropdownListeners]);
3538
+ React.useEffect(() => {
3539
+ if (isSelectOpen) {
3540
+ updateDropdownPlacement();
3541
+ }
3542
+ }, [isSelectOpen, selectOptions.length, updateDropdownPlacement]);
3543
+ // Close dropdown when clicking outside
3544
+ React.useEffect(() => {
3545
+ const handleClickOutside = (event) => {
3546
+ const target = event.target;
3547
+ if (selectRef.current &&
3548
+ !selectRef.current.contains(target) &&
3549
+ dropdownContainerRef.current &&
3550
+ !dropdownContainerRef.current.contains(target)) {
3551
+ handleSelectOpenChange(false);
3552
+ }
3553
+ };
3554
+ if (isSelectOpen) {
3555
+ document.addEventListener("mousedown", handleClickOutside);
3556
+ return () => {
3557
+ document.removeEventListener("mousedown", handleClickOutside);
3558
+ };
3559
+ }
3560
+ }, [isSelectOpen]);
3561
+ // Close on escape key
3562
+ React.useEffect(() => {
3563
+ const handleEscape = (event) => {
3564
+ if (event.key === "Escape") {
3565
+ handleSelectOpenChange(false);
3566
+ }
3567
+ };
3568
+ if (isSelectOpen) {
3569
+ document.addEventListener("keydown", handleEscape);
3570
+ return () => {
3571
+ document.removeEventListener("keydown", handleEscape);
3572
+ };
3573
+ }
3574
+ }, [isSelectOpen]);
3575
+ // Transform options to dropdown menu items
3576
+ const menuItems = selectOptions.map((option) => ({
3577
+ value: option.value,
3578
+ label: option.label ?? String(option.value),
3579
+ description: option.description,
3580
+ leadingIcon: option.leadingIcon,
3581
+ trailingIcon: option.trailingIcon,
3582
+ isDisabled: option.isDisabled,
3583
+ variant: option.variant,
3584
+ onClick: () => handleSelect(option),
3585
+ }));
3586
+ const widthStyle = selectMenuWidth === "full"
3587
+ ? "100%"
3588
+ : selectMenuWidth === "auto"
3589
+ ? "auto"
3590
+ : selectMenuWidth;
3591
+ const sizeConfig = {
3592
+ small: {
3593
+ gap: "gap-2",
3594
+ },
3595
+ medium: {
3596
+ gap: "gap-2",
3597
+ },
3598
+ large: {
3599
+ gap: "gap-3",
3600
+ },
3601
+ };
3602
+ // Create the select suffix component
3603
+ const selectSuffix = (jsxs("div", { className: "relative flex items-center h-full", children: [jsxs("div", { ref: selectRef, className: cn(selectTriggerVariants({
3604
+ size,
3605
+ validationState: currentValidationState,
3606
+ isDisabled,
3607
+ }), "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: [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 }), jsx(ChevronDown, { className: cn("shrink-0 transition-transform", size === "small"
3608
+ ? "w-3 h-3"
3609
+ : size === "medium"
3610
+ ? "w-3.5 h-3.5"
3611
+ : "w-4 h-4", isDisabled
3612
+ ? "text-surface-ink-neutral-disabled"
3613
+ : currentValidationState === "positive"
3614
+ ? "text-feedback-ink-positive-intense"
3615
+ : currentValidationState === "negative"
3616
+ ? "text-feedback-ink-negative-subtle"
3617
+ : "text-surface-ink-neutral-muted", isSelectOpen && "transform rotate-180") })] }), isSelectOpen && !isDisabled && (jsx("div", { ref: dropdownContainerRef, className: cn("absolute z-50 right-0", dropdownPlacement === "bottom"
3618
+ ? "top-full mt-1"
3619
+ : "bottom-full mb-1"), children: 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 }) }))] }));
3620
+ return (jsxs("div", { ref: componentRef, className: cn("w-full flex flex-col", sizeConfig[size].gap, containerClassName), children: [label && (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 })), 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 }), jsx(FormFooter, { helperText: displayHelperText, validationState: currentValidationState === "none"
3621
+ ? "default"
3622
+ : currentValidationState, size: size, isDisabled: isDisabled, className: "mt-1" })] }));
3623
+ });
3624
+ SelectTextField.displayName = "SelectTextField";
3625
+
3424
3626
  const switchVariants = cva("relative inline-flex items-center shrink-0 cursor-pointer rounded-full transition-all duration-200", {
3425
3627
  variants: {
3426
3628
  size: {
@@ -4013,5 +4215,5 @@ const TextArea = React.forwardRef(({ label, helperText, errorText, successText,
4013
4215
  });
4014
4216
  TextArea.displayName = "TextArea";
4015
4217
 
4016
- export { Alert, Amount, Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, DatePicker, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconButton, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, SearchableDropdown, Select, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Tooltip, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants };
4218
+ export { Alert, Amount, Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, DatePicker, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconButton, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, SearchableDropdown, Select, SelectTextField, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Tooltip, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectTriggerVariants, selectVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants };
4017
4219
  //# sourceMappingURL=index.esm.js.map