rn-grid-date-time-picker 1.0.0 → 1.2.0

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 (384) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +100 -638
  3. package/lib/commonjs/adapters/utcMidnight.js +15 -6
  4. package/lib/commonjs/adapters/utcMidnight.js.map +1 -1
  5. package/lib/commonjs/components/DateTimePicker.js +484 -85
  6. package/lib/commonjs/components/DateTimePicker.js.map +1 -1
  7. package/lib/commonjs/components/calendar/Calendar.js +21 -7
  8. package/lib/commonjs/components/calendar/Calendar.js.map +1 -1
  9. package/lib/commonjs/components/calendar/CalendarHeader.js +46 -6
  10. package/lib/commonjs/components/calendar/CalendarHeader.js.map +1 -1
  11. package/lib/commonjs/components/calendar/CalendarSwitch.js +150 -0
  12. package/lib/commonjs/components/calendar/CalendarSwitch.js.map +1 -0
  13. package/lib/commonjs/components/calendar/DayCell.js +8 -3
  14. package/lib/commonjs/components/calendar/DayCell.js.map +1 -1
  15. package/lib/commonjs/components/calendar/DayGrid.js +13 -2
  16. package/lib/commonjs/components/calendar/DayGrid.js.map +1 -1
  17. package/lib/commonjs/components/calendar/PeriodGrid.js +3 -1
  18. package/lib/commonjs/components/calendar/PeriodGrid.js.map +1 -1
  19. package/lib/commonjs/components/calendar/calendarStyles.js +3 -2
  20. package/lib/commonjs/components/calendar/calendarStyles.js.map +1 -1
  21. package/lib/commonjs/components/calendar/localeNames.js +46 -24
  22. package/lib/commonjs/components/calendar/localeNames.js.map +1 -1
  23. package/lib/commonjs/components/calendar/selection.js +9 -1
  24. package/lib/commonjs/components/calendar/selection.js.map +1 -1
  25. package/lib/commonjs/components/container/DefaultSheet.js +42 -11
  26. package/lib/commonjs/components/container/DefaultSheet.js.map +1 -1
  27. package/lib/commonjs/components/container/PickerContainer.js +4 -0
  28. package/lib/commonjs/components/container/PickerContainer.js.map +1 -1
  29. package/lib/commonjs/components/container/PickerLayout.js +1 -1
  30. package/lib/commonjs/components/container/PickerLayout.js.map +1 -1
  31. package/lib/commonjs/components/container/containerStyles.js +12 -4
  32. package/lib/commonjs/components/container/containerStyles.js.map +1 -1
  33. package/lib/commonjs/components/field/RangeFields.js +5 -1
  34. package/lib/commonjs/components/field/RangeFields.js.map +1 -1
  35. package/lib/commonjs/components/field/SegmentedInput.js +8 -3
  36. package/lib/commonjs/components/field/SegmentedInput.js.map +1 -1
  37. package/lib/commonjs/components/field/ValueField.js +64 -8
  38. package/lib/commonjs/components/field/ValueField.js.map +1 -1
  39. package/lib/commonjs/components/field/fieldStyles.js +17 -0
  40. package/lib/commonjs/components/field/fieldStyles.js.map +1 -1
  41. package/lib/commonjs/components/field/fieldText.js +29 -13
  42. package/lib/commonjs/components/field/fieldText.js.map +1 -1
  43. package/lib/commonjs/components/hooks/useBottomInset.js +32 -0
  44. package/lib/commonjs/components/hooks/useBottomInset.js.map +1 -0
  45. package/lib/commonjs/components/hooks/useKeyboardFold.js +36 -13
  46. package/lib/commonjs/components/hooks/useKeyboardFold.js.map +1 -1
  47. package/lib/commonjs/components/hooks/useOpenPicker.js +39 -17
  48. package/lib/commonjs/components/hooks/useOpenPicker.js.map +1 -1
  49. package/lib/commonjs/components/hooks/useTypedSegments.js +6 -2
  50. package/lib/commonjs/components/hooks/useTypedSegments.js.map +1 -1
  51. package/lib/commonjs/components/theme/defaultStrings.js +13 -3
  52. package/lib/commonjs/components/theme/defaultStrings.js.map +1 -1
  53. package/lib/commonjs/components/theme/direction.js +17 -0
  54. package/lib/commonjs/components/theme/direction.js.map +1 -0
  55. package/lib/commonjs/components/theme/numerals.js +16 -0
  56. package/lib/commonjs/components/theme/numerals.js.map +1 -0
  57. package/lib/commonjs/components/theme/styleKeys.js +10 -2
  58. package/lib/commonjs/components/theme/styleKeys.js.map +1 -1
  59. package/lib/commonjs/components/theme/tokens.js +4 -0
  60. package/lib/commonjs/components/theme/tokens.js.map +1 -1
  61. package/lib/commonjs/components/time/TimeRow.js +10 -2
  62. package/lib/commonjs/components/time/TimeRow.js.map +1 -1
  63. package/lib/commonjs/components/time/TypedTime.js +3 -1
  64. package/lib/commonjs/components/time/TypedTime.js.map +1 -1
  65. package/lib/commonjs/components/time/Wheel.js +20 -3
  66. package/lib/commonjs/components/time/Wheel.js.map +1 -1
  67. package/lib/commonjs/components/time/timeStyles.js +4 -5
  68. package/lib/commonjs/components/time/timeStyles.js.map +1 -1
  69. package/lib/commonjs/components/types.js +10 -0
  70. package/lib/commonjs/components/types.js.map +1 -1
  71. package/lib/commonjs/core/calendarSystem.js +123 -22
  72. package/lib/commonjs/core/calendarSystem.js.map +1 -1
  73. package/lib/commonjs/core/digits.js +25 -0
  74. package/lib/commonjs/core/digits.js.map +1 -0
  75. package/lib/commonjs/core/draft.js +31 -10
  76. package/lib/commonjs/core/draft.js.map +1 -1
  77. package/lib/commonjs/core/locale.js +20 -4
  78. package/lib/commonjs/core/locale.js.map +1 -1
  79. package/lib/commonjs/core/numerals.js +46 -0
  80. package/lib/commonjs/core/numerals.js.map +1 -0
  81. package/lib/commonjs/core/segmentEditor.js +9 -0
  82. package/lib/commonjs/core/segmentEditor.js.map +1 -1
  83. package/lib/commonjs/core/segments.js +2 -11
  84. package/lib/commonjs/core/segments.js.map +1 -1
  85. package/lib/commonjs/core/selectionRules.js +2 -1
  86. package/lib/commonjs/core/selectionRules.js.map +1 -1
  87. package/lib/commonjs/core/timeEntry.js +7 -91
  88. package/lib/commonjs/core/timeEntry.js.map +1 -1
  89. package/lib/commonjs/icons/index.js +5 -1
  90. package/lib/commonjs/icons/index.js.map +1 -1
  91. package/lib/commonjs/index.js +20 -0
  92. package/lib/commonjs/index.js.map +1 -1
  93. package/lib/module/adapters/utcMidnight.js +14 -5
  94. package/lib/module/adapters/utcMidnight.js.map +1 -1
  95. package/lib/module/components/DateTimePicker.js +490 -91
  96. package/lib/module/components/DateTimePicker.js.map +1 -1
  97. package/lib/module/components/calendar/Calendar.js +25 -11
  98. package/lib/module/components/calendar/Calendar.js.map +1 -1
  99. package/lib/module/components/calendar/CalendarHeader.js +47 -7
  100. package/lib/module/components/calendar/CalendarHeader.js.map +1 -1
  101. package/lib/module/components/calendar/CalendarSwitch.js +145 -0
  102. package/lib/module/components/calendar/CalendarSwitch.js.map +1 -0
  103. package/lib/module/components/calendar/DayCell.js +8 -3
  104. package/lib/module/components/calendar/DayCell.js.map +1 -1
  105. package/lib/module/components/calendar/DayGrid.js +14 -3
  106. package/lib/module/components/calendar/DayGrid.js.map +1 -1
  107. package/lib/module/components/calendar/PeriodGrid.js +3 -1
  108. package/lib/module/components/calendar/PeriodGrid.js.map +1 -1
  109. package/lib/module/components/calendar/calendarStyles.js +3 -2
  110. package/lib/module/components/calendar/calendarStyles.js.map +1 -1
  111. package/lib/module/components/calendar/localeNames.js +46 -24
  112. package/lib/module/components/calendar/localeNames.js.map +1 -1
  113. package/lib/module/components/calendar/selection.js +7 -0
  114. package/lib/module/components/calendar/selection.js.map +1 -1
  115. package/lib/module/components/container/DefaultSheet.js +42 -12
  116. package/lib/module/components/container/DefaultSheet.js.map +1 -1
  117. package/lib/module/components/container/PickerContainer.js +4 -0
  118. package/lib/module/components/container/PickerContainer.js.map +1 -1
  119. package/lib/module/components/container/PickerLayout.js +1 -1
  120. package/lib/module/components/container/PickerLayout.js.map +1 -1
  121. package/lib/module/components/container/containerStyles.js +11 -3
  122. package/lib/module/components/container/containerStyles.js.map +1 -1
  123. package/lib/module/components/field/RangeFields.js +5 -1
  124. package/lib/module/components/field/RangeFields.js.map +1 -1
  125. package/lib/module/components/field/SegmentedInput.js +8 -3
  126. package/lib/module/components/field/SegmentedInput.js.map +1 -1
  127. package/lib/module/components/field/ValueField.js +66 -10
  128. package/lib/module/components/field/ValueField.js.map +1 -1
  129. package/lib/module/components/field/fieldStyles.js +17 -0
  130. package/lib/module/components/field/fieldStyles.js.map +1 -1
  131. package/lib/module/components/field/fieldText.js +28 -11
  132. package/lib/module/components/field/fieldText.js.map +1 -1
  133. package/lib/module/components/hooks/useBottomInset.js +27 -0
  134. package/lib/module/components/hooks/useBottomInset.js.map +1 -0
  135. package/lib/module/components/hooks/useKeyboardFold.js +33 -12
  136. package/lib/module/components/hooks/useKeyboardFold.js.map +1 -1
  137. package/lib/module/components/hooks/useOpenPicker.js +39 -17
  138. package/lib/module/components/hooks/useOpenPicker.js.map +1 -1
  139. package/lib/module/components/hooks/useTypedSegments.js +6 -2
  140. package/lib/module/components/hooks/useTypedSegments.js.map +1 -1
  141. package/lib/module/components/theme/defaultStrings.js +11 -2
  142. package/lib/module/components/theme/defaultStrings.js.map +1 -1
  143. package/lib/module/components/theme/direction.js +13 -0
  144. package/lib/module/components/theme/direction.js.map +1 -0
  145. package/lib/module/components/theme/numerals.js +12 -0
  146. package/lib/module/components/theme/numerals.js.map +1 -0
  147. package/lib/module/components/theme/styleKeys.js +10 -2
  148. package/lib/module/components/theme/styleKeys.js.map +1 -1
  149. package/lib/module/components/theme/tokens.js +4 -0
  150. package/lib/module/components/theme/tokens.js.map +1 -1
  151. package/lib/module/components/time/TimeRow.js +11 -3
  152. package/lib/module/components/time/TimeRow.js.map +1 -1
  153. package/lib/module/components/time/TypedTime.js +3 -1
  154. package/lib/module/components/time/TypedTime.js.map +1 -1
  155. package/lib/module/components/time/Wheel.js +18 -2
  156. package/lib/module/components/time/Wheel.js.map +1 -1
  157. package/lib/module/components/time/timeStyles.js +4 -5
  158. package/lib/module/components/time/timeStyles.js.map +1 -1
  159. package/lib/module/components/types.js +10 -0
  160. package/lib/module/components/types.js.map +1 -1
  161. package/lib/module/core/calendarSystem.js +118 -19
  162. package/lib/module/core/calendarSystem.js.map +1 -1
  163. package/lib/module/core/digits.js +20 -0
  164. package/lib/module/core/digits.js.map +1 -0
  165. package/lib/module/core/draft.js +29 -9
  166. package/lib/module/core/draft.js.map +1 -1
  167. package/lib/module/core/locale.js +18 -3
  168. package/lib/module/core/locale.js.map +1 -1
  169. package/lib/module/core/numerals.js +39 -0
  170. package/lib/module/core/numerals.js.map +1 -0
  171. package/lib/module/core/segmentEditor.js +9 -0
  172. package/lib/module/core/segmentEditor.js.map +1 -1
  173. package/lib/module/core/segments.js +0 -8
  174. package/lib/module/core/segments.js.map +1 -1
  175. package/lib/module/core/selectionRules.js +2 -1
  176. package/lib/module/core/selectionRules.js.map +1 -1
  177. package/lib/module/core/timeEntry.js +7 -89
  178. package/lib/module/core/timeEntry.js.map +1 -1
  179. package/lib/module/icons/index.js +5 -1
  180. package/lib/module/icons/index.js.map +1 -1
  181. package/lib/module/index.js +2 -0
  182. package/lib/module/index.js.map +1 -1
  183. package/lib/typescript/commonjs/src/adapters/utcMidnight.d.ts.map +1 -1
  184. package/lib/typescript/commonjs/src/components/DateTimePicker.d.ts.map +1 -1
  185. package/lib/typescript/commonjs/src/components/calendar/Calendar.d.ts +8 -4
  186. package/lib/typescript/commonjs/src/components/calendar/Calendar.d.ts.map +1 -1
  187. package/lib/typescript/commonjs/src/components/calendar/CalendarHeader.d.ts.map +1 -1
  188. package/lib/typescript/commonjs/src/components/calendar/CalendarSwitch.d.ts +26 -0
  189. package/lib/typescript/commonjs/src/components/calendar/CalendarSwitch.d.ts.map +1 -0
  190. package/lib/typescript/commonjs/src/components/calendar/DayCell.d.ts +1 -1
  191. package/lib/typescript/commonjs/src/components/calendar/DayCell.d.ts.map +1 -1
  192. package/lib/typescript/commonjs/src/components/calendar/DayGrid.d.ts +2 -0
  193. package/lib/typescript/commonjs/src/components/calendar/DayGrid.d.ts.map +1 -1
  194. package/lib/typescript/commonjs/src/components/calendar/PeriodGrid.d.ts.map +1 -1
  195. package/lib/typescript/commonjs/src/components/calendar/calendarStyles.d.ts +1 -1
  196. package/lib/typescript/commonjs/src/components/calendar/calendarStyles.d.ts.map +1 -1
  197. package/lib/typescript/commonjs/src/components/calendar/localeNames.d.ts +8 -3
  198. package/lib/typescript/commonjs/src/components/calendar/localeNames.d.ts.map +1 -1
  199. package/lib/typescript/commonjs/src/components/calendar/selection.d.ts +2 -0
  200. package/lib/typescript/commonjs/src/components/calendar/selection.d.ts.map +1 -1
  201. package/lib/typescript/commonjs/src/components/container/DefaultSheet.d.ts +10 -2
  202. package/lib/typescript/commonjs/src/components/container/DefaultSheet.d.ts.map +1 -1
  203. package/lib/typescript/commonjs/src/components/container/PickerContainer.d.ts.map +1 -1
  204. package/lib/typescript/commonjs/src/components/container/containerStyles.d.ts +6 -0
  205. package/lib/typescript/commonjs/src/components/container/containerStyles.d.ts.map +1 -1
  206. package/lib/typescript/commonjs/src/components/field/RangeFields.d.ts +5 -0
  207. package/lib/typescript/commonjs/src/components/field/RangeFields.d.ts.map +1 -1
  208. package/lib/typescript/commonjs/src/components/field/SegmentedInput.d.ts.map +1 -1
  209. package/lib/typescript/commonjs/src/components/field/ValueField.d.ts +7 -0
  210. package/lib/typescript/commonjs/src/components/field/ValueField.d.ts.map +1 -1
  211. package/lib/typescript/commonjs/src/components/field/fieldStyles.d.ts +15 -0
  212. package/lib/typescript/commonjs/src/components/field/fieldStyles.d.ts.map +1 -1
  213. package/lib/typescript/commonjs/src/components/field/fieldText.d.ts +14 -5
  214. package/lib/typescript/commonjs/src/components/field/fieldText.d.ts.map +1 -1
  215. package/lib/typescript/commonjs/src/components/hooks/useBottomInset.d.ts +8 -0
  216. package/lib/typescript/commonjs/src/components/hooks/useBottomInset.d.ts.map +1 -0
  217. package/lib/typescript/commonjs/src/components/hooks/useKeyboardFold.d.ts +10 -2
  218. package/lib/typescript/commonjs/src/components/hooks/useKeyboardFold.d.ts.map +1 -1
  219. package/lib/typescript/commonjs/src/components/hooks/useOpenPicker.d.ts +2 -1
  220. package/lib/typescript/commonjs/src/components/hooks/useOpenPicker.d.ts.map +1 -1
  221. package/lib/typescript/commonjs/src/components/hooks/useTypedSegments.d.ts +3 -2
  222. package/lib/typescript/commonjs/src/components/hooks/useTypedSegments.d.ts.map +1 -1
  223. package/lib/typescript/commonjs/src/components/theme/defaultStrings.d.ts +13 -2
  224. package/lib/typescript/commonjs/src/components/theme/defaultStrings.d.ts.map +1 -1
  225. package/lib/typescript/commonjs/src/components/theme/direction.d.ts +8 -0
  226. package/lib/typescript/commonjs/src/components/theme/direction.d.ts.map +1 -0
  227. package/lib/typescript/commonjs/src/components/theme/numerals.d.ts +7 -0
  228. package/lib/typescript/commonjs/src/components/theme/numerals.d.ts.map +1 -0
  229. package/lib/typescript/commonjs/src/components/theme/styleKeys.d.ts +1 -1
  230. package/lib/typescript/commonjs/src/components/theme/styleKeys.d.ts.map +1 -1
  231. package/lib/typescript/commonjs/src/components/theme/tokens.d.ts +3 -1
  232. package/lib/typescript/commonjs/src/components/theme/tokens.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/src/components/time/TimeRow.d.ts.map +1 -1
  234. package/lib/typescript/commonjs/src/components/time/TypedTime.d.ts.map +1 -1
  235. package/lib/typescript/commonjs/src/components/time/Wheel.d.ts +5 -0
  236. package/lib/typescript/commonjs/src/components/time/Wheel.d.ts.map +1 -1
  237. package/lib/typescript/commonjs/src/components/time/timeStyles.d.ts +0 -2
  238. package/lib/typescript/commonjs/src/components/time/timeStyles.d.ts.map +1 -1
  239. package/lib/typescript/commonjs/src/components/types.d.ts +84 -4
  240. package/lib/typescript/commonjs/src/components/types.d.ts.map +1 -1
  241. package/lib/typescript/commonjs/src/core/calendarSystem.d.ts +20 -5
  242. package/lib/typescript/commonjs/src/core/calendarSystem.d.ts.map +1 -1
  243. package/lib/typescript/commonjs/src/core/digits.d.ts +3 -0
  244. package/lib/typescript/commonjs/src/core/digits.d.ts.map +1 -0
  245. package/lib/typescript/commonjs/src/core/draft.d.ts +12 -1
  246. package/lib/typescript/commonjs/src/core/draft.d.ts.map +1 -1
  247. package/lib/typescript/commonjs/src/core/locale.d.ts +6 -0
  248. package/lib/typescript/commonjs/src/core/locale.d.ts.map +1 -1
  249. package/lib/typescript/commonjs/src/core/numerals.d.ts +15 -0
  250. package/lib/typescript/commonjs/src/core/numerals.d.ts.map +1 -0
  251. package/lib/typescript/commonjs/src/core/segmentEditor.d.ts.map +1 -1
  252. package/lib/typescript/commonjs/src/core/segments.d.ts +0 -2
  253. package/lib/typescript/commonjs/src/core/segments.d.ts.map +1 -1
  254. package/lib/typescript/commonjs/src/core/selectionRules.d.ts +3 -2
  255. package/lib/typescript/commonjs/src/core/selectionRules.d.ts.map +1 -1
  256. package/lib/typescript/commonjs/src/core/timeEntry.d.ts +4 -24
  257. package/lib/typescript/commonjs/src/core/timeEntry.d.ts.map +1 -1
  258. package/lib/typescript/commonjs/src/icons/index.d.ts.map +1 -1
  259. package/lib/typescript/commonjs/src/index.d.ts +7 -3
  260. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  261. package/lib/typescript/module/src/adapters/utcMidnight.d.ts.map +1 -1
  262. package/lib/typescript/module/src/components/DateTimePicker.d.ts.map +1 -1
  263. package/lib/typescript/module/src/components/calendar/Calendar.d.ts +8 -4
  264. package/lib/typescript/module/src/components/calendar/Calendar.d.ts.map +1 -1
  265. package/lib/typescript/module/src/components/calendar/CalendarHeader.d.ts.map +1 -1
  266. package/lib/typescript/module/src/components/calendar/CalendarSwitch.d.ts +26 -0
  267. package/lib/typescript/module/src/components/calendar/CalendarSwitch.d.ts.map +1 -0
  268. package/lib/typescript/module/src/components/calendar/DayCell.d.ts +1 -1
  269. package/lib/typescript/module/src/components/calendar/DayCell.d.ts.map +1 -1
  270. package/lib/typescript/module/src/components/calendar/DayGrid.d.ts +2 -0
  271. package/lib/typescript/module/src/components/calendar/DayGrid.d.ts.map +1 -1
  272. package/lib/typescript/module/src/components/calendar/PeriodGrid.d.ts.map +1 -1
  273. package/lib/typescript/module/src/components/calendar/calendarStyles.d.ts +1 -1
  274. package/lib/typescript/module/src/components/calendar/calendarStyles.d.ts.map +1 -1
  275. package/lib/typescript/module/src/components/calendar/localeNames.d.ts +8 -3
  276. package/lib/typescript/module/src/components/calendar/localeNames.d.ts.map +1 -1
  277. package/lib/typescript/module/src/components/calendar/selection.d.ts +2 -0
  278. package/lib/typescript/module/src/components/calendar/selection.d.ts.map +1 -1
  279. package/lib/typescript/module/src/components/container/DefaultSheet.d.ts +10 -2
  280. package/lib/typescript/module/src/components/container/DefaultSheet.d.ts.map +1 -1
  281. package/lib/typescript/module/src/components/container/PickerContainer.d.ts.map +1 -1
  282. package/lib/typescript/module/src/components/container/containerStyles.d.ts +6 -0
  283. package/lib/typescript/module/src/components/container/containerStyles.d.ts.map +1 -1
  284. package/lib/typescript/module/src/components/field/RangeFields.d.ts +5 -0
  285. package/lib/typescript/module/src/components/field/RangeFields.d.ts.map +1 -1
  286. package/lib/typescript/module/src/components/field/SegmentedInput.d.ts.map +1 -1
  287. package/lib/typescript/module/src/components/field/ValueField.d.ts +7 -0
  288. package/lib/typescript/module/src/components/field/ValueField.d.ts.map +1 -1
  289. package/lib/typescript/module/src/components/field/fieldStyles.d.ts +15 -0
  290. package/lib/typescript/module/src/components/field/fieldStyles.d.ts.map +1 -1
  291. package/lib/typescript/module/src/components/field/fieldText.d.ts +14 -5
  292. package/lib/typescript/module/src/components/field/fieldText.d.ts.map +1 -1
  293. package/lib/typescript/module/src/components/hooks/useBottomInset.d.ts +8 -0
  294. package/lib/typescript/module/src/components/hooks/useBottomInset.d.ts.map +1 -0
  295. package/lib/typescript/module/src/components/hooks/useKeyboardFold.d.ts +10 -2
  296. package/lib/typescript/module/src/components/hooks/useKeyboardFold.d.ts.map +1 -1
  297. package/lib/typescript/module/src/components/hooks/useOpenPicker.d.ts +2 -1
  298. package/lib/typescript/module/src/components/hooks/useOpenPicker.d.ts.map +1 -1
  299. package/lib/typescript/module/src/components/hooks/useTypedSegments.d.ts +3 -2
  300. package/lib/typescript/module/src/components/hooks/useTypedSegments.d.ts.map +1 -1
  301. package/lib/typescript/module/src/components/theme/defaultStrings.d.ts +13 -2
  302. package/lib/typescript/module/src/components/theme/defaultStrings.d.ts.map +1 -1
  303. package/lib/typescript/module/src/components/theme/direction.d.ts +8 -0
  304. package/lib/typescript/module/src/components/theme/direction.d.ts.map +1 -0
  305. package/lib/typescript/module/src/components/theme/numerals.d.ts +7 -0
  306. package/lib/typescript/module/src/components/theme/numerals.d.ts.map +1 -0
  307. package/lib/typescript/module/src/components/theme/styleKeys.d.ts +1 -1
  308. package/lib/typescript/module/src/components/theme/styleKeys.d.ts.map +1 -1
  309. package/lib/typescript/module/src/components/theme/tokens.d.ts +3 -1
  310. package/lib/typescript/module/src/components/theme/tokens.d.ts.map +1 -1
  311. package/lib/typescript/module/src/components/time/TimeRow.d.ts.map +1 -1
  312. package/lib/typescript/module/src/components/time/TypedTime.d.ts.map +1 -1
  313. package/lib/typescript/module/src/components/time/Wheel.d.ts +5 -0
  314. package/lib/typescript/module/src/components/time/Wheel.d.ts.map +1 -1
  315. package/lib/typescript/module/src/components/time/timeStyles.d.ts +0 -2
  316. package/lib/typescript/module/src/components/time/timeStyles.d.ts.map +1 -1
  317. package/lib/typescript/module/src/components/types.d.ts +84 -4
  318. package/lib/typescript/module/src/components/types.d.ts.map +1 -1
  319. package/lib/typescript/module/src/core/calendarSystem.d.ts +20 -5
  320. package/lib/typescript/module/src/core/calendarSystem.d.ts.map +1 -1
  321. package/lib/typescript/module/src/core/digits.d.ts +3 -0
  322. package/lib/typescript/module/src/core/digits.d.ts.map +1 -0
  323. package/lib/typescript/module/src/core/draft.d.ts +12 -1
  324. package/lib/typescript/module/src/core/draft.d.ts.map +1 -1
  325. package/lib/typescript/module/src/core/locale.d.ts +6 -0
  326. package/lib/typescript/module/src/core/locale.d.ts.map +1 -1
  327. package/lib/typescript/module/src/core/numerals.d.ts +15 -0
  328. package/lib/typescript/module/src/core/numerals.d.ts.map +1 -0
  329. package/lib/typescript/module/src/core/segmentEditor.d.ts.map +1 -1
  330. package/lib/typescript/module/src/core/segments.d.ts +0 -2
  331. package/lib/typescript/module/src/core/segments.d.ts.map +1 -1
  332. package/lib/typescript/module/src/core/selectionRules.d.ts +3 -2
  333. package/lib/typescript/module/src/core/selectionRules.d.ts.map +1 -1
  334. package/lib/typescript/module/src/core/timeEntry.d.ts +4 -24
  335. package/lib/typescript/module/src/core/timeEntry.d.ts.map +1 -1
  336. package/lib/typescript/module/src/icons/index.d.ts.map +1 -1
  337. package/lib/typescript/module/src/index.d.ts +7 -3
  338. package/lib/typescript/module/src/index.d.ts.map +1 -1
  339. package/package.json +22 -7
  340. package/src/adapters/utcMidnight.ts +14 -5
  341. package/src/components/DateTimePicker.tsx +607 -108
  342. package/src/components/calendar/Calendar.tsx +54 -16
  343. package/src/components/calendar/CalendarHeader.tsx +41 -9
  344. package/src/components/calendar/CalendarSwitch.tsx +170 -0
  345. package/src/components/calendar/DayCell.tsx +16 -4
  346. package/src/components/calendar/DayGrid.tsx +18 -3
  347. package/src/components/calendar/PeriodGrid.tsx +3 -1
  348. package/src/components/calendar/calendarStyles.ts +3 -2
  349. package/src/components/calendar/localeNames.ts +52 -22
  350. package/src/components/calendar/selection.ts +8 -0
  351. package/src/components/container/DefaultSheet.tsx +60 -14
  352. package/src/components/container/PickerContainer.tsx +4 -0
  353. package/src/components/container/PickerLayout.tsx +1 -1
  354. package/src/components/container/containerStyles.ts +12 -3
  355. package/src/components/field/RangeFields.tsx +12 -2
  356. package/src/components/field/SegmentedInput.tsx +8 -3
  357. package/src/components/field/ValueField.tsx +94 -18
  358. package/src/components/field/fieldStyles.ts +6 -0
  359. package/src/components/field/fieldText.ts +68 -15
  360. package/src/components/hooks/useBottomInset.ts +33 -0
  361. package/src/components/hooks/useKeyboardFold.ts +41 -13
  362. package/src/components/hooks/useOpenPicker.ts +41 -18
  363. package/src/components/hooks/useTypedSegments.ts +7 -3
  364. package/src/components/theme/defaultStrings.ts +29 -4
  365. package/src/components/theme/direction.ts +12 -0
  366. package/src/components/theme/numerals.ts +11 -0
  367. package/src/components/theme/styleKeys.ts +18 -1
  368. package/src/components/theme/tokens.ts +5 -1
  369. package/src/components/time/TimeRow.tsx +23 -3
  370. package/src/components/time/TypedTime.tsx +3 -1
  371. package/src/components/time/Wheel.tsx +19 -5
  372. package/src/components/time/timeStyles.ts +2 -3
  373. package/src/components/types.ts +86 -4
  374. package/src/core/calendarSystem.ts +145 -21
  375. package/src/core/digits.ts +21 -0
  376. package/src/core/draft.ts +41 -13
  377. package/src/core/locale.ts +20 -3
  378. package/src/core/numerals.ts +35 -0
  379. package/src/core/segmentEditor.ts +13 -0
  380. package/src/core/segments.ts +0 -8
  381. package/src/core/selectionRules.ts +3 -2
  382. package/src/core/timeEntry.ts +6 -96
  383. package/src/icons/index.tsx +3 -1
  384. package/src/index.tsx +12 -2
@@ -1,13 +1,18 @@
1
- import React, { useCallback, useMemo, useState } from 'react';
1
+ import React, {
2
+ useCallback,
3
+ useEffect,
4
+ useMemo,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
2
8
  import { AccessibilityInfo, Pressable, Text, View } from 'react-native';
3
9
  import { addDays, compareCalendarDates } from '../../core/calendarDate';
4
10
  import {
5
11
  buildSystemGrid,
6
12
  daysOfMonth,
13
+ hijriDateText,
7
14
  hijriMonthNames,
8
15
  monthSystemFor,
9
- toHijri,
10
- type CalendarSystem,
11
16
  type MonthSystem,
12
17
  type SystemMonth,
13
18
  } from '../../core/calendarSystem';
@@ -21,9 +26,13 @@ import { buildCalendarStyles } from './calendarStyles';
21
26
  import { CalendarHeader, MonthChips } from './CalendarHeader';
22
27
  import type { DayCellState } from './DayCell';
23
28
  import DayGrid from './DayGrid';
24
- import { localeNames } from './localeNames';
29
+ import { fullDateLabel, localeNames } from './localeNames';
25
30
  import PeriodGrid, { type PeriodItem } from './PeriodGrid';
26
- import { firstSelectedDay, type CalendarSelection } from './selection';
31
+ import {
32
+ firstSelectedDay,
33
+ selectedDays,
34
+ type CalendarSelection,
35
+ } from './selection';
27
36
 
28
37
  export type CalendarView = 'day' | 'month' | 'year';
29
38
 
@@ -39,8 +48,8 @@ export interface CalendarProps {
39
48
  showHolidays: boolean;
40
49
  yearRange: { first: number; last: number };
41
50
  locale: string;
42
- /** Already resolved (see resolveCalendarSystem). Default 'gregory'. */
43
- calendarSystem?: CalendarSystem;
51
+ /** The grid on screen (a dual calendar shows one of the two). Default 'gregory'. */
52
+ calendarSystem?: 'gregory' | 'hijri';
44
53
  initialView?: CalendarView;
45
54
  /** 'month' / 'year': that grid is the last step and a tap picks the period's first day. */
46
55
  precision?: 'day' | 'month' | 'year';
@@ -48,7 +57,12 @@ export interface CalendarProps {
48
57
  showToday?: boolean;
49
58
  /** Gregorian year and month of the first day shown (also in the Hijri grid). */
50
59
  onVisibleMonthChange?: (year: number, month: number) => void;
51
- /** Second line under each day (default: the Hijri day in 'dual'; none in 'hijri', which shows only the Hijri day). */
60
+ /**
61
+ * A day in the month now shown (today when it's there, else the middle), so
62
+ * the other calendar system can open on the same days.
63
+ */
64
+ onAnchorChange?: (day: CalendarDate) => void;
65
+ /** A second line under each day. None by default. */
52
66
  subLabel?: (day: CalendarDate) => string | null;
53
67
  renderDay?: (state: DayCellState, onPress: () => void) => React.ReactNode;
54
68
  renderWeekday?: (weekday: Weekday, name: string) => React.ReactNode;
@@ -162,6 +176,7 @@ const Calendar: React.FC<CalendarProps> = (props) => {
162
176
  enableMonthSwipe = true,
163
177
  showToday,
164
178
  onVisibleMonthChange,
179
+ onAnchorChange,
165
180
  subLabel,
166
181
  renderDay,
167
182
  renderWeekday,
@@ -213,10 +228,29 @@ const Calendar: React.FC<CalendarProps> = (props) => {
213
228
  );
214
229
  const start = sys.monthStart(clamped);
215
230
  onVisibleMonthChange?.(start.year, start.month);
231
+ onAnchorChange?.(
232
+ cmpMonth(sys.monthOf(today), clamped) === 0
233
+ ? today
234
+ : addDays(start, Math.min(14, sys.monthLength(clamped) - 1))
235
+ );
216
236
  },
217
- [limits, sys, names, onVisibleMonthChange]
237
+ [limits, sys, names, today, onVisibleMonthChange, onAnchorChange]
218
238
  );
219
239
 
240
+ // A day newly picked outside the month on screen (typed in the field, say)
241
+ // brings the calendar to its month; picks in the month shown leave it be.
242
+ const dayKey = (d: CalendarDate) => `${d.year}-${d.month}-${d.day}`;
243
+ const shownPicks = useRef(new Set(selectedDays(selection).map(dayKey)));
244
+ useEffect(() => {
245
+ const days = selectedDays(selection);
246
+ const fresh = days.filter((d) => !shownPicks.current.has(dayKey(d)));
247
+ shownPicks.current = new Set(days.map(dayKey));
248
+ const last = fresh[fresh.length - 1];
249
+ if (last && cmpMonth(sys.monthOf(last), visible) !== 0)
250
+ goTo(sys.monthOf(last));
251
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- when the selection changes
252
+ }, [selection]);
253
+
220
254
  // A tap on a day of the previous / next month (the muted outside days) selects it
221
255
  // and moves the calendar to that month.
222
256
  const selectDay = useCallback(
@@ -228,12 +262,15 @@ const Calendar: React.FC<CalendarProps> = (props) => {
228
262
  [sys, visible, goTo, onSelectDay]
229
263
  );
230
264
 
231
- const subLabelFor = useMemo(() => {
232
- if (subLabel) return subLabel;
233
- if (calendarSystem === 'dual')
234
- return (d: CalendarDate) => String(toHijri(d)?.day ?? '');
235
- return undefined;
236
- }, [subLabel, calendarSystem]);
265
+ // Screen readers hear a Hijri grid's days as Hijri dates.
266
+ const dateLabel = useMemo(
267
+ () =>
268
+ sys.kind === 'hijri'
269
+ ? (day: CalendarDate) =>
270
+ hijriDateText(day, locale) ?? fullDateLabel(locale, day)
271
+ : undefined,
272
+ [sys, locale]
273
+ );
237
274
 
238
275
  const { min, max } = constraints.range;
239
276
  const prevMonth = sys.addMonths(visible, -1);
@@ -445,6 +482,7 @@ const Calendar: React.FC<CalendarProps> = (props) => {
445
482
  selection={selection}
446
483
  constraints={constraints}
447
484
  locale={locale}
485
+ dateLabel={dateLabel}
448
486
  onSelectDay={selectDay}
449
487
  onSwipe={
450
488
  enableMonthSwipe
@@ -454,7 +492,7 @@ const Calendar: React.FC<CalendarProps> = (props) => {
454
492
  }
455
493
  : undefined
456
494
  }
457
- subLabel={subLabelFor}
495
+ subLabel={subLabel}
458
496
  renderDay={renderDay}
459
497
  renderWeekday={renderWeekday}
460
498
  tokens={tokens}
@@ -1,6 +1,5 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import {
3
- I18nManager,
4
3
  Pressable,
5
4
  ScrollView,
6
5
  Text,
@@ -18,6 +17,8 @@ import {
18
17
  import type { PickerStrings } from '../theme/defaultStrings';
19
18
  import type { PickerStyles } from '../theme/styleKeys';
20
19
  import { MAX_FONT_SCALE } from '../theme/a11y';
20
+ import { useIsRTL } from '../theme/direction';
21
+ import { useNumerals } from '../theme/numerals';
21
22
  import type { ThemeTokens } from '../theme/tokens';
22
23
  import { useReduceMotion } from '../hooks/useReduceMotion';
23
24
  import { buildCalendarStyles } from './calendarStyles';
@@ -58,6 +59,8 @@ export const CalendarHeader: React.FC<HeaderProps> = ({
58
59
  styles,
59
60
  testID,
60
61
  }) => {
62
+ const digits = useNumerals();
63
+ const isRTL = useIsRTL();
61
64
  const s = buildCalendarStyles(tokens);
62
65
  const ico = resolveIcons(icons);
63
66
  const arrow = (
@@ -67,7 +70,7 @@ export const CalendarHeader: React.FC<HeaderProps> = ({
67
70
  label: string
68
71
  ) => {
69
72
  // Chevrons point in the reading direction; mirrored in right-to-left layouts.
70
- const pointsLeft = (dir === 'prev') !== I18nManager.isRTL;
73
+ const pointsLeft = (dir === 'prev') !== isRTL;
71
74
  const chevron = pointsLeft ? 'chevronLeft' : 'chevronRight';
72
75
  return (
73
76
  <Pressable
@@ -113,7 +116,7 @@ export const CalendarHeader: React.FC<HeaderProps> = ({
113
116
  maxFontSizeMultiplier={MAX_FONT_SCALE}
114
117
  style={[s.yearButtonText, styles?.yearButtonText]}
115
118
  >
116
- {title}
119
+ {digits(title)}
117
120
  </Text>
118
121
  <View style={s.caret}>
119
122
  {renderIcon(
@@ -164,15 +167,26 @@ export const MonthChips: React.FC<ChipsProps> = ({
164
167
  // the selected one is scrolled to the middle of the row.
165
168
  const chips = useRef<Record<number, { x: number; width: number }>>({});
166
169
  const viewport = useRef(0);
167
- const scrollToSelected = (animated: boolean) => {
170
+ const content = useRef(0);
171
+ // Until the row is dragged or the month changes, the selected chip is held
172
+ // in view: Android moves a right-to-left row to its end after the first
173
+ // layout, which undoes the first scroll.
174
+ const holding = useRef(true);
175
+ const first = useRef(true);
176
+ const selectedOffset = (): number | null => {
168
177
  const chip = chips.current[selectedMonth];
169
- if (!chip || !viewport.current) return;
170
- ref.current?.scrollTo({
171
- x: Math.max(0, chip.x - (viewport.current - chip.width) / 2),
172
- animated,
173
- });
178
+ if (!chip || !viewport.current) return null;
179
+ const centred = chip.x - (viewport.current - chip.width) / 2;
180
+ const end = Math.max(0, content.current - viewport.current);
181
+ return Math.max(0, content.current ? Math.min(centred, end) : centred);
182
+ };
183
+ const scrollToSelected = (animated: boolean) => {
184
+ const x = selectedOffset();
185
+ if (x !== null) ref.current?.scrollTo({ x, animated });
174
186
  };
175
187
  useEffect(() => {
188
+ if (first.current) first.current = false;
189
+ else holding.current = false;
176
190
  scrollToSelected(!reduceMotion);
177
191
  // eslint-disable-next-line react-hooks/exhaustive-deps -- scrolls only when the month changes
178
192
  }, [selectedMonth]);
@@ -194,6 +208,20 @@ export const MonthChips: React.FC<ChipsProps> = ({
194
208
  viewport.current = e.nativeEvent.layout.width;
195
209
  scrollToSelected(false);
196
210
  }}
211
+ onContentSizeChange={(width) => {
212
+ content.current = width;
213
+ if (holding.current) scrollToSelected(false);
214
+ }}
215
+ scrollEventThrottle={16}
216
+ onScroll={(e) => {
217
+ if (!holding.current) return;
218
+ const x = selectedOffset();
219
+ if (x !== null && Math.abs(e.nativeEvent.contentOffset.x - x) > 1)
220
+ ref.current?.scrollTo({ x, animated: false });
221
+ }}
222
+ onScrollBeginDrag={() => {
223
+ holding.current = false;
224
+ }}
197
225
  >
198
226
  {names.map((name, i) => {
199
227
  const month = i + 1;
@@ -203,6 +231,10 @@ export const MonthChips: React.FC<ChipsProps> = ({
203
231
  return (
204
232
  <Pressable
205
233
  key={month}
234
+ testID={testID ? `${testID}-chip-${month}` : undefined}
235
+ accessibilityRole="button"
236
+ accessibilityLabel={fullNames[i]}
237
+ accessibilityState={{ selected, disabled }}
206
238
  disabled={disabled}
207
239
  onPress={() => onSelect(month)}
208
240
  onLayout={onChipLayout(month)}
@@ -0,0 +1,170 @@
1
+ import React from 'react';
2
+ import { Pressable, StyleSheet, Text, View } from 'react-native';
3
+ import { MAX_FONT_SCALE } from '../theme/a11y';
4
+ import type { PickerStyles } from '../theme/styleKeys';
5
+ import { fontStyle, type ThemeTokens } from '../theme/tokens';
6
+
7
+ export interface SegmentOption<T extends string> {
8
+ value: T;
9
+ label: string;
10
+ }
11
+
12
+ interface Props<T extends string> {
13
+ /** 'switch': segments in a track (the calendar switch). 'tabs': underlined tabs (a dual calendar's). */
14
+ variant: 'switch' | 'tabs';
15
+ options: SegmentOption<T>[];
16
+ selected: T;
17
+ onSelect: (value: T) => void;
18
+ accessibilityLabel: string;
19
+ tokens: ThemeTokens;
20
+ styles?: PickerStyles;
21
+ testID?: string;
22
+ }
23
+
24
+ const KEYS = {
25
+ switch: {
26
+ box: 'calendarSwitch',
27
+ item: 'calendarSwitchSegment',
28
+ itemSelected: 'calendarSwitchSegmentSelected',
29
+ text: 'calendarSwitchText',
30
+ textSelected: 'calendarSwitchTextSelected',
31
+ },
32
+ tabs: {
33
+ box: 'dualTabs',
34
+ item: 'dualTab',
35
+ itemSelected: 'dualTabSelected',
36
+ text: 'dualTabText',
37
+ textSelected: 'dualTabTextSelected',
38
+ },
39
+ } as const;
40
+
41
+ const cache = new WeakMap<ThemeTokens, ReturnType<typeof create>>();
42
+
43
+ const create = (t: ThemeTokens) =>
44
+ StyleSheet.create({
45
+ switch: {
46
+ flexDirection: 'row',
47
+ padding: 4,
48
+ gap: 4,
49
+ marginTop: 12,
50
+ borderRadius: t.radius,
51
+ backgroundColor: t.toggleTrack,
52
+ },
53
+ switchItem: {
54
+ flex: 1,
55
+ minHeight: t.touchTarget - 8,
56
+ paddingHorizontal: 8,
57
+ alignItems: 'center',
58
+ justifyContent: 'center',
59
+ borderRadius: Math.max(0, t.radius - 2),
60
+ },
61
+ switchItemSelected: { backgroundColor: t.accent },
62
+ switchText: {
63
+ ...fontStyle(t, 'medium'),
64
+ fontSize: t.fontSizeMedium,
65
+ color: t.text,
66
+ },
67
+ switchTextSelected: { color: t.onAccent },
68
+ tabs: {
69
+ flexDirection: 'row',
70
+ marginTop: 8,
71
+ borderBottomWidth: StyleSheet.hairlineWidth,
72
+ borderBottomColor: t.separator,
73
+ },
74
+ tabsItem: {
75
+ flex: 1,
76
+ minHeight: t.touchTarget,
77
+ paddingHorizontal: 8,
78
+ alignItems: 'center',
79
+ justifyContent: 'center',
80
+ borderBottomWidth: 2,
81
+ borderBottomColor: 'transparent',
82
+ },
83
+ tabsItemSelected: { borderBottomColor: t.accent },
84
+ tabsText: {
85
+ ...fontStyle(t, 'medium'),
86
+ fontSize: t.fontSizeMedium,
87
+ color: t.mutedText,
88
+ },
89
+ tabsTextSelected: { ...fontStyle(t, 'semiBold'), color: t.accent },
90
+ });
91
+
92
+ const stylesFor = (t: ThemeTokens) => {
93
+ let s = cache.get(t);
94
+ if (!s) {
95
+ s = create(t);
96
+ cache.set(t, s);
97
+ }
98
+ return s;
99
+ };
100
+
101
+ /**
102
+ * One row of choices, one of them selected: the Gregorian / Hijri / Dual
103
+ * switch above the calendar, and the Gregorian / Hijri tabs of a dual calendar.
104
+ * Each part takes its own key from the `styles` prop.
105
+ */
106
+ const CalendarSwitch = <T extends string>({
107
+ variant,
108
+ options,
109
+ selected,
110
+ onSelect,
111
+ accessibilityLabel,
112
+ tokens,
113
+ styles,
114
+ testID,
115
+ }: Props<T>): React.ReactElement => {
116
+ const s = stylesFor(tokens);
117
+ const keys = KEYS[variant];
118
+ const own = {
119
+ box: variant === 'switch' ? s.switch : s.tabs,
120
+ item: variant === 'switch' ? s.switchItem : s.tabsItem,
121
+ itemSelected:
122
+ variant === 'switch' ? s.switchItemSelected : s.tabsItemSelected,
123
+ text: variant === 'switch' ? s.switchText : s.tabsText,
124
+ textSelected:
125
+ variant === 'switch' ? s.switchTextSelected : s.tabsTextSelected,
126
+ };
127
+ const tabs = variant === 'tabs';
128
+ return (
129
+ <View
130
+ style={[own.box, styles?.[keys.box]]}
131
+ accessibilityRole={tabs ? 'tablist' : 'radiogroup'}
132
+ accessibilityLabel={accessibilityLabel}
133
+ testID={testID}
134
+ >
135
+ {options.map((option) => {
136
+ const on = option.value === selected;
137
+ return (
138
+ <Pressable
139
+ key={option.value}
140
+ testID={testID ? `${testID}-${option.value}` : undefined}
141
+ accessibilityRole={tabs ? 'tab' : 'radio'}
142
+ accessibilityState={tabs ? { selected: on } : { checked: on }}
143
+ onPress={() => {
144
+ if (!on) onSelect(option.value);
145
+ }}
146
+ style={[
147
+ own.item,
148
+ styles?.[keys.item],
149
+ on && [own.itemSelected, styles?.[keys.itemSelected]],
150
+ ]}
151
+ >
152
+ <Text
153
+ numberOfLines={1}
154
+ maxFontSizeMultiplier={MAX_FONT_SCALE}
155
+ style={[
156
+ own.text,
157
+ styles?.[keys.text],
158
+ on && [own.textSelected, styles?.[keys.textSelected]],
159
+ ]}
160
+ >
161
+ {option.label}
162
+ </Text>
163
+ </Pressable>
164
+ );
165
+ })}
166
+ </View>
167
+ );
168
+ };
169
+
170
+ export default CalendarSwitch;
@@ -1,8 +1,10 @@
1
1
  import React, { memo } from 'react';
2
2
  import { Pressable, Text, View } from 'react-native';
3
+ import { isSameDay } from '../../core/calendarDate';
3
4
  import type { CalendarDate } from '../../core/types';
4
5
  import type { PickerStyles } from '../theme/styleKeys';
5
6
  import { DAY_HIT_SLOP, MAX_FONT_SCALE } from '../theme/a11y';
7
+ import { useNumerals } from '../theme/numerals';
6
8
  import type { ThemeTokens } from '../theme/tokens';
7
9
  import { buildCalendarStyles } from './calendarStyles';
8
10
 
@@ -19,7 +21,7 @@ export interface DayCellState {
19
21
  rangeRole: RangeRole;
20
22
  /** The number to show, when it isn't the Gregorian day (Hijri grid). */
21
23
  label?: number;
22
- /** Second line under the day number (Hijri day in 'dual' mode). */
24
+ /** A second line under the day number. Null unless a `subLabel` is given. */
23
25
  subLabel?: string | null;
24
26
  a11yLabel: string;
25
27
  }
@@ -54,6 +56,7 @@ const DayCell: React.FC<Props> = ({
54
56
  styles,
55
57
  testID,
56
58
  }) => {
59
+ const digits = useNumerals();
57
60
  const s = buildCalendarStyles(tokens);
58
61
  const filled =
59
62
  isSelected &&
@@ -109,14 +112,14 @@ const DayCell: React.FC<Props> = ({
109
112
  filled && [s.selectedText, styles?.selectedText],
110
113
  ]}
111
114
  >
112
- {label ?? date.day}
115
+ {digits(String(label ?? date.day))}
113
116
  </Text>
114
117
  {subLabel ? (
115
118
  <Text
116
119
  maxFontSizeMultiplier={MAX_FONT_SCALE}
117
120
  style={[s.subLabel, styles?.daySubLabel, filled && s.selectedText]}
118
121
  >
119
- {subLabel}
122
+ {digits(subLabel)}
120
123
  </Text>
121
124
  ) : null}
122
125
  </Pressable>
@@ -124,4 +127,13 @@ const DayCell: React.FC<Props> = ({
124
127
  );
125
128
  };
126
129
 
127
- export default memo(DayCell);
130
+ // A Hijri grid builds new day objects on each render, so days compare by value.
131
+ export default memo(
132
+ DayCell,
133
+ (prev, next) =>
134
+ (Object.keys(next) as (keyof Props)[]).every((key) =>
135
+ key === 'date'
136
+ ? isSameDay(prev.date, next.date)
137
+ : Object.is(prev[key], next[key])
138
+ ) && Object.keys(prev).length === Object.keys(next).length
139
+ );
@@ -1,5 +1,5 @@
1
1
  import React, { useMemo, useRef } from 'react';
2
- import { I18nManager, PanResponder, Text, View } from 'react-native';
2
+ import { PanResponder, Text, View } from 'react-native';
3
3
  import type { Constraints } from '../../core/constraints';
4
4
  import { isSameDay } from '../../core/calendarDate';
5
5
  import { buildMonthGrid, weekdayOrder } from '../../core/monthGrid';
@@ -7,6 +7,7 @@ import type { CalendarDate, Weekday } from '../../core/types';
7
7
  import type { PickerStrings } from '../theme/defaultStrings';
8
8
  import type { PickerStyles } from '../theme/styleKeys';
9
9
  import { MAX_FONT_SCALE } from '../theme/a11y';
10
+ import { useIsRTL } from '../theme/direction';
10
11
  import type { ThemeTokens } from '../theme/tokens';
11
12
  import { buildCalendarStyles } from './calendarStyles';
12
13
  import DayCell, { type DayCellState } from './DayCell';
@@ -30,6 +31,8 @@ export interface DayGridProps {
30
31
  selection: CalendarSelection;
31
32
  constraints: Constraints;
32
33
  locale: string;
34
+ /** What a screen reader says for a day. Default: the Gregorian date in `locale`. */
35
+ dateLabel?: (day: CalendarDate) => string;
33
36
  onSelectDay: (day: CalendarDate) => void;
34
37
  /** Swipe left / right to change month. */
35
38
  onSwipe?: (step: 1 | -1) => void;
@@ -66,6 +69,7 @@ const DayGrid: React.FC<DayGridProps> = ({
66
69
  selection,
67
70
  constraints,
68
71
  locale,
72
+ dateLabel,
69
73
  onSelectDay,
70
74
  onSwipe,
71
75
  subLabel,
@@ -81,13 +85,22 @@ const DayGrid: React.FC<DayGridProps> = ({
81
85
 
82
86
  const onSwipeRef = useRef(onSwipe);
83
87
  onSwipeRef.current = onSwipe;
88
+ const isRTLRef = useRef(false);
89
+ isRTLRef.current = useIsRTL();
84
90
  const pan = useMemo(
85
91
  () =>
86
92
  PanResponder.create({
93
+ // A touch no day takes (a greyed day, a gap) is the grid's from the start,
94
+ // so a swipe that begins there still changes month. A day that can be
95
+ // picked is asked first and keeps its tap.
96
+ onStartShouldSetPanResponder: () => !!onSwipeRef.current,
87
97
  onMoveShouldSetPanResponder: (_, g) =>
88
98
  !!onSwipeRef.current && isSwipeStart(g.dx, g.dy),
99
+ // Android: let the sheet's ScrollView take a vertical drag that starts
100
+ // on the grid (PanResponder blocks native views by default).
101
+ onShouldBlockNativeResponder: () => false,
89
102
  onPanResponderRelease: (_, g) => {
90
- const step = swipeStep(g.dx, I18nManager.isRTL);
103
+ const step = swipeStep(g.dx, isRTLRef.current);
91
104
  if (step !== 0) onSwipeRef.current?.(step);
92
105
  },
93
106
  }),
@@ -103,7 +116,9 @@ const DayGrid: React.FC<DayGridProps> = ({
103
116
  const isToday = isSameDay(cell.date, today);
104
117
  // Selected and unavailable are announced from the cell's state, so the
105
118
  // label only adds what the state can't say.
106
- const parts = [fullDateLabel(locale, cell.date)];
119
+ const parts = [
120
+ dateLabel ? dateLabel(cell.date) : fullDateLabel(locale, cell.date),
121
+ ];
107
122
  if (isToday) parts.push(strings.a11yToday);
108
123
  if (role === 'start') parts.push(strings.a11yRangeStart);
109
124
  if (role === 'end') parts.push(strings.a11yRangeEnd);
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { Pressable, Text, View } from 'react-native';
3
3
  import type { PickerStyles, StyleKey } from '../theme/styleKeys';
4
4
  import { MAX_FONT_SCALE } from '../theme/a11y';
5
+ import { useNumerals } from '../theme/numerals';
5
6
  import type { ThemeTokens } from '../theme/tokens';
6
7
  import { buildCalendarStyles } from './calendarStyles';
7
8
 
@@ -64,6 +65,7 @@ const PeriodGrid: React.FC<Props> = ({
64
65
  styles,
65
66
  testID,
66
67
  }) => {
68
+ const digits = useNumerals();
67
69
  const s = buildCalendarStyles(tokens);
68
70
  const k = KEYS[kind];
69
71
  return (
@@ -101,7 +103,7 @@ const PeriodGrid: React.FC<Props> = ({
101
103
  item.selected && s.gridSelectedText,
102
104
  ]}
103
105
  >
104
- {item.label}
106
+ {digits(item.label)}
105
107
  </Text>
106
108
  )}
107
109
  </Pressable>
@@ -99,11 +99,12 @@ const create = (t: ThemeTokens) =>
99
99
  today: { borderWidth: 1, borderColor: t.accent },
100
100
  selected: { backgroundColor: t.accent },
101
101
  selectedText: { color: t.onAccent, ...fontStyle(t, 'semiBold') },
102
- outsideText: { color: t.placeholder },
102
+ outsideText: { color: t.outsideText ?? t.mutedText },
103
103
  disabledText: { color: t.disabledText },
104
104
  holidayText: { color: t.holiday },
105
105
  pressed: { backgroundColor: t.rangeFill },
106
- grid: { flexDirection: 'row', flexWrap: 'wrap', paddingVertical: 8 },
106
+ // No top padding: the header's margin and the cell padding already space the first row.
107
+ grid: { flexDirection: 'row', flexWrap: 'wrap', paddingBottom: 8 },
107
108
  gridCell: { width: '33.33%', padding: 6 },
108
109
  gridButton: {
109
110
  minHeight: t.touchTarget,