infinity-ui-elements 1.9.26 → 1.9.27

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.
@@ -107,6 +107,12 @@ export interface DropdownMenuProps {
107
107
  * Whether to remove container styling (useful when nested in BottomSheet)
108
108
  */
109
109
  unstyled?: boolean;
110
+ /**
111
+ * When true, constrains the menu's max height and width to stay within the viewport.
112
+ * Useful when the menu is rendered in a portal (e.g. by SearchableDropdown).
113
+ * @default true
114
+ */
115
+ constrainToViewport?: boolean;
110
116
  }
111
117
  export declare const DropdownMenu: React.ForwardRefExoticComponent<DropdownMenuProps & React.RefAttributes<HTMLDivElement>>;
112
118
  //# sourceMappingURL=DropdownMenu.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../../src/components/Dropdown/DropdownMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;CAC3D;AAED,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACzC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,YAAY,0FA2MxB,CAAC"}
1
+ {"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../../src/components/Dropdown/DropdownMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;CAC3D;AAED,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACzC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,eAAO,MAAM,YAAY,0FAkRxB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchableDropdown.d.ts","sourceRoot":"","sources":["../../../src/components/SearchableDropdown/SearchableDropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG/E,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,uBACf,SAAQ,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,OAAO,CAAC;IAClD;;OAEG;IACH,KAAK,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACjC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACzC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACtD;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1E;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B;;OAEG;IACH,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAClC,IAAI,EAAE,sBAAsB,GAAG,SAAS,KACrC,IAAI,CAAC;CACX;AAaD,eAAO,MAAM,kBAAkB,kGAud9B,CAAC"}
1
+ {"version":3,"file":"SearchableDropdown.d.ts","sourceRoot":"","sources":["../../../src/components/SearchableDropdown/SearchableDropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG/E,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,uBACf,SAAQ,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,OAAO,CAAC;IAClD;;OAEG;IACH,KAAK,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACjC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACzC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACtD;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1E;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B;;OAEG;IACH,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAClC,IAAI,EAAE,sBAAsB,GAAG,SAAS,KACrC,IAAI,CAAC;CACX;AAaD,eAAO,MAAM,kBAAkB,kGAmf9B,CAAC"}
package/dist/index.esm.js CHANGED
@@ -3117,29 +3117,79 @@ 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", unstyled = false, }, 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, constrainToViewport = true, }, ref) => {
3121
+ const menuRef = React.useRef(null);
3122
+ const [viewportConstraints, setViewportConstraints] = React.useState({ maxHeight: null, maxWidth: null });
3123
+ const setRef = React.useCallback((el) => {
3124
+ menuRef.current = el;
3125
+ if (typeof ref === "function")
3126
+ ref(el);
3127
+ else if (ref)
3128
+ ref.current = el;
3129
+ }, [ref]);
3130
+ React.useEffect(() => {
3131
+ if (!constrainToViewport || !menuRef.current)
3132
+ return;
3133
+ const VIEWPORT_PADDING = 8;
3134
+ const updateConstraints = () => {
3135
+ const el = menuRef.current;
3136
+ if (!el)
3137
+ return;
3138
+ const rect = el.getBoundingClientRect();
3139
+ const viewportHeight = window.innerHeight;
3140
+ const viewportWidth = window.innerWidth;
3141
+ const spaceBelow = viewportHeight - rect.bottom - VIEWPORT_PADDING;
3142
+ const spaceRight = viewportWidth - rect.left - VIEWPORT_PADDING;
3143
+ setViewportConstraints({
3144
+ maxHeight: Math.max(0, Math.floor(spaceBelow)),
3145
+ maxWidth: rect.right > viewportWidth - VIEWPORT_PADDING
3146
+ ? Math.max(0, Math.floor(spaceRight))
3147
+ : null,
3148
+ });
3149
+ };
3150
+ const runAfterPaint = () => {
3151
+ requestAnimationFrame(() => {
3152
+ requestAnimationFrame(updateConstraints);
3153
+ });
3154
+ };
3155
+ runAfterPaint();
3156
+ window.addEventListener("resize", runAfterPaint);
3157
+ window.addEventListener("scroll", runAfterPaint, true);
3158
+ return () => {
3159
+ window.removeEventListener("resize", runAfterPaint);
3160
+ window.removeEventListener("scroll", runAfterPaint, true);
3161
+ };
3162
+ }, [constrainToViewport]);
3163
+ const parsedMaxHeight = parseInt(String(maxHeight), 10) || 400;
3164
+ const effectiveMaxHeight = viewportConstraints.maxHeight !== null
3165
+ ? `${Math.min(parsedMaxHeight, viewportConstraints.maxHeight)}px`
3166
+ : maxHeight;
3167
+ const effectiveMaxWidth = viewportConstraints.maxWidth !== null
3168
+ ? `${viewportConstraints.maxWidth}px`
3169
+ : undefined;
3121
3170
  const renderContent = () => {
3122
3171
  if (isLoading) {
3123
3172
  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" }) }));
3124
3173
  }
3125
3174
  if (customContent) {
3126
- return (jsxs("div", { className: `py-3 px-3 overflow-y-auto ${customContentClassName}`, style: { maxHeight }, children: [sectionHeading && (jsx(Text, { as: "div", variant: "body", size: "small", weight: "medium", className: "text-body-small-medium text-surface-ink-neutral-muted px-3 py-2 mb-1", children: sectionHeading })), jsx("div", { children: customContent })] }));
3175
+ return (jsxs("div", { className: `py-3 px-3 overflow-y-auto ${customContentClassName}`, style: { maxHeight: effectiveMaxHeight, maxWidth: effectiveMaxWidth }, children: [sectionHeading && (jsx(Text, { as: "div", variant: "body", size: "small", weight: "medium", className: "text-body-small-medium text-surface-ink-neutral-muted px-3 py-2 mb-1", children: sectionHeading })), jsx("div", { children: customContent })] }));
3127
3176
  }
3128
3177
  if (isEmpty || items.length === 0) {
3129
3178
  return (jsxs("div", { className: "flex flex-col items-center justify-center py-8 px-6 text-center", children: [emptyIcon || (jsx(Search, { className: "w-12 h-12 text-surface-ink-neutral-muted mb-4" })), jsx(Text, { as: "h3", variant: "body", size: "small", weight: "semibold", className: "text-surface-ink-neutral-normal mb-2", children: emptyTitle }), jsx(Text, { as: "p", variant: "body", size: "small", weight: "regular", className: "text-surface-ink-neutral-muted mb-3", children: emptyDescription }), emptyLinkText && (jsx(Link, { type: "anchor", color: "primary", size: "small", onClick: onEmptyLinkClick, children: emptyLinkText }))] }));
3130
3179
  }
3131
- return (jsxs("div", { className: `py-3 px-3 overflow-y-auto`, style: { maxHeight }, children: [sectionHeading && (jsx(Text, { as: "div", variant: "body", size: "small", weight: "medium", className: "text-surface-ink-neutral-muted px-3 py-2 mb-1", children: sectionHeading })), jsx("div", { className: "flex flex-col gap-1", children: items.map((item, index) => (jsx(ListItem, { title: item.label, description: item.description, leadingIcon: item.leadingIcon, trailingIcon: item.trailingIcon, showChevron: showChevron, isDisabled: item.isDisabled, isSelected: index === focusedIndex, variant: item.variant, onClick: () => {
3180
+ return (jsxs("div", { className: `py-3 px-3 overflow-y-auto`, style: { maxHeight: effectiveMaxHeight, maxWidth: effectiveMaxWidth }, children: [sectionHeading && (jsx(Text, { as: "div", variant: "body", size: "small", weight: "medium", className: "text-surface-ink-neutral-muted px-3 py-2 mb-1", children: sectionHeading })), jsx("div", { className: "flex flex-col gap-1", children: items.map((item, index) => (jsx(ListItem, { title: item.label, description: item.description, leadingIcon: item.leadingIcon, trailingIcon: item.trailingIcon, showChevron: showChevron, isDisabled: item.isDisabled, isSelected: index === focusedIndex, variant: item.variant, onClick: () => {
3132
3181
  item.onClick?.();
3133
3182
  onClose?.();
3134
3183
  }, containerClassName: cn(index === focusedIndex && "bg-action-fill-primary-faded") }, item.value))) })] }));
3135
3184
  };
3136
3185
  const widthClass = width === "full" ? "w-full" : width === "auto" ? "w-auto" : "";
3137
3186
  const footerVisible = showFooter ?? !disableFooter;
3138
- return (jsxs("div", { ref: ref, className: cn(!unstyled && "bg-white rounded-large overflow-hidden", unstyled && "w-full", widthClass, className), style: {
3187
+ return (jsxs("div", { ref: setRef, className: cn(!unstyled && "bg-white rounded-large overflow-hidden", unstyled && "w-full", widthClass, className), style: {
3139
3188
  ...(!unstyled && {
3140
3189
  boxShadow: "0 1px 2px rgba(25, 25, 30, 0.1), 0 2px 6px rgba(25, 25, 30, 0.06)",
3141
3190
  }),
3142
3191
  ...(width !== "full" && width !== "auto" ? { width } : {}),
3192
+ ...(effectiveMaxWidth ? { maxWidth: effectiveMaxWidth } : {}),
3143
3193
  }, 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"
3144
3194
  ? "flex-col"
3145
3195
  : "items-center flex-row"), children: [onSecondaryClick && (jsx(Button, { variant: "secondary", color: "primary", size: "medium", isFullWidth: true, onClick: onSecondaryClick, children: secondaryButtonText })), onPrimaryClick && (jsx(Button, { variant: "primary", color: "primary", size: "medium", isFullWidth: true, onClick: onPrimaryClick, children: primaryButtonText }))] })] }))] }));
@@ -4119,10 +4169,12 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
4119
4169
  const dropdownRef = React.useRef(null);
4120
4170
  const inputRef = React.useRef(null);
4121
4171
  const menuRef = React.useRef(null);
4172
+ const VIEWPORT_PADDING = 8;
4122
4173
  const [position, setPosition] = React.useState({
4123
4174
  top: 0,
4124
4175
  left: 0,
4125
4176
  width: 0,
4177
+ maxHeight: 400,
4126
4178
  });
4127
4179
  // Detect if we're on mobile (< 768px)
4128
4180
  React.useEffect(() => {
@@ -4184,17 +4236,38 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
4184
4236
  }
4185
4237
  }
4186
4238
  }, [isOpen]);
4187
- // Update position when dropdown opens or window resizes
4188
- React.useEffect(() => {
4189
- if (isOpen && dropdownRef.current) {
4190
- const rect = dropdownRef.current.getBoundingClientRect();
4191
- setPosition({
4192
- top: rect.bottom + window.scrollY,
4193
- left: rect.left + window.scrollX,
4194
- width: rect.width,
4195
- });
4239
+ // Update position when dropdown opens or window resizes - use viewport coords for portal
4240
+ const updateMenuPosition = React.useCallback(() => {
4241
+ if (!dropdownRef.current)
4242
+ return;
4243
+ const rect = dropdownRef.current.getBoundingClientRect();
4244
+ const viewportHeight = window.innerHeight;
4245
+ const viewportWidth = window.innerWidth;
4246
+ const spaceBelow = viewportHeight - rect.bottom - VIEWPORT_PADDING;
4247
+ const menuTop = rect.bottom + VIEWPORT_PADDING;
4248
+ const menuLeft = Math.max(VIEWPORT_PADDING, Math.min(rect.left, viewportWidth - rect.width - VIEWPORT_PADDING));
4249
+ setPosition({
4250
+ top: menuTop,
4251
+ left: menuLeft,
4252
+ width: rect.width,
4253
+ maxHeight: Math.max(0, Math.min(400, spaceBelow)),
4254
+ });
4255
+ }, []);
4256
+ React.useLayoutEffect(() => {
4257
+ if (isOpen) {
4258
+ updateMenuPosition();
4196
4259
  }
4197
- }, [isOpen]);
4260
+ }, [isOpen, updateMenuPosition]);
4261
+ React.useEffect(() => {
4262
+ if (!isOpen)
4263
+ return;
4264
+ window.addEventListener("resize", updateMenuPosition);
4265
+ window.addEventListener("scroll", updateMenuPosition, true);
4266
+ return () => {
4267
+ window.removeEventListener("resize", updateMenuPosition);
4268
+ window.removeEventListener("scroll", updateMenuPosition, true);
4269
+ };
4270
+ }, [isOpen, updateMenuPosition]);
4198
4271
  const searchValue = controlledSearchValue !== undefined
4199
4272
  ? controlledSearchValue
4200
4273
  : uncontrolledSearchValue;
@@ -4372,11 +4445,11 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
4372
4445
  // Render dropdown menu content
4373
4446
  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
4374
4447
  ? true
4375
- : false, footerLayout: footerLayout, onClose: () => setIsOpen(false), focusedIndex: focusedIndex, className: dropdownClassName, width: isMobile ? "full" : (dropdownWidth === "full" ? "full" : "auto"), unstyled: isMobile }));
4448
+ : false, footerLayout: footerLayout, onClose: () => setIsOpen(false), focusedIndex: focusedIndex, className: dropdownClassName, width: isMobile ? "full" : (dropdownWidth === "full" ? "full" : "auto"), maxHeight: `${position.maxHeight}px`, unstyled: isMobile, constrainToViewport: true }));
4376
4449
  // Mobile: BottomSheet, Desktop: Regular Dropdown
4377
4450
  const dropdownMenu = showDropdown && (isMobile ? (jsxs(BottomSheet, { isOpen: isOpen, onClose: () => setIsOpen(false), title: sectionHeading, variant: "default", showDragHandle: true, closeOnOverlayClick: true, closeOnEscape: true, closeOnSwipeDown: true, children: [jsx("div", { className: "mb-4", children: jsx(TextField, { value: searchValue, onChange: handleSearchChange, onKeyDown: handleKeyDown, containerClassName: "mb-0", placeholder: textFieldProps.placeholder || "Search...", autoFocus: true, ...textFieldProps }) }), renderDropdownContent()] })) : (jsx("div", { ref: menuRef, style: {
4378
- position: "absolute",
4379
- top: `${position.top + 8}px`,
4451
+ position: "fixed",
4452
+ top: `${position.top}px`,
4380
4453
  left: `${position.left}px`,
4381
4454
  width: dropdownWidth === "full" ? `${position.width}px` : "auto",
4382
4455
  zIndex: isInsideModal ? 10001 : 9999,