react-native-paper-dates 0.24.0 → 0.24.2

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 (120) hide show
  1. package/lib/commonjs/Date/AnimatedCrossView.js +2 -2
  2. package/lib/commonjs/Date/AnimatedCrossView.js.map +1 -1
  3. package/lib/commonjs/Date/AutoSizer.js +26 -12
  4. package/lib/commonjs/Date/AutoSizer.js.map +1 -1
  5. package/lib/commonjs/Date/Calendar.js +8 -4
  6. package/lib/commonjs/Date/Calendar.js.map +1 -1
  7. package/lib/commonjs/Date/CalendarEdit.js +70 -61
  8. package/lib/commonjs/Date/CalendarEdit.js.map +1 -1
  9. package/lib/commonjs/Date/CalendarHeader.js +30 -15
  10. package/lib/commonjs/Date/CalendarHeader.js.map +1 -1
  11. package/lib/commonjs/Date/DatePickerModal.js +33 -12
  12. package/lib/commonjs/Date/DatePickerModal.js.map +1 -1
  13. package/lib/commonjs/Date/DatePickerModalContent.js +69 -35
  14. package/lib/commonjs/Date/DatePickerModalContent.js.map +1 -1
  15. package/lib/commonjs/Date/DatePickerModalContentHeader.js +12 -5
  16. package/lib/commonjs/Date/DatePickerModalContentHeader.js.map +1 -1
  17. package/lib/commonjs/Date/DatePickerModalHeader.js +40 -40
  18. package/lib/commonjs/Date/DatePickerModalHeader.js.map +1 -1
  19. package/lib/commonjs/Date/DatePickerModalHeaderBackground.js +22 -4
  20. package/lib/commonjs/Date/DatePickerModalHeaderBackground.js.map +1 -1
  21. package/lib/commonjs/Date/Month.js +44 -30
  22. package/lib/commonjs/Date/Month.js.map +1 -1
  23. package/lib/commonjs/Date/Swiper.js +35 -22
  24. package/lib/commonjs/Date/Swiper.js.map +1 -1
  25. package/lib/commonjs/Date/Swiper.native.js +54 -21
  26. package/lib/commonjs/Date/Swiper.native.js.map +1 -1
  27. package/lib/commonjs/Date/SwiperUtils.js.map +1 -1
  28. package/lib/commonjs/Date/YearPicker.js +3 -1
  29. package/lib/commonjs/Date/YearPicker.js.map +1 -1
  30. package/lib/commonjs/Date/weekdayColumns.js +60 -0
  31. package/lib/commonjs/Date/weekdayColumns.js.map +1 -0
  32. package/lib/commonjs/shared/styles.js +3 -0
  33. package/lib/commonjs/shared/styles.js.map +1 -1
  34. package/lib/commonjs/shared/utils.js +9 -0
  35. package/lib/commonjs/shared/utils.js.map +1 -1
  36. package/lib/module/Date/AnimatedCrossView.js +2 -2
  37. package/lib/module/Date/AnimatedCrossView.js.map +1 -1
  38. package/lib/module/Date/AutoSizer.js +27 -13
  39. package/lib/module/Date/AutoSizer.js.map +1 -1
  40. package/lib/module/Date/Calendar.js +8 -4
  41. package/lib/module/Date/Calendar.js.map +1 -1
  42. package/lib/module/Date/CalendarEdit.js +70 -61
  43. package/lib/module/Date/CalendarEdit.js.map +1 -1
  44. package/lib/module/Date/CalendarHeader.js +31 -16
  45. package/lib/module/Date/CalendarHeader.js.map +1 -1
  46. package/lib/module/Date/DatePickerModal.js +35 -14
  47. package/lib/module/Date/DatePickerModal.js.map +1 -1
  48. package/lib/module/Date/DatePickerModalContent.js +69 -35
  49. package/lib/module/Date/DatePickerModalContent.js.map +1 -1
  50. package/lib/module/Date/DatePickerModalContentHeader.js +12 -5
  51. package/lib/module/Date/DatePickerModalContentHeader.js.map +1 -1
  52. package/lib/module/Date/DatePickerModalHeader.js +43 -43
  53. package/lib/module/Date/DatePickerModalHeader.js.map +1 -1
  54. package/lib/module/Date/DatePickerModalHeaderBackground.js +24 -6
  55. package/lib/module/Date/DatePickerModalHeaderBackground.js.map +1 -1
  56. package/lib/module/Date/Month.js +46 -32
  57. package/lib/module/Date/Month.js.map +1 -1
  58. package/lib/module/Date/Swiper.js +36 -23
  59. package/lib/module/Date/Swiper.js.map +1 -1
  60. package/lib/module/Date/Swiper.native.js +55 -22
  61. package/lib/module/Date/Swiper.native.js.map +1 -1
  62. package/lib/module/Date/SwiperUtils.js.map +1 -1
  63. package/lib/module/Date/YearPicker.js +4 -2
  64. package/lib/module/Date/YearPicker.js.map +1 -1
  65. package/lib/module/Date/weekdayColumns.js +51 -0
  66. package/lib/module/Date/weekdayColumns.js.map +1 -0
  67. package/lib/module/shared/styles.js +3 -0
  68. package/lib/module/shared/styles.js.map +1 -1
  69. package/lib/module/shared/utils.js +8 -0
  70. package/lib/module/shared/utils.js.map +1 -1
  71. package/lib/typescript/Date/AnimatedCrossView.d.ts.map +1 -1
  72. package/lib/typescript/Date/AutoSizer.d.ts +3 -1
  73. package/lib/typescript/Date/AutoSizer.d.ts.map +1 -1
  74. package/lib/typescript/Date/Calendar.d.ts +9 -0
  75. package/lib/typescript/Date/Calendar.d.ts.map +1 -1
  76. package/lib/typescript/Date/CalendarEdit.d.ts +3 -1
  77. package/lib/typescript/Date/CalendarEdit.d.ts.map +1 -1
  78. package/lib/typescript/Date/CalendarHeader.d.ts +5 -1
  79. package/lib/typescript/Date/CalendarHeader.d.ts.map +1 -1
  80. package/lib/typescript/Date/DatePickerModal.d.ts.map +1 -1
  81. package/lib/typescript/Date/DatePickerModalContent.d.ts +8 -0
  82. package/lib/typescript/Date/DatePickerModalContent.d.ts.map +1 -1
  83. package/lib/typescript/Date/DatePickerModalContentHeader.d.ts +2 -0
  84. package/lib/typescript/Date/DatePickerModalContentHeader.d.ts.map +1 -1
  85. package/lib/typescript/Date/DatePickerModalHeader.d.ts +2 -0
  86. package/lib/typescript/Date/DatePickerModalHeader.d.ts.map +1 -1
  87. package/lib/typescript/Date/DatePickerModalHeaderBackground.d.ts +3 -1
  88. package/lib/typescript/Date/DatePickerModalHeaderBackground.d.ts.map +1 -1
  89. package/lib/typescript/Date/Month.d.ts.map +1 -1
  90. package/lib/typescript/Date/Swiper.d.ts +1 -1
  91. package/lib/typescript/Date/Swiper.d.ts.map +1 -1
  92. package/lib/typescript/Date/Swiper.native.d.ts.map +1 -1
  93. package/lib/typescript/Date/SwiperUtils.d.ts +5 -0
  94. package/lib/typescript/Date/SwiperUtils.d.ts.map +1 -1
  95. package/lib/typescript/Date/YearPicker.d.ts.map +1 -1
  96. package/lib/typescript/Date/weekdayColumns.d.ts +9 -0
  97. package/lib/typescript/Date/weekdayColumns.d.ts.map +1 -0
  98. package/lib/typescript/shared/styles.d.ts +3 -0
  99. package/lib/typescript/shared/styles.d.ts.map +1 -1
  100. package/lib/typescript/shared/utils.d.ts +1 -0
  101. package/lib/typescript/shared/utils.d.ts.map +1 -1
  102. package/package.json +1 -1
  103. package/src/Date/AnimatedCrossView.tsx +2 -1
  104. package/src/Date/AutoSizer.tsx +36 -9
  105. package/src/Date/Calendar.tsx +13 -4
  106. package/src/Date/CalendarEdit.tsx +60 -51
  107. package/src/Date/CalendarHeader.tsx +38 -6
  108. package/src/Date/DatePickerModal.tsx +40 -13
  109. package/src/Date/DatePickerModalContent.tsx +78 -40
  110. package/src/Date/DatePickerModalContentHeader.tsx +14 -3
  111. package/src/Date/DatePickerModalHeader.tsx +47 -50
  112. package/src/Date/DatePickerModalHeaderBackground.tsx +30 -8
  113. package/src/Date/Month.tsx +73 -44
  114. package/src/Date/Swiper.native.tsx +92 -44
  115. package/src/Date/Swiper.tsx +46 -20
  116. package/src/Date/SwiperUtils.ts +2 -0
  117. package/src/Date/YearPicker.tsx +14 -2
  118. package/src/Date/weekdayColumns.ts +75 -0
  119. package/src/shared/styles.tsx +3 -0
  120. package/src/shared/utils.ts +6 -0
@@ -1,4 +1,4 @@
1
- import { StyleSheet, View } from 'react-native'
1
+ import { Platform, ScrollView, StyleSheet, View } from 'react-native'
2
2
  import { Icon, Text, TouchableRipple, useTheme } from 'react-native-paper'
3
3
  import Day, { EmptyDay } from './Day'
4
4
 
@@ -19,6 +19,7 @@ import {
19
19
  showWeekDay,
20
20
  useRangeChecker,
21
21
  } from './dateUtils'
22
+ import { alignTextToFirstWeekday } from './weekdayColumns'
22
23
  import { getCalendarHeaderHeight } from './CalendarHeader'
23
24
  import type { StyleProp, ViewStyle } from 'react-native'
24
25
  import type {
@@ -272,17 +273,54 @@ function Month(props: MonthSingleProps | MonthRangeProps | MonthMultiProps) {
272
273
 
273
274
  const iconSource = selectingYear ? 'menu-up' : 'menu-down'
274
275
 
276
+ const weeks = grid.map(({ weekIndex, generatedDays }) => (
277
+ <View style={styles.week} key={weekIndex}>
278
+ {generatedDays
279
+ .filter((gd) => showWeekDay(gd.dayIndex, disableWeekDays))
280
+ .map((gd) =>
281
+ gd.beforeWeekDay || gd.afterWeekDay ? (
282
+ <EmptyDay key={gd.dayIndex} />
283
+ ) : (
284
+ <Day
285
+ key={gd.dayIndex}
286
+ theme={theme}
287
+ day={gd.dayOfMonth}
288
+ month={gd.month}
289
+ year={gd.year}
290
+ selected={gd.selected}
291
+ inRange={gd.inRange}
292
+ leftCrop={gd.leftCrop}
293
+ rightCrop={gd.rightCrop}
294
+ onPressDate={onPressDate}
295
+ isToday={gd.isToday}
296
+ selectColor={selectColor}
297
+ primaryColor={primaryColor}
298
+ disabled={gd.disabled}
299
+ textColorOnPrimary={textColorOnPrimary}
300
+ dayContent={dayContent}
301
+ dayContentPosition={dayContentPosition}
302
+ dayContentStyle={dayContentStyle}
303
+ />
304
+ )
305
+ )}
306
+ </View>
307
+ ))
308
+
275
309
  return (
276
310
  <View
277
- style={{
278
- height: getMonthHeight(
279
- scrollMode,
280
- index,
281
- startWeekOnMonday,
282
- startYear,
283
- endYear
284
- ),
285
- }}
311
+ style={
312
+ isHorizontal
313
+ ? styles.monthFill
314
+ : {
315
+ height: getMonthHeight(
316
+ scrollMode,
317
+ index,
318
+ startWeekOnMonday,
319
+ startYear,
320
+ endYear
321
+ ),
322
+ }
323
+ }
286
324
  >
287
325
  <View
288
326
  style={[
@@ -305,6 +343,7 @@ function Month(props: MonthSingleProps | MonthRangeProps | MonthMultiProps) {
305
343
  {
306
344
  borderRadius: roundness,
307
345
  },
346
+ alignTextToFirstWeekday(disableWeekDays),
308
347
  ]}
309
348
  >
310
349
  <View
@@ -339,38 +378,26 @@ function Month(props: MonthSingleProps | MonthRangeProps | MonthMultiProps) {
339
378
  </View>
340
379
  </TouchableRipple>
341
380
  </View>
342
- {grid.map(({ weekIndex, generatedDays }) => (
343
- <View style={styles.week} key={weekIndex}>
344
- {generatedDays
345
- .filter((gd) => showWeekDay(gd.dayIndex, disableWeekDays))
346
- .map((gd) =>
347
- gd.beforeWeekDay || gd.afterWeekDay ? (
348
- <EmptyDay key={gd.dayIndex} />
349
- ) : (
350
- <Day
351
- key={gd.dayIndex}
352
- theme={theme}
353
- day={gd.dayOfMonth}
354
- month={gd.month}
355
- year={gd.year}
356
- selected={gd.selected}
357
- inRange={gd.inRange}
358
- leftCrop={gd.leftCrop}
359
- rightCrop={gd.rightCrop}
360
- onPressDate={onPressDate}
361
- isToday={gd.isToday}
362
- selectColor={selectColor}
363
- primaryColor={primaryColor}
364
- disabled={gd.disabled}
365
- textColorOnPrimary={textColorOnPrimary}
366
- dayContent={dayContent}
367
- dayContentPosition={dayContentPosition}
368
- dayContentStyle={dayContentStyle}
369
- />
370
- )
371
- )}
372
- </View>
373
- ))}
381
+ {isHorizontal ? (
382
+ <ScrollView
383
+ alwaysBounceVertical={false}
384
+ directionalLockEnabled
385
+ keyboardShouldPersistTaps="handled"
386
+ nestedScrollEnabled
387
+ style={[
388
+ sharedStyles.root,
389
+ sharedStyles.minHeightZero,
390
+ Platform.OS === 'web'
391
+ ? ({ colorScheme: theme.dark ? 'dark' : 'light' } as ViewStyle)
392
+ : null,
393
+ ]}
394
+ testID="react-native-paper-dates-month-days-scroll"
395
+ >
396
+ {weeks}
397
+ </ScrollView>
398
+ ) : (
399
+ weeks
400
+ )}
374
401
  </View>
375
402
  )
376
403
  }
@@ -387,6 +414,10 @@ const styles = StyleSheet.create({
387
414
  iconWrapper: {
388
415
  padding: 8,
389
416
  },
417
+ monthFill: {
418
+ flex: 1,
419
+ minHeight: 0,
420
+ },
390
421
  monthHeader: {
391
422
  height: montHeaderHeight,
392
423
  justifyContent: 'center',
@@ -403,10 +434,8 @@ const styles = StyleSheet.create({
403
434
  },
404
435
  yearButton: {
405
436
  alignSelf: 'flex-start',
406
- marginLeft: 6,
407
437
  },
408
438
  yearButtonInner: {
409
- paddingLeft: 16,
410
439
  flexDirection: 'row',
411
440
  alignItems: 'center',
412
441
  },
@@ -20,8 +20,9 @@ import {
20
20
  getBeginOffset,
21
21
  } from './dateUtils'
22
22
  import AutoSizer from './AutoSizer'
23
- import { memo, useCallback, useRef, useState } from 'react'
23
+ import { memo, useCallback, useEffect, useRef, useState } from 'react'
24
24
  import { sharedStyles } from '../shared/styles'
25
+ import { verticalScrollbarGutter } from './CalendarHeader'
25
26
 
26
27
  function getVisibleArray(
27
28
  i: number,
@@ -35,7 +36,7 @@ function getVisibleArray(
35
36
 
36
37
  function Swiper(props: SwiperProps) {
37
38
  return (
38
- <AutoSizer>
39
+ <AutoSizer initialLayout={props.initialLayout}>
39
40
  {({ width, height }) => (
40
41
  <SwiperInner {...props} width={width} height={height} />
41
42
  )}
@@ -64,6 +65,26 @@ function SwiperInner({
64
65
 
65
66
  const parentRef = useRef<ScrollView | null>(null)
66
67
 
68
+ // Start on the current month instead of at 0 (where no month is rendered)
69
+ // and then jumping there after mount. Later moves go through scrollTo.
70
+ const [initialContentOffset] = useState(() => {
71
+ if (!isIndexWithinRange(initialIndex, startYear, endYear)) {
72
+ return undefined
73
+ }
74
+ return isHorizontal
75
+ ? { x: getHorizontalMonthOffset(initialIndex, width), y: 0 }
76
+ : {
77
+ x: 0,
78
+ y:
79
+ getVerticalMonthsOffset(
80
+ initialIndex,
81
+ startWeekOnMonday,
82
+ startYear,
83
+ endYear
84
+ ) - montHeaderHeight,
85
+ }
86
+ })
87
+
67
88
  const scrollTo = useCallback(
68
89
  (index: number, animated: boolean) => {
69
90
  if (!isIndexWithinRange(index, startYear, endYear)) {
@@ -124,10 +145,13 @@ function SwiperInner({
124
145
  }
125
146
  }, [scrollTo, idx, startYear, endYear])
126
147
 
127
- const scrollToInitial = useCallback(() => {
148
+ const scrollToCurrent = useCallback(() => {
128
149
  scrollTo(idx.current, false)
129
150
  }, [scrollTo])
130
151
 
152
+ // onLayout can run against the previous page width during rotation, before
153
+ useEffect(scrollToCurrent, [scrollToCurrent])
154
+
131
155
  const onMomentumScrollEnd = useCallback(
132
156
  (e: NativeSyntheticEvent<NativeScrollEvent>) => {
133
157
  const contentOffset = e.nativeEvent.contentOffset
@@ -164,6 +188,19 @@ function SwiperInner({
164
188
  onNext,
165
189
  }
166
190
 
191
+ const needsMonthScroll =
192
+ isHorizontal &&
193
+ visibleIndexes.some(
194
+ (monthIndex) =>
195
+ getMonthHeight(
196
+ scrollMode,
197
+ monthIndex,
198
+ startWeekOnMonday,
199
+ startYear,
200
+ endYear
201
+ ) > height
202
+ )
203
+
167
204
  useYearChange(
168
205
  (newIndex) => {
169
206
  if (newIndex && isIndexWithinRange(newIndex, startYear, endYear)) {
@@ -185,10 +222,13 @@ function SwiperInner({
185
222
  ref={parentRef}
186
223
  horizontal={isHorizontal}
187
224
  pagingEnabled={isHorizontal}
188
- style={sharedStyles.root}
225
+ nestedScrollEnabled={isHorizontal}
226
+ directionalLockEnabled={isHorizontal}
227
+ style={[sharedStyles.root, sharedStyles.minHeightZero]}
189
228
  onMomentumScrollEnd={onMomentumScrollEnd}
190
229
  onScrollEndDrag={onMomentumScrollEnd}
191
- onLayout={scrollToInitial}
230
+ onLayout={scrollToCurrent}
231
+ contentOffset={initialContentOffset}
192
232
  showsHorizontalScrollIndicator={false}
193
233
  showsVerticalScrollIndicator={false}
194
234
  decelerationRate="fast"
@@ -208,48 +248,56 @@ function SwiperInner({
208
248
  ]}
209
249
  >
210
250
  {visibleIndexes
211
- ? new Array(visibleIndexes.length).fill(undefined).map((_, vi) => (
212
- <View
213
- key={vi}
214
- // eslint-disable-next-line react-native/no-inline-styles
215
- style={{
216
- top: isHorizontal
217
- ? 0
218
- : getVerticalMonthsOffset(
219
- visibleIndexes[vi],
220
- startWeekOnMonday,
221
- startYear,
222
- endYear
223
- ),
224
- left: isHorizontal
225
- ? getHorizontalMonthOffset(visibleIndexes[vi], width)
226
- : 0,
227
- right: isHorizontal ? undefined : 0,
228
- bottom: isHorizontal ? 0 : undefined,
229
- position: 'absolute',
230
- width: isHorizontal ? width : undefined,
231
- height: isHorizontal
232
- ? undefined
233
- : getMonthHeight(
234
- scrollMode,
235
- visibleIndexes[vi],
236
- startWeekOnMonday,
237
- startYear,
238
- endYear
239
- ),
240
- }}
241
- >
242
- {renderItem({
243
- index: visibleIndexes[vi],
244
- onPrev: onPrev,
245
- onNext: onNext,
246
- })}
247
- </View>
248
- ))
251
+ ? new Array(visibleIndexes.length).fill(undefined).map((_, vi) => {
252
+ const monthIndex = visibleIndexes[vi]
253
+ const monthHeight = getMonthHeight(
254
+ scrollMode,
255
+ monthIndex,
256
+ startWeekOnMonday,
257
+ startYear,
258
+ endYear
259
+ )
260
+ // Horizontal paging does not scroll inside a month. Bound the
261
+ // page to the dialog so the day grid can scroll in landscape.
262
+ return (
263
+ <View
264
+ key={vi}
265
+ // eslint-disable-next-line react-native/no-inline-styles
266
+ style={{
267
+ top: isHorizontal
268
+ ? 0
269
+ : getVerticalMonthsOffset(
270
+ monthIndex,
271
+ startWeekOnMonday,
272
+ startYear,
273
+ endYear
274
+ ),
275
+ left: isHorizontal
276
+ ? getHorizontalMonthOffset(monthIndex, width)
277
+ : 0,
278
+ right: isHorizontal ? undefined : 0,
279
+ position: 'absolute',
280
+ width: isHorizontal ? width : undefined,
281
+ height: isHorizontal ? height : monthHeight,
282
+ overflow: 'hidden',
283
+ }}
284
+ >
285
+ {renderItem({
286
+ index: monthIndex,
287
+ onPrev: onPrev,
288
+ onNext: onNext,
289
+ })}
290
+ </View>
291
+ )
292
+ })
249
293
  : null}
250
294
  </View>
251
295
  </ScrollView>
252
- {renderHeader && renderHeader(renderProps)}
296
+ {renderHeader &&
297
+ renderHeader({
298
+ ...renderProps,
299
+ endInset: needsMonthScroll ? verticalScrollbarGutter : 0,
300
+ })}
253
301
  {renderFooter && renderFooter(renderProps)}
254
302
  </>
255
303
  )
@@ -1,4 +1,3 @@
1
- import { View } from 'react-native'
2
1
  import { useTheme } from 'react-native-paper'
3
2
  import {
4
3
  getIndexFromVerticalOffset,
@@ -30,7 +29,7 @@ import {
30
29
  useRef,
31
30
  useState,
32
31
  } from 'react'
33
- import { sharedStyles } from '../shared/styles'
32
+ import { verticalScrollbarGutter } from './CalendarHeader'
34
33
 
35
34
  const useIsomorphicLayoutEffect =
36
35
  typeof window !== 'undefined' ? useLayoutEffect : useEffect
@@ -45,6 +44,7 @@ function Swiper({
45
44
  startWeekOnMonday,
46
45
  startYear,
47
46
  endYear,
47
+ initialLayout,
48
48
  }: SwiperProps) {
49
49
  const isHorizontal = scrollMode === 'horizontal'
50
50
 
@@ -94,26 +94,52 @@ function Swiper({
94
94
 
95
95
  return (
96
96
  <>
97
- {renderHeader && renderHeader(renderProps)}
98
97
  {isHorizontal ? (
99
- <View style={sharedStyles.root}>
100
- {renderItem({ index, onPrev, onNext })}
101
- </View>
102
- ) : (
103
- <AutoSizer>
104
- {({ width, height }) => (
105
- <VerticalScroller
106
- width={width}
107
- height={height}
108
- initialIndex={initialIndex}
109
- estimatedHeight={estimatedMonthHeight}
110
- renderItem={renderItem}
111
- startWeekOnMonday={startWeekOnMonday}
112
- startYear={startYear}
113
- endYear={endYear}
114
- />
115
- )}
98
+ <AutoSizer initialLayout={initialLayout}>
99
+ {({ height }) => {
100
+ const overflow =
101
+ getMonthHeight(
102
+ 'horizontal',
103
+ index,
104
+ startWeekOnMonday,
105
+ startYear,
106
+ endYear
107
+ ) > height
108
+ return (
109
+ <>
110
+ {renderItem({
111
+ index,
112
+ onPrev,
113
+ onNext,
114
+ })}
115
+ {renderHeader
116
+ ? renderHeader({
117
+ ...renderProps,
118
+ endInset: overflow ? verticalScrollbarGutter : 0,
119
+ })
120
+ : null}
121
+ </>
122
+ )
123
+ }}
116
124
  </AutoSizer>
125
+ ) : (
126
+ <>
127
+ {renderHeader && renderHeader(renderProps)}
128
+ <AutoSizer initialLayout={initialLayout}>
129
+ {({ width, height }) => (
130
+ <VerticalScroller
131
+ width={width}
132
+ height={height}
133
+ initialIndex={initialIndex}
134
+ estimatedHeight={estimatedMonthHeight}
135
+ renderItem={renderItem}
136
+ startWeekOnMonday={startWeekOnMonday}
137
+ startYear={startYear}
138
+ endYear={endYear}
139
+ />
140
+ )}
141
+ </AutoSizer>
142
+ </>
117
143
  )}
118
144
  {renderFooter && renderFooter(renderProps)}
119
145
  </>
@@ -10,6 +10,7 @@ import {
10
10
  import { defaultStartYear, defaultEndYear } from './dateUtils'
11
11
 
12
12
  export type RenderProps = {
13
+ endInset?: number
13
14
  index: number
14
15
  onNext: () => any
15
16
  onPrev: () => any
@@ -25,6 +26,7 @@ export type SwiperProps = {
25
26
  startWeekOnMonday: boolean
26
27
  startYear?: number
27
28
  endYear?: number
29
+ initialLayout?: { width: number; height: number }
28
30
  }
29
31
 
30
32
  // Helper function to get the minimum allowed index based on startYear
@@ -1,4 +1,11 @@
1
- import { FlatList, ScrollView, StyleSheet, View } from 'react-native'
1
+ import {
2
+ FlatList,
3
+ Platform,
4
+ ScrollView,
5
+ StyleSheet,
6
+ View,
7
+ type ViewStyle,
8
+ } from 'react-native'
2
9
  import { Text, TouchableRipple, useTheme } from 'react-native-paper'
3
10
  import { range } from '../shared/utils'
4
11
  import { memo, useEffect, useRef } from 'react'
@@ -51,7 +58,12 @@ export default function YearPicker({
51
58
  >
52
59
  <FlatList<number>
53
60
  ref={flatList}
54
- style={sharedStyles.root}
61
+ style={[
62
+ sharedStyles.root,
63
+ Platform.OS === 'web'
64
+ ? ({ colorScheme: theme.dark ? 'dark' : 'light' } as ViewStyle)
65
+ : null,
66
+ ]}
55
67
  data={years}
56
68
  renderScrollComponent={(sProps) => {
57
69
  return <ScrollView {...sProps} />
@@ -0,0 +1,75 @@
1
+ import { I18nManager, type DimensionValue, type ViewStyle } from 'react-native'
2
+ import { showWeekDay, type DisableWeekDaysType } from './dateUtils'
3
+
4
+ const compactTextButtonPadding = 8
5
+ const iconButtonPadding = 8
6
+ const iconButtonSize = 24 + 2 * iconButtonPadding
7
+ const letterHalfWidth = 4
8
+
9
+ export function alignIconToFirstWeekday(
10
+ disableWeekDays?: DisableWeekDaysType
11
+ ): ViewStyle {
12
+ return alignToFirstColumn(
13
+ disableWeekDays,
14
+ letterHalfWidth + iconButtonPadding
15
+ )
16
+ }
17
+
18
+ export function alignTextToFirstWeekday(
19
+ disableWeekDays?: DisableWeekDaysType
20
+ ): ViewStyle {
21
+ return alignToFirstColumn(disableWeekDays, letterHalfWidth)
22
+ }
23
+
24
+ export function alignTextToLastWeekday(
25
+ disableWeekDays?: DisableWeekDaysType
26
+ ): ViewStyle {
27
+ return alignToLastColumn(
28
+ disableWeekDays,
29
+ letterHalfWidth + compactTextButtonPadding
30
+ )
31
+ }
32
+
33
+ function alignToFirstColumn(
34
+ disableWeekDays: DisableWeekDaysType | undefined,
35
+ nudge: number
36
+ ): ViewStyle {
37
+ return {
38
+ marginStart: columnCentreInset(disableWeekDays),
39
+ transform: [{ translateX: I18nManager.isRTL ? nudge : -nudge }],
40
+ }
41
+ }
42
+
43
+ function alignToLastColumn(
44
+ disableWeekDays: DisableWeekDaysType | undefined,
45
+ nudge: number
46
+ ): ViewStyle {
47
+ return {
48
+ marginEnd: columnCentreInset(disableWeekDays),
49
+ transform: [{ translateX: I18nManager.isRTL ? -nudge : nudge }],
50
+ }
51
+ }
52
+
53
+ export function centerIconOnLastWeekday(
54
+ disableWeekDays?: DisableWeekDaysType
55
+ ): ViewStyle {
56
+ return alignToLastColumn(disableWeekDays, iconButtonSize / 2)
57
+ }
58
+
59
+ function columnCentreInset(
60
+ disableWeekDays: DisableWeekDaysType | undefined
61
+ ): DimensionValue {
62
+ const visibleColumns = [0, 1, 2, 3, 4, 5, 6].filter((dayIndex) =>
63
+ showWeekDay(dayIndex, disableWeekDays)
64
+ ).length
65
+ return `${50 / (visibleColumns || 7)}%`
66
+ }
67
+
68
+ export function weekdaySpan(disableWeekDays?: DisableWeekDaysType): ViewStyle {
69
+ const inset = columnCentreInset(disableWeekDays)
70
+ return { marginStart: inset, marginEnd: inset }
71
+ }
72
+
73
+ export const weekdaySpanOvershoot: ViewStyle = {
74
+ marginHorizontal: -letterHalfWidth,
75
+ }
@@ -4,6 +4,9 @@ export const sharedStyles = StyleSheet.create({
4
4
  flexDirectionRow: {
5
5
  flexDirection: 'row',
6
6
  },
7
+ minHeightZero: {
8
+ minHeight: 0,
9
+ },
7
10
  opacity0: {
8
11
  opacity: 0,
9
12
  },
@@ -1,4 +1,5 @@
1
1
  import { useRef } from 'react'
2
+ import { useWindowDimensions } from 'react-native'
2
3
  import { DefaultTheme, MD3DarkTheme, useTheme } from 'react-native-paper'
3
4
  import Color from 'color'
4
5
 
@@ -24,6 +25,11 @@ export function useLatest<T>(value: T) {
24
25
  return ref
25
26
  }
26
27
 
28
+ export function useIsLargeScreen() {
29
+ const { width, height } = useWindowDimensions()
30
+ return width > 650 && height > 650
31
+ }
32
+
27
33
  export function useHeaderBackgroundColor() {
28
34
  const theme = useTheme()
29
35
  return theme.colors.elevation.level3