react-native-customisable-combobox
Version:
A simple react native combobox
165 lines (164 loc) • 9.66 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Combobox = Combobox;
var react_1 = __importStar(require("react"));
var react_native_1 = require("react-native");
var DownIcon_1 = __importDefault(require("../src/components/Icons/DownIcon"));
var CloseIcon_1 = __importDefault(require("../src/components/Icons/CloseIcon"));
var styles_1 = require("./styles");
var useDebounce_1 = require("./hooks/useDebounce");
var useGetShowValue_1 = require("./hooks/useGetShowValue");
var useGetSearchItems_1 = require("./hooks/useGetSearchItems");
function Combobox(_a) {
var items = _a.items, renderItem = _a.renderItem, labelField = _a.labelField, valueField = _a.valueField, searchField = _a.searchField, style = _a.style, itemStyle = _a.itemStyle, selectedStyle = _a.selectedStyle, value = _a.value, onChange = _a.onChange, _b = _a.searchable, searchable = _b === void 0 ? false : _b, searchPlaceholder = _a.searchPlaceholder, onFocus = _a.onFocus, onBlur = _a.onBlur, showItemOnNoSearch = _a.showItemOnNoSearch, _c = _a.showAlwaysNoSearchItem, showAlwaysNoSearchItem = _c === void 0 ? false : _c, renderNoSearchItem = _a.renderNoSearchItem, renderSearchIcon = _a.renderSearchIcon, onSearchCallback = _a.onSearchCallback, onSelectedNotFoundItem = _a.onSelectedNotFoundItem, containerRadius = _a.containerRadius, showBorder = _a.showBorder, dropdownStyle = _a.dropdownStyle, label = _a.label, labelStyle = _a.labelStyle, renderLabel = _a.renderLabel, error = _a.error, errorStyle = _a.errorStyle, renderError = _a.renderError, mainContainerStyle = _a.mainContainerStyle, _d = _a.debounceDelay, debounceDelay = _d === void 0 ? 300 : _d, noFoundItemText = _a.noFoundItemText, noFoundItemTextStyle = _a.noFoundItemTextStyle, showTextStyle = _a.showTextStyle, _e = _a.useFlatList, useFlatList = _e === void 0 ? true : _e;
var _f = (0, react_1.useState)(false), open = _f[0], setOpen = _f[1];
var _g = (0, react_1.useState)(""), search = _g[0], setSearch = _g[1];
var _h = (0, react_1.useState)(value), selected = _h[0], setSelected = _h[1];
var _j = (0, react_1.useState)(false), focus = _j[0], setFocus = _j[1];
var _k = (0, react_1.useState)(0), dropdownTop = _k[0], setDropdownTop = _k[1];
var containerRef = (0, react_1.useRef)(null);
var debouncedSearch = (0, useDebounce_1.useDebounce)(search, debounceDelay);
var showValue = (0, useGetShowValue_1.useGetShowValue)({
selected: selected,
labelField: labelField,
search: search,
value: value,
setSelected: setSelected,
});
var searchedItems = (0, useGetSearchItems_1.useGetSearchItems)({
items: items,
searchField: searchField,
onSearchCallback: onSearchCallback,
search: debouncedSearch,
});
(0, react_1.useEffect)(function () {
if (containerRef.current) {
containerRef.current.measure(function (x, y, width, height, pageX, pageY) {
var dropdownHeight = !isNaN(height) ? height : 0;
setDropdownTop(dropdownHeight);
});
}
}, [open]);
var handleSelect = function (item) {
setSelected(item);
onChange(item);
handleClose();
};
var handleSearch = function (value) {
setOpen(true);
setSelected(null);
setSearch(value);
};
var handleFocus = function () {
setFocus(true);
onFocus && onFocus();
};
var handleBlur = function () {
setFocus(false);
onBlur && onBlur();
};
var handleOpen = function () {
setOpen(true);
};
var handleClose = function () {
setOpen(false);
};
var handleSelectedNotFoundItem = function () {
onSelectedNotFoundItem && onSelectedNotFoundItem(debouncedSearch);
setSelected(debouncedSearch);
handleClose();
};
var renderDropdownItem = function (_a) {
var item = _a.item, key = _a.key;
return (react_1.default.createElement(react_native_1.Pressable, { key: key, style: [styles_1.styles.item, itemStyle, selected === item && selectedStyle], onPress: function () { return handleSelect(item); } }, renderItem ? (renderItem({
item: item,
selected: selected === item,
})) : typeof item === "object" ? (react_1.default.createElement(react_native_1.Text, null, item &&
labelField &&
item[labelField])) : (react_1.default.createElement(react_native_1.Text, null, item))));
};
var renderItems = function () {
if (useFlatList) {
return (react_1.default.createElement(react_native_1.FlatList, { data: searchedItems, renderItem: function (_a) {
var item = _a.item, index = _a.index;
return renderDropdownItem({ item: item, key: index });
}, keyExtractor: function (item, index) {
return item && typeof item === "object" && valueField
? item[valueField].toString()
: index.toString();
}, style: { maxHeight: 200 } }));
}
return (react_1.default.createElement(react_native_1.ScrollView, { style: { maxHeight: 200 } }, searchedItems.map(function (item, index) {
return renderDropdownItem({ item: item, key: index });
})));
};
return (react_1.default.createElement(react_native_1.View, { style: [
styles_1.styles.mainContainer,
mainContainerStyle,
{ position: "relative" },
open && react_native_1.Platform.OS === "ios" ? { zIndex: 1000 } : {},
] },
renderLabel
? renderLabel()
: label && react_1.default.createElement(react_native_1.Text, { style: [styles_1.styles.label, labelStyle] }, label),
react_1.default.createElement(react_native_1.Pressable, { ref: containerRef, style: [
style,
styles_1.styles.container,
showBorder && styles_1.styles.border,
{
borderRadius: containerRadius || 5,
},
], onPress: handleOpen, onFocus: handleFocus, onBlur: handleBlur },
react_1.default.createElement(react_native_1.View, { style: [
focus && styles_1.styles.focus,
{
flex: 1,
flexDirection: "row",
alignItems: "center",
},
] }, searchable && open ? (react_1.default.createElement(react_native_1.View, { style: { flex: 1, flexDirection: "row" } },
renderSearchIcon && renderSearchIcon(),
react_1.default.createElement(react_native_1.TextInput, { style: [styles_1.styles.text, showTextStyle, styles_1.styles.search], placeholder: searchPlaceholder, defaultValue: showValue, onChangeText: handleSearch }))) : (react_1.default.createElement(react_native_1.View, { style: (styles_1.styles.text, showTextStyle) },
react_1.default.createElement(react_native_1.Text, null, showValue)))),
!open ? (react_1.default.createElement(DownIcon_1.default, { size: 18 })) : (react_1.default.createElement(react_native_1.Pressable, { onPress: handleClose },
react_1.default.createElement(CloseIcon_1.default, { size: 18 })))),
error && (react_1.default.createElement(react_native_1.Text, { style: [styles_1.styles.error, errorStyle] }, renderError ? renderError() : error)),
open && (react_1.default.createElement(react_native_1.View, { style: [
dropdownStyle,
styles_1.styles.dropdown,
{
marginTop: dropdownTop + 30,
},
] },
renderItems(),
searchedItems.length === 0 && !showItemOnNoSearch && (react_1.default.createElement(react_native_1.Pressable, { style: styles_1.styles.item },
react_1.default.createElement(react_native_1.Text, { style: [noFoundItemTextStyle] }, noFoundItemText ? noFoundItemText : "No items found"))),
(showAlwaysNoSearchItem ||
(showItemOnNoSearch && debouncedSearch.length === 0)) && (react_1.default.createElement(react_native_1.Pressable, { style: styles_1.styles.item, onPress: handleSelectedNotFoundItem }, renderNoSearchItem ? (renderNoSearchItem(search)) : (react_1.default.createElement(react_native_1.Text, null, search))))))));
}