@razorpay/blade
Version:
The Design System that powers Razorpay
342 lines (338 loc) • 15.3 kB
JavaScript
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