UNPKG

react-native-paper-select

Version:

Material Design Select Dropdown Component using React Native Paper

338 lines (292 loc) 13.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _flashList = require("@shopify/flash-list"); var _reactNativePaper = require("react-native-paper"); var _checkBox = _interopRequireDefault(require("../components/checkBox")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } const PaperSelect = ({ // Required props label, arrayList, selectedArrayList, multiEnable, value, onSelection, // Core props disabled = false, hideSearchBox = false, selectAllEnable = true, textInputMode = 'flat', theme: themeOverrides, inputRef, limit = null, limitError = `You can't select more than ${limit} items.`, limitErrorStyle, // Localization props dialogTitle, selectAllText = 'Select all', searchText = 'Search', dialogCloseButtonText = 'Close', dialogDoneButtonText = 'Done', errorText, // Style props containerStyle, textInputStyle, textInputOutlineStyle, dialogStyle, dialogTitleStyle, searchStyle, dialogCloseButtonStyle, dialogDoneButtonStyle, errorStyle, textColor, // Component props textInputProps: textInputPropOverrides, checkboxProps: checkboxPropsOverrides, searchbarProps: searchbarPropsOverrides, // New testID props testID, dialogTestID, searchbarTestID, selectAllCheckboxTestID, itemCheckboxTestIDPrefix = 'checkbox-' // Prefix for item checkboxes testID }) => { var _textInputPropOverrid, _textInputPropOverrid2, _textInputPropOverrid3, _textInputPropOverrid4, _textInputPropOverrid5; const theme = (0, _reactNativePaper.useTheme)(themeOverrides); const textInputIconProps = { style: styles.textInputIcon, size: 20, icon: 'chevron-down' }; const textInputProps = { underlineColor: (_textInputPropOverrid = textInputPropOverrides === null || textInputPropOverrides === void 0 ? void 0 : textInputPropOverrides.underlineColor) !== null && _textInputPropOverrid !== void 0 ? _textInputPropOverrid : 'black', activeUnderlineColor: (_textInputPropOverrid2 = textInputPropOverrides === null || textInputPropOverrides === void 0 ? void 0 : textInputPropOverrides.activeUnderlineColor) !== null && _textInputPropOverrid2 !== void 0 ? _textInputPropOverrid2 : 'black', outlineColor: (_textInputPropOverrid3 = textInputPropOverrides === null || textInputPropOverrides === void 0 ? void 0 : textInputPropOverrides.outlineColor) !== null && _textInputPropOverrid3 !== void 0 ? _textInputPropOverrid3 : 'black', activeOutlineColor: (_textInputPropOverrid4 = textInputPropOverrides === null || textInputPropOverrides === void 0 ? void 0 : textInputPropOverrides.activeOutlineColor) !== null && _textInputPropOverrid4 !== void 0 ? _textInputPropOverrid4 : 'black', left: textInputPropOverrides === null || textInputPropOverrides === void 0 ? void 0 : textInputPropOverrides.left, right: (_textInputPropOverrid5 = textInputPropOverrides === null || textInputPropOverrides === void 0 ? void 0 : textInputPropOverrides.right) !== null && _textInputPropOverrid5 !== void 0 ? _textInputPropOverrid5 : /*#__PURE__*/_react.default.createElement(_reactNativePaper.TextInput.Icon, textInputIconProps) }; const { height } = _reactNative.Dimensions.get('window'); const [searchKey, setSearchKey] = (0, _react.useState)(''); const [arrayHolder, setArrayHolder] = (0, _react.useState)([...arrayList]); const [list, setList] = (0, _react.useState)([...arrayList]); const [selectedList, setSelectedList] = (0, _react.useState)([...selectedArrayList]); const [maxLimit, setMaxLimit] = (0, _react.useState)(list.length); const [hasDisabled, setHasDisabled] = (0, _react.useState)(false); const [showLimitError, setShowLimitError] = (0, _react.useState)(false); const selfInputRef = (0, _react.useRef)(null); const selectInputRef = inputRef !== null && inputRef !== void 0 ? inputRef : selfInputRef; const [visible, setVisible] = (0, _react.useState)(false); const triggeredByOnCheckedSingle = (0, _react.useRef)(false); (0, _react.useEffect)(() => { if (showLimitError) { const timeoutId = setTimeout(() => { setShowLimitError(false); }, 10000); // Cleanup timeout on unmount or when showLimitError changes return () => clearTimeout(timeoutId); } // Return an empty cleanup function if showLimitError is false return () => {}; }, [showLimitError]); const showDialog = () => setVisible(true); const _hideDialog = (0, _react.useCallback)(() => { var _selectInputRef$curre; setSearchKey(''); const finalText = selectedList.map(val => { const matchedItem = arrayHolder.find(el => val._id === el._id); return matchedItem ? matchedItem.value : null; }).filter(Boolean).join(', '); // Generate comma-separated values onSelection({ text: finalText, selectedList: selectedList }); setVisible(false); selectInputRef === null || selectInputRef === void 0 ? void 0 : (_selectInputRef$curre = selectInputRef.current) === null || _selectInputRef$curre === void 0 ? void 0 : _selectInputRef$curre.blur(); }, [arrayHolder, selectedList, onSelection, selectInputRef]); const _closeDialog = () => { var _selectInputRef$curre2; setVisible(false); setSearchKey(''); selectInputRef === null || selectInputRef === void 0 ? void 0 : (_selectInputRef$curre2 = selectInputRef.current) === null || _selectInputRef$curre2 === void 0 ? void 0 : _selectInputRef$curre2.blur(); }; const _onFocus = () => { _reactNative.Keyboard.dismiss(); setArrayHolder(arrayList); setList(arrayList); setMaxLimit(arrayList.length); setHasDisabled(_checkIfAnyItemDisabled(arrayList)); setSelectedList(selectedArrayList); showDialog(); }; const _onChecked = item => { let selectedData = [...selectedList]; // Ensure no direct mutation of the state const indexSelected = selectedData.findIndex(val => val._id === item._id); // console.log(indexSelected); if (indexSelected > -1) { // If item is already selected, remove it selectedData = selectedData.filter(val => val._id !== item._id); // console.log(selectedData); } else { // If item is not selected, add it if (limit && selectedData.length === limit) { setShowLimitError(true); } else { setShowLimitError(false); selectedData = [...selectedData, item]; } } // Update the state with the modified array setSelectedList(selectedData); }; const _onCheckedSingle = item => { triggeredByOnCheckedSingle.current = true; // Directly manipulate the selectedList array without creating unnecessary copies setSelectedList(prevSelectedList => { // Check if the item is already in the list if (prevSelectedList.some(val => val._id === item._id)) { return []; // If it's already selected, clear the list } return [item]; // Otherwise, select the new item }); }; (0, _react.useEffect)(() => { if (triggeredByOnCheckedSingle.current) { triggeredByOnCheckedSingle.current = false; _hideDialog(); } }, [selectedList, _hideDialog]); const _exists = item => { return selectedList.some(val => val._id === item._id); }; const _isCheckedAll = () => { return selectedList.length > 0 && selectedList.length === list.length; }; const _checkAll = () => { // If all items are selected, unselect them, otherwise select all setSelectedList(selectedList.length === list.length ? [] : [...list]); }; const _renderItem = ({ item }) => /*#__PURE__*/_react.default.createElement(_checkBox.default, _extends({}, checkboxPropsOverrides, { isChecked: _exists(item), label: item.value, onPress: () => { multiEnable === true ? _onChecked(item) : _onCheckedSingle(item); }, disabled: item.disabled, testID: `${itemCheckboxTestIDPrefix}${item._id}` })); const _filterFunction = text => { setSearchKey(text); const lowercasedText = text.toLowerCase(); const newData = arrayHolder.filter(item => item.value.toLowerCase().includes(lowercasedText)); setList(newData); }; const _checkIfAnyItemDisabled = _list => { return _list.some(x => x.disabled); }; return /*#__PURE__*/_react.default.createElement(_reactNativePaper.ThemeProvider, { theme: theme }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: [styles.container, containerStyle] }, /*#__PURE__*/_react.default.createElement(_reactNativePaper.TextInput, _extends({}, textInputProps, { ref: selectInputRef, disabled: disabled, style: [styles.textInput, textInputStyle], outlineStyle: textInputOutlineStyle, label: label, mode: textInputMode, onFocus: disabled ? undefined : _onFocus, showSoftInputOnFocus: false, value: value, textColor: textColor, error: errorText && (errorText === null || errorText === void 0 ? void 0 : errorText.length) > 0 ? true : false, testID: testID })), errorText ? /*#__PURE__*/_react.default.createElement(_reactNativePaper.Text, { style: [{ color: theme.colors.error }, errorStyle] }, errorText) : null), /*#__PURE__*/_react.default.createElement(_reactNative.View, null, /*#__PURE__*/_react.default.createElement(_reactNativePaper.Portal, null, /*#__PURE__*/_react.default.createElement(_reactNativePaper.Dialog, { style: [styles.dialog, dialogStyle], visible: visible, dismissable: false, testID: dialogTestID }, /*#__PURE__*/_react.default.createElement(_reactNativePaper.Dialog.Title, { style: dialogTitleStyle }, dialogTitle !== null && dialogTitle !== void 0 ? dialogTitle : label), /*#__PURE__*/_react.default.createElement(_reactNativePaper.Dialog.ScrollArea, { style: { paddingHorizontal: 14, height: height - height * 40 / 100 } }, !hideSearchBox ? /*#__PURE__*/_react.default.createElement(_reactNativePaper.Searchbar, _extends({}, searchbarPropsOverrides, { value: searchKey, placeholder: searchText, onChangeText: text => _filterFunction(text), style: [styles.searchbar, searchStyle], testID: searchbarTestID })) : null, /*#__PURE__*/_react.default.createElement(_flashList.FlashList, { ListHeaderComponent: multiEnable === true && selectAllEnable === true ? /*#__PURE__*/_react.default.createElement(_checkBox.default, _extends({}, checkboxPropsOverrides, { isChecked: _isCheckedAll(), label: selectAllText, onPress: () => { _checkAll(); }, disabled: hasDisabled || limit && limit > 0 && limit !== maxLimit ? true : false, testID: selectAllCheckboxTestID })) : null, data: list, renderItem: _renderItem, keyExtractor: (item, index) => item._id.toString() || index.toString(), extraData: selectedList, keyboardShouldPersistTaps: "handled", estimatedItemSize: (height - height * 45 / 100) / 10 }), showLimitError ? /*#__PURE__*/_react.default.createElement(_reactNativePaper.Text, { style: [{ color: theme.colors.error }, limitErrorStyle] }, limitError) : null), /*#__PURE__*/_react.default.createElement(_reactNativePaper.Dialog.Actions, null, /*#__PURE__*/_react.default.createElement(_reactNativePaper.Button, { labelStyle: dialogCloseButtonStyle, onPress: _closeDialog }, dialogCloseButtonText), /*#__PURE__*/_react.default.createElement(_reactNativePaper.Button, { labelStyle: dialogDoneButtonStyle, onPress: _hideDialog }, dialogDoneButtonText)))))); }; const styles = _reactNative.StyleSheet.create({ container: { width: '100%', marginBottom: 10 }, dialog: { borderRadius: 5 }, dialogScrollView: { width: '100%' }, textInput: {// backgroundColor: '#fff', // color: '#000', }, textInputIcon: { justifyContent: 'center', alignItems: 'center', alignSelf: 'center', alignContent: 'center' }, searchbar: { borderColor: '#777777', backgroundColor: '#F1F1F2', borderWidth: 0.25, marginBottom: 10, marginHorizontal: 8, color: '#000', marginTop: 12 } }); var _default = /*#__PURE__*/(0, _react.memo)(PaperSelect); exports.default = _default; //# sourceMappingURL=paperSelect.js.map