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.
Files changed (227) hide show
  1. package/components/Accordion/Accordion.tsx +2 -6
  2. package/components/Accordion/AccordionItem.tsx +16 -12
  3. package/components/Accordion/AccordionItemContent.tsx +6 -1
  4. package/components/Accordion/AccordionItemHeader.tsx +1 -1
  5. package/components/Accordion/utils.ts +6 -0
  6. package/components/ActivityIndicator/ActivityIndicator.tsx +6 -15
  7. package/components/Appbar/AppbarBase.tsx +18 -13
  8. package/components/Button/Button.tsx +211 -264
  9. package/components/Button/index.tsx +9 -3
  10. package/components/Button/types.ts +16 -2
  11. package/components/Button/utils.ts +230 -208
  12. package/components/Card/Card.tsx +1 -1
  13. package/components/Checkbox/Checkbox.tsx +125 -88
  14. package/components/Checkbox/CheckboxBase.ios.tsx +14 -23
  15. package/components/Checkbox/CheckboxBase.tsx +21 -137
  16. package/components/Checkbox/context.tsx +14 -0
  17. package/components/Checkbox/index.tsx +11 -4
  18. package/components/Checkbox/types.ts +63 -29
  19. package/components/Checkbox/utils.ts +25 -108
  20. package/components/Chip/Chip.tsx +41 -52
  21. package/components/Chip/utils.ts +3 -7
  22. package/components/DateField/DateField.tsx +111 -0
  23. package/components/DateField/index.tsx +6 -0
  24. package/components/{DatePickerInput/inputUtils.ts → DateField/useDateFieldState.ts} +19 -51
  25. package/components/DatePicker/DateCalendar.tsx +83 -0
  26. package/components/DatePicker/DatePickerActions.tsx +73 -0
  27. package/components/DatePicker/DatePickerModal.tsx +246 -0
  28. package/components/DatePicker/DatePickerPopover.tsx +79 -0
  29. package/components/DatePicker/DatePickerProvider.tsx +158 -0
  30. package/components/DatePicker/DatePickerTrigger.tsx +23 -0
  31. package/components/DatePicker/context.tsx +83 -0
  32. package/components/DatePicker/index.tsx +45 -0
  33. package/components/DatePicker/utils.ts +295 -0
  34. package/components/DatePickerInline/DatePickerDockedHeader.tsx +117 -0
  35. package/components/DatePickerInline/DatePickerInline.tsx +17 -16
  36. package/components/DatePickerInline/DatePickerInlineBase.tsx +11 -5
  37. package/components/DatePickerInline/DatePickerInlineHeader.tsx +50 -20
  38. package/components/DatePickerInline/Day.tsx +25 -1
  39. package/components/DatePickerInline/DayNames.tsx +13 -10
  40. package/components/DatePickerInline/DayRange.tsx +2 -4
  41. package/components/DatePickerInline/HeaderItem.tsx +44 -29
  42. package/components/DatePickerInline/Month.tsx +48 -67
  43. package/components/DatePickerInline/MonthPicker.tsx +80 -92
  44. package/components/DatePickerInline/Swiper.native.tsx +21 -4
  45. package/components/DatePickerInline/Swiper.tsx +169 -14
  46. package/components/DatePickerInline/SwiperUtils.ts +1 -1
  47. package/components/DatePickerInline/Week.tsx +6 -1
  48. package/components/DatePickerInline/YearPicker.tsx +220 -78
  49. package/components/DatePickerInline/dateUtils.tsx +18 -13
  50. package/components/DatePickerInline/store.tsx +27 -0
  51. package/components/DatePickerInline/types.ts +6 -2
  52. package/components/DatePickerInline/utils.ts +66 -29
  53. package/components/Divider/Divider.tsx +192 -0
  54. package/components/Divider/index.tsx +10 -0
  55. package/components/Drawer/Drawer.tsx +17 -6
  56. package/components/Drawer/DrawerItemGroup.tsx +3 -7
  57. package/components/ElementGroup/ElementGroup.tsx +1 -1
  58. package/components/FilePicker/FilePicker.tsx +48 -78
  59. package/components/FilePicker/index.tsx +2 -1
  60. package/components/FilePicker/utils.ts +9 -0
  61. package/components/HelperText/HelperText.tsx +0 -35
  62. package/components/Icon/iconFactory.tsx +5 -4
  63. package/components/Icon/index.tsx +1 -1
  64. package/components/Icon/types.ts +17 -6
  65. package/components/IconButton/IconButton.tsx +84 -84
  66. package/components/IconButton/index.tsx +1 -0
  67. package/components/IconButton/types.ts +10 -0
  68. package/components/IconButton/utils.ts +167 -33
  69. package/components/List/List.tsx +276 -0
  70. package/components/List/context.tsx +27 -0
  71. package/components/List/index.ts +8 -0
  72. package/components/List/types.ts +117 -0
  73. package/components/List/utils.ts +79 -0
  74. package/components/LoadingIndicator/LoadingIndicator.tsx +253 -0
  75. package/components/LoadingIndicator/LoadingIndicator.web.tsx +136 -0
  76. package/components/LoadingIndicator/index.tsx +13 -0
  77. package/components/LoadingIndicator/utils.ts +117 -0
  78. package/components/Menu/Menu.tsx +162 -39
  79. package/components/Menu/index.tsx +10 -7
  80. package/components/Menu/utils.ts +21 -70
  81. package/components/NavigationRail/NavigationRail.tsx +15 -9
  82. package/components/Popover/Popover.tsx +119 -145
  83. package/components/Popover/PopoverRoot.tsx +60 -0
  84. package/components/Popover/common.ts +54 -34
  85. package/components/Popover/index.ts +12 -1
  86. package/components/Popover/usePlatformMeasure.native.ts +90 -0
  87. package/components/Popover/usePlatformMeasure.ts +120 -0
  88. package/components/Popover/utils.ts +34 -0
  89. package/components/Portal/Portal.tsx +1 -2
  90. package/components/Radio/Radio.tsx +188 -0
  91. package/components/Radio/RadioBase.ios.tsx +69 -0
  92. package/components/Radio/RadioBase.tsx +136 -0
  93. package/components/Radio/context.tsx +23 -0
  94. package/components/Radio/index.tsx +20 -0
  95. package/components/Radio/types.ts +101 -0
  96. package/components/Radio/utils.ts +115 -0
  97. package/components/Rating/Rating.tsx +1 -1
  98. package/components/Select/Select.tsx +521 -785
  99. package/components/Select/context.tsx +81 -0
  100. package/components/Select/index.ts +26 -14
  101. package/components/Select/types.ts +65 -58
  102. package/components/Select/utils.ts +126 -0
  103. package/components/Slot/Slot.tsx +244 -0
  104. package/components/Slot/compose-refs.tsx +62 -0
  105. package/components/Slot/index.tsx +8 -0
  106. package/components/Surface/Surface.android.tsx +32 -7
  107. package/components/Surface/Surface.ios.tsx +34 -29
  108. package/components/Surface/Surface.tsx +31 -4
  109. package/components/Surface/utils.ts +44 -6
  110. package/components/Switch/Switch.ios.tsx +1 -1
  111. package/components/Switch/Switch.tsx +10 -3
  112. package/components/Tabs/TabItem.tsx +35 -58
  113. package/components/Tabs/TabLabel.tsx +5 -9
  114. package/components/Tabs/Tabs.tsx +156 -150
  115. package/components/Tabs/utils.ts +15 -2
  116. package/components/Text/textFactory.tsx +17 -5
  117. package/components/TextInput/TextInput.tsx +663 -579
  118. package/components/TextInput/index.tsx +19 -3
  119. package/components/TextInput/types.ts +77 -28
  120. package/components/TextInput/utils.ts +235 -145
  121. package/components/TimeField/TimeField.tsx +75 -0
  122. package/components/TimeField/index.tsx +6 -0
  123. package/components/TimeField/useTimeFieldState.ts +70 -0
  124. package/components/{TimePickerField/sanitizeTime.ts → TimeField/utils.ts} +77 -10
  125. package/components/TimePicker/AnalogClock.tsx +1 -1
  126. package/components/TimePicker/TimeInput.tsx +87 -42
  127. package/components/TimePicker/TimeInputs.tsx +138 -50
  128. package/components/TimePicker/TimePicker.tsx +74 -11
  129. package/components/TimePicker/TimePickerModal.tsx +186 -0
  130. package/components/TimePicker/context.tsx +17 -0
  131. package/components/TimePicker/index.tsx +15 -3
  132. package/components/TimePicker/utils.ts +93 -4
  133. package/components/Tooltip/Tooltip.tsx +42 -67
  134. package/components/Tooltip/TooltipContent.tsx +32 -5
  135. package/components/Tooltip/TooltipTrigger.tsx +20 -20
  136. package/components/Tooltip/index.tsx +1 -1
  137. package/components/TouchableRipple/TouchableRipple.native.tsx +83 -16
  138. package/components/TouchableRipple/TouchableRipple.tsx +150 -102
  139. package/components/TouchableRipple/rippleFromForegroundColor.ts +21 -0
  140. package/hocs/index.tsx +1 -1
  141. package/hocs/withKeyboardAccessibility.tsx +2 -3
  142. package/hocs/withPortal.tsx +1 -1
  143. package/hooks/index.tsx +2 -12
  144. package/hooks/useActionState.tsx +19 -8
  145. package/hooks/useContrastColor.ts +1 -2
  146. package/hooks/useFilePicker.tsx +7 -17
  147. package/hooks/useHandleNumberFormat.tsx +2 -2
  148. package/hooks/useMediaQuery.tsx +1 -2
  149. package/package.json +95 -111
  150. package/shortcuts-manager/ShortcutsManager/ShortcutsManager.tsx +6 -3
  151. package/shortcuts-manager/ShortcutsManager/utils.tsx +1 -1
  152. package/shortcuts-manager/useSetScopes/useSetScopes.tsx +1 -1
  153. package/shortcuts-manager/useShortcut/useShortcut.tsx +1 -1
  154. package/styles/shadow.ts +2 -1
  155. package/styles/themes/LightTheme.tsx +1 -1
  156. package/utils/DocumentPicker/documentPicker.ts +78 -27
  157. package/utils/DocumentPicker/types.ts +0 -1
  158. package/utils/extractSubcomponents.ts +89 -0
  159. package/utils/extractTextStyles.ts +1 -2
  160. package/utils/formatNumberWithMask/formatNumberWithMask.ts +2 -1
  161. package/utils/index.ts +0 -3
  162. package/utils/normalizeToNumberString/normalizeToNumberString.ts +1 -1
  163. package/components/DatePickerDocked/DatePickerDocked.tsx +0 -30
  164. package/components/DatePickerDocked/DatePickerDockedHeader.tsx +0 -129
  165. package/components/DatePickerDocked/index.tsx +0 -17
  166. package/components/DatePickerDocked/types.ts +0 -11
  167. package/components/DatePickerDocked/utils.ts +0 -157
  168. package/components/DatePickerInline/DatePickerContext.tsx +0 -21
  169. package/components/DatePickerInput/DatePickerInput.tsx +0 -139
  170. package/components/DatePickerInput/DatePickerInputModal.tsx +0 -48
  171. package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +0 -77
  172. package/components/DatePickerInput/DateRangeInput.tsx +0 -88
  173. package/components/DatePickerInput/index.tsx +0 -10
  174. package/components/DatePickerInput/types.ts +0 -28
  175. package/components/DatePickerInput/utils.ts +0 -15
  176. package/components/DatePickerModal/AnimatedCrossView.tsx +0 -94
  177. package/components/DatePickerModal/CalendarEdit.tsx +0 -139
  178. package/components/DatePickerModal/DatePickerModal.tsx +0 -85
  179. package/components/DatePickerModal/DatePickerModalContent.tsx +0 -155
  180. package/components/DatePickerModal/DatePickerModalContentHeader.tsx +0 -213
  181. package/components/DatePickerModal/DatePickerModalHeader.tsx +0 -74
  182. package/components/DatePickerModal/DatePickerModalHeaderBackground.tsx +0 -13
  183. package/components/DatePickerModal/index.tsx +0 -16
  184. package/components/DatePickerModal/types.ts +0 -92
  185. package/components/DatePickerModal/utils.ts +0 -122
  186. package/components/DateTimePicker/DateTimePicker.tsx +0 -172
  187. package/components/DateTimePicker/index.tsx +0 -10
  188. package/components/DateTimePicker/utils.ts +0 -12
  189. package/components/HorizontalDivider/HorizontalDivider.tsx +0 -103
  190. package/components/HorizontalDivider/index.tsx +0 -9
  191. package/components/ListItem/ListItem.tsx +0 -136
  192. package/components/ListItem/ListItemDescription.tsx +0 -25
  193. package/components/ListItem/ListItemTitle.tsx +0 -25
  194. package/components/ListItem/index.tsx +0 -14
  195. package/components/ListItem/utils.ts +0 -115
  196. package/components/Menu/MenuDivider.tsx +0 -13
  197. package/components/Menu/MenuItem.tsx +0 -128
  198. package/components/Popover/Popover.native.tsx +0 -185
  199. package/components/RadioButton/RadioButton.tsx +0 -138
  200. package/components/RadioButton/RadioButtonAndroid.tsx +0 -188
  201. package/components/RadioButton/RadioButtonGroup.tsx +0 -98
  202. package/components/RadioButton/RadioButtonIOS.tsx +0 -106
  203. package/components/RadioButton/RadioButtonItem.tsx +0 -232
  204. package/components/RadioButton/index.ts +0 -22
  205. package/components/RadioButton/utils.ts +0 -165
  206. package/components/TimePickerField/TimePickerField.tsx +0 -152
  207. package/components/TimePickerField/index.tsx +0 -10
  208. package/components/TimePickerField/utils.ts +0 -94
  209. package/components/TimePickerModal/TimePickerModal.tsx +0 -115
  210. package/components/TimePickerModal/index.tsx +0 -10
  211. package/components/TimePickerModal/utils.ts +0 -47
  212. package/components/VerticalDivider/VerticalDivider.tsx +0 -100
  213. package/components/VerticalDivider/index.tsx +0 -9
  214. package/context-bridge/index.tsx +0 -87
  215. package/fast-context/index.tsx +0 -190
  216. package/hocs/typedMemo.tsx +0 -5
  217. package/hooks/useControlledValue.tsx +0 -68
  218. package/hooks/useLatest.tsx +0 -9
  219. package/hooks/useMergedRefs.ts +0 -14
  220. package/hooks/usePrevious.ts +0 -13
  221. package/hooks/useSearchable.tsx +0 -74
  222. package/hooks/useSubcomponents.tsx +0 -59
  223. package/hooks/useToggle.tsx +0 -24
  224. package/utils/color.ts +0 -22
  225. package/utils/compare/index.ts +0 -54
  226. package/utils/lodash.ts +0 -49
  227. package/utils/repository.ts +0 -53
@@ -0,0 +1,117 @@
1
+ import { add, setYear } from 'date-fns';
2
+ import { memo, useCallback, useMemo } from 'react';
3
+ import { View, type ViewStyle } from 'react-native';
4
+ import { StyleSheet } from 'react-native-unistyles';
5
+
6
+ import type { DatePickerLocale } from '../DatePicker/context';
7
+ import type { DisableWeekDaysType } from './dateUtils';
8
+ import DayNames from './DayNames';
9
+ import HeaderItem from './HeaderItem';
10
+ import { useDatePickerInlineStoreRef, useDatePickerInlineStoreValue } from './store';
11
+ import { datePickerHeaderStyles } from './utils';
12
+
13
+ export type DockedHeaderProps = {
14
+ locale?: DatePickerLocale;
15
+ scrollMode: 'horizontal' | 'vertical';
16
+ disableWeekDays?: DisableWeekDaysType;
17
+ style?: ViewStyle;
18
+ };
19
+
20
+ function DatePickerDockedHeader({
21
+ locale = 'en',
22
+ scrollMode,
23
+ disableWeekDays,
24
+ style: styleProp,
25
+ }: DockedHeaderProps) {
26
+ const setStore = useDatePickerInlineStoreRef().set;
27
+ const { localDate, pickerType } = useDatePickerInlineStoreValue(state => ({
28
+ localDate: state.localDate,
29
+ pickerType: state.pickerType,
30
+ }));
31
+ const isHorizontal = scrollMode === 'horizontal';
32
+
33
+ const { monthName, year } = useMemo(
34
+ () => ({
35
+ monthName: new Intl.DateTimeFormat(locale, { month: 'short' }).format(localDate),
36
+ year: localDate.getFullYear(),
37
+ }),
38
+ [localDate, locale],
39
+ );
40
+
41
+ const handleMonthDropdown = useCallback(() => {
42
+ setStore(prev => ({ pickerType: prev.pickerType === 'month' ? undefined : 'month' }));
43
+ }, [setStore]);
44
+
45
+ const handleYearDropdown = useCallback(() => {
46
+ setStore(prev => ({ pickerType: prev.pickerType === 'year' ? undefined : 'year' }));
47
+ }, [setStore]);
48
+
49
+ const handleMonthPrev = useCallback(() => {
50
+ setStore(prev => ({ localDate: add(prev.localDate, { months: -1 }) }));
51
+ }, [setStore]);
52
+
53
+ const handleMonthNext = useCallback(() => {
54
+ setStore(prev => ({ localDate: add(prev.localDate, { months: 1 }) }));
55
+ }, [setStore]);
56
+
57
+ const handleYearPrev = useCallback(() => {
58
+ setStore(prev => ({
59
+ localDate: setYear(prev.localDate, prev.localDate.getFullYear() - 1),
60
+ }));
61
+ }, [setStore]);
62
+
63
+ const handleYearNext = useCallback(() => {
64
+ setStore(prev => ({
65
+ localDate: setYear(prev.localDate, prev.localDate.getFullYear() + 1),
66
+ }));
67
+ }, [setStore]);
68
+
69
+ const pickerOpen = pickerType === 'month' || pickerType === 'year';
70
+
71
+ return (
72
+ <View pointerEvents="box-none">
73
+ {isHorizontal && (
74
+ <View
75
+ style={[
76
+ datePickerHeaderStyles.datePickerHeader,
77
+ styles.row,
78
+ pickerOpen && styles.rowPickerOpen,
79
+ styleProp,
80
+ ]}>
81
+ <HeaderItem
82
+ onPrev={handleMonthPrev}
83
+ onNext={handleMonthNext}
84
+ onPressDropdown={handleMonthDropdown}
85
+ type="month"
86
+ value={monthName}
87
+ pickerType={pickerType}
88
+ selecting={pickerType === 'month'}
89
+ />
90
+ <HeaderItem
91
+ onPrev={handleYearPrev}
92
+ onNext={handleYearNext}
93
+ onPressDropdown={handleYearDropdown}
94
+ type="year"
95
+ value={year}
96
+ pickerType={pickerType}
97
+ selecting={pickerType === 'year'}
98
+ />
99
+ </View>
100
+ )}
101
+ <DayNames disableWeekDays={disableWeekDays} locale={locale} />
102
+ </View>
103
+ );
104
+ }
105
+
106
+ const styles = StyleSheet.create(theme => ({
107
+ row: {
108
+ flexDirection: 'row',
109
+ alignItems: 'center',
110
+ },
111
+ rowPickerOpen: {
112
+ borderBottomWidth: StyleSheet.hairlineWidth,
113
+ borderBottomColor: theme.colors.outlineVariant,
114
+ },
115
+ }));
116
+
117
+ export default memo(DatePickerDockedHeader);
@@ -1,18 +1,18 @@
1
- import { memo, useCallback, useMemo } from 'react';
1
+ import { useControlledValue } from '@react-native-molecules/utils/hooks';
2
+ import { memo, useCallback } from 'react';
2
3
  import { View, type ViewStyle } from 'react-native';
3
4
 
4
- import { useControlledValue } from '../../hooks';
5
- import type {
6
- LocalState,
7
- LocalStateMultiple,
8
- LocalStateRange,
9
- LocalStateSingle,
10
- } from '../DatePickerModal/types';
5
+ import DatePickerDockedHeader from './DatePickerDockedHeader';
11
6
  import DatePickerInlineBase from './DatePickerInlineBase';
12
7
  import DatePickerInlineHeader from './DatePickerInlineHeader';
13
- import type { DatePickerInlineBaseProps } from './types';
8
+ import type { CalendarDate, CalendarDates, DatePickerInlineBaseProps } from './types';
14
9
  import { datePickerStyles } from './utils';
15
10
 
11
+ type LocalState = LocalStateSingle | LocalStateMultiple | LocalStateRange;
12
+ type LocalStateSingle = { date: CalendarDate };
13
+ type LocalStateMultiple = { dates: CalendarDates };
14
+ type LocalStateRange = { startDate: CalendarDate; endDate: CalendarDate };
15
+
16
16
  export type DatePickerInlineProps = DatePickerInlineBaseProps & {
17
17
  containerStyle?: ViewStyle;
18
18
  };
@@ -25,6 +25,8 @@ const DatePickerInline = ({
25
25
  onChange,
26
26
  locale = 'en',
27
27
  mode = 'single',
28
+ headerLayout = 'default',
29
+ HeaderComponent,
28
30
  containerStyle: containerStyleProp,
29
31
  ...rest
30
32
  }: DatePickerInlineProps) => {
@@ -40,16 +42,15 @@ const DatePickerInline = ({
40
42
  onChange: onInnerChange,
41
43
  });
42
44
 
43
- const { containerStyle } = useMemo(() => {
44
- return {
45
- containerStyle: [datePickerStyles.container, datePickerStyles.root, containerStyleProp],
46
- };
47
- }, [containerStyleProp]);
45
+ const resolvedHeader =
46
+ HeaderComponent ??
47
+ (headerLayout === 'docked' ? DatePickerDockedHeader : DatePickerInlineHeader);
48
48
 
49
49
  return (
50
- <View style={containerStyle}>
50
+ <View style={[datePickerStyles.container, datePickerStyles.root, containerStyleProp]}>
51
51
  <DatePickerInlineBase
52
52
  {...rest}
53
+ headerLayout={headerLayout}
53
54
  locale={locale}
54
55
  mode={mode}
55
56
  startDate={(state as LocalStateRange)?.startDate}
@@ -59,7 +60,7 @@ const DatePickerInline = ({
59
60
  dates={(state as LocalStateMultiple)?.dates}
60
61
  // TODO - fix ts issues
61
62
  // @ts-ignore
62
- HeaderComponent={DatePickerInlineHeader}
63
+ HeaderComponent={resolvedHeader}
63
64
  />
64
65
  </View>
65
66
  );
@@ -1,11 +1,11 @@
1
+ import { useLatest } from '@react-native-molecules/utils/hooks';
1
2
  import { memo, useCallback, useEffect, useMemo } from 'react';
2
3
  import { StyleSheet, View } from 'react-native';
3
4
 
4
- import { useLatest } from '../../hooks';
5
- import { defaultValue, Provider, useDatePickerStore } from './DatePickerContext';
6
5
  import { areDatesOnSameDay, dateToUnix, getEndOfDay, getInitialIndex } from './dateUtils';
7
6
  import Month from './Month';
8
7
  import MonthPicker from './MonthPicker';
8
+ import { defaultValue, Provider, useDatePickerInlineStore } from './store';
9
9
  import Swiper from './Swiper';
10
10
  import type {
11
11
  CalendarDate,
@@ -43,8 +43,10 @@ function DatePickerInlineBaseChild(props: DatePickerInlineBaseProps) {
43
43
  HeaderComponent,
44
44
  onToggle,
45
45
  monthStyle,
46
+ showOutsideDays,
47
+ headerLayout,
46
48
  } = props;
47
- const [pickerType, setStore] = useDatePickerStore(state => state.pickerType);
49
+ const [pickerType, setStore] = useDatePickerInlineStore(state => state.pickerType);
48
50
 
49
51
  const scrollMode = mode === 'range' || mode === 'multiple' ? 'vertical' : 'horizontal';
50
52
  const isHorizontal = scrollMode === 'horizontal';
@@ -125,6 +127,7 @@ function DatePickerInlineBaseChild(props: DatePickerInlineBaseProps) {
125
127
  scrollMode={scrollMode}
126
128
  disableWeekDays={disableWeekDays}
127
129
  customMonthStyles={monthStyle}
130
+ showOutsideDays={showOutsideDays}
128
131
  />
129
132
  );
130
133
  },
@@ -140,6 +143,7 @@ function DatePickerInlineBaseChild(props: DatePickerInlineBaseProps) {
140
143
  scrollMode,
141
144
  disableWeekDays,
142
145
  monthStyle,
146
+ showOutsideDays,
143
147
  ],
144
148
  );
145
149
 
@@ -166,8 +170,10 @@ function DatePickerInlineBaseChild(props: DatePickerInlineBaseProps) {
166
170
  renderItem={renderMonthComponent}
167
171
  renderHeader={renderCalenderHeader}
168
172
  />
169
- {isHorizontal && pickerType === 'year' && <YearPicker />}
170
- {isHorizontal && pickerType === 'month' && <MonthPicker />}
173
+ {isHorizontal && pickerType === 'year' && (
174
+ <YearPicker layout={headerLayout === 'docked' ? 'list' : 'grid'} />
175
+ )}
176
+ {isHorizontal && pickerType === 'month' && <MonthPicker locale={locale} />}
171
177
  </View>
172
178
  );
173
179
  }
@@ -1,11 +1,12 @@
1
- import { add, format } from 'date-fns';
1
+ import { add, setYear } from 'date-fns';
2
2
  import { memo, useCallback, useMemo } from 'react';
3
3
  import { type StyleProp, View, type ViewStyle } from 'react-native';
4
4
 
5
- import { useDatePickerStore, useDatePickerStoreValue } from './DatePickerContext';
5
+ import type { DatePickerLocale } from '../DatePicker/context';
6
6
  import type { DisableWeekDaysType } from './dateUtils';
7
7
  import DayNames from './DayNames';
8
8
  import HeaderItem from './HeaderItem';
9
+ import { useDatePickerInlineStore, useDatePickerInlineStoreValue } from './store';
9
10
  import { datePickerHeaderStyles, dayNamesHeight } from './utils';
10
11
 
11
12
  const buttonContainerHeight = 56;
@@ -13,7 +14,7 @@ const buttonContainerMarginTop = 4;
13
14
  const buttonContainerMarginBottom = 8;
14
15
 
15
16
  export type CalendarHeaderProps = {
16
- locale?: string;
17
+ locale?: DatePickerLocale;
17
18
  scrollMode: 'horizontal' | 'vertical';
18
19
  disableWeekDays?: DisableWeekDaysType;
19
20
  style?: ViewStyle;
@@ -25,18 +26,21 @@ function DatePickerInlineHeader({
25
26
  disableWeekDays,
26
27
  style: styleProp,
27
28
  }: CalendarHeaderProps) {
28
- const [_, setStore] = useDatePickerStore(state => state);
29
- const { localDate, isYearPickerType } = useDatePickerStoreValue(state => ({
29
+ const [_, setStore] = useDatePickerInlineStore(state => state);
30
+ const { localDate, pickerType } = useDatePickerInlineStoreValue(state => ({
30
31
  localDate: state.localDate,
31
- isYearPickerType: state.pickerType === 'year',
32
+ pickerType: state.pickerType,
32
33
  }));
33
34
  const isHorizontal = scrollMode === 'horizontal';
34
35
 
35
36
  const { monthName, year } = useMemo(() => {
36
37
  const y = localDate.getFullYear();
37
38
 
38
- return { monthName: format(localDate, 'LLLL'), year: y };
39
- }, [localDate]);
39
+ return {
40
+ monthName: new Intl.DateTimeFormat(locale, { month: 'long' }).format(localDate),
41
+ year: y,
42
+ };
43
+ }, [localDate, locale]);
40
44
 
41
45
  const { containerStyle } = useMemo(() => {
42
46
  // const { datePickerHeader, buttonContainer, buttonWrapper, spacer, ...rest } =
@@ -54,36 +58,62 @@ function DatePickerInlineHeader({
54
58
  };
55
59
  }, [styleProp]);
56
60
 
61
+ const handleOnMonthPress = useCallback(() => {
62
+ isHorizontal &&
63
+ setStore(prev => ({
64
+ pickerType: prev.pickerType === 'month' ? undefined : 'month',
65
+ }));
66
+ }, [isHorizontal, setStore]);
67
+
57
68
  const handleOnYearPress = useCallback(() => {
58
- isHorizontal && setStore(prev => ({ pickerType: prev.pickerType ? undefined : 'year' }));
69
+ isHorizontal &&
70
+ setStore(prev => ({
71
+ pickerType: prev.pickerType === 'year' ? undefined : 'year',
72
+ }));
59
73
  }, [isHorizontal, setStore]);
60
74
 
61
- const handleOnPrev = useCallback(() => {
75
+ const handleMonthPrev = useCallback(() => {
62
76
  setStore(prev => ({ localDate: add(prev.localDate, { months: -1 }) }));
63
77
  }, [setStore]);
64
78
 
65
- const handleOnNext = useCallback(() => {
79
+ const handleMonthNext = useCallback(() => {
66
80
  setStore(prev => ({ localDate: add(prev.localDate, { months: 1 }) }));
67
81
  }, [setStore]);
68
82
 
83
+ const handleYearPrev = useCallback(() => {
84
+ setStore(prev => ({
85
+ localDate: setYear(prev.localDate, prev.localDate.getFullYear() - 1),
86
+ }));
87
+ }, [setStore]);
88
+
89
+ const handleYearNext = useCallback(() => {
90
+ setStore(prev => ({
91
+ localDate: setYear(prev.localDate, prev.localDate.getFullYear() + 1),
92
+ }));
93
+ }, [setStore]);
94
+
69
95
  return (
70
96
  <View pointerEvents={'box-none'}>
71
97
  <>
72
98
  {isHorizontal && (
73
99
  <View style={containerStyle}>
74
100
  <HeaderItem
75
- onPressDropdown={handleOnYearPress}
76
- type="year"
77
- value={`${monthName} ${year}`}
78
- pickerType="year"
79
- selecting={isYearPickerType}
101
+ onPrev={handleMonthPrev}
102
+ onNext={handleMonthNext}
103
+ onPressDropdown={handleOnMonthPress}
104
+ type="month"
105
+ value={monthName}
106
+ pickerType={pickerType}
107
+ selecting={pickerType === 'month'}
80
108
  />
81
109
  <HeaderItem
82
- onNext={handleOnNext}
83
- onPrev={handleOnPrev}
84
- selecting={false}
110
+ onNext={handleYearNext}
111
+ onPrev={handleYearPrev}
112
+ onPressDropdown={handleOnYearPress}
113
+ type="year"
114
+ selecting={pickerType === 'year'}
85
115
  value={year}
86
- pickerType="year"
116
+ pickerType={pickerType}
87
117
  />
88
118
  </View>
89
119
  )}
@@ -1,11 +1,17 @@
1
1
  import { memo, useCallback, useMemo } from 'react';
2
2
  import { type StyleProp, View, type ViewStyle } from 'react-native';
3
3
 
4
+ import { useActionState } from '../../hooks';
4
5
  import { resolveStateVariant } from '../../utils';
6
+ import { StateLayer } from '../StateLayer';
5
7
  import { Text } from '../Text';
6
8
  import { TouchableRipple } from '../TouchableRipple';
7
9
  import DayRange from './DayRange';
8
- import { datePickerDayEmptyStyles, datePickerDayStyles } from './utils';
10
+ import {
11
+ datePickerDayEmptyStyles,
12
+ datePickerDayStateLayerStyles,
13
+ datePickerDayStyles,
14
+ } from './utils';
9
15
 
10
16
  function EmptyDayPure() {
11
17
  return <View style={datePickerDayEmptyStyles.root} />;
@@ -23,6 +29,7 @@ function Day(props: {
23
29
  rightCrop: boolean;
24
30
  isToday: boolean;
25
31
  disabled: boolean;
32
+ outside?: boolean;
26
33
  onPressDate: (date: Date) => any;
27
34
  }) {
28
35
  const {
@@ -36,17 +43,32 @@ function Day(props: {
36
43
  onPressDate,
37
44
  isToday,
38
45
  disabled,
46
+ outside,
39
47
  } = props;
48
+
49
+ const { hovered, actionsRef } = useActionState({ actionsToListen: ['hover'] });
50
+
40
51
  const state = resolveStateVariant({
41
52
  disabled,
42
53
  selected,
43
54
  inRange,
44
55
  today: isToday,
56
+ outside: !!outside,
45
57
  });
46
58
  datePickerDayStyles.useVariants({
47
59
  state: state as any,
48
60
  });
49
61
 
62
+ datePickerDayStateLayerStyles.useVariants({
63
+ state: resolveStateVariant({
64
+ hovered: hovered,
65
+ outsideAndHovered: !!outside && !selected && !inRange && hovered,
66
+ selectedAndHovered: selected && hovered,
67
+ inRangeAndHovered: inRange && hovered,
68
+ todayAndHovered: isToday && hovered,
69
+ }) as any,
70
+ });
71
+
50
72
  const onPress = useCallback(() => {
51
73
  onPressDate(new Date(year, month, day));
52
74
  }, [onPressDate, year, month, day]);
@@ -69,6 +91,7 @@ function Day(props: {
69
91
  <DayRange inRange={inRange} leftCrop={leftCrop} rightCrop={rightCrop} />
70
92
 
71
93
  <TouchableRipple
94
+ ref={actionsRef}
72
95
  testID={`day-${year}-${month}-${day}`}
73
96
  disabled={disabled}
74
97
  borderless={true}
@@ -80,6 +103,7 @@ function Day(props: {
80
103
  {day}
81
104
  </Text>
82
105
  </View>
106
+ <StateLayer style={datePickerDayStateLayerStyles.stateLayer} />
83
107
  </TouchableRipple>
84
108
  </View>
85
109
  );
@@ -1,23 +1,26 @@
1
- import { memo } from 'react';
1
+ import { memo, useMemo } from 'react';
2
2
  import { View } from 'react-native';
3
3
 
4
- import { addDays, format, startOfWeek } from '../../utils/date-fns';
4
+ import { addDays, startOfWeek } from '../../utils/date-fns';
5
+ import type { DatePickerLocale } from '../DatePicker/context';
5
6
  import { type DisableWeekDaysType, showWeekDay } from './dateUtils';
6
7
  import DayName from './DayName';
7
8
  import { dateDayNameStyles } from './utils';
8
9
 
9
- const shortDayNames = (() => {
10
- const firstDOW = startOfWeek(new Date());
11
- return Array.from(Array(7)).map((_, i) => format(addDays(firstDOW, i), 'EEEEE'));
12
- })();
13
-
14
10
  function DayNames({
15
11
  disableWeekDays,
16
- }: // locale,
17
- {
12
+ locale,
13
+ }: {
18
14
  disableWeekDays?: DisableWeekDaysType;
19
- locale?: string;
15
+ locale?: DatePickerLocale;
20
16
  }) {
17
+ const shortDayNames = useMemo(() => {
18
+ const firstDOW = startOfWeek(new Date());
19
+ return Array.from(Array(7)).map((_, i) =>
20
+ new Intl.DateTimeFormat(locale, { weekday: 'narrow' }).format(addDays(firstDOW, i)),
21
+ );
22
+ }, [locale]);
23
+
21
24
  return (
22
25
  <View style={dateDayNameStyles.container} pointerEvents={'none'}>
23
26
  {shortDayNames
@@ -1,5 +1,5 @@
1
1
  import { memo } from 'react';
2
- import { StyleSheet, View } from 'react-native';
2
+ import { View } from 'react-native';
3
3
 
4
4
  import { resolveStateVariant } from '../../utils';
5
5
  import { datePickerDayRangeStyles } from './utils';
@@ -29,9 +29,7 @@ function DayRange({
29
29
  return (
30
30
  <>
31
31
  {(inRange || isCrop) && (
32
- <View
33
- pointerEvents="none"
34
- style={[StyleSheet.absoluteFill, datePickerDayRangeStyles.container]}>
32
+ <View pointerEvents="none" style={datePickerDayRangeStyles.container}>
35
33
  {isCrop && (
36
34
  <>
37
35
  <View style={datePickerDayRangeStyles.rightCrop} />
@@ -1,11 +1,12 @@
1
- import { memo, useCallback, useMemo } from 'react';
2
- import { type StyleProp, View, type ViewStyle } from 'react-native';
1
+ import { memo, useCallback } from 'react';
2
+ import { View } from 'react-native';
3
3
 
4
- import { datePickerHeaderItemStyles } from '../DatePickerDocked/utils';
4
+ import { datePickerHeaderItemStyles } from '../DatePicker/utils';
5
+ import { Icon } from '../Icon';
5
6
  import { IconButton } from '../IconButton';
6
7
  import { Text } from '../Text';
7
8
  import { TouchableRipple } from '../TouchableRipple';
8
- import { useDatePickerStoreValue } from './DatePickerContext';
9
+ import { useDatePickerInlineStoreValue } from './store';
9
10
 
10
11
  function HeaderItem({
11
12
  value,
@@ -24,7 +25,7 @@ function HeaderItem({
24
25
  onNext?: (type: 'month' | 'year' | undefined) => void;
25
26
  onPrev?: (type: 'month' | 'year' | undefined) => void;
26
27
  }) {
27
- const { startDateYear, endDateYear } = useDatePickerStoreValue(state => ({
28
+ const { startDateYear, endDateYear } = useDatePickerInlineStoreValue(state => ({
28
29
  startDateYear: state.startDateYear,
29
30
  endDateYear: state.endDateYear,
30
31
  }));
@@ -42,10 +43,11 @@ function HeaderItem({
42
43
  onNext && onNext(type);
43
44
  }, [onNext, type]);
44
45
 
45
- const containerStyle = useMemo(
46
- () =>
47
- [
46
+ return (
47
+ <View
48
+ style={[
48
49
  datePickerHeaderItemStyles.buttonContainer,
50
+ // eslint-disable-next-line react-native/no-inline-styles
49
51
  {
50
52
  justifyContent: !onPressDropdown
51
53
  ? 'flex-end'
@@ -53,22 +55,23 @@ function HeaderItem({
53
55
  ? 'flex-start'
54
56
  : 'center',
55
57
  },
56
- ] as StyleProp<ViewStyle>,
57
- [onPressDropdown, onNext],
58
- );
59
-
60
- return (
61
- <View style={containerStyle} pointerEvents={'box-none'}>
62
- {!selecting && onPrev && (
63
- <View style={datePickerHeaderItemStyles.buttonWrapper}>
58
+ ]}
59
+ pointerEvents={'box-none'}>
60
+ {onPrev && (
61
+ <View
62
+ style={[
63
+ datePickerHeaderItemStyles.buttonWrapper,
64
+ // eslint-disable-next-line react-native/no-inline-styles
65
+ (selecting || disabled) && { opacity: 0 },
66
+ ]}>
64
67
  <IconButton
65
68
  type="material-community"
66
69
  name="chevron-left"
67
- size="md"
70
+ size={24}
68
71
  // Todo: Translate
69
72
  accessibilityLabel={'Previous'}
70
73
  onPress={handleOnPrevious}
71
- disabled={value === startDateYear}
74
+ disabled={value === startDateYear || selecting || disabled}
72
75
  />
73
76
  </View>
74
77
  )}
@@ -80,27 +83,39 @@ function HeaderItem({
80
83
  accessibilityLabel={`${value}`}
81
84
  style={datePickerHeaderItemStyles.buttonStyle}>
82
85
  <View style={datePickerHeaderItemStyles.innerStyle}>
83
- <Text style={datePickerHeaderItemStyles.labelStyle} selectable={false}>
86
+ <Text
87
+ style={[
88
+ datePickerHeaderItemStyles.labelStyle,
89
+ // eslint-disable-next-line react-native/no-inline-styles
90
+ disabled && { opacity: 0.5 },
91
+ ]}
92
+ selectable={false}>
84
93
  {value}
85
94
  </Text>
86
- <IconButton
87
- onPress={handlePressDropDown}
88
- name={selecting && type === pickerType ? 'menu-up' : 'menu-down'}
89
- size="sm"
90
- disabled={disabled}
91
- />
95
+ {!disabled && (
96
+ <Icon
97
+ onPress={handlePressDropDown}
98
+ name={selecting && type === pickerType ? 'menu-up' : 'menu-down'}
99
+ size={18}
100
+ />
101
+ )}
92
102
  </View>
93
103
  </TouchableRipple>
94
104
  )}
95
- {!selecting && onNext && (
96
- <View style={datePickerHeaderItemStyles.buttonWrapper}>
105
+ {onNext && (
106
+ <View
107
+ style={[
108
+ datePickerHeaderItemStyles.buttonWrapper,
109
+ // eslint-disable-next-line react-native/no-inline-styles
110
+ (selecting || disabled) && { opacity: 0 },
111
+ ]}>
97
112
  <IconButton
98
113
  name="chevron-right"
99
- size="md"
114
+ size={24}
100
115
  // Todo: Translate
101
116
  accessibilityLabel={'Next'}
102
117
  onPress={handleOnNext}
103
- disabled={value === endDateYear}
118
+ disabled={value === endDateYear || selecting || disabled}
104
119
  />
105
120
  </View>
106
121
  )}