UNPKG

@razorpay/blade

Version:

The Design System that powers Razorpay

342 lines (338 loc) 15.3 kB
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties'; import _defineProperty from '@babel/runtime/helpers/defineProperty'; import React__default from 'react'; import styled from 'styled-components'; import { componentIds } from './componentIds.js'; import { getNormalTextColor, validateActionListItemProps } from './actionListUtils.js'; import { getActionListSectionRole, getActionListItemRole } from './getA11yRoles.js'; import '../Divider/index.js'; import '../Box/BaseBox/index.js'; import { useDropdown } from '../Dropdown/useDropdown.js'; import '../Typography/index.js'; import '../../utils/index.js'; import '../../utils/metaAttribute/index.js'; import '../../utils/assignWithoutSideEffects/index.js'; import '../../utils/makeSize/index.js'; import '../../utils/makeAccessible/index.js'; import '../../utils/logger/index.js'; import '../Badge/index.js'; import '../Box/index.js'; import { dropdownComponentIds } from '../Dropdown/dropdownComponentIds.js'; import '../BaseMenu/index.js'; import '../Checkbox/index.js'; import '../Avatar/index.js'; import '../../utils/makeAnalyticsAttribute/index.js'; import { jsx, jsxs } from 'react/jsx-runtime'; import { BaseBox } from '../Box/BaseBox/BaseBox.web.js'; import { makeSize } from '../../utils/makeSize/makeSize.js'; import { makeAccessible } from '../../utils/makeAccessible/makeAccessible.web.js'; import { Text } from '../Typography/Text/Text.js'; import { assignWithoutSideEffects } from '../../utils/assignWithoutSideEffects/assignWithoutSideEffects.js'; import { isReactNative } from '../../utils/platform/isReactNative.js'; import { metaAttribute } from '../../utils/metaAttribute/metaAttribute.web.js'; import { MetaConstants } from '../../utils/metaAttribute/metaConstants.js'; import { makeAnalyticsAttribute } from '../../utils/makeAnalyticsAttribute/makeAnalyticsAttribute.js'; import { Divider } from '../Divider/Divider.js'; import { useBaseMenuItem } from '../BaseMenu/BaseMenuContext.js'; import { Box } from '../Box/Box.js'; import { Avatar } from '../Avatar/Avatar.web.js'; import { Badge } from '../Badge/Badge.js'; import { Checkbox } from '../Checkbox/Checkbox.js'; import { throwBladeError } from '../../utils/logger/logger.js'; import { BaseMenuItem } from '../BaseMenu/BaseMenuItem/BaseMenuItem.js'; import { castWebType } from '../../utils/platform/castUtils.js'; var _excluded = ["title", "children", "testID", "_hideDivider", "_sectionChildValues"]; 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; } var StyledActionListSectionTitle = /*#__PURE__*/styled(BaseBox).withConfig({ displayName: "ActionListItem__StyledActionListSectionTitle", componentId: "m6qdwa-0" })(function (props) { return { // @TODO: replace this styled-component with new layout box when we have padding shorthand padding: makeSize(props.theme.spacing[3]) }; }); var _ActionListSectionTitle = function _ActionListSectionTitle(_ref) { var title = _ref.title, _ref$isInsideVirtuali = _ref.isInsideVirtualizedList, isInsideVirtualizedList = _ref$isInsideVirtuali === void 0 ? false : _ref$isInsideVirtuali; return /*#__PURE__*/jsx(StyledActionListSectionTitle, _objectSpread(_objectSpread({}, makeAccessible({ hidden: !isInsideVirtualizedList, role: isInsideVirtualizedList ? 'heading' : undefined })), {}, { children: /*#__PURE__*/jsx(Text, { color: "surface.text.gray.muted", size: "small", weight: "semibold", children: title }) })); }; var ActionListSectionTitle = /*#__PURE__*/assignWithoutSideEffects(_ActionListSectionTitle, { componentId: componentIds.ActionListSectionTitle }); var _ActionListSection = function _ActionListSection(_ref2) { var title = _ref2.title, children = _ref2.children, testID = _ref2.testID, _hideDivider = _ref2._hideDivider, _sectionChildValues = _ref2._sectionChildValues, rest = _objectWithoutProperties(_ref2, _excluded); var _useDropdown = useDropdown(), hasAutoCompleteInHeader = _useDropdown.hasAutoCompleteInHeader, dropdownTriggerer = _useDropdown.dropdownTriggerer, filteredValues = _useDropdown.filteredValues; var hasAutoComplete = hasAutoCompleteInHeader || dropdownTriggerer === dropdownComponentIds.triggers.AutoComplete; var isSectionVisible = React__default.useMemo(function () { if (hasAutoComplete) { var visibleActionListItemInSection = _sectionChildValues === null || _sectionChildValues === void 0 ? void 0 : _sectionChildValues.find(function (actionItemValue) { return filteredValues.includes(actionItemValue); }); return Boolean(visibleActionListItemInSection); } return true; }, [_sectionChildValues, hasAutoComplete, filteredValues]); var showDividerInRN = !(_hideDivider && isReactNative()); var showDividerInAutoComplete = hasAutoComplete ? isSectionVisible && filteredValues.length > 1 : true; return /*#__PURE__*/jsxs(BaseBox, _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, makeAccessible({ role: getActionListSectionRole(), label: title })), metaAttribute({ name: MetaConstants.ActionListSection, testID: testID })), makeAnalyticsAttribute(rest)), {}, { children: [isSectionVisible ? /*#__PURE__*/jsx(ActionListSectionTitle, { title: title }) : null, /*#__PURE__*/jsx(BaseBox, _objectSpread(_objectSpread({}, makeAccessible({ // On web, we just wrap it in another listbox to announce item count properly for particular group. // On React Native, we ignore it since `menu` + `group` role will take care of accessibility role: isReactNative() ? undefined : 'listbox' })), {}, { children: children })), showDividerInAutoComplete && showDividerInRN ? /*#__PURE__*/jsx(Divider, { marginX: "spacing.3", marginY: "spacing.1" }) : null] })); }; var ActionListSection = /*#__PURE__*/assignWithoutSideEffects( /*#__PURE__*/React__default.memo(_ActionListSection), { componentId: componentIds.ActionListSection }); var _ActionListItemIcon = function _ActionListItemIcon(_ref3) { var icon = _ref3.icon; var Icon = icon; var _useBaseMenuItem = useBaseMenuItem(), color = _useBaseMenuItem.color, isDisabled = _useBaseMenuItem.isDisabled; var iconState = isDisabled ? 'disabled' : 'muted'; return /*#__PURE__*/jsx(Icon, { color: color === 'negative' ? 'feedback.icon.negative.intense' : "interactive.icon.gray.".concat(iconState), size: "medium" }); }; var ActionListItemIcon = /*#__PURE__*/assignWithoutSideEffects(_ActionListItemIcon, { componentId: componentIds.ActionListItemIcon }); var _ActionListItemBadgeGroup = function _ActionListItemBadgeGroup(_ref4) { var children = _ref4.children; return /*#__PURE__*/jsx(Box, { display: "flex", alignItems: "center", flexDirection: "row", children: children }); }; var ActionListItemBadgeGroup = /*#__PURE__*/assignWithoutSideEffects(_ActionListItemBadgeGroup, { componentId: componentIds.ActionListItemBadgeGroup }); var _ActionListItemAvatar = function _ActionListItemAvatar(avatarProps) { return /*#__PURE__*/jsx(Avatar, _objectSpread({ size: "xsmall" }, avatarProps)); }; var ActionListItemAvatar = /*#__PURE__*/assignWithoutSideEffects(_ActionListItemAvatar, { componentId: componentIds.ActionListItemAvatar }); var _ActionListItemBadge = function _ActionListItemBadge(props) { return /*#__PURE__*/jsx(Badge, _objectSpread({ size: "medium", marginLeft: "spacing.3" }, props)); }; var ActionListItemBadge = /*#__PURE__*/assignWithoutSideEffects(_ActionListItemBadge, { componentId: componentIds.ActionListItemBadge }); var _ActionListItemText = function _ActionListItemText(_ref5) { var children = _ref5.children; var _useBaseMenuItem2 = useBaseMenuItem(), isDisabled = _useBaseMenuItem2.isDisabled; return /*#__PURE__*/jsx(Text, { variant: "caption", color: getNormalTextColor(isDisabled, { isMuted: true }), children: children }); }; var ActionListItemText = /*#__PURE__*/assignWithoutSideEffects(_ActionListItemText, { componentId: componentIds.ActionListItemText }); var BaseMenuLeadingItem = function BaseMenuLeadingItem(_ref6) { var isSelected = _ref6.isSelected, isDisabled = _ref6.isDisabled; return /*#__PURE__*/jsx(BaseBox, _objectSpread(_objectSpread({ pointerEvents: "none" // Adding aria-hidden because the listbox item in multiselect in itself explains the behaviour so announcing checkbox is unneccesary and just a nice UI tweak for us }, makeAccessible({ hidden: true })), {}, { children: /*#__PURE__*/jsx(Checkbox, { isChecked: isSelected, tabIndex: -1, isDisabled: isDisabled, children: null }) })); }; var makeActionListItemClickable = function makeActionListItemClickable(clickHandler) { if (isReactNative()) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error // @ts-ignore: ignoring ReactNative press type for the peace of mind return { onPress: clickHandler }; } return { onClick: clickHandler }; }; /** * ### ActionListItem * * Creates option inside `ActionList`. * * #### Usage * * ```jsx * <ActionList> * <ActionListItem * title="Home" * value="home" * leading={<ActionListItemIcon icon={HomeIcon} />} * trailing={<ActionListItemText>⌘ + S</ActionListItemText>} * /> * </ActionList> * ``` */ var _ActionListItem = function _ActionListItem(props) { var _useDropdown2 = useDropdown(), activeIndex = _useDropdown2.activeIndex, dropdownBaseId = _useDropdown2.dropdownBaseId, onOptionClick = _useDropdown2.onOptionClick, selectedIndices = _useDropdown2.selectedIndices, setShouldIgnoreBlurAnimation = _useDropdown2.setShouldIgnoreBlurAnimation, selectionType = _useDropdown2.selectionType, dropdownTriggerer = _useDropdown2.dropdownTriggerer, isKeydownPressed = _useDropdown2.isKeydownPressed, filteredValues = _useDropdown2.filteredValues, hasAutoCompleteInHeader = _useDropdown2.hasAutoCompleteInHeader, hasUnControlledFilterChipSelectInput = _useDropdown2.hasUnControlledFilterChipSelectInput; React__default.useEffect(function () { if (activeIndex === props._index && props._virtualizedIndex !== undefined) { var _props$_onVirtualized; (_props$_onVirtualized = props._onVirtualizedFocus) === null || _props$_onVirtualized === void 0 ? void 0 : _props$_onVirtualized.call(props, props._virtualizedIndex); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [activeIndex]); var hasAutoComplete = hasAutoCompleteInHeader || dropdownTriggerer === dropdownComponentIds.triggers.AutoComplete; var renderOnWebAs = props.href ? 'a' : 'button'; /** * In SelectInput, returns the isSelected according to selected indexes in the state * * In Other Triggers (Menu Usecase), returns `props.isSelected` since passing the * isSelected prop explicitly is the only way to select item in menu */ var getIsSelected = function getIsSelected() { if (dropdownTriggerer === dropdownComponentIds.triggers.SelectInput || hasAutoComplete || hasUnControlledFilterChipSelectInput) { if (typeof props._index === 'number') { return selectedIndices.includes(props._index); } return undefined; } return props.isSelected; }; var isSelected = getIsSelected(); React__default.useEffect(function () { validateActionListItemProps({ leading: props.leading, trailing: props.trailing, titleSuffix: props.titleSuffix }); }, [props.leading, props.trailing, props.titleSuffix]); React__default.useEffect(function () { if (true) { if (dropdownTriggerer === dropdownComponentIds.triggers.SelectInput && props.intent === 'negative') { throwBladeError({ message: 'negative intent ActionListItem cannot be used inside Dropdown with SelectInput trigger', moduleName: 'ActionListItem' }); } } }, [props.intent, dropdownTriggerer]); var isVisible = hasAutoComplete && filteredValues ? filteredValues.includes(props.value) : true; return /*#__PURE__*/jsx(BaseMenuItem, _objectSpread(_objectSpread(_objectSpread(_objectSpread({ isVisible: isVisible, as: !isReactNative() ? renderOnWebAs : undefined, id: "".concat(dropdownBaseId, "-").concat(props._index), tabIndex: -1, title: props.title, description: props.description, leading: selectionType === 'multiple' ? /*#__PURE__*/jsx(BaseMenuLeadingItem, { isSelected: isSelected, isDisabled: props.isDisabled }, "".concat(dropdownBaseId, "-").concat(props._index, "-leading-").concat(isSelected)) : props.leading, trailing: props.trailing, titleSuffix: props.titleSuffix, href: props.href, target: props.target, className: activeIndex === props._index ? 'active-focus' : '', isSelected: isSelected, isDisabled: props.isDisabled, role: getActionListItemRole(dropdownTriggerer, props.href) }, makeActionListItemClickable(function (e) { if (typeof props._index === 'number') { var _props$onClick; onOptionClick(e, props._index); (_props$onClick = props.onClick) === null || _props$onClick === void 0 ? void 0 : _props$onClick.call(props, { name: props.value, value: isSelected, event: castWebType(e) }); } })), makeAnalyticsAttribute(_objectSpread({}, props))), metaAttribute({ name: MetaConstants.ActionListItem, testID: props.testID })), {}, { onMouseDown: function onMouseDown() { // We want to keep focus on Dropdown's trigger while option is being clicked // So We set this flag that ignores the blur animation to avoid the flicker between focus out + focus in setShouldIgnoreBlurAnimation(true); }, onMouseUp: function onMouseUp() { // (Contd from above comment...) We set this flag back to false since blur of SelectInput is done calling by this time setShouldIgnoreBlurAnimation(false); }, "data-value": props.value, "data-index": props._index, selectionType: selectionType, color: props.intent, isKeydownPressed: isKeydownPressed })); }; var ActionListItem = /*#__PURE__*/assignWithoutSideEffects( /*#__PURE__*/React__default.memo(_ActionListItem), { componentId: componentIds.ActionListItem, displayName: componentIds.ActionListItem }); export { ActionListItem, ActionListItemAvatar, ActionListItemBadge, ActionListItemBadgeGroup, ActionListItemIcon, ActionListItemText, ActionListSection, ActionListSectionTitle }; //# sourceMappingURL=ActionListItem.js.map