rn-grid-date-time-picker 1.0.0 → 1.1.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 (353) hide show
  1. package/CHANGELOG.md +61 -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 +444 -82
  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 +43 -5
  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 +9 -1
  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 +1 -1
  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 +3 -1
  34. package/lib/commonjs/components/field/RangeFields.js.map +1 -1
  35. package/lib/commonjs/components/field/SegmentedInput.js +7 -2
  36. package/lib/commonjs/components/field/SegmentedInput.js.map +1 -1
  37. package/lib/commonjs/components/field/ValueField.js +8 -4
  38. package/lib/commonjs/components/field/ValueField.js.map +1 -1
  39. package/lib/commonjs/components/field/fieldText.js +19 -12
  40. package/lib/commonjs/components/field/fieldText.js.map +1 -1
  41. package/lib/commonjs/components/hooks/useBottomInset.js +32 -0
  42. package/lib/commonjs/components/hooks/useBottomInset.js.map +1 -0
  43. package/lib/commonjs/components/hooks/useKeyboardFold.js +36 -13
  44. package/lib/commonjs/components/hooks/useKeyboardFold.js.map +1 -1
  45. package/lib/commonjs/components/hooks/useOpenPicker.js +39 -17
  46. package/lib/commonjs/components/hooks/useOpenPicker.js.map +1 -1
  47. package/lib/commonjs/components/hooks/useTypedSegments.js +6 -2
  48. package/lib/commonjs/components/hooks/useTypedSegments.js.map +1 -1
  49. package/lib/commonjs/components/theme/defaultStrings.js +7 -1
  50. package/lib/commonjs/components/theme/defaultStrings.js.map +1 -1
  51. package/lib/commonjs/components/theme/numerals.js +16 -0
  52. package/lib/commonjs/components/theme/numerals.js.map +1 -0
  53. package/lib/commonjs/components/theme/styleKeys.js +4 -1
  54. package/lib/commonjs/components/theme/styleKeys.js.map +1 -1
  55. package/lib/commonjs/components/theme/tokens.js +4 -0
  56. package/lib/commonjs/components/theme/tokens.js.map +1 -1
  57. package/lib/commonjs/components/time/TimeRow.js +10 -2
  58. package/lib/commonjs/components/time/TimeRow.js.map +1 -1
  59. package/lib/commonjs/components/time/TypedTime.js +3 -1
  60. package/lib/commonjs/components/time/TypedTime.js.map +1 -1
  61. package/lib/commonjs/components/time/Wheel.js +20 -3
  62. package/lib/commonjs/components/time/Wheel.js.map +1 -1
  63. package/lib/commonjs/components/types.js +10 -0
  64. package/lib/commonjs/components/types.js.map +1 -1
  65. package/lib/commonjs/core/calendarSystem.js +85 -22
  66. package/lib/commonjs/core/calendarSystem.js.map +1 -1
  67. package/lib/commonjs/core/digits.js +25 -0
  68. package/lib/commonjs/core/digits.js.map +1 -0
  69. package/lib/commonjs/core/draft.js +31 -10
  70. package/lib/commonjs/core/draft.js.map +1 -1
  71. package/lib/commonjs/core/locale.js +20 -4
  72. package/lib/commonjs/core/locale.js.map +1 -1
  73. package/lib/commonjs/core/numerals.js +46 -0
  74. package/lib/commonjs/core/numerals.js.map +1 -0
  75. package/lib/commonjs/core/segmentEditor.js +9 -0
  76. package/lib/commonjs/core/segmentEditor.js.map +1 -1
  77. package/lib/commonjs/core/segments.js +2 -11
  78. package/lib/commonjs/core/segments.js.map +1 -1
  79. package/lib/commonjs/core/selectionRules.js +2 -1
  80. package/lib/commonjs/core/selectionRules.js.map +1 -1
  81. package/lib/commonjs/core/timeEntry.js +7 -91
  82. package/lib/commonjs/core/timeEntry.js.map +1 -1
  83. package/lib/commonjs/icons/index.js +5 -1
  84. package/lib/commonjs/icons/index.js.map +1 -1
  85. package/lib/commonjs/index.js +14 -0
  86. package/lib/commonjs/index.js.map +1 -1
  87. package/lib/module/adapters/utcMidnight.js +14 -5
  88. package/lib/module/adapters/utcMidnight.js.map +1 -1
  89. package/lib/module/components/DateTimePicker.js +450 -88
  90. package/lib/module/components/DateTimePicker.js.map +1 -1
  91. package/lib/module/components/calendar/Calendar.js +25 -11
  92. package/lib/module/components/calendar/Calendar.js.map +1 -1
  93. package/lib/module/components/calendar/CalendarHeader.js +43 -5
  94. package/lib/module/components/calendar/CalendarHeader.js.map +1 -1
  95. package/lib/module/components/calendar/CalendarSwitch.js +145 -0
  96. package/lib/module/components/calendar/CalendarSwitch.js.map +1 -0
  97. package/lib/module/components/calendar/DayCell.js +8 -3
  98. package/lib/module/components/calendar/DayCell.js.map +1 -1
  99. package/lib/module/components/calendar/DayGrid.js +9 -1
  100. package/lib/module/components/calendar/DayGrid.js.map +1 -1
  101. package/lib/module/components/calendar/PeriodGrid.js +3 -1
  102. package/lib/module/components/calendar/PeriodGrid.js.map +1 -1
  103. package/lib/module/components/calendar/calendarStyles.js +1 -1
  104. package/lib/module/components/calendar/calendarStyles.js.map +1 -1
  105. package/lib/module/components/calendar/localeNames.js +46 -24
  106. package/lib/module/components/calendar/localeNames.js.map +1 -1
  107. package/lib/module/components/calendar/selection.js +7 -0
  108. package/lib/module/components/calendar/selection.js.map +1 -1
  109. package/lib/module/components/container/DefaultSheet.js +42 -12
  110. package/lib/module/components/container/DefaultSheet.js.map +1 -1
  111. package/lib/module/components/container/PickerContainer.js +4 -0
  112. package/lib/module/components/container/PickerContainer.js.map +1 -1
  113. package/lib/module/components/container/PickerLayout.js +1 -1
  114. package/lib/module/components/container/PickerLayout.js.map +1 -1
  115. package/lib/module/components/container/containerStyles.js +11 -3
  116. package/lib/module/components/container/containerStyles.js.map +1 -1
  117. package/lib/module/components/field/RangeFields.js +3 -1
  118. package/lib/module/components/field/RangeFields.js.map +1 -1
  119. package/lib/module/components/field/SegmentedInput.js +7 -2
  120. package/lib/module/components/field/SegmentedInput.js.map +1 -1
  121. package/lib/module/components/field/ValueField.js +8 -4
  122. package/lib/module/components/field/ValueField.js.map +1 -1
  123. package/lib/module/components/field/fieldText.js +20 -11
  124. package/lib/module/components/field/fieldText.js.map +1 -1
  125. package/lib/module/components/hooks/useBottomInset.js +27 -0
  126. package/lib/module/components/hooks/useBottomInset.js.map +1 -0
  127. package/lib/module/components/hooks/useKeyboardFold.js +33 -12
  128. package/lib/module/components/hooks/useKeyboardFold.js.map +1 -1
  129. package/lib/module/components/hooks/useOpenPicker.js +39 -17
  130. package/lib/module/components/hooks/useOpenPicker.js.map +1 -1
  131. package/lib/module/components/hooks/useTypedSegments.js +6 -2
  132. package/lib/module/components/hooks/useTypedSegments.js.map +1 -1
  133. package/lib/module/components/theme/defaultStrings.js +7 -1
  134. package/lib/module/components/theme/defaultStrings.js.map +1 -1
  135. package/lib/module/components/theme/numerals.js +12 -0
  136. package/lib/module/components/theme/numerals.js.map +1 -0
  137. package/lib/module/components/theme/styleKeys.js +4 -1
  138. package/lib/module/components/theme/styleKeys.js.map +1 -1
  139. package/lib/module/components/theme/tokens.js +4 -0
  140. package/lib/module/components/theme/tokens.js.map +1 -1
  141. package/lib/module/components/time/TimeRow.js +11 -3
  142. package/lib/module/components/time/TimeRow.js.map +1 -1
  143. package/lib/module/components/time/TypedTime.js +3 -1
  144. package/lib/module/components/time/TypedTime.js.map +1 -1
  145. package/lib/module/components/time/Wheel.js +18 -2
  146. package/lib/module/components/time/Wheel.js.map +1 -1
  147. package/lib/module/components/types.js +10 -0
  148. package/lib/module/components/types.js.map +1 -1
  149. package/lib/module/core/calendarSystem.js +81 -19
  150. package/lib/module/core/calendarSystem.js.map +1 -1
  151. package/lib/module/core/digits.js +20 -0
  152. package/lib/module/core/digits.js.map +1 -0
  153. package/lib/module/core/draft.js +29 -9
  154. package/lib/module/core/draft.js.map +1 -1
  155. package/lib/module/core/locale.js +18 -3
  156. package/lib/module/core/locale.js.map +1 -1
  157. package/lib/module/core/numerals.js +39 -0
  158. package/lib/module/core/numerals.js.map +1 -0
  159. package/lib/module/core/segmentEditor.js +9 -0
  160. package/lib/module/core/segmentEditor.js.map +1 -1
  161. package/lib/module/core/segments.js +0 -8
  162. package/lib/module/core/segments.js.map +1 -1
  163. package/lib/module/core/selectionRules.js +2 -1
  164. package/lib/module/core/selectionRules.js.map +1 -1
  165. package/lib/module/core/timeEntry.js +7 -89
  166. package/lib/module/core/timeEntry.js.map +1 -1
  167. package/lib/module/icons/index.js +5 -1
  168. package/lib/module/icons/index.js.map +1 -1
  169. package/lib/module/index.js +2 -0
  170. package/lib/module/index.js.map +1 -1
  171. package/lib/typescript/commonjs/src/adapters/utcMidnight.d.ts.map +1 -1
  172. package/lib/typescript/commonjs/src/components/DateTimePicker.d.ts.map +1 -1
  173. package/lib/typescript/commonjs/src/components/calendar/Calendar.d.ts +8 -4
  174. package/lib/typescript/commonjs/src/components/calendar/Calendar.d.ts.map +1 -1
  175. package/lib/typescript/commonjs/src/components/calendar/CalendarHeader.d.ts.map +1 -1
  176. package/lib/typescript/commonjs/src/components/calendar/CalendarSwitch.d.ts +26 -0
  177. package/lib/typescript/commonjs/src/components/calendar/CalendarSwitch.d.ts.map +1 -0
  178. package/lib/typescript/commonjs/src/components/calendar/DayCell.d.ts +1 -1
  179. package/lib/typescript/commonjs/src/components/calendar/DayCell.d.ts.map +1 -1
  180. package/lib/typescript/commonjs/src/components/calendar/DayGrid.d.ts +2 -0
  181. package/lib/typescript/commonjs/src/components/calendar/DayGrid.d.ts.map +1 -1
  182. package/lib/typescript/commonjs/src/components/calendar/PeriodGrid.d.ts.map +1 -1
  183. package/lib/typescript/commonjs/src/components/calendar/localeNames.d.ts +8 -3
  184. package/lib/typescript/commonjs/src/components/calendar/localeNames.d.ts.map +1 -1
  185. package/lib/typescript/commonjs/src/components/calendar/selection.d.ts +2 -0
  186. package/lib/typescript/commonjs/src/components/calendar/selection.d.ts.map +1 -1
  187. package/lib/typescript/commonjs/src/components/container/DefaultSheet.d.ts +10 -2
  188. package/lib/typescript/commonjs/src/components/container/DefaultSheet.d.ts.map +1 -1
  189. package/lib/typescript/commonjs/src/components/container/PickerContainer.d.ts.map +1 -1
  190. package/lib/typescript/commonjs/src/components/container/containerStyles.d.ts +6 -0
  191. package/lib/typescript/commonjs/src/components/container/containerStyles.d.ts.map +1 -1
  192. package/lib/typescript/commonjs/src/components/field/RangeFields.d.ts +3 -0
  193. package/lib/typescript/commonjs/src/components/field/RangeFields.d.ts.map +1 -1
  194. package/lib/typescript/commonjs/src/components/field/SegmentedInput.d.ts.map +1 -1
  195. package/lib/typescript/commonjs/src/components/field/ValueField.d.ts +3 -0
  196. package/lib/typescript/commonjs/src/components/field/ValueField.d.ts.map +1 -1
  197. package/lib/typescript/commonjs/src/components/field/fieldText.d.ts +9 -5
  198. package/lib/typescript/commonjs/src/components/field/fieldText.d.ts.map +1 -1
  199. package/lib/typescript/commonjs/src/components/hooks/useBottomInset.d.ts +8 -0
  200. package/lib/typescript/commonjs/src/components/hooks/useBottomInset.d.ts.map +1 -0
  201. package/lib/typescript/commonjs/src/components/hooks/useKeyboardFold.d.ts +10 -2
  202. package/lib/typescript/commonjs/src/components/hooks/useKeyboardFold.d.ts.map +1 -1
  203. package/lib/typescript/commonjs/src/components/hooks/useOpenPicker.d.ts +2 -1
  204. package/lib/typescript/commonjs/src/components/hooks/useOpenPicker.d.ts.map +1 -1
  205. package/lib/typescript/commonjs/src/components/hooks/useTypedSegments.d.ts +3 -2
  206. package/lib/typescript/commonjs/src/components/hooks/useTypedSegments.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/src/components/theme/defaultStrings.d.ts +11 -2
  208. package/lib/typescript/commonjs/src/components/theme/defaultStrings.d.ts.map +1 -1
  209. package/lib/typescript/commonjs/src/components/theme/numerals.d.ts +7 -0
  210. package/lib/typescript/commonjs/src/components/theme/numerals.d.ts.map +1 -0
  211. package/lib/typescript/commonjs/src/components/theme/styleKeys.d.ts +1 -1
  212. package/lib/typescript/commonjs/src/components/theme/styleKeys.d.ts.map +1 -1
  213. package/lib/typescript/commonjs/src/components/theme/tokens.d.ts +3 -1
  214. package/lib/typescript/commonjs/src/components/theme/tokens.d.ts.map +1 -1
  215. package/lib/typescript/commonjs/src/components/time/TimeRow.d.ts.map +1 -1
  216. package/lib/typescript/commonjs/src/components/time/TypedTime.d.ts.map +1 -1
  217. package/lib/typescript/commonjs/src/components/time/Wheel.d.ts +5 -0
  218. package/lib/typescript/commonjs/src/components/time/Wheel.d.ts.map +1 -1
  219. package/lib/typescript/commonjs/src/components/types.d.ts +77 -4
  220. package/lib/typescript/commonjs/src/components/types.d.ts.map +1 -1
  221. package/lib/typescript/commonjs/src/core/calendarSystem.d.ts +10 -5
  222. package/lib/typescript/commonjs/src/core/calendarSystem.d.ts.map +1 -1
  223. package/lib/typescript/commonjs/src/core/digits.d.ts +3 -0
  224. package/lib/typescript/commonjs/src/core/digits.d.ts.map +1 -0
  225. package/lib/typescript/commonjs/src/core/draft.d.ts +12 -1
  226. package/lib/typescript/commonjs/src/core/draft.d.ts.map +1 -1
  227. package/lib/typescript/commonjs/src/core/locale.d.ts +6 -0
  228. package/lib/typescript/commonjs/src/core/locale.d.ts.map +1 -1
  229. package/lib/typescript/commonjs/src/core/numerals.d.ts +15 -0
  230. package/lib/typescript/commonjs/src/core/numerals.d.ts.map +1 -0
  231. package/lib/typescript/commonjs/src/core/segmentEditor.d.ts.map +1 -1
  232. package/lib/typescript/commonjs/src/core/segments.d.ts +0 -2
  233. package/lib/typescript/commonjs/src/core/segments.d.ts.map +1 -1
  234. package/lib/typescript/commonjs/src/core/selectionRules.d.ts +3 -2
  235. package/lib/typescript/commonjs/src/core/selectionRules.d.ts.map +1 -1
  236. package/lib/typescript/commonjs/src/core/timeEntry.d.ts +4 -24
  237. package/lib/typescript/commonjs/src/core/timeEntry.d.ts.map +1 -1
  238. package/lib/typescript/commonjs/src/icons/index.d.ts.map +1 -1
  239. package/lib/typescript/commonjs/src/index.d.ts +7 -3
  240. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  241. package/lib/typescript/module/src/adapters/utcMidnight.d.ts.map +1 -1
  242. package/lib/typescript/module/src/components/DateTimePicker.d.ts.map +1 -1
  243. package/lib/typescript/module/src/components/calendar/Calendar.d.ts +8 -4
  244. package/lib/typescript/module/src/components/calendar/Calendar.d.ts.map +1 -1
  245. package/lib/typescript/module/src/components/calendar/CalendarHeader.d.ts.map +1 -1
  246. package/lib/typescript/module/src/components/calendar/CalendarSwitch.d.ts +26 -0
  247. package/lib/typescript/module/src/components/calendar/CalendarSwitch.d.ts.map +1 -0
  248. package/lib/typescript/module/src/components/calendar/DayCell.d.ts +1 -1
  249. package/lib/typescript/module/src/components/calendar/DayCell.d.ts.map +1 -1
  250. package/lib/typescript/module/src/components/calendar/DayGrid.d.ts +2 -0
  251. package/lib/typescript/module/src/components/calendar/DayGrid.d.ts.map +1 -1
  252. package/lib/typescript/module/src/components/calendar/PeriodGrid.d.ts.map +1 -1
  253. package/lib/typescript/module/src/components/calendar/localeNames.d.ts +8 -3
  254. package/lib/typescript/module/src/components/calendar/localeNames.d.ts.map +1 -1
  255. package/lib/typescript/module/src/components/calendar/selection.d.ts +2 -0
  256. package/lib/typescript/module/src/components/calendar/selection.d.ts.map +1 -1
  257. package/lib/typescript/module/src/components/container/DefaultSheet.d.ts +10 -2
  258. package/lib/typescript/module/src/components/container/DefaultSheet.d.ts.map +1 -1
  259. package/lib/typescript/module/src/components/container/PickerContainer.d.ts.map +1 -1
  260. package/lib/typescript/module/src/components/container/containerStyles.d.ts +6 -0
  261. package/lib/typescript/module/src/components/container/containerStyles.d.ts.map +1 -1
  262. package/lib/typescript/module/src/components/field/RangeFields.d.ts +3 -0
  263. package/lib/typescript/module/src/components/field/RangeFields.d.ts.map +1 -1
  264. package/lib/typescript/module/src/components/field/SegmentedInput.d.ts.map +1 -1
  265. package/lib/typescript/module/src/components/field/ValueField.d.ts +3 -0
  266. package/lib/typescript/module/src/components/field/ValueField.d.ts.map +1 -1
  267. package/lib/typescript/module/src/components/field/fieldText.d.ts +9 -5
  268. package/lib/typescript/module/src/components/field/fieldText.d.ts.map +1 -1
  269. package/lib/typescript/module/src/components/hooks/useBottomInset.d.ts +8 -0
  270. package/lib/typescript/module/src/components/hooks/useBottomInset.d.ts.map +1 -0
  271. package/lib/typescript/module/src/components/hooks/useKeyboardFold.d.ts +10 -2
  272. package/lib/typescript/module/src/components/hooks/useKeyboardFold.d.ts.map +1 -1
  273. package/lib/typescript/module/src/components/hooks/useOpenPicker.d.ts +2 -1
  274. package/lib/typescript/module/src/components/hooks/useOpenPicker.d.ts.map +1 -1
  275. package/lib/typescript/module/src/components/hooks/useTypedSegments.d.ts +3 -2
  276. package/lib/typescript/module/src/components/hooks/useTypedSegments.d.ts.map +1 -1
  277. package/lib/typescript/module/src/components/theme/defaultStrings.d.ts +11 -2
  278. package/lib/typescript/module/src/components/theme/defaultStrings.d.ts.map +1 -1
  279. package/lib/typescript/module/src/components/theme/numerals.d.ts +7 -0
  280. package/lib/typescript/module/src/components/theme/numerals.d.ts.map +1 -0
  281. package/lib/typescript/module/src/components/theme/styleKeys.d.ts +1 -1
  282. package/lib/typescript/module/src/components/theme/styleKeys.d.ts.map +1 -1
  283. package/lib/typescript/module/src/components/theme/tokens.d.ts +3 -1
  284. package/lib/typescript/module/src/components/theme/tokens.d.ts.map +1 -1
  285. package/lib/typescript/module/src/components/time/TimeRow.d.ts.map +1 -1
  286. package/lib/typescript/module/src/components/time/TypedTime.d.ts.map +1 -1
  287. package/lib/typescript/module/src/components/time/Wheel.d.ts +5 -0
  288. package/lib/typescript/module/src/components/time/Wheel.d.ts.map +1 -1
  289. package/lib/typescript/module/src/components/types.d.ts +77 -4
  290. package/lib/typescript/module/src/components/types.d.ts.map +1 -1
  291. package/lib/typescript/module/src/core/calendarSystem.d.ts +10 -5
  292. package/lib/typescript/module/src/core/calendarSystem.d.ts.map +1 -1
  293. package/lib/typescript/module/src/core/digits.d.ts +3 -0
  294. package/lib/typescript/module/src/core/digits.d.ts.map +1 -0
  295. package/lib/typescript/module/src/core/draft.d.ts +12 -1
  296. package/lib/typescript/module/src/core/draft.d.ts.map +1 -1
  297. package/lib/typescript/module/src/core/locale.d.ts +6 -0
  298. package/lib/typescript/module/src/core/locale.d.ts.map +1 -1
  299. package/lib/typescript/module/src/core/numerals.d.ts +15 -0
  300. package/lib/typescript/module/src/core/numerals.d.ts.map +1 -0
  301. package/lib/typescript/module/src/core/segmentEditor.d.ts.map +1 -1
  302. package/lib/typescript/module/src/core/segments.d.ts +0 -2
  303. package/lib/typescript/module/src/core/segments.d.ts.map +1 -1
  304. package/lib/typescript/module/src/core/selectionRules.d.ts +3 -2
  305. package/lib/typescript/module/src/core/selectionRules.d.ts.map +1 -1
  306. package/lib/typescript/module/src/core/timeEntry.d.ts +4 -24
  307. package/lib/typescript/module/src/core/timeEntry.d.ts.map +1 -1
  308. package/lib/typescript/module/src/icons/index.d.ts.map +1 -1
  309. package/lib/typescript/module/src/index.d.ts +7 -3
  310. package/lib/typescript/module/src/index.d.ts.map +1 -1
  311. package/package.json +22 -7
  312. package/src/adapters/utcMidnight.ts +14 -5
  313. package/src/components/DateTimePicker.tsx +556 -102
  314. package/src/components/calendar/Calendar.tsx +54 -16
  315. package/src/components/calendar/CalendarHeader.tsx +38 -7
  316. package/src/components/calendar/CalendarSwitch.tsx +170 -0
  317. package/src/components/calendar/DayCell.tsx +16 -4
  318. package/src/components/calendar/DayGrid.tsx +13 -1
  319. package/src/components/calendar/PeriodGrid.tsx +3 -1
  320. package/src/components/calendar/calendarStyles.ts +1 -1
  321. package/src/components/calendar/localeNames.ts +52 -22
  322. package/src/components/calendar/selection.ts +8 -0
  323. package/src/components/container/DefaultSheet.tsx +60 -14
  324. package/src/components/container/PickerContainer.tsx +4 -0
  325. package/src/components/container/PickerLayout.tsx +1 -1
  326. package/src/components/container/containerStyles.ts +12 -3
  327. package/src/components/field/RangeFields.tsx +8 -2
  328. package/src/components/field/SegmentedInput.tsx +7 -2
  329. package/src/components/field/ValueField.tsx +12 -4
  330. package/src/components/field/fieldText.ts +45 -13
  331. package/src/components/hooks/useBottomInset.ts +33 -0
  332. package/src/components/hooks/useKeyboardFold.ts +41 -13
  333. package/src/components/hooks/useOpenPicker.ts +41 -18
  334. package/src/components/hooks/useTypedSegments.ts +7 -3
  335. package/src/components/theme/defaultStrings.ts +18 -3
  336. package/src/components/theme/numerals.ts +11 -0
  337. package/src/components/theme/styleKeys.ts +13 -1
  338. package/src/components/theme/tokens.ts +5 -1
  339. package/src/components/time/TimeRow.tsx +23 -3
  340. package/src/components/time/TypedTime.tsx +3 -1
  341. package/src/components/time/Wheel.tsx +19 -5
  342. package/src/components/types.ts +79 -4
  343. package/src/core/calendarSystem.ts +103 -21
  344. package/src/core/digits.ts +21 -0
  345. package/src/core/draft.ts +41 -13
  346. package/src/core/locale.ts +20 -3
  347. package/src/core/numerals.ts +35 -0
  348. package/src/core/segmentEditor.ts +13 -0
  349. package/src/core/segments.ts +0 -8
  350. package/src/core/selectionRules.ts +3 -2
  351. package/src/core/timeEntry.ts +6 -96
  352. package/src/icons/index.tsx +3 -1
  353. package/src/index.tsx +12 -2
package/README.md CHANGED
@@ -1,57 +1,71 @@
1
1
  # rn-grid-date-time-picker
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/rn-grid-date-time-picker)](https://www.npmjs.com/package/rn-grid-date-time-picker)
4
- [![npm downloads](https://img.shields.io/npm/dm/rn-grid-date-time-picker)](https://www.npmjs.com/package/rn-grid-date-time-picker)
5
- [![CI](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/actions/workflows/ci.yml/badge.svg)](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/actions/workflows/ci.yml)
4
+ ![Platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20Android%20%7C%20Expo%20Go-blue)
6
5
  [![types](https://img.shields.io/npm/types/rn-grid-date-time-picker)](https://www.npmjs.com/package/rn-grid-date-time-picker)
7
- [![license](https://img.shields.io/npm/l/rn-grid-date-time-picker)](./LICENSE)
8
- ![Platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20Android-blue)
9
- ![Expo Go](https://img.shields.io/badge/Expo%20Go-compatible-000020)
10
6
 
11
- A flexible, themeable date & time picker for React Native: single, multiple and range selection, typed or wheel time entry, limits and holidays, Hijri support. Runs on **iOS and Android**. Pure JS, so it also works in Expo Go and bare React Native apps.
12
-
13
- <!--
14
- Screenshots: add images to docs/ and uncomment. Use absolute raw.githubusercontent.com
15
- URLs so they also show on npmjs.com, e.g.
16
- https://raw.githubusercontent.com/Bhairavi-ancy/rn-grid-date-time-picker/main/docs/range.gif
7
+ A themeable date and time picker for React Native: one date, several dates or a range, typed or tapped, with limits, holidays and the Hijri calendar. Pure JS, so there's nothing native to install. It runs on iOS and Android and works in Expo Go.
17
8
 
9
+ <!-- Absolute URLs so the screenshots also show on npmjs.com. -->
18
10
  <p align="center">
19
- <img src="…/docs/single.png" width="240" alt="Single date in a bottom sheet" />
20
- <img src="…/docs/range.gif" width="240" alt="Picking a date range" />
21
- <img src="…/docs/datetime.png" width="240" alt="Date and time with typed segments" />
11
+ <img src="https://raw.githubusercontent.com/Bhairavi-ancy/rn-grid-date-time-picker/main/docs/screenshots.png" width="760" alt="The bottom sheet three ways: a date picked, a From / To date range, and a date with a typed time" />
22
12
  </p>
23
- -->
24
13
 
25
14
  <!--
26
15
  Live demo: after publishing, create a Snack (see CONTRIBUTING.md) and uncomment.
16
+ The query offers only Expo Go, iOS and Android (no web) and opens on Android.
27
17
 
28
- **[Try it in Expo Snack →](https://snack.expo.dev/@your-account/rn-grid-date-time-picker)**
18
+ **[Try it in Expo Snack →](https://snack.expo.dev/@your-account/rn-grid-date-time-picker?supportedPlatforms=mydevice,ios,android&platform=android)**
29
19
  -->
30
20
 
31
- - [Features](#features)
32
- - [Install](#install)
33
- - [Quick start](#quick-start)
34
- - [Values](#values)
35
- - [Props](#props)
36
- - [Limits & greying](#limits--greying)
37
- - [Presentation](#presentation-1) · [Field and typing](#field-and-typing) · [Time](#time-1)
38
- - [Locale, RTL & Hijri](#locale-rtl--hijri)
39
- - [Theming](#theming) · [Icons](#icons) · [Strings / i18n](#strings--i18n)
40
- - [Your own validation](#your-own-validation) · [Your own input](#your-own-input)
41
- - [Accessibility](#accessibility) · [Testing](#testing)
42
- - [Platform support and known limits](#platform-support-and-known-limits)
43
-
44
- ## Features
45
-
46
- - **Dates and date-times**: one value, several dates, or a range (in one field or From / To).
47
- - **Typed or tapped**: type the date and time as segments, or pick them on the calendar and a time row (typed boxes or a scrolling wheel, 12- or 24-hour, minute steps).
48
- - **Limits**: min / max days with edge times, disabled weekdays, holidays (marked or disabled, loaded per year), custom checks, per-day time bounds, or your own constraint engine.
49
- - **Calendar**: day, month and year views, month swipe, a Today button, outside days, any first day of the week, years 1900–2200.
50
- - **Hijri**: Gregorian, Gregorian with Hijri days, or a Hijri (Umm al-Qura) grid.
51
- - **Exact commits**: `onChange` fires once per Confirm. Closing fires nothing.
52
- - **Accessible and RTL-aware**: every control is labelled, reduce motion is respected, font scaling is capped, and chevrons mirror in RTL.
53
- - **Yours to restyle**: theme tokens, a `styles` key for every part, every string, and render props for the sheet, field, label, days, cells and time row.
54
- - **No native code**: one runtime dependency ([Luxon](https://moment.github.io/luxon/)).
21
+ ## Why this picker
22
+
23
+ - **Every kind of pick**: one date, several dates, or a range in one field or as From / To, with or without a time. Month-and-year and year-only picks too.
24
+ - **Typed or tapped**: users type the date and time, or pick them on the calendar. Time is typed boxes or a scrolling wheel, 12- or 24-hour, in minute steps.
25
+ - **Only the days you allow**: block past dates, weekends, holidays loaded from your server, booked days, or hours outside opening times.
26
+ - **Saves only on Confirm**: by default `onChange` fires once, when the user confirms, and closing the sheet never touches your value. `commitMode="instant"` saves each edit instead.
27
+ - **Gregorian, Hijri or both**: a Hijri (Umm al-Qura) calendar written in Arabic, Gregorian and Hijri tabs, or a switch between them. Layouts mirror in RTL.
28
+ - **Your design**: colours, fonts, corners and every text, a style for every part, or your own field, sheet and day cells.
29
+ - **Accessible and light**: every control is labelled for screen readers, reduce motion is respected, and the only dependency is [Luxon](https://moment.github.io/luxon/).
30
+
31
+ ## Hijri and Arabic
32
+
33
+ <img align="right" src="https://raw.githubusercontent.com/Bhairavi-ancy/rn-grid-date-time-picker/main/docs/hijri-dual.png" width="200" alt="Gregorian and Hijri tabs, the Hijri month in Arabic" />
34
+
35
+ `calendarSystem="hijri"` lays out Hijri months, days and years in Arabic, whatever your app's language. `"dual"` shows Gregorian and Hijri as two tabs, and `calendarSwitch` lets users switch for themselves. Values stay plain Gregorian strings, so your API doesn't change.
36
+
37
+ ```tsx
38
+ <DateTimePicker
39
+ type="date"
40
+ value={value}
41
+ onChange={setValue}
42
+ calendarSystem="dual"
43
+ />
44
+ ```
45
+
46
+ More in [Locale, RTL and Hijri](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/localization.md).
47
+
48
+ <br clear="right" />
49
+
50
+ ## Make it yours
51
+
52
+ <p align="center">
53
+ <img src="https://raw.githubusercontent.com/Bhairavi-ancy/rn-grid-date-time-picker/main/docs/theme-blue-sharp.png" width="200" alt="Blue accent, square corners" />
54
+ <img src="https://raw.githubusercontent.com/Bhairavi-ancy/rn-grid-date-time-picker/main/docs/theme-teal.png" width="200" alt="Teal accent, medium corners" />
55
+ <img src="https://raw.githubusercontent.com/Bhairavi-ancy/rn-grid-date-time-picker/main/docs/theme-coral-round.png" width="200" alt="Coral accent, round corners" />
56
+ </p>
57
+
58
+ One `theme` prop sets the colours, fonts, corners and sizes. Each of the sheets above is one line:
59
+
60
+ ```tsx
61
+ const blue = { accent: '#2563EB', rangeFill: '#DBEAFE', radius: 4 };
62
+ const teal = { accent: '#0F766E', rangeFill: '#CCFBF1', radius: 8 };
63
+ const coral = { accent: '#D9434B', rangeFill: '#FDE2E2', radius: 16 };
64
+
65
+ <DateTimePicker type="date" value={value} onChange={setValue} theme={teal} />
66
+ ```
67
+
68
+ Every text can be changed with `strings`, every part has a style key in `styles`, and the field, sheet and day cells can be your own components. See [Theming, fonts and icons](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/theming.md).
55
69
 
56
70
  ## Install
57
71
 
@@ -61,7 +75,7 @@ npm i rn-grid-date-time-picker
61
75
  yarn add rn-grid-date-time-picker
62
76
  ```
63
77
 
64
- There are no native steps. It works in Expo Go and in bare React Native apps. `react` (18 or later) and `react-native` (0.71 or later) are peer dependencies.
78
+ There are no native steps. `react` (18 or later) and `react-native` (0.71 or later) are peer dependencies.
65
79
 
66
80
  ## Quick start
67
81
 
@@ -106,609 +120,57 @@ A range:
106
120
  />
107
121
  ```
108
122
 
109
- ## Values
110
-
111
- Values are strings, so they can go straight into a form, a store or an API.
112
-
113
- | Mode | `value` accepted | `onChange` receives |
114
- |---|---|---|
115
- | `single` | `string` (`''` = empty) | `string` |
116
- | `multiple` | `string[]`; a non-empty `string` counts as a one-item list | `string[]`, sorted by date |
117
- | `range` | `{ from, to }` or `[from, to]` | `{ from, to }` |
118
- | any, on clear (×) | – | `''` |
119
-
120
- The string format is set by `valueFormat`:
121
-
122
- | `valueFormat` | date | date-time |
123
- |---|---|---|
124
- | `'iso'` (default) | `'2026-10-24'`. Only `YYYY-MM-DD` is accepted; anything else reads as empty. | A UTC ISO instant with seconds and milliseconds zeroed: `'2026-10-24T10:00:00.000Z'`. Any ISO 8601 string with `Z` or an offset is accepted (one without an offset is read as UTC) and shown in `timeZone`. |
125
- | `'utc-midnight'` | `'2026-10-24T00:00:00.000Z'`: the calendar day at UTC midnight, never shifted by a zone. | The same as `'iso'`. |
126
- | a `ValueAdapter` | yours | yours |
127
-
128
- ```ts
129
- interface ValueAdapter {
130
- parse(raw: string, ctx: AdapterContext): DateTimeValue | null; // null = empty or invalid
131
- format(value: DateTimeValue, ctx: AdapterContext): string; // '' when incomplete
132
- /** Confirm without a change: what to emit for the stored raw string. Default: raw as-is. */
133
- formatUnchanged?(raw: string, ctx: AdapterContext): string;
134
- }
135
- interface AdapterContext { type: 'date' | 'datetime'; timeZone: string }
136
- interface DateTimeValue { date: CalendarDate; time: Time | null }
137
- ```
138
-
139
- For example, an adapter that stores epoch milliseconds:
140
-
141
- ```ts
142
- import type { ValueAdapter } from 'rn-grid-date-time-picker';
143
-
144
- const epochMs: ValueAdapter = {
145
- parse: (raw) => {
146
- const d = new Date(Number(raw));
147
- if (!raw || Number.isNaN(d.getTime())) return null;
148
- return {
149
- date: { year: d.getFullYear(), month: d.getMonth() + 1, day: d.getDate() },
150
- time: { hour: d.getHours(), minute: d.getMinutes() },
151
- };
152
- },
153
- format: ({ date, time }) =>
154
- time
155
- ? String(new Date(date.year, date.month - 1, date.day, time.hour, time.minute).getTime())
156
- : '',
157
- };
158
- ```
159
-
160
- `isoAdapter` and `utcMidnightAdapter` are exported too.
161
-
162
- **Empty and clear.** `''` (or `[]`, or `{ from: '', to: '' }`) is empty. A value the format can't read is treated as empty. The × on the field calls `onChange('')` straight away, in every mode.
163
-
164
- **Unchanged Confirm.** If the user confirms without changing a value, the stored string comes back as it came in (`'iso'`), so a value with seconds or an offset isn't rewritten. `'utc-midnight'` re-serialises the stored instant or day as UTC (`formatUnchanged`).
165
-
166
- **Time zones.** Date-time values are read and written in `timeZone` (an IANA name; default: the device zone). "Today" uses the same zone. Dates have no zone. A wall time skipped by a daylight-saving change moves forward, and a repeated one uses its first occurrence.
167
-
168
- ## Props
169
-
170
- ### What it picks
171
-
172
- | Prop | Type | Default | Notes |
173
- |---|---|---|---|
174
- | `type` | `'date' \| 'datetime'` | required | |
175
- | `mode` | `'single' \| 'multiple' \| 'range'` | `'single'` | |
176
- | `value` | `PickerValue` | required | See [Values](#values). |
177
- | `onChange` | `(value: PickerValue) => void` | required | Once per Confirm, or with `''` on clear. |
178
- | `onBlur` | `() => void` | – | Right after every `onChange` that saves a value (Confirm, an `'instant'` edit, typing in the on-screen field), like a form field losing focus. Not on clear. |
179
- | `commitMode` | `'confirm' \| 'instant'` | `'confirm'` | `'instant'` saves every complete, allowed edit, and × in the field above the calendar clears the saved value. |
180
- | `valueFormat` | `'iso' \| 'utc-midnight' \| ValueAdapter` | `'iso'` | |
181
- | `multiple` | `{ timeMode?: 'shared' \| 'perDate'; maxSelections?: number; joinConsecutive?: boolean }` | `timeMode: 'shared'` | `joinConsecutive` draws neighbouring days as one band. |
182
- | `range` | `{ layout?: 'singleField' \| 'fromTo'; allowSameDay?: boolean; minDays?: number; maxDays?: number; reselect?: 'newRange' \| 'moveNearestEnd' }` | `layout: 'singleField'`, `reselect: 'newRange'` | `allowSameDay` is for dates; date-time ranges may always start and end on one day. `minDays` / `maxDays` count calendar days with both ends included (the 1st to the 3rd is 3 days; a same-day range is 1). |
183
-
184
- ### Presentation
185
-
186
- | Prop | Type | Default | Notes |
187
- |---|---|---|---|
188
- | `presentation` | `'sheet' \| 'inline'` | `'sheet'` | |
189
- | `visible` | `boolean` | – | Controls the sheet; without it the picker opens itself. |
190
- | `onOpen` / `onClose` | `() => void` | – | `onClose` fires whenever the sheet closes: Close, the backdrop, Android back, and after Confirm. |
191
- | `onBeforeOpen` | `() => void` | – | Just before opening, e.g. to close your own dropdowns. |
192
- | `showField` | `boolean` | `true` | Hide the on-screen field (for example with `visible`). |
193
- | `sheet` | `SheetOptions` | – | `height`, `maxHeight`, `fixedHeader`, `fixedFooter`, `showField`, `fieldPlaceholder`, `fieldIcon`. See [Sheet layout](#sheet-layout). |
194
- | `renderSheet` | `(p: SheetRenderProps) => ReactNode` | built-in sheet | See [Presentation](#presentation). |
123
+ Values are strings, so they go straight into a form, a store or an API. See [Values](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/values.md) for other formats.
195
124
 
196
- ### Value field
125
+ ## Common props
197
126
 
198
- | Prop | Type | Default | Notes |
127
+ | Prop | Type | Default | What it does |
199
128
  |---|---|---|---|
200
- | `label`, `placeholder`, `helperText`, `instruction` | `string` | – | `helperText` sits with the label, `instruction` under the field. |
201
- | `isMandatory` | `boolean` | `false` | Adds ` *` to the label. |
202
- | `disabled`, `readOnly` | `boolean` | `false` | Neither opens; disabled also greys the field. |
203
- | `allowTyping` | `boolean` | `false` | Type in the field inside the sheet. |
204
- | `allowFieldTyping` | `boolean` | `false` | Type in the on-screen field (single mode). A complete, allowed value is saved once, when focus leaves the field or its last box fills. |
205
- | `allowClear` | `boolean` | `false` | Shows × when there is a value. |
206
- | `errorMessage` | `string` | – | Your error, shown under the field. |
207
- | `dateFormat` | `string` | from `locale` | `dd`, `MM` and `yyyy` with one separator, in any case: `'dd/mm/yyyy'`, `'DD.MM.YYYY'`, `'yyyy-MM-dd'`. Used for the field text, the typed segments and the placeholder. Anything else (for example `'d/m/yy'` or `'dd MMM yyyy'`) logs a warning in development and uses the locale order. |
208
- | `renderLabel` | `(p: LabelRenderProps) => ReactNode` | built-in label | |
209
- | `renderInstruction` | `(p: InstructionRenderProps) => ReactNode` | built-in text | |
210
- | `icons` | `Partial<Record<IconName, ComponentType<IconRenderProps> \| null>>` | built-in icons | Your own component per icon; `null` hides it. `IconName`: `'calendar' \| 'clear' \| 'chevronLeft' \| 'chevronRight' \| 'chevronDown'`. See [Icons](#icons). |
211
- | `iconProps` | `Partial<Record<IconName, IconOptions>>` | – | `color`, `disabledColor`, `size`, `width`, `height` per icon, for the built-in icons and yours. |
212
-
213
- ### Slots and render props
214
-
215
- | Prop | Type | Notes |
216
- |---|---|---|
217
- | `header`, `bodyTop`, `bodyBottom`, `footer` | `ReactNode \| (state: PickerState) => ReactNode` | `header` replaces the title + Reset row; `footer` replaces Confirm (call `state.confirm`). |
218
- | `title` | `string` | Sheet title (default `strings.titleDate`). |
219
- | `onReset` | `() => void` | Shows a Reset button in the header. |
220
- | `onConfirm` | `(value: PickerValue) => void` | Only when Confirm is pressed and saves, after `onChange` and `onBlur`. Not for `'instant'` edits. |
221
- | `confirmDisabled` | `boolean` | Keep Confirm disabled. |
222
- | `renderField` | `(state: PickerState) => ReactNode` | Replaces the on-screen field with your own input: show `state.displayText`, open with `state.open`, clear with `state.clear`. See [Your own input](#your-own-input). |
223
- | `renderDay` | `(state: DayCellState, onPress: () => void) => ReactNode` | |
224
- | `renderWeekday` | `(weekday: Weekday, name: string) => ReactNode` | |
225
- | `renderMonthChip` | `(month: number, state: { selected; disabled }) => ReactNode` | |
226
- | `renderYearCell`, `renderMonthCell` | `(item: PeriodItem) => ReactNode` | |
227
- | `renderEmptyState` | `() => ReactNode` | Shown when no day can be picked. |
228
- | `renderTimeRow` | `(state: PickerState) => ReactNode` | Replaces the time row. Read `state.time` (ranges: `state.rangeTimes`) and change it with `state.setTime(time, end?)`, which works like the built-in row, including before a day is picked. |
229
-
230
- ### Calendar
231
-
232
- | Prop | Type | Default |
233
- |---|---|---|
234
- | `firstDayOfWeek` | `1`–`7` (Monday = 1) | from `locale`'s region (Sunday for `en-US`, Monday for `en-GB`), else `7` (Sunday) |
235
- | `showOutsideDays` | `boolean` | `true` |
236
- | `yearRange` | `{ first: number; last: number }` | `DEFAULT_YEAR_RANGE` (1900–2200) |
237
- | `initialView` | `'day' \| 'month' \| 'year'` | `'day'` |
238
- | `precision` | `'day' \| 'month' \| 'year'` | `'day'`: what one pick is. With `'month'` or `'year'` the month or year grid is the last step, the saved value is the period's first day, the field shows "March 2026" or "2026", and a period can be picked when any day in it can (so `minDate` 15 Oct still allows October). The current month or year is outlined. Single date pickers only (ignored for date-time, range and multiple), always Gregorian, without typing. |
239
- | `initialVisibleDate` | `CalendarDate` | today: with no value, the calendar opens on this day's month without selecting it (e.g. `{ year: 2000, month: 1, day: 1 }` for a date of birth); a value's month always wins |
240
- | `enableMonthSwipe` | `boolean` | `true` |
241
- | `showToday` | `boolean` | `false` |
242
- | `calendarSystem` | `'gregory' \| 'dual' \| 'hijri'` | `'gregory'` |
243
- | `locale` | BCP-47 tag | the device locale |
244
- | `timeZone` | IANA zone | the device zone |
245
- | `now` | `() => Date` | `() => new Date()` |
246
-
247
- ### Time
248
-
249
- | Prop | Type | Default | Notes |
250
- |---|---|---|---|
251
- | `timeInput` | `'typed' \| 'wheel'` | `'typed'` | |
252
- | `timeFormat` | `'12h' \| '24h'` | from `locale`, else `'12h'` | |
253
- | `minuteStep` | `number` | `1` | A step that divides the hour: 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30 or 60. Off-step minutes are flagged on Confirm, never rounded silently. |
254
- | `newDayTime` | `Time` | – | Every newly picked day gets this time. It wins over a time typed before the day and over the current time. |
255
-
256
- ### Limits
257
-
258
- | Prop | Type | Default | Notes |
259
- |---|---|---|---|
260
- | `minDate`, `maxDate` | `CalendarDate` | – | `{ year, month, day }`, month 1–12. |
261
- | `disabledWeekdays` | `Weekday[]` | `[]` | Reason `'WEEKDAY'`. |
262
- | `disabledDates` | `(day) => boolean` | – | Reason `'CUSTOM'`. |
263
- | `enabledDates` | `(day) => boolean` | – | `false` → reason `'CUSTOM'`. |
264
- | `timeBounds` | `(day) => TimeBounds \| null` | – | Per-day `{ min?, max? }` times. |
265
- | `holidays` | `string[]` | `[]` | `'YYYY-MM-DD'`; ISO strings are cut to the date. |
266
- | `loadHolidays` | `(year) => Promise<string[]>` | – | Called once per year the calendar shows. |
267
- | `showHolidays` | `boolean` | `true` | Holiday styling on day cells. |
268
- | `disableHolidays` | `boolean` | `false` | Holidays can't be picked (reason `'HOLIDAY'`). |
269
- | `getConstraints` | `(ctx: ConstraintContext) => Constraints` | – | Full control; see below. |
270
-
271
- ### Look, text and events
272
-
273
- | Prop | Type | Notes |
274
- |---|---|---|
275
- | `theme` | `Partial<ThemeTokens>` | See [Theming](#theming). |
276
- | `styles` | `PickerStyles` | A style for any part. |
277
- | `strings` | `Partial<PickerStrings>` | See [Strings / i18n](#strings--i18n). |
278
- | `testID` | `string` | The prefix for every part; see [Testing](#testing). |
279
- | `onVisibleMonthChange` | `(year, month) => void` | The Gregorian month of the first day shown. |
280
- | `onError` | `(code: PickerErrorCode, value) => void` | `'NOTHING_SELECTABLE'` once per open when no day can be picked. When Confirm is pressed with a time problem: `'INCOMPLETE'`, `'INVALID'`, `'OFF_STEP'`, `'BEFORE_MIN'`, `'AFTER_MAX'` or `'TIME_NOT_ALLOWED'`, with the saved value. |
281
- | `validate` | `(value: PickerValue) => string \| null \| undefined` | – | Your own check on Confirm, after the built-in ones. Return a message to show it inside the picker and save nothing; `null` to save. See [Your own validation](#your-own-validation). |
282
-
283
- ## Limits & greying
284
-
285
- The limit props cover most cases:
286
-
287
- ```tsx
288
- <DateTimePicker
289
- type="date"
290
- value={value}
291
- onChange={setValue}
292
- minDate={{ year: 2026, month: 10, day: 1 }}
293
- maxDate={{ year: 2026, month: 12, day: 31 }}
294
- disabledWeekdays={[6, 7]}
295
- holidays={['2026-12-25']}
296
- disableHolidays
297
- disabledDates={(d) => d.day === 13}
298
- />
299
- ```
300
-
301
- Greyed days are drawn in the `disabledText` colour (no strike-through), aren't pressable and are read out as "unavailable". A typed value on a greyed day keeps Confirm disabled and shows `strings.errorNotAllowed`. Greying only guides the user, so keep your own validation for what is saved.
302
-
303
- `createConstraints` is the engine behind those props. Use it on its own, for example to check a value on the server side of a form:
304
-
305
- ```ts
306
- import { createConstraints, toDateKey } from 'rn-grid-date-time-picker';
307
-
308
- const bookedDays = new Set(['2026-10-27']);
309
- const c = createConstraints({
310
- type: 'datetime',
311
- timeZone: 'Europe/Berlin',
312
- now: new Date(),
313
- // A bound can carry a time on its edge day.
314
- min: { date: { year: 2026, month: 10, day: 24 }, time: { hour: 9, minute: 0 } },
315
- disabledWeekdays: [7],
316
- isDisabled: (d) => (bookedDays.has(toDateKey(d)) ? 'BOOKED' : false),
317
- });
318
- c.dayStatus({ year: 2026, month: 10, day: 25 }); // { disabled: true, reasons: ['WEEKDAY'], holiday: false }
319
- c.isValueAllowed({ date: { year: 2026, month: 10, day: 24 }, time: { hour: 8, minute: 30 } }); // false
320
- ```
321
-
322
- Reasons come in this order: `OUTSIDE_RANGE`, `WEEKDAY`, `HOLIDAY`, then what `isDisabled` returns (`true` → `'CUSTOM'`, or your own reason string or list), then `CUSTOM` from `isEnabled`. In range and multiple modes the picker adds `RANGE_LENGTH` and `MAX_SELECTIONS` while the user picks.
323
-
324
- For full control, pass `getConstraints`. Its result is used as is, and the limit props arrive in `ctx.limits` so you can merge them:
325
-
326
- ```tsx
327
- <DateTimePicker
328
- type="datetime"
329
- value={value}
330
- onChange={setValue}
331
- maxDate={lastDay}
332
- getConstraints={(ctx) =>
333
- createConstraints({
334
- type: ctx.type,
335
- timeZone: ctx.timeZone,
336
- now: ctx.now,
337
- maxDate: ctx.limits.maxDate,
338
- // From now on, to the minute; refreshed while the sheet is open.
339
- min: { date: ctx.today, time: ctx.nowTime },
340
- dependsOnNow: true,
341
- holidays: ctx.holidays,
342
- timeBounds: () => ({ min: { hour: 9, minute: 0 }, max: { hour: 17, minute: 30 } }),
343
- })
344
- }
345
- />
346
- ```
347
-
348
- `ctx` also holds `today` and `nowTime` (the current day and time in `timeZone`) and `holidays` (the prop plus every year loaded so far).
349
-
350
- ## Presentation
351
-
352
- `presentation="sheet"` (the default) opens a built-in bottom sheet: an RN `Modal` with a backdrop, up to 90% of the screen (see [Sheet layout](#sheet-layout)). The body scrolls between the title and Confirm when it doesn't fit, and the sheet waits for the keyboard to close before opening. `presentation="inline"` renders the same content in place, for example inside your own sheet or a filter panel.
353
-
354
- The built-in sheet doesn't add a safe-area inset. Add one with `styles.sheet`:
355
-
356
- ```tsx
357
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
358
-
359
- const insets = useSafeAreaInsets();
360
- <DateTimePicker styles={{ sheet: { paddingBottom: 24 + insets.bottom } }} /* … */ />;
361
- ```
362
-
363
- Or bring your own sheet with `renderSheet`. It is called only while the picker is open and rendered in place (no portal), so it works inside other sheets:
364
-
365
- ```tsx
366
- import { Modal, Pressable, StyleSheet, View } from 'react-native';
367
- import type { SheetRenderProps } from 'rn-grid-date-time-picker';
368
-
369
- const renderSheet = ({ onRequestClose, body, footer }: SheetRenderProps) => (
370
- <Modal visible transparent animationType="fade" onRequestClose={onRequestClose}>
371
- <Pressable style={StyleSheet.absoluteFill} onPress={onRequestClose} />
372
- <View style={{ margin: 16, marginTop: 'auto', borderRadius: 16, backgroundColor: '#fff' }}>
373
- {body}
374
- {footer}
375
- </View>
376
- </Modal>
377
- );
378
- ```
379
-
380
- Call `onRequestClose` for Close, the backdrop and Android back. It fires `onClose` and never `onChange`.
381
-
382
- ### Sheet layout
383
-
384
- Everything inside the sheet can be set from props:
385
-
386
- | What | How |
387
- |---|---|
388
- | Title | `title="Choose a day"` (default `strings.titleDate`) |
389
- | The whole header | `header={(state) => <MyHeader onClose={state.close} />}`; `header={null}` hides it |
390
- | Confirm, or your own buttons | `footer={(state) => <MyButton disabled={!state.canConfirm} onPress={state.confirm} />}`; `footer={null}` hides it |
391
- | Content above / below the calendar | `bodyTop`, `bodyBottom` |
392
- | Styles | `styles.sheet` (panel), `sheetBackdrop`, `header`, `title`, `container`, `body`, `footer`, `confirmButton`, `confirmText` |
393
- | Placeholders | `sheet.fieldPlaceholder` for the field above the calendar; `strings.placeholderDay` / `placeholderMonth` / `placeholderYear` / `placeholderHour` / `placeholderHour24` / `placeholderMinute` for the typed segments and time boxes (and the empty field) |
394
- | Size and scrolling | `sheet` (below) |
395
-
396
- `sheet` takes:
397
-
398
- | Option | Default | |
399
- |---|---|---|
400
- | `height` | as tall as the content | A fixed height, in points or as a percentage of the screen (`'60%'`). The footer then sits at the bottom. |
401
- | `maxHeight` | `'90%'` | The most the sheet grows to. Beyond it the body scrolls. |
402
- | `fixedHeader` | `true` | The header stays put while the body scrolls. `false` scrolls it with the body. |
403
- | `fixedFooter` | `true` | Confirm stays pinned below the body. `false` scrolls it at the end of the body. `renderSheet` then gets `footer: null`. |
404
- | `showField` | `true` | The field above the calendar, which shows the picked date and takes typing with `allowTyping`. When it's hidden, its errors still show above the calendar. Applies inline too. |
405
- | `fieldPlaceholder` | from `dateFormat` | Placeholder of that field when it shows text. |
406
- | `fieldIcon` | `false` | The calendar icon at the end of that field, as on the on-screen field. |
407
-
408
- ```tsx
409
- <DateTimePicker
410
- title="Choose a day"
411
- header={(state) => <MyHeader title="Choose a day" onClose={state.close} />}
412
- sheet={{ height: '70%', fixedHeader: true, fixedFooter: false, showField: false }}
413
- styles={{ sheet: { borderTopLeftRadius: 24, borderTopRightRadius: 24 } }}
414
- strings={{ placeholderHour: 'HH', placeholderMinute: 'MM' }}
415
- …
416
- />
417
- ```
418
-
419
- `height` and `maxHeight` size the built-in sheet only; with `renderSheet`, your sheet sets its own size. `fixedHeader` and `fixedFooter` apply to both.
420
-
421
- ## Field and typing
422
-
423
- The on-screen field shows the saved value (never the draft) in `dateFormat`, with an optional ×, label, helper text, instruction and error. Tap it, or its calendar icon, to open the picker.
424
-
425
- With `allowTyping`, the field inside the sheet takes the date and time as segments (day, month, year, hour, minute, AM/PM) in the locale's order. Each segment moves on when it's full, Backspace on an empty segment goes back, and leaving a segment pads it. Typing and the calendar edit the same draft. While the keyboard is up, the calendar folds away so the field and Confirm stay visible. On iOS every box's number pad has a Done button (`strings.done`) that closes the keyboard. Errors (incomplete, invalid date, year outside `yearRange`) show once the user leaves the field. The date and the time each stay on one line; when the field is too narrow (large text, a small phone) the time moves to a second line. In 12-hour mode a typed time reads as AM until AM/PM is switched, as in the time row. A date typed with the time still empty takes the time the user already typed in the time row (or `newDayTime`, or the current time), like a tapped day. Fast input (a hardware keyboard, autofill) is handled character by character.
426
-
427
- `allowFieldTyping` makes the on-screen field typeable too (single mode). A complete, allowed value is saved once typing pauses: when focus leaves the field, or when its last box fills. `onChange` doesn't see values on the way (typing 09:30 never saves 09:03); correcting a box saves again when it's full or left.
428
-
429
- ## Time
430
-
431
- Date-time pickers show a time row under the calendar:
432
-
433
- - **Typed** (default): `[hh] : [mm] [AM | PM]`, or `[HH] : [mm]` in 24-hour. Two hour digits jump to the minutes. Empty minutes count as `00`. A time is saved when focus leaves a box, and Confirm also saves a time still being typed. The AM/PM side that can't hold an allowed time is disabled.
434
- - **Wheel** (`timeInput="wheel"`): hour, minute (by `minuteStep`) and AM/PM columns on native scroll views, with momentum and snapping. Rows outside the day's limits are dimmed and can't be stopped on. Confirm waits until the wheel settles.
435
-
436
- **Time checks happen on Confirm, not while typing.** Nothing is flagged as the user types, and Confirm stays enabled. Pressing it with an unfinished, impossible, off-step or out-of-limits time shows the error under the time row, calls `onError`, and saves nothing. Editing the time hides the error again until the next Confirm. With `commitMode="instant"` there's no Confirm, so errors show as they happen, and a time with a problem is never saved.
437
-
438
- A newly picked day on an empty date-time starts at the current time, rounded up to the next minute step. `newDayTime` replaces that. An existing time is kept when another day is picked. Range mode has start and end rows. Multiple mode has one shared row, or (with `timeMode: 'perDate'`) a row for the day last tapped.
439
-
440
- ## Locale, RTL & Hijri
441
-
442
- - **`locale`** (default: the device locale from `Intl.DateTimeFormat().resolvedOptions().locale`, else `'en-US'`) sets month and weekday names, the default `dateFormat` (from `Intl`: `MM/dd/yyyy` for `en-US`, `dd/MM/yyyy` for `en-GB`, `dd.MM.yyyy` for `de-DE`; a separator other than `/`, `-` or `.` becomes `/`; fallback `yyyy-MM-dd`) the default `timeFormat` (the locale's hour cycle, else `'12h'`) and the default `firstDayOfWeek` (the region's first day from CLDR week data: Sunday for `en-US`, Monday for `en-GB` and `de-DE`, Saturday for `ar-EG`; Sunday when the tag has no region).
443
- - **RTL**: layouts use start/end, so they flip with `I18nManager`. The chevrons point the right way, and swipe directions are mirrored. Typed dates and times keep their left-to-right digit order.
444
- - **Hijri**: `calendarSystem="dual"` shows the Hijri day under each Gregorian day; `"hijri"` lays out Hijri (Umm al-Qura) months, years and day numbers. Values stay Gregorian either way. Hijri dates come from the platform's `Intl` (`islamic-umalqura`). Some JS engines and devices ship without that calendar, for example some Hermes / Android builds. The picker checks once, and if it isn't available it falls back to `'gregory'`. The default is always `'gregory'`, whatever the locale.
445
-
446
- ## Theming
447
-
448
- `theme` overrides any token. A given `accent` also becomes `borderFocused`.
449
-
450
- | Token | Default | Used for |
451
- |---|---|---|
452
- | `accent` | `#2563EB` | Selection, links, focused borders, Confirm |
453
- | `onAccent` | `#FFFFFF` | Text on the accent |
454
- | `text` | `#111827` | Values and day numbers |
455
- | `heading` | `#111827` | Year title, time label and boxes |
456
- | `mutedText` | `#6B7280` | Weekdays, helper text, chevrons, × |
457
- | `placeholder` | `#9CA3AF` | Placeholders |
458
- | `border` | `#D1D5DB` | Field border |
459
- | `inputBorder` | `#D1D5DB` | Time box border |
460
- | `separator` | `#E5E7EB` | Line above the time row |
461
- | `toggleTrack` | `#F3F4F6` | Behind AM / PM |
462
- | `borderFocused` | `#2563EB` | Focused field / box |
463
- | `error` | `#DC2626` | Errors, mandatory mark |
464
- | `background` | `#FFFFFF` | Field, sheet |
465
- | `surface` | `#F9FAFB` | Wheel highlight |
466
- | `disabledBackground` | `#F3F4F6` | Disabled field |
467
- | `disabledText` | `#9CA3AF` | Disabled text, greyed days |
468
- | `rangeFill` | `#DBEAFE` | Range band |
469
- | `holiday` | `#DC2626` | Holiday days |
470
- | `fontFamily` | `undefined` (system font) | One family for all text, at weight 400 / 500 / 600 as each part needs |
471
- | `fontRegular`, `fontMedium`, `fontSemiBold` | `undefined` | A family per weight, for fonts shipped as one file per weight; each one set wins over `fontFamily`. `INTER_FONTS` sets all four to Inter, `SYSTEM_FONTS` clears them |
472
- | `fontSizeSmall` | `12` | Weekday names, helper / error text, AM / PM in the field (the Hijri day under a dual cell is 75% of it) |
473
- | `fontSizeMedium` | `14` | Field text and label, day numbers, month chips, cells, Today, time boxes, AM / PM toggle |
474
- | `fontSizeLarge` | `16` | Sheet title, Confirm, year title, time label, wheel |
475
- | `radius` | `8` | Field and button corners (the sheet uses `radius * 2`) |
476
- | `fieldHeight` | `44` | Field minimum height |
477
- | `touchTarget` | `44` | Minimum button size |
478
-
479
- `DEFAULT_TOKENS` is exported.
480
-
481
- ### Fonts
482
-
483
- The picker uses the system font by default (San Francisco on iOS, Roboto on Android) at weights 400 / 500 / 600, so there's nothing to load.
484
-
485
- The picker was designed with **Inter**. To use it, load its static files under these names and pass `INTER_FONTS`. The package doesn't ship or load font files:
486
-
487
- ```tsx
488
- // Expo
489
- import { useFonts } from 'expo-font';
490
- import { Inter_400Regular, Inter_500Medium, Inter_600SemiBold } from '@expo-google-fonts/inter';
491
- import { INTER_FONTS } from 'rn-grid-date-time-picker';
492
-
493
- const [loaded] = useFonts({
494
- 'Inter-Regular': Inter_400Regular,
495
- 'Inter-Medium': Inter_500Medium,
496
- 'Inter-SemiBold': Inter_600SemiBold,
497
- });
498
-
499
- <DateTimePicker theme={{ ...INTER_FONTS }} … />
500
- ```
501
-
502
- In a bare app, add `Inter-Regular.ttf`, `Inter-Medium.ttf` and `Inter-SemiBold.ttf` to your fonts folder (`react-native.config.js` → `assets`) and run `npx react-native-asset`. If a family isn't loaded, iOS and Android fall back to the system font, but every text is drawn at the regular weight.
503
-
504
- Every text in the picker takes its family and size from these tokens, so one `theme` sets the font for all of it:
505
-
506
- ```tsx
507
- // One font file with several weights (or the system font name):
508
- <DateTimePicker theme={{ fontFamily: 'Inter', fontSizeMedium: 15 }} … />
509
-
510
- // One file per weight, as loaded with expo-font or react-native assets:
511
- <DateTimePicker
512
- theme={{
513
- fontRegular: 'Inter-Regular',
514
- fontMedium: 'Inter-Medium',
515
- fontSemiBold: 'Inter-SemiBold',
516
- }}
517
- …
518
- />
519
- ```
520
-
521
- To change a single part, pass a text style through `styles` (for example `styles={{ dayText: { fontSize: 13 } }}`).
522
-
523
- `styles` takes a style for any of these keys:
524
-
525
- - **Containers**: `container`, `sheet`, `sheetBackdrop`, `header`, `title`, `resetButton`, `resetText`, `body`, `footer`, `confirmButton`, `confirmText`.
526
- - **Field**: `field`, `fieldFocused`, `fieldError`, `fieldDisabled`, `fieldText`, `fieldTextDisabled` (the value while disabled; the placeholder keeps its colour), `fieldPlaceholder`, `fieldSegment`, `fieldSegmentFocused`, `fieldSeparator`, `fieldPeriod`, `fieldPeriodSelected`, `fieldPeriodText`, `fieldIcon`, `clearIcon`, `label`, `mandatoryMark`, `helperText`, `instructionText`, `errorText`, `validationText`.
527
- - **Calendar header**: `calendarHeader`, `navArrow`, `navArrowDisabled`, `yearButton`, `yearButtonText`, `monthChipRow`, `monthChip`, `monthChipText`, `monthChipSelected`, `monthChipDisabled`.
528
- - **Weekdays and days**: `weekdayRow`, `weekdayText`, `day`, `dayText`, `dayPressed`, `today`, `todayText`, `selected`, `selectedText`, `rangeStart`, `rangeMiddle`, `rangeEnd`, `rangeFill`, `outside`, `outsideText`, `disabled`, `disabledText`, `holiday`, `holidayText`, `daySubLabel` (the Hijri day in a dual cell).
529
- - **Grids**: `yearGrid`, `yearCell`, `yearCellSelected`, `yearCellDisabled`, `yearCellText`, `yearCellCurrent`, `monthGrid`, `monthCell`, `monthCellSelected`, `monthCellDisabled`, `monthCellText`, `monthCellCurrent` (the outlined current year / month in a `precision` pick).
530
- - **Time**: `timeRow`, `timeLabel`, `timeBox`, `timeBoxFocused`, `timeBoxError`, `timeBoxText`, `timeColon`, `ampmToggle`, `ampmOption`, `ampmOptionSelected`, `ampmOptionDisabled`, `ampmOptionText`, `wheel`, `wheelRow`, `wheelRowSelected`, `wheelRowDisabled` (the row), `wheelText`, `wheelTextSelected`, `wheelTextDisabled` (its text), `wheelHighlight`.
531
- - **Other**: `todayButton`, `todayButtonText`, `emptyState`, `emptyStateText`.
532
-
533
- ## Icons
534
-
535
- The built-in icons are drawn with plain Views, so there's nothing native to install. Each icon gets `{ color, size, width, height }`, where `size` is the smaller of `width` and `height`. By default:
536
-
537
- | Icon | Where | Colour | Size |
538
- |---|---|---|---|
539
- | `calendar` | Field | `accent`, or `disabledText` when the field is disabled | 18 |
540
- | `clear` | Field (with `allowClear`) | `mutedText` | 12 |
541
- | `chevronLeft`, `chevronRight` | Calendar header | `mutedText` | 24 |
542
- | `chevronDown` | Next to the year title | `accent` | 24 |
543
-
544
- Change the colour or size with `iconProps`, or swap the icon with `icons`. The two work together:
545
-
546
- ```tsx
547
- // Your app's own SVG, e.g. with react-native-svg-transformer:
548
- import CalendarSvg from './assets/icons/calendar.svg';
549
-
550
- <DateTimePicker
551
- iconProps={{
552
- calendar: { color: '#2563EB', disabledColor: '#9CA3AF', size: 20 },
553
- clear: { color: '#2563EB', width: 12, height: 12 },
554
- }}
555
- icons={{
556
- // An SVG component that takes width / height; pass the colour on as it expects.
557
- calendar: ({ color, width, height }) => (
558
- <CalendarSvg width={width} height={height} stroke={color} />
559
- ),
560
- chevronDown: null, // hide the caret next to the year
561
- }}
562
- …
563
- />
564
- ```
565
-
566
- The built-in `CalendarIcon`, `ClearIcon`, `ChevronLeftIcon`, `ChevronRightIcon` and `ChevronDownIcon` are exported, so you can use them elsewhere in your app.
567
-
568
- **The clear (×) icon** shows only when `allowClear` is set, the field has a value, and the field is neither disabled nor read-only. `icons={{ clear: null }}` hides it even with `allowClear`. Pressing it calls `onChange('')` right away, with no Confirm, so there's no separate clear handler to pass: your `onChange` receives `''`.
569
-
570
- ## Your own validation
571
-
572
- Every built-in message can be reworded through `strings` (`errorNotAllowed`, `errorTimeNotAllowed`, `errorIncomplete`, `errorMinuteStep(step)`, `errorRangeTooLong(n)` and the rest). For rules only your app knows, pass `validate`. It runs when Confirm is pressed, after the built-in checks pass, with the value about to be saved:
573
-
574
- ```tsx
575
- <DateTimePicker
576
- type="datetime"
577
- value={value}
578
- onChange={setValue}
579
- validate={(v) => {
580
- const at = DateTime.fromISO(v as string);
581
- if (at < DateTime.now().plus({ minutes: 5 })) return 'Pick a time at least 5 minutes from now';
582
- if (at > DateTime.now().plus({ days: 31 })) return 'Pick a time within the next 31 days';
583
- return null;
584
- }}
585
- styles={{ validationText: { textAlign: 'center' } }}
586
- />
587
- ```
588
-
589
- A message keeps the sheet open, saves nothing, calls `onError('VALIDATION', value)`, and shows above the footer (`testID` `${testID}-validation-error`). It is styled by `errorText`, then `validationText`, and disappears as soon as the selection changes. With `commitMode="instant"`, `validate` runs before each save. To stop days or times from being picked at all, use the limit props (`minDate`, `timeBounds`, `disabledDates` …); `validate` is for rules you'd rather explain than grey out.
590
-
591
- ## Your own input
592
-
593
- `renderField` swaps the on-screen field for your own input, with your own icons. Tapping it opens the picker's sheet (or the sheet you give `renderSheet`):
594
-
595
- ```tsx
596
- <DateTimePicker
597
- type="date"
598
- value={value}
599
- onChange={setValue}
600
- dateFormat="dd/mm/yyyy"
601
- renderField={(state) => (
602
- <MyInput
603
- label="Due date"
604
- value={state.displayText} // '21/10/2026', or '' when empty
605
- placeholder="DD/MM/YYYY"
606
- disabled={state.disabled}
607
- onPress={state.open}
608
- rightIcon={<MyCalendarIcon />}
609
- onClear={state.displayText ? state.clear : undefined}
610
- />
611
- )}
612
- />
613
- ```
614
-
615
- `state.clear` is the same as the built-in ×: it calls your `onChange('')`. Calling `setValue('')` yourself does the same thing.
616
-
617
- You can also hide the field and open the picker from anywhere, with `showField={false}`, `visible` and `onClose`:
618
-
619
- ```tsx
620
- <MyInput onPress={() => setOpen(true)} value={value} />
621
- <DateTimePicker showField={false} visible={open} onClose={() => setOpen(false)} value={value} onChange={setValue} type="date" />
622
- ```
623
-
624
- ## Strings / i18n
625
-
626
- Every visible and spoken text is in `strings`, and the defaults are English (`DEFAULT_STRINGS`). Pass any subset. `rangeSeparator` (default `' – '`) joins the two ends of a range in the field text, e.g. `' ↔ '`. A few entries are functions:
627
-
628
- ```ts
629
- errorYearOutOfRange: ({ first, last }) => string;
630
- errorMinuteStep: (step) => string;
631
- errorRangeTooShort: (days) => string;
632
- errorRangeTooLong: (days) => string;
633
- ```
634
-
635
- With i18next:
636
-
637
- ```tsx
638
- import { useMemo } from 'react';
639
- import { useTranslation } from 'react-i18next';
640
- import DateTimePicker, {
641
- type DateTimePickerProps,
642
- type PickerStrings,
643
- } from 'rn-grid-date-time-picker';
644
-
645
- function LocalizedPicker(props: Omit<DateTimePickerProps, 'strings' | 'locale'>) {
646
- const { t, i18n } = useTranslation();
647
- const strings = useMemo<Partial<PickerStrings>>(
648
- () => ({
649
- titleDate: t('picker.titleDate'),
650
- confirm: t('picker.confirm'),
651
- today: t('picker.today'),
652
- errorNotAllowed: t('picker.errors.notAllowed'),
653
- errorMinuteStep: (step) => t('picker.errors.minuteStep', { step }),
654
- errorYearOutOfRange: ({ first, last }) => t('picker.errors.yearRange', { first, last }),
655
- a11yOpen: t('picker.a11y.open'),
656
- }),
657
- [t]
658
- );
659
- return <DateTimePicker {...props} strings={strings} locale={i18n.language} />;
660
- }
661
- ```
662
-
663
- Memoise `strings` (and `theme`) so they aren't rebuilt on every render.
664
-
665
- ## Accessibility
666
-
667
- - Every control has a role, a label and state. Day cells are read as full dates with "today", "holiday", "start of range" or "end of range"; selected and unavailable come from their state, so they aren't said twice. Typed segments include the field's label ("From, Day"). AM/PM in the time row are radio buttons. Month changes are announced.
668
- - Day cells reach a 48 pt touch target. Text grows with the system font size up to 1.4×, then stops so fixed-size parts don't clip.
669
- - Reduce motion is respected: scrolls and snaps jump instead of animating.
670
- - Errors are announced: a live region on Android, an announcement on iOS. The wheel supports increment / decrement actions.
671
-
672
- ## Testing
673
-
674
- Every part gets a testID built from the `testID` prop (`dp` here):
675
-
676
- | testID | Part |
677
- |---|---|
678
- | `dp-trigger-field` | The on-screen field (press to open) |
679
- | `dp-trigger-clear`, `dp-trigger-icon`, `dp-trigger-label`, `dp-trigger-error`, `dp-trigger-instruction` | Its ×, calendar icon, label, error and instruction |
680
- | `dp-trigger-segment-{day,month,year,hour,minute,period}` | Its typed segments (`allowFieldTyping`) |
681
- | `dp-sheet`, `dp-sheet-backdrop` | The sheet panel and its backdrop (the `testID` passed to `renderSheet`) |
682
- | `dp-inline` | The inline container |
683
- | `dp-scroll` | The sheet's scrolling body |
684
- | `dp-reset`, `dp-confirm` | Reset and Confirm |
685
- | `dp-value`, `dp-value-field`, `dp-value-segment-…`, `dp-value-clear`, `dp-value-error` | The field inside the sheet |
686
- | `dp-from`, `dp-to`, `dp-from-wrap`, `dp-to-wrap`, `dp-from-segment-…`, `dp-range-error` | From / To range fields |
687
- | `dp-calendar`, `dp-grid` | The calendar and its day grid |
688
- | `dp-prev`, `dp-next`, `dp-prev-left` / `-right`, `dp-next-left` / `-right`, `dp-title` | Header arrows (the suffix tells which way the chevron points) and the year title |
689
- | `dp-chip-{1–12}` | Month chips |
690
- | `dp-day-{y}-{m}-{d}` | Day cells, e.g. `dp-day-2026-10-24` (no zero padding) |
691
- | `dp-year-{y}`, `dp-month-{m}` | Year and month grid cells |
692
- | `dp-today`, `dp-empty` | The Today button and the empty state |
693
- | `dp-time`, `dp-time-from`, `dp-time-to` | Time rows (one row, or start / end) |
694
- | `dp-time-hour`, `dp-time-minute`, `dp-time-am`, `dp-time-pm` | Typed time boxes and AM / PM |
695
- | `dp-time-wheel`, `dp-time-wheel-{hour,minute,period}`, `…-scroll` | Wheel columns and their scroll views |
696
-
697
- For Jest, no transform changes are needed: `main` points to the CommonJS build. To pin the clock and zone in tests, pass `now` and `timeZone`.
698
-
699
- ## Platform support and known limits
700
-
701
- - **iOS and Android** are the supported targets. The package is pure JS, so it runs in Expo Go.
702
- - **Web** is untested.
703
- - The keyboard's **Done button** is iOS-only: React Native adds it above each box's number pad (`returnKeyType="done"`). Android's number pad has its own.
704
- - **Hijri** needs `Intl` support for `islamic-umalqura` and falls back to Gregorian without it (see above).
705
- - The built-in sheet doesn't add a safe-area inset; use `styles.sheet.paddingBottom` or `renderSheet`.
706
- - A `minuteStep` that doesn't divide 60, an unknown `timeZone`, or a custom `valueFormat.parse` that throws falls back (step 1, the device zone, an empty value) with a warning in development. Errors thrown by your own callbacks (`disabledDates`, `enabledDates`, `timeBounds`, `getConstraints`) are not caught.
707
- - Only one runtime dependency: `luxon`. Exported types don't reference Luxon, so you don't need `@types/luxon`.
129
+ | `type` | `'date' \| 'datetime'` | required | A date, or a date and time |
130
+ | `mode` | `'single' \| 'multiple' \| 'range'` | `'single'` | One date, several, or a range |
131
+ | `value` / `onChange` | `PickerValue` | required | The saved value; `onChange` fires on Confirm |
132
+ | `presentation` | `'sheet' \| 'inline'` | `'sheet'` | A bottom sheet, or in place on the page |
133
+ | `label`, `placeholder` | `string` | – | The field's label and placeholder |
134
+ | `allowTyping` | `boolean` | `false` | Type the date and time in the sheet |
135
+ | `allowClear` | `boolean` | `false` | An × that clears the value |
136
+ | `minDate`, `maxDate` | `{ year, month, day }` | – | The first and last days that can be picked |
137
+ | `disabledWeekdays` | `Weekday[]` | `[]` | Weekdays that can't be picked, e.g. `[6, 7]` |
138
+ | `holidays`, `loadHolidays` | `string[]`, `(year) => Promise<string[]>` | – | Holidays to mark, or to block with `disableHolidays` |
139
+ | `timeInput` | `'typed' \| 'wheel'` | `'typed'` | Typed time boxes or a scrolling wheel |
140
+ | `timeFormat` | `'12h' \| '24h'` | from `locale` | The clock |
141
+ | `minuteStep` | `number` | `1` | Minutes in steps, e.g. `15` |
142
+ | `locale` | BCP-47 tag | the device's | Month and weekday names, date order, first day of the week |
143
+ | `calendarSystem` | `'gregory' \| 'dual' \| 'hijri'` | `'gregory'` | The calendar |
144
+ | `theme` | `Partial<ThemeTokens>` | – | Colours, fonts, corners and sizes |
145
+ | `strings` | `Partial<PickerStrings>` | English | Every visible and spoken text |
146
+
147
+ Every other prop is in [Props](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/props.md).
148
+
149
+ ## How do I…
150
+
151
+ - **Grey out past days, weekends or booked days?** [Limits and validation](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/limits.md)
152
+ - **Check a value with my own rule on Confirm?** [Your own validation](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/limits.md#your-own-validation)
153
+ - **Store epoch milliseconds or UTC midnight?** [Values](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/values.md)
154
+ - **Change the sheet, or show the picker inline?** [Sheet, field and time](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/presentation.md)
155
+ - **Use my own input or my own sheet?** [Your own input](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/presentation.md#your-own-input)
156
+ - **Pick only a month and year?** `precision="month"` in [Props](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/props.md#calendar)
157
+ - **Match my app's colours, fonts and icons?** [Theming, fonts and icons](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/theming.md)
158
+ - **Translate the texts?** [Strings and i18n](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/localization.md#strings--i18n)
159
+ - **Find the testIDs for my tests?** [Accessibility and testing](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/testing.md)
160
+
161
+ All pages: [docs](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/README.md).
162
+
163
+ ## Platform support
164
+
165
+ - **iOS and Android**, in Expo Go and bare React Native apps. Web is untested.
166
+ - **Hijri** needs the platform's `Intl` support for the Islamic calendar. Some Hermes builds on Android lack it, and the picker then falls back to Gregorian.
167
+ - **The built-in sheet** sits on the keyboard while it's up, and keeps the home indicator or Android's navigation bar free below Confirm, read from `react-native-safe-area-context` when your app has it, or from `sheet.bottomInset`.
168
+
169
+ Other known limits are listed in the [docs](https://github.com/Bhairavi-ancy/rn-grid-date-time-picker/blob/main/docs/README.md#platform-support-and-known-limits).
708
170
 
709
171
  ## Contributing
710
172
 
711
- See [CONTRIBUTING.md](CONTRIBUTING.md) for the setup, scripts and the example app, and the [code of conduct](CODE_OF_CONDUCT.md).
173
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the setup, scripts and the example app.
712
174
 
713
175
  ## License
714
176