infinity-ui-elements 1.9.26 → 1.9.28

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../../../src/components/Dropdown/Dropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,QAAA,MAAM,gBAAgB;;mFAcrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAE5C,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9D;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB;;OAEG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;OAEG;IACH,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,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;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;CACtB;AAED,eAAO,MAAM,QAAQ,sFA4RpB,CAAC;AAIF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../../../src/components/Dropdown/Dropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,QAAA,MAAM,gBAAgB;;mFAcrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAE5C,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9D;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB;;OAEG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;OAEG;IACH,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,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;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;CACtB;AAED,eAAO,MAAM,QAAQ,sFA0RpB,CAAC;AAIF,OAAO,EAAE,gBAAgB,EAAE,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,kGA4gB9B,CAAC"}
package/dist/index.esm.js CHANGED
@@ -3163,14 +3163,12 @@ const Dropdown = React.forwardRef(({ className, trigger, items = [], customConte
3163
3163
  const isOpen = controlledOpen !== undefined ? controlledOpen : uncontrolledOpen;
3164
3164
  const dropdownRef = React.useRef(null);
3165
3165
  const menuRef = React.useRef(null);
3166
- const VIEWPORT_PADDING = 8;
3167
- const MENU_MAX_HEIGHT = 400;
3168
3166
  const [menuPosition, setMenuPosition] = React.useState({
3169
3167
  top: "100%",
3170
3168
  bottom: "auto",
3171
3169
  left: "0",
3172
3170
  right: "auto",
3173
- maxHeight: `${MENU_MAX_HEIGHT}px`,
3171
+ maxHeight: "400px",
3174
3172
  });
3175
3173
  // Detect if we're on mobile (< 768px)
3176
3174
  const [isMobile, setIsMobile] = React.useState(false);
@@ -3229,56 +3227,68 @@ const Dropdown = React.forwardRef(({ className, trigger, items = [], customConte
3229
3227
  const calculatePosition = () => {
3230
3228
  const triggerRect = dropdownRef.current.getBoundingClientRect();
3231
3229
  const menuElement = menuRef.current;
3232
- const currentContainerRect = dropdownRef.current.getBoundingClientRect();
3230
+ // Get menu dimensions (use a temporary measurement if needed)
3233
3231
  const menuRect = menuElement.getBoundingClientRect();
3234
- const menuHeight = menuRect.height || MENU_MAX_HEIGHT;
3235
- const menuWidth = menuRect.width || 320; // fallback for initial render (w-80 = 320px)
3232
+ const menuHeight = menuRect.height || 400; // fallback to max-height
3233
+ const menuWidth = menuRect.width;
3236
3234
  const viewportHeight = window.innerHeight;
3237
3235
  const viewportWidth = window.innerWidth;
3238
- const spaceBelow = viewportHeight - triggerRect.bottom - VIEWPORT_PADDING;
3239
- const spaceAbove = triggerRect.top - VIEWPORT_PADDING;
3236
+ const spaceBelow = viewportHeight - triggerRect.bottom;
3237
+ const spaceAbove = triggerRect.top;
3238
+ const spaceRight = viewportWidth - triggerRect.left;
3239
+ const spaceLeft = triggerRect.right;
3240
3240
  const position = {
3241
- maxHeight: `${MENU_MAX_HEIGHT}px`,
3241
+ top: "auto",
3242
+ bottom: "auto",
3243
+ left: "auto",
3244
+ right: "auto",
3245
+ maxHeight: "400px",
3242
3246
  };
3243
- // Vertical positioning: prefer below, flip above if not enough space
3247
+ // Vertical positioning
3244
3248
  if (spaceBelow >= menuHeight || spaceBelow >= spaceAbove) {
3249
+ // Position below trigger
3245
3250
  position.top = "100%";
3246
3251
  position.bottom = "auto";
3247
- position.maxHeight = `${Math.min(MENU_MAX_HEIGHT, Math.max(0, spaceBelow))}px`;
3252
+ position.maxHeight = `${Math.min(400, spaceBelow - 16)}px`;
3248
3253
  }
3249
3254
  else {
3255
+ // Position above trigger
3250
3256
  position.top = "auto";
3251
3257
  position.bottom = "100%";
3252
- position.maxHeight = `${Math.min(MENU_MAX_HEIGHT, Math.max(0, spaceAbove))}px`;
3258
+ position.maxHeight = `${Math.min(400, spaceAbove - 16)}px`;
3259
+ }
3260
+ // Horizontal positioning
3261
+ if (spaceRight >= menuWidth) {
3262
+ // Align to left edge of trigger
3263
+ position.left = "0";
3264
+ position.right = "auto";
3265
+ }
3266
+ else if (spaceLeft >= menuWidth) {
3267
+ // Align to right edge of trigger
3268
+ position.left = "auto";
3269
+ position.right = "0";
3270
+ }
3271
+ else {
3272
+ // Not enough space on either side, try to center or align based on available space
3273
+ if (triggerRect.left + menuWidth > viewportWidth) {
3274
+ position.left = "auto";
3275
+ position.right = "0";
3276
+ }
3277
+ else {
3278
+ position.left = "0";
3279
+ position.right = "auto";
3280
+ }
3253
3281
  }
3254
- // Horizontal: clamp menu left so it stays within viewport
3255
- const minMenuLeft = VIEWPORT_PADDING;
3256
- const maxMenuLeft = viewportWidth - menuWidth - VIEWPORT_PADDING;
3257
- const desiredMenuLeft = Math.max(minMenuLeft, Math.min(maxMenuLeft, triggerRect.left));
3258
- position.left = `${desiredMenuLeft - currentContainerRect.left}px`;
3259
- position.right = "auto";
3260
3282
  setMenuPosition(position);
3261
3283
  };
3262
- // Run after layout so menu dimensions are correct (double rAF for paint)
3263
- let cancelled = false;
3264
- const scheduleUpdate = () => {
3265
- requestAnimationFrame(() => {
3266
- requestAnimationFrame(() => {
3267
- if (!cancelled &&
3268
- dropdownRef.current &&
3269
- menuRef.current) {
3270
- calculatePosition();
3271
- }
3272
- });
3273
- });
3274
- };
3275
- scheduleUpdate();
3276
- const handleResize = () => scheduleUpdate();
3277
- const handleScroll = () => scheduleUpdate();
3284
+ // Calculate position after menu is rendered
3285
+ calculatePosition();
3286
+ // Recalculate on window resize or scroll
3287
+ const handleResize = () => calculatePosition();
3288
+ const handleScroll = () => calculatePosition();
3278
3289
  window.addEventListener("resize", handleResize);
3279
3290
  window.addEventListener("scroll", handleScroll, true);
3280
3291
  return () => {
3281
- cancelled = true;
3282
3292
  window.removeEventListener("resize", handleResize);
3283
3293
  window.removeEventListener("scroll", handleScroll, true);
3284
3294
  };
@@ -4119,10 +4129,13 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
4119
4129
  const dropdownRef = React.useRef(null);
4120
4130
  const inputRef = React.useRef(null);
4121
4131
  const menuRef = React.useRef(null);
4132
+ const VIEWPORT_PADDING = 8;
4133
+ const MENU_MAX_HEIGHT = 400;
4134
+ const MIN_SPACE_TO_OPEN_BELOW = 200;
4122
4135
  const [position, setPosition] = React.useState({
4123
- top: 0,
4124
4136
  left: 0,
4125
- width: 0,
4137
+ width: 200,
4138
+ maxHeight: MENU_MAX_HEIGHT,
4126
4139
  });
4127
4140
  // Detect if we're on mobile (< 768px)
4128
4141
  React.useEffect(() => {
@@ -4184,17 +4197,50 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
4184
4197
  }
4185
4198
  }
4186
4199
  }, [isOpen]);
4187
- // Update position when dropdown opens or window resizes
4188
- React.useEffect(() => {
4189
- if (isOpen && dropdownRef.current) {
4190
- const rect = dropdownRef.current.getBoundingClientRect();
4200
+ // Update position when dropdown opens or window resizes - viewport coords, open above if not enough space below
4201
+ const updateMenuPosition = React.useCallback(() => {
4202
+ if (!dropdownRef.current)
4203
+ return;
4204
+ const rect = dropdownRef.current.getBoundingClientRect();
4205
+ const viewportHeight = window.innerHeight;
4206
+ const viewportWidth = window.innerWidth;
4207
+ const spaceBelow = viewportHeight - rect.bottom - VIEWPORT_PADDING;
4208
+ const spaceAbove = rect.top - VIEWPORT_PADDING;
4209
+ const openAbove = spaceBelow < MIN_SPACE_TO_OPEN_BELOW || spaceBelow < spaceAbove;
4210
+ const menuLeft = Math.max(VIEWPORT_PADDING, Math.min(rect.left, viewportWidth - Math.max(rect.width, 200) - VIEWPORT_PADDING));
4211
+ const menuWidth = Math.max(rect.width, 200);
4212
+ if (openAbove) {
4191
4213
  setPosition({
4192
- top: rect.bottom + window.scrollY,
4193
- left: rect.left + window.scrollX,
4194
- width: rect.width,
4214
+ bottom: viewportHeight - rect.top + VIEWPORT_PADDING,
4215
+ left: menuLeft,
4216
+ width: menuWidth,
4217
+ maxHeight: Math.max(120, Math.min(MENU_MAX_HEIGHT, spaceAbove)),
4195
4218
  });
4196
4219
  }
4197
- }, [isOpen]);
4220
+ else {
4221
+ setPosition({
4222
+ top: rect.bottom + VIEWPORT_PADDING,
4223
+ left: menuLeft,
4224
+ width: menuWidth,
4225
+ maxHeight: Math.max(120, Math.min(MENU_MAX_HEIGHT, spaceBelow)),
4226
+ });
4227
+ }
4228
+ }, []);
4229
+ React.useLayoutEffect(() => {
4230
+ if (isOpen) {
4231
+ updateMenuPosition();
4232
+ }
4233
+ }, [isOpen, updateMenuPosition]);
4234
+ React.useEffect(() => {
4235
+ if (!isOpen)
4236
+ return;
4237
+ window.addEventListener("resize", updateMenuPosition);
4238
+ window.addEventListener("scroll", updateMenuPosition, true);
4239
+ return () => {
4240
+ window.removeEventListener("resize", updateMenuPosition);
4241
+ window.removeEventListener("scroll", updateMenuPosition, true);
4242
+ };
4243
+ }, [isOpen, updateMenuPosition]);
4198
4244
  const searchValue = controlledSearchValue !== undefined
4199
4245
  ? controlledSearchValue
4200
4246
  : uncontrolledSearchValue;
@@ -4372,11 +4418,14 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
4372
4418
  // Render dropdown menu content
4373
4419
  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
4420
  ? true
4375
- : false, footerLayout: footerLayout, onClose: () => setIsOpen(false), focusedIndex: focusedIndex, className: dropdownClassName, width: isMobile ? "full" : (dropdownWidth === "full" ? "full" : "auto"), unstyled: isMobile }));
4421
+ : false, footerLayout: footerLayout, onClose: () => setIsOpen(false), focusedIndex: focusedIndex, className: dropdownClassName, width: isMobile ? "full" : (dropdownWidth === "full" ? "full" : "auto"), maxHeight: `${position.maxHeight}px`, unstyled: isMobile }));
4376
4422
  // Mobile: BottomSheet, Desktop: Regular Dropdown
4377
4423
  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`,
4424
+ position: "fixed",
4425
+ ...(position.top !== undefined && { top: `${position.top}px` }),
4426
+ ...(position.bottom !== undefined && {
4427
+ bottom: `${position.bottom}px`,
4428
+ }),
4380
4429
  left: `${position.left}px`,
4381
4430
  width: dropdownWidth === "full" ? `${position.width}px` : "auto",
4382
4431
  zIndex: isInsideModal ? 10001 : 9999,