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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. package/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/date-field/DateFieldHiddenInput.js +148 -0
  12. package/lib/commonjs/date-field/DateFieldHiddenInput.js.map +1 -0
  13. package/lib/commonjs/date-field/DateFieldInput.js +122 -0
  14. package/lib/commonjs/date-field/DateFieldInput.js.map +1 -0
  15. package/lib/commonjs/date-field/DateFieldRoot.js +85 -0
  16. package/lib/commonjs/date-field/DateFieldRoot.js.map +1 -0
  17. package/lib/commonjs/date-field/DateFieldSegment.js +92 -0
  18. package/lib/commonjs/date-field/DateFieldSegment.js.map +1 -0
  19. package/lib/commonjs/date-field/context.js +19 -0
  20. package/lib/commonjs/date-field/context.js.map +1 -0
  21. package/lib/commonjs/date-field/index.js +34 -0
  22. package/lib/commonjs/date-field/index.js.map +1 -0
  23. package/lib/commonjs/date-field/segmentIndex.js +23 -0
  24. package/lib/commonjs/date-field/segmentIndex.js.map +1 -0
  25. package/lib/commonjs/date-field/segmentKeyboard.js +169 -0
  26. package/lib/commonjs/date-field/segmentKeyboard.js.map +1 -0
  27. package/lib/commonjs/date-field/types.js +6 -0
  28. package/lib/commonjs/date-field/types.js.map +1 -0
  29. package/lib/commonjs/date-field/useDateFieldSegmentState.js +381 -0
  30. package/lib/commonjs/date-field/useDateFieldSegmentState.js.map +1 -0
  31. package/lib/commonjs/date-field/useRangeDateFieldBridge.js +67 -0
  32. package/lib/commonjs/date-field/useRangeDateFieldBridge.js.map +1 -0
  33. package/lib/commonjs/date-picker/DatePickerRoot.js +123 -0
  34. package/lib/commonjs/date-picker/DatePickerRoot.js.map +1 -0
  35. package/lib/commonjs/date-picker/context.js +17 -0
  36. package/lib/commonjs/date-picker/context.js.map +1 -0
  37. package/lib/commonjs/date-picker/index.js +26 -0
  38. package/lib/commonjs/date-picker/index.js.map +1 -0
  39. package/lib/commonjs/date-range-picker/DateRangePickerRoot.js +144 -0
  40. package/lib/commonjs/date-range-picker/DateRangePickerRoot.js.map +1 -0
  41. package/lib/commonjs/date-range-picker/context.js +23 -0
  42. package/lib/commonjs/date-range-picker/context.js.map +1 -0
  43. package/lib/commonjs/date-range-picker/index.js +26 -0
  44. package/lib/commonjs/date-range-picker/index.js.map +1 -0
  45. package/lib/commonjs/date-time-field/DateTimeFieldHiddenInput.js +150 -0
  46. package/lib/commonjs/date-time-field/DateTimeFieldHiddenInput.js.map +1 -0
  47. package/lib/commonjs/date-time-field/DateTimeFieldInput.js +104 -0
  48. package/lib/commonjs/date-time-field/DateTimeFieldInput.js.map +1 -0
  49. package/lib/commonjs/date-time-field/DateTimeFieldRoot.js +159 -0
  50. package/lib/commonjs/date-time-field/DateTimeFieldRoot.js.map +1 -0
  51. package/lib/commonjs/date-time-field/DateTimeFieldSegment.js +87 -0
  52. package/lib/commonjs/date-time-field/DateTimeFieldSegment.js.map +1 -0
  53. package/lib/commonjs/date-time-field/context.js +17 -0
  54. package/lib/commonjs/date-time-field/context.js.map +1 -0
  55. package/lib/commonjs/date-time-field/index.js +40 -0
  56. package/lib/commonjs/date-time-field/index.js.map +1 -0
  57. package/lib/commonjs/date-time-field/useDateTimeFieldSegmentState.js +564 -0
  58. package/lib/commonjs/date-time-field/useDateTimeFieldSegmentState.js.map +1 -0
  59. package/lib/commonjs/date-time-list/DateTimeListRoot.js +418 -0
  60. package/lib/commonjs/date-time-list/DateTimeListRoot.js.map +1 -0
  61. package/lib/commonjs/date-time-list/context.js +26 -0
  62. package/lib/commonjs/date-time-list/context.js.map +1 -0
  63. package/lib/commonjs/date-time-list/index.js +62 -0
  64. package/lib/commonjs/date-time-list/index.js.map +1 -0
  65. package/lib/commonjs/date-time-picker/DateTimePickerRoot.js +134 -0
  66. package/lib/commonjs/date-time-picker/DateTimePickerRoot.js.map +1 -0
  67. package/lib/commonjs/date-time-picker/context.js +17 -0
  68. package/lib/commonjs/date-time-picker/context.js.map +1 -0
  69. package/lib/commonjs/date-time-picker/index.js +26 -0
  70. package/lib/commonjs/date-time-picker/index.js.map +1 -0
  71. package/lib/commonjs/dialog/DialogRoot.js +1 -1
  72. package/lib/commonjs/dialog/DialogRoot.js.map +1 -1
  73. package/lib/commonjs/index.js +148 -0
  74. package/lib/commonjs/index.js.map +1 -1
  75. package/lib/commonjs/month-calendar/MonthCalendarCell.js +64 -0
  76. package/lib/commonjs/month-calendar/MonthCalendarCell.js.map +1 -0
  77. package/lib/commonjs/month-calendar/MonthCalendarRoot.js +103 -0
  78. package/lib/commonjs/month-calendar/MonthCalendarRoot.js.map +1 -0
  79. package/lib/commonjs/month-calendar/MonthCalendarYearCell.js +63 -0
  80. package/lib/commonjs/month-calendar/MonthCalendarYearCell.js.map +1 -0
  81. package/lib/commonjs/month-calendar/context.js +17 -0
  82. package/lib/commonjs/month-calendar/context.js.map +1 -0
  83. package/lib/commonjs/month-calendar/index.js +34 -0
  84. package/lib/commonjs/month-calendar/index.js.map +1 -0
  85. package/lib/commonjs/month-picker/MonthPickerRoot.js +118 -0
  86. package/lib/commonjs/month-picker/MonthPickerRoot.js.map +1 -0
  87. package/lib/commonjs/month-picker/context.js +17 -0
  88. package/lib/commonjs/month-picker/context.js.map +1 -0
  89. package/lib/commonjs/month-picker/index.js +26 -0
  90. package/lib/commonjs/month-picker/index.js.map +1 -0
  91. package/lib/commonjs/overlay/useAnchorPosition.js +27 -16
  92. package/lib/commonjs/overlay/useAnchorPosition.js.map +1 -1
  93. package/lib/commonjs/overlay/useDismissOverlay.web.js +10 -2
  94. package/lib/commonjs/overlay/useDismissOverlay.web.js.map +1 -1
  95. package/lib/commonjs/overlay/useOverlayPosition.js +5 -2
  96. package/lib/commonjs/overlay/useOverlayPosition.js.map +1 -1
  97. package/lib/commonjs/portal/portal.js +59 -2
  98. package/lib/commonjs/portal/portal.js.map +1 -1
  99. package/lib/commonjs/range-calendar/RangeCalendarRoot.js +148 -0
  100. package/lib/commonjs/range-calendar/RangeCalendarRoot.js.map +1 -0
  101. package/lib/commonjs/range-calendar/context.js +17 -0
  102. package/lib/commonjs/range-calendar/context.js.map +1 -0
  103. package/lib/commonjs/range-calendar/index.js +20 -0
  104. package/lib/commonjs/range-calendar/index.js.map +1 -0
  105. package/lib/commonjs/select/SelectRoot.js +1 -1
  106. package/lib/commonjs/select/SelectRoot.js.map +1 -1
  107. package/lib/commonjs/utils/accessibleLabel.js +23 -0
  108. package/lib/commonjs/utils/accessibleLabel.js.map +1 -0
  109. package/lib/commonjs/utils/createPortal.web.js +21 -0
  110. package/lib/commonjs/utils/createPortal.web.js.map +1 -0
  111. package/lib/module/calendar/CalendarGrid.js +29 -0
  112. package/lib/module/calendar/CalendarGrid.js.map +1 -0
  113. package/lib/module/calendar/CalendarRoot.js +91 -0
  114. package/lib/module/calendar/CalendarRoot.js.map +1 -0
  115. package/lib/module/calendar/context.js +12 -0
  116. package/lib/module/calendar/context.js.map +1 -0
  117. package/lib/module/calendar/index.js +6 -0
  118. package/lib/module/calendar/index.js.map +1 -0
  119. package/lib/module/calendar/types.js +4 -0
  120. package/lib/module/calendar/types.js.map +1 -0
  121. package/lib/module/date-field/DateFieldHiddenInput.js +146 -0
  122. package/lib/module/date-field/DateFieldHiddenInput.js.map +1 -0
  123. package/lib/module/date-field/DateFieldInput.js +118 -0
  124. package/lib/module/date-field/DateFieldInput.js.map +1 -0
  125. package/lib/module/date-field/DateFieldRoot.js +81 -0
  126. package/lib/module/date-field/DateFieldRoot.js.map +1 -0
  127. package/lib/module/date-field/DateFieldSegment.js +88 -0
  128. package/lib/module/date-field/DateFieldSegment.js.map +1 -0
  129. package/lib/module/date-field/context.js +15 -0
  130. package/lib/module/date-field/context.js.map +1 -0
  131. package/lib/module/date-field/index.js +7 -0
  132. package/lib/module/date-field/index.js.map +1 -0
  133. package/lib/module/date-field/segmentIndex.js +18 -0
  134. package/lib/module/date-field/segmentIndex.js.map +1 -0
  135. package/lib/module/date-field/segmentKeyboard.js +157 -0
  136. package/lib/module/date-field/segmentKeyboard.js.map +1 -0
  137. package/lib/module/date-field/types.js +4 -0
  138. package/lib/module/date-field/types.js.map +1 -0
  139. package/lib/module/date-field/useDateFieldSegmentState.js +378 -0
  140. package/lib/module/date-field/useDateFieldSegmentState.js.map +1 -0
  141. package/lib/module/date-field/useRangeDateFieldBridge.js +63 -0
  142. package/lib/module/date-field/useRangeDateFieldBridge.js.map +1 -0
  143. package/lib/module/date-picker/DatePickerRoot.js +119 -0
  144. package/lib/module/date-picker/DatePickerRoot.js.map +1 -0
  145. package/lib/module/date-picker/context.js +12 -0
  146. package/lib/module/date-picker/context.js.map +1 -0
  147. package/lib/module/date-picker/index.js +5 -0
  148. package/lib/module/date-picker/index.js.map +1 -0
  149. package/lib/module/date-range-picker/DateRangePickerRoot.js +140 -0
  150. package/lib/module/date-range-picker/DateRangePickerRoot.js.map +1 -0
  151. package/lib/module/date-range-picker/context.js +19 -0
  152. package/lib/module/date-range-picker/context.js.map +1 -0
  153. package/lib/module/date-range-picker/index.js +5 -0
  154. package/lib/module/date-range-picker/index.js.map +1 -0
  155. package/lib/module/date-time-field/DateTimeFieldHiddenInput.js +148 -0
  156. package/lib/module/date-time-field/DateTimeFieldHiddenInput.js.map +1 -0
  157. package/lib/module/date-time-field/DateTimeFieldInput.js +100 -0
  158. package/lib/module/date-time-field/DateTimeFieldInput.js.map +1 -0
  159. package/lib/module/date-time-field/DateTimeFieldRoot.js +154 -0
  160. package/lib/module/date-time-field/DateTimeFieldRoot.js.map +1 -0
  161. package/lib/module/date-time-field/DateTimeFieldSegment.js +83 -0
  162. package/lib/module/date-time-field/DateTimeFieldSegment.js.map +1 -0
  163. package/lib/module/date-time-field/context.js +12 -0
  164. package/lib/module/date-time-field/context.js.map +1 -0
  165. package/lib/module/date-time-field/index.js +7 -0
  166. package/lib/module/date-time-field/index.js.map +1 -0
  167. package/lib/module/date-time-field/useDateTimeFieldSegmentState.js +561 -0
  168. package/lib/module/date-time-field/useDateTimeFieldSegmentState.js.map +1 -0
  169. package/lib/module/date-time-list/DateTimeListRoot.js +416 -0
  170. package/lib/module/date-time-list/DateTimeListRoot.js.map +1 -0
  171. package/lib/module/date-time-list/context.js +20 -0
  172. package/lib/module/date-time-list/context.js.map +1 -0
  173. package/lib/module/date-time-list/index.js +5 -0
  174. package/lib/module/date-time-list/index.js.map +1 -0
  175. package/lib/module/date-time-picker/DateTimePickerRoot.js +130 -0
  176. package/lib/module/date-time-picker/DateTimePickerRoot.js.map +1 -0
  177. package/lib/module/date-time-picker/context.js +12 -0
  178. package/lib/module/date-time-picker/context.js.map +1 -0
  179. package/lib/module/date-time-picker/index.js +5 -0
  180. package/lib/module/date-time-picker/index.js.map +1 -0
  181. package/lib/module/dialog/DialogRoot.js +1 -1
  182. package/lib/module/dialog/DialogRoot.js.map +1 -1
  183. package/lib/module/index.js +11 -2
  184. package/lib/module/index.js.map +1 -1
  185. package/lib/module/month-calendar/MonthCalendarCell.js +60 -0
  186. package/lib/module/month-calendar/MonthCalendarCell.js.map +1 -0
  187. package/lib/module/month-calendar/MonthCalendarRoot.js +99 -0
  188. package/lib/module/month-calendar/MonthCalendarRoot.js.map +1 -0
  189. package/lib/module/month-calendar/MonthCalendarYearCell.js +59 -0
  190. package/lib/module/month-calendar/MonthCalendarYearCell.js.map +1 -0
  191. package/lib/module/month-calendar/context.js +12 -0
  192. package/lib/module/month-calendar/context.js.map +1 -0
  193. package/lib/module/month-calendar/index.js +7 -0
  194. package/lib/module/month-calendar/index.js.map +1 -0
  195. package/lib/module/month-picker/MonthPickerRoot.js +114 -0
  196. package/lib/module/month-picker/MonthPickerRoot.js.map +1 -0
  197. package/lib/module/month-picker/context.js +12 -0
  198. package/lib/module/month-picker/context.js.map +1 -0
  199. package/lib/module/month-picker/index.js +5 -0
  200. package/lib/module/month-picker/index.js.map +1 -0
  201. package/lib/module/overlay/useAnchorPosition.js +27 -16
  202. package/lib/module/overlay/useAnchorPosition.js.map +1 -1
  203. package/lib/module/overlay/useDismissOverlay.web.js +9 -2
  204. package/lib/module/overlay/useDismissOverlay.web.js.map +1 -1
  205. package/lib/module/overlay/useOverlayPosition.js +5 -2
  206. package/lib/module/overlay/useOverlayPosition.js.map +1 -1
  207. package/lib/module/portal/portal.js +59 -2
  208. package/lib/module/portal/portal.js.map +1 -1
  209. package/lib/module/range-calendar/RangeCalendarRoot.js +144 -0
  210. package/lib/module/range-calendar/RangeCalendarRoot.js.map +1 -0
  211. package/lib/module/range-calendar/context.js +12 -0
  212. package/lib/module/range-calendar/context.js.map +1 -0
  213. package/lib/module/range-calendar/index.js +5 -0
  214. package/lib/module/range-calendar/index.js.map +1 -0
  215. package/lib/module/select/SelectRoot.js +1 -1
  216. package/lib/module/select/SelectRoot.js.map +1 -1
  217. package/lib/module/utils/accessibleLabel.js +18 -0
  218. package/lib/module/utils/accessibleLabel.js.map +1 -0
  219. package/lib/module/utils/createPortal.web.js +17 -0
  220. package/lib/module/utils/createPortal.web.js.map +1 -0
  221. package/lib/typescript/calendar/CalendarGrid.d.ts +7 -0
  222. package/lib/typescript/calendar/CalendarGrid.d.ts.map +1 -0
  223. package/lib/typescript/calendar/CalendarRoot.d.ts +10 -0
  224. package/lib/typescript/calendar/CalendarRoot.d.ts.map +1 -0
  225. package/lib/typescript/calendar/context.d.ts +18 -0
  226. package/lib/typescript/calendar/context.d.ts.map +1 -0
  227. package/lib/typescript/calendar/index.d.ts +5 -0
  228. package/lib/typescript/calendar/index.d.ts.map +1 -0
  229. package/lib/typescript/calendar/types.d.ts +29 -0
  230. package/lib/typescript/calendar/types.d.ts.map +1 -0
  231. package/lib/typescript/date-field/DateFieldHiddenInput.d.ts +4 -0
  232. package/lib/typescript/date-field/DateFieldHiddenInput.d.ts.map +1 -0
  233. package/lib/typescript/date-field/DateFieldInput.d.ts +8 -0
  234. package/lib/typescript/date-field/DateFieldInput.d.ts.map +1 -0
  235. package/lib/typescript/date-field/DateFieldRoot.d.ts +10 -0
  236. package/lib/typescript/date-field/DateFieldRoot.d.ts.map +1 -0
  237. package/lib/typescript/date-field/DateFieldSegment.d.ts +9 -0
  238. package/lib/typescript/date-field/DateFieldSegment.d.ts.map +1 -0
  239. package/lib/typescript/date-field/context.d.ts +33 -0
  240. package/lib/typescript/date-field/context.d.ts.map +1 -0
  241. package/lib/typescript/date-field/index.d.ts +9 -0
  242. package/lib/typescript/date-field/index.d.ts.map +1 -0
  243. package/lib/typescript/date-field/segmentIndex.d.ts +7 -0
  244. package/lib/typescript/date-field/segmentIndex.d.ts.map +1 -0
  245. package/lib/typescript/date-field/segmentKeyboard.d.ts +23 -0
  246. package/lib/typescript/date-field/segmentKeyboard.d.ts.map +1 -0
  247. package/lib/typescript/date-field/types.d.ts +38 -0
  248. package/lib/typescript/date-field/types.d.ts.map +1 -0
  249. package/lib/typescript/date-field/useDateFieldSegmentState.d.ts +26 -0
  250. package/lib/typescript/date-field/useDateFieldSegmentState.d.ts.map +1 -0
  251. package/lib/typescript/date-field/useRangeDateFieldBridge.d.ts +4 -0
  252. package/lib/typescript/date-field/useRangeDateFieldBridge.d.ts.map +1 -0
  253. package/lib/typescript/date-picker/DatePickerRoot.d.ts +28 -0
  254. package/lib/typescript/date-picker/DatePickerRoot.d.ts.map +1 -0
  255. package/lib/typescript/date-picker/context.d.ts +25 -0
  256. package/lib/typescript/date-picker/context.d.ts.map +1 -0
  257. package/lib/typescript/date-picker/index.d.ts +5 -0
  258. package/lib/typescript/date-picker/index.d.ts.map +1 -0
  259. package/lib/typescript/date-range-picker/DateRangePickerRoot.d.ts +43 -0
  260. package/lib/typescript/date-range-picker/DateRangePickerRoot.d.ts.map +1 -0
  261. package/lib/typescript/date-range-picker/context.d.ts +42 -0
  262. package/lib/typescript/date-range-picker/context.d.ts.map +1 -0
  263. package/lib/typescript/date-range-picker/index.d.ts +4 -0
  264. package/lib/typescript/date-range-picker/index.d.ts.map +1 -0
  265. package/lib/typescript/date-time-field/DateTimeFieldHiddenInput.d.ts +4 -0
  266. package/lib/typescript/date-time-field/DateTimeFieldHiddenInput.d.ts.map +1 -0
  267. package/lib/typescript/date-time-field/DateTimeFieldInput.d.ts +10 -0
  268. package/lib/typescript/date-time-field/DateTimeFieldInput.d.ts.map +1 -0
  269. package/lib/typescript/date-time-field/DateTimeFieldRoot.d.ts +24 -0
  270. package/lib/typescript/date-time-field/DateTimeFieldRoot.d.ts.map +1 -0
  271. package/lib/typescript/date-time-field/DateTimeFieldSegment.d.ts +10 -0
  272. package/lib/typescript/date-time-field/DateTimeFieldSegment.d.ts.map +1 -0
  273. package/lib/typescript/date-time-field/context.d.ts +27 -0
  274. package/lib/typescript/date-time-field/context.d.ts.map +1 -0
  275. package/lib/typescript/date-time-field/index.d.ts +8 -0
  276. package/lib/typescript/date-time-field/index.d.ts.map +1 -0
  277. package/lib/typescript/date-time-field/useDateTimeFieldSegmentState.d.ts +26 -0
  278. package/lib/typescript/date-time-field/useDateTimeFieldSegmentState.d.ts.map +1 -0
  279. package/lib/typescript/date-time-list/DateTimeListRoot.d.ts +42 -0
  280. package/lib/typescript/date-time-list/DateTimeListRoot.d.ts.map +1 -0
  281. package/lib/typescript/date-time-list/context.d.ts +29 -0
  282. package/lib/typescript/date-time-list/context.d.ts.map +1 -0
  283. package/lib/typescript/date-time-list/index.d.ts +4 -0
  284. package/lib/typescript/date-time-list/index.d.ts.map +1 -0
  285. package/lib/typescript/date-time-picker/DateTimePickerRoot.d.ts +36 -0
  286. package/lib/typescript/date-time-picker/DateTimePickerRoot.d.ts.map +1 -0
  287. package/lib/typescript/date-time-picker/context.d.ts +25 -0
  288. package/lib/typescript/date-time-picker/context.d.ts.map +1 -0
  289. package/lib/typescript/date-time-picker/index.d.ts +4 -0
  290. package/lib/typescript/date-time-picker/index.d.ts.map +1 -0
  291. package/lib/typescript/dialog/types.d.ts +2 -1
  292. package/lib/typescript/dialog/types.d.ts.map +1 -1
  293. package/lib/typescript/index.d.ts +11 -2
  294. package/lib/typescript/index.d.ts.map +1 -1
  295. package/lib/typescript/month-calendar/MonthCalendarCell.d.ts +9 -0
  296. package/lib/typescript/month-calendar/MonthCalendarCell.d.ts.map +1 -0
  297. package/lib/typescript/month-calendar/MonthCalendarRoot.d.ts +30 -0
  298. package/lib/typescript/month-calendar/MonthCalendarRoot.d.ts.map +1 -0
  299. package/lib/typescript/month-calendar/MonthCalendarYearCell.d.ts +9 -0
  300. package/lib/typescript/month-calendar/MonthCalendarYearCell.d.ts.map +1 -0
  301. package/lib/typescript/month-calendar/context.d.ts +20 -0
  302. package/lib/typescript/month-calendar/context.d.ts.map +1 -0
  303. package/lib/typescript/month-calendar/index.d.ts +7 -0
  304. package/lib/typescript/month-calendar/index.d.ts.map +1 -0
  305. package/lib/typescript/month-picker/MonthPickerRoot.d.ts +29 -0
  306. package/lib/typescript/month-picker/MonthPickerRoot.d.ts.map +1 -0
  307. package/lib/typescript/month-picker/context.d.ts +23 -0
  308. package/lib/typescript/month-picker/context.d.ts.map +1 -0
  309. package/lib/typescript/month-picker/index.d.ts +4 -0
  310. package/lib/typescript/month-picker/index.d.ts.map +1 -0
  311. package/lib/typescript/overlay/useAnchorPosition.d.ts.map +1 -1
  312. package/lib/typescript/overlay/useDismissOverlay.web.d.ts.map +1 -1
  313. package/lib/typescript/overlay/useOverlayPosition.d.ts.map +1 -1
  314. package/lib/typescript/portal/portal.d.ts.map +1 -1
  315. package/lib/typescript/range-calendar/RangeCalendarRoot.d.ts +34 -0
  316. package/lib/typescript/range-calendar/RangeCalendarRoot.d.ts.map +1 -0
  317. package/lib/typescript/range-calendar/context.d.ts +26 -0
  318. package/lib/typescript/range-calendar/context.d.ts.map +1 -0
  319. package/lib/typescript/range-calendar/index.d.ts +5 -0
  320. package/lib/typescript/range-calendar/index.d.ts.map +1 -0
  321. package/lib/typescript/select/types.d.ts +2 -1
  322. package/lib/typescript/select/types.d.ts.map +1 -1
  323. package/lib/typescript/utils/accessibleLabel.d.ts +13 -0
  324. package/lib/typescript/utils/accessibleLabel.d.ts.map +1 -0
  325. package/lib/typescript/utils/createPortal.web.d.ts +17 -0
  326. package/lib/typescript/utils/createPortal.web.d.ts.map +1 -0
  327. package/package.json +3 -2
  328. package/src/calendar/CalendarGrid.tsx +29 -0
  329. package/src/calendar/CalendarRoot.tsx +138 -0
  330. package/src/calendar/context.tsx +28 -0
  331. package/src/calendar/index.ts +4 -0
  332. package/src/calendar/types.ts +30 -0
  333. package/src/date-field/DateFieldHiddenInput.tsx +152 -0
  334. package/src/date-field/DateFieldInput.tsx +138 -0
  335. package/src/date-field/DateFieldRoot.tsx +117 -0
  336. package/src/date-field/DateFieldSegment.tsx +97 -0
  337. package/src/date-field/context.tsx +48 -0
  338. package/src/date-field/index.ts +8 -0
  339. package/src/date-field/segmentIndex.tsx +17 -0
  340. package/src/date-field/segmentKeyboard.ts +207 -0
  341. package/src/date-field/types.ts +40 -0
  342. package/src/date-field/useDateFieldSegmentState.ts +455 -0
  343. package/src/date-field/useRangeDateFieldBridge.ts +78 -0
  344. package/src/date-picker/DatePickerRoot.tsx +186 -0
  345. package/src/date-picker/context.tsx +34 -0
  346. package/src/date-picker/index.ts +4 -0
  347. package/src/date-range-picker/DateRangePickerRoot.tsx +236 -0
  348. package/src/date-range-picker/context.tsx +48 -0
  349. package/src/date-range-picker/index.ts +8 -0
  350. package/src/date-time-field/DateTimeFieldHiddenInput.tsx +156 -0
  351. package/src/date-time-field/DateTimeFieldInput.tsx +119 -0
  352. package/src/date-time-field/DateTimeFieldRoot.tsx +209 -0
  353. package/src/date-time-field/DateTimeFieldSegment.tsx +95 -0
  354. package/src/date-time-field/context.tsx +41 -0
  355. package/src/date-time-field/index.ts +7 -0
  356. package/src/date-time-field/useDateTimeFieldSegmentState.ts +672 -0
  357. package/src/date-time-list/DateTimeListRoot.tsx +530 -0
  358. package/src/date-time-list/context.tsx +45 -0
  359. package/src/date-time-list/index.ts +16 -0
  360. package/src/date-time-picker/DateTimePickerRoot.tsx +210 -0
  361. package/src/date-time-picker/context.tsx +33 -0
  362. package/src/date-time-picker/index.ts +7 -0
  363. package/src/dialog/DialogRoot.tsx +1 -1
  364. package/src/dialog/types.ts +2 -1
  365. package/src/index.ts +21 -2
  366. package/src/month-calendar/MonthCalendarCell.tsx +53 -0
  367. package/src/month-calendar/MonthCalendarRoot.tsx +153 -0
  368. package/src/month-calendar/MonthCalendarYearCell.tsx +54 -0
  369. package/src/month-calendar/context.tsx +30 -0
  370. package/src/month-calendar/index.ts +6 -0
  371. package/src/month-picker/MonthPickerRoot.tsx +183 -0
  372. package/src/month-picker/context.tsx +31 -0
  373. package/src/month-picker/index.ts +3 -0
  374. package/src/overlay/useAnchorPosition.ts +25 -11
  375. package/src/overlay/useDismissOverlay.web.ts +10 -2
  376. package/src/overlay/useOverlayPosition.ts +5 -2
  377. package/src/portal/portal.tsx +79 -2
  378. package/src/range-calendar/RangeCalendarRoot.tsx +213 -0
  379. package/src/range-calendar/context.tsx +33 -0
  380. package/src/range-calendar/index.ts +4 -0
  381. package/src/select/SelectRoot.tsx +1 -1
  382. package/src/select/types.ts +2 -1
  383. package/src/utils/accessibleLabel.ts +22 -0
  384. package/src/utils/createPortal.web.ts +18 -0
@@ -0,0 +1,183 @@
1
+ import {
2
+ forwardRef,
3
+ useCallback,
4
+ useEffect,
5
+ useMemo,
6
+ useRef,
7
+ useState,
8
+ type ComponentRef,
9
+ type ReactNode,
10
+ } from 'react';
11
+ import { View, type ViewProps } from 'react-native';
12
+ import type { DateComponentLabels, MonthId } from '@cdx-ui/formatters';
13
+ import { resolveDateComponentLabels } from '@cdx-ui/formatters';
14
+ import { mergeRefs, useControllableState } from '@cdx-ui/utils';
15
+ import { DateFieldRoot } from '../date-field/DateFieldRoot';
16
+ import { Slot } from '../slot';
17
+ import { dataAttributes, mergeDataAttributes } from '../utils/dataAttributes';
18
+ import type { PickerSurfaceType } from '../date-picker/context';
19
+ import { MonthPickerContext } from './context';
20
+
21
+ export interface MonthPickerRootProps extends Omit<ViewProps, 'children'> {
22
+ asChild?: boolean;
23
+ children?: ReactNode;
24
+ className?: string;
25
+ value?: MonthId;
26
+ defaultValue?: MonthId;
27
+ /** Called with the new `MonthId`, or `undefined` when the selection is cleared. */
28
+ onValueChange?: (value: MonthId | undefined) => void;
29
+ /** Controlled open state. Use `defaultOpen` for the uncontrolled variant. */
30
+ isOpen?: boolean;
31
+ defaultOpen?: boolean;
32
+ onOpenChange?: (open: boolean) => void;
33
+ isDisabled?: boolean;
34
+ isReadOnly?: boolean;
35
+ isInvalid?: boolean;
36
+ isRequired?: boolean;
37
+ /** Earliest selectable month, applied to the embedded calendar. Build with `monthId(...)`. */
38
+ minValue?: MonthId;
39
+ /** Latest selectable month, applied to the embedded calendar. Build with `monthId(...)`. */
40
+ maxValue?: MonthId;
41
+ name?: string;
42
+ locale?: string;
43
+ labels?: Partial<DateComponentLabels>;
44
+ }
45
+
46
+ export const MonthPickerRoot = forwardRef<ComponentRef<typeof View>, MonthPickerRootProps>(
47
+ (
48
+ {
49
+ asChild,
50
+ children,
51
+ value: valueProp,
52
+ defaultValue,
53
+ onValueChange,
54
+ isOpen: openProp,
55
+ defaultOpen = false,
56
+ onOpenChange,
57
+ isDisabled: disabled = false,
58
+ isReadOnly,
59
+ isInvalid,
60
+ isRequired,
61
+ minValue,
62
+ maxValue,
63
+ locale = 'en-US',
64
+ labels: labelsProp,
65
+ ...props
66
+ },
67
+ ref,
68
+ ) => {
69
+ const labels = useMemo(() => resolveDateComponentLabels(labelsProp), [labelsProp]);
70
+ const [value, setValue] = useControllableState<MonthId | undefined>({
71
+ prop: valueProp,
72
+ defaultProp: defaultValue,
73
+ onChange: onValueChange,
74
+ });
75
+
76
+ const [open, setOpenState] = useControllableState<boolean>({
77
+ prop: openProp,
78
+ defaultProp: defaultOpen,
79
+ onChange: onOpenChange,
80
+ });
81
+
82
+ const [draftValue, setDraftValue] = useState<MonthId | undefined>(value);
83
+
84
+ const surfacesRef = useRef<Set<PickerSurfaceType>>(new Set());
85
+ const anchorRef = useRef<ComponentRef<typeof View>>(null);
86
+ const triggerRef = useRef<ComponentRef<typeof View>>(null);
87
+
88
+ const setOpen = useCallback(
89
+ (next: boolean) => {
90
+ if (disabled && next) {
91
+ return;
92
+ }
93
+ if (next) {
94
+ setDraftValue(value);
95
+ }
96
+ setOpenState(next);
97
+ },
98
+ [disabled, setOpenState, value],
99
+ );
100
+
101
+ const registerSurface = useCallback((type: PickerSurfaceType) => {
102
+ if (surfacesRef.current.has(type)) {
103
+ return;
104
+ }
105
+ surfacesRef.current.add(type);
106
+ if (surfacesRef.current.size > 1) {
107
+ console.warn(
108
+ '[Forge UI] MonthPicker: multiple presentation surfaces detected. Use only one of Popover, Dialog, or BottomSheet.',
109
+ );
110
+ }
111
+ }, []);
112
+
113
+ useEffect(() => {
114
+ setDraftValue(value);
115
+ }, [value]);
116
+
117
+ useEffect(() => {
118
+ if (!open) {
119
+ surfacesRef.current.clear();
120
+ }
121
+ }, [open]);
122
+
123
+ const contextValue = useMemo(
124
+ () => ({
125
+ value,
126
+ onValueChange: setValue,
127
+ draftValue,
128
+ setDraftValue,
129
+ open: open ?? false,
130
+ setOpen,
131
+ disabled,
132
+ minValue,
133
+ maxValue,
134
+ locale,
135
+ labels,
136
+ registerSurface,
137
+ anchorRef,
138
+ triggerRef,
139
+ }),
140
+ [
141
+ value,
142
+ setValue,
143
+ draftValue,
144
+ open,
145
+ setOpen,
146
+ disabled,
147
+ minValue,
148
+ maxValue,
149
+ locale,
150
+ labels,
151
+ registerSurface,
152
+ ],
153
+ );
154
+
155
+ const Comp = asChild ? Slot : View;
156
+
157
+ return (
158
+ <MonthPickerContext.Provider value={contextValue}>
159
+ <Comp
160
+ ref={mergeRefs(ref, anchorRef)}
161
+ {...props}
162
+ {...mergeDataAttributes(props, dataAttributes({ disabled, open }))}
163
+ >
164
+ <DateFieldRoot
165
+ value={value}
166
+ onValueChange={(next) => setValue(next as MonthId | undefined)}
167
+ mode="month"
168
+ locale={locale}
169
+ labels={labelsProp}
170
+ isDisabled={disabled}
171
+ isReadOnly={isReadOnly}
172
+ isInvalid={isInvalid}
173
+ isRequired={isRequired}
174
+ >
175
+ {children}
176
+ </DateFieldRoot>
177
+ </Comp>
178
+ </MonthPickerContext.Provider>
179
+ );
180
+ },
181
+ );
182
+
183
+ MonthPickerRoot.displayName = 'MonthPickerRoot';
@@ -0,0 +1,31 @@
1
+ import { createContext, useContext, type RefObject } from 'react';
2
+ import type { View } from 'react-native';
3
+ import type { DateComponentLabels, MonthId } from '@cdx-ui/formatters';
4
+ import type { PickerSurfaceType } from '../date-picker/context';
5
+
6
+ export interface MonthPickerContextValue {
7
+ value?: MonthId;
8
+ onValueChange?: (value: MonthId | undefined) => void;
9
+ draftValue?: MonthId;
10
+ setDraftValue: (value: MonthId | undefined) => void;
11
+ open: boolean;
12
+ setOpen: (open: boolean) => void;
13
+ disabled: boolean;
14
+ minValue?: MonthId;
15
+ maxValue?: MonthId;
16
+ locale: string;
17
+ labels: DateComponentLabels;
18
+ registerSurface: (type: PickerSurfaceType) => void;
19
+ anchorRef: RefObject<View | null>;
20
+ triggerRef: RefObject<View | null>;
21
+ }
22
+
23
+ export const MonthPickerContext = createContext<MonthPickerContextValue | null>(null);
24
+
25
+ export function useMonthPickerContext(): MonthPickerContextValue {
26
+ const ctx = useContext(MonthPickerContext);
27
+ if (!ctx) {
28
+ throw new Error('MonthPicker compound components must be used within MonthPickerRoot');
29
+ }
30
+ return ctx;
31
+ }
@@ -0,0 +1,3 @@
1
+ export { MonthPickerRoot } from './MonthPickerRoot';
2
+ export type { MonthPickerRootProps } from './MonthPickerRoot';
3
+ export { MonthPickerContext, useMonthPickerContext, type MonthPickerContextValue } from './context';
@@ -78,21 +78,35 @@ export function useAnchorPosition(
78
78
 
79
79
  let cancelled = false;
80
80
 
81
- if (Platform.OS === 'web') {
82
- measureAnchor();
83
- } else {
84
- const anchor = anchorRef.current;
85
- if (!anchor) {
86
- return;
81
+ const runMeasure = () => {
82
+ if (!cancelled) {
83
+ measureAnchor();
87
84
  }
85
+ };
86
+
87
+ runMeasure();
88
88
 
89
- anchor.measureInWindow((x: number, y: number, width: number, height: number) => {
90
- if (!cancelled) {
91
- setLayoutIfChanged(setLayout, { x, y, width, height });
92
- }
93
- });
89
+ if (Platform.OS === 'web') {
90
+ const frame = requestAnimationFrame(runMeasure);
91
+ return () => {
92
+ cancelled = true;
93
+ cancelAnimationFrame(frame);
94
+ };
94
95
  }
95
96
 
97
+ const anchor = anchorRef.current;
98
+ if (!anchor) {
99
+ return () => {
100
+ cancelled = true;
101
+ };
102
+ }
103
+
104
+ anchor.measureInWindow((x: number, y: number, width: number, height: number) => {
105
+ if (!cancelled) {
106
+ setLayoutIfChanged(setLayout, { x, y, width, height });
107
+ }
108
+ });
109
+
96
110
  return () => {
97
111
  cancelled = true;
98
112
  };
@@ -1,6 +1,14 @@
1
1
  import type { RefObject } from 'react';
2
2
  import { useEffect, useRef } from 'react';
3
3
 
4
+ function refContainsNode(ref: RefObject<unknown>, target: Node): boolean {
5
+ const current = ref.current as { contains?: (node: Node) => boolean } | null;
6
+ if (!current || typeof current.contains !== 'function') {
7
+ return false;
8
+ }
9
+ return current.contains(target);
10
+ }
11
+
4
12
  /**
5
13
  * Dismisses an overlay when the user clicks/presses outside of it or when
6
14
  * focus moves to an element outside the overlay via keyboard.
@@ -24,11 +32,11 @@ export function useDismissOverlay(
24
32
  }
25
33
 
26
34
  const isInsideOverlay = (target: Node) => {
27
- if (contentRef.current?.contains?.(target)) {
35
+ if (refContainsNode(contentRef, target)) {
28
36
  return true;
29
37
  }
30
38
  for (const ref of excludeRefsRef.current) {
31
- if (ref.current?.contains?.(target)) {
39
+ if (refContainsNode(ref, target)) {
32
40
  return true;
33
41
  }
34
42
  }
@@ -37,6 +37,9 @@ export const OverlayInsetsProvider = OverlayInsetsContext.Provider;
37
37
  /** Minimum gap (px) between the overlay edge and the viewport/safe-area boundary. */
38
38
  const SCREEN_EDGE_PADDING = 8;
39
39
 
40
+ /** Gap between anchor and popover content. */
41
+ const POPOVER_GAP = 4;
42
+
40
43
  /** Minimum usable space (px) below the anchor before the overlay flips above. */
41
44
  const MIN_CONTENT_HEIGHT = 200;
42
45
 
@@ -71,7 +74,7 @@ export function useOverlayPosition(anchorLayout: AnchorLayout | null): OverlayPo
71
74
  const maxHeight = Math.max(0, spaceBelow);
72
75
  return {
73
76
  style: {
74
- top: anchorBottom,
77
+ top: anchorBottom + POPOVER_GAP,
75
78
  left: anchorLayout.x,
76
79
  width: anchorLayout.width,
77
80
  maxHeight,
@@ -84,7 +87,7 @@ export function useOverlayPosition(anchorLayout: AnchorLayout | null): OverlayPo
84
87
  const maxHeight = Math.max(0, spaceAbove);
85
88
  return {
86
89
  style: {
87
- bottom: viewportHeight - anchorLayout.y,
90
+ bottom: viewportHeight - anchorLayout.y + POPOVER_GAP,
88
91
  left: anchorLayout.x,
89
92
  width: anchorLayout.width,
90
93
  maxHeight,
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { useEffect, useSyncExternalStore } from 'react';
3
3
  import { Platform, type View, type ViewStyle } from 'react-native';
4
+ import { createPortalFn } from '../utils/createPortal';
4
5
 
5
6
  const DEFAULT_PORTAL_HOST = 'FORGE_UI_DEFAULT_HOST_NAME';
6
7
 
@@ -17,12 +18,67 @@ const store: PortalStore = {
17
18
  listeners: new Set(),
18
19
  };
19
20
 
21
+ /** Tracks mounted PortalHost instances per host name — only the first mount renders portals. */
22
+ const hostStackStore = {
23
+ stacks: new Map<string, symbol[]>(),
24
+ listeners: new Set<() => void>(),
25
+ };
26
+
27
+ let hasWarnedMultiplePortalHosts = false;
28
+
20
29
  // --------------------------------------------------
21
30
 
22
31
  function emit() {
23
32
  for (const cb of store.listeners) cb();
24
33
  }
25
34
 
35
+ function emitHostStack() {
36
+ for (const cb of hostStackStore.listeners) cb();
37
+ }
38
+
39
+ function getHostStackSnapshot() {
40
+ return hostStackStore.stacks;
41
+ }
42
+
43
+ function subscribeHostStack(cb: () => void) {
44
+ hostStackStore.listeners.add(cb);
45
+ return () => {
46
+ hostStackStore.listeners.delete(cb);
47
+ };
48
+ }
49
+
50
+ function pushPortalHost(name: string, id: symbol) {
51
+ const stacks = new Map(hostStackStore.stacks);
52
+ const stack = [...(stacks.get(name) ?? [])];
53
+ stack.push(id);
54
+ stacks.set(name, stack);
55
+ hostStackStore.stacks = stacks;
56
+
57
+ if (__DEV__ && !hasWarnedMultiplePortalHosts && stack.length > 1) {
58
+ hasWarnedMultiplePortalHosts = true;
59
+ console.warn(
60
+ '[Forge UI] Multiple PortalHost instances detected for the same host name. ' +
61
+ 'Only the first mounted PortalHost renders portal content. ' +
62
+ 'Mount a single PortalHost near your app root (ForgeDesignProvider does this automatically).',
63
+ );
64
+ }
65
+
66
+ emitHostStack();
67
+ }
68
+
69
+ function popPortalHost(name: string, id: symbol) {
70
+ const stacks = new Map(hostStackStore.stacks);
71
+ const stack = (stacks.get(name) ?? []).filter((entry) => entry !== id);
72
+ stacks.set(name, stack);
73
+ hostStackStore.stacks = stacks;
74
+ emitHostStack();
75
+ }
76
+
77
+ function isActivePortalHost(name: string, id: symbol) {
78
+ const stack = hostStackStore.stacks.get(name) ?? [];
79
+ return stack.length > 0 && stack[0] === id;
80
+ }
81
+
26
82
  function getSnapshot() {
27
83
  return store.map;
28
84
  }
@@ -55,10 +111,31 @@ function removePortal(hostName: string, name: string) {
55
111
  // --------------------------------------------------
56
112
 
57
113
  export function PortalHost({ name = DEFAULT_PORTAL_HOST }: { name?: string }) {
114
+ const hostId = React.useRef(Symbol()).current;
115
+
116
+ useEffect(() => {
117
+ pushPortalHost(name, hostId);
118
+ return () => {
119
+ popPortalHost(name, hostId);
120
+ };
121
+ }, [name, hostId]);
122
+
123
+ useSyncExternalStore(subscribeHostStack, getHostStackSnapshot, getHostStackSnapshot);
124
+
58
125
  const map = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
59
126
  const portalMap = map.get(name) ?? new Map<string, React.ReactNode>();
60
- if (portalMap.size === 0) return null;
61
- return <>{Array.from(portalMap.values())}</>;
127
+
128
+ if (!isActivePortalHost(name, hostId) || portalMap.size === 0) {
129
+ return null;
130
+ }
131
+
132
+ const content = <>{Array.from(portalMap.values())}</>;
133
+
134
+ if (Platform.OS === 'web' && createPortalFn && typeof document !== 'undefined') {
135
+ return createPortalFn(content, document.body);
136
+ }
137
+
138
+ return content;
62
139
  }
63
140
 
64
141
  // --------------------------------------------------
@@ -0,0 +1,213 @@
1
+ import {
2
+ forwardRef,
3
+ useCallback,
4
+ useEffect,
5
+ useMemo,
6
+ useRef,
7
+ useState,
8
+ type ComponentRef,
9
+ type ReactNode,
10
+ } from 'react';
11
+ import { View, type ViewProps } from 'react-native';
12
+ import {
13
+ normalizeDateRange,
14
+ resolveDateComponentLabels,
15
+ todayMonthId,
16
+ toMonthId,
17
+ type DateComponentLabels,
18
+ type DateId,
19
+ type MonthId,
20
+ } from '@cdx-ui/formatters';
21
+ import { useControllableState } from '@cdx-ui/utils';
22
+ import { Slot } from '../slot';
23
+ import { accessibleLabelAttributes, resolveAccessibleLabel } from '../utils/accessibleLabel';
24
+ import { dataAttributes, mergeDataAttributes } from '../utils/dataAttributes';
25
+ import type { CalendarView } from '../calendar/context';
26
+ import { RangeCalendarContext, type RangeCalendarFocus } from './context';
27
+
28
+ export interface RangeCalendarRootProps extends Omit<ViewProps, 'children'> {
29
+ asChild?: boolean;
30
+ children?: ReactNode;
31
+ className?: string;
32
+ startValue?: DateId;
33
+ endValue?: DateId;
34
+ defaultStartValue?: DateId;
35
+ defaultEndValue?: DateId;
36
+ onRangeChange?: (range: { startId?: DateId; endId?: DateId }) => void;
37
+ monthId?: MonthId;
38
+ defaultMonthId?: MonthId;
39
+ onMonthIdChange?: (monthId: MonthId) => void;
40
+ focusedField?: RangeCalendarFocus;
41
+ defaultFocusedField?: RangeCalendarFocus;
42
+ onFocusedFieldChange?: (field: RangeCalendarFocus) => void;
43
+ /** Earliest selectable date. Build with `dateId(...)` from `@cdx-ui/formatters`. */
44
+ minValue?: DateId;
45
+ /** Latest selectable date. Build with `dateId(...)` from `@cdx-ui/formatters`. */
46
+ maxValue?: DateId;
47
+ disabled?: boolean;
48
+ locale?: string;
49
+ labels?: Partial<DateComponentLabels>;
50
+ /** Accessible name for the range-calendar region. */
51
+ accessibilityLabel?: string;
52
+ }
53
+
54
+ export const RangeCalendarRoot = forwardRef<ComponentRef<typeof View>, RangeCalendarRootProps>(
55
+ (props, ref) => {
56
+ const {
57
+ asChild,
58
+ children,
59
+ startValue: startProp,
60
+ endValue: endProp,
61
+ defaultStartValue,
62
+ defaultEndValue,
63
+ onRangeChange,
64
+ monthId: monthIdProp,
65
+ defaultMonthId,
66
+ onMonthIdChange,
67
+ focusedField: focusedProp,
68
+ defaultFocusedField = 'start',
69
+ onFocusedFieldChange,
70
+ minValue,
71
+ maxValue,
72
+ disabled = false,
73
+ locale = 'en-US',
74
+ labels: labelsProp,
75
+ accessibilityLabel: accessibilityLabelProp,
76
+ 'aria-label': ariaLabelProp,
77
+ ...rest
78
+ } = props;
79
+
80
+ const labels = useMemo(() => resolveDateComponentLabels(labelsProp), [labelsProp]);
81
+ const accessibilityLabel = resolveAccessibleLabel({
82
+ accessibilityLabel: accessibilityLabelProp,
83
+ 'aria-label': ariaLabelProp,
84
+ });
85
+
86
+ const isRangeControlled = 'startValue' in props || 'endValue' in props;
87
+ const [uncontrolledStart, setUncontrolledStart] = useState<DateId | undefined>(
88
+ defaultStartValue,
89
+ );
90
+ const [uncontrolledEnd, setUncontrolledEnd] = useState<DateId | undefined>(defaultEndValue);
91
+
92
+ const startId = isRangeControlled ? startProp : uncontrolledStart;
93
+ const endId = isRangeControlled ? endProp : uncontrolledEnd;
94
+
95
+ const [monthId, setMonthId] = useControllableState<MonthId>({
96
+ prop: monthIdProp,
97
+ defaultProp:
98
+ defaultMonthId ??
99
+ (startId ? toMonthId(startId) : endId ? toMonthId(endId) : todayMonthId()),
100
+ onChange: onMonthIdChange,
101
+ });
102
+
103
+ const prevRangeRef = useRef({ startId, endId });
104
+ useEffect(() => {
105
+ if (monthIdProp !== undefined) {
106
+ prevRangeRef.current = { startId, endId };
107
+ return;
108
+ }
109
+ if (prevRangeRef.current.startId === startId && prevRangeRef.current.endId === endId) {
110
+ return;
111
+ }
112
+ prevRangeRef.current = { startId, endId };
113
+ const anchor = startId ?? endId;
114
+ if (anchor !== undefined) {
115
+ setMonthId(toMonthId(anchor));
116
+ }
117
+ }, [endId, monthIdProp, setMonthId, startId]);
118
+
119
+ const [focusedField, setFocusedField] = useControllableState<RangeCalendarFocus>({
120
+ prop: focusedProp,
121
+ defaultProp: defaultFocusedField,
122
+ onChange: onFocusedFieldChange,
123
+ });
124
+
125
+ const [view, setViewState] = useState<CalendarView>('month');
126
+
127
+ const setView = useCallback((next: CalendarView) => {
128
+ setViewState(next);
129
+ }, []);
130
+
131
+ const onDayPress = useCallback(
132
+ (dateId: DateId) => {
133
+ if (disabled) {
134
+ return;
135
+ }
136
+
137
+ let next: { startId: DateId; endId?: DateId };
138
+
139
+ // Empty or complete range → start a new selection at this day.
140
+ if (!startId || endId) {
141
+ next = { startId: dateId, endId: undefined };
142
+ setFocusedField('end');
143
+ } else {
144
+ // Incomplete range (start only) → set end and normalize order.
145
+ next = normalizeDateRange({ startId, endId: dateId });
146
+ setFocusedField('start');
147
+ }
148
+
149
+ if (!isRangeControlled) {
150
+ setUncontrolledStart(next.startId);
151
+ setUncontrolledEnd(next.endId);
152
+ }
153
+ onRangeChange?.(next);
154
+ },
155
+ [disabled, endId, isRangeControlled, onRangeChange, setFocusedField, startId],
156
+ );
157
+
158
+ const contextValue = useMemo(
159
+ () => ({
160
+ startId,
161
+ endId,
162
+ onRangeChange,
163
+ monthId: monthId ?? todayMonthId(),
164
+ onMonthIdChange: setMonthId,
165
+ focusedField: focusedField ?? 'start',
166
+ onFocusedFieldChange: setFocusedField,
167
+ minValue,
168
+ maxValue,
169
+ disabled,
170
+ locale,
171
+ labels,
172
+ onDayPress,
173
+ view,
174
+ setView,
175
+ }),
176
+ [
177
+ startId,
178
+ endId,
179
+ onRangeChange,
180
+ monthId,
181
+ setMonthId,
182
+ focusedField,
183
+ setFocusedField,
184
+ minValue,
185
+ maxValue,
186
+ disabled,
187
+ locale,
188
+ labels,
189
+ onDayPress,
190
+ view,
191
+ setView,
192
+ ],
193
+ );
194
+
195
+ const Comp = asChild ? Slot : View;
196
+
197
+ return (
198
+ <RangeCalendarContext.Provider value={contextValue}>
199
+ <Comp
200
+ ref={ref}
201
+ accessibilityRole="none"
202
+ {...rest}
203
+ {...mergeDataAttributes(rest, dataAttributes({ disabled }))}
204
+ {...accessibleLabelAttributes(accessibilityLabel)}
205
+ >
206
+ {children}
207
+ </Comp>
208
+ </RangeCalendarContext.Provider>
209
+ );
210
+ },
211
+ );
212
+
213
+ RangeCalendarRoot.displayName = 'RangeCalendarRoot';
@@ -0,0 +1,33 @@
1
+ import { createContext, useContext } from 'react';
2
+ import type { DateComponentLabels, DateId, MonthId } from '@cdx-ui/formatters';
3
+ import type { CalendarView } from '../calendar/context';
4
+
5
+ export type RangeCalendarFocus = 'start' | 'end';
6
+
7
+ export interface RangeCalendarContextValue {
8
+ startId?: DateId;
9
+ endId?: DateId;
10
+ onRangeChange?: (range: { startId?: DateId; endId?: DateId }) => void;
11
+ monthId: MonthId;
12
+ onMonthIdChange: (monthId: MonthId) => void;
13
+ focusedField: RangeCalendarFocus;
14
+ onFocusedFieldChange: (field: RangeCalendarFocus) => void;
15
+ minValue?: DateId;
16
+ maxValue?: DateId;
17
+ disabled: boolean;
18
+ locale: string;
19
+ labels: DateComponentLabels;
20
+ onDayPress: (dateId: DateId) => void;
21
+ view: CalendarView;
22
+ setView: (view: CalendarView) => void;
23
+ }
24
+
25
+ export const RangeCalendarContext = createContext<RangeCalendarContextValue | null>(null);
26
+
27
+ export function useRangeCalendarContext(): RangeCalendarContextValue {
28
+ const ctx = useContext(RangeCalendarContext);
29
+ if (!ctx) {
30
+ throw new Error('RangeCalendar compound components must be used within RangeCalendarRoot');
31
+ }
32
+ return ctx;
33
+ }
@@ -0,0 +1,4 @@
1
+ export { RangeCalendarRoot } from './RangeCalendarRoot';
2
+ export type { RangeCalendarRootProps } from './RangeCalendarRoot';
3
+ export { useRangeCalendarContext } from './context';
4
+ export type { RangeCalendarFocus } from './context';
@@ -28,7 +28,7 @@ export const SelectRoot = forwardRef<ComponentRef<typeof View>, SelectRootProps>
28
28
  value: valueProp,
29
29
  defaultValue,
30
30
  onValueChange,
31
- open: openProp,
31
+ isOpen: openProp,
32
32
  defaultOpen = false,
33
33
  onOpenChange,
34
34
  disabled = false,