Skip to content

Instantly share code, notes, and snippets.

@mMarcos208
Created April 22, 2021 18:34
Show Gist options
  • Save mMarcos208/d715e2dee8c24449913540f916bc37ab to your computer and use it in GitHub Desktop.
Save mMarcos208/d715e2dee8c24449913540f916bc37ab to your computer and use it in GitHub Desktop.
React Native Select Multiple
import React, {useCallback, useMemo, useState} from 'react'
import {TouchableOpacity, View, ScrollView, Modal} from 'react-native'
import {Button, Checkbox} from 'react-native-paper'
import Icon from '@/components/Icon'
import colors from '@/styles/colors'
import InputSelectMultipleHeader from './InputSelectMultipleHeader'
import styles from './styles'
type Item = {
value: number
label: string
}
type InputSelectMultipleProps = {
values: Item[]
onChange(values: Item[]): void
title: string
}
const hitSlop = {top: 20, left: 20, bottom: 20, right: 20}
const InputSelectMultiple = ({title, values, onChange}: InputSelectMultipleProps) => {
const [isOpen, setIsOpen] = useState<boolean>(false)
const [items, setItems] = useState(
useMemo(
() =>
values.map((i) => ({
...i,
selected: false,
})),
[],
),
)
const clearSelection = useCallback(() => {
setItems(
items.map((i) => {
i.selected = false
return i
}),
)
onChange([])
}, [items])
const onPress = useCallback(
(item: Item) => {
setItems(
items.map((i) => {
if (item.value === i.value) {
i.selected = !i.selected
}
return i
}),
)
onChange(items.filter((i) => i.selected === true))
},
[items],
)
const handleOpen = useCallback((open: boolean) => {
setIsOpen(open)
}, [])
return (
<>
<InputSelectMultipleHeader
title={title}
selectedItemsCount={items.filter((i) => i.selected).length}
clearSelection={clearSelection}
handleOpen={handleOpen}
isOpen={isOpen}
/>
<Modal visible={isOpen} animationType="fade">
<ScrollView contentContainerStyle={styles.scrollViewContent}>
<TouchableOpacity style={styles.close} hitSlop={hitSlop} onPress={() => setIsOpen(false)}>
<Icon name="close" size={14} color={colors.silverTree} />
</TouchableOpacity>
<View style={styles.modal}>
{items.map((item) => (
<Checkbox.Item
key={item.value}
style={styles.checkbox}
label={item.label}
labelStyle={styles.checkboxLabel}
status={item.selected ? 'checked' : 'unchecked'}
onPress={() => onPress(item)}
/>
))}
</View>
<Button mode="contained" focusable onPress={() => setIsOpen(false)}>
Fechar
</Button>
</ScrollView>
</Modal>
</>
)
}
export default InputSelectMultiple
import React from 'react'
import {TextInput} from 'react-native-paper'
import Item from '@/components/Form/Item'
import colors from '@/styles/colors'
type InputSelectMultipleHeaderProps = {
isOpen: boolean
selectedItemsCount: number
title: string
clearSelection(): void
handleOpen(isOpen: boolean): void
}
const InputSelectMultipleHeader = ({
isOpen,
title,
selectedItemsCount,
clearSelection,
handleOpen,
}: InputSelectMultipleHeaderProps) => {
return (
<Item>
<TextInput
focusable={false}
blurOnSubmit={false}
value={selectedItemsCount ? `${selectedItemsCount} item(s) selecionados` : ''}
showSoftInputOnFocus
label={title}
autoCapitalize="none"
mode="outlined"
disabled
left={
selectedItemsCount ? (
<TextInput.Icon name="close-circle-outline" color={colors.vanilla} onPress={clearSelection} />
) : null
}
right={
<TextInput.Icon
name={isOpen ? 'chevron-up' : 'chevron-down'}
color={colors.vanilla}
onPress={() => {
handleOpen(!isOpen)
}}
/>
}
/>
</Item>
)
}
export default InputSelectMultipleHeader
import {StyleSheet} from 'react-native'
import colors from '@/styles/colors'
const styles = StyleSheet.create({
selected: {
backgroundColor: 'lightgray',
marginLeft: 0,
paddingLeft: 18,
},
checkbox: {
borderWidth: 0.5,
borderRadius: 4,
borderColor: colors.silverTree,
marginTop: 5,
},
checkboxLabel: {
flex: 1,
color: colors.black,
},
modal: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'white',
paddingVertical: 15,
paddingHorizontal: 15,
borderRadius: 4,
borderColor: colors.placeholder,
},
scrollViewContent: {
flexGrow: 1,
},
close: {
marginVertical: 27,
paddingHorizontal: 17,
},
})
export default styles
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment