infinity-ui-elements 1.14.18 → 1.14.20-beta.0

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
@@ -1943,7 +1943,7 @@ const Counter = React.forwardRef(({ value, max, size = "medium", color = "neutra
1943
1943
  });
1944
1944
  Counter.displayName = "Counter";
1945
1945
 
1946
- const tooltipVariants = cva("fixed z-[1000] bg-popup-fill-intense text-action-ink-on-primary-normal rounded-medium border border-popup-outline-subtle flex flex-col p-4 rounded-xlarge min-w-[200px] max-w-[300px] transition-opacity duration-200", {
1946
+ const tooltipVariants = cva("fixed z-50 bg-popup-fill-intense text-action-ink-on-primary-normal rounded-medium border border-popup-outline-subtle flex flex-col p-4 rounded-xlarge min-w-[200px] max-w-[300px] transition-opacity duration-200", {
1947
1947
  variants: {
1948
1948
  isVisible: {
1949
1949
  true: "opacity-100 pointer-events-auto shadow-[0_4px_20px_rgba(0,0,0,0.15)]",
@@ -3153,17 +3153,17 @@ const dropdownVariants = cva("bg-surface-fill-primary-normal border border-surfa
3153
3153
  size: "medium",
3154
3154
  },
3155
3155
  });
3156
- const Dropdown = React.forwardRef(({ className, trigger, items = [], customContent, customContentClassName, sectionHeading, isLoading = false, isEmpty = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText = "Primary", secondaryButtonText = "Secondary", onPrimaryClick, onSecondaryClick, size = "medium", open: controlledOpen, defaultOpen = false, onOpenChange, containerClassName, menuClassName, showChevron = false, emptyIcon, disableFooter = false, showFooter, usePortal = true, ...props }, ref) => {
3156
+ const Dropdown = React.forwardRef(({ className, trigger, items = [], customContent, customContentClassName, sectionHeading, isLoading = false, isEmpty = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText = "Primary", secondaryButtonText = "Secondary", onPrimaryClick, onSecondaryClick, size = "medium", open: controlledOpen, defaultOpen = false, onOpenChange, containerClassName, menuClassName, showChevron = false, emptyIcon, disableFooter = false, showFooter, ...props }, ref) => {
3157
3157
  const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
3158
3158
  const isOpen = controlledOpen !== undefined ? controlledOpen : uncontrolledOpen;
3159
3159
  const dropdownRef = React.useRef(null);
3160
3160
  const menuRef = React.useRef(null);
3161
3161
  const [menuPosition, setMenuPosition] = React.useState({
3162
- top: 0,
3163
- left: 0,
3164
- width: 0,
3162
+ top: "100%",
3163
+ bottom: "auto",
3164
+ left: "0",
3165
+ right: "auto",
3165
3166
  maxHeight: "400px",
3166
- position: "below",
3167
3167
  });
3168
3168
  // Detect if we're on mobile (< 768px)
3169
3169
  const [isMobile, setIsMobile] = React.useState(false);
@@ -3217,36 +3217,62 @@ const Dropdown = React.forwardRef(({ className, trigger, items = [], customConte
3217
3217
  }, [isOpen]);
3218
3218
  // Calculate and adjust dropdown position to keep it within viewport
3219
3219
  React.useEffect(() => {
3220
- if (!isOpen || !dropdownRef.current)
3220
+ if (!isOpen || !dropdownRef.current || !menuRef.current)
3221
3221
  return;
3222
3222
  const calculatePosition = () => {
3223
3223
  const triggerRect = dropdownRef.current.getBoundingClientRect();
3224
3224
  const menuElement = menuRef.current;
3225
- // Get menu dimensions
3226
- const menuHeight = menuElement?.getBoundingClientRect().height || 400;
3227
- triggerRect.width; // Match trigger width or use size variant
3225
+ // Get menu dimensions (use a temporary measurement if needed)
3226
+ const menuRect = menuElement.getBoundingClientRect();
3227
+ const menuHeight = menuRect.height || 400; // fallback to max-height
3228
+ const menuWidth = menuRect.width;
3228
3229
  const viewportHeight = window.innerHeight;
3230
+ const viewportWidth = window.innerWidth;
3229
3231
  const spaceBelow = viewportHeight - triggerRect.bottom;
3230
3232
  const spaceAbove = triggerRect.top;
3233
+ const spaceRight = viewportWidth - triggerRect.left;
3234
+ const spaceLeft = triggerRect.right;
3231
3235
  const position = {
3232
- top: 0,
3233
- left: triggerRect.left + window.scrollX,
3234
- width: triggerRect.width,
3236
+ top: "auto",
3237
+ bottom: "auto",
3238
+ left: "auto",
3239
+ right: "auto",
3235
3240
  maxHeight: "400px",
3236
- position: "below",
3237
3241
  };
3238
3242
  // Vertical positioning
3239
3243
  if (spaceBelow >= menuHeight || spaceBelow >= spaceAbove) {
3240
3244
  // Position below trigger
3241
- position.top = triggerRect.bottom + window.scrollY + 8; // 8px gap
3245
+ position.top = "100%";
3246
+ position.bottom = "auto";
3242
3247
  position.maxHeight = `${Math.min(400, spaceBelow - 16)}px`;
3243
- position.position = "below";
3244
3248
  }
3245
3249
  else {
3246
3250
  // Position above trigger
3247
- position.top = triggerRect.top + window.scrollY - menuHeight - 8; // 8px gap
3251
+ position.top = "auto";
3252
+ position.bottom = "100%";
3248
3253
  position.maxHeight = `${Math.min(400, spaceAbove - 16)}px`;
3249
- position.position = "above";
3254
+ }
3255
+ // Horizontal positioning
3256
+ if (spaceRight >= menuWidth) {
3257
+ // Align to left edge of trigger
3258
+ position.left = "0";
3259
+ position.right = "auto";
3260
+ }
3261
+ else if (spaceLeft >= menuWidth) {
3262
+ // Align to right edge of trigger
3263
+ position.left = "auto";
3264
+ position.right = "0";
3265
+ }
3266
+ else {
3267
+ // Not enough space on either side, try to center or align based on available space
3268
+ if (triggerRect.left + menuWidth > viewportWidth) {
3269
+ position.left = "auto";
3270
+ position.right = "0";
3271
+ }
3272
+ else {
3273
+ position.left = "0";
3274
+ position.right = "auto";
3275
+ }
3250
3276
  }
3251
3277
  setMenuPosition(position);
3252
3278
  };
@@ -3269,29 +3295,16 @@ const Dropdown = React.forwardRef(({ className, trigger, items = [], customConte
3269
3295
  };
3270
3296
  // Render dropdown menu content wrapped in BottomSheet for mobile
3271
3297
  const renderDropdownContent = () => (jsx(DropdownMenu, { ref: ref, items: items, customContent: customContent, customContentClassName: customContentClassName, sectionHeading: sectionHeading, isLoading: isLoading, isEmpty: isEmpty, emptyTitle: emptyTitle, emptyDescription: emptyDescription, emptyLinkText: emptyLinkText, onEmptyLinkClick: onEmptyLinkClick, primaryButtonText: primaryButtonText, secondaryButtonText: secondaryButtonText, onPrimaryClick: onPrimaryClick, onSecondaryClick: onSecondaryClick, showChevron: showChevron, emptyIcon: emptyIcon, disableFooter: disableFooter, showFooter: showFooter, onClose: () => handleOpenChange(false), className: className, width: isMobile ? "full" : sizeMap[size], maxHeight: menuPosition.maxHeight, unstyled: isMobile }));
3272
- // Render the dropdown menu for desktop
3273
- const renderDesktopDropdown = () => {
3274
- if (!isOpen)
3275
- return null;
3276
- const dropdownMenu = (jsx("div", { ref: menuRef, className: cn("fixed z-[1000]", menuClassName), style: {
3277
- top: `${menuPosition.top}px`,
3278
- left: `${menuPosition.left}px`,
3279
- width: `${menuPosition.width}px`,
3280
- }, children: renderDropdownContent() }));
3281
- // Use portal if enabled, otherwise render inline
3282
- return usePortal && typeof document !== 'undefined'
3283
- ? createPortal(dropdownMenu, document.body)
3284
- : (jsx("div", { ref: menuRef, className: cn("absolute z-[1000]", menuClassName), style: {
3285
- top: menuPosition.position === "below" ? "100%" : "auto",
3286
- bottom: menuPosition.position === "above" ? "100%" : "auto",
3287
- left: "0",
3288
- marginTop: menuPosition.position === "below" ? "0.5rem" : "0",
3289
- marginBottom: menuPosition.position === "above" ? "0.5rem" : "0",
3290
- }, children: renderDropdownContent() }));
3291
- };
3292
3298
  return (jsxs("div", { ref: dropdownRef, className: cn("relative inline-block", containerClassName), ...props, children: [trigger && (jsx("div", { onClick: toggleOpen, className: "cursor-pointer", children: trigger })), isMobile ? (jsx(BottomSheet, { isOpen: isOpen, onClose: () => handleOpenChange(false), title: sectionHeading, variant: "default", showDragHandle: true, closeOnOverlayClick: true, closeOnEscape: true, closeOnSwipeDown: true, children: renderDropdownContent() })) : (
3293
- /* Desktop: Regular Dropdown Menu with Portal */
3294
- renderDesktopDropdown())] }));
3299
+ /* Desktop: Regular Dropdown Menu */
3300
+ isOpen && (jsx("div", { ref: menuRef, className: cn("absolute z-50", menuClassName), style: {
3301
+ top: menuPosition.top,
3302
+ bottom: menuPosition.bottom,
3303
+ left: menuPosition.left,
3304
+ right: menuPosition.right,
3305
+ marginTop: menuPosition.top === "100%" ? "0.5rem" : "0",
3306
+ marginBottom: menuPosition.bottom === "100%" ? "0.5rem" : "0",
3307
+ }, children: renderDropdownContent() })))] }));
3295
3308
  });
3296
3309
  Dropdown.displayName = "Dropdown";
3297
3310
 
@@ -3815,7 +3828,7 @@ const Select = React.forwardRef(({ className, options = [], value: controlledVal
3815
3828
  const displaySuffix = suffix ? (jsxs(Fragment, { children: [suffix, chevronIcon] })) : (chevronIcon);
3816
3829
  // Render dropdown menu content
3817
3830
  const renderDropdownContent = () => (jsx(DropdownMenu, { items: menuItems, sectionHeading: sectionHeading, isEmpty: options.length === 0, emptyTitle: emptyTitle, emptyDescription: emptyDescription, emptyIcon: emptyIcon, disableFooter: true, onClose: () => handleOpenChange(false), className: menuClassName, width: isMobile ? "full" : widthStyle, unstyled: isMobile }));
3818
- return (jsxs("div", { ref: containerRef, className: "relative w-full", children: [jsx(TextField, { ref: inputRef, label: label, helperText: helperText, errorText: errorText, successText: successText, validationState: validationState, isDisabled: isDisabled, isRequired: isRequired, isOptional: isOptional, isLoading: isLoading, size: size, prefix: displayPrefix, suffix: displaySuffix, showClearButton: showClearButton && hasValue && !isLoading, onClear: handleClear, placeholder: placeholder, value: displayValue, readOnly: true, containerClassName: cn("w-full", containerClassName), labelClassName: labelClassName, className: cn("cursor-pointer", triggerClassName, className), inputClassName: "cursor-pointer", infoHeading: infoHeading, infoDescription: infoDescription, LinkComponent: LinkComponent, linkText: linkText, linkHref: linkHref, onLinkClick: onLinkClick, onClick: toggleOpen, onKeyDown: handleKeyDown, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isOpen, ...props }), isOpen && !isDisabled && !isLoading && (isMobile ? (jsx(BottomSheet, { isOpen: isOpen, onClose: () => handleOpenChange(false), title: sectionHeading || label, variant: "default", showDragHandle: true, closeOnOverlayClick: true, closeOnEscape: true, closeOnSwipeDown: true, children: renderDropdownContent() })) : (jsx("div", { ref: dropdownContainerRef, className: cn("absolute z-[1000] left-0 right-0", dropdownPlacement === "bottom"
3831
+ return (jsxs("div", { ref: containerRef, className: "relative w-full", children: [jsx(TextField, { ref: inputRef, label: label, helperText: helperText, errorText: errorText, successText: successText, validationState: validationState, isDisabled: isDisabled, isRequired: isRequired, isOptional: isOptional, isLoading: isLoading, size: size, prefix: displayPrefix, suffix: displaySuffix, showClearButton: showClearButton && hasValue && !isLoading, onClear: handleClear, placeholder: placeholder, value: displayValue, readOnly: true, containerClassName: cn("w-full", containerClassName), labelClassName: labelClassName, className: cn("cursor-pointer", triggerClassName, className), inputClassName: "cursor-pointer", infoHeading: infoHeading, infoDescription: infoDescription, LinkComponent: LinkComponent, linkText: linkText, linkHref: linkHref, onLinkClick: onLinkClick, onClick: toggleOpen, onKeyDown: handleKeyDown, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isOpen, ...props }), isOpen && !isDisabled && !isLoading && (isMobile ? (jsx(BottomSheet, { isOpen: isOpen, onClose: () => handleOpenChange(false), title: sectionHeading || label, variant: "default", showDragHandle: true, closeOnOverlayClick: true, closeOnEscape: true, closeOnSwipeDown: true, children: renderDropdownContent() })) : (jsx("div", { ref: dropdownContainerRef, className: cn("absolute z-50 left-0 right-0", dropdownPlacement === "bottom"
3819
3832
  ? "top-full mt-1"
3820
3833
  : "bottom-full mb-1"), children: renderDropdownContent() })))] }));
3821
3834
  });
@@ -4973,7 +4986,7 @@ const SelectTextField = React.forwardRef(({ textValue: controlledTextValue, defa
4973
4986
  ? "text-feedback-ink-positive-intense"
4974
4987
  : currentValidationState === "negative"
4975
4988
  ? "text-feedback-ink-negative-subtle"
4976
- : "text-surface-ink-neutral-muted", isSelectOpen && "transform rotate-180") })] }), isSelectOpen && !effectiveSelectDisabled && (isMobile ? (jsx(BottomSheet, { isOpen: isSelectOpen, onClose: () => handleSelectOpenChange(false), title: selectSectionHeading || label, variant: "default", showDragHandle: true, closeOnOverlayClick: true, closeOnEscape: true, closeOnSwipeDown: true, children: renderDropdownContent() })) : (jsx("div", { ref: dropdownContainerRef, className: cn("absolute z-[1000]", position === "prefix" ? "left-[-12px]" : "right-[-12px]", dropdownPlacement === "bottom"
4989
+ : "text-surface-ink-neutral-muted", isSelectOpen && "transform rotate-180") })] }), isSelectOpen && !effectiveSelectDisabled && (isMobile ? (jsx(BottomSheet, { isOpen: isSelectOpen, onClose: () => handleSelectOpenChange(false), title: selectSectionHeading || label, variant: "default", showDragHandle: true, closeOnOverlayClick: true, closeOnEscape: true, closeOnSwipeDown: true, children: renderDropdownContent() })) : (jsx("div", { ref: dropdownContainerRef, className: cn("absolute z-50", position === "prefix" ? "left-[-12px]" : "right-[-12px]", dropdownPlacement === "bottom"
4977
4990
  ? "top-[30px] mt-1"
4978
4991
  : "bottom-full mb-1"), children: renderDropdownContent() })))] }));
4979
4992
  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, ...(position === "prefix"
@@ -5254,13 +5267,13 @@ function TableHeader({ headerGroups, enableRowSelection, enableSelectAll, showHe
5254
5267
  large: 48,
5255
5268
  auto: 56,
5256
5269
  }[size] ?? 40;
5257
- return (jsx("thead", { className: cn(showHeaderBackground ? "bg-surface-fill-neutral-moderate" : "bg-white", stickyHeader && "sticky top-0 z-[100]"), children: headerGroups.map((headerGroup, groupIndex) => {
5270
+ return (jsx("thead", { className: cn(showHeaderBackground ? "bg-surface-fill-neutral-moderate" : "bg-white", stickyHeader && "sticky top-0 z-[8]"), children: headerGroups.map((headerGroup, groupIndex) => {
5258
5271
  const stickyTop = stickyHeader ? groupIndex * headerHeight : undefined;
5259
- return (jsxs("tr", { children: [enableRowSelection && enableSelectAll && (jsx("th", { className: cn(tableHeaderVariants({ size }), showHeaderBackground && "bg-surface-fill-neutral-moderate", stickyHeader && "sticky z-[101]", "w-10 rounded-tl-xlarge rounded-bl-xlarge", headerClassName), style: { top: stickyTop }, children: jsx(Checkbox, { checked: isAllRowsSelected, isIndeterminate: isSomeRowsSelected, onChange: onToggleAllRows, "aria-label": "Select all rows" }) })), headerGroup.headers.map((header, index) => {
5272
+ return (jsxs("tr", { children: [enableRowSelection && enableSelectAll && (jsx("th", { className: cn(tableHeaderVariants({ size }), showHeaderBackground && "bg-surface-fill-neutral-moderate", stickyHeader && "sticky z-20", "w-10 rounded-tl-xlarge rounded-bl-xlarge", headerClassName), style: { top: stickyTop }, children: jsx(Checkbox, { checked: isAllRowsSelected, isIndeterminate: isSomeRowsSelected, onChange: onToggleAllRows, "aria-label": "Select all rows" }) })), headerGroup.headers.map((header, index) => {
5260
5273
  const isFirstColumn = index === 0;
5261
5274
  const isLastColumn = index === headerGroup.headers.length - 1;
5262
5275
  return (jsx("th", { className: cn(tableHeaderVariants({ size }), showHeaderBackground &&
5263
- "bg-surface-fill-neutral-moderate border-none", stickyHeader && "sticky z-[101]", !enableRowSelection && index === 0 && "rounded-tl-xlarge ", isLastColumn && "rounded-tr-xlarge", header.column.columnDef.meta?.headerClassName, headerClassName), style: {
5276
+ "bg-surface-fill-neutral-moderate border-none", stickyHeader && "sticky z-20", !enableRowSelection && index === 0 && "rounded-tl-xlarge ", isLastColumn && "rounded-tr-xlarge", header.column.columnDef.meta?.headerClassName, headerClassName), style: {
5264
5277
  ...getColumnStyle(header.column.id, {
5265
5278
  width: header.getSize(),
5266
5279
  minWidth: header.column.columnDef.minSize,