UNPKG

@razorpay/blade

Version:

The Design System that powers Razorpay

348 lines (336 loc) 15.9 kB
import _defineProperty from '@babel/runtime/helpers/defineProperty'; import React__default from 'react'; import '../BaseInput/index.js'; import { InputChevronIcon } from './InputChevronIcon.web.js'; import isEmpty from '../../../utils/lodashButBetter/isEmpty.js'; import { useDropdown } from '../../Dropdown/useDropdown.js'; import '../../../utils/index.js'; import { getActionListContainerRole } from '../../ActionList/getA11yRoles.js'; import '../../../utils/metaAttribute/index.js'; import { getTagsGroup } from '../../Tag/getTagsGroup.js'; import { useFirstRender } from '../../../utils/useFirstRender.js'; import { useTableContext } from '../../Table/TableContext.js'; import { rowDensityToIsTableInputCellMapping, tableEditableCellRowDensityToInputSizeMap, validationStateToInputTrailingIconMap } from '../../Table/tokens.js'; import { useTableEditableCell } from '../../Table/TableEditableCellContext.js'; import '../../../utils/makeAnalyticsAttribute/index.js'; import '../../../utils/fireNativeEvent/index.js'; import { dropdownComponentIds } from '../../Dropdown/dropdownComponentIds.js'; import { jsx } from 'react/jsx-runtime'; import { isBrowser } from '../../../utils/platform/isBrowser.js'; import { fireNativeEvent } from '../../../utils/fireNativeEvent/fireNativeEvent.web.js'; import { isReactNative } from '../../../utils/platform/isReactNative.js'; import { BaseInput } from '../BaseInput/BaseInput.js'; import { MetaConstants } from '../../../utils/metaAttribute/metaConstants.js'; import { makeAnalyticsAttribute } from '../../../utils/makeAnalyticsAttribute/makeAnalyticsAttribute.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; } var useControlledDropdownInput = function useControlledDropdownInput(props) { var isFirstRender = useFirstRender(); var _useDropdown = useDropdown(), changeCallbackTriggerer = _useDropdown.changeCallbackTriggerer, isControlled = _useDropdown.isControlled, options = _useDropdown.options, selectedIndices = _useDropdown.selectedIndices, controlledValueIndices = _useDropdown.controlledValueIndices, setSelectedIndices = _useDropdown.setSelectedIndices, selectionType = _useDropdown.selectionType, setIsControlled = _useDropdown.setIsControlled; var getValuesArrayFromIndices = function getValuesArrayFromIndices() { var indices = []; if (isControlled) { indices = controlledValueIndices; } else { indices = selectedIndices; } return indices.map(function (selectionIndex) { return options[selectionIndex].value; }); }; var selectValues = function selectValues(valuesToSelect) { if (options.length > 0) { // we use empty `''` for clearing the input if (isEmpty(valuesToSelect)) { setSelectedIndices([]); } else if (typeof valuesToSelect === 'string') { // single select control var selectedItemIndex = options.findIndex(function (option) { return option.value === valuesToSelect; }); if (selectedItemIndex >= 0) { setSelectedIndices([selectedItemIndex]); } } else { // multiselect control // Handles repeated values in user state var uniqueValues = Array.from(new Set(valuesToSelect)); // Handle selectionType single with multiselect values var userValues = selectionType === 'single' ? [valuesToSelect === null || valuesToSelect === void 0 ? void 0 : valuesToSelect[0]] : uniqueValues; var selectedItemIndices = userValues.map(function (optionValue) { return options.findIndex(function (option) { return option.value === optionValue; }); }).filter(function (value) { return value >= 0; }); setSelectedIndices(selectedItemIndices); } } }; // Handles `defaultValue` prop React__default.useEffect(function () { if (options.length > 0 && props.defaultValue) { selectValues(props.defaultValue); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [options.length]); // Handles `value` prop React__default.useEffect(function () { if (options.length > 0 && props.value !== undefined) { if (!isControlled) { setIsControlled(true); } selectValues(props.value); // in single select AutoComplete, we have to set inputValue of autocomplete according to the new selection. if (selectionType === 'single' && !Array.isArray(props.value) && !props.isSelectInput) { var _props$syncInputValue; (_props$syncInputValue = props.syncInputValueWithSelection) === null || _props$syncInputValue === void 0 ? void 0 : _props$syncInputValue.call(props, props.value); } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.value, options]); // onChange behaviour React__default.useEffect(function () { // Ignore calling onChange on mount if (!isFirstRender) { var _props$onChange; (_props$onChange = props.onChange) === null || _props$onChange === void 0 ? void 0 : _props$onChange.call(props, { name: props.name, values: getValuesArrayFromIndices() }); if (isBrowser()) { fireNativeEvent(props.triggererRef, ['change', 'input']); } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [changeCallbackTriggerer]); }; var _BaseDropdownInputTrigger = function _BaseDropdownInputTrigger(props, ref) { var _props$placeholder, _props$validationStat, _props$maxRows, _props$label; var _useDropdown2 = useDropdown(), isOpen = _useDropdown2.isOpen, activeTagIndex = _useDropdown2.activeTagIndex, setActiveTagIndex = _useDropdown2.setActiveTagIndex, displayValue = _useDropdown2.displayValue, selectionType = _useDropdown2.selectionType, dropdownTriggerer = _useDropdown2.dropdownTriggerer, dropdownBaseId = _useDropdown2.dropdownBaseId, selectedIndices = _useDropdown2.selectedIndices, triggererRef = _useDropdown2.triggererRef, headerAutoCompleteRef = _useDropdown2.headerAutoCompleteRef, triggererWrapperRef = _useDropdown2.triggererWrapperRef, isTagDismissedRef = _useDropdown2.isTagDismissedRef, onTriggerClick = _useDropdown2.onTriggerClick, value = _useDropdown2.value, shouldIgnoreBlurAnimation = _useDropdown2.shouldIgnoreBlurAnimation, setShouldIgnoreBlurAnimation = _useDropdown2.setShouldIgnoreBlurAnimation, activeIndex = _useDropdown2.activeIndex, hasFooterAction = _useDropdown2.hasFooterAction, options = _useDropdown2.options, removeOption = _useDropdown2.removeOption, setChangeCallbackTriggerer = _useDropdown2.setChangeCallbackTriggerer, changeCallbackTriggerer = _useDropdown2.changeCallbackTriggerer; var _useTableContext = useTableContext(), rowDensity = _useTableContext.rowDensity; var _useTableEditableCell = useTableEditableCell(), isInsideTableEditableCell = _useTableEditableCell.isInsideTableEditableCell; var dropdownTriggerPlaceholder = (_props$placeholder = props.placeholder) !== null && _props$placeholder !== void 0 ? _props$placeholder : 'Select Option'; var isAutoCompleteInHeader = !props.isSelectInput && dropdownTriggerer !== dropdownComponentIds.triggers.AutoComplete; var getShowAllTags = React__default.useCallback(function () { if (isAutoCompleteInHeader) { // When AutoComplete is in bottomsheet header, we never want to show all tags in outer select input if (props.isSelectInput) { return false; } // ... And we always want to show all tags in inner AutoComplete return true; } return isOpen; }, [isAutoCompleteInHeader, props.isSelectInput, isOpen]); useControlledDropdownInput({ onChange: props.onChange, name: props.name, value: props.value, defaultValue: props.defaultValue, syncInputValueWithSelection: props.syncInputValueWithSelection, isSelectInput: props.isSelectInput, triggererRef: triggererRef }); var getValue = function getValue() { var prefix = ''; if (props.labelPosition === 'inside-input' && props.label) { prefix = "".concat(props.label, ": "); } if (props.isSelectInput) { if (selectionType === 'single') { return "".concat(prefix).concat(displayValue); } // In multiselect, we return tags so no display value is required return undefined; } // In AutoComplete, input has a special value too return props.inputValue; }; var getTags = React__default.useMemo(function () { return function (_ref) { var size = _ref.size; if (selectionType === 'single') { return undefined; } return getTagsGroup({ size: size, tags: selectedIndices.map(function (selectedIndex) { var _options$selectedInde; return (_options$selectedInde = options[selectedIndex]) === null || _options$selectedInde === void 0 ? void 0 : _options$selectedInde.title; }), activeTagIndex: activeTagIndex, isDisabled: props.isDisabled, onDismiss: function onDismiss(_ref2) { var tagIndex = _ref2.tagIndex; if (isTagDismissedRef.current) { isTagDismissedRef.current.value = true; } if (!isReactNative()) { var _triggererRef$current; (_triggererRef$current = triggererRef.current) === null || _triggererRef$current === void 0 ? void 0 : _triggererRef$current.focus(); } removeOption(selectedIndices[tagIndex]); setChangeCallbackTriggerer(Number(changeCallbackTriggerer) + 1); } }); }; }, // eslint-disable-next-line react-hooks/exhaustive-deps [selectedIndices, selectionType, activeTagIndex, changeCallbackTriggerer, options]); var tableInputProps = { isTableInputCell: rowDensityToIsTableInputCellMapping[rowDensity], id: 'table-editable-cell-input', size: tableEditableCellRowDensityToInputSizeMap[rowDensity], trailingIcon: validationStateToInputTrailingIconMap[(_props$validationStat = props.validationState) !== null && _props$validationStat !== void 0 ? _props$validationStat : 'none'], showHintsAsTooltip: true }; var isValidationStateNone = props.validationState === 'none' || props.validationState === undefined; return /*#__PURE__*/jsx(BaseInput, _objectSpread(_objectSpread(_objectSpread({ as: props.isSelectInput ? 'button' : 'input', ref: isReactNative() ? null : // eslint-disable-next-line @typescript-eslint/no-explicit-any function (node) { if (isAutoCompleteInHeader) { headerAutoCompleteRef.current = node; } else { triggererRef.current = node; } if (ref) { if (typeof ref === 'function') { ref(node); } else { ref.current = node; } } }, isDropdownTrigger: true, setInputWrapperRef: function setInputWrapperRef(wrapperNode) { // when autocomplete is in header, its not a trigger but a component inside of DropdownOverlay if (!isAutoCompleteInHeader) { triggererWrapperRef.current = wrapperNode; } }, maxTagRows: (_props$maxRows = props.maxRows) !== null && _props$maxRows !== void 0 ? _props$maxRows : 'single', tags: getTags({ size: props.size || 'medium' }), showAllTags: getShowAllTags(), activeTagIndex: activeTagIndex, setActiveTagIndex: setActiveTagIndex, shouldIgnoreBlurAnimation: shouldIgnoreBlurAnimation, setShouldIgnoreBlurAnimation: setShouldIgnoreBlurAnimation, textAlign: "left" // Form Props , label: props.label, placeholder: selectionType === 'multiple' && selectedIndices.length > 0 ? undefined : dropdownTriggerPlaceholder, hideLabelText: ((_props$label = props.label) === null || _props$label === void 0 ? void 0 : _props$label.length) === 0, accessibilityLabel: props.accessibilityLabel, labelPosition: props.labelPosition === 'inside-input' ? undefined : props.labelPosition, isLabelInsideInput: props.labelPosition === 'inside-input', necessityIndicator: props.necessityIndicator, autoCompleteSuggestionType: "none", validationState: props.validationState, helpText: props.helpText, errorText: props.errorText, successText: props.successText, name: props.name, isDisabled: props.isDisabled, isRequired: props.isRequired, prefix: props.prefix, suffix: props.suffix, autoFocus: props.autoFocus // eslint-disable-line jsx-a11y/no-autofocus , value: getValue(), onClick: function onClick(e) { var _props$onTriggerClick; if (props.isDisabled) { return; } (_props$onTriggerClick = props.onTriggerClick) === null || _props$onTriggerClick === void 0 ? void 0 : _props$onTriggerClick.call(props, e); }, onFocus: props.onFocus, onBlur: function onBlur(_ref3) { var _props$onBlur; var name = _ref3.name; (_props$onBlur = props.onBlur) === null || _props$onBlur === void 0 ? void 0 : _props$onBlur.call(props, { name: name, value: value }); }, leadingIcon: props.icon // Meta Props , componentName: props.isSelectInput ? MetaConstants.SelectInput : MetaConstants.AutoComplete, testID: props.testID // a11y Props , id: "".concat(dropdownBaseId, "-trigger"), labelId: "".concat(dropdownBaseId, "-label"), role: isAutoCompleteInHeader ? 'searchbox' : 'combobox', hasPopup: isAutoCompleteInHeader ? false : getActionListContainerRole(hasFooterAction, dropdownTriggerer), isPopupExpanded: isOpen, activeDescendant: activeIndex >= 0 ? "".concat(dropdownBaseId, "-").concat(activeIndex) : undefined, popupId: isAutoCompleteInHeader ? undefined : "".concat(dropdownBaseId, "-actionlist") // Special Props for Unique behaviour between Select and AutoComplete , onChange: props.isSelectInput ? undefined : props.onInputValueChange, onKeyDown: props.onTriggerKeydown, size: props.size }, makeAnalyticsAttribute(props)), {}, { onTrailingInteractionElementClick: function onTrailingInteractionElementClick() { if (!props.isDisabled) { // Icon onClicks to the SelectInput itself if (!isReactNative()) { var _triggererRef$current2; (_triggererRef$current2 = triggererRef.current) === null || _triggererRef$current2 === void 0 ? void 0 : _triggererRef$current2.focus(); } onTriggerClick(); } }, trailingInteractionElement: isAutoCompleteInHeader || isInsideTableEditableCell && !isValidationStateNone ? null : /*#__PURE__*/jsx(InputChevronIcon, { isDisabled: props.isDisabled, isOpen: isOpen }) }, isInsideTableEditableCell ? tableInputProps : undefined), {}, { // When AutoComplete is present inside DropdownOverlay, the floating ui adds tabIndex -1 internally. We override it with tabIndex 0 here tabIndex: isAutoCompleteInHeader ? 0 : undefined })); }; var BaseDropdownInputTrigger = /*#__PURE__*/React__default.forwardRef(_BaseDropdownInputTrigger); export { BaseDropdownInputTrigger }; //# sourceMappingURL=BaseDropdownInputTrigger.js.map