@cdx-ui/primitives 0.0.1-beta.140 → 0.0.1-beta.142

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 (433) hide show
  1. package/lib/commonjs/calendar/CalendarGrid.js +33 -0
  2. package/lib/commonjs/calendar/CalendarGrid.js.map +1 -0
  3. package/lib/commonjs/calendar/CalendarRoot.js +95 -0
  4. package/lib/commonjs/calendar/CalendarRoot.js.map +1 -0
  5. package/lib/commonjs/calendar/context.js +17 -0
  6. package/lib/commonjs/calendar/context.js.map +1 -0
  7. package/lib/commonjs/calendar/index.js +27 -0
  8. package/lib/commonjs/calendar/index.js.map +1 -0
  9. package/lib/commonjs/calendar/types.js +6 -0
  10. package/lib/commonjs/calendar/types.js.map +1 -0
  11. package/lib/commonjs/checkbox/CheckboxRoot.web.js +91 -28
  12. package/lib/commonjs/checkbox/CheckboxRoot.web.js.map +1 -1
  13. package/lib/commonjs/checkbox/useCheckboxRoot.js +33 -19
  14. package/lib/commonjs/checkbox/useCheckboxRoot.js.map +1 -1
  15. package/lib/commonjs/date-field/DateFieldHiddenInput.js +148 -0
  16. package/lib/commonjs/date-field/DateFieldHiddenInput.js.map +1 -0
  17. package/lib/commonjs/date-field/DateFieldInput.js +122 -0
  18. package/lib/commonjs/date-field/DateFieldInput.js.map +1 -0
  19. package/lib/commonjs/date-field/DateFieldRoot.js +85 -0
  20. package/lib/commonjs/date-field/DateFieldRoot.js.map +1 -0
  21. package/lib/commonjs/date-field/DateFieldSegment.js +92 -0
  22. package/lib/commonjs/date-field/DateFieldSegment.js.map +1 -0
  23. package/lib/commonjs/date-field/context.js +19 -0
  24. package/lib/commonjs/date-field/context.js.map +1 -0
  25. package/lib/commonjs/date-field/index.js +34 -0
  26. package/lib/commonjs/date-field/index.js.map +1 -0
  27. package/lib/commonjs/date-field/segmentIndex.js +23 -0
  28. package/lib/commonjs/date-field/segmentIndex.js.map +1 -0
  29. package/lib/commonjs/date-field/segmentKeyboard.js +169 -0
  30. package/lib/commonjs/date-field/segmentKeyboard.js.map +1 -0
  31. package/lib/commonjs/date-field/types.js +6 -0
  32. package/lib/commonjs/date-field/types.js.map +1 -0
  33. package/lib/commonjs/date-field/useDateFieldSegmentState.js +381 -0
  34. package/lib/commonjs/date-field/useDateFieldSegmentState.js.map +1 -0
  35. package/lib/commonjs/date-field/useRangeDateFieldBridge.js +67 -0
  36. package/lib/commonjs/date-field/useRangeDateFieldBridge.js.map +1 -0
  37. package/lib/commonjs/date-picker/DatePickerRoot.js +123 -0
  38. package/lib/commonjs/date-picker/DatePickerRoot.js.map +1 -0
  39. package/lib/commonjs/date-picker/context.js +17 -0
  40. package/lib/commonjs/date-picker/context.js.map +1 -0
  41. package/lib/commonjs/date-picker/index.js +26 -0
  42. package/lib/commonjs/date-picker/index.js.map +1 -0
  43. package/lib/commonjs/date-range-picker/DateRangePickerRoot.js +144 -0
  44. package/lib/commonjs/date-range-picker/DateRangePickerRoot.js.map +1 -0
  45. package/lib/commonjs/date-range-picker/context.js +23 -0
  46. package/lib/commonjs/date-range-picker/context.js.map +1 -0
  47. package/lib/commonjs/date-range-picker/index.js +26 -0
  48. package/lib/commonjs/date-range-picker/index.js.map +1 -0
  49. package/lib/commonjs/date-time-field/DateTimeFieldHiddenInput.js +150 -0
  50. package/lib/commonjs/date-time-field/DateTimeFieldHiddenInput.js.map +1 -0
  51. package/lib/commonjs/date-time-field/DateTimeFieldInput.js +104 -0
  52. package/lib/commonjs/date-time-field/DateTimeFieldInput.js.map +1 -0
  53. package/lib/commonjs/date-time-field/DateTimeFieldRoot.js +159 -0
  54. package/lib/commonjs/date-time-field/DateTimeFieldRoot.js.map +1 -0
  55. package/lib/commonjs/date-time-field/DateTimeFieldSegment.js +87 -0
  56. package/lib/commonjs/date-time-field/DateTimeFieldSegment.js.map +1 -0
  57. package/lib/commonjs/date-time-field/context.js +17 -0
  58. package/lib/commonjs/date-time-field/context.js.map +1 -0
  59. package/lib/commonjs/date-time-field/index.js +40 -0
  60. package/lib/commonjs/date-time-field/index.js.map +1 -0
  61. package/lib/commonjs/date-time-field/useDateTimeFieldSegmentState.js +564 -0
  62. package/lib/commonjs/date-time-field/useDateTimeFieldSegmentState.js.map +1 -0
  63. package/lib/commonjs/date-time-list/DateTimeListRoot.js +418 -0
  64. package/lib/commonjs/date-time-list/DateTimeListRoot.js.map +1 -0
  65. package/lib/commonjs/date-time-list/context.js +26 -0
  66. package/lib/commonjs/date-time-list/context.js.map +1 -0
  67. package/lib/commonjs/date-time-list/index.js +62 -0
  68. package/lib/commonjs/date-time-list/index.js.map +1 -0
  69. package/lib/commonjs/date-time-picker/DateTimePickerRoot.js +134 -0
  70. package/lib/commonjs/date-time-picker/DateTimePickerRoot.js.map +1 -0
  71. package/lib/commonjs/date-time-picker/context.js +17 -0
  72. package/lib/commonjs/date-time-picker/context.js.map +1 -0
  73. package/lib/commonjs/date-time-picker/index.js +26 -0
  74. package/lib/commonjs/date-time-picker/index.js.map +1 -0
  75. package/lib/commonjs/dialog/DialogRoot.js +1 -1
  76. package/lib/commonjs/dialog/DialogRoot.js.map +1 -1
  77. package/lib/commonjs/index.js +148 -0
  78. package/lib/commonjs/index.js.map +1 -1
  79. package/lib/commonjs/month-calendar/MonthCalendarCell.js +64 -0
  80. package/lib/commonjs/month-calendar/MonthCalendarCell.js.map +1 -0
  81. package/lib/commonjs/month-calendar/MonthCalendarRoot.js +103 -0
  82. package/lib/commonjs/month-calendar/MonthCalendarRoot.js.map +1 -0
  83. package/lib/commonjs/month-calendar/MonthCalendarYearCell.js +63 -0
  84. package/lib/commonjs/month-calendar/MonthCalendarYearCell.js.map +1 -0
  85. package/lib/commonjs/month-calendar/context.js +17 -0
  86. package/lib/commonjs/month-calendar/context.js.map +1 -0
  87. package/lib/commonjs/month-calendar/index.js +34 -0
  88. package/lib/commonjs/month-calendar/index.js.map +1 -0
  89. package/lib/commonjs/month-picker/MonthPickerRoot.js +118 -0
  90. package/lib/commonjs/month-picker/MonthPickerRoot.js.map +1 -0
  91. package/lib/commonjs/month-picker/context.js +17 -0
  92. package/lib/commonjs/month-picker/context.js.map +1 -0
  93. package/lib/commonjs/month-picker/index.js +26 -0
  94. package/lib/commonjs/month-picker/index.js.map +1 -0
  95. package/lib/commonjs/overlay/useAnchorPosition.js +27 -16
  96. package/lib/commonjs/overlay/useAnchorPosition.js.map +1 -1
  97. package/lib/commonjs/overlay/useDismissOverlay.web.js +10 -2
  98. package/lib/commonjs/overlay/useDismissOverlay.web.js.map +1 -1
  99. package/lib/commonjs/overlay/useOverlayPosition.js +5 -2
  100. package/lib/commonjs/overlay/useOverlayPosition.js.map +1 -1
  101. package/lib/commonjs/portal/portal.js +59 -2
  102. package/lib/commonjs/portal/portal.js.map +1 -1
  103. package/lib/commonjs/radio/RadioGroup.js +65 -16
  104. package/lib/commonjs/radio/RadioGroup.js.map +1 -1
  105. package/lib/commonjs/radio/RadioRoot.web.js +114 -26
  106. package/lib/commonjs/radio/RadioRoot.web.js.map +1 -1
  107. package/lib/commonjs/radio/context.js.map +1 -1
  108. package/lib/commonjs/radio/useRadioGroupNavigation.js +79 -0
  109. package/lib/commonjs/radio/useRadioGroupNavigation.js.map +1 -0
  110. package/lib/commonjs/radio/useRadioRoot.js +14 -13
  111. package/lib/commonjs/radio/useRadioRoot.js.map +1 -1
  112. package/lib/commonjs/range-calendar/RangeCalendarRoot.js +148 -0
  113. package/lib/commonjs/range-calendar/RangeCalendarRoot.js.map +1 -0
  114. package/lib/commonjs/range-calendar/context.js +17 -0
  115. package/lib/commonjs/range-calendar/context.js.map +1 -0
  116. package/lib/commonjs/range-calendar/index.js +20 -0
  117. package/lib/commonjs/range-calendar/index.js.map +1 -0
  118. package/lib/commonjs/select/SelectRoot.js +1 -1
  119. package/lib/commonjs/select/SelectRoot.js.map +1 -1
  120. package/lib/commonjs/utils/accessibleLabel.js +23 -0
  121. package/lib/commonjs/utils/accessibleLabel.js.map +1 -0
  122. package/lib/commonjs/utils/createPortal.web.js +21 -0
  123. package/lib/commonjs/utils/createPortal.web.js.map +1 -0
  124. package/lib/module/calendar/CalendarGrid.js +29 -0
  125. package/lib/module/calendar/CalendarGrid.js.map +1 -0
  126. package/lib/module/calendar/CalendarRoot.js +91 -0
  127. package/lib/module/calendar/CalendarRoot.js.map +1 -0
  128. package/lib/module/calendar/context.js +12 -0
  129. package/lib/module/calendar/context.js.map +1 -0
  130. package/lib/module/calendar/index.js +6 -0
  131. package/lib/module/calendar/index.js.map +1 -0
  132. package/lib/module/calendar/types.js +4 -0
  133. package/lib/module/calendar/types.js.map +1 -0
  134. package/lib/module/checkbox/CheckboxRoot.web.js +92 -29
  135. package/lib/module/checkbox/CheckboxRoot.web.js.map +1 -1
  136. package/lib/module/checkbox/useCheckboxRoot.js +34 -20
  137. package/lib/module/checkbox/useCheckboxRoot.js.map +1 -1
  138. package/lib/module/date-field/DateFieldHiddenInput.js +146 -0
  139. package/lib/module/date-field/DateFieldHiddenInput.js.map +1 -0
  140. package/lib/module/date-field/DateFieldInput.js +118 -0
  141. package/lib/module/date-field/DateFieldInput.js.map +1 -0
  142. package/lib/module/date-field/DateFieldRoot.js +81 -0
  143. package/lib/module/date-field/DateFieldRoot.js.map +1 -0
  144. package/lib/module/date-field/DateFieldSegment.js +88 -0
  145. package/lib/module/date-field/DateFieldSegment.js.map +1 -0
  146. package/lib/module/date-field/context.js +15 -0
  147. package/lib/module/date-field/context.js.map +1 -0
  148. package/lib/module/date-field/index.js +7 -0
  149. package/lib/module/date-field/index.js.map +1 -0
  150. package/lib/module/date-field/segmentIndex.js +18 -0
  151. package/lib/module/date-field/segmentIndex.js.map +1 -0
  152. package/lib/module/date-field/segmentKeyboard.js +157 -0
  153. package/lib/module/date-field/segmentKeyboard.js.map +1 -0
  154. package/lib/module/date-field/types.js +4 -0
  155. package/lib/module/date-field/types.js.map +1 -0
  156. package/lib/module/date-field/useDateFieldSegmentState.js +378 -0
  157. package/lib/module/date-field/useDateFieldSegmentState.js.map +1 -0
  158. package/lib/module/date-field/useRangeDateFieldBridge.js +63 -0
  159. package/lib/module/date-field/useRangeDateFieldBridge.js.map +1 -0
  160. package/lib/module/date-picker/DatePickerRoot.js +119 -0
  161. package/lib/module/date-picker/DatePickerRoot.js.map +1 -0
  162. package/lib/module/date-picker/context.js +12 -0
  163. package/lib/module/date-picker/context.js.map +1 -0
  164. package/lib/module/date-picker/index.js +5 -0
  165. package/lib/module/date-picker/index.js.map +1 -0
  166. package/lib/module/date-range-picker/DateRangePickerRoot.js +140 -0
  167. package/lib/module/date-range-picker/DateRangePickerRoot.js.map +1 -0
  168. package/lib/module/date-range-picker/context.js +19 -0
  169. package/lib/module/date-range-picker/context.js.map +1 -0
  170. package/lib/module/date-range-picker/index.js +5 -0
  171. package/lib/module/date-range-picker/index.js.map +1 -0
  172. package/lib/module/date-time-field/DateTimeFieldHiddenInput.js +148 -0
  173. package/lib/module/date-time-field/DateTimeFieldHiddenInput.js.map +1 -0
  174. package/lib/module/date-time-field/DateTimeFieldInput.js +100 -0
  175. package/lib/module/date-time-field/DateTimeFieldInput.js.map +1 -0
  176. package/lib/module/date-time-field/DateTimeFieldRoot.js +154 -0
  177. package/lib/module/date-time-field/DateTimeFieldRoot.js.map +1 -0
  178. package/lib/module/date-time-field/DateTimeFieldSegment.js +83 -0
  179. package/lib/module/date-time-field/DateTimeFieldSegment.js.map +1 -0
  180. package/lib/module/date-time-field/context.js +12 -0
  181. package/lib/module/date-time-field/context.js.map +1 -0
  182. package/lib/module/date-time-field/index.js +7 -0
  183. package/lib/module/date-time-field/index.js.map +1 -0
  184. package/lib/module/date-time-field/useDateTimeFieldSegmentState.js +561 -0
  185. package/lib/module/date-time-field/useDateTimeFieldSegmentState.js.map +1 -0
  186. package/lib/module/date-time-list/DateTimeListRoot.js +416 -0
  187. package/lib/module/date-time-list/DateTimeListRoot.js.map +1 -0
  188. package/lib/module/date-time-list/context.js +20 -0
  189. package/lib/module/date-time-list/context.js.map +1 -0
  190. package/lib/module/date-time-list/index.js +5 -0
  191. package/lib/module/date-time-list/index.js.map +1 -0
  192. package/lib/module/date-time-picker/DateTimePickerRoot.js +130 -0
  193. package/lib/module/date-time-picker/DateTimePickerRoot.js.map +1 -0
  194. package/lib/module/date-time-picker/context.js +12 -0
  195. package/lib/module/date-time-picker/context.js.map +1 -0
  196. package/lib/module/date-time-picker/index.js +5 -0
  197. package/lib/module/date-time-picker/index.js.map +1 -0
  198. package/lib/module/dialog/DialogRoot.js +1 -1
  199. package/lib/module/dialog/DialogRoot.js.map +1 -1
  200. package/lib/module/index.js +11 -2
  201. package/lib/module/index.js.map +1 -1
  202. package/lib/module/month-calendar/MonthCalendarCell.js +60 -0
  203. package/lib/module/month-calendar/MonthCalendarCell.js.map +1 -0
  204. package/lib/module/month-calendar/MonthCalendarRoot.js +99 -0
  205. package/lib/module/month-calendar/MonthCalendarRoot.js.map +1 -0
  206. package/lib/module/month-calendar/MonthCalendarYearCell.js +59 -0
  207. package/lib/module/month-calendar/MonthCalendarYearCell.js.map +1 -0
  208. package/lib/module/month-calendar/context.js +12 -0
  209. package/lib/module/month-calendar/context.js.map +1 -0
  210. package/lib/module/month-calendar/index.js +7 -0
  211. package/lib/module/month-calendar/index.js.map +1 -0
  212. package/lib/module/month-picker/MonthPickerRoot.js +114 -0
  213. package/lib/module/month-picker/MonthPickerRoot.js.map +1 -0
  214. package/lib/module/month-picker/context.js +12 -0
  215. package/lib/module/month-picker/context.js.map +1 -0
  216. package/lib/module/month-picker/index.js +5 -0
  217. package/lib/module/month-picker/index.js.map +1 -0
  218. package/lib/module/overlay/useAnchorPosition.js +27 -16
  219. package/lib/module/overlay/useAnchorPosition.js.map +1 -1
  220. package/lib/module/overlay/useDismissOverlay.web.js +9 -2
  221. package/lib/module/overlay/useDismissOverlay.web.js.map +1 -1
  222. package/lib/module/overlay/useOverlayPosition.js +5 -2
  223. package/lib/module/overlay/useOverlayPosition.js.map +1 -1
  224. package/lib/module/portal/portal.js +59 -2
  225. package/lib/module/portal/portal.js.map +1 -1
  226. package/lib/module/radio/RadioGroup.js +68 -19
  227. package/lib/module/radio/RadioGroup.js.map +1 -1
  228. package/lib/module/radio/RadioRoot.web.js +117 -29
  229. package/lib/module/radio/RadioRoot.web.js.map +1 -1
  230. package/lib/module/radio/context.js.map +1 -1
  231. package/lib/module/radio/useRadioGroupNavigation.js +74 -0
  232. package/lib/module/radio/useRadioGroupNavigation.js.map +1 -0
  233. package/lib/module/radio/useRadioRoot.js +14 -13
  234. package/lib/module/radio/useRadioRoot.js.map +1 -1
  235. package/lib/module/range-calendar/RangeCalendarRoot.js +144 -0
  236. package/lib/module/range-calendar/RangeCalendarRoot.js.map +1 -0
  237. package/lib/module/range-calendar/context.js +12 -0
  238. package/lib/module/range-calendar/context.js.map +1 -0
  239. package/lib/module/range-calendar/index.js +5 -0
  240. package/lib/module/range-calendar/index.js.map +1 -0
  241. package/lib/module/select/SelectRoot.js +1 -1
  242. package/lib/module/select/SelectRoot.js.map +1 -1
  243. package/lib/module/utils/accessibleLabel.js +18 -0
  244. package/lib/module/utils/accessibleLabel.js.map +1 -0
  245. package/lib/module/utils/createPortal.web.js +17 -0
  246. package/lib/module/utils/createPortal.web.js.map +1 -0
  247. package/lib/typescript/calendar/CalendarGrid.d.ts +7 -0
  248. package/lib/typescript/calendar/CalendarGrid.d.ts.map +1 -0
  249. package/lib/typescript/calendar/CalendarRoot.d.ts +10 -0
  250. package/lib/typescript/calendar/CalendarRoot.d.ts.map +1 -0
  251. package/lib/typescript/calendar/context.d.ts +18 -0
  252. package/lib/typescript/calendar/context.d.ts.map +1 -0
  253. package/lib/typescript/calendar/index.d.ts +5 -0
  254. package/lib/typescript/calendar/index.d.ts.map +1 -0
  255. package/lib/typescript/calendar/types.d.ts +29 -0
  256. package/lib/typescript/calendar/types.d.ts.map +1 -0
  257. package/lib/typescript/checkbox/CheckboxRoot.web.d.ts +8 -0
  258. package/lib/typescript/checkbox/CheckboxRoot.web.d.ts.map +1 -1
  259. package/lib/typescript/checkbox/useCheckboxRoot.d.ts +7 -18
  260. package/lib/typescript/checkbox/useCheckboxRoot.d.ts.map +1 -1
  261. package/lib/typescript/date-field/DateFieldHiddenInput.d.ts +4 -0
  262. package/lib/typescript/date-field/DateFieldHiddenInput.d.ts.map +1 -0
  263. package/lib/typescript/date-field/DateFieldInput.d.ts +8 -0
  264. package/lib/typescript/date-field/DateFieldInput.d.ts.map +1 -0
  265. package/lib/typescript/date-field/DateFieldRoot.d.ts +10 -0
  266. package/lib/typescript/date-field/DateFieldRoot.d.ts.map +1 -0
  267. package/lib/typescript/date-field/DateFieldSegment.d.ts +9 -0
  268. package/lib/typescript/date-field/DateFieldSegment.d.ts.map +1 -0
  269. package/lib/typescript/date-field/context.d.ts +33 -0
  270. package/lib/typescript/date-field/context.d.ts.map +1 -0
  271. package/lib/typescript/date-field/index.d.ts +9 -0
  272. package/lib/typescript/date-field/index.d.ts.map +1 -0
  273. package/lib/typescript/date-field/segmentIndex.d.ts +7 -0
  274. package/lib/typescript/date-field/segmentIndex.d.ts.map +1 -0
  275. package/lib/typescript/date-field/segmentKeyboard.d.ts +23 -0
  276. package/lib/typescript/date-field/segmentKeyboard.d.ts.map +1 -0
  277. package/lib/typescript/date-field/types.d.ts +38 -0
  278. package/lib/typescript/date-field/types.d.ts.map +1 -0
  279. package/lib/typescript/date-field/useDateFieldSegmentState.d.ts +26 -0
  280. package/lib/typescript/date-field/useDateFieldSegmentState.d.ts.map +1 -0
  281. package/lib/typescript/date-field/useRangeDateFieldBridge.d.ts +4 -0
  282. package/lib/typescript/date-field/useRangeDateFieldBridge.d.ts.map +1 -0
  283. package/lib/typescript/date-picker/DatePickerRoot.d.ts +28 -0
  284. package/lib/typescript/date-picker/DatePickerRoot.d.ts.map +1 -0
  285. package/lib/typescript/date-picker/context.d.ts +25 -0
  286. package/lib/typescript/date-picker/context.d.ts.map +1 -0
  287. package/lib/typescript/date-picker/index.d.ts +5 -0
  288. package/lib/typescript/date-picker/index.d.ts.map +1 -0
  289. package/lib/typescript/date-range-picker/DateRangePickerRoot.d.ts +43 -0
  290. package/lib/typescript/date-range-picker/DateRangePickerRoot.d.ts.map +1 -0
  291. package/lib/typescript/date-range-picker/context.d.ts +42 -0
  292. package/lib/typescript/date-range-picker/context.d.ts.map +1 -0
  293. package/lib/typescript/date-range-picker/index.d.ts +4 -0
  294. package/lib/typescript/date-range-picker/index.d.ts.map +1 -0
  295. package/lib/typescript/date-time-field/DateTimeFieldHiddenInput.d.ts +4 -0
  296. package/lib/typescript/date-time-field/DateTimeFieldHiddenInput.d.ts.map +1 -0
  297. package/lib/typescript/date-time-field/DateTimeFieldInput.d.ts +10 -0
  298. package/lib/typescript/date-time-field/DateTimeFieldInput.d.ts.map +1 -0
  299. package/lib/typescript/date-time-field/DateTimeFieldRoot.d.ts +24 -0
  300. package/lib/typescript/date-time-field/DateTimeFieldRoot.d.ts.map +1 -0
  301. package/lib/typescript/date-time-field/DateTimeFieldSegment.d.ts +10 -0
  302. package/lib/typescript/date-time-field/DateTimeFieldSegment.d.ts.map +1 -0
  303. package/lib/typescript/date-time-field/context.d.ts +27 -0
  304. package/lib/typescript/date-time-field/context.d.ts.map +1 -0
  305. package/lib/typescript/date-time-field/index.d.ts +8 -0
  306. package/lib/typescript/date-time-field/index.d.ts.map +1 -0
  307. package/lib/typescript/date-time-field/useDateTimeFieldSegmentState.d.ts +26 -0
  308. package/lib/typescript/date-time-field/useDateTimeFieldSegmentState.d.ts.map +1 -0
  309. package/lib/typescript/date-time-list/DateTimeListRoot.d.ts +42 -0
  310. package/lib/typescript/date-time-list/DateTimeListRoot.d.ts.map +1 -0
  311. package/lib/typescript/date-time-list/context.d.ts +29 -0
  312. package/lib/typescript/date-time-list/context.d.ts.map +1 -0
  313. package/lib/typescript/date-time-list/index.d.ts +4 -0
  314. package/lib/typescript/date-time-list/index.d.ts.map +1 -0
  315. package/lib/typescript/date-time-picker/DateTimePickerRoot.d.ts +36 -0
  316. package/lib/typescript/date-time-picker/DateTimePickerRoot.d.ts.map +1 -0
  317. package/lib/typescript/date-time-picker/context.d.ts +25 -0
  318. package/lib/typescript/date-time-picker/context.d.ts.map +1 -0
  319. package/lib/typescript/date-time-picker/index.d.ts +4 -0
  320. package/lib/typescript/date-time-picker/index.d.ts.map +1 -0
  321. package/lib/typescript/dialog/types.d.ts +2 -1
  322. package/lib/typescript/dialog/types.d.ts.map +1 -1
  323. package/lib/typescript/index.d.ts +11 -2
  324. package/lib/typescript/index.d.ts.map +1 -1
  325. package/lib/typescript/month-calendar/MonthCalendarCell.d.ts +9 -0
  326. package/lib/typescript/month-calendar/MonthCalendarCell.d.ts.map +1 -0
  327. package/lib/typescript/month-calendar/MonthCalendarRoot.d.ts +30 -0
  328. package/lib/typescript/month-calendar/MonthCalendarRoot.d.ts.map +1 -0
  329. package/lib/typescript/month-calendar/MonthCalendarYearCell.d.ts +9 -0
  330. package/lib/typescript/month-calendar/MonthCalendarYearCell.d.ts.map +1 -0
  331. package/lib/typescript/month-calendar/context.d.ts +20 -0
  332. package/lib/typescript/month-calendar/context.d.ts.map +1 -0
  333. package/lib/typescript/month-calendar/index.d.ts +7 -0
  334. package/lib/typescript/month-calendar/index.d.ts.map +1 -0
  335. package/lib/typescript/month-picker/MonthPickerRoot.d.ts +29 -0
  336. package/lib/typescript/month-picker/MonthPickerRoot.d.ts.map +1 -0
  337. package/lib/typescript/month-picker/context.d.ts +23 -0
  338. package/lib/typescript/month-picker/context.d.ts.map +1 -0
  339. package/lib/typescript/month-picker/index.d.ts +4 -0
  340. package/lib/typescript/month-picker/index.d.ts.map +1 -0
  341. package/lib/typescript/overlay/useAnchorPosition.d.ts.map +1 -1
  342. package/lib/typescript/overlay/useDismissOverlay.web.d.ts.map +1 -1
  343. package/lib/typescript/overlay/useOverlayPosition.d.ts.map +1 -1
  344. package/lib/typescript/portal/portal.d.ts.map +1 -1
  345. package/lib/typescript/radio/RadioGroup.d.ts.map +1 -1
  346. package/lib/typescript/radio/RadioRoot.web.d.ts +8 -0
  347. package/lib/typescript/radio/RadioRoot.web.d.ts.map +1 -1
  348. package/lib/typescript/radio/context.d.ts +6 -1
  349. package/lib/typescript/radio/context.d.ts.map +1 -1
  350. package/lib/typescript/radio/types.d.ts +7 -0
  351. package/lib/typescript/radio/types.d.ts.map +1 -1
  352. package/lib/typescript/radio/useRadioGroupNavigation.d.ts +17 -0
  353. package/lib/typescript/radio/useRadioGroupNavigation.d.ts.map +1 -0
  354. package/lib/typescript/radio/useRadioRoot.d.ts +4 -18
  355. package/lib/typescript/radio/useRadioRoot.d.ts.map +1 -1
  356. package/lib/typescript/range-calendar/RangeCalendarRoot.d.ts +34 -0
  357. package/lib/typescript/range-calendar/RangeCalendarRoot.d.ts.map +1 -0
  358. package/lib/typescript/range-calendar/context.d.ts +26 -0
  359. package/lib/typescript/range-calendar/context.d.ts.map +1 -0
  360. package/lib/typescript/range-calendar/index.d.ts +5 -0
  361. package/lib/typescript/range-calendar/index.d.ts.map +1 -0
  362. package/lib/typescript/select/types.d.ts +2 -1
  363. package/lib/typescript/select/types.d.ts.map +1 -1
  364. package/lib/typescript/utils/accessibleLabel.d.ts +13 -0
  365. package/lib/typescript/utils/accessibleLabel.d.ts.map +1 -0
  366. package/lib/typescript/utils/createPortal.web.d.ts +17 -0
  367. package/lib/typescript/utils/createPortal.web.d.ts.map +1 -0
  368. package/package.json +3 -2
  369. package/src/calendar/CalendarGrid.tsx +29 -0
  370. package/src/calendar/CalendarRoot.tsx +138 -0
  371. package/src/calendar/context.tsx +28 -0
  372. package/src/calendar/index.ts +4 -0
  373. package/src/calendar/types.ts +30 -0
  374. package/src/checkbox/CheckboxRoot.web.tsx +105 -29
  375. package/src/checkbox/useCheckboxRoot.ts +37 -15
  376. package/src/date-field/DateFieldHiddenInput.tsx +152 -0
  377. package/src/date-field/DateFieldInput.tsx +138 -0
  378. package/src/date-field/DateFieldRoot.tsx +117 -0
  379. package/src/date-field/DateFieldSegment.tsx +97 -0
  380. package/src/date-field/context.tsx +48 -0
  381. package/src/date-field/index.ts +8 -0
  382. package/src/date-field/segmentIndex.tsx +17 -0
  383. package/src/date-field/segmentKeyboard.ts +207 -0
  384. package/src/date-field/types.ts +40 -0
  385. package/src/date-field/useDateFieldSegmentState.ts +455 -0
  386. package/src/date-field/useRangeDateFieldBridge.ts +78 -0
  387. package/src/date-picker/DatePickerRoot.tsx +186 -0
  388. package/src/date-picker/context.tsx +34 -0
  389. package/src/date-picker/index.ts +4 -0
  390. package/src/date-range-picker/DateRangePickerRoot.tsx +236 -0
  391. package/src/date-range-picker/context.tsx +48 -0
  392. package/src/date-range-picker/index.ts +8 -0
  393. package/src/date-time-field/DateTimeFieldHiddenInput.tsx +156 -0
  394. package/src/date-time-field/DateTimeFieldInput.tsx +119 -0
  395. package/src/date-time-field/DateTimeFieldRoot.tsx +209 -0
  396. package/src/date-time-field/DateTimeFieldSegment.tsx +95 -0
  397. package/src/date-time-field/context.tsx +41 -0
  398. package/src/date-time-field/index.ts +7 -0
  399. package/src/date-time-field/useDateTimeFieldSegmentState.ts +672 -0
  400. package/src/date-time-list/DateTimeListRoot.tsx +530 -0
  401. package/src/date-time-list/context.tsx +45 -0
  402. package/src/date-time-list/index.ts +16 -0
  403. package/src/date-time-picker/DateTimePickerRoot.tsx +210 -0
  404. package/src/date-time-picker/context.tsx +33 -0
  405. package/src/date-time-picker/index.ts +7 -0
  406. package/src/dialog/DialogRoot.tsx +1 -1
  407. package/src/dialog/types.ts +2 -1
  408. package/src/index.ts +21 -2
  409. package/src/month-calendar/MonthCalendarCell.tsx +53 -0
  410. package/src/month-calendar/MonthCalendarRoot.tsx +153 -0
  411. package/src/month-calendar/MonthCalendarYearCell.tsx +54 -0
  412. package/src/month-calendar/context.tsx +30 -0
  413. package/src/month-calendar/index.ts +6 -0
  414. package/src/month-picker/MonthPickerRoot.tsx +183 -0
  415. package/src/month-picker/context.tsx +31 -0
  416. package/src/month-picker/index.ts +3 -0
  417. package/src/overlay/useAnchorPosition.ts +25 -11
  418. package/src/overlay/useDismissOverlay.web.ts +10 -2
  419. package/src/overlay/useOverlayPosition.ts +5 -2
  420. package/src/portal/portal.tsx +79 -2
  421. package/src/radio/RadioGroup.tsx +84 -20
  422. package/src/radio/RadioRoot.web.tsx +136 -31
  423. package/src/radio/context.tsx +6 -1
  424. package/src/radio/types.ts +6 -0
  425. package/src/radio/useRadioGroupNavigation.ts +104 -0
  426. package/src/radio/useRadioRoot.ts +18 -11
  427. package/src/range-calendar/RangeCalendarRoot.tsx +213 -0
  428. package/src/range-calendar/context.tsx +33 -0
  429. package/src/range-calendar/index.ts +4 -0
  430. package/src/select/SelectRoot.tsx +1 -1
  431. package/src/select/types.ts +2 -1
  432. package/src/utils/accessibleLabel.ts +22 -0
  433. package/src/utils/createPortal.web.ts +18 -0
@@ -0,0 +1,455 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import {
3
+ formatDateId,
4
+ formatDateSegment,
5
+ formatMonthId,
6
+ getEmptyDateSegmentText,
7
+ parseDateId,
8
+ parseMonthId,
9
+ type DateFieldMode,
10
+ type DateId,
11
+ type DateSegment,
12
+ type DateSegmentType,
13
+ type MonthId,
14
+ } from '@cdx-ui/formatters';
15
+ import type { DateFieldValue } from './context';
16
+ import {
17
+ applySegmentDigit,
18
+ commitSegmentDraft,
19
+ findAdjacentEditableIndex,
20
+ getSegmentMaxLength,
21
+ isSegmentDraftComplete,
22
+ } from './segmentKeyboard';
23
+
24
+ interface UseDateFieldSegmentStateOptions {
25
+ mode: DateFieldMode;
26
+ segments: DateSegment[];
27
+ value: DateFieldValue;
28
+ setValue: (value: DateFieldValue) => void;
29
+ disabled: boolean;
30
+ readOnly: boolean;
31
+ }
32
+
33
+ /** In-progress segment values. Wire `value` is only written when this is complete. */
34
+ interface PartialParts {
35
+ year?: number;
36
+ month?: number;
37
+ day?: number;
38
+ }
39
+
40
+ type PartialPartKey = keyof PartialParts;
41
+
42
+ function isPartialPartKey(type: DateSegmentType): type is PartialPartKey {
43
+ return type === 'year' || type === 'month' || type === 'day';
44
+ }
45
+
46
+ function requiredSegmentTypes(mode: DateFieldMode): PartialPartKey[] {
47
+ return mode === 'month' ? ['month', 'year'] : ['month', 'day', 'year'];
48
+ }
49
+
50
+ function isComplete(parts: PartialParts, mode: DateFieldMode): boolean {
51
+ return requiredSegmentTypes(mode).every((type) => parts[type] != null);
52
+ }
53
+
54
+ function partialPartsToWire(parts: PartialParts, mode: DateFieldMode): DateFieldValue {
55
+ const { year, month, day } = parts;
56
+ if (year == null || month == null) {
57
+ return undefined;
58
+ }
59
+ if (mode === 'month') {
60
+ return formatMonthId({ year, month });
61
+ }
62
+ if (day == null) {
63
+ return undefined;
64
+ }
65
+ return formatDateId({ year, month, day });
66
+ }
67
+
68
+ function partsFromValue(value: DateFieldValue, mode: DateFieldMode): PartialParts {
69
+ if (!value) {
70
+ return {};
71
+ }
72
+ if (mode === 'month') {
73
+ const parsed = parseMonthId(value as MonthId);
74
+ return parsed ? { year: parsed.year, month: parsed.month } : {};
75
+ }
76
+ const parsed = parseDateId(value as DateId);
77
+ return parsed ? { year: parsed.year, month: parsed.month, day: parsed.day } : {};
78
+ }
79
+
80
+ function formatPartialSegment(type: DateSegmentType, value: number): string {
81
+ return formatDateSegment(type, value);
82
+ }
83
+
84
+ export function useDateFieldSegmentState({
85
+ mode,
86
+ segments,
87
+ value,
88
+ setValue,
89
+ disabled,
90
+ readOnly,
91
+ }: UseDateFieldSegmentStateOptions) {
92
+ const [focusedSegmentIndex, setFocusedSegmentIndex] = useState<number | null>(null);
93
+ const [segmentDraft, setSegmentDraft] = useState('');
94
+ const [isDraftDirty, setIsDraftDirty] = useState(false);
95
+ const [partialParts, setPartialParts] = useState<PartialParts>(() => partsFromValue(value, mode));
96
+
97
+ const focusedSegmentIndexRef = useRef(focusedSegmentIndex);
98
+ const segmentDraftRef = useRef(segmentDraft);
99
+ const isDraftDirtyRef = useRef(isDraftDirty);
100
+ const segmentsRef = useRef(segments);
101
+ const valueRef = useRef(value);
102
+ const partialPartsRef = useRef(partialParts);
103
+ focusedSegmentIndexRef.current = focusedSegmentIndex;
104
+ segmentDraftRef.current = segmentDraft;
105
+ isDraftDirtyRef.current = isDraftDirty;
106
+ segmentsRef.current = segments;
107
+ valueRef.current = value;
108
+ partialPartsRef.current = partialParts;
109
+
110
+ // Keep partial parts aligned when a complete controlled value is provided.
111
+ // Do not reset partials when value becomes undefined mid-entry (incomplete date).
112
+ useEffect(() => {
113
+ if (!value) {
114
+ if (focusedSegmentIndexRef.current == null && !isDraftDirtyRef.current) {
115
+ partialPartsRef.current = {};
116
+ setPartialParts({});
117
+ }
118
+ return;
119
+ }
120
+ const next = partsFromValue(value, mode);
121
+ partialPartsRef.current = next;
122
+ setPartialParts(next);
123
+ }, [value, mode]);
124
+
125
+ const setDraftState = (draft: string, dirty: boolean, index = focusedSegmentIndexRef.current) => {
126
+ if (index != null) {
127
+ setFocusedSegmentIndex(index);
128
+ focusedSegmentIndexRef.current = index;
129
+ }
130
+ setSegmentDraft(draft);
131
+ setIsDraftDirty(dirty);
132
+ segmentDraftRef.current = draft;
133
+ isDraftDirtyRef.current = dirty;
134
+ };
135
+
136
+ const writePartial = useCallback(
137
+ (next: PartialParts) => {
138
+ partialPartsRef.current = next;
139
+ setPartialParts(next);
140
+
141
+ if (isComplete(next, mode)) {
142
+ const wire = partialPartsToWire(next, mode);
143
+ if (wire !== undefined) {
144
+ setValue(wire);
145
+ valueRef.current = wire;
146
+ }
147
+ return;
148
+ }
149
+
150
+ // Incomplete — never invent year/day defaults onto the wire value.
151
+ if (valueRef.current !== undefined) {
152
+ setValue(undefined);
153
+ valueRef.current = undefined;
154
+ }
155
+ },
156
+ [mode, setValue],
157
+ );
158
+
159
+ const clearAll = useCallback(() => {
160
+ partialPartsRef.current = {};
161
+ setPartialParts({});
162
+ setValue(undefined);
163
+ valueRef.current = undefined;
164
+ }, [setValue]);
165
+
166
+ const commitSegmentValue = useCallback(
167
+ (segmentType: DateSegment['type'], segmentValue: number) => {
168
+ if (disabled || readOnly || !isPartialPartKey(segmentType)) {
169
+ return;
170
+ }
171
+ writePartial({
172
+ ...partialPartsRef.current,
173
+ [segmentType]: segmentValue,
174
+ });
175
+ },
176
+ [disabled, readOnly, writePartial],
177
+ );
178
+
179
+ const clearSegmentValue = useCallback(
180
+ (segmentType: DateSegment['type']) => {
181
+ if (!isPartialPartKey(segmentType)) {
182
+ return;
183
+ }
184
+ const { [segmentType]: _cleared, ...next } = partialPartsRef.current;
185
+ writePartial(next);
186
+ },
187
+ [writePartial],
188
+ );
189
+
190
+ const commitFocusedSegment = useCallback(
191
+ (draft: string) => {
192
+ const index = focusedSegmentIndexRef.current;
193
+ if (index == null) {
194
+ return;
195
+ }
196
+ const segment = segmentsRef.current[index];
197
+ if (!segment?.isEditable) {
198
+ return;
199
+ }
200
+ if (draft === '') {
201
+ clearSegmentValue(segment.type);
202
+ return;
203
+ }
204
+ const parsed = commitSegmentDraft(segment, draft);
205
+ if (parsed != null) {
206
+ commitSegmentValue(segment.type, parsed);
207
+ }
208
+ },
209
+ [clearSegmentValue, commitSegmentValue],
210
+ );
211
+
212
+ const initialDraftForSegment = (segment: DateSegment | undefined): string => {
213
+ if (!segment) {
214
+ return '';
215
+ }
216
+ const partial = partialPartsRef.current[segment.type as keyof PartialParts];
217
+ if (partial != null) {
218
+ return formatPartialSegment(segment.type, partial);
219
+ }
220
+ if (segment.value == null) {
221
+ return '';
222
+ }
223
+ return segment.text;
224
+ };
225
+
226
+ const focusSegment = useCallback(
227
+ (index: number) => {
228
+ if (disabled || readOnly) {
229
+ return;
230
+ }
231
+ const segment = segmentsRef.current[index];
232
+ if (!segment?.isEditable) {
233
+ return;
234
+ }
235
+ setDraftState(initialDraftForSegment(segment), false, index);
236
+ },
237
+ [disabled, readOnly],
238
+ );
239
+
240
+ const blurSegment = useCallback(
241
+ (index: number) => {
242
+ if (focusedSegmentIndexRef.current !== index) {
243
+ return;
244
+ }
245
+ const segment = segmentsRef.current[index];
246
+ if (segment?.isEditable && isDraftDirtyRef.current) {
247
+ commitFocusedSegment(segmentDraftRef.current);
248
+ }
249
+ setFocusedSegmentIndex(null);
250
+ setSegmentDraft('');
251
+ setIsDraftDirty(false);
252
+ focusedSegmentIndexRef.current = null;
253
+ segmentDraftRef.current = '';
254
+ isDraftDirtyRef.current = false;
255
+ },
256
+ [commitFocusedSegment],
257
+ );
258
+
259
+ const focusNextEditableSegment = useCallback(() => {
260
+ const current = focusedSegmentIndexRef.current;
261
+ if (current == null) {
262
+ return;
263
+ }
264
+ const next = findAdjacentEditableIndex(segmentsRef.current, current, 1);
265
+ if (next == null) {
266
+ return;
267
+ }
268
+ setDraftState(initialDraftForSegment(segmentsRef.current[next]), false, next);
269
+ }, []);
270
+
271
+ const focusPrevEditableSegment = useCallback(() => {
272
+ const current = focusedSegmentIndexRef.current;
273
+ if (current == null) {
274
+ return;
275
+ }
276
+ const prev = findAdjacentEditableIndex(segmentsRef.current, current, -1);
277
+ if (prev == null) {
278
+ return;
279
+ }
280
+ setDraftState(initialDraftForSegment(segmentsRef.current[prev]), false, prev);
281
+ }, []);
282
+
283
+ const handleSegmentDigit = useCallback(
284
+ (input: string) => {
285
+ if (focusedSegmentIndexRef.current == null || disabled || readOnly) {
286
+ return;
287
+ }
288
+
289
+ let index = focusedSegmentIndexRef.current;
290
+ let draft = segmentDraftRef.current;
291
+ let dirty = isDraftDirtyRef.current;
292
+ const currentSegments = segmentsRef.current;
293
+ const queue = input.split('').filter((char) => /^\d$/.test(char));
294
+
295
+ while (queue.length > 0) {
296
+ const digit = queue.shift() ?? '';
297
+ const segment = currentSegments[index];
298
+ if (!segment?.isEditable) {
299
+ break;
300
+ }
301
+ const {
302
+ draft: nextDraft,
303
+ isDraftDirty: nextDirty,
304
+ shouldCommit,
305
+ spillDigit,
306
+ } = applySegmentDigit(draft, segment.text, dirty, digit, segment.type);
307
+ draft = nextDraft;
308
+ dirty = nextDirty;
309
+ if (shouldCommit) {
310
+ const parsed = commitSegmentDraft(segment, draft);
311
+ if (parsed != null) {
312
+ commitSegmentValue(segment.type, parsed);
313
+ }
314
+ const next = findAdjacentEditableIndex(currentSegments, index, 1);
315
+ if (next == null) {
316
+ dirty = false;
317
+ break;
318
+ }
319
+ index = next;
320
+ draft = initialDraftForSegment(currentSegments[next]);
321
+ dirty = false;
322
+ if (spillDigit) {
323
+ queue.unshift(spillDigit);
324
+ }
325
+ }
326
+ }
327
+
328
+ setDraftState(draft, dirty, index);
329
+ },
330
+ [commitSegmentValue, disabled, readOnly],
331
+ );
332
+
333
+ const handleSegmentInputChange = useCallback(
334
+ (raw: string) => {
335
+ if (focusedSegmentIndexRef.current == null || disabled || readOnly) {
336
+ return;
337
+ }
338
+
339
+ const index = focusedSegmentIndexRef.current;
340
+ const segment = segmentsRef.current[index];
341
+ if (!segment?.isEditable) {
342
+ return;
343
+ }
344
+
345
+ const maxLength = getSegmentMaxLength(segment.type);
346
+ const digits = raw.replace(/\D/g, '');
347
+ const prevDigits = segmentDraftRef.current.replace(/\D/g, '');
348
+
349
+ if (digits === prevDigits) {
350
+ return;
351
+ }
352
+
353
+ if (digits.length === 0) {
354
+ setDraftState('', true, index);
355
+ clearSegmentValue(segment.type);
356
+ return;
357
+ }
358
+
359
+ if (digits.length > prevDigits.length && digits.startsWith(prevDigits)) {
360
+ handleSegmentDigit(digits.slice(prevDigits.length));
361
+ return;
362
+ }
363
+
364
+ if (digits.length > maxLength) {
365
+ setDraftState('', true, index);
366
+ handleSegmentDigit(digits);
367
+ return;
368
+ }
369
+
370
+ // Same-length replace or shorten — also auto-advance when draft is unambiguous.
371
+ setDraftState(digits, true, index);
372
+ if (isSegmentDraftComplete(segment.type, digits)) {
373
+ const parsed = commitSegmentDraft(segment, digits);
374
+ if (parsed != null) {
375
+ commitSegmentValue(segment.type, parsed);
376
+ }
377
+ const next = findAdjacentEditableIndex(segmentsRef.current, index, 1);
378
+ if (next == null) {
379
+ setDraftState(digits, false, index);
380
+ return;
381
+ }
382
+ setDraftState(initialDraftForSegment(segmentsRef.current[next]), false, next);
383
+ }
384
+ },
385
+ [clearSegmentValue, commitSegmentValue, disabled, handleSegmentDigit, readOnly],
386
+ );
387
+
388
+ const handleSegmentBackspace = useCallback(() => {
389
+ if (focusedSegmentIndexRef.current == null || disabled || readOnly) {
390
+ return;
391
+ }
392
+
393
+ const index = focusedSegmentIndexRef.current;
394
+ const segment = segmentsRef.current[index];
395
+ const draft = segmentDraftRef.current.replace(/\D/g, '');
396
+
397
+ if (draft.length > 0) {
398
+ const nextDraft = draft.slice(0, -1);
399
+ setDraftState(nextDraft, true, index);
400
+ if (nextDraft.length === 0 && segment) {
401
+ clearSegmentValue(segment.type);
402
+ }
403
+ return;
404
+ }
405
+
406
+ const prev = findAdjacentEditableIndex(segmentsRef.current, index, -1);
407
+ if (prev == null) {
408
+ clearAll();
409
+ return;
410
+ }
411
+ setDraftState(initialDraftForSegment(segmentsRef.current[prev]), false, prev);
412
+ }, [clearAll, clearSegmentValue, disabled, readOnly]);
413
+
414
+ const getSegmentDisplayText = useCallback(
415
+ (index: number) => {
416
+ const segment = segments[index];
417
+ if (!segment) {
418
+ return '';
419
+ }
420
+ if (focusedSegmentIndex === index) {
421
+ if (segmentDraft === '') {
422
+ return getEmptyDateSegmentText(segment.type) || segment.text;
423
+ }
424
+ return segmentDraft;
425
+ }
426
+
427
+ const partial = partialParts[segment.type as keyof PartialParts];
428
+ if (partial != null) {
429
+ return formatPartialSegment(segment.type, partial);
430
+ }
431
+
432
+ if (segment.value != null) {
433
+ return segment.text;
434
+ }
435
+
436
+ return getEmptyDateSegmentText(segment.type) || segment.text;
437
+ },
438
+ [focusedSegmentIndex, partialParts, segmentDraft, segments],
439
+ );
440
+
441
+ return {
442
+ focusedSegmentIndex,
443
+ segmentDraft,
444
+ setFocusedSegmentIndex,
445
+ focusSegment,
446
+ blurSegment,
447
+ focusNextEditableSegment,
448
+ focusPrevEditableSegment,
449
+ handleSegmentDigit,
450
+ handleSegmentInputChange,
451
+ handleSegmentBackspace,
452
+ getSegmentDisplayText,
453
+ onSegmentChange: commitSegmentValue,
454
+ };
455
+ }
@@ -0,0 +1,78 @@
1
+ import { useCallback, useMemo } from 'react';
2
+ import { getDateFieldSegments, resolveDateComponentLabels, type DateId } from '@cdx-ui/formatters';
3
+ import type { DateRangePickerContextValue } from '../date-range-picker/context';
4
+ import type { DateFieldContextValue, DateFieldValue } from './context';
5
+ import { useDateFieldSegmentState } from './useDateFieldSegmentState';
6
+
7
+ const DEFAULT_LOCALE = 'en-US';
8
+
9
+ export function useRangeDateFieldBridge(
10
+ slot: 'start' | 'end',
11
+ rangeCtx: DateRangePickerContextValue | null,
12
+ ): DateFieldContextValue | null {
13
+ const locale = rangeCtx?.locale ?? DEFAULT_LOCALE;
14
+ const labels = rangeCtx?.labels ?? resolveDateComponentLabels();
15
+ const value: DateFieldValue = rangeCtx
16
+ ? slot === 'start'
17
+ ? rangeCtx.startValue
18
+ : rangeCtx.endValue
19
+ : undefined;
20
+
21
+ const segments = useMemo(
22
+ () => (rangeCtx ? getDateFieldSegments(value, { mode: 'date', locale }) : []),
23
+ [rangeCtx, value, locale],
24
+ );
25
+
26
+ const setValue = useCallback(
27
+ (next: DateFieldValue) => {
28
+ if (!rangeCtx) {
29
+ return;
30
+ }
31
+ if (slot === 'start') {
32
+ if (!next) {
33
+ return;
34
+ }
35
+ rangeCtx.onRangeChange?.({
36
+ startId: next as DateId,
37
+ endId: rangeCtx.endValue,
38
+ });
39
+ return;
40
+ }
41
+ if (!rangeCtx.startValue) {
42
+ return;
43
+ }
44
+ rangeCtx.onRangeChange?.({
45
+ startId: rangeCtx.startValue,
46
+ endId: next as DateId | undefined,
47
+ });
48
+ },
49
+ [rangeCtx, slot],
50
+ );
51
+
52
+ const segmentState = useDateFieldSegmentState({
53
+ mode: 'date',
54
+ segments,
55
+ value,
56
+ setValue,
57
+ disabled: !!rangeCtx?.disabled,
58
+ readOnly: !!rangeCtx?.readOnly,
59
+ });
60
+
61
+ return useMemo(() => {
62
+ if (!rangeCtx) {
63
+ return null;
64
+ }
65
+ return {
66
+ value,
67
+ onValueChange: setValue,
68
+ mode: 'date' as const,
69
+ locale,
70
+ labels,
71
+ segments,
72
+ disabled: rangeCtx.disabled,
73
+ readOnly: rangeCtx.readOnly,
74
+ invalid: rangeCtx.invalid,
75
+ ...segmentState,
76
+ };
77
+ }, [rangeCtx, value, setValue, locale, labels, segments, segmentState]);
78
+ }
@@ -0,0 +1,186 @@
1
+ import {
2
+ forwardRef,
3
+ useCallback,
4
+ useEffect,
5
+ useMemo,
6
+ useRef,
7
+ type ComponentRef,
8
+ type ReactNode,
9
+ } from 'react';
10
+ import { View, type ViewProps } from 'react-native';
11
+ import type { DateComponentLabels, DateId } from '@cdx-ui/formatters';
12
+ import { resolveDateComponentLabels } from '@cdx-ui/formatters';
13
+ import { mergeRefs, useControllableState } from '@cdx-ui/utils';
14
+ import { DateFieldRoot } from '../date-field/DateFieldRoot';
15
+ import { Slot } from '../slot';
16
+ import { dataAttributes, mergeDataAttributes } from '../utils/dataAttributes';
17
+ import { DatePickerContext, type PickerSurfaceType } from './context';
18
+
19
+ export interface DatePickerRootProps extends Omit<ViewProps, 'children'> {
20
+ asChild?: boolean;
21
+ children?: ReactNode;
22
+ className?: string;
23
+ value?: DateId;
24
+ defaultValue?: DateId;
25
+ onValueChange?: (value: DateId | undefined) => void;
26
+ /** Controlled open state. Use `defaultOpen` for the uncontrolled variant. */
27
+ isOpen?: boolean;
28
+ defaultOpen?: boolean;
29
+ onOpenChange?: (open: boolean) => void;
30
+ isDisabled?: boolean;
31
+ isReadOnly?: boolean;
32
+ isInvalid?: boolean;
33
+ isRequired?: boolean;
34
+ /** Earliest selectable date, applied to the embedded calendar. Build with `dateId(...)`. */
35
+ minValue?: DateId;
36
+ /** Latest selectable date, applied to the embedded calendar. Build with `dateId(...)`. */
37
+ maxValue?: DateId;
38
+ name?: string;
39
+ locale?: string;
40
+ labels?: Partial<DateComponentLabels>;
41
+ }
42
+
43
+ export const DatePickerRoot = forwardRef<ComponentRef<typeof View>, DatePickerRootProps>(
44
+ (
45
+ {
46
+ asChild,
47
+ children,
48
+ value: valueProp,
49
+ defaultValue,
50
+ onValueChange,
51
+ isOpen: openProp,
52
+ defaultOpen = false,
53
+ onOpenChange,
54
+ isDisabled: disabled = false,
55
+ isReadOnly,
56
+ isInvalid,
57
+ isRequired,
58
+ minValue,
59
+ maxValue,
60
+ locale = 'en-US',
61
+ labels: labelsProp,
62
+ ...props
63
+ },
64
+ ref,
65
+ ) => {
66
+ const labels = useMemo(() => resolveDateComponentLabels(labelsProp), [labelsProp]);
67
+ const [value, setValue] = useControllableState<DateId | undefined>({
68
+ prop: valueProp,
69
+ defaultProp: defaultValue,
70
+ onChange: (next) => {
71
+ onValueChange?.(next);
72
+ },
73
+ });
74
+
75
+ const [open, setOpenState] = useControllableState<boolean>({
76
+ prop: openProp,
77
+ defaultProp: defaultOpen,
78
+ onChange: onOpenChange,
79
+ });
80
+
81
+ const [draftValue, setDraftValue] = useControllableState<DateId | undefined>({
82
+ prop: undefined,
83
+ defaultProp: value,
84
+ });
85
+
86
+ const surfacesRef = useRef<Set<PickerSurfaceType>>(new Set());
87
+ const anchorRef = useRef<ComponentRef<typeof View>>(null);
88
+ const triggerRef = useRef<ComponentRef<typeof View>>(null);
89
+
90
+ const setOpen = useCallback(
91
+ (next: boolean) => {
92
+ if (disabled && next) {
93
+ return;
94
+ }
95
+ if (next) {
96
+ setDraftValue(value);
97
+ }
98
+ setOpenState(next);
99
+ },
100
+ [disabled, setDraftValue, setOpenState, value],
101
+ );
102
+
103
+ const registerSurface = useCallback((type: PickerSurfaceType) => {
104
+ if (surfacesRef.current.has(type)) {
105
+ return;
106
+ }
107
+ surfacesRef.current.add(type);
108
+ if (surfacesRef.current.size > 1) {
109
+ console.warn(
110
+ '[Forge UI] DatePicker: multiple presentation surfaces detected. Use only one of Popover, Dialog, or BottomSheet.',
111
+ );
112
+ }
113
+ }, []);
114
+
115
+ useEffect(() => {
116
+ setDraftValue(value);
117
+ }, [setDraftValue, value]);
118
+
119
+ useEffect(() => {
120
+ if (!open) {
121
+ surfacesRef.current.clear();
122
+ }
123
+ }, [open]);
124
+
125
+ const contextValue = useMemo(
126
+ () => ({
127
+ value,
128
+ onValueChange: setValue,
129
+ draftValue,
130
+ setDraftValue,
131
+ open: open ?? false,
132
+ setOpen,
133
+ disabled,
134
+ minValue,
135
+ maxValue,
136
+ locale,
137
+ labels,
138
+ registerSurface,
139
+ anchorRef,
140
+ triggerRef,
141
+ }),
142
+ [
143
+ value,
144
+ setValue,
145
+ draftValue,
146
+ setDraftValue,
147
+ open,
148
+ setOpen,
149
+ disabled,
150
+ minValue,
151
+ maxValue,
152
+ locale,
153
+ labels,
154
+ registerSurface,
155
+ ],
156
+ );
157
+
158
+ const Comp = asChild ? Slot : View;
159
+
160
+ return (
161
+ <DatePickerContext.Provider value={contextValue}>
162
+ <Comp
163
+ ref={mergeRefs(ref, anchorRef)}
164
+ {...props}
165
+ {...mergeDataAttributes(props, dataAttributes({ disabled, open }))}
166
+ >
167
+ <DateFieldRoot
168
+ value={value}
169
+ onValueChange={(next) => setValue(next as DateId | undefined)}
170
+ mode="date"
171
+ locale={locale}
172
+ labels={labelsProp}
173
+ isDisabled={disabled}
174
+ isReadOnly={isReadOnly}
175
+ isInvalid={isInvalid}
176
+ isRequired={isRequired}
177
+ >
178
+ {children}
179
+ </DateFieldRoot>
180
+ </Comp>
181
+ </DatePickerContext.Provider>
182
+ );
183
+ },
184
+ );
185
+
186
+ DatePickerRoot.displayName = 'DatePickerRoot';