react-native-paper-select
Version:
Material Design Select Dropdown Component using React Native Paper
338 lines (292 loc) • 13.8 kB
JavaScript
;
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