@razorpay/blade
Version:
The Design System that powers Razorpay
191 lines (185 loc) • 8.33 kB
JavaScript
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import { useFloating, shift, flip, offset, arrow, autoUpdate, useTransitionStyles, useClick, useRole, useInteractions, FloatingPortal, FloatingFocusManager } from '@floating-ui/react';
import React__default from 'react';
import { PopoverContent } from '../Popover/PopoverContent.js';
import { ARROW_HEIGHT, ARROW_WIDTH } from '../Popover/constants.js';
import { PopoverContext } from '../Popover/PopoverContext.js';
import { transitionDelay } from './tourTokens.js';
import '../BladeProvider/index.js';
import '../Box/BaseBox/index.js';
import '../../utils/metaAttribute/index.js';
import '../../tokens/global/index.js';
import { useControllableState } from '../../utils/useControllable.js';
import '../PopupArrow/index.js';
import '../../utils/makeAccessible/index.js';
import { useId } from '../../utils/useId.js';
import { getFloatingPlacementParts } from '../../utils/getFloatingPlacementParts.js';
import { componentZIndices } from '../../utils/componentZIndices.js';
import { jsx, Fragment } from 'react/jsx-runtime';
import useTheme from '../BladeProvider/useTheme.js';
import { size } from '../../tokens/global/size.js';
import { BaseBox } from '../Box/BaseBox/BaseBox.web.js';
import { metaAttribute } from '../../utils/metaAttribute/metaAttribute.web.js';
import { MetaConstants } from '../../utils/metaAttribute/metaConstants.js';
import { makeAccessible } from '../../utils/makeAccessible/makeAccessible.web.js';
import { PopupArrow } from '../PopupArrow/PopupArrow.web.js';
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
// TODO: Refactor out Popover/FloatingUI logic to a reusable hook/component later on
var TourPopover = function TourPopover(_ref) {
var attachTo = _ref.attachTo,
content = _ref.content,
title = _ref.title,
titleLeading = _ref.titleLeading,
footer = _ref.footer,
_ref$placement = _ref.placement,
placement = _ref$placement === void 0 ? 'top' : _ref$placement,
onOpenChange = _ref.onOpenChange,
_ref$zIndex = _ref.zIndex,
zIndex = _ref$zIndex === void 0 ? componentZIndices.popover : _ref$zIndex,
isOpen = _ref.isOpen,
defaultIsOpen = _ref.defaultIsOpen,
isTransitioning = _ref.isTransitioning;
var _useTheme = useTheme(),
theme = _useTheme.theme;
var defaultInitialFocusRef = React__default.useRef(null);
var arrowRef = React__default.useRef(null);
var titleId = useId('popover-title');
var GAP = theme.spacing[4];
var _getFloatingPlacement = getFloatingPlacementParts(placement),
_getFloatingPlacement2 = _slicedToArray(_getFloatingPlacement, 1),
side = _getFloatingPlacement2[0];
var isHorizontal = side === 'left' || side === 'right';
var isOppositeAxis = side === 'right' || side === 'bottom';
var _useControllableState = useControllableState({
value: isOpen,
defaultValue: defaultIsOpen,
onChange: function onChange(isOpen) {
return onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange({
isOpen: isOpen
});
}
}),
_useControllableState2 = _slicedToArray(_useControllableState, 2),
controllableIsOpen = _useControllableState2[0],
controllableSetIsOpen = _useControllableState2[1];
var _useFloating = useFloating({
open: controllableIsOpen,
onOpenChange: function onOpenChange(isOpen) {
return controllableSetIsOpen(function () {
return isOpen;
});
},
placement: placement,
strategy: 'fixed',
middleware: [shift({
crossAxis: false,
padding: GAP
}), flip({
padding: GAP,
fallbackAxisSideDirection: 'end'
}), offset(GAP + ARROW_HEIGHT), arrow({
element: arrowRef,
padding: isHorizontal ? GAP + ARROW_HEIGHT : ARROW_WIDTH
})],
transform: true,
whileElementsMounted: autoUpdate
}),
refs = _useFloating.refs,
floatingStyles = _useFloating.floatingStyles,
context = _useFloating.context,
computedPlacement = _useFloating.placement;
var close = React__default.useCallback(function () {
controllableSetIsOpen(function () {
return false;
});
}, [controllableSetIsOpen]);
// we need to animate from the offset of the computed placement
// because placement can change dynamically based on available space
var _getFloatingPlacement3 = getFloatingPlacementParts(computedPlacement),
_getFloatingPlacement4 = _slicedToArray(_getFloatingPlacement3, 1),
computedSide = _getFloatingPlacement4[0];
var computedIsHorizontal = computedSide === 'left' || computedSide === 'right';
var animationOffset = isOppositeAxis ? -size[4] : size[4];
var _useTransitionStyles = useTransitionStyles(context, {
duration: {
open: transitionDelay,
close: theme.motion.duration.xquick
},
initial: {
opacity: 0,
transform: "translate".concat(computedIsHorizontal ? 'X' : 'Y', "(").concat(animationOffset, "px)")
}
}),
isMounted = _useTransitionStyles.isMounted,
styles = _useTransitionStyles.styles;
// remove click handler if popover is controlled
var isControlled = isOpen !== undefined;
var click = useClick(context, {
enabled: !isControlled
});
var role = useRole(context);
var _useInteractions = useInteractions([click, role]),
getFloatingProps = _useInteractions.getFloatingProps;
var contextValue = React__default.useMemo(function () {
return {
close: close,
defaultInitialFocusRef: defaultInitialFocusRef,
titleId: titleId
};
}, [close, titleId]);
// https://github.com/floating-ui/floating-ui/discussions/2352#discussioncomment-6044834
React__default.useLayoutEffect(function () {
window.setTimeout(function () {
if (!attachTo) return;
refs.setReference(attachTo.current);
refs.setPositionReference(attachTo.current);
});
}, [attachTo, refs, isOpen]);
return /*#__PURE__*/jsx(PopoverContext.Provider, {
value: contextValue,
children: /*#__PURE__*/jsx(FloatingPortal, {
children: /*#__PURE__*/jsx(FloatingFocusManager
// TODO: check if isTransitioning is enough since scrolling can take longer
, {
disabled: isOpen === false || !isMounted || isTransitioning,
initialFocus: defaultInitialFocusRef,
context: context,
modal: true,
guards: true,
children: isMounted ? /*#__PURE__*/jsx(BaseBox, _objectSpread(_objectSpread(_objectSpread(_objectSpread({
ref: refs.setFloating,
style: _objectSpread(_objectSpread({}, floatingStyles), {}, {
pointerEvents: isMounted ? 'auto' : 'none'
})
// TODO: Tokenize zIndex values
,
zIndex: zIndex
}, getFloatingProps()), metaAttribute({
name: MetaConstants.TourPopover
})), makeAccessible({
labelledBy: titleId
})), {}, {
children: /*#__PURE__*/jsx(PopoverContent, {
title: title,
titleLeading: titleLeading,
footer: footer,
style: styles,
arrow: /*#__PURE__*/jsx(PopupArrow, {
ref: arrowRef,
context: context,
width: ARROW_WIDTH,
height: ARROW_HEIGHT,
fillColor: theme.colors.popup.background.subtle,
strokeColor: theme.colors.popup.border.subtle
}),
children: content
})
})) : /*#__PURE__*/jsx(Fragment, {})
})
})
});
};
export { TourPopover };
//# sourceMappingURL=TourPopover.web.js.map