UNPKG

@spaced-out/ui-design-system

Version:
127 lines (123 loc) 5.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SkipElementFromNavigation = exports.FocusManagerWithArrowKeyNavigation = void 0; var React = _interopRequireWildcard(require("react")); var _react2 = require("@floating-ui/react"); var _classify = _interopRequireDefault(require("../../utils/classify")); var _FocusManagerWithArrowKeyNavigationModule = _interopRequireDefault(require("./FocusManagerWithArrowKeyNavigation.module.css")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } const SKIP_ELEMENT_DISPLAY_NAME = 'SkipElementFromNavigation'; const SkipElementFromNavigation = exports.SkipElementFromNavigation = /*#__PURE__*/React.forwardRef((_ref, ref) => { let { children, className, ...restProps } = _ref; return /*#__PURE__*/React.createElement("div", _extends({}, restProps, { className: className, tabIndex: -1, ref: ref }), children); }); SkipElementFromNavigation.displayName = SKIP_ELEMENT_DISPLAY_NAME; const FocusManagerWithArrowKeyNavigation = props => { const { classNames, children, initialFocus = -1, orientation = 'vertical', modal = false, cols = 1, focusItemOnOpen = 'auto', loop = false, listReference, ...restFloatingFocusManagerProps } = props; const { refs, context } = (0, _react2.useFloating)({ open: true }); const [activeIndex, setActiveIndex] = React.useState(null); const listRef = React.useRef([]); const childrenArray = React.Children.toArray(children).filter(Boolean); // Note(Nishant): This is to correctly call the onClick handler which could have been on child // we also need to set the active index correctly on click for list navigation to work const childOnClickPassthrough = function (childOnClickHandler, index) { if (childOnClickHandler) { for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } childOnClickHandler(...args); } setActiveIndex(index); }; // Add childOnClickPassthrough for the list of references passed in case of custom nodes passed if (listReference) { listReference.current.map((element, index) => { const childClickHandler = element.onclick; element.onclick = function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } childOnClickPassthrough(childClickHandler, index, ...args); }; }); } // Note(Nishant): Force the list navigation props onto the children // while using this component make sure your all the passed children have a focus state let skippedChildrenCount = 0; const clonedChildren = listReference ? children : childrenArray.map((child, index) => { const { onClick: childClickHandler } = child.props; let adjustedIndex = index - skippedChildrenCount; if (child?.type?.displayName === SKIP_ELEMENT_DISPLAY_NAME) { skippedChildrenCount++; adjustedIndex = null; } return /*#__PURE__*/React.cloneElement(child, { ...child.props, tabIndex: activeIndex === index ? 0 : -1, ref: node => { if (adjustedIndex !== null) { listRef.current[adjustedIndex] = node; } }, onClick: function () { for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } childOnClickPassthrough(childClickHandler, adjustedIndex, ...args); } }); }); const listNavigation = (0, _react2.useListNavigation)(context, { orientation, cols, listRef: listReference ? listReference : listRef, activeIndex, onNavigate: setActiveIndex, focusItemOnOpen, loop }); const { getFloatingProps } = (0, _react2.useInteractions)([listNavigation]); return /*#__PURE__*/React.createElement(_react2.FloatingFocusManager, _extends({ context: context, modal: modal, initialFocus: initialFocus }, restFloatingFocusManagerProps), /*#__PURE__*/React.createElement("div", _extends({ ref: refs.setFloating, "data-testid": "FocusManagerWithArrowKeyNavigation" }, getFloatingProps(), { className: (0, _classify.default)(_FocusManagerWithArrowKeyNavigationModule.default.wrapper, classNames?.wrapper) }), clonedChildren)); }; exports.FocusManagerWithArrowKeyNavigation = FocusManagerWithArrowKeyNavigation;