infinity-ui-elements 1.9.17 → 1.9.19

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
@@ -3117,7 +3117,7 @@ const DateRangePicker = React.forwardRef(({ className, value: controlledValue, d
3117
3117
  });
3118
3118
  DateRangePicker.displayName = "DateRangePicker";
3119
3119
 
3120
- const DropdownMenu = React.forwardRef(({ 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, showChevron = false, emptyIcon, disableFooter = false, showFooter, footerLayout = "horizontal", onClose, focusedIndex = -1, className, width = "auto", maxHeight = "400px", }, ref) => {
3120
+ const DropdownMenu = React.forwardRef(({ 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, showChevron = false, emptyIcon, disableFooter = false, showFooter, footerLayout = "horizontal", onClose, focusedIndex = -1, className, width = "auto", maxHeight = "400px", unstyled = false, }, ref) => {
3121
3121
  const renderContent = () => {
3122
3122
  if (isLoading) {
3123
3123
  return (jsx("div", { className: "flex flex-col items-center justify-center py-12 px-6", children: jsx(Loader2, { className: "w-12 h-12 text-action-ink-primary-normal mb-4 animate-spin" }) }));
@@ -3135,8 +3135,10 @@ const DropdownMenu = React.forwardRef(({ items = [], customContent, customConten
3135
3135
  };
3136
3136
  const widthClass = width === "full" ? "w-full" : width === "auto" ? "w-auto" : "";
3137
3137
  const footerVisible = showFooter ?? !disableFooter;
3138
- return (jsxs("div", { ref: ref, className: cn("bg-white rounded-large overflow-hidden", widthClass, className), style: {
3139
- boxShadow: "0 1px 2px rgba(25, 25, 30, 0.1), 0 2px 6px rgba(25, 25, 30, 0.06)",
3138
+ return (jsxs("div", { ref: ref, className: cn(!unstyled && "bg-white rounded-large overflow-hidden", unstyled && "w-full", widthClass, className), style: {
3139
+ ...(!unstyled && {
3140
+ boxShadow: "0 1px 2px rgba(25, 25, 30, 0.1), 0 2px 6px rgba(25, 25, 30, 0.06)",
3141
+ }),
3140
3142
  ...(width !== "full" && width !== "auto" ? { width } : {}),
3141
3143
  }, children: [renderContent(), footerVisible && (jsxs("div", { className: "flex flex-col", children: [jsx(Divider, { thickness: "thin", variant: "muted" }), jsxs("div", { className: cn("flex gap-3 p-4", footerLayout === "vertical"
3142
3144
  ? "flex-col"
@@ -3168,6 +3170,18 @@ const Dropdown = React.forwardRef(({ className, trigger, items = [], customConte
3168
3170
  right: "auto",
3169
3171
  maxHeight: "400px",
3170
3172
  });
3173
+ // Detect if we're on mobile (< 768px)
3174
+ const [isMobile, setIsMobile] = React.useState(false);
3175
+ React.useEffect(() => {
3176
+ const checkMobile = () => {
3177
+ setIsMobile(window.innerWidth < 768);
3178
+ };
3179
+ // Check on mount
3180
+ checkMobile();
3181
+ // Add resize listener
3182
+ window.addEventListener('resize', checkMobile);
3183
+ return () => window.removeEventListener('resize', checkMobile);
3184
+ }, []);
3171
3185
  const handleOpenChange = (newOpen) => {
3172
3186
  if (controlledOpen === undefined) {
3173
3187
  setUncontrolledOpen(newOpen);
@@ -3284,14 +3298,18 @@ const Dropdown = React.forwardRef(({ className, trigger, items = [], customConte
3284
3298
  medium: "w-80",
3285
3299
  large: "w-96",
3286
3300
  };
3287
- return (jsxs("div", { ref: dropdownRef, className: cn("relative inline-block", containerClassName), ...props, children: [trigger && (jsx("div", { onClick: toggleOpen, className: "cursor-pointer", children: trigger })), isOpen && (jsx("div", { ref: menuRef, className: cn("absolute z-50", menuClassName), style: {
3301
+ // Render dropdown menu content wrapped in BottomSheet for mobile
3302
+ 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 }));
3303
+ 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() })) : (
3304
+ /* Desktop: Regular Dropdown Menu */
3305
+ isOpen && (jsx("div", { ref: menuRef, className: cn("absolute z-50", menuClassName), style: {
3288
3306
  top: menuPosition.top,
3289
3307
  bottom: menuPosition.bottom,
3290
3308
  left: menuPosition.left,
3291
3309
  right: menuPosition.right,
3292
3310
  marginTop: menuPosition.top === "100%" ? "0.5rem" : "0",
3293
3311
  marginBottom: menuPosition.bottom === "100%" ? "0.5rem" : "0",
3294
- }, children: 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: sizeMap[size], maxHeight: menuPosition.maxHeight }) }))] }));
3312
+ }, children: renderDropdownContent() })))] }));
3295
3313
  });
3296
3314
  Dropdown.displayName = "Dropdown";
3297
3315
 
@@ -4075,6 +4093,7 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
4075
4093
  const [isOpen, setIsOpen] = React.useState(false);
4076
4094
  const [focusedIndex, setFocusedIndex] = React.useState(-1);
4077
4095
  const [isInsideModal, setIsInsideModal] = React.useState(false);
4096
+ const [isMobile, setIsMobile] = React.useState(false);
4078
4097
  const dropdownRef = React.useRef(null);
4079
4098
  const inputRef = React.useRef(null);
4080
4099
  const menuRef = React.useRef(null);
@@ -4083,6 +4102,17 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
4083
4102
  left: 0,
4084
4103
  width: 0,
4085
4104
  });
4105
+ // Detect if we're on mobile (< 768px)
4106
+ React.useEffect(() => {
4107
+ const checkMobile = () => {
4108
+ setIsMobile(window.innerWidth < 768);
4109
+ };
4110
+ // Check on mount
4111
+ checkMobile();
4112
+ // Add resize listener
4113
+ window.addEventListener('resize', checkMobile);
4114
+ return () => window.removeEventListener('resize', checkMobile);
4115
+ }, []);
4086
4116
  React.useImperativeHandle(ref, () => inputRef.current);
4087
4117
  // Determine current value (controlled or uncontrolled)
4088
4118
  const value = controlledValue !== undefined ? controlledValue : uncontrolledValue;
@@ -4317,15 +4347,18 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
4317
4347
  };
4318
4348
  });
4319
4349
  const showDropdown = isOpen && searchValue.length >= minSearchLength;
4320
- const dropdownMenu = showDropdown && (jsx("div", { ref: menuRef, style: {
4350
+ // Render dropdown menu content
4351
+ const renderDropdownContent = () => (jsx(DropdownMenu, { items: itemsWithHandlers, sectionHeading: sectionHeading, isLoading: isLoading, isEmpty: itemsWithAddNew.length === 0 && !showAddNew, emptyTitle: emptyTitle, emptyDescription: emptyDescription, emptyLinkText: emptyLinkText, onEmptyLinkClick: onEmptyLinkClick, primaryButtonText: primaryButtonText, secondaryButtonText: secondaryButtonText, onPrimaryClick: onPrimaryClick, onSecondaryClick: onSecondaryClick, showChevron: showChevron, emptyIcon: emptyIcon, disableFooter: disableFooter, showFooter: (primaryButtonText || secondaryButtonText) && !disableFooter
4352
+ ? true
4353
+ : false, footerLayout: footerLayout, onClose: () => setIsOpen(false), focusedIndex: focusedIndex, className: dropdownClassName, width: isMobile ? "full" : (dropdownWidth === "full" ? "full" : "auto"), unstyled: isMobile }));
4354
+ // Mobile: BottomSheet, Desktop: Regular Dropdown
4355
+ const dropdownMenu = showDropdown && (isMobile ? (jsx(BottomSheet, { isOpen: isOpen, onClose: () => setIsOpen(false), title: sectionHeading, variant: "default", showDragHandle: true, closeOnOverlayClick: true, closeOnEscape: true, closeOnSwipeDown: true, children: renderDropdownContent() })) : (jsx("div", { ref: menuRef, style: {
4321
4356
  position: "absolute",
4322
4357
  top: `${position.top + 8}px`,
4323
4358
  left: `${position.left}px`,
4324
4359
  width: dropdownWidth === "full" ? `${position.width}px` : "auto",
4325
4360
  zIndex: isInsideModal ? 10001 : 9999,
4326
- }, children: jsx(DropdownMenu, { items: itemsWithHandlers, sectionHeading: sectionHeading, isLoading: isLoading, isEmpty: itemsWithAddNew.length === 0 && !showAddNew, emptyTitle: emptyTitle, emptyDescription: emptyDescription, emptyLinkText: emptyLinkText, onEmptyLinkClick: onEmptyLinkClick, primaryButtonText: primaryButtonText, secondaryButtonText: secondaryButtonText, onPrimaryClick: onPrimaryClick, onSecondaryClick: onSecondaryClick, showChevron: showChevron, emptyIcon: emptyIcon, disableFooter: disableFooter, showFooter: (primaryButtonText || secondaryButtonText) && !disableFooter
4327
- ? true
4328
- : false, footerLayout: footerLayout, onClose: () => setIsOpen(false), focusedIndex: focusedIndex, className: dropdownClassName, width: dropdownWidth === "full" ? "full" : "auto" }) }));
4361
+ }, children: renderDropdownContent() })));
4329
4362
  return (jsxs(Fragment, { children: [jsx("div", { ref: dropdownRef, className: cn("relative", containerClassName), children: jsx(TextField, { ref: inputRef, value: searchValue, onChange: handleSearchChange, onFocus: handleFocus, onKeyDown: handleKeyDown, containerClassName: "mb-0", ...textFieldProps }) }), typeof document !== "undefined" &&
4330
4363
  dropdownMenu &&
4331
4364
  createPortal(dropdownMenu, document.body)] }));
@@ -4337,12 +4370,12 @@ const SidePanel = React.forwardRef(({ isOpen, onClose, title, titleIcon, descrip
4337
4370
  const contentRef = ref || panelRef;
4338
4371
  const [isVisible, setIsVisible] = React.useState(false);
4339
4372
  const [shouldRender, setShouldRender] = React.useState(false);
4340
- // Width configurations
4373
+ // Width configurations - full width on mobile, specified width on tablet/desktop
4341
4374
  const widthConfig = {
4342
- small: "w-80",
4343
- medium: "w-96",
4344
- large: "w-[32rem]",
4345
- xlarge: "w-[40rem]",
4375
+ small: "w-full md:w-80",
4376
+ medium: "w-full md:w-96",
4377
+ large: "w-full md:w-[32rem]",
4378
+ xlarge: "w-full md:w-[40rem]",
4346
4379
  };
4347
4380
  // Handle mounting and unmounting with animation
4348
4381
  React.useEffect(() => {
@@ -4414,7 +4447,7 @@ const SidePanel = React.forwardRef(({ isOpen, onClose, title, titleIcon, descrip
4414
4447
  const widthClass = width in widthConfig
4415
4448
  ? widthConfig[width]
4416
4449
  : width;
4417
- return (jsxs("div", { className: cn("fixed inset-0 z-9999 flex p-4", positionClasses[position].container, className), role: "dialog", "aria-modal": "true", "aria-label": ariaLabel || title, "aria-describedby": ariaDescribedBy, children: [jsx("div", { className: cn("absolute inset-0 bg-black/50 backdrop-blur-sm transition-opacity duration-300", isVisible ? "opacity-100" : "opacity-0", overlayClassName), onClick: handleOverlayClick, "aria-hidden": "true" }), jsxs("div", { ref: contentRef, className: cn("relative bg-white shadow-2xl transition-transform duration-300 ease-out rounded-large", "flex flex-col max-w-full overflow-hidden", position === "center" ? "max-h-[90vh]" : "h-full", widthClass, positionClasses[position].panel, contentClassName), children: [hasHeader && (jsxs("div", { className: cn("flex items-center justify-between gap-4 px-7 py-5 shrink-0 border-b border-surface-outline-neutral-subtle", headerClassName), children: [jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [titleIcon && (jsx("div", { className: "flex items-center justify-center shrink-0", children: typeof titleIcon === "string" ? (jsx(Icon, { name: titleIcon, size: 20 })) : (titleIcon) })), jsxs("div", { className: "flex flex-col flex-1 min-w-0", children: [title && (jsx(Text, { as: "h2", variant: "body", size: "large", weight: "semibold", color: "default", className: "truncate", children: title })), description && (jsx(Text, { as: "p", variant: "body", size: "small", weight: "regular", color: "subtle", className: "mt-0.5", children: description }))] })] }), jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [headerActions, showCloseButton && onClose && (jsx(IconButton, { icon: "close", onClick: onClose, color: "neutral", size: "small", "aria-label": "Close side panel" }))] })] })), !hasHeader && showCloseButton && onClose && (jsx("div", { className: "absolute top-4 right-4 z-10", children: jsx(IconButton, { icon: "close", onClick: onClose, color: "neutral", size: "small", "aria-label": "Close side panel" }) })), jsx("div", { className: cn("flex-1 overflow-y-auto px-6", hasHeader ? "py-6" : "pt-6 pb-4", !footer && "pb-6", bodyClassName), children: children }), footer && (jsxs("div", { className: "flex flex-col shrink-0", children: [jsx(Divider, { thickness: "thin", variant: "muted" }), jsx("div", { className: cn("flex items-center justify-end gap-3 px-6 py-4", footerClassName), children: footer })] }))] })] }));
4450
+ return (jsxs("div", { className: cn("fixed inset-0 z-9999 flex p-0 md:p-4", positionClasses[position].container, className), role: "dialog", "aria-modal": "true", "aria-label": ariaLabel || title, "aria-describedby": ariaDescribedBy, children: [jsx("div", { className: cn("absolute inset-0 bg-black/50 backdrop-blur-sm transition-opacity duration-300", isVisible ? "opacity-100" : "opacity-0", overlayClassName), onClick: handleOverlayClick, "aria-hidden": "true" }), jsxs("div", { ref: contentRef, className: cn("relative bg-white shadow-2xl transition-transform duration-300 ease-out rounded-none md:rounded-large", "flex flex-col max-w-full overflow-hidden", position === "center" ? "max-h-[90vh]" : "h-full", widthClass, positionClasses[position].panel, contentClassName), children: [hasHeader && (jsxs("div", { className: cn("flex items-center justify-between gap-4 px-7 py-5 shrink-0 border-b border-surface-outline-neutral-subtle", headerClassName), children: [jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [titleIcon && (jsx("div", { className: "flex items-center justify-center shrink-0", children: typeof titleIcon === "string" ? (jsx(Icon, { name: titleIcon, size: 20 })) : (titleIcon) })), jsxs("div", { className: "flex flex-col flex-1 min-w-0", children: [title && (jsx(Text, { as: "h2", variant: "body", size: "large", weight: "semibold", color: "default", className: "truncate", children: title })), description && (jsx(Text, { as: "p", variant: "body", size: "small", weight: "regular", color: "subtle", className: "mt-0.5", children: description }))] })] }), jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [headerActions, showCloseButton && onClose && (jsx(IconButton, { icon: "close", onClick: onClose, color: "neutral", size: "small", "aria-label": "Close side panel" }))] })] })), !hasHeader && showCloseButton && onClose && (jsx("div", { className: "absolute top-4 right-4 z-10", children: jsx(IconButton, { icon: "close", onClick: onClose, color: "neutral", size: "small", "aria-label": "Close side panel" }) })), jsx("div", { className: cn("flex-1 overflow-y-auto px-6", hasHeader ? "py-6" : "pt-6 pb-4", !footer && "pb-6", bodyClassName), children: children }), footer && (jsxs("div", { className: "flex flex-col shrink-0", children: [jsx(Divider, { thickness: "thin", variant: "muted" }), jsx("div", { className: cn("flex items-center justify-end gap-3 px-6 py-4", footerClassName), children: footer })] }))] })] }));
4418
4451
  });
4419
4452
  SidePanel.displayName = "SidePanel";
4420
4453