@razorpay/blade 8.10.2 → 8.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,12 +5,13 @@ import _typeof from '@babel/runtime/helpers/typeof';
5
5
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
6
6
  import styled, { ThemeProvider, css, keyframes } from 'styled-components';
7
7
  import _objectWithoutProperties$1 from '@babel/runtime/helpers/objectWithoutProperties';
8
- import { FloatingDelayGroup, FloatingOverlay, useFloating, FloatingFocusManager, shift, flip, offset, arrow, autoUpdate, useTransitionStyles, useDelayGroup, useDelayGroupContext, useHover, useFocus, useRole, useInteractions, FloatingPortal, FloatingArrow } from '@floating-ui/react';
8
+ import { FloatingDelayGroup, detectOverflow, useFloating, FloatingOverlay, FloatingPortal, FloatingFocusManager, shift, flip, offset, arrow, autoUpdate, useTransitionStyles, useDelayGroup, useDelayGroupContext, useHover, useFocus, useRole, useInteractions, FloatingArrow } from '@floating-ui/react';
9
9
  import _toConsumableArray$1 from '@babel/runtime/helpers/toConsumableArray';
10
10
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
11
+ import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator';
12
+ import _regeneratorRuntime from '@babel/runtime/regenerator';
11
13
  import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
12
14
  import _createClass from '@babel/runtime/helpers/createClass';
13
- import { createPortal } from 'react-dom';
14
15
 
15
16
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
16
17
 
@@ -4806,14 +4807,6 @@ var ActionListBox = /*#__PURE__*/assignWithoutSideEffects(_ActionListBox, {
4806
4807
  displayName: 'ActionListBox'
4807
4808
  });
4808
4809
 
4809
- /*
4810
- * This content is licensed according to the W3C Software License at
4811
- * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
4812
- *
4813
- * This software or document includes material copied from or derived from
4814
- * https://www.w3.org/WAI/ARIA/apg/example-index/combobox/combobox-select-only.html.
4815
- * Copyright © 2022 W3C® (MIT, ERCIM, Keio, Beihang)
4816
- */
4817
4810
  var componentIds = {
4818
4811
  DropdownOverlay: 'DropdownOverlay',
4819
4812
  Dropdown: 'Dropdown',
@@ -5100,6 +5093,96 @@ var makeInputDisplayValue = function makeInputDisplayValue(selectedIndices, opti
5100
5093
  return "".concat(selectedIndices.length, " items selected");
5101
5094
  };
5102
5095
 
5096
+ /**
5097
+ * This object is used for calculating overflows in dropdown overlay.
5098
+ * 400 is used since max-width of dropdown overlay is 400px.
5099
+ */
5100
+ var POSITION_THRESHOLDS = {
5101
+ top: -400,
5102
+ bottom: -300,
5103
+ left: -400,
5104
+ right: -400
5105
+ };
5106
+ /**
5107
+ * This function calculates the position of dropdown overlay with respect to dropdown trigger element.
5108
+ * For non-menus (e.g SelectInput), position is flipped if overflow is on bottom.
5109
+ * For menus (e.g. DropdownButton), position is flipped if overflow is on right or bottom.
5110
+ * Additional spacing is added to clientHeight to provide spacing above the dropdown trigger.
5111
+ */
5112
+
5113
+ var getDropdownOverlayPosition = function getDropdownOverlayPosition(_ref) {
5114
+ var position = _ref.overflow,
5115
+ isMenu = _ref.isMenu,
5116
+ triggererEl = _ref.triggererEl;
5117
+ var zeroSpacing = 'spacing.0';
5118
+ var bottom = position.bottom,
5119
+ right = position.right;
5120
+ var newPosition = {
5121
+ left: zeroSpacing
5122
+ };
5123
+
5124
+ if (!isMenu) {
5125
+ if (bottom > POSITION_THRESHOLDS.bottom) {
5126
+ newPosition.bottom = "".concat(Number(triggererEl === null || triggererEl === void 0 ? void 0 : triggererEl.clientHeight) + Number(size[32]), "px");
5127
+ }
5128
+
5129
+ console.log({
5130
+ newPosition: newPosition
5131
+ });
5132
+ return newPosition;
5133
+ }
5134
+
5135
+ if (right > POSITION_THRESHOLDS.right) {
5136
+ newPosition.right = zeroSpacing;
5137
+ newPosition.left = undefined;
5138
+ }
5139
+
5140
+ if (bottom > POSITION_THRESHOLDS.bottom) {
5141
+ newPosition.bottom = "".concat(Number(triggererEl === null || triggererEl === void 0 ? void 0 : triggererEl.clientHeight) + Number(size[20]), "px");
5142
+ newPosition.top = undefined;
5143
+ }
5144
+
5145
+ return newPosition;
5146
+ };
5147
+ var getDropdownOverflowMiddleware = function getDropdownOverflowMiddleware(_ref2) {
5148
+ var isMenu = _ref2.isMenu,
5149
+ triggererRef = _ref2.triggererRef,
5150
+ setDropdownPosition = _ref2.setDropdownPosition;
5151
+ return {
5152
+ name: 'detectOverflowMiddleware',
5153
+ fn: function fn(state) {
5154
+ return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
5155
+ var overflow, position;
5156
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
5157
+ while (1) {
5158
+ switch (_context.prev = _context.next) {
5159
+ case 0:
5160
+ _context.next = 2;
5161
+ return detectOverflow(state, {
5162
+ elementContext: 'reference'
5163
+ });
5164
+
5165
+ case 2:
5166
+ overflow = _context.sent;
5167
+ position = getDropdownOverlayPosition({
5168
+ overflow: overflow,
5169
+ isMenu: isMenu,
5170
+ triggererEl: triggererRef.current
5171
+ });
5172
+ setDropdownPosition(position);
5173
+ return _context.abrupt("return", {});
5174
+
5175
+ case 6:
5176
+ case "end":
5177
+ return _context.stop();
5178
+ }
5179
+ }
5180
+ }, _callee);
5181
+ }))();
5182
+ }
5183
+ };
5184
+ };
5185
+
5103
5186
  var _excluded$4R = ["isOpen", "setIsOpen", "close", "selectedIndices", "setSelectedIndices", "activeIndex", "setActiveIndex", "shouldIgnoreBlur", "setShouldIgnoreBlur", "isKeydownPressed", "setIsKeydownPressed", "options", "selectionType", "changeCallbackTriggerer", "setChangeCallbackTriggerer", "isControlled", "setControlledValueIndices"];
5104
5187
 
5105
5188
  function ownKeys$5I(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
@@ -17494,7 +17577,8 @@ var useBladeInnerRef = function useBladeInnerRef(targetRef, handlers) {
17494
17577
  },
17495
17578
  getBoundingClientRect: function getBoundingClientRect() {
17496
17579
  return element === null || element === void 0 ? void 0 : element.getBoundingClientRect();
17497
- }
17580
+ },
17581
+ clientHeight: element.clientHeight
17498
17582
  };
17499
17583
  }, [innerRef, handlers]);
17500
17584
  return innerRef;
@@ -21735,7 +21819,8 @@ var _DropdownOverlay = function _DropdownOverlay(_ref) {
21735
21819
  isOpen = _useDropdown.isOpen,
21736
21820
  triggererRef = _useDropdown.triggererRef,
21737
21821
  hasLabelOnLeft = _useDropdown.hasLabelOnLeft,
21738
- dropdownTriggerer = _useDropdown.dropdownTriggerer;
21822
+ dropdownTriggerer = _useDropdown.dropdownTriggerer,
21823
+ setIsOpen = _useDropdown.setIsOpen;
21739
21824
 
21740
21825
  var _useTheme = useTheme(),
21741
21826
  theme = _useTheme.theme;
@@ -21750,7 +21835,29 @@ var _DropdownOverlay = function _DropdownOverlay(_ref) {
21750
21835
  width = _React$useState4[0],
21751
21836
  setWidth = _React$useState4[1];
21752
21837
 
21838
+ var _useState = useState({}),
21839
+ _useState2 = _slicedToArray(_useState, 2),
21840
+ dropdownPosition = _useState2[0],
21841
+ setDropdownPosition = _useState2[1];
21842
+
21753
21843
  var isMenu = dropdownTriggerer !== 'SelectInput';
21844
+
21845
+ var _useFloating = useFloating({
21846
+ open: isOpen,
21847
+ onOpenChange: setIsOpen,
21848
+ strategy: 'absolute',
21849
+ placement: 'bottom-start',
21850
+ elements: {
21851
+ reference: triggererRef.current
21852
+ },
21853
+ middleware: [getDropdownOverflowMiddleware({
21854
+ isMenu: isMenu,
21855
+ triggererRef: triggererRef,
21856
+ setDropdownPosition: setDropdownPosition
21857
+ })]
21858
+ }),
21859
+ refs = _useFloating.refs;
21860
+
21754
21861
  var fadeIn = /*#__PURE__*/css(["animation:", " ", " ", ";"], dropdownFadeIn, makeMotionTime(theme.motion.duration.quick), String(theme.motion.easing.entrance.revealing));
21755
21862
  var fadeOut = /*#__PURE__*/css(["animation:", " ", " ", ";"], dropdownFadeOut, makeMotionTime(theme.motion.duration.quick), String(theme.motion.easing.entrance.revealing));
21756
21863
  React__default.useEffect(function () {
@@ -21806,28 +21913,34 @@ var _DropdownOverlay = function _DropdownOverlay(_ref) {
21806
21913
  opacity: isOpen ? 1 : 0
21807
21914
  };
21808
21915
  }, [isOpen]);
21809
- return /*#__PURE__*/jsx(BaseBox, {
21810
- position: "relative",
21811
- children: /*#__PURE__*/jsx(StyledDropdownOverlay, _objectSpread$Q(_objectSpread$Q({
21812
- width: isMenu ? undefined : width // In SelectInput, Overlay should always take width of Input
21813
- ,
21814
- minWidth: isMenu ? '240px' : undefined // in SelectInput, we don't want to set maxWidth because it takes width according to the trigger
21815
- ,
21816
- maxWidth: isMenu ? '400px' : undefined,
21817
- left: isMenu ? 'spacing.0' : undefined,
21818
- right: isMenu ? undefined : 'spacing.0',
21819
- style: styles,
21820
- display: castWebType(display),
21821
- position: "absolute",
21822
- transition: isOpen ? fadeIn : fadeOut,
21823
- onAnimationEnd: onAnimationEnd
21824
- }, metaAttribute({
21825
- name: MetaConstants.DropdownOverlay,
21826
- testID: testID
21827
- })), {}, {
21828
- children: children
21829
- }))
21830
- });
21916
+ return (
21917
+ /*#__PURE__*/
21918
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21919
+ jsx(BaseBox, {
21920
+ position: "relative",
21921
+ ref: refs.setFloating,
21922
+ children: /*#__PURE__*/jsx(StyledDropdownOverlay, _objectSpread$Q(_objectSpread$Q({
21923
+ width: isMenu ? 'max-content' : width // In SelectInput, Overlay should always take width of Input
21924
+ ,
21925
+ minWidth: isMenu ? '240px' : undefined // in SelectInput, we don't want to set maxWidth because it takes width according to the trigger
21926
+ ,
21927
+ maxWidth: isMenu ? '400px' : undefined,
21928
+ left: dropdownPosition.left,
21929
+ right: dropdownPosition.right,
21930
+ bottom: dropdownPosition.bottom,
21931
+ style: styles,
21932
+ display: castWebType(display),
21933
+ position: "absolute",
21934
+ transition: isOpen ? fadeIn : fadeOut,
21935
+ onAnimationEnd: onAnimationEnd
21936
+ }, metaAttribute({
21937
+ name: MetaConstants.DropdownOverlay,
21938
+ testID: testID
21939
+ })), {}, {
21940
+ children: children
21941
+ }))
21942
+ })
21943
+ );
21831
21944
  };
21832
21945
 
21833
21946
  var DropdownOverlay = /*#__PURE__*/assignWithoutSideEffects(_DropdownOverlay, {
@@ -24969,25 +25082,6 @@ isVisible, opts) {
24969
25082
  };
24970
25083
  }
24971
25084
 
24972
- var createModalRootWrapper = function createModalRootWrapper(id) {
24973
- var element = document.createElement('div');
24974
- element.setAttribute('id', id);
24975
- document.body.appendChild(element);
24976
- return element;
24977
- };
24978
-
24979
- var ModalPortal = function ModalPortal(_ref) {
24980
- var children = _ref.children;
24981
- var wrapperID = 'blade-modal-root-portal';
24982
- var element = document.getElementById(wrapperID);
24983
-
24984
- if (!element) {
24985
- element = createModalRootWrapper(wrapperID);
24986
- }
24987
-
24988
- return /*#__PURE__*/createPortal(children, element);
24989
- };
24990
-
24991
25085
  /* eslint-disable @typescript-eslint/no-explicit-any */
24992
25086
  var ModalContext = /*#__PURE__*/React__default.createContext({
24993
25087
  // eslint-disable-next-line @typescript-eslint/no-empty-function
@@ -25406,48 +25500,9 @@ var Modal = function Modal(_ref2) {
25406
25500
  open: isMounted
25407
25501
  }),
25408
25502
  refs = _useFloating.refs,
25409
- context = _useFloating.context; // eslint-disable-next-line @typescript-eslint/no-explicit-any
25410
-
25503
+ context = _useFloating.context;
25411
25504
 
25412
25505
  var defaultInitialFocusRef = React__default.useRef(null);
25413
- var originalFocusElement = React__default.useRef(null);
25414
- var returnFocus = React__default.useCallback(function () {
25415
- if (!originalFocusElement.current) return;
25416
- originalFocusElement.current.focus(); // After returning focus we will clear the original focus
25417
- // Because if modal can be opened up via multiple triggers
25418
- // We want to ensure the focus returns back to the most recent triggerer
25419
-
25420
- originalFocusElement.current = null;
25421
- }, [originalFocusElement]);
25422
- var focusOnInitialRef = React__default.useCallback(function () {
25423
- if (!initialFocusRef) {
25424
- var _defaultInitialFocusR;
25425
-
25426
- // focus on close button
25427
- (_defaultInitialFocusR = defaultInitialFocusRef.current) === null || _defaultInitialFocusR === void 0 ? void 0 : _defaultInitialFocusR.focus();
25428
- } else {
25429
- var _initialFocusRef$curr;
25430
-
25431
- // focus on the initialRef passed by the user
25432
- (_initialFocusRef$curr = initialFocusRef.current) === null || _initialFocusRef$curr === void 0 ? void 0 : _initialFocusRef$curr.focus();
25433
- }
25434
- }, [initialFocusRef]);
25435
- React__default.useEffect(function () {
25436
- if (isMounted) {
25437
- var _originalFocusElement;
25438
-
25439
- // set the original focus element where the focus will return to after closing the modal
25440
- originalFocusElement.current = (_originalFocusElement = originalFocusElement.current) !== null && _originalFocusElement !== void 0 ? _originalFocusElement : document.activeElement; // focus on an element on Modal, if initialFocusRef is not passed, focus on the close button
25441
-
25442
- focusOnInitialRef();
25443
- }
25444
- }, [isMounted, focusOnInitialRef]);
25445
- React__default.useEffect(function () {
25446
- // Return focus to the element that originally had it
25447
- if (!isOpen) {
25448
- returnFocus();
25449
- }
25450
- }, [isOpen, returnFocus]);
25451
25506
  var modalContext = React__default.useMemo(function () {
25452
25507
  return {
25453
25508
  isOpen: isOpen,
@@ -25472,10 +25527,12 @@ var Modal = function Modal(_ref2) {
25472
25527
  throw new Error('[Blade Modal] Modal only accepts ModalHeader, ModalBody and ModalFooter as children');
25473
25528
  }
25474
25529
  });
25475
- return /*#__PURE__*/jsx(ModalPortal, {
25530
+ return /*#__PURE__*/jsx(FloatingPortal, {
25476
25531
  children: /*#__PURE__*/jsx(ModalContext.Provider, {
25477
25532
  value: modalContext,
25478
25533
  children: isMounted ? /*#__PURE__*/jsx(FloatingFocusManager, {
25534
+ returnFocus: true,
25535
+ initialFocus: initialFocusRef !== null && initialFocusRef !== void 0 ? initialFocusRef : defaultInitialFocusRef,
25479
25536
  context: context,
25480
25537
  modal: true,
25481
25538
  children: /*#__PURE__*/jsxs(Box, {