react-native-molecules 0.5.0-beta.2 → 0.5.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/components/Accordion/Accordion.tsx +2 -6
- package/components/Accordion/AccordionItem.tsx +16 -12
- package/components/Accordion/AccordionItemContent.tsx +6 -1
- package/components/Accordion/AccordionItemHeader.tsx +1 -1
- package/components/Accordion/utils.ts +6 -0
- package/components/ActivityIndicator/ActivityIndicator.tsx +6 -15
- package/components/Appbar/AppbarBase.tsx +18 -13
- package/components/Button/Button.tsx +209 -264
- package/components/Button/index.tsx +9 -3
- package/components/Button/types.ts +16 -2
- package/components/Button/utils.ts +230 -208
- package/components/Checkbox/CheckboxBase.tsx +23 -128
- package/components/Checkbox/utils.ts +0 -25
- package/components/Chip/Chip.tsx +40 -52
- package/components/Chip/utils.ts +3 -7
- package/components/DateField/DateField.tsx +110 -0
- package/components/DateField/index.tsx +6 -0
- package/components/{DatePickerInput/inputUtils.ts → DateField/useDateFieldState.ts} +17 -49
- package/components/DatePicker/DateCalendar.tsx +83 -0
- package/components/DatePicker/DatePickerActions.tsx +73 -0
- package/components/DatePicker/DatePickerModal.tsx +234 -0
- package/components/DatePicker/DatePickerPopover.tsx +79 -0
- package/components/DatePicker/DatePickerProvider.tsx +152 -0
- package/components/DatePicker/DatePickerTrigger.tsx +23 -0
- package/components/DatePicker/context.tsx +82 -0
- package/components/DatePicker/index.tsx +44 -0
- package/components/DatePicker/utils.ts +293 -0
- package/components/DatePickerInline/DatePickerContext.tsx +1 -0
- package/components/DatePickerInline/DatePickerDockedHeader.tsx +113 -0
- package/components/DatePickerInline/DatePickerInline.tsx +16 -15
- package/components/DatePickerInline/DatePickerInlineBase.tsx +7 -1
- package/components/DatePickerInline/Day.tsx +25 -1
- package/components/DatePickerInline/DayRange.tsx +2 -4
- package/components/DatePickerInline/HeaderItem.tsx +42 -27
- package/components/DatePickerInline/Month.tsx +45 -65
- package/components/DatePickerInline/MonthPicker.tsx +25 -41
- package/components/DatePickerInline/Swiper.native.tsx +21 -4
- package/components/DatePickerInline/Swiper.tsx +168 -13
- package/components/DatePickerInline/Week.tsx +6 -1
- package/components/DatePickerInline/YearPicker.tsx +206 -53
- package/components/DatePickerInline/dateUtils.tsx +17 -12
- package/components/DatePickerInline/types.ts +3 -0
- package/components/DatePickerInline/utils.ts +66 -29
- package/components/Drawer/Drawer.tsx +17 -6
- package/components/ElementGroup/ElementGroup.tsx +16 -14
- package/components/FilePicker/FilePicker.tsx +48 -78
- package/components/FilePicker/index.tsx +2 -1
- package/components/FilePicker/utils.ts +9 -0
- package/components/HelperText/HelperText.tsx +0 -35
- package/components/Icon/iconFactory.tsx +3 -3
- package/components/Icon/index.tsx +1 -1
- package/components/Icon/types.ts +17 -6
- package/components/IconButton/IconButton.tsx +42 -57
- package/components/IconButton/utils.ts +142 -33
- package/components/ListItem/ListItem.tsx +3 -1
- package/components/ListItem/utils.ts +1 -1
- package/components/LoadingIndicator/LoadingIndicator.tsx +253 -0
- package/components/LoadingIndicator/LoadingIndicator.web.tsx +136 -0
- package/components/LoadingIndicator/index.tsx +13 -0
- package/components/LoadingIndicator/utils.ts +117 -0
- package/components/Menu/Menu.tsx +3 -18
- package/components/NavigationRail/NavigationRail.tsx +15 -9
- package/components/Popover/Popover.tsx +122 -145
- package/components/Popover/PopoverRoot.tsx +74 -0
- package/components/Popover/common.ts +50 -34
- package/components/Popover/index.ts +18 -1
- package/components/Popover/usePlatformMeasure.native.ts +90 -0
- package/components/Popover/usePlatformMeasure.ts +118 -0
- package/components/Popover/utils.ts +34 -0
- package/components/Select/Select.tsx +368 -507
- package/components/Select/context.tsx +72 -0
- package/components/Select/index.ts +8 -14
- package/components/Select/types.ts +2 -4
- package/components/Select/utils.ts +144 -0
- package/components/Slot/Slot.tsx +244 -0
- package/components/Slot/compose-refs.tsx +62 -0
- package/components/Slot/index.tsx +8 -0
- package/components/Surface/Surface.android.tsx +34 -8
- package/components/Surface/Surface.ios.tsx +36 -29
- package/components/Surface/Surface.tsx +31 -4
- package/components/Surface/utils.ts +44 -30
- package/components/Switch/Switch.tsx +8 -2
- package/components/Tabs/TabItem.tsx +35 -58
- package/components/Tabs/TabLabel.tsx +5 -9
- package/components/Tabs/Tabs.tsx +154 -148
- package/components/Tabs/utils.ts +15 -2
- package/components/TextInput/TextInput.tsx +658 -575
- package/components/TextInput/index.tsx +19 -3
- package/components/TextInput/types.ts +76 -27
- package/components/TextInput/utils.ts +225 -145
- package/components/TimeField/TimeField.tsx +75 -0
- package/components/TimeField/index.tsx +6 -0
- package/components/TimeField/useTimeFieldState.ts +70 -0
- package/components/{TimePickerField/sanitizeTime.ts → TimeField/utils.ts} +77 -10
- package/components/TimePicker/TimeInput.tsx +87 -37
- package/components/TimePicker/TimeInputs.tsx +137 -49
- package/components/TimePicker/TimePicker.tsx +73 -10
- package/components/TimePicker/TimePickerModal.tsx +186 -0
- package/components/TimePicker/context.tsx +17 -0
- package/components/TimePicker/index.tsx +15 -3
- package/components/TimePicker/utils.ts +93 -0
- package/components/Tooltip/Tooltip.tsx +42 -67
- package/components/Tooltip/TooltipContent.tsx +32 -5
- package/components/Tooltip/TooltipTrigger.tsx +20 -20
- package/components/Tooltip/index.tsx +1 -1
- package/components/TouchableRipple/TouchableRipple.native.tsx +50 -14
- package/components/TouchableRipple/TouchableRipple.tsx +137 -47
- package/hocs/withPortal.tsx +1 -1
- package/hooks/index.tsx +0 -6
- package/hooks/useActionState.tsx +19 -8
- package/hooks/useControlledValue.tsx +20 -4
- package/hooks/useFilePicker.tsx +6 -16
- package/hooks/useWhatHasUpdated.tsx +48 -0
- package/package.json +17 -13
- package/shortcuts-manager/ShortcutsManager/ShortcutsManager.tsx +5 -2
- package/styles/shadow.ts +2 -1
- package/styles/themes/LightTheme.tsx +1 -1
- package/utils/DocumentPicker/documentPicker.ts +78 -27
- package/utils/DocumentPicker/types.ts +0 -1
- package/utils/extractPropertiesFromStyles.ts +25 -0
- package/utils/extractSubcomponents.ts +89 -0
- package/utils/lodash.ts +77 -5
- package/components/DatePickerDocked/DatePickerDocked.tsx +0 -30
- package/components/DatePickerDocked/DatePickerDockedHeader.tsx +0 -129
- package/components/DatePickerDocked/index.tsx +0 -17
- package/components/DatePickerDocked/types.ts +0 -11
- package/components/DatePickerDocked/utils.ts +0 -157
- package/components/DatePickerInput/DatePickerInput.tsx +0 -139
- package/components/DatePickerInput/DatePickerInputModal.tsx +0 -48
- package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +0 -77
- package/components/DatePickerInput/DateRangeInput.tsx +0 -88
- package/components/DatePickerInput/index.tsx +0 -10
- package/components/DatePickerInput/types.ts +0 -28
- package/components/DatePickerInput/utils.ts +0 -15
- package/components/DatePickerModal/AnimatedCrossView.tsx +0 -94
- package/components/DatePickerModal/CalendarEdit.tsx +0 -139
- package/components/DatePickerModal/DatePickerModal.tsx +0 -85
- package/components/DatePickerModal/DatePickerModalContent.tsx +0 -155
- package/components/DatePickerModal/DatePickerModalContentHeader.tsx +0 -213
- package/components/DatePickerModal/DatePickerModalHeader.tsx +0 -74
- package/components/DatePickerModal/DatePickerModalHeaderBackground.tsx +0 -13
- package/components/DatePickerModal/index.tsx +0 -16
- package/components/DatePickerModal/types.ts +0 -92
- package/components/DatePickerModal/utils.ts +0 -122
- package/components/DateTimePicker/DateTimePicker.tsx +0 -172
- package/components/DateTimePicker/index.tsx +0 -10
- package/components/DateTimePicker/utils.ts +0 -12
- package/components/Popover/Popover.native.tsx +0 -185
- package/components/TimePickerField/TimePickerField.tsx +0 -152
- package/components/TimePickerField/index.tsx +0 -10
- package/components/TimePickerField/utils.ts +0 -94
- package/components/TimePickerModal/TimePickerModal.tsx +0 -115
- package/components/TimePickerModal/index.tsx +0 -10
- package/components/TimePickerModal/utils.ts +0 -47
- package/hooks/useSearchable.tsx +0 -74
- package/hooks/useSubcomponents.tsx +0 -59
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { format, parse, set } from 'date-fns';
|
|
2
|
-
import { StyleSheet } from 'react-native-unistyles';
|
|
3
|
-
|
|
4
|
-
export declare type MaskItem = string | RegExp | [RegExp];
|
|
5
|
-
export declare type MaskArray = Array<MaskItem>;
|
|
6
|
-
export declare type Mask = MaskArray | ((value?: string) => MaskArray);
|
|
7
|
-
|
|
8
|
-
import { getRegisteredComponentStylesWithFallback } from '../../core';
|
|
9
|
-
|
|
10
|
-
const timepickerFieldStylesDefault = StyleSheet.create({
|
|
11
|
-
root: {},
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
export const styles = getRegisteredComponentStylesWithFallback(
|
|
15
|
-
'TimePickerField',
|
|
16
|
-
timepickerFieldStylesDefault,
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
export const timeMask24Hour: Mask = (text: string = '') => {
|
|
20
|
-
const cleanTime = text.replace(/\D+/g, '');
|
|
21
|
-
|
|
22
|
-
const hourFirstDigit = /[012]/; // only 0,1 or 2
|
|
23
|
-
let hourSecondDigit = /\d/; // any number
|
|
24
|
-
|
|
25
|
-
if (cleanTime.charAt(0) === '2') {
|
|
26
|
-
hourSecondDigit = /[0123]/; // only 0,1,2 or 3
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const minuteFirstDigit = /[012345]/; // only 0,1,2,3,4 or 5
|
|
30
|
-
const minuteSecondDigit = /\d/; // any number
|
|
31
|
-
|
|
32
|
-
return [hourFirstDigit, hourSecondDigit, ':', minuteFirstDigit, minuteSecondDigit];
|
|
33
|
-
};
|
|
34
|
-
export const timeMask12Hour: Mask = (text: string = '') => {
|
|
35
|
-
const cleanTime = text.replace(/\D+/g, '');
|
|
36
|
-
|
|
37
|
-
const hourFirstDigit = /[01]/; // only 0,1 or 2
|
|
38
|
-
let hourSecondDigit = /\d/; // any number
|
|
39
|
-
|
|
40
|
-
if (cleanTime.charAt(0) === '1') {
|
|
41
|
-
hourSecondDigit = /[012]/; // only 0,1,2 or 3
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const minuteFirstDigit = /[012345]/; // only 0,1,2,3,4 or 5
|
|
45
|
-
const minuteSecondDigit = /\d/; // any number
|
|
46
|
-
|
|
47
|
-
return [hourFirstDigit, hourSecondDigit, ':', minuteFirstDigit, minuteSecondDigit, /[ap]/, 'm'];
|
|
48
|
-
};
|
|
49
|
-
export const timeFormat = {
|
|
50
|
-
'24': {
|
|
51
|
-
format: 'HH:mm',
|
|
52
|
-
mask: timeMask24Hour,
|
|
53
|
-
},
|
|
54
|
-
'12': {
|
|
55
|
-
format: 'hh:mmaaa',
|
|
56
|
-
mask: timeMask12Hour,
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const referenceDate = new Date('2022-01-01T00:00:00.000Z');
|
|
61
|
-
|
|
62
|
-
export const sanitizeTimeString = (time: string): string => time.replace(/[^\d:]/g, '');
|
|
63
|
-
|
|
64
|
-
export const getFormattedTime = ({ time, is24Hour }: { time: string; is24Hour: boolean }) => {
|
|
65
|
-
if (!time) {
|
|
66
|
-
return '';
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const [hour = '0', minute = '0'] = sanitizeTimeString(time).split(':');
|
|
70
|
-
|
|
71
|
-
const newHour = hour.padStart(2, '0');
|
|
72
|
-
const newMinute = minute.padStart(2, '0');
|
|
73
|
-
|
|
74
|
-
return format(
|
|
75
|
-
set(referenceDate, { hours: +newHour, minutes: +newMinute }),
|
|
76
|
-
timeFormat[is24Hour ? '24' : '12'].format,
|
|
77
|
-
);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export const getOutputTime = ({ time, is24Hour }: { time: string; is24Hour: boolean }) => {
|
|
81
|
-
if (!time) return '';
|
|
82
|
-
|
|
83
|
-
const formattedTime = sanitizeTimeString(getFormattedTime({ time, is24Hour }));
|
|
84
|
-
const isPM = time.replace(/[\d:]/g, '').includes('p');
|
|
85
|
-
|
|
86
|
-
return format(
|
|
87
|
-
parse(
|
|
88
|
-
formattedTime + (is24Hour ? '' : isPM ? 'pm' : 'am'),
|
|
89
|
-
timeFormat[is24Hour ? '24' : '12'].format,
|
|
90
|
-
referenceDate,
|
|
91
|
-
),
|
|
92
|
-
'HH:mm',
|
|
93
|
-
);
|
|
94
|
-
};
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import { KeyboardAvoidingView, Platform, View } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { format } from '../../utils/date-fns';
|
|
5
|
-
import { Button } from '../Button';
|
|
6
|
-
import { IconButton } from '../IconButton';
|
|
7
|
-
import { Modal, type ModalProps } from '../Modal';
|
|
8
|
-
import { Portal } from '../Portal';
|
|
9
|
-
import { Text } from '../Text';
|
|
10
|
-
import TimePicker from '../TimePicker/TimePicker';
|
|
11
|
-
import {
|
|
12
|
-
clockTypes,
|
|
13
|
-
getTimeInputTypeIcon,
|
|
14
|
-
inputTypes,
|
|
15
|
-
type PossibleClockTypes,
|
|
16
|
-
type PossibleInputTypes,
|
|
17
|
-
reverseInputTypes,
|
|
18
|
-
} from '../TimePicker/timeUtils';
|
|
19
|
-
import { styles } from './utils';
|
|
20
|
-
|
|
21
|
-
export type Props = Omit<ModalProps, 'children'> & {
|
|
22
|
-
is24Hour?: boolean;
|
|
23
|
-
label?: string;
|
|
24
|
-
uppercase?: boolean;
|
|
25
|
-
cancelLabel?: string;
|
|
26
|
-
confirmLabel?: string;
|
|
27
|
-
time?: string;
|
|
28
|
-
onConfirm: (time: string) => any;
|
|
29
|
-
keyboardIcon?: string;
|
|
30
|
-
clockIcon?: string;
|
|
31
|
-
isLandscape?: boolean;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export function TimePickerModal({
|
|
35
|
-
isOpen,
|
|
36
|
-
onClose,
|
|
37
|
-
onConfirm: onConfirmProp,
|
|
38
|
-
time: timeProp,
|
|
39
|
-
label = 'Select time',
|
|
40
|
-
uppercase = false,
|
|
41
|
-
cancelLabel = 'Cancel',
|
|
42
|
-
confirmLabel = 'Ok',
|
|
43
|
-
is24Hour,
|
|
44
|
-
keyboardIcon = 'keyboard-outline',
|
|
45
|
-
clockIcon = 'clock-outline',
|
|
46
|
-
isLandscape = false,
|
|
47
|
-
style,
|
|
48
|
-
...rest
|
|
49
|
-
}: Props) {
|
|
50
|
-
const [inputType, setInputType] = useState<PossibleInputTypes>(inputTypes.picker);
|
|
51
|
-
const [focused, setFocused] = useState<PossibleClockTypes>(clockTypes.hours);
|
|
52
|
-
const [time, setTime] = useState(() => timeProp || format(new Date(), 'HH:mm'));
|
|
53
|
-
|
|
54
|
-
const modelStyle = useMemo(() => [styles.modalContent, style], [style]);
|
|
55
|
-
|
|
56
|
-
const onFocusInput = useCallback((type: PossibleClockTypes) => setFocused(type), []);
|
|
57
|
-
|
|
58
|
-
const onChange = useCallback(
|
|
59
|
-
(params: { focused?: PossibleClockTypes | undefined; time: string }) => {
|
|
60
|
-
if (params.focused) {
|
|
61
|
-
setFocused(params.focused);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
setTime(params.time);
|
|
65
|
-
},
|
|
66
|
-
[setFocused, setTime],
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
const onConfirm = useCallback(() => onConfirmProp(time), [onConfirmProp, time]);
|
|
70
|
-
|
|
71
|
-
useEffect(() => {
|
|
72
|
-
setTime(timeProp || format(new Date(), 'HH:mm'));
|
|
73
|
-
}, [timeProp]);
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
<Portal>
|
|
77
|
-
<Modal {...rest} isOpen={isOpen} style={modelStyle} onClose={onClose}>
|
|
78
|
-
<KeyboardAvoidingView
|
|
79
|
-
style={styles.keyboardView}
|
|
80
|
-
behavior={Platform.OS === 'ios' ? 'padding' : undefined}>
|
|
81
|
-
<View style={styles.labelContainer}>
|
|
82
|
-
<Text style={styles.label}>{uppercase ? label.toUpperCase() : label}</Text>
|
|
83
|
-
</View>
|
|
84
|
-
<View style={styles.timePickerContainer}>
|
|
85
|
-
<TimePicker
|
|
86
|
-
is24Hour={is24Hour}
|
|
87
|
-
inputType={inputType}
|
|
88
|
-
focused={focused}
|
|
89
|
-
time={time}
|
|
90
|
-
onTimeChange={onChange}
|
|
91
|
-
onFocusInput={onFocusInput}
|
|
92
|
-
isLandscape={isLandscape}
|
|
93
|
-
/>
|
|
94
|
-
</View>
|
|
95
|
-
<View style={styles.footer}>
|
|
96
|
-
<IconButton
|
|
97
|
-
name={getTimeInputTypeIcon(inputType, {
|
|
98
|
-
keyboard: keyboardIcon,
|
|
99
|
-
picker: clockIcon,
|
|
100
|
-
})}
|
|
101
|
-
onPress={() => setInputType(reverseInputTypes[inputType])}
|
|
102
|
-
style={styles.inputTypeToggle}
|
|
103
|
-
accessibilityLabel="toggle keyboard"
|
|
104
|
-
/>
|
|
105
|
-
<View style={styles.fill} />
|
|
106
|
-
<Button onPress={onClose}>{cancelLabel}</Button>
|
|
107
|
-
<Button onPress={onConfirm}>{confirmLabel}</Button>
|
|
108
|
-
</View>
|
|
109
|
-
</KeyboardAvoidingView>
|
|
110
|
-
</Modal>
|
|
111
|
-
</Portal>
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export default memo(TimePickerModal);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { getRegisteredComponentWithFallback } from '../../core';
|
|
2
|
-
import TimePickerModalDefault from './TimePickerModal';
|
|
3
|
-
|
|
4
|
-
export const TimePickerModal = getRegisteredComponentWithFallback(
|
|
5
|
-
'TimePickerModal',
|
|
6
|
-
TimePickerModalDefault,
|
|
7
|
-
);
|
|
8
|
-
|
|
9
|
-
export type { Props as TimePickerModalProps } from './TimePickerModal';
|
|
10
|
-
export { styles } from './utils';
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
|
|
3
|
-
import { getRegisteredComponentStylesWithFallback } from '../../core';
|
|
4
|
-
|
|
5
|
-
const timepickerModalStylesDefault = StyleSheet.create(theme => ({
|
|
6
|
-
keyboardView: {
|
|
7
|
-
justifyContent: 'center',
|
|
8
|
-
alignItems: 'center',
|
|
9
|
-
flex: 1,
|
|
10
|
-
},
|
|
11
|
-
modalContent: {
|
|
12
|
-
minWidth: 287,
|
|
13
|
-
width: undefined,
|
|
14
|
-
maxWidth: undefined,
|
|
15
|
-
flex: undefined,
|
|
16
|
-
borderRadius: theme.shapes.corner.extraLarge,
|
|
17
|
-
},
|
|
18
|
-
labelContainer: {
|
|
19
|
-
height: 28,
|
|
20
|
-
justifyContent: 'flex-end',
|
|
21
|
-
paddingLeft: theme.spacings['6'],
|
|
22
|
-
paddingRight: theme.spacings['6'],
|
|
23
|
-
alignSelf: 'flex-start',
|
|
24
|
-
},
|
|
25
|
-
label: {
|
|
26
|
-
letterSpacing: 1,
|
|
27
|
-
fontSize: theme.typescale.labelLarge.fontSize,
|
|
28
|
-
color: theme.colors.onSurface,
|
|
29
|
-
fontWeight: theme.typescale.labelLarge.fontWeight,
|
|
30
|
-
},
|
|
31
|
-
timePickerContainer: {
|
|
32
|
-
padding: theme.spacings['6'],
|
|
33
|
-
},
|
|
34
|
-
footer: {
|
|
35
|
-
flexDirection: 'row',
|
|
36
|
-
alignItems: 'center',
|
|
37
|
-
padding: theme.spacings['2'],
|
|
38
|
-
width: '100%',
|
|
39
|
-
},
|
|
40
|
-
inputTypeToggle: { margin: theme.spacings['1'] },
|
|
41
|
-
fill: { flex: 1 },
|
|
42
|
-
}));
|
|
43
|
-
|
|
44
|
-
export const styles = getRegisteredComponentStylesWithFallback(
|
|
45
|
-
'TimePickerModal',
|
|
46
|
-
timepickerModalStylesDefault,
|
|
47
|
-
);
|
package/hooks/useSearchable.tsx
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { type ReactElement, useCallback, useMemo } from 'react';
|
|
2
|
-
|
|
3
|
-
import { IconButton } from '../components/IconButton';
|
|
4
|
-
import {
|
|
5
|
-
TextInput,
|
|
6
|
-
type TextInputElementProps,
|
|
7
|
-
type TextInputProps,
|
|
8
|
-
} from '../components/TextInput';
|
|
9
|
-
import useControlledValue from './useControlledValue';
|
|
10
|
-
|
|
11
|
-
export interface UseSearchableProps {
|
|
12
|
-
searchable?: boolean;
|
|
13
|
-
onQueryChange?: (search: string) => void;
|
|
14
|
-
query?: string;
|
|
15
|
-
searchInputProps?: Omit<TextInputProps, 'value' | 'onChangeText'>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const useSearchInputProps = (props?: Partial<TextInputProps>) => {
|
|
19
|
-
const onChange = props?.onChangeText;
|
|
20
|
-
const onPressClear = useCallback(() => {
|
|
21
|
-
onChange?.('');
|
|
22
|
-
}, [onChange]);
|
|
23
|
-
|
|
24
|
-
const right = useCallback(
|
|
25
|
-
({ color, forceFocus }: TextInputElementProps) => (
|
|
26
|
-
<IconButton
|
|
27
|
-
name={props?.value ? 'close-circle-outline' : 'magnify'}
|
|
28
|
-
onPress={props?.value ? onPressClear : forceFocus}
|
|
29
|
-
color={color}
|
|
30
|
-
/>
|
|
31
|
-
),
|
|
32
|
-
[onPressClear, props?.value],
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
return useMemo(
|
|
36
|
-
() => (props?.right === undefined ? props : { right, ...props }),
|
|
37
|
-
[props, right],
|
|
38
|
-
);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const useSearchable = ({
|
|
42
|
-
searchable,
|
|
43
|
-
onQueryChange,
|
|
44
|
-
query,
|
|
45
|
-
searchInputProps,
|
|
46
|
-
}: UseSearchableProps = {}): ReactElement<TextInputProps> | null => {
|
|
47
|
-
const [value, onValueChange] = useControlledValue({
|
|
48
|
-
value: query || '',
|
|
49
|
-
defaultValue: '', // to disable the useControlledValue inside TextInput
|
|
50
|
-
onChange: onQueryChange,
|
|
51
|
-
disabled: !searchable,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
const props = useSearchInputProps(
|
|
55
|
-
useMemo(
|
|
56
|
-
() => ({
|
|
57
|
-
...searchInputProps,
|
|
58
|
-
value,
|
|
59
|
-
onChangeText: onValueChange,
|
|
60
|
-
}),
|
|
61
|
-
[onValueChange, searchInputProps, value],
|
|
62
|
-
),
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
return useMemo(() => {
|
|
66
|
-
if (!searchable || !onQueryChange) return null;
|
|
67
|
-
|
|
68
|
-
return <TextInput {...props} />;
|
|
69
|
-
}, [onQueryChange, props, searchable]);
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export { useSearchInputProps };
|
|
73
|
-
|
|
74
|
-
export default useSearchable;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { ReactElement } from 'react';
|
|
2
|
-
import { Children, type FC, isValidElement, useMemo } from 'react';
|
|
3
|
-
|
|
4
|
-
export type UseSubcomponentsProps<T extends string> = {
|
|
5
|
-
children: ReactElement | ReactElement[];
|
|
6
|
-
/**
|
|
7
|
-
* array of displayName as string
|
|
8
|
-
* */
|
|
9
|
-
allowedChildren: T[];
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* This will return an object with the displayNames as the property names
|
|
14
|
-
* eg. allowedChildren: ['Drawer_Header', 'Drawer_Content', 'Drawer_Footer', 'DrawerItem'];
|
|
15
|
-
*
|
|
16
|
-
* return value -> {
|
|
17
|
-
* Drawer_Header: [],
|
|
18
|
-
* Drawer_Content: [],
|
|
19
|
-
* Drawer_Footer: [],
|
|
20
|
-
* DrawerItem: [],
|
|
21
|
-
* }
|
|
22
|
-
* */
|
|
23
|
-
const useSubcomponents = <T extends string = string>({
|
|
24
|
-
children,
|
|
25
|
-
allowedChildren,
|
|
26
|
-
}: UseSubcomponentsProps<T>) => {
|
|
27
|
-
return useMemo(() => {
|
|
28
|
-
// this will create properties with default empty array values even if they don't exist in the children
|
|
29
|
-
const defaultContext = allowedChildren.reduce((context, childName) => {
|
|
30
|
-
return {
|
|
31
|
-
...context,
|
|
32
|
-
[childName]: [],
|
|
33
|
-
};
|
|
34
|
-
}, {}) as {
|
|
35
|
-
[key in T]: ReactElement[];
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
return Children.map(children, child => child).reduce((context, child) => {
|
|
39
|
-
if (!isValidElement(child)) return context;
|
|
40
|
-
|
|
41
|
-
if (
|
|
42
|
-
!allowedChildren.find(name => name === ((child.type as FC).displayName as string))
|
|
43
|
-
) {
|
|
44
|
-
return context;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const name = (child.type as FC).displayName as T;
|
|
48
|
-
|
|
49
|
-
if (!name) return context;
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
...context,
|
|
53
|
-
[name]: [...context[name], child],
|
|
54
|
-
};
|
|
55
|
-
}, defaultContext);
|
|
56
|
-
}, [allowedChildren, children]);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export default useSubcomponents;
|