react-native-molecules 0.5.0-beta.20 → 0.5.0-beta.22
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/Card/Card.tsx +1 -1
- package/components/Checkbox/CheckboxBase.ios.tsx +9 -16
- package/components/Checkbox/CheckboxBase.tsx +11 -18
- package/components/DateField/DateField.tsx +4 -3
- package/components/DatePicker/DateCalendar.tsx +4 -4
- package/components/DatePicker/DatePickerModal.tsx +35 -23
- package/components/DatePicker/DatePickerProvider.tsx +8 -2
- package/components/DatePicker/context.tsx +2 -1
- package/components/DatePicker/index.tsx +1 -0
- package/components/DatePickerInline/DatePickerDockedHeader.tsx +11 -7
- package/components/DatePickerInline/DatePickerInline.tsx +1 -1
- package/components/DatePickerInline/DatePickerInlineBase.tsx +3 -3
- package/components/DatePickerInline/DatePickerInlineHeader.tsx +50 -20
- package/components/DatePickerInline/DayNames.tsx +13 -10
- package/components/DatePickerInline/HeaderItem.tsx +2 -2
- package/components/DatePickerInline/Month.tsx +4 -3
- package/components/DatePickerInline/MonthPicker.tsx +74 -54
- package/components/DatePickerInline/Swiper.native.tsx +2 -2
- package/components/DatePickerInline/Swiper.tsx +3 -3
- package/components/DatePickerInline/YearPicker.tsx +136 -112
- package/components/DatePickerInline/{DatePickerContext.tsx → store.tsx} +7 -3
- package/components/DatePickerInline/types.ts +4 -3
- package/components/Divider/Divider.tsx +192 -0
- package/components/Divider/index.tsx +11 -0
- package/components/Drawer/DrawerItemGroup.tsx +3 -7
- package/components/IconButton/IconButton.tsx +2 -12
- package/components/List/List.tsx +507 -0
- package/components/List/context.tsx +28 -0
- package/components/List/index.ts +9 -0
- package/components/List/types.ts +149 -0
- package/components/{ListItem → List}/utils.ts +47 -50
- package/components/Menu/Menu.tsx +156 -12
- package/components/Menu/index.tsx +11 -7
- package/components/Menu/utils.ts +21 -70
- package/components/RadioButton/RadioButtonAndroid.tsx +38 -54
- package/components/RadioButton/RadioButtonIOS.tsx +2 -16
- package/components/Select/Select.tsx +139 -497
- package/components/Select/context.tsx +14 -32
- package/components/Select/types.ts +44 -53
- package/components/Select/utils.ts +15 -47
- package/components/Text/textFactory.tsx +17 -5
- package/components/TimeField/TimeField.tsx +1 -1
- package/components/TimePicker/TimeInput.tsx +2 -7
- package/components/TimePicker/TimePickerModal.tsx +15 -15
- package/components/TimePicker/utils.ts +0 -4
- package/components/TouchableRipple/TouchableRipple.native.tsx +36 -5
- package/components/TouchableRipple/TouchableRipple.tsx +53 -19
- package/components/TouchableRipple/rippleFromForegroundColor.ts +21 -0
- package/package.json +4 -2
- package/components/HorizontalDivider/HorizontalDivider.tsx +0 -103
- package/components/HorizontalDivider/index.tsx +0 -9
- package/components/ListItem/ListItem.tsx +0 -138
- package/components/ListItem/ListItemDescription.tsx +0 -25
- package/components/ListItem/ListItemTitle.tsx +0 -25
- package/components/ListItem/index.tsx +0 -14
- package/components/Menu/MenuDivider.tsx +0 -13
- package/components/Menu/MenuItem.tsx +0 -128
- package/components/VerticalDivider/VerticalDivider.tsx +0 -100
- package/components/VerticalDivider/index.tsx +0 -9
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { memo, useMemo } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import { format } from '../../utils/date-fns';
|
|
5
4
|
import { Text } from '../Text';
|
|
6
5
|
import { getCalendarHeaderHeight } from './DatePickerInlineHeader';
|
|
7
6
|
import {
|
|
@@ -43,6 +42,7 @@ function Month(props: MonthSingleProps | MonthRangeProps | MonthMultiProps) {
|
|
|
43
42
|
disableWeekDays,
|
|
44
43
|
validRange,
|
|
45
44
|
showOutsideDays,
|
|
45
|
+
locale,
|
|
46
46
|
// customMonthStyles,
|
|
47
47
|
} = props;
|
|
48
48
|
const isHorizontal = scrollMode === 'horizontal';
|
|
@@ -54,9 +54,10 @@ function Month(props: MonthSingleProps | MonthRangeProps | MonthMultiProps) {
|
|
|
54
54
|
const md = addMonths(new Date(), realIndex);
|
|
55
55
|
const y = md.getFullYear();
|
|
56
56
|
const m = md.getMonth();
|
|
57
|
+
const name = new Intl.DateTimeFormat(locale, { month: 'long' }).format(md);
|
|
57
58
|
|
|
58
|
-
return { monthName:
|
|
59
|
-
}, [index]);
|
|
59
|
+
return { monthName: name, month: m, year: y };
|
|
60
|
+
}, [index, locale]);
|
|
60
61
|
|
|
61
62
|
const grid = useMemo(
|
|
62
63
|
() =>
|
|
@@ -1,29 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { memo, useCallback, useMemo
|
|
3
|
-
import { FlatList, View, type ViewStyle } from 'react-native';
|
|
1
|
+
import { setMonth } from 'date-fns';
|
|
2
|
+
import { memo, useCallback, useMemo } from 'react';
|
|
3
|
+
import { FlatList, type FlatListProps, View, type ViewStyle } from 'react-native';
|
|
4
4
|
import { StyleSheet } from 'react-native-unistyles';
|
|
5
5
|
|
|
6
6
|
import { resolveStateVariant } from '../../utils';
|
|
7
7
|
import { range } from '../../utils/dateTimePicker';
|
|
8
|
+
import type { DatePickerLocale } from '../DatePicker/context';
|
|
8
9
|
import { datePickerMonthItemStyles, datePickerMonthPickerStyles } from '../DatePicker/utils';
|
|
9
|
-
import {
|
|
10
|
+
import { Divider } from '../Divider';
|
|
10
11
|
import { Icon } from '../Icon';
|
|
11
|
-
import {
|
|
12
|
+
import { List, type ListContentProcessPropsArgs, useListContextValue } from '../List';
|
|
12
13
|
import { Text } from '../Text';
|
|
13
|
-
import {
|
|
14
|
+
import { useDatePickerInlineStore, useDatePickerInlineStoreValue } from './store';
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
type MonthListItem = { id: number; label: string };
|
|
17
|
+
|
|
18
|
+
export default function MonthPicker({ locale }: { locale?: DatePickerLocale }) {
|
|
19
|
+
const [_, setStore] = useDatePickerInlineStore(state => state);
|
|
20
|
+
const { localDate, selectingMonth } = useDatePickerInlineStoreValue(state => ({
|
|
18
21
|
localDate: state.localDate,
|
|
19
22
|
selectingMonth: state.pickerType === 'month',
|
|
20
23
|
}));
|
|
21
|
-
// const monthPickerStyles = useComponentStyles('DatePickerDocked_MonthPicker');
|
|
22
|
-
const flatList = useRef<FlatList<number> | null>(null);
|
|
23
24
|
const months = range(0, 11);
|
|
25
|
+
const monthItems = useMemo<MonthListItem[]>(
|
|
26
|
+
() => months.map(month => ({ id: month, label: String(month) })),
|
|
27
|
+
[months],
|
|
28
|
+
);
|
|
24
29
|
|
|
25
30
|
const handleOnChange = useCallback(
|
|
26
|
-
(month: number) => {
|
|
31
|
+
(month: number | null) => {
|
|
32
|
+
if (month === null) return;
|
|
27
33
|
setStore(prev => ({
|
|
28
34
|
localDate: setMonth(prev.localDate, month),
|
|
29
35
|
pickerType: undefined,
|
|
@@ -32,18 +38,26 @@ export default function MonthPicker() {
|
|
|
32
38
|
[setStore],
|
|
33
39
|
);
|
|
34
40
|
|
|
35
|
-
const
|
|
36
|
-
({
|
|
37
|
-
|
|
41
|
+
const processFlatListProps = useCallback(
|
|
42
|
+
({
|
|
43
|
+
props,
|
|
44
|
+
items,
|
|
45
|
+
}: ListContentProcessPropsArgs<
|
|
46
|
+
MonthListItem,
|
|
47
|
+
Omit<FlatListProps<MonthListItem>, 'children' | 'ref'>
|
|
48
|
+
>): FlatListProps<MonthListItem> => ({
|
|
49
|
+
...props,
|
|
50
|
+
data: items,
|
|
51
|
+
renderItem: ({ item }) => (
|
|
38
52
|
<Month
|
|
39
|
-
month={item}
|
|
40
|
-
selected={localDate.getMonth() === item}
|
|
41
|
-
onPressMonth={handleOnChange}
|
|
53
|
+
month={item.id}
|
|
42
54
|
monthStyles={datePickerMonthPickerStyles.root}
|
|
55
|
+
locale={locale}
|
|
43
56
|
/>
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
),
|
|
58
|
+
keyExtractor: item => `${item.id}`,
|
|
59
|
+
}),
|
|
60
|
+
[locale],
|
|
47
61
|
);
|
|
48
62
|
|
|
49
63
|
if (!selectingMonth) {
|
|
@@ -51,39 +65,45 @@ export default function MonthPicker() {
|
|
|
51
65
|
}
|
|
52
66
|
|
|
53
67
|
return (
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
<List
|
|
69
|
+
items={monthItems}
|
|
70
|
+
multiple={false}
|
|
71
|
+
value={localDate.getMonth()}
|
|
72
|
+
onChange={handleOnChange}>
|
|
73
|
+
<View
|
|
74
|
+
style={[
|
|
75
|
+
StyleSheet.absoluteFill,
|
|
76
|
+
styles.root,
|
|
77
|
+
selectingMonth ? styles.opacity1 : styles.opacity0,
|
|
78
|
+
]}
|
|
79
|
+
pointerEvents={selectingMonth ? 'auto' : 'none'}>
|
|
80
|
+
<Divider />
|
|
81
|
+
<List.Content<MonthListItem, typeof FlatList<MonthListItem>>
|
|
82
|
+
ContainerComponent={FlatList<MonthListItem>}
|
|
83
|
+
style={styles.list}
|
|
84
|
+
processProps={processFlatListProps}
|
|
85
|
+
/>
|
|
86
|
+
</View>
|
|
87
|
+
</List>
|
|
71
88
|
);
|
|
72
89
|
}
|
|
73
90
|
|
|
74
91
|
function MonthPure({
|
|
75
92
|
month,
|
|
76
|
-
selected,
|
|
77
|
-
onPressMonth,
|
|
78
93
|
monthStyles,
|
|
94
|
+
locale,
|
|
79
95
|
}: {
|
|
80
96
|
month: number;
|
|
81
|
-
selected: boolean;
|
|
82
|
-
onPressMonth: (newMonth: number) => any;
|
|
83
97
|
monthStyles: ViewStyle;
|
|
98
|
+
locale?: DatePickerLocale;
|
|
84
99
|
}) {
|
|
100
|
+
const isSelected = useListContextValue(state => {
|
|
101
|
+
const selectedValue = state.value as any;
|
|
102
|
+
return (selectedValue?.id ?? selectedValue) === month;
|
|
103
|
+
});
|
|
104
|
+
|
|
85
105
|
const state = resolveStateVariant({
|
|
86
|
-
selected,
|
|
106
|
+
selected: isSelected,
|
|
87
107
|
});
|
|
88
108
|
|
|
89
109
|
datePickerMonthItemStyles.useVariants({
|
|
@@ -95,25 +115,25 @@ function MonthPure({
|
|
|
95
115
|
|
|
96
116
|
return {
|
|
97
117
|
monthButtonStyle: [monthButton, monthStyles],
|
|
98
|
-
accessibilityState: { selected },
|
|
118
|
+
accessibilityState: { selected: isSelected },
|
|
99
119
|
};
|
|
100
|
-
|
|
101
|
-
}, [selected, monthStyles, state]);
|
|
120
|
+
}, [isSelected, monthStyles]);
|
|
102
121
|
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
122
|
+
const monthLabel = useMemo(
|
|
123
|
+
() => new Intl.DateTimeFormat(locale, { month: 'long' }).format(new Date(2000, month, 1)),
|
|
124
|
+
[locale, month],
|
|
125
|
+
);
|
|
106
126
|
|
|
107
127
|
return (
|
|
108
|
-
<
|
|
109
|
-
|
|
128
|
+
<List.Item
|
|
129
|
+
value={month}
|
|
110
130
|
accessibilityRole="button"
|
|
111
131
|
accessibilityLabel={String(month)}
|
|
112
132
|
accessibilityState={accessibilityState}
|
|
113
133
|
style={monthButtonStyle}
|
|
114
134
|
testID={`pick-month-${month}`}
|
|
115
135
|
left={
|
|
116
|
-
|
|
136
|
+
isSelected ? (
|
|
117
137
|
<View style={styles.checkIconView}>
|
|
118
138
|
<Icon name="check" size={24} />
|
|
119
139
|
</View>
|
|
@@ -123,10 +143,10 @@ function MonthPure({
|
|
|
123
143
|
}>
|
|
124
144
|
<View style={datePickerMonthItemStyles.monthInner}>
|
|
125
145
|
<Text style={datePickerMonthItemStyles.monthLabel} selectable={false}>
|
|
126
|
-
{
|
|
146
|
+
{monthLabel}
|
|
127
147
|
</Text>
|
|
128
148
|
</View>
|
|
129
|
-
</
|
|
149
|
+
</List.Item>
|
|
130
150
|
);
|
|
131
151
|
}
|
|
132
152
|
const Month = memo(MonthPure);
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
} from 'react-native';
|
|
10
10
|
|
|
11
11
|
import AutoSizer from './AutoSizer';
|
|
12
|
-
import { useDatePickerStore } from './DatePickerContext';
|
|
13
12
|
import { beginOffset, estimatedMonthHeight, getInitialIndex, totalMonths } from './dateUtils';
|
|
14
13
|
import { addMonths, getRealIndex } from './dateUtils';
|
|
15
14
|
import {
|
|
@@ -18,6 +17,7 @@ import {
|
|
|
18
17
|
getMonthHeight,
|
|
19
18
|
getVerticalMonthsOffset,
|
|
20
19
|
} from './Month';
|
|
20
|
+
import { useDatePickerInlineStore } from './store';
|
|
21
21
|
import type { SwiperProps } from './SwiperUtils';
|
|
22
22
|
import { montHeaderHeight } from './utils';
|
|
23
23
|
|
|
@@ -56,7 +56,7 @@ function SwiperInner({
|
|
|
56
56
|
);
|
|
57
57
|
|
|
58
58
|
const parentRef = useRef<ScrollView | null>(null);
|
|
59
|
-
const [{ localDate }, setStore] =
|
|
59
|
+
const [{ localDate }, setStore] = useDatePickerInlineStore(state => state);
|
|
60
60
|
|
|
61
61
|
const scrollTo = useCallback(
|
|
62
62
|
(index: number, animated: boolean) => {
|
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
|
|
13
13
|
import { useLatest } from '../../hooks';
|
|
14
14
|
import AutoSizer from './AutoSizer';
|
|
15
|
-
import { useDatePickerStore } from './DatePickerContext';
|
|
16
15
|
import { beginOffset, estimatedMonthHeight, getInitialIndex, totalMonths } from './dateUtils';
|
|
17
16
|
import { addMonths, getRealIndex } from './dateUtils';
|
|
18
17
|
import { getIndexFromVerticalOffset, getMonthHeight, getVerticalMonthsOffset } from './Month';
|
|
18
|
+
import { useDatePickerInlineStore } from './store';
|
|
19
19
|
import type { SwiperProps } from './SwiperUtils';
|
|
20
20
|
import { montHeaderHeight } from './utils';
|
|
21
21
|
|
|
@@ -73,7 +73,7 @@ function HorizontalScroller({
|
|
|
73
73
|
visibleHorizontalArray(initialIndex),
|
|
74
74
|
);
|
|
75
75
|
const parentRef = useRef<HTMLDivElement | null>(null);
|
|
76
|
-
const [{ localDate }, setStore] =
|
|
76
|
+
const [{ localDate }, setStore] = useDatePickerInlineStore(state => state);
|
|
77
77
|
const settleTimerRef = useRef<number | null>(null);
|
|
78
78
|
const isRecenteringRef = useRef(false);
|
|
79
79
|
|
|
@@ -209,7 +209,7 @@ function VerticalScroller({
|
|
|
209
209
|
const [visibleIndexes, setVisibleIndexes] = useState<number[]>(visibleArray(initialIndex));
|
|
210
210
|
|
|
211
211
|
const parentRef = useRef<HTMLDivElement | null>(null);
|
|
212
|
-
const [{ localDate }, setStore] =
|
|
212
|
+
const [{ localDate }, setStore] = useDatePickerInlineStore(state => state);
|
|
213
213
|
|
|
214
214
|
useIsomorphicLayoutEffect(() => {
|
|
215
215
|
const element = parentRef.current;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { setYear } from 'date-fns';
|
|
2
2
|
import { memo, useCallback, useLayoutEffect, useMemo, useRef } from 'react';
|
|
3
|
-
import { FlatList,
|
|
3
|
+
import { FlatList, type FlatListProps, StyleSheet, View } from 'react-native';
|
|
4
4
|
|
|
5
5
|
import { getYearRange, resolveStateVariant } from '../../utils';
|
|
6
6
|
import { datePickerMonthItemStyles, datePickerMonthPickerStyles } from '../DatePicker/utils';
|
|
7
|
-
import {
|
|
7
|
+
import { Divider } from '../Divider';
|
|
8
8
|
import { Icon } from '../Icon';
|
|
9
|
-
import {
|
|
9
|
+
import { List, type ListContentProcessPropsArgs, useListContextValue } from '../List';
|
|
10
10
|
import { Text } from '../Text';
|
|
11
|
-
import {
|
|
11
|
+
import { useDatePickerInlineStore } from './store';
|
|
12
12
|
import { datePickerYearItemStyles, datePickerYearPickerStyles } from './utils';
|
|
13
13
|
|
|
14
|
+
type YearListItem = { id: number; label: string };
|
|
15
|
+
|
|
14
16
|
const GRID_ITEM_HEIGHT = 62;
|
|
15
17
|
const NUM_COLUMNS = 3;
|
|
16
18
|
const LIST_ITEM_HEIGHT = 46;
|
|
@@ -25,23 +27,19 @@ export default function YearPicker({ layout = 'grid' }: YearPickerProps) {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
function YearPickerGrid() {
|
|
28
|
-
const [{ startDateYear, endDateYear, localDate, pickerType }, setStore] =
|
|
29
|
-
state => state
|
|
30
|
-
);
|
|
30
|
+
const [{ startDateYear, endDateYear, localDate, pickerType }, setStore] =
|
|
31
|
+
useDatePickerInlineStore(state => state);
|
|
31
32
|
const years = useMemo(
|
|
32
33
|
() => getYearRange(startDateYear, endDateYear),
|
|
33
34
|
[startDateYear, endDateYear],
|
|
34
35
|
);
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
return chunks;
|
|
41
|
-
}, [years]);
|
|
36
|
+
const yearItems = useMemo(
|
|
37
|
+
() => years.map(year => ({ id: year, label: String(year) })),
|
|
38
|
+
[years],
|
|
39
|
+
);
|
|
42
40
|
const selectingYear = pickerType === 'year';
|
|
43
41
|
const selectedYear = localDate.getFullYear();
|
|
44
|
-
const
|
|
42
|
+
const flatListRef = useRef<FlatList<YearListItem> | null>(null);
|
|
45
43
|
|
|
46
44
|
const initialScrollOffset = useMemo(() => {
|
|
47
45
|
if (years.length === 0) return 0;
|
|
@@ -53,7 +51,7 @@ function YearPickerGrid() {
|
|
|
53
51
|
|
|
54
52
|
useLayoutEffect(() => {
|
|
55
53
|
if (!selectingYear) return;
|
|
56
|
-
|
|
54
|
+
flatListRef.current?.scrollToOffset({ offset: initialScrollOffset, animated: false });
|
|
57
55
|
}, [selectingYear, initialScrollOffset]);
|
|
58
56
|
|
|
59
57
|
const { containerStyle, yearStyle } = useMemo(() => {
|
|
@@ -71,7 +69,8 @@ function YearPickerGrid() {
|
|
|
71
69
|
}, [selectingYear]);
|
|
72
70
|
|
|
73
71
|
const handleOnChange = useCallback(
|
|
74
|
-
(year: number) => {
|
|
72
|
+
(year: number | null) => {
|
|
73
|
+
if (year === null) return;
|
|
75
74
|
setStore(prev => ({
|
|
76
75
|
localDate: setYear(prev.localDate, year),
|
|
77
76
|
pickerType: undefined,
|
|
@@ -80,83 +79,103 @@ function YearPickerGrid() {
|
|
|
80
79
|
[setStore],
|
|
81
80
|
);
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
82
|
+
const getRowLayout = useCallback(
|
|
83
|
+
(_data: ArrayLike<YearListItem> | null | undefined, index: number) => ({
|
|
84
|
+
length: GRID_ITEM_HEIGHT,
|
|
85
|
+
offset: GRID_ITEM_HEIGHT * index,
|
|
86
|
+
index,
|
|
87
|
+
}),
|
|
88
|
+
[],
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const processGridFlatListProps = useCallback(
|
|
92
|
+
({
|
|
93
|
+
props,
|
|
94
|
+
items,
|
|
95
|
+
isEmpty,
|
|
96
|
+
emptyState,
|
|
97
|
+
}: ListContentProcessPropsArgs<
|
|
98
|
+
YearListItem,
|
|
99
|
+
Omit<FlatListProps<YearListItem>, 'children' | 'ref'>
|
|
100
|
+
>): FlatListProps<YearListItem> => ({
|
|
101
|
+
...props,
|
|
102
|
+
data: items,
|
|
103
|
+
numColumns: NUM_COLUMNS,
|
|
104
|
+
contentContainerStyle: gridStyles.grid,
|
|
105
|
+
columnWrapperStyle: gridStyles.row,
|
|
106
|
+
renderItem: ({ item }) => (
|
|
107
|
+
<View style={gridStyles.cell}>
|
|
108
|
+
<YearPill year={item.id} yearStyles={yearStyle} />
|
|
110
109
|
</View>
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
),
|
|
111
|
+
keyExtractor: item => `${item.id}`,
|
|
112
|
+
getItemLayout: getRowLayout,
|
|
113
|
+
initialScrollIndex: Math.floor(initialScrollOffset / GRID_ITEM_HEIGHT),
|
|
114
|
+
removeClippedSubviews: true,
|
|
115
|
+
ListEmptyComponent: isEmpty
|
|
116
|
+
? function GridListEmpty() {
|
|
117
|
+
return <>{emptyState}</>;
|
|
118
|
+
}
|
|
119
|
+
: undefined,
|
|
120
|
+
}),
|
|
121
|
+
[getRowLayout, initialScrollOffset, yearStyle],
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<List items={yearItems} multiple={false} value={selectedYear} onChange={handleOnChange}>
|
|
126
|
+
<View style={containerStyle} pointerEvents={selectingYear ? 'auto' : 'none'}>
|
|
127
|
+
<Divider />
|
|
128
|
+
<List.Content<YearListItem, typeof FlatList<YearListItem>>
|
|
129
|
+
ref={flatListRef}
|
|
130
|
+
ContainerComponent={FlatList<YearListItem>}
|
|
131
|
+
style={gridStyles.list}
|
|
132
|
+
processProps={processGridFlatListProps}
|
|
133
|
+
/>
|
|
134
|
+
</View>
|
|
135
|
+
</List>
|
|
113
136
|
);
|
|
114
137
|
}
|
|
115
138
|
|
|
116
|
-
function YearPillPure({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
yearStyles,
|
|
121
|
-
}: {
|
|
122
|
-
year: number;
|
|
123
|
-
selected: boolean;
|
|
124
|
-
onPressYear: (newYear: number) => any;
|
|
125
|
-
yearStyles: Record<string, any>;
|
|
126
|
-
}) {
|
|
127
|
-
datePickerYearItemStyles.useVariants({
|
|
128
|
-
state: resolveStateVariant({ selected }) as any,
|
|
139
|
+
function YearPillPure({ year, yearStyles }: { year: number; yearStyles: Record<string, any> }) {
|
|
140
|
+
const isSelected = useListContextValue(state => {
|
|
141
|
+
const selectedValue = state.value as any;
|
|
142
|
+
return (selectedValue?.id ?? selectedValue) === year;
|
|
129
143
|
});
|
|
130
144
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
145
|
+
datePickerYearItemStyles.useVariants({
|
|
146
|
+
state: resolveStateVariant({ selected: isSelected }) as any,
|
|
147
|
+
});
|
|
134
148
|
|
|
135
149
|
return (
|
|
136
|
-
<
|
|
150
|
+
<List.Item
|
|
151
|
+
value={year}
|
|
137
152
|
contentStyle={datePickerYearItemStyles.content}
|
|
138
|
-
onPress={handlePressYear}
|
|
139
153
|
accessibilityRole="button"
|
|
140
154
|
accessibilityLabel={String(year)}
|
|
141
155
|
style={[yearStyles, datePickerYearItemStyles.yearButton]}
|
|
142
156
|
testID={`pick-year-${year}`}>
|
|
143
|
-
<
|
|
157
|
+
<Text
|
|
158
|
+
typescale="bodyLarge"
|
|
159
|
+
style={datePickerYearItemStyles.yearLabel}
|
|
160
|
+
selectable={false}>
|
|
144
161
|
{year}
|
|
145
|
-
</
|
|
146
|
-
</
|
|
162
|
+
</Text>
|
|
163
|
+
</List.Item>
|
|
147
164
|
);
|
|
148
165
|
}
|
|
149
166
|
const YearPill = memo(YearPillPure);
|
|
150
167
|
|
|
151
168
|
function YearPickerList() {
|
|
152
|
-
const [{ startDateYear, endDateYear, localDate, pickerType }, setStore] =
|
|
153
|
-
state => state
|
|
154
|
-
);
|
|
155
|
-
const flatList = useRef<FlatList<number> | null>(null);
|
|
169
|
+
const [{ startDateYear, endDateYear, localDate, pickerType }, setStore] =
|
|
170
|
+
useDatePickerInlineStore(state => state);
|
|
156
171
|
const years = useMemo(
|
|
157
172
|
() => getYearRange(startDateYear, endDateYear),
|
|
158
173
|
[startDateYear, endDateYear],
|
|
159
174
|
);
|
|
175
|
+
const yearItems = useMemo<YearListItem[]>(
|
|
176
|
+
() => years.map(year => ({ id: year, label: String(year) })),
|
|
177
|
+
[years],
|
|
178
|
+
);
|
|
160
179
|
const selectingYear = pickerType === 'year';
|
|
161
180
|
const selectedYear = localDate.getFullYear();
|
|
162
181
|
|
|
@@ -167,7 +186,8 @@ function YearPickerList() {
|
|
|
167
186
|
}, [selectedYear, years]);
|
|
168
187
|
|
|
169
188
|
const handleOnChange = useCallback(
|
|
170
|
-
(year: number) => {
|
|
189
|
+
(year: number | null) => {
|
|
190
|
+
if (year === null) return;
|
|
171
191
|
setStore(prev => ({
|
|
172
192
|
localDate: setYear(prev.localDate, year),
|
|
173
193
|
pickerType: undefined,
|
|
@@ -176,15 +196,8 @@ function YearPickerList() {
|
|
|
176
196
|
[setStore],
|
|
177
197
|
);
|
|
178
198
|
|
|
179
|
-
const renderItem = useCallback(
|
|
180
|
-
({ item }: { item: number }) => (
|
|
181
|
-
<YearRow year={item} selected={selectedYear === item} onPressYear={handleOnChange} />
|
|
182
|
-
),
|
|
183
|
-
[selectedYear, handleOnChange],
|
|
184
|
-
);
|
|
185
|
-
|
|
186
199
|
const getItemLayout = useCallback(
|
|
187
|
-
(_data:
|
|
200
|
+
(_data: ArrayLike<YearListItem> | null | undefined, index: number) => ({
|
|
188
201
|
length: LIST_ITEM_HEIGHT,
|
|
189
202
|
offset: LIST_ITEM_HEIGHT * index,
|
|
190
203
|
index,
|
|
@@ -192,51 +205,59 @@ function YearPickerList() {
|
|
|
192
205
|
[],
|
|
193
206
|
);
|
|
194
207
|
|
|
208
|
+
const processFlatListProps = useCallback(
|
|
209
|
+
({
|
|
210
|
+
props,
|
|
211
|
+
items,
|
|
212
|
+
}: ListContentProcessPropsArgs<
|
|
213
|
+
YearListItem,
|
|
214
|
+
Omit<FlatListProps<YearListItem>, 'children' | 'ref'>
|
|
215
|
+
>): FlatListProps<YearListItem> => ({
|
|
216
|
+
...props,
|
|
217
|
+
data: items,
|
|
218
|
+
renderItem: ({ item }) => <YearRow year={item.id} />,
|
|
219
|
+
keyExtractor: item => `${item.id}`,
|
|
220
|
+
initialScrollIndex,
|
|
221
|
+
getItemLayout,
|
|
222
|
+
}),
|
|
223
|
+
[getItemLayout, initialScrollIndex],
|
|
224
|
+
);
|
|
225
|
+
|
|
195
226
|
if (!selectingYear) return null;
|
|
196
227
|
|
|
197
228
|
return (
|
|
198
|
-
<
|
|
199
|
-
<
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
/>
|
|
209
|
-
</View>
|
|
229
|
+
<List items={yearItems} multiple={false} value={selectedYear} onChange={handleOnChange}>
|
|
230
|
+
<View style={[StyleSheet.absoluteFill, listStyles.root]} pointerEvents="auto">
|
|
231
|
+
<Divider />
|
|
232
|
+
<List.Content<YearListItem, typeof FlatList<YearListItem>>
|
|
233
|
+
ContainerComponent={FlatList<YearListItem>}
|
|
234
|
+
style={listStyles.list}
|
|
235
|
+
processProps={processFlatListProps}
|
|
236
|
+
/>
|
|
237
|
+
</View>
|
|
238
|
+
</List>
|
|
210
239
|
);
|
|
211
240
|
}
|
|
212
241
|
|
|
213
|
-
function YearRowPure({
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}: {
|
|
218
|
-
year: number;
|
|
219
|
-
selected: boolean;
|
|
220
|
-
onPressYear: (newYear: number) => any;
|
|
221
|
-
}) {
|
|
222
|
-
datePickerMonthItemStyles.useVariants({
|
|
223
|
-
state: resolveStateVariant({ selected }) as any,
|
|
242
|
+
function YearRowPure({ year }: { year: number }) {
|
|
243
|
+
const isSelected = useListContextValue(state => {
|
|
244
|
+
const selectedValue = state.value as any;
|
|
245
|
+
return (selectedValue?.id ?? selectedValue) === year;
|
|
224
246
|
});
|
|
225
247
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
248
|
+
datePickerMonthItemStyles.useVariants({
|
|
249
|
+
state: resolveStateVariant({ selected: isSelected }) as any,
|
|
250
|
+
});
|
|
229
251
|
|
|
230
252
|
return (
|
|
231
|
-
<
|
|
232
|
-
|
|
253
|
+
<List.Item
|
|
254
|
+
value={year}
|
|
233
255
|
accessibilityRole="button"
|
|
234
256
|
accessibilityLabel={String(year)}
|
|
235
|
-
accessibilityState={{ selected }}
|
|
236
257
|
style={datePickerMonthItemStyles.monthButton}
|
|
237
258
|
testID={`pick-year-${year}`}
|
|
238
259
|
left={
|
|
239
|
-
|
|
260
|
+
isSelected ? (
|
|
240
261
|
<View style={listStyles.checkIconView}>
|
|
241
262
|
<Icon name="check" size={24} />
|
|
242
263
|
</View>
|
|
@@ -249,7 +270,7 @@ function YearRowPure({
|
|
|
249
270
|
{year}
|
|
250
271
|
</Text>
|
|
251
272
|
</View>
|
|
252
|
-
</
|
|
273
|
+
</List.Item>
|
|
253
274
|
);
|
|
254
275
|
}
|
|
255
276
|
const YearRow = memo(YearRowPure);
|
|
@@ -260,7 +281,10 @@ const gridStyles = StyleSheet.create({
|
|
|
260
281
|
top: 56,
|
|
261
282
|
zIndex: 100,
|
|
262
283
|
},
|
|
263
|
-
list: {
|
|
284
|
+
list: {
|
|
285
|
+
flex: 1,
|
|
286
|
+
width: '100%',
|
|
287
|
+
},
|
|
264
288
|
grid: { alignItems: 'center' },
|
|
265
289
|
row: {
|
|
266
290
|
flexDirection: 'row',
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createFastContext } from '../../fast-context';
|
|
2
|
+
import { registerPortalContext } from '../Portal/Portal';
|
|
2
3
|
|
|
3
4
|
export type Store = {
|
|
4
5
|
localDate: Date;
|
|
@@ -16,7 +17,10 @@ export const defaultValue = {
|
|
|
16
17
|
|
|
17
18
|
export const {
|
|
18
19
|
Provider,
|
|
19
|
-
useContext:
|
|
20
|
-
useContextValue:
|
|
21
|
-
useStoreRef:
|
|
20
|
+
useContext: useDatePickerInlineStore,
|
|
21
|
+
useContextValue: useDatePickerInlineStoreValue,
|
|
22
|
+
useStoreRef: useDatePickerInlineStoreRef,
|
|
23
|
+
Context: DatePickerInlineStoreContext,
|
|
22
24
|
} = createFastContext<Store>();
|
|
25
|
+
|
|
26
|
+
registerPortalContext(DatePickerInlineStoreContext);
|