react-native-molecules 0.5.0-beta.3 → 0.5.0-beta.30
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/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 +211 -264
- package/components/Button/index.tsx +9 -3
- package/components/Button/types.ts +16 -2
- package/components/Button/utils.ts +230 -208
- package/components/Card/Card.tsx +1 -1
- package/components/Checkbox/Checkbox.tsx +125 -88
- package/components/Checkbox/CheckboxBase.ios.tsx +14 -23
- package/components/Checkbox/CheckboxBase.tsx +21 -137
- package/components/Checkbox/context.tsx +14 -0
- package/components/Checkbox/index.tsx +11 -4
- package/components/Checkbox/types.ts +63 -29
- package/components/Checkbox/utils.ts +25 -108
- package/components/Chip/Chip.tsx +41 -52
- package/components/Chip/utils.ts +3 -7
- package/components/DateField/DateField.tsx +111 -0
- package/components/DateField/index.tsx +6 -0
- package/components/{DatePickerInput/inputUtils.ts → DateField/useDateFieldState.ts} +19 -51
- package/components/DatePicker/DateCalendar.tsx +83 -0
- package/components/DatePicker/DatePickerActions.tsx +73 -0
- package/components/DatePicker/DatePickerModal.tsx +246 -0
- package/components/DatePicker/DatePickerPopover.tsx +79 -0
- package/components/DatePicker/DatePickerProvider.tsx +158 -0
- package/components/DatePicker/DatePickerTrigger.tsx +23 -0
- package/components/DatePicker/context.tsx +83 -0
- package/components/DatePicker/index.tsx +45 -0
- package/components/DatePicker/utils.ts +295 -0
- package/components/DatePickerInline/DatePickerDockedHeader.tsx +117 -0
- package/components/DatePickerInline/DatePickerInline.tsx +17 -16
- package/components/DatePickerInline/DatePickerInlineBase.tsx +11 -5
- package/components/DatePickerInline/DatePickerInlineHeader.tsx +50 -20
- package/components/DatePickerInline/Day.tsx +25 -1
- package/components/DatePickerInline/DayNames.tsx +13 -10
- package/components/DatePickerInline/DayRange.tsx +2 -4
- package/components/DatePickerInline/HeaderItem.tsx +44 -29
- package/components/DatePickerInline/Month.tsx +48 -67
- package/components/DatePickerInline/MonthPicker.tsx +80 -92
- package/components/DatePickerInline/Swiper.native.tsx +21 -4
- package/components/DatePickerInline/Swiper.tsx +169 -14
- package/components/DatePickerInline/SwiperUtils.ts +1 -1
- package/components/DatePickerInline/Week.tsx +6 -1
- package/components/DatePickerInline/YearPicker.tsx +220 -78
- package/components/DatePickerInline/dateUtils.tsx +18 -13
- package/components/DatePickerInline/store.tsx +27 -0
- package/components/DatePickerInline/types.ts +6 -2
- package/components/DatePickerInline/utils.ts +66 -29
- package/components/Divider/Divider.tsx +192 -0
- package/components/Divider/index.tsx +10 -0
- package/components/Drawer/Drawer.tsx +17 -6
- package/components/Drawer/DrawerItemGroup.tsx +3 -7
- package/components/ElementGroup/ElementGroup.tsx +1 -1
- 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 +5 -4
- package/components/Icon/index.tsx +1 -1
- package/components/Icon/types.ts +17 -6
- package/components/IconButton/IconButton.tsx +84 -84
- package/components/IconButton/index.tsx +1 -0
- package/components/IconButton/types.ts +10 -0
- package/components/IconButton/utils.ts +167 -33
- package/components/List/List.tsx +276 -0
- package/components/List/context.tsx +27 -0
- package/components/List/index.ts +8 -0
- package/components/List/types.ts +117 -0
- package/components/List/utils.ts +79 -0
- 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 +162 -39
- package/components/Menu/index.tsx +10 -7
- package/components/Menu/utils.ts +21 -70
- package/components/NavigationRail/NavigationRail.tsx +15 -9
- package/components/Popover/Popover.tsx +119 -145
- package/components/Popover/PopoverRoot.tsx +60 -0
- package/components/Popover/common.ts +54 -34
- package/components/Popover/index.ts +12 -1
- package/components/Popover/usePlatformMeasure.native.ts +90 -0
- package/components/Popover/usePlatformMeasure.ts +120 -0
- package/components/Popover/utils.ts +34 -0
- package/components/Portal/Portal.tsx +1 -2
- package/components/Radio/Radio.tsx +188 -0
- package/components/Radio/RadioBase.ios.tsx +69 -0
- package/components/Radio/RadioBase.tsx +136 -0
- package/components/Radio/context.tsx +23 -0
- package/components/Radio/index.tsx +20 -0
- package/components/Radio/types.ts +101 -0
- package/components/Radio/utils.ts +115 -0
- package/components/Rating/Rating.tsx +1 -1
- package/components/Select/Select.tsx +521 -785
- package/components/Select/context.tsx +81 -0
- package/components/Select/index.ts +26 -14
- package/components/Select/types.ts +65 -58
- package/components/Select/utils.ts +126 -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 +32 -7
- package/components/Surface/Surface.ios.tsx +34 -29
- package/components/Surface/Surface.tsx +31 -4
- package/components/Surface/utils.ts +44 -6
- package/components/Switch/Switch.ios.tsx +1 -1
- package/components/Switch/Switch.tsx +10 -3
- package/components/Tabs/TabItem.tsx +35 -58
- package/components/Tabs/TabLabel.tsx +5 -9
- package/components/Tabs/Tabs.tsx +156 -150
- package/components/Tabs/utils.ts +15 -2
- package/components/Text/textFactory.tsx +17 -5
- package/components/TextInput/TextInput.tsx +663 -579
- package/components/TextInput/index.tsx +19 -3
- package/components/TextInput/types.ts +77 -28
- package/components/TextInput/utils.ts +235 -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/AnalogClock.tsx +1 -1
- package/components/TimePicker/TimeInput.tsx +87 -42
- package/components/TimePicker/TimeInputs.tsx +138 -50
- package/components/TimePicker/TimePicker.tsx +74 -11
- 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 -4
- 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 +83 -16
- package/components/TouchableRipple/TouchableRipple.tsx +150 -102
- package/components/TouchableRipple/rippleFromForegroundColor.ts +21 -0
- package/hocs/index.tsx +1 -1
- package/hocs/withKeyboardAccessibility.tsx +2 -3
- package/hocs/withPortal.tsx +1 -1
- package/hooks/index.tsx +2 -12
- package/hooks/useActionState.tsx +19 -8
- package/hooks/useContrastColor.ts +1 -2
- package/hooks/useFilePicker.tsx +7 -17
- package/hooks/useHandleNumberFormat.tsx +2 -2
- package/hooks/useMediaQuery.tsx +1 -2
- package/package.json +95 -111
- package/shortcuts-manager/ShortcutsManager/ShortcutsManager.tsx +6 -3
- package/shortcuts-manager/ShortcutsManager/utils.tsx +1 -1
- package/shortcuts-manager/useSetScopes/useSetScopes.tsx +1 -1
- package/shortcuts-manager/useShortcut/useShortcut.tsx +1 -1
- 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/extractSubcomponents.ts +89 -0
- package/utils/extractTextStyles.ts +1 -2
- package/utils/formatNumberWithMask/formatNumberWithMask.ts +2 -1
- package/utils/index.ts +0 -3
- package/utils/normalizeToNumberString/normalizeToNumberString.ts +1 -1
- 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/DatePickerInline/DatePickerContext.tsx +0 -21
- 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/HorizontalDivider/HorizontalDivider.tsx +0 -103
- package/components/HorizontalDivider/index.tsx +0 -9
- package/components/ListItem/ListItem.tsx +0 -136
- package/components/ListItem/ListItemDescription.tsx +0 -25
- package/components/ListItem/ListItemTitle.tsx +0 -25
- package/components/ListItem/index.tsx +0 -14
- package/components/ListItem/utils.ts +0 -115
- package/components/Menu/MenuDivider.tsx +0 -13
- package/components/Menu/MenuItem.tsx +0 -128
- package/components/Popover/Popover.native.tsx +0 -185
- package/components/RadioButton/RadioButton.tsx +0 -138
- package/components/RadioButton/RadioButtonAndroid.tsx +0 -188
- package/components/RadioButton/RadioButtonGroup.tsx +0 -98
- package/components/RadioButton/RadioButtonIOS.tsx +0 -106
- package/components/RadioButton/RadioButtonItem.tsx +0 -232
- package/components/RadioButton/index.ts +0 -22
- package/components/RadioButton/utils.ts +0 -165
- 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/components/VerticalDivider/VerticalDivider.tsx +0 -100
- package/components/VerticalDivider/index.tsx +0 -9
- package/context-bridge/index.tsx +0 -87
- package/fast-context/index.tsx +0 -190
- package/hocs/typedMemo.tsx +0 -5
- package/hooks/useControlledValue.tsx +0 -68
- package/hooks/useLatest.tsx +0 -9
- package/hooks/useMergedRefs.ts +0 -14
- package/hooks/usePrevious.ts +0 -13
- package/hooks/useSearchable.tsx +0 -74
- package/hooks/useSubcomponents.tsx +0 -59
- package/hooks/useToggle.tsx +0 -24
- package/utils/color.ts +0 -22
- package/utils/compare/index.ts +0 -54
- package/utils/lodash.ts +0 -49
- package/utils/repository.ts +0 -53
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useControlledValue } from '@react-native-molecules/utils/hooks';
|
|
2
|
+
import { memo, useCallback, useMemo } from 'react';
|
|
2
3
|
|
|
3
4
|
import useFilePicker from '../../hooks/useFilePicker';
|
|
4
5
|
import type { DocumentPickerOptions, DocumentResult } from '../../utils/DocumentPicker';
|
|
5
|
-
import { ActivityIndicator } from '../ActivityIndicator';
|
|
6
6
|
import { IconButton } from '../IconButton';
|
|
7
7
|
import { TextInput, type TextInputProps } from '../TextInput';
|
|
8
|
+
import { FilePickerContext } from './utils';
|
|
8
9
|
|
|
9
10
|
export type OmitProp =
|
|
10
11
|
| 'editable'
|
|
11
12
|
| 'multiline'
|
|
12
13
|
| 'onChangeText'
|
|
14
|
+
| 'onChange'
|
|
13
15
|
| 'keyboardType'
|
|
14
16
|
| 'defaultValue'
|
|
15
17
|
| 'value'
|
|
@@ -24,45 +26,39 @@ export type Props = Omit<TextInputProps, OmitProp> &
|
|
|
24
26
|
*/
|
|
25
27
|
multiple?: boolean;
|
|
26
28
|
/**
|
|
27
|
-
*
|
|
28
|
-
* @default false
|
|
29
|
+
* Default value for uncontrolled usage
|
|
29
30
|
*/
|
|
30
|
-
|
|
31
|
-
left?: ReactNode;
|
|
32
|
-
right?: ReactNode;
|
|
31
|
+
defaultValue?: DocumentResult[];
|
|
33
32
|
/**
|
|
34
33
|
* To Control the value
|
|
35
34
|
*/
|
|
36
|
-
value?: DocumentResult
|
|
35
|
+
value?: DocumentResult[];
|
|
37
36
|
/**
|
|
38
37
|
* The Callback function to return the selected files as an array or object
|
|
39
38
|
*/
|
|
40
|
-
onChange?: (result: DocumentResult |
|
|
41
|
-
/**
|
|
42
|
-
* To replace the default progress indicator
|
|
43
|
-
*/
|
|
44
|
-
progressIndicator?: ReactNode;
|
|
39
|
+
onChange?: (result: DocumentResult[] | undefined) => any;
|
|
45
40
|
};
|
|
46
41
|
|
|
47
|
-
const FilePicker = (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
42
|
+
const FilePicker = ({
|
|
43
|
+
ref,
|
|
44
|
+
type,
|
|
45
|
+
multiple,
|
|
46
|
+
transitionStyle,
|
|
47
|
+
mode,
|
|
48
|
+
presentationStyle,
|
|
49
|
+
value: valueProp,
|
|
50
|
+
defaultValue,
|
|
51
|
+
onChange,
|
|
52
|
+
onCancel,
|
|
53
|
+
onError,
|
|
54
|
+
children,
|
|
55
|
+
...rest
|
|
56
|
+
}: Props) => {
|
|
57
|
+
const [value, onValueChange] = useControlledValue<DocumentResult[] | undefined>({
|
|
58
|
+
value: valueProp,
|
|
59
|
+
defaultValue,
|
|
60
|
+
onChange,
|
|
61
|
+
});
|
|
66
62
|
|
|
67
63
|
const { openFilePicker } = useFilePicker({
|
|
68
64
|
type,
|
|
@@ -74,60 +70,34 @@ const FilePicker = (
|
|
|
74
70
|
onError,
|
|
75
71
|
});
|
|
76
72
|
|
|
77
|
-
const
|
|
78
|
-
(
|
|
79
|
-
if (Array.isArray(response)) {
|
|
80
|
-
if (response.length > 1) {
|
|
81
|
-
setDisplayText(`${response.length} file${response.length > 1 ? 's' : ''}`);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
73
|
+
const displayText = useMemo(() => {
|
|
74
|
+
if (!value) return '';
|
|
84
75
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
},
|
|
91
|
-
[],
|
|
92
|
-
);
|
|
76
|
+
if (value.length > 1) {
|
|
77
|
+
return `${value.length} files`;
|
|
78
|
+
}
|
|
79
|
+
return value[0]?.name || '';
|
|
80
|
+
}, [value]);
|
|
93
81
|
|
|
94
82
|
const onPress = useCallback(() => {
|
|
95
83
|
openFilePicker(response => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
onChange?.(response);
|
|
84
|
+
onValueChange(response);
|
|
99
85
|
});
|
|
100
|
-
}, [
|
|
101
|
-
|
|
102
|
-
const rightElement = useMemo(() => {
|
|
103
|
-
if (!loading) {
|
|
104
|
-
return (
|
|
105
|
-
<>
|
|
106
|
-
{rightProp || (
|
|
107
|
-
<IconButton type="material-community" name="upload" onPress={onPress} />
|
|
108
|
-
)}
|
|
109
|
-
</>
|
|
110
|
-
);
|
|
111
|
-
} else {
|
|
112
|
-
return <>{progressIndicator || <ActivityIndicator />}</>;
|
|
113
|
-
}
|
|
114
|
-
}, [loading, onPress, progressIndicator, rightProp]);
|
|
86
|
+
}, [onValueChange, openFilePicker]);
|
|
115
87
|
|
|
116
|
-
|
|
117
|
-
useEffect(() => {
|
|
118
|
-
onSetInputValue(value);
|
|
119
|
-
}, [onSetInputValue, value]);
|
|
88
|
+
const contextValue = useMemo(() => ({ onPressTrigger: onPress }), [onPress]);
|
|
120
89
|
|
|
121
90
|
return (
|
|
122
|
-
<
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
91
|
+
<FilePickerContext value={contextValue}>
|
|
92
|
+
<TextInput value={displayText} {...rest} editable={false} ref={ref}>
|
|
93
|
+
<TextInput.Label>Choose file</TextInput.Label>
|
|
94
|
+
<TextInput.Right>
|
|
95
|
+
<IconButton type="material-community" name="upload" onPress={onPress} />
|
|
96
|
+
</TextInput.Right>
|
|
97
|
+
{children}
|
|
98
|
+
</TextInput>
|
|
99
|
+
</FilePickerContext>
|
|
130
100
|
);
|
|
131
101
|
};
|
|
132
102
|
|
|
133
|
-
export default memo(
|
|
103
|
+
export default memo(FilePicker);
|
|
@@ -4,4 +4,5 @@ import FilePickerDefault from './FilePicker';
|
|
|
4
4
|
export const FilePicker = getRegisteredComponentWithFallback('FilePicker', FilePickerDefault);
|
|
5
5
|
|
|
6
6
|
export type { Props as FilePickerProps } from './FilePicker';
|
|
7
|
-
export {
|
|
7
|
+
export type { FilePickerContextType } from './utils';
|
|
8
|
+
export { defaultStyles, FilePickerContext } from './utils';
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
1
2
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
3
|
|
|
3
4
|
import { getRegisteredComponentStylesWithFallback } from '../../core';
|
|
4
5
|
|
|
6
|
+
export type FilePickerContextType = {
|
|
7
|
+
onPressTrigger: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const FilePickerContext = createContext<FilePickerContextType>({
|
|
11
|
+
onPressTrigger: () => {},
|
|
12
|
+
});
|
|
13
|
+
|
|
5
14
|
const filePickerStylesDefault = StyleSheet.create({
|
|
6
15
|
root: {},
|
|
7
16
|
});
|
|
@@ -24,41 +24,6 @@ export type Props = TextProps & {
|
|
|
24
24
|
testID?: string;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* Helper text is used in conjuction with input elements to provide additional hints for the user.
|
|
29
|
-
*
|
|
30
|
-
* <div class="screenshots">
|
|
31
|
-
* <img class="small" src="screenshots/helper-text.gif" />
|
|
32
|
-
* </div>
|
|
33
|
-
*
|
|
34
|
-
* ## Usage
|
|
35
|
-
* ```js
|
|
36
|
-
* import * as React from 'react';
|
|
37
|
-
* import { View } from 'react-native';
|
|
38
|
-
* import { HelperText, TextInput } from 'react-native-paper';
|
|
39
|
-
*
|
|
40
|
-
* const MyComponent = () => {
|
|
41
|
-
* const [text, setText] = React.useState('');
|
|
42
|
-
*
|
|
43
|
-
* const onChangeText = text => setText(text);
|
|
44
|
-
*
|
|
45
|
-
* const hasErrors = () => {
|
|
46
|
-
* return !text.includes('@');
|
|
47
|
-
* };
|
|
48
|
-
*
|
|
49
|
-
* return (
|
|
50
|
-
* <View>
|
|
51
|
-
* <TextInput label="Email" value={text} onChangeText={onChangeText} />
|
|
52
|
-
* <HelperText variant="error" visible={hasErrors()}>
|
|
53
|
-
* Email address is invalid!
|
|
54
|
-
* </HelperText>
|
|
55
|
-
* </View>
|
|
56
|
-
* );
|
|
57
|
-
* };
|
|
58
|
-
*
|
|
59
|
-
* export default MyComponent;
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
27
|
const HelperText = ({
|
|
63
28
|
style: styleProp,
|
|
64
29
|
variant = 'info',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// import { textFactory } from '../Text/textFactory';
|
|
2
|
-
import { memoize } from '
|
|
3
|
-
|
|
2
|
+
import { memoize } from '@react-native-molecules/utils/helpers/lodash';
|
|
3
|
+
|
|
4
|
+
import type { IconType } from './types';
|
|
4
5
|
|
|
5
6
|
const customIcons: any = {};
|
|
6
7
|
|
|
@@ -10,9 +11,9 @@ export const registerCustomIconType = (id: string, customIcon: any) => {
|
|
|
10
11
|
|
|
11
12
|
export default memoize((type: IconType) => {
|
|
12
13
|
switch (type) {
|
|
13
|
-
case
|
|
14
|
+
case 'material-community':
|
|
14
15
|
return require('@react-native-vector-icons/material-design-icons').default;
|
|
15
|
-
case
|
|
16
|
+
case 'feather':
|
|
16
17
|
return require('@react-native-vector-icons/feather').default;
|
|
17
18
|
default:
|
|
18
19
|
if (Object.prototype.hasOwnProperty.call(customIcons, type)) {
|
|
@@ -4,4 +4,4 @@ import IconDefault from './Icon';
|
|
|
4
4
|
export const Icon = getRegisteredComponentWithFallback('Icon', IconDefault);
|
|
5
5
|
|
|
6
6
|
export { registerCustomIconType } from './iconFactory';
|
|
7
|
-
export type {
|
|
7
|
+
export type { CustomIconTypes, IconProps, IconType } from './types';
|
package/components/Icon/types.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import type { ColorValue, TextProps } from 'react-native';
|
|
2
2
|
|
|
3
|
-
export enum IconPacks {
|
|
4
|
-
MaterialCommunity = 'material-community',
|
|
5
|
-
Feather = 'feather',
|
|
6
|
-
}
|
|
7
|
-
|
|
8
3
|
export interface VectorIconProps extends TextProps {
|
|
9
4
|
/**
|
|
10
5
|
* Size of the icon, can also be passed as fontSize in the style object.
|
|
@@ -28,7 +23,23 @@ export interface VectorIconProps extends TextProps {
|
|
|
28
23
|
color?: ColorValue | number | undefined;
|
|
29
24
|
}
|
|
30
25
|
|
|
31
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Interface for registering custom icon types.
|
|
28
|
+
* Users can extend this interface via declaration merging to add their own icon types.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // In your app's type declarations (e.g., global.d.ts or a dedicated types file)
|
|
32
|
+
* declare module 'react-native-molecules' {
|
|
33
|
+
* interface CustomIconTypes {
|
|
34
|
+
* 'my-custom-icons': true;
|
|
35
|
+
* 'another-icon-set': true;
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
export interface CustomIconTypes {}
|
|
41
|
+
|
|
42
|
+
export type IconType = 'material-community' | 'feather' | keyof CustomIconTypes;
|
|
32
43
|
|
|
33
44
|
export type IconProps = VectorIconProps & {
|
|
34
45
|
type?: IconType;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import color from 'color';
|
|
2
1
|
import { forwardRef, memo, useMemo } from 'react';
|
|
3
2
|
import {
|
|
4
3
|
type GestureResponderEvent,
|
|
5
4
|
type StyleProp,
|
|
6
5
|
type TextStyle,
|
|
7
6
|
type ViewProps,
|
|
8
|
-
type ViewStyle,
|
|
9
7
|
} from 'react-native';
|
|
10
8
|
|
|
11
|
-
import { useActionState } from '../../hooks
|
|
9
|
+
import { useActionState } from '../../hooks';
|
|
12
10
|
import { resolveStateVariant } from '../../utils';
|
|
13
|
-
import { Icon, type IconType } from '../Icon';
|
|
11
|
+
import { Icon, type IconProps, type IconType } from '../Icon';
|
|
14
12
|
import CrossFadeIcon from '../Icon/CrossFadeIcon';
|
|
15
13
|
import { StateLayer } from '../StateLayer';
|
|
16
|
-
import { Surface } from '../Surface';
|
|
17
14
|
import { TouchableRipple, type TouchableRippleProps } from '../TouchableRipple';
|
|
18
|
-
import type { IconButtonVariant } from './types';
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
import type { IconButtonShape, IconButtonVariant, IconButtonWidth } from './types';
|
|
16
|
+
import {
|
|
17
|
+
defaultStyles,
|
|
18
|
+
iconButtonConstants,
|
|
19
|
+
iconButtonDefaultProps,
|
|
20
|
+
iconButtonSizeToIconSizeMap,
|
|
21
|
+
} from './utils';
|
|
22
22
|
|
|
23
23
|
export type Props = Omit<TouchableRippleProps, 'children' | 'style'> & {
|
|
24
24
|
/**
|
|
@@ -29,6 +29,14 @@ export type Props = Omit<TouchableRippleProps, 'children' | 'style'> & {
|
|
|
29
29
|
* Mode of the icon button. By default there is no specified mode - only pressable icon will be rendered.
|
|
30
30
|
*/
|
|
31
31
|
variant?: IconButtonVariant;
|
|
32
|
+
/**
|
|
33
|
+
* Container shape. Material 3 supports round and square icon buttons.
|
|
34
|
+
*/
|
|
35
|
+
shape?: IconButtonShape;
|
|
36
|
+
/**
|
|
37
|
+
* Container width option. `default` maps to Material 3's uniform width.
|
|
38
|
+
*/
|
|
39
|
+
width?: IconButtonWidth;
|
|
32
40
|
/**
|
|
33
41
|
* Whether icon button is selected. A selected button receives alternative combination of icon and container colors.
|
|
34
42
|
*/
|
|
@@ -63,14 +71,11 @@ export type Props = Omit<TouchableRippleProps, 'children' | 'style'> & {
|
|
|
63
71
|
*/
|
|
64
72
|
style?: StyleProp<TextStyle>;
|
|
65
73
|
iconStyle?: StyleProp<TextStyle>;
|
|
74
|
+
iconProps?: Omit<IconProps, 'name' | 'type' | 'style' | 'color' | 'size'>;
|
|
66
75
|
/**
|
|
67
76
|
* color of the icon
|
|
68
77
|
*/
|
|
69
78
|
color?: string;
|
|
70
|
-
/**
|
|
71
|
-
* Style of the innerContainer
|
|
72
|
-
*/
|
|
73
|
-
innerContainerStyle?: ViewStyle;
|
|
74
79
|
/**
|
|
75
80
|
* Props for the state layer
|
|
76
81
|
* */
|
|
@@ -82,20 +87,22 @@ const emptyObject = {};
|
|
|
82
87
|
const IconButton = (
|
|
83
88
|
{
|
|
84
89
|
name,
|
|
85
|
-
size =
|
|
90
|
+
size = iconButtonDefaultProps.size,
|
|
86
91
|
color: _iconColor,
|
|
87
92
|
type,
|
|
88
93
|
accessibilityLabel,
|
|
89
94
|
disabled = false,
|
|
90
95
|
onPress,
|
|
91
96
|
selected = false,
|
|
92
|
-
animated =
|
|
93
|
-
variant =
|
|
97
|
+
animated = iconButtonDefaultProps.animated,
|
|
98
|
+
variant = iconButtonDefaultProps.variant,
|
|
99
|
+
shape = iconButtonDefaultProps.shape,
|
|
100
|
+
width = iconButtonDefaultProps.width,
|
|
94
101
|
style,
|
|
95
|
-
innerContainerStyle: innerContainerStyleProp = emptyObject,
|
|
96
102
|
testID,
|
|
97
103
|
stateLayerProps = emptyObject,
|
|
98
|
-
iconStyle,
|
|
104
|
+
iconStyle: iconStyleProp,
|
|
105
|
+
iconProps,
|
|
99
106
|
...rest
|
|
100
107
|
}: Props,
|
|
101
108
|
ref: any,
|
|
@@ -117,100 +124,93 @@ const IconButton = (
|
|
|
117
124
|
variant: variant as any,
|
|
118
125
|
// @ts-ignore // TODO - fix this
|
|
119
126
|
state,
|
|
127
|
+
// @ts-ignore // TODO - fix this
|
|
120
128
|
size: typeof size === 'string' && size ? size : undefined,
|
|
121
129
|
});
|
|
122
130
|
|
|
123
131
|
const {
|
|
124
132
|
iconColor,
|
|
125
133
|
iconSize,
|
|
126
|
-
rippleColor,
|
|
127
134
|
containerStyle,
|
|
128
135
|
accessibilityState,
|
|
129
|
-
innerContainerStyle,
|
|
130
136
|
// accessibilityTraits,
|
|
131
137
|
stateLayerStyle,
|
|
138
|
+
iconStyle,
|
|
132
139
|
} = useMemo(() => {
|
|
133
140
|
const iconSizeInNum =
|
|
134
141
|
iconButtonSizeToIconSizeMap[size as keyof typeof iconButtonSizeToIconSizeMap] ??
|
|
135
|
-
(typeof size === 'number' && size ? (size as number) :
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
(typeof size === 'number' && size ? (size as number) : 24);
|
|
143
|
+
const containerHeight = Math.max(
|
|
144
|
+
iconButtonConstants.minContainerSize,
|
|
145
|
+
iconSizeInNum + iconButtonConstants.containerPadding,
|
|
146
|
+
);
|
|
147
|
+
const widthAdjustment =
|
|
148
|
+
width === 'narrow'
|
|
149
|
+
? iconButtonConstants.narrowWidthAdjustment
|
|
150
|
+
: width === 'wide'
|
|
151
|
+
? iconButtonConstants.wideWidthAdjustment
|
|
152
|
+
: 0;
|
|
153
|
+
const containerWidth = Math.max(iconSizeInNum, containerHeight + widthAdjustment);
|
|
154
|
+
const borderRadius =
|
|
155
|
+
shape === 'round' ? containerHeight / 2 : iconButtonConstants.squareCornerRadius;
|
|
144
156
|
|
|
145
157
|
return {
|
|
146
158
|
iconColor: _iconColor,
|
|
147
159
|
iconSize: iconSizeInNum,
|
|
148
|
-
rippleColor: _rippleColor,
|
|
149
|
-
innerContainerStyle: [defaultStyles.innerContainer, innerContainerStyleProp],
|
|
150
160
|
containerStyle: [
|
|
151
|
-
iconSizeInNum
|
|
152
|
-
? {
|
|
153
|
-
width: iconSizeInNum + whiteSpace,
|
|
154
|
-
height: iconSizeInNum + whiteSpace,
|
|
155
|
-
}
|
|
156
|
-
: {},
|
|
157
161
|
defaultStyles.root,
|
|
162
|
+
{
|
|
163
|
+
width: containerWidth,
|
|
164
|
+
height: containerHeight,
|
|
165
|
+
borderRadius,
|
|
166
|
+
},
|
|
158
167
|
style,
|
|
159
168
|
],
|
|
169
|
+
iconStyle: [defaultStyles.icon, iconStyleProp],
|
|
160
170
|
// accessibilityTraits: disabled ? ['button', 'disabled'] : 'button',
|
|
161
171
|
accessibilityState: { disabled },
|
|
162
|
-
stateLayerStyle: [defaultStyles.stateLayer, stateLayerProps?.style],
|
|
172
|
+
stateLayerStyle: [defaultStyles.stateLayer, { borderRadius }, stateLayerProps?.style],
|
|
163
173
|
};
|
|
164
174
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
165
|
-
}, [
|
|
166
|
-
_iconColor,
|
|
167
|
-
disabled,
|
|
168
|
-
innerContainerStyleProp,
|
|
169
|
-
size,
|
|
170
|
-
stateLayerProps?.style,
|
|
171
|
-
style,
|
|
172
|
-
state,
|
|
173
|
-
variant,
|
|
174
|
-
]);
|
|
175
|
+
}, [_iconColor, disabled, shape, size, stateLayerProps?.style, style, state, variant, width]);
|
|
175
176
|
|
|
176
177
|
return (
|
|
177
|
-
<
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
hitSlop={
|
|
191
|
-
// @ts-ignore
|
|
192
|
-
TouchableRipple?.supported ? rippleSupportedHitSlop : rippleUnsupportedHitSlop
|
|
193
|
-
}
|
|
178
|
+
<TouchableRipple
|
|
179
|
+
borderless
|
|
180
|
+
centered={shape === 'round' && width === 'default'}
|
|
181
|
+
onPress={onPress}
|
|
182
|
+
rippleAlpha={0.12}
|
|
183
|
+
accessibilityLabel={accessibilityLabel}
|
|
184
|
+
style={containerStyle}
|
|
185
|
+
// accessibilityTraits={accessibilityTraits}
|
|
186
|
+
// accessibilityComponentType="button"
|
|
187
|
+
accessibilityRole="button"
|
|
188
|
+
accessibilityState={accessibilityState}
|
|
189
|
+
disabled={disabled}
|
|
190
|
+
hitSlop={
|
|
194
191
|
// @ts-ignore
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
192
|
+
TouchableRipple?.supported ? rippleSupportedHitSlop : rippleUnsupportedHitSlop
|
|
193
|
+
}
|
|
194
|
+
// @ts-ignore
|
|
195
|
+
ref={actionsRef}
|
|
196
|
+
testID={testID}
|
|
197
|
+
{...rest}>
|
|
198
|
+
<>
|
|
199
|
+
<IconComponent
|
|
200
|
+
color={iconColor}
|
|
201
|
+
name={name}
|
|
202
|
+
size={iconSize}
|
|
203
|
+
type={type}
|
|
204
|
+
style={iconStyle}
|
|
205
|
+
{...iconProps}
|
|
206
|
+
/>
|
|
207
|
+
<StateLayer
|
|
208
|
+
testID={testID ? `${testID}-stateLayer` : ''}
|
|
209
|
+
{...stateLayerProps}
|
|
210
|
+
style={stateLayerStyle}
|
|
211
|
+
/>
|
|
212
|
+
</>
|
|
213
|
+
</TouchableRipple>
|
|
214
214
|
);
|
|
215
215
|
};
|
|
216
216
|
|
|
@@ -4,4 +4,5 @@ import IconButtonDefault from './IconButton';
|
|
|
4
4
|
export const IconButton = getRegisteredComponentWithFallback('IconButton', IconButtonDefault);
|
|
5
5
|
|
|
6
6
|
export type { Props as IconButtonProps } from './IconButton';
|
|
7
|
+
export type * from './types';
|
|
7
8
|
export { defaultStyles } from './utils';
|
|
@@ -1 +1,11 @@
|
|
|
1
1
|
export type IconButtonVariant = 'default' | 'outlined' | 'contained' | 'contained-tonal';
|
|
2
|
+
export type IconButtonShape = 'round' | 'square';
|
|
3
|
+
export type IconButtonWidth = 'narrow' | 'default' | 'wide';
|
|
4
|
+
|
|
5
|
+
export type IconButtonDefaultProps = {
|
|
6
|
+
size: 'xs' | 'sm' | 'md' | 'lg' | number;
|
|
7
|
+
variant: IconButtonVariant;
|
|
8
|
+
shape: IconButtonShape;
|
|
9
|
+
width: IconButtonWidth;
|
|
10
|
+
animated: boolean;
|
|
11
|
+
};
|