funda-ui 4.7.525 → 4.7.545

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.
@@ -2322,6 +2322,7 @@ var CascadingSelect = /*#__PURE__*/(0,external_root_React_commonjs2_react_common
2322
2322
  var rootRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2323
2323
  var inputRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2324
2324
  var listRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2325
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
2325
2326
 
2326
2327
  // searchable
2327
2328
  var _useState = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)([]),
@@ -2439,7 +2440,7 @@ var CascadingSelect = /*#__PURE__*/(0,external_root_React_commonjs2_react_common
2439
2440
  // STEP 2:
2440
2441
  //-----------
2441
2442
  // Detect position
2442
- if (window.innerHeight - _triggerBox.top > 100) {
2443
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
2443
2444
  targetPos = 'bottom';
2444
2445
  } else {
2445
2446
  targetPos = 'top';
@@ -2679,6 +2679,7 @@ var CascadingSelectE2E = /*#__PURE__*/(0,external_root_React_commonjs2_react_com
2679
2679
  var rootRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2680
2680
  var inputRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2681
2681
  var listRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2682
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
2682
2683
 
2683
2684
  // searchable
2684
2685
  var _useState = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)([]),
@@ -2821,7 +2822,7 @@ var CascadingSelectE2E = /*#__PURE__*/(0,external_root_React_commonjs2_react_com
2821
2822
  // STEP 2:
2822
2823
  //-----------
2823
2824
  // Detect position
2824
- if (window.innerHeight - _triggerBox.top > 100) {
2825
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
2825
2826
  targetPos = 'bottom';
2826
2827
  } else {
2827
2828
  targetPos = 'top';
package/Date/index.js CHANGED
@@ -5034,6 +5034,8 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5034
5034
  langToday = props.langToday,
5035
5035
  attributes = _objectWithoutProperties(props, _excluded);
5036
5036
  var DEPTH = depth || 1055; // the default value same as bootstrap
5037
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
5038
+
5037
5039
  var defaultValueIsEmpty = function defaultValueIsEmpty(s) {
5038
5040
  return typeof s === 'undefined' || s === null || s === 'null' || s === '';
5039
5041
  };
@@ -5328,7 +5330,7 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5328
5330
  // STEP 1:
5329
5331
  //-----------
5330
5332
  // Detect position
5331
- if (window.innerHeight - _triggerBox.top > 100) {
5333
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
5332
5334
  targetPos = 'bottom';
5333
5335
  } else {
5334
5336
  targetPos = 'top';
@@ -1285,6 +1285,8 @@ var DropdownMenu = function DropdownMenu(props) {
1285
1285
  selected = _useState4[0],
1286
1286
  setSelected = _useState4[1];
1287
1287
  var _hoverDelay = !isNaN(hoverDelay) && typeof hoverDelay !== 'undefined' ? hoverDelay : 150;
1288
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
1289
+
1288
1290
  var defaultLabel = triggerContent === undefined ? '' : triggerContent;
1289
1291
  var selectedLabel = triggerSwitchActive ? selected ? selected.label : defaultLabel : defaultLabel;
1290
1292
  var selectOptionsListPresentation = options === null || options === void 0 ? void 0 : options.map(function (selectOption, index) {
@@ -1375,7 +1377,7 @@ var DropdownMenu = function DropdownMenu(props) {
1375
1377
  // STEP 2:
1376
1378
  //-----------
1377
1379
  // Detect position
1378
- if (window.innerHeight - _triggerBox.top > 100) {
1380
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
1379
1381
  targetPos = 'bottom';
1380
1382
  } else {
1381
1383
  targetPos = 'top';
@@ -2892,6 +2892,7 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
2892
2892
  var EXCEEDED_SIDE_POS_OFFSET = Number(exceededSidePosOffset) || 15;
2893
2893
  var AUTO_SHOW_OPTIONS = typeof autoShowOptions !== 'undefined' && autoShowOptions === true ? true : false;
2894
2894
  var MANUAL_REQ = typeof fetchTrigger !== 'undefined' && fetchTrigger === true ? true : false; // Manual requests
2895
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
2895
2896
 
2896
2897
  var NO_MATCH_POPUP = typeof noMatchPopup === 'undefined' ? true : noMatchPopup;
2897
2898
  var WIN_WIDTH = typeof winWidth === 'function' ? winWidth() : winWidth ? winWidth : 'auto';
@@ -3025,7 +3026,6 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3025
3026
  if (isBlurringRef.current && !MANUAL_REQ) return;
3026
3027
 
3027
3028
  //
3028
- var contentHeightOffset = 80;
3029
3029
  var contentMaxHeight = 0;
3030
3030
 
3031
3031
  // update modal position
@@ -3052,7 +3052,7 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3052
3052
  // STEP 2:
3053
3053
  //-----------
3054
3054
  // Detect position
3055
- if (window.innerHeight - _triggerBox.top > 100) {
3055
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
3056
3056
  targetPos = 'bottom';
3057
3057
  } else {
3058
3058
  targetPos = 'top';
@@ -3066,6 +3066,11 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3066
3066
  var _contentActualHeight = listContentRef.current.querySelector('.livesearch__options-contentlist-inner').clientHeight;
3067
3067
  if (targetPos === 'top') {
3068
3068
  contentMaxHeight = _triggerBox.top;
3069
+
3070
+ // Calculate the final height with minimum height protection
3071
+ var contentHeightOffset = 0;
3072
+ var finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
3073
+
3069
3074
  if (_contentBox.height > _contentActualHeight) {
3070
3075
  if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
3071
3076
  } else {
@@ -3073,11 +3078,16 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3073
3078
 
3074
3079
  // recalculate the height
3075
3080
  _contentBox = listContentRef.current.getBoundingClientRect();
3076
- if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = contentMaxHeight - contentHeightOffset + 'px';
3081
+ if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = finalHeight + 'px';
3077
3082
  }
3078
3083
  }
3079
3084
  if (targetPos === 'bottom') {
3080
3085
  contentMaxHeight = window.innerHeight - _triggerBox.bottom;
3086
+
3087
+ // Calculate the final height with minimum height protection
3088
+ var _contentHeightOffset = 10;
3089
+ var _finalHeight = Math.max(contentMaxHeight - _contentHeightOffset, 150); // Ensure minimum height of 150px
3090
+
3081
3091
  if (_contentBox.height > _contentActualHeight) {
3082
3092
  if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
3083
3093
  } else {
@@ -3085,7 +3095,7 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3085
3095
 
3086
3096
  // recalculate the height
3087
3097
  _contentBox = listContentRef.current.getBoundingClientRect();
3088
- if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = contentMaxHeight - 10 + 'px';
3098
+ if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = _finalHeight + 'px';
3089
3099
  }
3090
3100
  }
3091
3101
 
@@ -3094,17 +3104,16 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3094
3104
  // Adjust position
3095
3105
  if (targetPos === 'top') {
3096
3106
  _modalRef.style.left = x + 'px';
3097
- //_modalRef.style.top = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2 + 'px';
3098
- _modalRef.style.top = 'auto';
3099
- _modalRef.style.bottom = window.innerHeight - _triggerBox.top + POS_OFFSET + 2 + 'px';
3100
- _modalRef.style.setProperty('position', 'fixed', 'important');
3107
+ _modalRef.style.bottom = 'auto';
3108
+ // Position the popup above the trigger without overlapping
3109
+ var topPosition = y - POS_OFFSET - listContentRef.current.clientHeight - 2;
3110
+ _modalRef.style.top = topPosition + 'px';
3101
3111
  _modalRef.classList.add('pos-top');
3102
3112
  }
3103
3113
  if (targetPos === 'bottom') {
3104
3114
  _modalRef.style.left = x + 'px';
3105
3115
  _modalRef.style.bottom = 'auto';
3106
3116
  _modalRef.style.top = y + height + POS_OFFSET + 'px';
3107
- _modalRef.style.setProperty('position', 'absolute', 'important');
3108
3117
  _modalRef.classList.remove('pos-top');
3109
3118
  }
3110
3119
 
package/Select/index.d.ts CHANGED
@@ -47,6 +47,7 @@ export declare type SelectProps = {
47
47
  controlClassName?: string;
48
48
  controlExClassName?: string;
49
49
  optionsExClassName?: string;
50
+ customScrollContainer?: string | HTMLElement | React.RefObject<HTMLElement>;
50
51
  exceededSidePosOffset?: number;
51
52
  clearIcon?: boolean;
52
53
  renderOption?: (optionData: OptionConfig, index: number) => React.ReactNode;
package/Select/index.js CHANGED
@@ -3578,7 +3578,7 @@ var format_string = __webpack_require__(933);
3578
3578
  // EXTERNAL MODULE: ../Utils/dist/cjs/cls.js
3579
3579
  var cls = __webpack_require__(188);
3580
3580
  ;// CONCATENATED MODULE: ./src/index.tsx
3581
- var _excluded = ["contentRef", "popupRef", "wrapperClassName", "controlClassName", "controlExClassName", "optionsExClassName", "exceededSidePosOffset", "clearIcon", "renderOption", "multiSelect", "multiSelectEntireAreaTrigger", "multiSelectSelectedItemOnlyStatus", "renderSelectedValue", "disabled", "required", "defaultValue", "value", "label", "name", "readOnly", "placeholder", "id", "autoComplete", "autoCapitalize", "spellCheck", "options", "clearTrigger", "loader", "lockBodyScroll", "hierarchical", "indentation", "doubleIndent", "style", "depth", "controlArrow", "winWidth", "tabIndex", "firstRequestAutoExec", "fetchTrigger", "fetchNoneInfo", "fetchUpdate", "fetchFuncAsync", "fetchFuncMethod", "fetchFuncMethodParams", "data", "extractValueByBrackets", "fetchCallback", "onFetch", "onLoad", "onSelect", "onChange", "onBlur", "onFocus", "onKeyPressed"];
3581
+ var _excluded = ["contentRef", "popupRef", "wrapperClassName", "controlClassName", "controlExClassName", "optionsExClassName", "customScrollContainer", "exceededSidePosOffset", "clearIcon", "renderOption", "multiSelect", "multiSelectEntireAreaTrigger", "multiSelectSelectedItemOnlyStatus", "renderSelectedValue", "disabled", "required", "defaultValue", "value", "label", "name", "readOnly", "placeholder", "id", "autoComplete", "autoCapitalize", "spellCheck", "options", "clearTrigger", "loader", "lockBodyScroll", "hierarchical", "indentation", "doubleIndent", "style", "depth", "controlArrow", "winWidth", "tabIndex", "firstRequestAutoExec", "fetchTrigger", "fetchNoneInfo", "fetchUpdate", "fetchFuncAsync", "fetchFuncMethod", "fetchFuncMethodParams", "data", "extractValueByBrackets", "fetchCallback", "onFetch", "onLoad", "onSelect", "onChange", "onBlur", "onFocus", "onKeyPressed"];
3582
3582
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3583
3583
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3584
3584
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
@@ -3626,6 +3626,7 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
3626
3626
  controlClassName = props.controlClassName,
3627
3627
  controlExClassName = props.controlExClassName,
3628
3628
  optionsExClassName = props.optionsExClassName,
3629
+ customScrollContainer = props.customScrollContainer,
3629
3630
  exceededSidePosOffset = props.exceededSidePosOffset,
3630
3631
  clearIcon = props.clearIcon,
3631
3632
  renderOption = props.renderOption,
@@ -3701,6 +3702,8 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
3701
3702
  var listContentRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
3702
3703
  var optionsRes = options ? (0,validate.isJSON)(options) ? JSON.parse(options) : options : [];
3703
3704
  var LIST_CONTAINER_MAX_HEIGHT = 300;
3705
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
3706
+
3704
3707
  var keyboardSelectedItem = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
3705
3708
 
3706
3709
  // loading
@@ -4286,7 +4289,6 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4286
4289
  if (isBlurringRef.current) return;
4287
4290
 
4288
4291
  //
4289
- var contentHeightOffset = 80;
4290
4292
  var contentMaxHeight = 0;
4291
4293
 
4292
4294
  // update modal position
@@ -4321,8 +4323,36 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4321
4323
  _contentOldHeight = listContainerHeightLimit(_contentOldHeight);
4322
4324
 
4323
4325
  // You need to wait for the height of the pop-up container to be set
4324
- // Detect position
4325
- if (window.innerHeight - _triggerBox.top > 100) {
4326
+ // Detect position
4327
+ var containerHeight = window.innerHeight;
4328
+ var containerTop = 0;
4329
+
4330
+ // If custom scroll container is specified, use it instead of window
4331
+ if (customScrollContainer) {
4332
+ var customContainer = null;
4333
+ if (typeof customScrollContainer === 'string') {
4334
+ // Handle selector string
4335
+ customContainer = document.querySelector(customScrollContainer);
4336
+ } else if (customScrollContainer instanceof HTMLElement) {
4337
+ // Handle DOM element directly
4338
+ customContainer = customScrollContainer;
4339
+ } else if (customScrollContainer && 'current' in customScrollContainer) {
4340
+ // Handle React ref
4341
+ customContainer = customScrollContainer.current;
4342
+ }
4343
+ if (customContainer) {
4344
+ var containerRect = customContainer.getBoundingClientRect();
4345
+ containerHeight = containerRect.height;
4346
+ containerTop = containerRect.top;
4347
+ }
4348
+ }
4349
+
4350
+ // Calculate available space below the trigger
4351
+ var availableSpaceBelow = containerHeight - (_triggerBox.top - containerTop);
4352
+
4353
+ // Use a more reasonable threshold for position decision
4354
+ // Consider the minimum space needed for a usable dropdown
4355
+ if (availableSpaceBelow > MIN_SPACE_FOR_DROPDOWN) {
4326
4356
  targetPos = 'bottom';
4327
4357
  } else {
4328
4358
  targetPos = 'top';
@@ -4333,13 +4363,20 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4333
4363
  //-----------
4334
4364
  // Set the pop-up height
4335
4365
  if (targetPos === 'top') {
4336
- contentMaxHeight = _triggerBox.top;
4366
+ // Calculate available space above the trigger
4367
+ var availableSpaceAbove = _triggerBox.top - containerTop;
4368
+ contentMaxHeight = availableSpaceAbove;
4337
4369
 
4338
4370
  // height restrictions
4339
4371
  contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
4372
+
4373
+ // Calculate the final height with minimum height protection
4374
+ var contentHeightOffset = 0;
4375
+ var finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
4376
+
4340
4377
  if (_contentBox.height > contentMaxHeight) {
4341
- listContentRef.current.style.height = contentMaxHeight - contentHeightOffset + 'px';
4342
- if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = contentMaxHeight - contentHeightOffset;
4378
+ listContentRef.current.style.height = finalHeight + 'px';
4379
+ if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = finalHeight;
4343
4380
 
4344
4381
  // has scrollbar
4345
4382
  listContentRef.current.dataset.hasScrollbar = 'true';
@@ -4354,13 +4391,20 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4354
4391
  }
4355
4392
  }
4356
4393
  if (targetPos === 'bottom') {
4357
- contentMaxHeight = window.innerHeight - _triggerBox.bottom;
4394
+ // Calculate available space below the trigger
4395
+ var _availableSpaceBelow = containerHeight - (_triggerBox.bottom - containerTop);
4396
+ contentMaxHeight = _availableSpaceBelow;
4358
4397
 
4359
4398
  // height restrictions
4360
4399
  contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
4400
+
4401
+ // Calculate the final height with minimum height protection
4402
+ var _contentHeightOffset = 10;
4403
+ var _finalHeight = Math.max(contentMaxHeight - _contentHeightOffset, 150); // Ensure minimum height of 150px
4404
+
4361
4405
  if (_contentBox.height > contentMaxHeight) {
4362
- listContentRef.current.style.height = contentMaxHeight - 10 + 'px';
4363
- if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = contentMaxHeight - 10;
4406
+ listContentRef.current.style.height = _finalHeight + 'px';
4407
+ if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = _finalHeight;
4364
4408
 
4365
4409
  // has scrollbar
4366
4410
  listContentRef.current.dataset.hasScrollbar = 'true';
@@ -4380,17 +4424,16 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4380
4424
  // Adjust position
4381
4425
  if (targetPos === 'top') {
4382
4426
  _modalRef.style.left = x + 'px';
4383
- //_modalRef.style.top = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2 + 'px';
4384
- _modalRef.style.top = 'auto';
4385
- _modalRef.style.bottom = window.innerHeight - _triggerBox.top + POS_OFFSET + 2 + 'px';
4386
- _modalRef.style.setProperty('position', 'fixed', 'important');
4427
+ _modalRef.style.bottom = 'auto';
4428
+ // Position the popup above the trigger without overlapping
4429
+ var topPosition = y - POS_OFFSET - listContentRef.current.clientHeight - 2;
4430
+ _modalRef.style.top = topPosition + 'px';
4387
4431
  _modalRef.classList.add('pos-top');
4388
4432
  }
4389
4433
  if (targetPos === 'bottom') {
4390
4434
  _modalRef.style.left = x + 'px';
4391
4435
  _modalRef.style.bottom = 'auto';
4392
4436
  _modalRef.style.top = y + height + POS_OFFSET + 'px';
4393
- _modalRef.style.setProperty('position', 'absolute', 'important');
4394
4437
  _modalRef.classList.remove('pos-top');
4395
4438
  }
4396
4439
 
@@ -4400,16 +4443,38 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4400
4443
  var _modalContent = _modalRef;
4401
4444
  var _modalBox = _modalContent.getBoundingClientRect();
4402
4445
  if (typeof _modalContent.dataset.offset === 'undefined' && _modalBox.left > 0) {
4446
+ // Get container width for boundary checking
4447
+ var containerWidth = window.innerWidth;
4448
+ var containerLeft = 0;
4449
+ if (customScrollContainer) {
4450
+ var _customContainer = null;
4451
+ if (typeof customScrollContainer === 'string') {
4452
+ // Handle selector string
4453
+ _customContainer = document.querySelector(customScrollContainer);
4454
+ } else if (customScrollContainer instanceof HTMLElement) {
4455
+ // Handle DOM element directly
4456
+ _customContainer = customScrollContainer;
4457
+ } else if (customScrollContainer && 'current' in customScrollContainer) {
4458
+ // Handle React ref
4459
+ _customContainer = customScrollContainer.current;
4460
+ }
4461
+ if (_customContainer) {
4462
+ var _containerRect = _customContainer.getBoundingClientRect();
4463
+ containerWidth = _containerRect.width;
4464
+ containerLeft = _containerRect.left;
4465
+ }
4466
+ }
4467
+
4403
4468
  // 10 pixels is used to account for some bias in mobile devices
4404
- if (_modalBox.right + 10 > window.innerWidth) {
4405
- var _modalOffsetPosition = _modalBox.right - window.innerWidth + EXCEEDED_SIDE_POS_OFFSET;
4469
+ if (_modalBox.right + 10 > containerLeft + containerWidth) {
4470
+ var _modalOffsetPosition = _modalBox.right - (containerLeft + containerWidth) + EXCEEDED_SIDE_POS_OFFSET;
4406
4471
  _modalContent.dataset.offset = _modalOffsetPosition;
4407
4472
  _modalContent.style.marginLeft = "-".concat(_modalOffsetPosition, "px");
4408
4473
  // console.log('_modalPosition: ', _modalOffsetPosition)
4409
4474
  }
4410
4475
 
4411
- if (_modalBox.left - 10 < 0) {
4412
- var _modalOffsetPosition2 = Math.abs(_modalBox.left) + EXCEEDED_SIDE_POS_OFFSET;
4476
+ if (_modalBox.left - 10 < containerLeft) {
4477
+ var _modalOffsetPosition2 = Math.abs(_modalBox.left - containerLeft) + EXCEEDED_SIDE_POS_OFFSET;
4413
4478
  _modalContent.dataset.offset = _modalOffsetPosition2;
4414
4479
  _modalContent.style.marginLeft = "".concat(_modalOffsetPosition2, "px");
4415
4480
  // console.log('_modalPosition: ', _modalOffsetPosition)
@@ -2322,6 +2322,7 @@ var CascadingSelect = /*#__PURE__*/(0,external_root_React_commonjs2_react_common
2322
2322
  var rootRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2323
2323
  var inputRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2324
2324
  var listRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2325
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
2325
2326
 
2326
2327
  // searchable
2327
2328
  var _useState = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)([]),
@@ -2439,7 +2440,7 @@ var CascadingSelect = /*#__PURE__*/(0,external_root_React_commonjs2_react_common
2439
2440
  // STEP 2:
2440
2441
  //-----------
2441
2442
  // Detect position
2442
- if (window.innerHeight - _triggerBox.top > 100) {
2443
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
2443
2444
  targetPos = 'bottom';
2444
2445
  } else {
2445
2446
  targetPos = 'top';
@@ -2679,6 +2679,7 @@ var CascadingSelectE2E = /*#__PURE__*/(0,external_root_React_commonjs2_react_com
2679
2679
  var rootRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2680
2680
  var inputRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2681
2681
  var listRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
2682
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
2682
2683
 
2683
2684
  // searchable
2684
2685
  var _useState = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)([]),
@@ -2821,7 +2822,7 @@ var CascadingSelectE2E = /*#__PURE__*/(0,external_root_React_commonjs2_react_com
2821
2822
  // STEP 2:
2822
2823
  //-----------
2823
2824
  // Detect position
2824
- if (window.innerHeight - _triggerBox.top > 100) {
2825
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
2825
2826
  targetPos = 'bottom';
2826
2827
  } else {
2827
2828
  targetPos = 'top';
@@ -5034,6 +5034,8 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5034
5034
  langToday = props.langToday,
5035
5035
  attributes = _objectWithoutProperties(props, _excluded);
5036
5036
  var DEPTH = depth || 1055; // the default value same as bootstrap
5037
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
5038
+
5037
5039
  var defaultValueIsEmpty = function defaultValueIsEmpty(s) {
5038
5040
  return typeof s === 'undefined' || s === null || s === 'null' || s === '';
5039
5041
  };
@@ -5328,7 +5330,7 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5328
5330
  // STEP 1:
5329
5331
  //-----------
5330
5332
  // Detect position
5331
- if (window.innerHeight - _triggerBox.top > 100) {
5333
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
5332
5334
  targetPos = 'bottom';
5333
5335
  } else {
5334
5336
  targetPos = 'top';
@@ -1285,6 +1285,8 @@ var DropdownMenu = function DropdownMenu(props) {
1285
1285
  selected = _useState4[0],
1286
1286
  setSelected = _useState4[1];
1287
1287
  var _hoverDelay = !isNaN(hoverDelay) && typeof hoverDelay !== 'undefined' ? hoverDelay : 150;
1288
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
1289
+
1288
1290
  var defaultLabel = triggerContent === undefined ? '' : triggerContent;
1289
1291
  var selectedLabel = triggerSwitchActive ? selected ? selected.label : defaultLabel : defaultLabel;
1290
1292
  var selectOptionsListPresentation = options === null || options === void 0 ? void 0 : options.map(function (selectOption, index) {
@@ -1375,7 +1377,7 @@ var DropdownMenu = function DropdownMenu(props) {
1375
1377
  // STEP 2:
1376
1378
  //-----------
1377
1379
  // Detect position
1378
- if (window.innerHeight - _triggerBox.top > 100) {
1380
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
1379
1381
  targetPos = 'bottom';
1380
1382
  } else {
1381
1383
  targetPos = 'top';
@@ -2892,6 +2892,7 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
2892
2892
  var EXCEEDED_SIDE_POS_OFFSET = Number(exceededSidePosOffset) || 15;
2893
2893
  var AUTO_SHOW_OPTIONS = typeof autoShowOptions !== 'undefined' && autoShowOptions === true ? true : false;
2894
2894
  var MANUAL_REQ = typeof fetchTrigger !== 'undefined' && fetchTrigger === true ? true : false; // Manual requests
2895
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
2895
2896
 
2896
2897
  var NO_MATCH_POPUP = typeof noMatchPopup === 'undefined' ? true : noMatchPopup;
2897
2898
  var WIN_WIDTH = typeof winWidth === 'function' ? winWidth() : winWidth ? winWidth : 'auto';
@@ -3025,7 +3026,6 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3025
3026
  if (isBlurringRef.current && !MANUAL_REQ) return;
3026
3027
 
3027
3028
  //
3028
- var contentHeightOffset = 80;
3029
3029
  var contentMaxHeight = 0;
3030
3030
 
3031
3031
  // update modal position
@@ -3052,7 +3052,7 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3052
3052
  // STEP 2:
3053
3053
  //-----------
3054
3054
  // Detect position
3055
- if (window.innerHeight - _triggerBox.top > 100) {
3055
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
3056
3056
  targetPos = 'bottom';
3057
3057
  } else {
3058
3058
  targetPos = 'top';
@@ -3066,6 +3066,11 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3066
3066
  var _contentActualHeight = listContentRef.current.querySelector('.livesearch__options-contentlist-inner').clientHeight;
3067
3067
  if (targetPos === 'top') {
3068
3068
  contentMaxHeight = _triggerBox.top;
3069
+
3070
+ // Calculate the final height with minimum height protection
3071
+ var contentHeightOffset = 0;
3072
+ var finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
3073
+
3069
3074
  if (_contentBox.height > _contentActualHeight) {
3070
3075
  if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
3071
3076
  } else {
@@ -3073,11 +3078,16 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3073
3078
 
3074
3079
  // recalculate the height
3075
3080
  _contentBox = listContentRef.current.getBoundingClientRect();
3076
- if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = contentMaxHeight - contentHeightOffset + 'px';
3081
+ if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = finalHeight + 'px';
3077
3082
  }
3078
3083
  }
3079
3084
  if (targetPos === 'bottom') {
3080
3085
  contentMaxHeight = window.innerHeight - _triggerBox.bottom;
3086
+
3087
+ // Calculate the final height with minimum height protection
3088
+ var _contentHeightOffset = 10;
3089
+ var _finalHeight = Math.max(contentMaxHeight - _contentHeightOffset, 150); // Ensure minimum height of 150px
3090
+
3081
3091
  if (_contentBox.height > _contentActualHeight) {
3082
3092
  if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
3083
3093
  } else {
@@ -3085,7 +3095,7 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3085
3095
 
3086
3096
  // recalculate the height
3087
3097
  _contentBox = listContentRef.current.getBoundingClientRect();
3088
- if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = contentMaxHeight - 10 + 'px';
3098
+ if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = _finalHeight + 'px';
3089
3099
  }
3090
3100
  }
3091
3101
 
@@ -3094,17 +3104,16 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
3094
3104
  // Adjust position
3095
3105
  if (targetPos === 'top') {
3096
3106
  _modalRef.style.left = x + 'px';
3097
- //_modalRef.style.top = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2 + 'px';
3098
- _modalRef.style.top = 'auto';
3099
- _modalRef.style.bottom = window.innerHeight - _triggerBox.top + POS_OFFSET + 2 + 'px';
3100
- _modalRef.style.setProperty('position', 'fixed', 'important');
3107
+ _modalRef.style.bottom = 'auto';
3108
+ // Position the popup above the trigger without overlapping
3109
+ var topPosition = y - POS_OFFSET - listContentRef.current.clientHeight - 2;
3110
+ _modalRef.style.top = topPosition + 'px';
3101
3111
  _modalRef.classList.add('pos-top');
3102
3112
  }
3103
3113
  if (targetPos === 'bottom') {
3104
3114
  _modalRef.style.left = x + 'px';
3105
3115
  _modalRef.style.bottom = 'auto';
3106
3116
  _modalRef.style.top = y + height + POS_OFFSET + 'px';
3107
- _modalRef.style.setProperty('position', 'absolute', 'important');
3108
3117
  _modalRef.classList.remove('pos-top');
3109
3118
  }
3110
3119
 
@@ -47,6 +47,7 @@ export declare type SelectProps = {
47
47
  controlClassName?: string;
48
48
  controlExClassName?: string;
49
49
  optionsExClassName?: string;
50
+ customScrollContainer?: string | HTMLElement | React.RefObject<HTMLElement>;
50
51
  exceededSidePosOffset?: number;
51
52
  clearIcon?: boolean;
52
53
  renderOption?: (optionData: OptionConfig, index: number) => React.ReactNode;
@@ -3578,7 +3578,7 @@ var format_string = __webpack_require__(933);
3578
3578
  // EXTERNAL MODULE: ../Utils/dist/cjs/cls.js
3579
3579
  var cls = __webpack_require__(188);
3580
3580
  ;// CONCATENATED MODULE: ./src/index.tsx
3581
- var _excluded = ["contentRef", "popupRef", "wrapperClassName", "controlClassName", "controlExClassName", "optionsExClassName", "exceededSidePosOffset", "clearIcon", "renderOption", "multiSelect", "multiSelectEntireAreaTrigger", "multiSelectSelectedItemOnlyStatus", "renderSelectedValue", "disabled", "required", "defaultValue", "value", "label", "name", "readOnly", "placeholder", "id", "autoComplete", "autoCapitalize", "spellCheck", "options", "clearTrigger", "loader", "lockBodyScroll", "hierarchical", "indentation", "doubleIndent", "style", "depth", "controlArrow", "winWidth", "tabIndex", "firstRequestAutoExec", "fetchTrigger", "fetchNoneInfo", "fetchUpdate", "fetchFuncAsync", "fetchFuncMethod", "fetchFuncMethodParams", "data", "extractValueByBrackets", "fetchCallback", "onFetch", "onLoad", "onSelect", "onChange", "onBlur", "onFocus", "onKeyPressed"];
3581
+ var _excluded = ["contentRef", "popupRef", "wrapperClassName", "controlClassName", "controlExClassName", "optionsExClassName", "customScrollContainer", "exceededSidePosOffset", "clearIcon", "renderOption", "multiSelect", "multiSelectEntireAreaTrigger", "multiSelectSelectedItemOnlyStatus", "renderSelectedValue", "disabled", "required", "defaultValue", "value", "label", "name", "readOnly", "placeholder", "id", "autoComplete", "autoCapitalize", "spellCheck", "options", "clearTrigger", "loader", "lockBodyScroll", "hierarchical", "indentation", "doubleIndent", "style", "depth", "controlArrow", "winWidth", "tabIndex", "firstRequestAutoExec", "fetchTrigger", "fetchNoneInfo", "fetchUpdate", "fetchFuncAsync", "fetchFuncMethod", "fetchFuncMethodParams", "data", "extractValueByBrackets", "fetchCallback", "onFetch", "onLoad", "onSelect", "onChange", "onBlur", "onFocus", "onKeyPressed"];
3582
3582
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3583
3583
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3584
3584
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
@@ -3626,6 +3626,7 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
3626
3626
  controlClassName = props.controlClassName,
3627
3627
  controlExClassName = props.controlExClassName,
3628
3628
  optionsExClassName = props.optionsExClassName,
3629
+ customScrollContainer = props.customScrollContainer,
3629
3630
  exceededSidePosOffset = props.exceededSidePosOffset,
3630
3631
  clearIcon = props.clearIcon,
3631
3632
  renderOption = props.renderOption,
@@ -3701,6 +3702,8 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
3701
3702
  var listContentRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
3702
3703
  var optionsRes = options ? (0,validate.isJSON)(options) ? JSON.parse(options) : options : [];
3703
3704
  var LIST_CONTAINER_MAX_HEIGHT = 300;
3705
+ var MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
3706
+
3704
3707
  var keyboardSelectedItem = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
3705
3708
 
3706
3709
  // loading
@@ -4286,7 +4289,6 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4286
4289
  if (isBlurringRef.current) return;
4287
4290
 
4288
4291
  //
4289
- var contentHeightOffset = 80;
4290
4292
  var contentMaxHeight = 0;
4291
4293
 
4292
4294
  // update modal position
@@ -4321,8 +4323,36 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4321
4323
  _contentOldHeight = listContainerHeightLimit(_contentOldHeight);
4322
4324
 
4323
4325
  // You need to wait for the height of the pop-up container to be set
4324
- // Detect position
4325
- if (window.innerHeight - _triggerBox.top > 100) {
4326
+ // Detect position
4327
+ var containerHeight = window.innerHeight;
4328
+ var containerTop = 0;
4329
+
4330
+ // If custom scroll container is specified, use it instead of window
4331
+ if (customScrollContainer) {
4332
+ var customContainer = null;
4333
+ if (typeof customScrollContainer === 'string') {
4334
+ // Handle selector string
4335
+ customContainer = document.querySelector(customScrollContainer);
4336
+ } else if (customScrollContainer instanceof HTMLElement) {
4337
+ // Handle DOM element directly
4338
+ customContainer = customScrollContainer;
4339
+ } else if (customScrollContainer && 'current' in customScrollContainer) {
4340
+ // Handle React ref
4341
+ customContainer = customScrollContainer.current;
4342
+ }
4343
+ if (customContainer) {
4344
+ var containerRect = customContainer.getBoundingClientRect();
4345
+ containerHeight = containerRect.height;
4346
+ containerTop = containerRect.top;
4347
+ }
4348
+ }
4349
+
4350
+ // Calculate available space below the trigger
4351
+ var availableSpaceBelow = containerHeight - (_triggerBox.top - containerTop);
4352
+
4353
+ // Use a more reasonable threshold for position decision
4354
+ // Consider the minimum space needed for a usable dropdown
4355
+ if (availableSpaceBelow > MIN_SPACE_FOR_DROPDOWN) {
4326
4356
  targetPos = 'bottom';
4327
4357
  } else {
4328
4358
  targetPos = 'top';
@@ -4333,13 +4363,20 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4333
4363
  //-----------
4334
4364
  // Set the pop-up height
4335
4365
  if (targetPos === 'top') {
4336
- contentMaxHeight = _triggerBox.top;
4366
+ // Calculate available space above the trigger
4367
+ var availableSpaceAbove = _triggerBox.top - containerTop;
4368
+ contentMaxHeight = availableSpaceAbove;
4337
4369
 
4338
4370
  // height restrictions
4339
4371
  contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
4372
+
4373
+ // Calculate the final height with minimum height protection
4374
+ var contentHeightOffset = 0;
4375
+ var finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
4376
+
4340
4377
  if (_contentBox.height > contentMaxHeight) {
4341
- listContentRef.current.style.height = contentMaxHeight - contentHeightOffset + 'px';
4342
- if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = contentMaxHeight - contentHeightOffset;
4378
+ listContentRef.current.style.height = finalHeight + 'px';
4379
+ if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = finalHeight;
4343
4380
 
4344
4381
  // has scrollbar
4345
4382
  listContentRef.current.dataset.hasScrollbar = 'true';
@@ -4354,13 +4391,20 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4354
4391
  }
4355
4392
  }
4356
4393
  if (targetPos === 'bottom') {
4357
- contentMaxHeight = window.innerHeight - _triggerBox.bottom;
4394
+ // Calculate available space below the trigger
4395
+ var _availableSpaceBelow = containerHeight - (_triggerBox.bottom - containerTop);
4396
+ contentMaxHeight = _availableSpaceBelow;
4358
4397
 
4359
4398
  // height restrictions
4360
4399
  contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
4400
+
4401
+ // Calculate the final height with minimum height protection
4402
+ var _contentHeightOffset = 10;
4403
+ var _finalHeight = Math.max(contentMaxHeight - _contentHeightOffset, 150); // Ensure minimum height of 150px
4404
+
4361
4405
  if (_contentBox.height > contentMaxHeight) {
4362
- listContentRef.current.style.height = contentMaxHeight - 10 + 'px';
4363
- if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = contentMaxHeight - 10;
4406
+ listContentRef.current.style.height = _finalHeight + 'px';
4407
+ if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = _finalHeight;
4364
4408
 
4365
4409
  // has scrollbar
4366
4410
  listContentRef.current.dataset.hasScrollbar = 'true';
@@ -4380,17 +4424,16 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4380
4424
  // Adjust position
4381
4425
  if (targetPos === 'top') {
4382
4426
  _modalRef.style.left = x + 'px';
4383
- //_modalRef.style.top = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2 + 'px';
4384
- _modalRef.style.top = 'auto';
4385
- _modalRef.style.bottom = window.innerHeight - _triggerBox.top + POS_OFFSET + 2 + 'px';
4386
- _modalRef.style.setProperty('position', 'fixed', 'important');
4427
+ _modalRef.style.bottom = 'auto';
4428
+ // Position the popup above the trigger without overlapping
4429
+ var topPosition = y - POS_OFFSET - listContentRef.current.clientHeight - 2;
4430
+ _modalRef.style.top = topPosition + 'px';
4387
4431
  _modalRef.classList.add('pos-top');
4388
4432
  }
4389
4433
  if (targetPos === 'bottom') {
4390
4434
  _modalRef.style.left = x + 'px';
4391
4435
  _modalRef.style.bottom = 'auto';
4392
4436
  _modalRef.style.top = y + height + POS_OFFSET + 'px';
4393
- _modalRef.style.setProperty('position', 'absolute', 'important');
4394
4437
  _modalRef.classList.remove('pos-top');
4395
4438
  }
4396
4439
 
@@ -4400,16 +4443,38 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4400
4443
  var _modalContent = _modalRef;
4401
4444
  var _modalBox = _modalContent.getBoundingClientRect();
4402
4445
  if (typeof _modalContent.dataset.offset === 'undefined' && _modalBox.left > 0) {
4446
+ // Get container width for boundary checking
4447
+ var containerWidth = window.innerWidth;
4448
+ var containerLeft = 0;
4449
+ if (customScrollContainer) {
4450
+ var _customContainer = null;
4451
+ if (typeof customScrollContainer === 'string') {
4452
+ // Handle selector string
4453
+ _customContainer = document.querySelector(customScrollContainer);
4454
+ } else if (customScrollContainer instanceof HTMLElement) {
4455
+ // Handle DOM element directly
4456
+ _customContainer = customScrollContainer;
4457
+ } else if (customScrollContainer && 'current' in customScrollContainer) {
4458
+ // Handle React ref
4459
+ _customContainer = customScrollContainer.current;
4460
+ }
4461
+ if (_customContainer) {
4462
+ var _containerRect = _customContainer.getBoundingClientRect();
4463
+ containerWidth = _containerRect.width;
4464
+ containerLeft = _containerRect.left;
4465
+ }
4466
+ }
4467
+
4403
4468
  // 10 pixels is used to account for some bias in mobile devices
4404
- if (_modalBox.right + 10 > window.innerWidth) {
4405
- var _modalOffsetPosition = _modalBox.right - window.innerWidth + EXCEEDED_SIDE_POS_OFFSET;
4469
+ if (_modalBox.right + 10 > containerLeft + containerWidth) {
4470
+ var _modalOffsetPosition = _modalBox.right - (containerLeft + containerWidth) + EXCEEDED_SIDE_POS_OFFSET;
4406
4471
  _modalContent.dataset.offset = _modalOffsetPosition;
4407
4472
  _modalContent.style.marginLeft = "-".concat(_modalOffsetPosition, "px");
4408
4473
  // console.log('_modalPosition: ', _modalOffsetPosition)
4409
4474
  }
4410
4475
 
4411
- if (_modalBox.left - 10 < 0) {
4412
- var _modalOffsetPosition2 = Math.abs(_modalBox.left) + EXCEEDED_SIDE_POS_OFFSET;
4476
+ if (_modalBox.left - 10 < containerLeft) {
4477
+ var _modalOffsetPosition2 = Math.abs(_modalBox.left - containerLeft) + EXCEEDED_SIDE_POS_OFFSET;
4413
4478
  _modalContent.dataset.offset = _modalOffsetPosition2;
4414
4479
  _modalContent.style.marginLeft = "".concat(_modalOffsetPosition2, "px");
4415
4480
  // console.log('_modalPosition: ', _modalOffsetPosition)
@@ -168,6 +168,7 @@ const CascadingSelect = forwardRef((props: CascadingSelectProps, externalRef: an
168
168
  const rootRef = useRef<any>(null);
169
169
  const inputRef = useRef<any>(null);
170
170
  const listRef = useRef<any>(null);
171
+ const MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
171
172
 
172
173
  // searchable
173
174
  const [columnSearchKeywords, setColumnSearchKeywords] = useState<string[]>([]);
@@ -282,7 +283,7 @@ const CascadingSelect = forwardRef((props: CascadingSelectProps, externalRef: an
282
283
  // STEP 2:
283
284
  //-----------
284
285
  // Detect position
285
- if (window.innerHeight - _triggerBox.top > 100) {
286
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
286
287
  targetPos = 'bottom';
287
288
  } else {
288
289
  targetPos = 'top';
@@ -184,6 +184,7 @@ const CascadingSelectE2E = forwardRef((props: CascadingSelectE2EProps, externalR
184
184
  const rootRef = useRef<any>(null);
185
185
  const inputRef = useRef<any>(null);
186
186
  const listRef = useRef<any>(null);
187
+ const MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
187
188
 
188
189
  // searchable
189
190
  const [columnSearchKeywords, setColumnSearchKeywords] = useState<string[]>([]);
@@ -318,7 +319,7 @@ const CascadingSelectE2E = forwardRef((props: CascadingSelectE2EProps, externalR
318
319
  // STEP 2:
319
320
  //-----------
320
321
  // Detect position
321
- if (window.innerHeight - _triggerBox.top > 100) {
322
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
322
323
  targetPos = 'bottom';
323
324
  } else {
324
325
  targetPos = 'top';
@@ -193,6 +193,9 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
193
193
 
194
194
 
195
195
  const DEPTH = depth || 1055; // the default value same as bootstrap
196
+ const MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
197
+
198
+
196
199
  const defaultValueIsEmpty = (s: any) => {
197
200
  return typeof s === 'undefined' || s === null || s === 'null' || s === '';
198
201
  };
@@ -521,7 +524,7 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
521
524
  // STEP 1:
522
525
  //-----------
523
526
  // Detect position
524
- if (window.innerHeight - _triggerBox.top > 100) {
527
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
525
528
  targetPos = 'bottom';
526
529
  } else {
527
530
  targetPos = 'top';
@@ -88,6 +88,7 @@ const DropdownMenu = (props: DropdownMenuProps) => {
88
88
  const [isOpen, setIsOpen] = useState<boolean>(false);
89
89
  const [selected, setSelected] = useState<any>(null);
90
90
  const _hoverDelay = !isNaN(hoverDelay as never) && typeof hoverDelay !== 'undefined' ? hoverDelay : 150;
91
+ const MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
91
92
 
92
93
 
93
94
  const defaultLabel = triggerContent === undefined ? '' : triggerContent;
@@ -207,7 +208,7 @@ const DropdownMenu = (props: DropdownMenuProps) => {
207
208
  // STEP 2:
208
209
  //-----------
209
210
  // Detect position
210
- if (window.innerHeight - _triggerBox.top > 100) {
211
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
211
212
  targetPos = 'bottom';
212
213
  } else {
213
214
  targetPos = 'top';
@@ -153,6 +153,7 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
153
153
  const EXCEEDED_SIDE_POS_OFFSET = Number(exceededSidePosOffset) || 15;
154
154
  const AUTO_SHOW_OPTIONS = typeof autoShowOptions !== 'undefined' && autoShowOptions === true ? true : false;
155
155
  const MANUAL_REQ = typeof fetchTrigger !== 'undefined' && fetchTrigger === true ? true : false; // Manual requests
156
+ const MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
156
157
 
157
158
  const NO_MATCH_POPUP = typeof noMatchPopup === 'undefined' ? true : noMatchPopup;
158
159
  const WIN_WIDTH = typeof winWidth === 'function' ? winWidth() : winWidth ? winWidth : 'auto';
@@ -275,7 +276,6 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
275
276
 
276
277
 
277
278
  //
278
- const contentHeightOffset = 80;
279
279
  let contentMaxHeight = 0;
280
280
 
281
281
  // update modal position
@@ -300,7 +300,7 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
300
300
  // STEP 2:
301
301
  //-----------
302
302
  // Detect position
303
- if (window.innerHeight - _triggerBox.top > 100) {
303
+ if (window.innerHeight - _triggerBox.top > MIN_SPACE_FOR_DROPDOWN) {
304
304
  targetPos = 'bottom';
305
305
  } else {
306
306
  targetPos = 'top';
@@ -320,6 +320,10 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
320
320
  if (targetPos === 'top') {
321
321
  contentMaxHeight = _triggerBox.top;
322
322
 
323
+ // Calculate the final height with minimum height protection
324
+ const contentHeightOffset = 0;
325
+ const finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
326
+
323
327
  if (_contentBox.height > _contentActualHeight) {
324
328
  if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
325
329
  } else {
@@ -327,7 +331,7 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
327
331
 
328
332
  // recalculate the height
329
333
  _contentBox = listContentRef.current.getBoundingClientRect();
330
- if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = contentMaxHeight - contentHeightOffset + 'px';
334
+ if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = finalHeight + 'px';
331
335
 
332
336
  }
333
337
  }
@@ -335,6 +339,10 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
335
339
  if (targetPos === 'bottom') {
336
340
  contentMaxHeight = window.innerHeight - _triggerBox.bottom;
337
341
 
342
+ // Calculate the final height with minimum height protection
343
+ const contentHeightOffset = 10;
344
+ const finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
345
+
338
346
  if (_contentBox.height > _contentActualHeight) {
339
347
  if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
340
348
  } else {
@@ -342,7 +350,7 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
342
350
 
343
351
  // recalculate the height
344
352
  _contentBox = listContentRef.current.getBoundingClientRect();
345
- if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = contentMaxHeight - 10 + 'px';
353
+ if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = finalHeight + 'px';
346
354
  }
347
355
 
348
356
  }
@@ -354,25 +362,22 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
354
362
  // Adjust position
355
363
  if (targetPos === 'top') {
356
364
  _modalRef.style.left = x + 'px';
357
- //_modalRef.style.top = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2 + 'px';
358
- _modalRef.style.top = 'auto';
359
- _modalRef.style.bottom = (window.innerHeight - _triggerBox.top) + POS_OFFSET + 2 + 'px';
360
- _modalRef.style.setProperty('position', 'fixed', 'important');
365
+ _modalRef.style.bottom = 'auto';
366
+ // Position the popup above the trigger without overlapping
367
+ const topPosition = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2;
368
+ _modalRef.style.top = topPosition + 'px';
361
369
  _modalRef.classList.add('pos-top');
370
+
362
371
  }
363
372
 
364
373
  if (targetPos === 'bottom') {
365
374
  _modalRef.style.left = x + 'px';
366
375
  _modalRef.style.bottom = 'auto';
367
376
  _modalRef.style.top = y + height + POS_OFFSET + 'px';
368
- _modalRef.style.setProperty('position', 'absolute', 'important');
369
377
  _modalRef.classList.remove('pos-top');
370
378
  }
371
379
 
372
380
 
373
-
374
-
375
-
376
381
  // STEP 5:
377
382
  //-----------
378
383
  // Determine whether it exceeds the far right or left side of the screen
@@ -109,6 +109,7 @@ export type SelectProps = {
109
109
  controlClassName?: string;
110
110
  controlExClassName?: string;
111
111
  optionsExClassName?: string;
112
+ customScrollContainer?: string | HTMLElement | React.RefObject<HTMLElement>;
112
113
  exceededSidePosOffset?: number;
113
114
  clearIcon?: boolean;
114
115
  renderOption?: (optionData: OptionConfig, index: number) => React.ReactNode;
@@ -188,6 +189,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
188
189
  controlClassName,
189
190
  controlExClassName,
190
191
  optionsExClassName,
192
+ customScrollContainer,
191
193
  exceededSidePosOffset,
192
194
  clearIcon,
193
195
  renderOption,
@@ -265,6 +267,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
265
267
  const listContentRef = useRef<any>(null);
266
268
  const optionsRes = options ? (isJSON(options) ? JSON.parse(options as string) : options) : [];
267
269
  const LIST_CONTAINER_MAX_HEIGHT = 300;
270
+ const MIN_SPACE_FOR_DROPDOWN = 200; // Minimum space needed to show dropdown below trigger
268
271
 
269
272
  const keyboardSelectedItem = useRef<any>(null);
270
273
 
@@ -813,7 +816,6 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
813
816
  if (isBlurringRef.current) return;
814
817
 
815
818
  //
816
- const contentHeightOffset = 80;
817
819
  let contentMaxHeight = 0;
818
820
 
819
821
  // update modal position
@@ -850,8 +852,38 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
850
852
  _contentOldHeight = listContainerHeightLimit(_contentOldHeight);
851
853
 
852
854
  // You need to wait for the height of the pop-up container to be set
853
- // Detect position
854
- if (window.innerHeight - _triggerBox.top > 100) {
855
+ // Detect position
856
+ let containerHeight = window.innerHeight;
857
+ let containerTop = 0;
858
+
859
+ // If custom scroll container is specified, use it instead of window
860
+ if (customScrollContainer) {
861
+ let customContainer: HTMLElement | null = null;
862
+
863
+ if (typeof customScrollContainer === 'string') {
864
+ // Handle selector string
865
+ customContainer = document.querySelector(customScrollContainer);
866
+ } else if (customScrollContainer instanceof HTMLElement) {
867
+ // Handle DOM element directly
868
+ customContainer = customScrollContainer;
869
+ } else if (customScrollContainer && 'current' in customScrollContainer) {
870
+ // Handle React ref
871
+ customContainer = customScrollContainer.current;
872
+ }
873
+
874
+ if (customContainer) {
875
+ const containerRect = customContainer.getBoundingClientRect();
876
+ containerHeight = containerRect.height;
877
+ containerTop = containerRect.top;
878
+ }
879
+ }
880
+
881
+ // Calculate available space below the trigger
882
+ const availableSpaceBelow = containerHeight - (_triggerBox.top - containerTop);
883
+
884
+ // Use a more reasonable threshold for position decision
885
+ // Consider the minimum space needed for a usable dropdown
886
+ if (availableSpaceBelow > MIN_SPACE_FOR_DROPDOWN) {
855
887
  targetPos = 'bottom';
856
888
  } else {
857
889
  targetPos = 'top';
@@ -865,15 +897,20 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
865
897
  //-----------
866
898
  // Set the pop-up height
867
899
  if (targetPos === 'top') {
868
- contentMaxHeight = _triggerBox.top;
900
+ // Calculate available space above the trigger
901
+ const availableSpaceAbove = _triggerBox.top - containerTop;
902
+ contentMaxHeight = availableSpaceAbove;
869
903
 
870
904
  // height restrictions
871
905
  contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
872
906
 
907
+ // Calculate the final height with minimum height protection
908
+ const contentHeightOffset = 0;
909
+ const finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
873
910
 
874
911
  if (_contentBox.height > contentMaxHeight) {
875
- listContentRef.current.style.height = contentMaxHeight - contentHeightOffset + 'px';
876
- if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = contentMaxHeight - contentHeightOffset;
912
+ listContentRef.current.style.height = finalHeight + 'px';
913
+ if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = finalHeight;
877
914
 
878
915
  // has scrollbar
879
916
  listContentRef.current.dataset.hasScrollbar = 'true';
@@ -892,16 +929,20 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
892
929
  }
893
930
 
894
931
  if (targetPos === 'bottom') {
895
- contentMaxHeight = window.innerHeight - _triggerBox.bottom;
896
-
932
+ // Calculate available space below the trigger
933
+ const availableSpaceBelow = containerHeight - (_triggerBox.bottom - containerTop);
934
+ contentMaxHeight = availableSpaceBelow;
897
935
 
898
936
  // height restrictions
899
937
  contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
900
938
 
939
+ // Calculate the final height with minimum height protection
940
+ const contentHeightOffset = 10;
941
+ const finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
901
942
 
902
943
  if (_contentBox.height > contentMaxHeight) {
903
- listContentRef.current.style.height = contentMaxHeight - 10 + 'px';
904
- if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = contentMaxHeight - 10;
944
+ listContentRef.current.style.height = finalHeight + 'px';
945
+ if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = finalHeight;
905
946
 
906
947
  // has scrollbar
907
948
  listContentRef.current.dataset.hasScrollbar = 'true';
@@ -925,18 +966,18 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
925
966
  // Adjust position
926
967
  if (targetPos === 'top') {
927
968
  _modalRef.style.left = x + 'px';
928
- //_modalRef.style.top = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2 + 'px';
929
- _modalRef.style.top = 'auto';
930
- _modalRef.style.bottom = (window.innerHeight - _triggerBox.top) + POS_OFFSET + 2 + 'px';
931
- _modalRef.style.setProperty('position', 'fixed', 'important');
969
+ _modalRef.style.bottom = 'auto';
970
+ // Position the popup above the trigger without overlapping
971
+ const topPosition = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2;
972
+ _modalRef.style.top = topPosition + 'px';
932
973
  _modalRef.classList.add('pos-top');
974
+
933
975
  }
934
976
 
935
977
  if (targetPos === 'bottom') {
936
978
  _modalRef.style.left = x + 'px';
937
979
  _modalRef.style.bottom = 'auto';
938
980
  _modalRef.style.top = y + height + POS_OFFSET + 'px';
939
- _modalRef.style.setProperty('position', 'absolute', 'important');
940
981
  _modalRef.classList.remove('pos-top');
941
982
  }
942
983
 
@@ -949,23 +990,46 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
949
990
  const _modalBox = _modalContent.getBoundingClientRect();
950
991
  if (typeof _modalContent.dataset.offset === 'undefined' && _modalBox.left > 0) {
951
992
 
993
+ // Get container width for boundary checking
994
+ let containerWidth = window.innerWidth;
995
+ let containerLeft = 0;
996
+
997
+ if (customScrollContainer) {
998
+ let customContainer: HTMLElement | null = null;
999
+
1000
+ if (typeof customScrollContainer === 'string') {
1001
+ // Handle selector string
1002
+ customContainer = document.querySelector(customScrollContainer);
1003
+ } else if (customScrollContainer instanceof HTMLElement) {
1004
+ // Handle DOM element directly
1005
+ customContainer = customScrollContainer;
1006
+ } else if (customScrollContainer && 'current' in customScrollContainer) {
1007
+ // Handle React ref
1008
+ customContainer = customScrollContainer.current;
1009
+ }
1010
+
1011
+ if (customContainer) {
1012
+ const containerRect = customContainer.getBoundingClientRect();
1013
+ containerWidth = containerRect.width;
1014
+ containerLeft = containerRect.left;
1015
+ }
1016
+ }
1017
+
952
1018
  // 10 pixels is used to account for some bias in mobile devices
953
- if ((_modalBox.right + 10) > window.innerWidth) {
954
- const _modalOffsetPosition = _modalBox.right - window.innerWidth + EXCEEDED_SIDE_POS_OFFSET;
1019
+ if ((_modalBox.right + 10) > (containerLeft + containerWidth)) {
1020
+ const _modalOffsetPosition = _modalBox.right - (containerLeft + containerWidth) + EXCEEDED_SIDE_POS_OFFSET;
955
1021
  _modalContent.dataset.offset = _modalOffsetPosition;
956
1022
  _modalContent.style.marginLeft = `-${_modalOffsetPosition}px`;
957
1023
  // console.log('_modalPosition: ', _modalOffsetPosition)
958
1024
  }
959
1025
 
960
-
961
- if ((_modalBox.left - 10) < 0) {
962
- const _modalOffsetPosition = Math.abs(_modalBox.left) + EXCEEDED_SIDE_POS_OFFSET;
1026
+ if ((_modalBox.left - 10) < containerLeft) {
1027
+ const _modalOffsetPosition = Math.abs(_modalBox.left - containerLeft) + EXCEEDED_SIDE_POS_OFFSET;
963
1028
  _modalContent.dataset.offset = _modalOffsetPosition;
964
1029
  _modalContent.style.marginLeft = `${_modalOffsetPosition}px`;
965
1030
  // console.log('_modalPosition: ', _modalOffsetPosition)
966
1031
  }
967
1032
 
968
-
969
1033
  }
970
1034
 
971
1035
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "UIUX Lab",
3
3
  "email": "uiuxlab@gmail.com",
4
4
  "name": "funda-ui",
5
- "version": "4.7.525",
5
+ "version": "4.7.545",
6
6
  "description": "React components using pure Bootstrap 5+ which does not contain any external style and script libraries.",
7
7
  "repository": {
8
8
  "type": "git",