import ZenInput from './ZenInput'; import ZenText from './ZenText'; import type { ThemeType } from '../../literals/Type.literal'; import { useState } from 'react'; import { TouchableOpacity, StyleSheet, View, Dimensions, ScrollView } from 'react-native'; import ThemeConfig from '../../config/Theme.config'; import { useTheme } from './../../hooks/useTheme'; import LayersConfig from '../../config/Layers.config'; import LayoutConfig from '../../config/LayoutConfig'; import ColorUtil from '../../util/Color.util'; type ZenSelectProps = { items: string[]; label?: string; placeholder?: string; dir?: 'ltr' | 'rtl'; leftIcon?: string; rightIcon?: string; leftAccessory?: any; rightAccessory?: any; disabled?: boolean; type?: ThemeType; defaultValue?: string; onChange?: (selectedItem: string) => void; maxNumberOfVisibleItems?: number; }; /** * @docunator * @title ZenSelect * @description A select component with a label. The label is optional. Based on ZenInput. * @category Themed Components * @author Danilo Ramírez Mattey * @version 1.0.0 * @param {string[]} items The list of items to select from. This is required * @param {string} label The label for the select component * @param {string} placeholder The placeholder for the select component * @param {string} dir The direction of the text. Can be 'ltr' or 'rtl'. Default is 'ltr' * @param {string} leftIcon The left icon name * @param {Element} leftAccessory The left accessory element * @param {boolean} disabled Whether the select is disabled * @param {string} type The theme type for the select. Default is 'primary' * @param {string} defaultValue The default selected value * @param {Function} onChange Callback function when the selected item changes * @param {number} maxNumberOfVisibleItems The maximum number of items to show when the select is opened. Default is 3 * @see ZenInput * @example {tsx} import { Table, Row, Column, ZenSelect } from 'react-zen-ui';} export default function App() { return (
); } */ export default function ZenSelect({ items, label = 'Select', placeholder = 'Select', dir = 'ltr', leftIcon, leftAccessory, disabled = false, type = 'primary', defaultValue = '', onChange = (s: string) => { return s; }, maxNumberOfVisibleItems = 5, }: ZenSelectProps) { const [opened, setOpened] = useState(false); const [selectedItem, setSelectedItem] = useState(defaultValue); const [randomId] = useState(Math.random().toString(36).substring(7)); const theme = useTheme(); if (!theme[type]) { throw new Error( 'ZenSelect: Invalid type provided. Available types are primary, secondary, success, warning, danger, info.' ); } const changeOpened = () => { setOpened(!opened); }; const changeSelectedItem = (s: string) => { setSelectedItem(s); setOpened(false); if (onChange) { onChange(s); } }; const styles = StyleSheet.create({ container: { position: 'relative', }, overlay: { backgroundColor: 'red', }, modal: { position: 'absolute', // backgroundColor: 'red', // bottom: 0, top: '100%', zIndex: LayersConfig.select, width: '100%', borderRadius: LayoutConfig.border, // padding: LayoutConfig.space, // paddingBottom: LayoutConfig.space * 10, paddingLeft: LayoutConfig.space, paddingRight: LayoutConfig.space, // paddingBottom: LayoutConfig.space * 10, display: 'flex', gap: LayoutConfig.space, backgroundColor: ColorUtil.shade( theme.background, ThemeConfig.defaultShareRatio.input ), borderWidth: 1, borderColor: theme[type] ?? theme.primary, maxHeight: maxNumberOfVisibleItems && items.length > maxNumberOfVisibleItems ? (Dimensions.get('window').fontScale * 18 + LayoutConfig.space) * maxNumberOfVisibleItems : undefined, }, }); return ( {opened && ( {items.map((item: string, index: number) => ( { changeSelectedItem(item); }} key={`select_item_${index}_${randomId}`} activeOpacity={ThemeConfig.defaultDimValue} > {item} ))} )} ); }