@astryxdesign/core 0.7.6-canary.f73623d → 0.7.6-canary.f899313

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 (921) hide show
  1. package/dist/Badge/Badge.d.ts.map +1 -1
  2. package/dist/Badge/Badge.js +2 -1
  3. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  4. package/dist/ComplexSelector/ComplexSelector.js +8 -2
  5. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  6. package/dist/DateInput/MonthScroller.js +17 -18
  7. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  8. package/dist/DateRangeInput/DateRangeInput.js +8 -4
  9. package/dist/DropdownMenu/DropdownMenuGroup.d.ts.map +1 -1
  10. package/dist/DropdownMenu/DropdownMenuGroup.js +2 -1
  11. package/dist/Field/FieldLabel.d.ts.map +1 -1
  12. package/dist/Field/FieldLabel.js +27 -2
  13. package/dist/FieldStatus/FieldStatus.d.ts +3 -0
  14. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  15. package/dist/FieldStatus/FieldStatus.js +1 -0
  16. package/dist/FileInput/FileInput.d.ts +3 -0
  17. package/dist/FileInput/FileInput.d.ts.map +1 -1
  18. package/dist/FileInput/FileInput.js +59 -33
  19. package/dist/Layer/useTouchTrigger.d.ts +9 -0
  20. package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
  21. package/dist/Layer/useTouchTrigger.js +1 -1
  22. package/dist/Link/Link.d.ts.map +1 -1
  23. package/dist/Link/Link.js +10 -1
  24. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  25. package/dist/MultiSelector/MultiSelector.js +19 -9
  26. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  27. package/dist/NumberInput/NumberInput.js +11 -15
  28. package/dist/Selector/Selector.d.ts.map +1 -1
  29. package/dist/Selector/Selector.js +9 -6
  30. package/dist/Selector/hooks.js +2 -2
  31. package/dist/Slider/Slider.d.ts.map +1 -1
  32. package/dist/Slider/Slider.js +82 -10
  33. package/dist/Token/Token.d.ts +1 -1
  34. package/dist/Token/Token.d.ts.map +1 -1
  35. package/dist/Token/Token.js +15 -0
  36. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  37. package/dist/Tokenizer/Tokenizer.js +16 -1
  38. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  39. package/dist/Typeahead/BaseTypeahead.js +10 -3
  40. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  41. package/dist/Typeahead/Typeahead.js +36 -10
  42. package/dist/astryx.css +1 -1
  43. package/dist/i18n/useListFormatter.d.ts +9 -0
  44. package/dist/i18n/useListFormatter.d.ts.map +1 -0
  45. package/dist/i18n/useListFormatter.js +41 -0
  46. package/package.json +18 -5
  47. package/src/Badge/Badge.tsx +2 -1
  48. package/src/Chat/ChatMessage.spec.md +64 -65
  49. package/src/Citation/Citation.spec.md +60 -47
  50. package/src/ComplexSelector/ComplexSelector.tsx +19 -2
  51. package/src/DateInput/DateInput.spec.md +74 -57
  52. package/src/DateInput/MonthScroller.tsx +15 -17
  53. package/src/DateRangeInput/DateRangeInput.tsx +18 -3
  54. package/src/DropdownMenu/DropdownMenuGroup.tsx +2 -1
  55. package/src/Field/Field.doc.mjs +2 -1
  56. package/src/Field/FieldLabel.doc.mjs +4 -2
  57. package/src/Field/FieldLabel.spec.md +30 -21
  58. package/src/Field/FieldLabel.tsx +37 -3
  59. package/src/FieldStatus/FieldStatus.tsx +7 -0
  60. package/src/FileInput/FileInput.tsx +69 -28
  61. package/src/FormLayout/FormLayout.spec.md +11 -19
  62. package/src/Layer/useTouchTrigger.ts +1 -1
  63. package/src/Lightbox/Lightbox.spec.md +249 -61
  64. package/src/Link/Link.tsx +9 -2
  65. package/src/MultiSelector/MultiSelector.spec.md +121 -114
  66. package/src/MultiSelector/MultiSelector.tsx +19 -5
  67. package/src/NumberInput/NumberInput.tsx +11 -18
  68. package/src/ProgressBar/ProgressBar.spec.md +143 -119
  69. package/src/Selector/Selector.tsx +16 -6
  70. package/src/Selector/hooks.ts +2 -2
  71. package/src/Slider/Slider.spec.md +18 -16
  72. package/src/Slider/Slider.tsx +101 -9
  73. package/src/Token/Token.spec.md +24 -23
  74. package/src/Token/Token.tsx +15 -0
  75. package/src/Tokenizer/Tokenizer.tsx +10 -0
  76. package/src/Typeahead/BaseTypeahead.tsx +18 -2
  77. package/src/Typeahead/Typeahead.tsx +40 -9
  78. package/src/i18n/useListFormatter.ts +42 -0
  79. package/dist/Item/ItemMarkerColumns.a11y.chromium.spec.d.ts +0 -2
  80. package/dist/Item/ItemMarkerColumns.a11y.chromium.spec.js +0 -132
  81. package/dist/Lightbox/LightboxKeyboard.a11y.browser.spec.d.ts +0 -2
  82. package/dist/Lightbox/LightboxKeyboard.a11y.browser.spec.js +0 -78
  83. package/dist/Lightbox/LightboxViewport.a11y.browser.spec.d.ts +0 -2
  84. package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +0 -66
  85. package/dist/List/ListMarkers.a11y.chromium.spec.d.ts +0 -2
  86. package/dist/List/ListMarkers.a11y.chromium.spec.js +0 -677
  87. package/dist/Markdown/Markdown.fr23.bench.d.ts +0 -2
  88. package/dist/Markdown/Markdown.fr23.bench.d.ts.map +0 -1
  89. package/dist/Markdown/Markdown.fr23.bench.js +0 -152
  90. package/dist/Markdown/MarkdownTable.a11y.chromium.spec.d.ts +0 -2
  91. package/dist/Markdown/MarkdownTable.a11y.chromium.spec.js +0 -590
  92. package/dist/Markdown/plugins/headingLinks.a11y.chromium.spec.d.ts +0 -2
  93. package/dist/Markdown/plugins/headingLinks.a11y.chromium.spec.js +0 -657
  94. package/dist/MobileNav/MobileNavPinchZoom.a11y.chromium.spec.d.ts +0 -2
  95. package/dist/MobileNav/MobileNavPinchZoom.a11y.chromium.spec.js +0 -153
  96. package/dist/MultiSelector/CreateRow.a11y.chromium.spec.d.ts +0 -2
  97. package/dist/MultiSelector/CreateRow.a11y.chromium.spec.js +0 -117
  98. package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.d.ts +0 -2
  99. package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.js +0 -49
  100. package/dist/MultiSelector/OptionActions.a11y.chromium.spec.d.ts +0 -2
  101. package/dist/MultiSelector/OptionActions.a11y.chromium.spec.js +0 -273
  102. package/dist/Outline/OutlineFocus.a11y.chromium.spec.d.ts +0 -2
  103. package/dist/Outline/OutlineFocus.a11y.chromium.spec.js +0 -421
  104. package/dist/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.d.ts +0 -2
  105. package/dist/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.js +0 -118
  106. package/dist/reset.a11y.chromium.spec.d.ts +0 -2
  107. package/dist/reset.a11y.chromium.spec.js +0 -231
  108. package/dist/reset.until-found.a11y.browser.spec.d.ts +0 -2
  109. package/dist/reset.until-found.a11y.browser.spec.js +0 -72
  110. package/src/AlertDialog/AlertDialog.test.tsx +0 -519
  111. package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +0 -128
  112. package/src/AlertDialog/__tests__/AlertDialog.a11y.renders.tsx +0 -52
  113. package/src/AlertDialog/__tests__/AlertDialog.a11y.states.ts +0 -68
  114. package/src/AlertDialog/__tests__/AlertDialog.a11y.test.tsx +0 -144
  115. package/src/AlertDialog/useImperativeAlertDialog.test.tsx +0 -163
  116. package/src/AppShell/AppShell.test.tsx +0 -1310
  117. package/src/AppShell/__tests__/AppShellMainKeyboard.a11y.browser.spec.ts +0 -534
  118. package/src/AppShell/observeMainOverflow.test.ts +0 -173
  119. package/src/AspectRatio/AspectRatio.test.tsx +0 -398
  120. package/src/AspectRatio/__tests__/AspectRatioFitLayers.a11y.browser.spec.ts +0 -158
  121. package/src/Avatar/Avatar.test.tsx +0 -867
  122. package/src/Avatar/AvatarStatusDot.test.tsx +0 -306
  123. package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +0 -126
  124. package/src/AvatarGroup/AvatarGroup.test.tsx +0 -313
  125. package/src/AvatarGroup/AvatarGroupOverflow.test.tsx +0 -263
  126. package/src/Badge/Badge.test.tsx +0 -125
  127. package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +0 -260
  128. package/src/Banner/Banner.test.tsx +0 -879
  129. package/src/Blockquote/Blockquote.test.tsx +0 -121
  130. package/src/BottomSheet/BottomSheet.test.tsx +0 -3154
  131. package/src/BottomSheet/BottomSheetEdgeTint.test.tsx +0 -248
  132. package/src/BottomSheet/BottomSheetKeyboard.test.tsx +0 -195
  133. package/src/BottomSheet/BottomSheetPanel.test.tsx +0 -549
  134. package/src/BottomSheet/BottomSheetReplace.test.tsx +0 -1638
  135. package/src/BottomSheet/BottomSheetStacking.announce.test.tsx +0 -246
  136. package/src/BottomSheet/BottomSheetStacking.test.tsx +0 -3184
  137. package/src/BottomSheet/BottomSheetSwitcher.test.tsx +0 -2010
  138. package/src/BottomSheet/__tests__/BottomSheetDrag.a11y.chromium.spec.ts +0 -129
  139. package/src/BottomSheet/__tests__/BottomSheetFocusReturn.a11y.browser.spec.ts +0 -97
  140. package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +0 -415
  141. package/src/BottomSheet/__tests__/BottomSheetNativeModal.a11y.browser.spec.ts +0 -462
  142. package/src/BottomSheet/__tests__/BottomSheetPinchZoom.a11y.chromium.spec.ts +0 -247
  143. package/src/BottomSheet/__tests__/BottomSheetToastOutlet.a11y.chromium.spec.ts +0 -83
  144. package/src/BottomSheet/snapOffsets.test.ts +0 -254
  145. package/src/BottomSheet/useSheetGestures.test.ts +0 -1690
  146. package/src/Breadcrumbs/Breadcrumbs.test.tsx +0 -921
  147. package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +0 -132
  148. package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.renders.tsx +0 -45
  149. package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.states.ts +0 -81
  150. package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.test.tsx +0 -125
  151. package/src/Button/Button.test.tsx +0 -864
  152. package/src/Button/__tests__/Button.a11y.chromium.spec.ts +0 -355
  153. package/src/Button/__tests__/Button.a11y.harnesses.tsx +0 -47
  154. package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -25
  155. package/src/Button/__tests__/Button.a11y.renders.tsx +0 -139
  156. package/src/Button/__tests__/Button.a11y.states.ts +0 -317
  157. package/src/Button/__tests__/Button.a11y.test.tsx +0 -187
  158. package/src/ButtonGroup/ButtonGroup.test.tsx +0 -1025
  159. package/src/Calendar/Calendar.test.tsx +0 -2186
  160. package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +0 -141
  161. package/src/Calendar/__tests__/Calendar.a11y.known-failures.ts +0 -12
  162. package/src/Calendar/__tests__/Calendar.a11y.renders.tsx +0 -57
  163. package/src/Calendar/__tests__/Calendar.a11y.states.ts +0 -139
  164. package/src/Calendar/__tests__/Calendar.a11y.test.tsx +0 -137
  165. package/src/Calendar/dayCellUtils.test.ts +0 -520
  166. package/src/Calendar/getInitialFocusDate.test.ts +0 -94
  167. package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +0 -54
  168. package/src/Calendar/hooks/useCalendarConstraints.test.ts +0 -153
  169. package/src/Calendar/hooks/useCalendarDays.test.ts +0 -265
  170. package/src/Calendar/hooks/useCalendarNavigation.test.ts +0 -252
  171. package/src/Card/Card.test.tsx +0 -202
  172. package/src/Carousel/Carousel.test.tsx +0 -1036
  173. package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +0 -207
  174. package/src/Carousel/__tests__/Carousel.a11y.known-failures.ts +0 -12
  175. package/src/Carousel/__tests__/Carousel.a11y.renders.tsx +0 -39
  176. package/src/Carousel/__tests__/Carousel.a11y.states.ts +0 -139
  177. package/src/Carousel/__tests__/Carousel.a11y.test.tsx +0 -127
  178. package/src/Center/Center.test.tsx +0 -406
  179. package/src/Chat/ChatComposer.test.tsx +0 -364
  180. package/src/Chat/ChatComposerDrawer.test.tsx +0 -130
  181. package/src/Chat/ChatComposerInput.test.tsx +0 -2136
  182. package/src/Chat/ChatComposerTokenElement.test.tsx +0 -85
  183. package/src/Chat/ChatDictationButton.test.tsx +0 -108
  184. package/src/Chat/ChatLayout.test.tsx +0 -311
  185. package/src/Chat/ChatLayoutScrollButton.test.tsx +0 -99
  186. package/src/Chat/ChatMessage.test.tsx +0 -344
  187. package/src/Chat/ChatMessageBubble.test.tsx +0 -294
  188. package/src/Chat/ChatMessageList.test.tsx +0 -198
  189. package/src/Chat/ChatMessageMetadata.test.tsx +0 -66
  190. package/src/Chat/ChatPastedTextToken.test.tsx +0 -71
  191. package/src/Chat/ChatSendButton.test.tsx +0 -309
  192. package/src/Chat/ChatSystemMessage.test.tsx +0 -189
  193. package/src/Chat/ChatTokenizedText.test.tsx +0 -163
  194. package/src/Chat/ChatToolCalls.test.tsx +0 -413
  195. package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +0 -577
  196. package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +0 -740
  197. package/src/Chat/__tests__/ChatMessageBubble.a11y.chromium.spec.ts +0 -457
  198. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.test.ts +0 -91
  199. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.ts +0 -91
  200. package/src/Chat/__tests__/ChatMessageList.a11y.chromium.spec.ts +0 -465
  201. package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +0 -416
  202. package/src/Chat/__tests__/ChatSendButton.a11y.chromium.spec.ts +0 -1523
  203. package/src/Chat/__tests__/ChatSystemMessage.a11y.chromium.spec.ts +0 -1004
  204. package/src/Chat/__tests__/ChatTokenizedText.a11y.chromium.spec.ts +0 -574
  205. package/src/Chat/__tests__/useChatStreamScroll.a11y.chromium.spec.ts +0 -263
  206. package/src/Chat/__tests__/useChatStreamScroll.fixture.tsx +0 -61
  207. package/src/Chat/useChatDictation.test.tsx +0 -369
  208. package/src/Chat/useChatNewMessages.test.tsx +0 -209
  209. package/src/Chat/useChatPasteAsToken.test.ts +0 -191
  210. package/src/Chat/useChatStreamScroll.test.tsx +0 -381
  211. package/src/Chat/useTriggerMenu.test.tsx +0 -994
  212. package/src/CheckboxInput/CheckboxInput.test.tsx +0 -926
  213. package/src/CheckboxInput/__tests__/Checkbox.a11y.chromium.spec.ts +0 -354
  214. package/src/CheckboxInput/__tests__/Checkbox.a11y.known-failures.ts +0 -54
  215. package/src/CheckboxInput/__tests__/Checkbox.a11y.renders.tsx +0 -310
  216. package/src/CheckboxInput/__tests__/Checkbox.a11y.states.ts +0 -404
  217. package/src/CheckboxInput/__tests__/Checkbox.a11y.test.tsx +0 -128
  218. package/src/CheckboxList/CheckboxList.fr10.test.tsx +0 -51
  219. package/src/CheckboxList/CheckboxList.test.tsx +0 -1159
  220. package/src/CheckboxList/__tests__/CheckboxList.a11y.chromium.spec.ts +0 -1998
  221. package/src/Citation/Citation.test.tsx +0 -361
  222. package/src/ClickableCard/ClickableCard.test.tsx +0 -382
  223. package/src/Code/Code.test.tsx +0 -75
  224. package/src/CodeBlock/CodeBlock.highlightStyles.test.tsx +0 -87
  225. package/src/CodeBlock/CodeBlock.test.tsx +0 -752
  226. package/src/CodeBlock/CodeLanguage.test.tsx +0 -173
  227. package/src/CodeBlock/__tests__/CodeBlockCopyClearance.a11y.chromium.spec.ts +0 -325
  228. package/src/CodeBlock/__tests__/CodeBlockLanguages.a11y.chromium.spec.ts +0 -64
  229. package/src/CodeBlock/__tests__/CodeBlockOverflowStop.a11y.chromium.spec.ts +0 -126
  230. package/src/CodeBlock/__tests__/DiffRowPaint.a11y.chromium.spec.ts +0 -94
  231. package/src/CodeBlock/highlightRanges.test.ts +0 -253
  232. package/src/CodeBlock/languages.test.ts +0 -402
  233. package/src/CodeBlock/tokenizer.test.ts +0 -280
  234. package/src/CodeBlock/tokenizerBudget.test.ts +0 -112
  235. package/src/Collapsible/Collapsible.test.tsx +0 -620
  236. package/src/Collapsible/CollapsibleGroup.test.tsx +0 -656
  237. package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +0 -194
  238. package/src/Collapsible/__tests__/Collapsible.a11y.states.ts +0 -117
  239. package/src/Collapsible/__tests__/Collapsible.a11y.test.tsx +0 -140
  240. package/src/Collapsible/__tests__/CollapsibleGroup.a11y.chromium.spec.ts +0 -559
  241. package/src/Collapsible/__tests__/CollapsibleGroup.a11y.renders.tsx +0 -45
  242. package/src/Collapsible/__tests__/CollapsibleGroup.a11y.states.ts +0 -139
  243. package/src/Collapsible/__tests__/CollapsibleGroup.a11y.test.tsx +0 -135
  244. package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +0 -141
  245. package/src/Collapsible/useCollapsible.test.tsx +0 -236
  246. package/src/CommandPalette/CommandPalette.perf.test.ts +0 -100
  247. package/src/CommandPalette/CommandPalette.test.tsx +0 -750
  248. package/src/CommandPalette/CommandPaletteEmpty.test.tsx +0 -101
  249. package/src/CommandPalette/CommandPaletteFooter.test.tsx +0 -122
  250. package/src/CommandPalette/CommandPaletteGroup.test.tsx +0 -129
  251. package/src/CommandPalette/CommandPaletteInput.test.tsx +0 -539
  252. package/src/CommandPalette/CommandPaletteItem.test.tsx +0 -417
  253. package/src/CommandPalette/CommandPaletteList.test.tsx +0 -184
  254. package/src/CommandPalette/__tests__/CommandPalette.a11y.chromium.spec.ts +0 -600
  255. package/src/CommandPalette/__tests__/CommandPaletteEmptyAudit.a11y.chromium.spec.ts +0 -715
  256. package/src/CommandPalette/__tests__/CommandPaletteFooter.a11y.chromium.spec.ts +0 -582
  257. package/src/CommandPalette/__tests__/CommandPaletteInputAudit.a11y.chromium.spec.ts +0 -336
  258. package/src/CommandPalette/__tests__/CommandPaletteItemAudit.a11y.chromium.spec.ts +0 -523
  259. package/src/ComplexSelector/ComplexSelector.focusableDisabled.test.tsx +0 -76
  260. package/src/ComplexSelector/ComplexSelector.fr10.test.tsx +0 -262
  261. package/src/ComplexSelector/ComplexSelector.test.tsx +0 -1171
  262. package/src/ComplexSelector/__tests__/ComplexSelector.a11y.chromium.spec.ts +0 -965
  263. package/src/ContextMenu/ContextMenu.test.tsx +0 -1617
  264. package/src/ContextMenu/ContextMenu.triggerProps.test.tsx +0 -54
  265. package/src/ContextMenu/__tests__/ContextMenuAudit.a11y.chromium.spec.ts +0 -439
  266. package/src/ContextMenu/__tests__/ContextMenuCursorAnchor.a11y.browser.spec.ts +0 -154
  267. package/src/ContextMenu/__tests__/ContextMenuLongPress.a11y.chromium.spec.ts +0 -117
  268. package/src/DateInput/DateInput.fr10.test.tsx +0 -283
  269. package/src/DateInput/DateInput.test.tsx +0 -1571
  270. package/src/DateInput/DateInputTouch.test.tsx +0 -2948
  271. package/src/DateInput/MonthScrollerSettle.test.tsx +0 -165
  272. package/src/DateInput/NativeDateField.test.tsx +0 -741
  273. package/src/DateInput/Presentation.test.tsx +0 -121
  274. package/src/DateInput/__tests__/DateInputAudit.a11y.chromium.spec.ts +0 -577
  275. package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +0 -312
  276. package/src/DateInput/__tests__/WheelPinchZoom.a11y.chromium.spec.ts +0 -171
  277. package/src/DateRangeInput/DateRangeInput.fr10.test.tsx +0 -165
  278. package/src/DateRangeInput/DateRangeInput.test.tsx +0 -1151
  279. package/src/DateTimeInput/DateTimeInput.fr10.test.tsx +0 -319
  280. package/src/DateTimeInput/DateTimeInput.test.tsx +0 -2656
  281. package/src/DateTimeInput/DateTimeInputTouch.test.tsx +0 -1071
  282. package/src/DateTimeInput/NativePickerSegments.test.tsx +0 -657
  283. package/src/DateTimeInput/Presentation.test.tsx +0 -89
  284. package/src/Dialog/Dialog.source-build.test.mjs +0 -43
  285. package/src/Dialog/Dialog.test.tsx +0 -1599
  286. package/src/Dialog/DialogHeader.test.tsx +0 -477
  287. package/src/Dialog/__tests__/Dialog.a11y.browser.spec.ts +0 -111
  288. package/src/Dialog/__tests__/Dialog.a11y.chromium.spec.ts +0 -218
  289. package/src/Dialog/__tests__/Dialog.a11y.known-failures.ts +0 -28
  290. package/src/Dialog/__tests__/Dialog.a11y.renders.tsx +0 -107
  291. package/src/Dialog/__tests__/Dialog.a11y.states.ts +0 -104
  292. package/src/Dialog/__tests__/Dialog.a11y.test.tsx +0 -102
  293. package/src/Dialog/__tests__/Dialog.reduced-motion.a11y.browser.spec.ts +0 -252
  294. package/src/Dialog/__tests__/DialogSecondDocument.a11y.browser.spec.ts +0 -202
  295. package/src/Dialog/useImperativeDialog.test.tsx +0 -78
  296. package/src/Divider/Divider.test.tsx +0 -155
  297. package/src/Drawer/Drawer.test.tsx +0 -1335
  298. package/src/Drawer/DrawerDirection.test.tsx +0 -127
  299. package/src/Drawer/DrawerHeader.test.tsx +0 -102
  300. package/src/Drawer/__tests__/DrawerAudit.a11y.chromium.spec.ts +0 -402
  301. package/src/Drawer/__tests__/DrawerHeaderAudit.a11y.chromium.spec.ts +0 -298
  302. package/src/Drawer/__tests__/DrawerNonModalPageScroll.a11y.chromium.spec.ts +0 -267
  303. package/src/DropdownMenu/DropdownMenu.ssr.test.tsx +0 -93
  304. package/src/DropdownMenu/DropdownMenu.test.tsx +0 -4498
  305. package/src/DropdownMenu/DropdownMenuContext.public.test.ts +0 -22
  306. package/src/DropdownMenu/DropdownMenuLazySheet.test.tsx +0 -126
  307. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +0 -635
  308. package/src/DropdownMenu/DropdownMenuSheetFirstOpen.test.tsx +0 -72
  309. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +0 -2442
  310. package/src/DropdownMenu/__tests__/DropdownMenuDividerAudit.a11y.chromium.spec.ts +0 -281
  311. package/src/DropdownMenu/__tests__/DropdownMenuDrillIn.a11y.chromium.spec.ts +0 -175
  312. package/src/DropdownMenu/__tests__/DropdownMenuFocusReturn.a11y.browser.spec.ts +0 -74
  313. package/src/DropdownMenu/__tests__/DropdownMenuGroupAudit.a11y.chromium.spec.ts +0 -335
  314. package/src/DropdownMenu/__tests__/DropdownMenuItemAudit.a11y.chromium.spec.ts +0 -367
  315. package/src/DropdownMenu/__tests__/DropdownMenuRadioGroupAudit.a11y.chromium.spec.ts +0 -328
  316. package/src/DropdownMenu/__tests__/DropdownMenuRadioItemAudit.a11y.chromium.spec.ts +0 -540
  317. package/src/DropdownMenu/__tests__/DropdownMenuSubMenuAudit.a11y.chromium.spec.ts +0 -671
  318. package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +0 -158
  319. package/src/DropdownMenu/__tests__/Menu.a11y.known-failures.ts +0 -26
  320. package/src/DropdownMenu/__tests__/Menu.a11y.renders.tsx +0 -65
  321. package/src/DropdownMenu/__tests__/Menu.a11y.states.ts +0 -138
  322. package/src/DropdownMenu/__tests__/Menu.a11y.test.tsx +0 -136
  323. package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +0 -149
  324. package/src/DropdownMenu/__tests__/MenuButton.a11y.known-failures.ts +0 -12
  325. package/src/DropdownMenu/__tests__/MenuButton.a11y.renders.tsx +0 -67
  326. package/src/DropdownMenu/__tests__/MenuButton.a11y.states.ts +0 -141
  327. package/src/DropdownMenu/__tests__/MenuButton.a11y.test.tsx +0 -138
  328. package/src/DropdownMenu/__tests__/MenuHeaderFooter.a11y.chromium.spec.ts +0 -231
  329. package/src/DropdownMenu/__tests__/MenuHoverFocus.a11y.chromium.spec.ts +0 -238
  330. package/src/DropdownMenu/__tests__/MenuPinchZoom.a11y.chromium.spec.ts +0 -173
  331. package/src/DropdownMenu/__tests__/MenuPress.a11y.chromium.spec.ts +0 -503
  332. package/src/DropdownMenu/__tests__/SubMenuHeaderFooter.a11y.chromium.spec.ts +0 -268
  333. package/src/DropdownMenu/__tests__/warmMenuBottomSheet.tsx +0 -43
  334. package/src/DropdownMenu/lazyMenuBottomSheet.test.ts +0 -60
  335. package/src/EmptyState/EmptyState.announce.test.tsx +0 -227
  336. package/src/EmptyState/EmptyState.test.tsx +0 -284
  337. package/src/Field/Field.test.tsx +0 -800
  338. package/src/Field/FieldLabel.test.tsx +0 -244
  339. package/src/Field/InputClearButton.test.tsx +0 -395
  340. package/src/Field/__tests__/FieldLabelAudit.a11y.chromium.spec.ts +0 -297
  341. package/src/Field/fieldInputFamily.test.tsx +0 -160
  342. package/src/FieldStatus/FieldStatus.test.tsx +0 -482
  343. package/src/FieldStatus/__tests__/StatusMessage.a11y.chromium.spec.ts +0 -206
  344. package/src/FieldStatus/__tests__/StatusMessage.a11y.known-failures.ts +0 -13
  345. package/src/FieldStatus/__tests__/StatusMessage.a11y.renders.tsx +0 -287
  346. package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +0 -302
  347. package/src/FieldStatus/__tests__/StatusMessage.a11y.test.tsx +0 -154
  348. package/src/FileInput/FileInput.fr10.test.tsx +0 -21
  349. package/src/FileInput/FileInput.test.tsx +0 -1291
  350. package/src/FormLayout/FormLayout.test.tsx +0 -444
  351. package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +0 -46
  352. package/src/Grid/Grid.test.tsx +0 -509
  353. package/src/HStack/HStack.test.tsx +0 -129
  354. package/src/Heading/Heading.test.tsx +0 -328
  355. package/src/HoverCard/HoverCard.test.tsx +0 -1339
  356. package/src/Icon/Icon.test.tsx +0 -990
  357. package/src/Icon/globalIconRegistry.test.tsx +0 -613
  358. package/src/IconButton/IconButton.test.tsx +0 -156
  359. package/src/Indicator/Indicator.test.tsx +0 -389
  360. package/src/Indicator/indicatorRegistry.test.tsx +0 -106
  361. package/src/InputGroup/InputGroup.test.tsx +0 -502
  362. package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +0 -185
  363. package/src/Item/Item.source-build.test.mjs +0 -88
  364. package/src/Item/Item.swipeLayer.test.tsx +0 -74
  365. package/src/Item/Item.test.tsx +0 -1515
  366. package/src/Item/ItemMarkerColumns.a11y.chromium.spec.ts +0 -211
  367. package/src/Item/__tests__/ItemSwipeActions.a11y.chromium.spec.ts +0 -337
  368. package/src/Item/__tests__/ItemSwipePinchZoom.a11y.chromium.spec.ts +0 -186
  369. package/src/Kbd/Kbd.test.tsx +0 -299
  370. package/src/Layer/LayerProvider.test.tsx +0 -143
  371. package/src/Layer/__tests__/LayerBrowserHide.a11y.chromium.spec.ts +0 -126
  372. package/src/Layer/__tests__/LayerReducedMotion.a11y.chromium.spec.ts +0 -176
  373. package/src/Layer/__tests__/TouchTrigger.a11y.chromium.spec.ts +0 -200
  374. package/src/Layer/anchorName.test.ts +0 -146
  375. package/src/Layer/layerDismissalFamilies.test.tsx +0 -487
  376. package/src/Layer/layerDismissalInvariants.test.tsx +0 -501
  377. package/src/Layer/layerHost.test.ts +0 -117
  378. package/src/Layer/layerScopedContext.test.tsx +0 -499
  379. package/src/Layer/layerViewportInset.source-build.test.mjs +0 -90
  380. package/src/Layer/layerViewportInset.test.ts +0 -120
  381. package/src/Layer/popoverOperations.test.ts +0 -205
  382. package/src/Layer/useLayer.test.tsx +0 -2845
  383. package/src/Layer/useLayerDismissal.test.tsx +0 -580
  384. package/src/Layer/useTouchTrigger.test.ts +0 -70
  385. package/src/Layout/Layout.test.tsx +0 -375
  386. package/src/Layout/LayoutSlots.test.tsx +0 -376
  387. package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +0 -134
  388. package/src/Layout/__tests__/Layout.a11y.renders.tsx +0 -110
  389. package/src/Layout/__tests__/Layout.a11y.states.ts +0 -93
  390. package/src/Layout/__tests__/Layout.a11y.test.tsx +0 -142
  391. package/src/Layout/__tests__/childrenAsContent.test.tsx +0 -59
  392. package/src/Layout/__tests__/contentWidth.test.tsx +0 -303
  393. package/src/Layout/__tests__/edgeCompensation.test.tsx +0 -191
  394. package/src/Layout/__tests__/nestedPadding.test.tsx +0 -264
  395. package/src/Layout/overlayPaddingReset.test.tsx +0 -224
  396. package/src/Lightbox/Lightbox.test.tsx +0 -837
  397. package/src/Lightbox/LightboxKeyboard.a11y.browser.spec.ts +0 -78
  398. package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +0 -74
  399. package/src/Lightbox/useLightbox.test.tsx +0 -263
  400. package/src/Link/Link.test.tsx +0 -457
  401. package/src/Link/__tests__/Link.a11y.chromium.spec.ts +0 -153
  402. package/src/Link/__tests__/Link.a11y.renders.tsx +0 -97
  403. package/src/Link/__tests__/Link.a11y.states.ts +0 -104
  404. package/src/Link/__tests__/Link.a11y.test.tsx +0 -127
  405. package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +0 -262
  406. package/src/Link/__tests__/Link.truncation.a11y.chromium.spec.ts +0 -58
  407. package/src/Link/useLinkComponent.test.tsx +0 -572
  408. package/src/Link/useLinkify.test.tsx +0 -146
  409. package/src/List/List.test.tsx +0 -1052
  410. package/src/List/ListItem.source-build.test.mjs +0 -41
  411. package/src/List/ListMarkers.a11y.chromium.spec.ts +0 -904
  412. package/src/Markdown/Markdown.codeLanguages.test.tsx +0 -137
  413. package/src/Markdown/Markdown.fr23.bench.ts +0 -176
  414. package/src/Markdown/Markdown.fr23.perf.test.ts +0 -484
  415. package/src/Markdown/Markdown.helpers.perf.test.ts +0 -495
  416. package/src/Markdown/Markdown.public.test.ts +0 -309
  417. package/src/Markdown/Markdown.renderBoundary.test.tsx +0 -72
  418. package/src/Markdown/Markdown.rerender.test.tsx +0 -143
  419. package/src/Markdown/Markdown.test.tsx +0 -1383
  420. package/src/Markdown/MarkdownTable.a11y.chromium.spec.ts +0 -727
  421. package/src/Markdown/__tests__/MarkdownNesting.a11y.chromium.spec.ts +0 -102
  422. package/src/Markdown/angleDestinations.test.tsx +0 -104
  423. package/src/Markdown/ast.test.ts +0 -374
  424. package/src/Markdown/atxHeadingIndentation.test.tsx +0 -53
  425. package/src/Markdown/blockNesting.test.tsx +0 -124
  426. package/src/Markdown/blockquoteMarkers.test.tsx +0 -69
  427. package/src/Markdown/characterReferences.test.ts +0 -47
  428. package/src/Markdown/codeSpans.test.tsx +0 -65
  429. package/src/Markdown/emphasis.test.tsx +0 -214
  430. package/src/Markdown/fenceInfo.test.tsx +0 -47
  431. package/src/Markdown/imageAlt.test.tsx +0 -84
  432. package/src/Markdown/incremental.test.ts +0 -1198
  433. package/src/Markdown/incrementalIndentation.test.tsx +0 -36
  434. package/src/Markdown/indentedFences.test.tsx +0 -374
  435. package/src/Markdown/indentedTables.test.tsx +0 -53
  436. package/src/Markdown/linkBrackets.test.tsx +0 -116
  437. package/src/Markdown/linkDestinationLinear.test.tsx +0 -54
  438. package/src/Markdown/linkDestinations.test.tsx +0 -127
  439. package/src/Markdown/linkTextCode.test.tsx +0 -65
  440. package/src/Markdown/listBullets.test.tsx +0 -55
  441. package/src/Markdown/listContinuation.test.tsx +0 -94
  442. package/src/Markdown/listThematicBreak.test.tsx +0 -49
  443. package/src/Markdown/longLinkLabels.test.tsx +0 -49
  444. package/src/Markdown/openFenceFinalNewline.test.tsx +0 -85
  445. package/src/Markdown/parser.perf.test.ts +0 -398
  446. package/src/Markdown/parser.public.test.ts +0 -144
  447. package/src/Markdown/parser.test.ts +0 -1925
  448. package/src/Markdown/plugin-renderer/MarkdownPluginNodeRenderer.test.tsx +0 -300
  449. package/src/Markdown/plugins/frontmatter.test.tsx +0 -150
  450. package/src/Markdown/plugins/headingLinks.a11y.chromium.spec.ts +0 -856
  451. package/src/Markdown/plugins/headingLinks.ssr.test.tsx +0 -143
  452. package/src/Markdown/plugins/headingLinks.test.tsx +0 -637
  453. package/src/Markdown/plugins/protocol.test.tsx +0 -1083
  454. package/src/Markdown/plugins/semanticFence.test.tsx +0 -655
  455. package/src/Markdown/plugins/softBreaks.test.tsx +0 -172
  456. package/src/Markdown/plugins/sourceDecoration.test.tsx +0 -799
  457. package/src/Markdown/plugins/sourceLines.test.tsx +0 -715
  458. package/src/Markdown/plugins/textTransform.test.ts +0 -467
  459. package/src/Markdown/remark.test.tsx +0 -1877
  460. package/src/Markdown/streaming.test.ts +0 -148
  461. package/src/Markdown/streamingListShapes.test.tsx +0 -93
  462. package/src/Markdown/trailingSpaces.test.tsx +0 -45
  463. package/src/MetadataList/MetadataList.test.tsx +0 -383
  464. package/src/MobileNav/MobileNav.test.tsx +0 -296
  465. package/src/MobileNav/MobileNavCloseEdgeCases.test.tsx +0 -584
  466. package/src/MobileNav/MobileNavCloseTiming.test.ts +0 -58
  467. package/src/MobileNav/MobileNavCloseVisibility.test.tsx +0 -172
  468. package/src/MobileNav/MobileNavEntryAnimation.test.tsx +0 -212
  469. package/src/MobileNav/MobileNavFocus.test.tsx +0 -553
  470. package/src/MobileNav/MobileNavPinchZoom.a11y.chromium.spec.ts +0 -147
  471. package/src/MobileNav/MobileNavReopen.test.tsx +0 -118
  472. package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +0 -109
  473. package/src/MobileNav/MobileNavToggle.test.tsx +0 -179
  474. package/src/MobileNav/__tests__/MobileNavHeader.a11y.chromium.spec.ts +0 -89
  475. package/src/MobileNav/__tests__/MobileNavWidth.a11y.chromium.spec.ts +0 -103
  476. package/src/MoreMenu/MoreMenu.test.tsx +0 -367
  477. package/src/MultiSelector/CreateRow.a11y.chromium.spec.ts +0 -148
  478. package/src/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.ts +0 -72
  479. package/src/MultiSelector/MultiSelector.focusableDisabled.test.tsx +0 -121
  480. package/src/MultiSelector/MultiSelector.fr10.test.tsx +0 -221
  481. package/src/MultiSelector/MultiSelector.test.tsx +0 -4971
  482. package/src/MultiSelector/OptionActions.a11y.chromium.spec.ts +0 -310
  483. package/src/MultiSelector/__tests__/MultiSelector.a11y.chromium.spec.ts +0 -46
  484. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +0 -135
  485. package/src/NavIcon/NavIcon.test.tsx +0 -41
  486. package/src/NavMenu/NavHeadingMenu.test.tsx +0 -714
  487. package/src/NavMenu/__tests__/NavMenusSlideSelection.a11y.chromium.spec.ts +0 -137
  488. package/src/NumberInput/NumberInput.fr10.test.tsx +0 -21
  489. package/src/NumberInput/NumberInput.test.tsx +0 -2697
  490. package/src/NumberInput/__tests__/NumberInput.a11y.chromium.spec.ts +0 -124
  491. package/src/NumberInput/__tests__/NumberInput.a11y.known-failures.ts +0 -26
  492. package/src/NumberInput/__tests__/NumberInput.a11y.renders.tsx +0 -77
  493. package/src/NumberInput/__tests__/NumberInput.a11y.states.ts +0 -116
  494. package/src/NumberInput/__tests__/NumberInput.a11y.test.tsx +0 -154
  495. package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +0 -102
  496. package/src/NumberInput/numberInputCommit.test.ts +0 -72
  497. package/src/NumberInput/numberParser.docblock.test.ts +0 -234
  498. package/src/NumberInput/numberParser.test.ts +0 -222
  499. package/src/Outline/Outline.test.tsx +0 -1134
  500. package/src/Outline/OutlineFocus.a11y.chromium.spec.ts +0 -551
  501. package/src/Outline/parseOutlineFromMarkdown.test.ts +0 -104
  502. package/src/OverflowList/OverflowList.test.tsx +0 -1073
  503. package/src/Overlay/Overlay.test.tsx +0 -424
  504. package/src/Pagination/Pagination.test.tsx +0 -1754
  505. package/src/Popover/Popover.test.tsx +0 -1508
  506. package/src/Popover/PopoverPresentation.test.tsx +0 -952
  507. package/src/Popover/__tests__/PopoverSecondDocument.a11y.chromium.spec.ts +0 -267
  508. package/src/PowerSearch/PowerSearch.test.tsx +0 -1027
  509. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +0 -1190
  510. package/src/PowerSearch/PowerSearchFilterEditor.test.tsx +0 -377
  511. package/src/PowerSearch/PowerSearchToken.test.tsx +0 -230
  512. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +0 -754
  513. package/src/PowerSearch/formatFilterValue.test.ts +0 -339
  514. package/src/PowerSearch/resolveDateTimeRangePart.test.ts +0 -40
  515. package/src/PowerSearch/usePowerSearchConfig.test.ts +0 -832
  516. package/src/PowerSearch/usePowerSearchSource.test.ts +0 -621
  517. package/src/ProgressBar/ProgressBar.test.tsx +0 -928
  518. package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +0 -127
  519. package/src/ProgressBar/__tests__/ProgressBar.a11y.known-failures.ts +0 -12
  520. package/src/ProgressBar/__tests__/ProgressBar.a11y.renders.tsx +0 -38
  521. package/src/ProgressBar/__tests__/ProgressBar.a11y.states.ts +0 -123
  522. package/src/ProgressBar/__tests__/ProgressBar.a11y.test.tsx +0 -107
  523. package/src/ProgressBar/__tests__/ProgressBarMotion.a11y.chromium.spec.ts +0 -831
  524. package/src/RadioList/RadioList.fr10.test.tsx +0 -67
  525. package/src/RadioList/RadioList.test.tsx +0 -1051
  526. package/src/RadioList/RadioListItem.press.source-build.test.mjs +0 -80
  527. package/src/RadioList/__tests__/RadioGroup.a11y.chromium.spec.ts +0 -274
  528. package/src/RadioList/__tests__/RadioGroup.a11y.known-failures.ts +0 -12
  529. package/src/RadioList/__tests__/RadioGroup.a11y.renders.tsx +0 -232
  530. package/src/RadioList/__tests__/RadioGroup.a11y.states.ts +0 -503
  531. package/src/RadioList/__tests__/RadioGroup.a11y.test.tsx +0 -217
  532. package/src/Resizable/ResizeHandle.test.tsx +0 -1067
  533. package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +0 -127
  534. package/src/Resizable/__tests__/ResizeHandle.a11y.known-failures.ts +0 -39
  535. package/src/Resizable/__tests__/ResizeHandle.a11y.renders.tsx +0 -80
  536. package/src/Resizable/__tests__/ResizeHandle.a11y.states.ts +0 -197
  537. package/src/Resizable/__tests__/ResizeHandle.a11y.test.tsx +0 -123
  538. package/src/Resizable/shippedDirections.test.ts +0 -462
  539. package/src/Resizable/useResizable.test.ts +0 -1725
  540. package/src/Resizable/utils.test.ts +0 -74
  541. package/src/ScrollableArea/ScrollableArea.test.tsx +0 -304
  542. package/src/Section/Section.test.tsx +0 -376
  543. package/src/SegmentedControl/SegmentedControl.test.tsx +0 -981
  544. package/src/SelectableCard/SelectableCard.test.tsx +0 -216
  545. package/src/Selector/Selector.focusableDisabled.test.tsx +0 -127
  546. package/src/Selector/Selector.fr10.test.tsx +0 -149
  547. package/src/Selector/Selector.sheetActiveDescendant.test.tsx +0 -95
  548. package/src/Selector/Selector.source-build.test.mjs +0 -79
  549. package/src/Selector/Selector.test.tsx +0 -5117
  550. package/src/Selector/__tests__/Combobox.a11y.known-failures.ts +0 -27
  551. package/src/Selector/__tests__/Combobox.a11y.states.ts +0 -145
  552. package/src/Selector/__tests__/ComboboxField.a11y.chromium.spec.ts +0 -458
  553. package/src/Selector/__tests__/EmptyStateAnnouncement.a11y.chromium.spec.ts +0 -91
  554. package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +0 -131
  555. package/src/Selector/__tests__/Listbox.a11y.dom.ts +0 -38
  556. package/src/Selector/__tests__/Listbox.a11y.inventory.test.ts +0 -63
  557. package/src/Selector/__tests__/Listbox.a11y.known-failures.ts +0 -12
  558. package/src/Selector/__tests__/Listbox.a11y.states.ts +0 -232
  559. package/src/Selector/__tests__/Selector.a11y.chromium.spec.ts +0 -46
  560. package/src/Selector/__tests__/Selector.combobox.a11y.chromium.spec.ts +0 -109
  561. package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +0 -133
  562. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +0 -128
  563. package/src/Selector/useCombobox.public.test.tsx +0 -89
  564. package/src/Selector/useCombobox.test.tsx +0 -444
  565. package/src/SideNav/SideNav.test.tsx +0 -4275
  566. package/src/SideNav/SideNavRailMotion.test.tsx +0 -620
  567. package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +0 -542
  568. package/src/SizeContext/SizeContext.test.tsx +0 -226
  569. package/src/Skeleton/Skeleton.test.tsx +0 -148
  570. package/src/Slider/Slider.fr10.test.tsx +0 -93
  571. package/src/Slider/Slider.test.tsx +0 -1661
  572. package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +0 -125
  573. package/src/Slider/__tests__/Slider.a11y.known-failures.ts +0 -12
  574. package/src/Slider/__tests__/Slider.a11y.renders.tsx +0 -42
  575. package/src/Slider/__tests__/Slider.a11y.states.ts +0 -106
  576. package/src/Slider/__tests__/Slider.a11y.test.tsx +0 -105
  577. package/src/Spinner/Spinner.test.tsx +0 -484
  578. package/src/Stack/Stack.test.tsx +0 -473
  579. package/src/Stack/StackItem.test.tsx +0 -105
  580. package/src/StatusDot/StatusDot.test.tsx +0 -213
  581. package/src/Stepper/Stepper.public.test.ts +0 -91
  582. package/src/Stepper/Stepper.test.tsx +0 -2130
  583. package/src/Switch/Switch.focusRing.source-build.test.mjs +0 -81
  584. package/src/Switch/Switch.test.tsx +0 -1136
  585. package/src/Switch/__tests__/Switch.a11y.chromium.spec.ts +0 -211
  586. package/src/Switch/__tests__/Switch.a11y.known-failures.ts +0 -28
  587. package/src/Switch/__tests__/Switch.a11y.states.ts +0 -275
  588. package/src/Switch/__tests__/Switch.a11y.test.tsx +0 -144
  589. package/src/TabList/TabList.test.tsx +0 -1755
  590. package/src/TabList/__tests__/TabListOverflow.interaction.browser.spec.ts +0 -99
  591. package/src/TabList/__tests__/TabPressPointer.interaction.browser.spec.ts +0 -163
  592. package/src/TabList/__tests__/Tabs.a11y.chromium.spec.ts +0 -199
  593. package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +0 -12
  594. package/src/TabList/__tests__/Tabs.a11y.renders.tsx +0 -92
  595. package/src/TabList/__tests__/Tabs.a11y.states.ts +0 -247
  596. package/src/TabList/__tests__/Tabs.a11y.test.tsx +0 -153
  597. package/src/Table/Table.perf.test.tsx +0 -569
  598. package/src/Table/Table.test.tsx +0 -1883
  599. package/src/Table/TableHeaderCell.test.tsx +0 -291
  600. package/src/Table/TableSelectionToolbar.test.tsx +0 -109
  601. package/src/Table/__tests__/Table.a11y.chromium.spec.ts +0 -141
  602. package/src/Table/__tests__/Table.a11y.contracts.ts +0 -35
  603. package/src/Table/__tests__/Table.a11y.renders.tsx +0 -112
  604. package/src/Table/__tests__/Table.a11y.states.ts +0 -136
  605. package/src/Table/__tests__/Table.a11y.test.tsx +0 -198
  606. package/src/Table/__tests__/TableMinWidth.a11y.chromium.spec.ts +0 -75
  607. package/src/Table/__tests__/TableRowGlide.a11y.browser.spec.ts +0 -382
  608. package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +0 -138
  609. package/src/Table/__tests__/TableStickyDividers.a11y.browser.spec.ts +0 -560
  610. package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +0 -941
  611. package/src/Table/plugins/columnSettings/useTableColumnSettings.test.tsx +0 -175
  612. package/src/Table/plugins/columnSettings/useTableColumnSettingsState.test.tsx +0 -296
  613. package/src/Table/plugins/filtering/useTableFilterState.test.tsx +0 -143
  614. package/src/Table/plugins/filtering/useTableFiltering.test.tsx +0 -357
  615. package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +0 -112
  616. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +0 -409
  617. package/src/Table/plugins/pagination/useTablePagination-perf.test.tsx +0 -232
  618. package/src/Table/plugins/pagination/useTablePagination.test.tsx +0 -666
  619. package/src/Table/plugins/rowExpansion/useTableRowExpansion.glide.test.tsx +0 -280
  620. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +0 -681
  621. package/src/Table/plugins/rowIndex/useTableRowIndex.test.tsx +0 -132
  622. package/src/Table/plugins/rowStatus/useTableRowStatus.public.test.ts +0 -92
  623. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +0 -519
  624. package/src/Table/plugins/selection/useTableSelection-perf.test.tsx +0 -258
  625. package/src/Table/plugins/selection/useTableSelection.test.tsx +0 -424
  626. package/src/Table/plugins/selection/useTableSelectionState.test.tsx +0 -451
  627. package/src/Table/plugins/sortable/__tests__/useTableSortable.a11y.test.tsx +0 -174
  628. package/src/Table/plugins/sortable/__tests__/useTableSortable.a11y.ts +0 -86
  629. package/src/Table/plugins/sortable/useTableSortable.test.tsx +0 -786
  630. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +0 -580
  631. package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +0 -334
  632. package/src/Table/plugins/tree/useTableTreeData-perf.test.tsx +0 -163
  633. package/src/Table/plugins/tree/useTableTreeData.test.tsx +0 -992
  634. package/src/Table/plugins/tree/useTableTreeState.test.tsx +0 -740
  635. package/src/Table/tableContextMenu.test.tsx +0 -208
  636. package/src/Text/Text.test.tsx +0 -405
  637. package/src/Text/useTruncation.test.tsx +0 -196
  638. package/src/TextArea/TextArea.fr10.test.tsx +0 -21
  639. package/src/TextArea/TextArea.test.tsx +0 -1317
  640. package/src/TextInput/TextInput.fr10.test.tsx +0 -21
  641. package/src/TextInput/TextInput.test.tsx +0 -1280
  642. package/src/TextInput/__tests__/TextInput.a11y.chromium.spec.ts +0 -214
  643. package/src/TextInput/__tests__/TextInput.a11y.known-failures.ts +0 -40
  644. package/src/TextInput/__tests__/TextInput.a11y.renders.tsx +0 -202
  645. package/src/TextInput/__tests__/TextInput.a11y.states.ts +0 -384
  646. package/src/TextInput/__tests__/TextInput.a11y.test.tsx +0 -130
  647. package/src/Thumbnail/Thumbnail.test.tsx +0 -384
  648. package/src/TimeInput/NativeTimeInput.test.tsx +0 -343
  649. package/src/TimeInput/Presentation.test.tsx +0 -192
  650. package/src/TimeInput/TimeInput.fr10.test.tsx +0 -312
  651. package/src/TimeInput/TimeInput.test.tsx +0 -907
  652. package/src/Timer/Timer.test.tsx +0 -302
  653. package/src/Timestamp/Timestamp.test.tsx +0 -1661
  654. package/src/Timestamp/tooltipEntries.test.ts +0 -566
  655. package/src/Toast/ToastViewport.modalHost.test.tsx +0 -891
  656. package/src/Toast/ToastViewport.test.tsx +0 -3130
  657. package/src/Toast/useToast.test.tsx +0 -258
  658. package/src/ToggleButton/ToggleButton.test.tsx +0 -1000
  659. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +0 -177
  660. package/src/ToggleButton/__tests__/ToggleButton.a11y.renders.tsx +0 -133
  661. package/src/ToggleButton/__tests__/ToggleButton.a11y.states.ts +0 -167
  662. package/src/ToggleButton/__tests__/ToggleButton.a11y.test.tsx +0 -103
  663. package/src/Token/Token.test.tsx +0 -707
  664. package/src/Token/__tests__/TokenRemoveTarget.a11y.chromium.spec.ts +0 -87
  665. package/src/Tokenizer/Tokenizer.fr10.test.tsx +0 -28
  666. package/src/Tokenizer/Tokenizer.props-type.test.tsx +0 -126
  667. package/src/Tokenizer/Tokenizer.ssr.test.tsx +0 -196
  668. package/src/Tokenizer/Tokenizer.test.tsx +0 -2216
  669. package/src/Tokenizer/TokenizerBottomSheet.test.tsx +0 -2738
  670. package/src/Tokenizer/__tests__/TokenizerEndLane.a11y.chromium.spec.ts +0 -505
  671. package/src/Toolbar/Toolbar.test.tsx +0 -600
  672. package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +0 -176
  673. package/src/Toolbar/__tests__/Toolbar.a11y.renders.tsx +0 -63
  674. package/src/Toolbar/__tests__/Toolbar.a11y.states.ts +0 -142
  675. package/src/Toolbar/__tests__/Toolbar.a11y.test.tsx +0 -126
  676. package/src/Tooltip/Tooltip.test.tsx +0 -819
  677. package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +0 -141
  678. package/src/Tooltip/__tests__/Tooltip.a11y.renders.tsx +0 -86
  679. package/src/Tooltip/__tests__/Tooltip.a11y.states.ts +0 -132
  680. package/src/Tooltip/__tests__/Tooltip.a11y.test.tsx +0 -126
  681. package/src/Tooltip/__tests__/TooltipFocusReturn.a11y.chromium.spec.ts +0 -130
  682. package/src/Tooltip/__tests__/TooltipHoverBridge.a11y.chromium.spec.ts +0 -75
  683. package/src/Tooltip/__tests__/TooltipTallContent.a11y.browser.spec.ts +0 -673
  684. package/src/Tooltip/__tests__/TooltipTallContentTracking.a11y.browser.spec.ts +0 -1162
  685. package/src/Tooltip/useTooltip.test.tsx +0 -483
  686. package/src/TopNav/TopNav.test.tsx +0 -863
  687. package/src/TopNav/TopNavMegaMenu.reduced-motion.source-build.test.mjs +0 -83
  688. package/src/TopNav/TopNavMegaMenu.test.tsx +0 -1153
  689. package/src/TopNav/TopNavMenu.test.tsx +0 -502
  690. package/src/TopNav/__tests__/TopNavMobileLongHeading.a11y.chromium.spec.ts +0 -75
  691. package/src/TreeList/TreeList.test.tsx +0 -1737
  692. package/src/TreeList/__tests__/TreeList.a11y.chromium.spec.ts +0 -138
  693. package/src/TreeList/__tests__/TreeList.a11y.renders.tsx +0 -44
  694. package/src/TreeList/__tests__/TreeList.a11y.states.ts +0 -164
  695. package/src/TreeList/__tests__/TreeList.a11y.test.tsx +0 -138
  696. package/src/TreeList/__tests__/TreeListGuideAlignment.interaction.browser.spec.ts +0 -127
  697. package/src/TreeList/__tests__/TreeListRowNames.a11y.chromium.spec.ts +0 -83
  698. package/src/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.ts +0 -138
  699. package/src/Typeahead/BaseTypeahead.test.tsx +0 -553
  700. package/src/Typeahead/Typeahead.fr10.test.tsx +0 -28
  701. package/src/Typeahead/Typeahead.test.tsx +0 -2984
  702. package/src/Typeahead/TypeaheadItem.test.tsx +0 -134
  703. package/src/VStack/VStack.test.tsx +0 -128
  704. package/src/VisuallyHidden/VisuallyHidden.test.tsx +0 -115
  705. package/src/__tests__/BusyOwnerAnnouncement.test.tsx +0 -853
  706. package/src/__tests__/CardPress.a11y.chromium.spec.ts +0 -353
  707. package/src/__tests__/DisabledTriggerFocus.a11y.chromium.spec.ts +0 -87
  708. package/src/__tests__/PressModality.a11y.chromium.spec.ts +0 -392
  709. package/src/__tests__/PressedState.a11y.chromium.spec.ts +0 -814
  710. package/src/__tests__/TestIcon.tsx +0 -26
  711. package/src/__tests__/babelPluginAddExtensions.test.ts +0 -190
  712. package/src/__tests__/fastRoleQueries.ts +0 -66
  713. package/src/__tests__/forcedColors.ts +0 -60
  714. package/src/__tests__/internalModulesNotExperimental.test.ts +0 -88
  715. package/src/__tests__/pressState.ts +0 -216
  716. package/src/__tests__/stubMatchMedia.test.ts +0 -79
  717. package/src/__tests__/stubMatchMedia.ts +0 -95
  718. package/src/__tests__/stylexDeclarations.ts +0 -51
  719. package/src/__tests__/unthemedLength.ts +0 -34
  720. package/src/docPropLiterals.test.ts +0 -964
  721. package/src/docPropReferences.test.ts +0 -178
  722. package/src/docs-script.test.mjs +0 -55
  723. package/src/gestures/__tests__/GestureHost.test.ts +0 -2136
  724. package/src/gestures/__tests__/LongPressGestureRecognizer.test.ts +0 -141
  725. package/src/gestures/__tests__/PanGestureRecognizer.test.ts +0 -327
  726. package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +0 -74
  727. package/src/gestures/__tests__/PressTracker.test.ts +0 -275
  728. package/src/gestures/__tests__/ScreenEdgePanGestureRecognizer.test.ts +0 -498
  729. package/src/gestures/__tests__/SwipeGestureRecognizer.test.ts +0 -108
  730. package/src/gestures/__tests__/TapGestureRecognizer.test.ts +0 -154
  731. package/src/gestures/__tests__/VelocityTracker.streams.test.ts +0 -243
  732. package/src/gestures/__tests__/VelocityTracker.test.ts +0 -261
  733. package/src/gestures/__tests__/arena.test.ts +0 -864
  734. package/src/gestures/__tests__/arenaContinuous.test.ts +0 -207
  735. package/src/gestures/__tests__/arenaPinchSwipeEdge.test.ts +0 -193
  736. package/src/gestures/__tests__/arenaTapLongPress.test.ts +0 -211
  737. package/src/gestures/__tests__/browser/build-fixture.mjs +0 -46
  738. package/src/gestures/__tests__/browser/fixture.ts +0 -307
  739. package/src/gestures/__tests__/browser/gestures.interaction.browser.spec.ts +0 -1137
  740. package/src/gestures/__tests__/browserNegotiation.test.ts +0 -293
  741. package/src/gestures/__tests__/fixtures/pointer-streams/README.md +0 -82
  742. package/src/gestures/__tests__/fixtures/pointer-streams/android-chromium-fling.json +0 -130
  743. package/src/gestures/__tests__/fixtures/pointer-streams/android-chromium-slow.json +0 -860
  744. package/src/gestures/__tests__/fixtures/pointer-streams/android-chromium-stop-release.json +0 -357
  745. package/src/gestures/__tests__/fixtures/pointer-streams/android-firefox-fling.json +0 -66
  746. package/src/gestures/__tests__/fixtures/pointer-streams/android-firefox-slow.json +0 -268
  747. package/src/gestures/__tests__/fixtures/pointer-streams/android-firefox-stop-release.json +0 -128
  748. package/src/gestures/__tests__/fixtures/pointer-streams/capture.html +0 -123
  749. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-mouse-fling.json +0 -64
  750. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-mouse-slow.json +0 -268
  751. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-mouse-stop-release.json +0 -124
  752. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-pen-fling.json +0 -64
  753. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-pen-slow.json +0 -268
  754. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-pen-stop-release.json +0 -124
  755. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-touch-fling.json +0 -84
  756. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-touch-slow.json +0 -381
  757. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-touch-stop-release.json +0 -171
  758. package/src/gestures/__tests__/fixtures/pointer-streams/ios-safari-fling.json +0 -45
  759. package/src/gestures/__tests__/fixtures/pointer-streams/ios-safari-slow.json +0 -101
  760. package/src/gestures/__tests__/fixtures/pointer-streams/ios-safari-stop-release.json +0 -130
  761. package/src/gestures/__tests__/haptics.test.ts +0 -187
  762. package/src/gestures/__tests__/harness.ts +0 -252
  763. package/src/gestures/__tests__/pressTrackerFactory.test.ts +0 -59
  764. package/src/gestures/__tests__/recognizerKind.test.ts +0 -78
  765. package/src/gestures/__tests__/touchActionRule.test.ts +0 -54
  766. package/src/gestures/__tests__/useGestureRecognizer.test.tsx +0 -570
  767. package/src/hooks/__tests__/MenuPressShadowRoot.a11y.chromium.spec.ts +0 -144
  768. package/src/hooks/__tests__/menuLinkClicks.ts +0 -71
  769. package/src/hooks/actionGroupTracker.exports.test.ts +0 -28
  770. package/src/hooks/actionGroupTracker.test.ts +0 -510
  771. package/src/hooks/computeOverflow.test.ts +0 -422
  772. package/src/hooks/deprecatedApis.public.test.ts +0 -33
  773. package/src/hooks/menuPressGesture.test.ts +0 -253
  774. package/src/hooks/scrollKeyboardDelegation.test.ts +0 -188
  775. package/src/hooks/scrollbarGutter.test.ts +0 -167
  776. package/src/hooks/useAnnounce.modal.test.tsx +0 -1291
  777. package/src/hooks/useAnnounce.replace.test.tsx +0 -516
  778. package/src/hooks/useAnnounce.test.tsx +0 -293
  779. package/src/hooks/useAnnounceRenderedText.adopters.test.tsx +0 -235
  780. package/src/hooks/useAutoMediaMode.test.ts +0 -109
  781. package/src/hooks/useBusyAnnouncement.adopters.test.tsx +0 -69
  782. package/src/hooks/useBusyAnnouncement.test.tsx +0 -112
  783. package/src/hooks/useClickableContainer.test.tsx +0 -236
  784. package/src/hooks/useClipboard.test.tsx +0 -151
  785. package/src/hooks/useContainerReveal.test.tsx +0 -163
  786. package/src/hooks/useDevWarning.test.tsx +0 -45
  787. package/src/hooks/useEntryAnimation.ssr.test.tsx +0 -143
  788. package/src/hooks/useFocusTrap.test.tsx +0 -635
  789. package/src/hooks/useFocusTrapEscapeShim.test.tsx +0 -166
  790. package/src/hooks/useGridFocus.test.tsx +0 -165
  791. package/src/hooks/useHotkeys.test.ts +0 -265
  792. package/src/hooks/useImageMode.test.ts +0 -133
  793. package/src/hooks/useInputContainer.test.tsx +0 -180
  794. package/src/hooks/useInputStatusIcon.test.tsx +0 -240
  795. package/src/hooks/useIsHydrating.test.tsx +0 -70
  796. package/src/hooks/useKeyboardHint.test.tsx +0 -92
  797. package/src/hooks/useListFocus.test.tsx +0 -664
  798. package/src/hooks/useLongPress.test.tsx +0 -152
  799. package/src/hooks/useMediaQuery.test.ts +0 -165
  800. package/src/hooks/useMenuHover.test.tsx +0 -536
  801. package/src/hooks/useMenuPress.test.tsx +0 -565
  802. package/src/hooks/useMergedRefs.test.tsx +0 -62
  803. package/src/hooks/useOverflow.test.ts +0 -504
  804. package/src/hooks/useRenamedProp.test.tsx +0 -95
  805. package/src/hooks/useScrollLock.test.ts +0 -248
  806. package/src/hooks/useScrollOverflow.test.tsx +0 -323
  807. package/src/hooks/useScrollableArea.test.tsx +0 -836
  808. package/src/hooks/useStreamingText.test.ts +0 -237
  809. package/src/hooks/useTreeFocus.test.tsx +0 -351
  810. package/src/hooks/useTypeahead.test.tsx +0 -351
  811. package/src/i18n/__tests__/InternationalizationProvider.test.tsx +0 -128
  812. package/src/i18n/__tests__/e2e-pagination.test.tsx +0 -172
  813. package/src/i18n/__tests__/e2e-powersearch.test.tsx +0 -166
  814. package/src/i18n/__tests__/getLocaleDirection.test.ts +0 -40
  815. package/src/i18n/__tests__/resolve.test.ts +0 -325
  816. package/src/i18n/__tests__/useCollator.test.tsx +0 -115
  817. package/src/i18n/__tests__/useDirection.test.tsx +0 -66
  818. package/src/i18n/__tests__/useLocale.test.tsx +0 -52
  819. package/src/i18n/useTranslator.test.tsx +0 -267
  820. package/src/inputFontFloor.test.ts +0 -106
  821. package/src/internal/tokenizer-presentation.test.ts +0 -29
  822. package/src/internal/touch.test.ts +0 -44
  823. package/src/motion/__tests__/animatedLayout.interaction.browser.spec.ts +0 -1613
  824. package/src/motion/__tests__/animatedLayoutAdopters.interaction.browser.spec.ts +0 -217
  825. package/src/motion/__tests__/animatedLayoutBundle.ts +0 -17
  826. package/src/motion/__tests__/animator.interaction.browser.spec.ts +0 -843
  827. package/src/motion/__tests__/motionBundle.ts +0 -14
  828. package/src/motion/animatedLayout.boundary.test.ts +0 -155
  829. package/src/motion/animatedLayout.swap.test.ts +0 -827
  830. package/src/motion/animatedLayout.test.ts +0 -1154
  831. package/src/motion/animatedLayoutAdopters.test.tsx +0 -500
  832. package/src/motion/animator.test.ts +0 -3746
  833. package/src/motion/bezier.test.ts +0 -52
  834. package/src/motion/coast.test.ts +0 -99
  835. package/src/motion/decay.test.ts +0 -120
  836. package/src/motion/projection.test.ts +0 -107
  837. package/src/motion/reducedMotion.test.ts +0 -129
  838. package/src/motion/reducedMotionPlan.test.ts +0 -208
  839. package/src/motion/resolveMotion.test.ts +0 -123
  840. package/src/motion/resolveSnapPoint.test.ts +0 -189
  841. package/src/motion/roles.test.ts +0 -273
  842. package/src/motion/rubberBand.test.ts +0 -88
  843. package/src/motion/selectPage.test.ts +0 -31
  844. package/src/motion/spring.test.ts +0 -650
  845. package/src/motion/uikit/gestures.test.ts +0 -89
  846. package/src/motion/uikit/springRows.test.ts +0 -71
  847. package/src/motion/uikit/tableImports.test.ts +0 -293
  848. package/src/motion/uikit/uikit.test.ts +0 -364
  849. package/src/motion/uikit/values.test.ts +0 -121
  850. package/src/naming.test.ts +0 -44
  851. package/src/postinstall.test.mjs +0 -216
  852. package/src/reset.a11y.chromium.spec.ts +0 -238
  853. package/src/reset.test.ts +0 -205
  854. package/src/reset.until-found.a11y.browser.spec.ts +0 -76
  855. package/src/reset.until-found.test.ts +0 -32
  856. package/src/serverSafeComponents.test.ts +0 -675
  857. package/src/stylexValidation.source-build.test.mjs +0 -42
  858. package/src/tailwind-theme.test.ts +0 -153
  859. package/src/theme/MediaTheme.dom.test.tsx +0 -97
  860. package/src/theme/Theme.test.tsx +0 -337
  861. package/src/theme/__tests__/SpacingRootFontSize.a11y.chromium.spec.ts +0 -199
  862. package/src/theme/contrast.test.ts +0 -94
  863. package/src/theme/declarationBoundary.test.ts +0 -126
  864. package/src/theme/defineTheme.test.ts +0 -2028
  865. package/src/theme/derivedVarRegistry.test.ts +0 -592
  866. package/src/theme/expandColorScale.test.ts +0 -651
  867. package/src/theme/expandMotionScale.test.ts +0 -145
  868. package/src/theme/expandRadiusScale.test.ts +0 -59
  869. package/src/theme/expandTypeScale.test.ts +0 -351
  870. package/src/theme/extensibleAxes.test.ts +0 -432
  871. package/src/theme/generateThemeRules.test.ts +0 -1870
  872. package/src/theme/hct.test.ts +0 -93
  873. package/src/theme/onMediaTokens.test.ts +0 -431
  874. package/src/theme/publicThemeHelperContract.test.ts +0 -67
  875. package/src/theme/syntax/defineSyntaxTheme.diff.test.ts +0 -91
  876. package/src/theme/syntax/serverSafeSyntax.test.ts +0 -68
  877. package/src/theme/syntax/useSyntaxTheme.diff.test.tsx +0 -40
  878. package/src/theme/themeAdaptations.test.ts +0 -1795
  879. package/src/theme/themeMotion.test.ts +0 -620
  880. package/src/theme/themeRegistry.test.ts +0 -59
  881. package/src/theme/themingTargets.test.ts +0 -589
  882. package/src/theme/tokenValueCompat.test.ts +0 -204
  883. package/src/theme/tokens.test.ts +0 -441
  884. package/src/theme/useTheme.test.tsx +0 -322
  885. package/src/unicodePropertyEscapes.source-build.test.mjs +0 -69
  886. package/src/utils/chainEventHandlers.test.ts +0 -39
  887. package/src/utils/characters.test.ts +0 -141
  888. package/src/utils/color.test.ts +0 -233
  889. package/src/utils/composeEventHandlers.test.ts +0 -71
  890. package/src/utils/customPropertyArmLayering.test.ts +0 -131
  891. package/src/utils/dateParser.test.ts +0 -402
  892. package/src/utils/dateTypes.test.ts +0 -40
  893. package/src/utils/devWarning.test.ts +0 -56
  894. package/src/utils/edgeAutoscroll.test.ts +0 -192
  895. package/src/utils/focusReturn.test.ts +0 -119
  896. package/src/utils/getKey.test.ts +0 -25
  897. package/src/utils/getNodeText.test.ts +0 -24
  898. package/src/utils/hitArea.test.ts +0 -628
  899. package/src/utils/ime.test.ts +0 -32
  900. package/src/utils/inputAria.test.ts +0 -39
  901. package/src/utils/interactionModality.test.ts +0 -144
  902. package/src/utils/isApplePlatform.test.ts +0 -61
  903. package/src/utils/mergeProps.test.ts +0 -166
  904. package/src/utils/mergeRefs.test.ts +0 -48
  905. package/src/utils/parseStyleKey.test.ts +0 -56
  906. package/src/utils/plainDate.test.ts +0 -938
  907. package/src/utils/presentation.test.ts +0 -380
  908. package/src/utils/pressFeedback.test.ts +0 -1012
  909. package/src/utils/pressGesture.test.ts +0 -332
  910. package/src/utils/pressPaintPriority.test.ts +0 -80
  911. package/src/utils/pressPaintSource.test.ts +0 -65
  912. package/src/utils/pressableCoverage.test.ts +0 -192
  913. package/src/utils/primaryClick.test.ts +0 -38
  914. package/src/utils/safeUrl.test.ts +0 -101
  915. package/src/utils/sharedMutationObserver.test.ts +0 -106
  916. package/src/utils/sharedResizeObserver.test.ts +0 -283
  917. package/src/utils/themeProps.test.ts +0 -62
  918. package/src/utils/timeFormat.test.ts +0 -204
  919. package/src/utils/timeParser.test.ts +0 -295
  920. package/src/utils/touchPresentation.test.ts +0 -462
  921. package/src/utils/unicodeDigits.test.ts +0 -44
@@ -1,2186 +0,0 @@
1
- // Copyright (c) Meta Platforms, Inc. and affiliates.
2
-
3
- /**
4
- * @file Calendar.test.tsx
5
- * @input Uses vitest, @testing-library/react
6
- * @output Test suite for Calendar component
7
- * @position Tests for Calendar.tsx
8
- *
9
- * SYNC: When Calendar.tsx changes, update tests accordingly
10
- */
11
-
12
- import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
13
- import {act, render, screen, within, waitFor} from '@testing-library/react';
14
- import userEvent from '@testing-library/user-event';
15
- import {getButton} from '../__tests__/fastRoleQueries';
16
- import {
17
- getForcedColorsRules,
18
- getAllInjectedCss,
19
- } from '../__tests__/forcedColors';
20
- import * as stylex from '@stylexjs/stylex';
21
- import {useState} from 'react';
22
- import {Calendar} from './Calendar';
23
- import type {CalendarHandle, ISODateString, DateRange} from './Calendar';
24
- import {calendarStyles} from './styles';
25
- import {defineTheme} from '../theme/defineTheme';
26
- import {generateThemeCSS} from '../theme/generateThemeRules';
27
- import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
28
- import {InternationalizationProvider} from '../i18n/InternationalizationProvider';
29
- import {standaloneShortWeekdayNamesByLocale} from './standaloneShortWeekdayNames.generated';
30
-
31
- function generateThemeTestCSS(theme: Parameters<typeof generateThemeCSS>[0]) {
32
- const {prose, component} = generateThemeCSS(theme);
33
- return [prose, component].filter(Boolean).join('\n\n');
34
- }
35
- afterEach(() => {
36
- __resetLiveRegionsForTest();
37
- });
38
-
39
- function politeRegion(): HTMLElement | null {
40
- return document.querySelector('[data-astryx-live-region="polite"]');
41
- }
42
-
43
- /** A controlled Calendar whose owner follows the focus-date changes. */
44
- function ControlledFocusCalendar({
45
- onFocusDateChange,
46
- }: {
47
- onFocusDateChange: (iso: string) => void;
48
- }) {
49
- const [focusDate, setFocusDate] = useState<ISODateString>('2026-01-01');
50
- return (
51
- <Calendar
52
- focusDate={focusDate}
53
- onFocusDateChange={iso => {
54
- onFocusDateChange(iso);
55
- setFocusDate(iso);
56
- }}
57
- />
58
- );
59
- }
60
-
61
- /**
62
- * Helper to find a day button by its day number.
63
- * Day buttons are native <button> elements with aria-labels like
64
- * "Thursday, January 15, 2026". Each button is the sole child of a
65
- * role="gridcell" wrapper.
66
- */
67
- function getDayButton(day: number, month = 'January', year = 2026) {
68
- // Match the full date pattern with the day number
69
- const pattern = new RegExp(`${month}\\s+${day},\\s+${year}`);
70
- return getButton(pattern);
71
- }
72
-
73
- describe('Calendar', () => {
74
- it("with week numbers, the header row's corner cell is a named columnheader, so every row child is a grid cell", () => {
75
- render(<Calendar focusDate="2026-01-01" hasWeekNumbers />);
76
- const grid = screen.getByRole('grid');
77
- const stray = grid.querySelectorAll(
78
- '[role="row"] > :not([role="gridcell"]):not([role="columnheader"]):not([role="rowheader"])',
79
- );
80
- expect(stray).toHaveLength(0);
81
- // Named from CLDR ("week" in en-US), as visually hidden text.
82
- expect(
83
- within(grid).getByRole('columnheader', {name: 'week'}),
84
- ).toBeInTheDocument();
85
- expect(within(grid).getAllByRole('rowheader').length).toBeGreaterThan(0);
86
- });
87
-
88
- // ─── Basic Rendering ─────────────────────────────────────────
89
- it('forwards ref to the calendar root element', () => {
90
- let root: HTMLDivElement | null = null;
91
- render(
92
- <Calendar
93
- ref={el => {
94
- root = el;
95
- }}
96
- />,
97
- );
98
- expect(root).toBeInstanceOf(HTMLDivElement);
99
- });
100
-
101
- it('exposes navigation through handleRef', () => {
102
- let handle: CalendarHandle | null = null;
103
- render(
104
- <Calendar
105
- handleRef={h => {
106
- handle = h;
107
- }}
108
- />,
109
- );
110
-
111
- act(() => {
112
- handle?.navigateTo('2026-03-01');
113
- });
114
-
115
- expect(screen.getByText('March 2026')).toBeInTheDocument();
116
- });
117
-
118
- it('renders current month by default', () => {
119
- render(<Calendar />);
120
-
121
- const today = new Date();
122
- const formatter = new Intl.DateTimeFormat(undefined, {
123
- year: 'numeric',
124
- month: 'long',
125
- });
126
- const expectedLabel = formatter.format(today);
127
-
128
- expect(screen.getByText(expectedLabel)).toBeInTheDocument();
129
- });
130
-
131
- it("marks today's cell with aria-current='date'", () => {
132
- render(<Calendar />);
133
-
134
- const now = new Date();
135
- const iso = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
136
-
137
- const todayCell = document.querySelector(`button[data-date="${iso}"]`);
138
- expect(todayCell).not.toBeNull();
139
- expect(todayCell).toHaveAttribute('aria-current', 'date');
140
-
141
- // Only today's cell is marked current.
142
- const others = Array.from(
143
- document.querySelectorAll('button[data-date]'),
144
- ).filter(el => el.getAttribute('data-date') !== iso);
145
- expect(others.length).toBeGreaterThan(0);
146
- others.forEach(el => expect(el).not.toHaveAttribute('aria-current'));
147
- });
148
-
149
- it('displays day names', () => {
150
- render(<Calendar />);
151
-
152
- expect(screen.getByText('Su')).toBeInTheDocument();
153
- expect(screen.getByText('Mo')).toBeInTheDocument();
154
- expect(screen.getByText('Tu')).toBeInTheDocument();
155
- expect(screen.getByText('We')).toBeInTheDocument();
156
- expect(screen.getByText('Th')).toBeInTheDocument();
157
- expect(screen.getByText('Fr')).toBeInTheDocument();
158
- expect(screen.getByText('Sa')).toBeInTheDocument();
159
- });
160
-
161
- it('uses the provider locale for stand-alone short day names', () => {
162
- const localizedNames = standaloneShortWeekdayNamesByLocale.es;
163
- const englishNames = standaloneShortWeekdayNamesByLocale.en;
164
- expect(localizedNames).not.toEqual(englishNames);
165
-
166
- const {rerender} = render(
167
- <InternationalizationProvider locale="es-ES">
168
- <Calendar />
169
- </InternationalizationProvider>,
170
- );
171
-
172
- expect(
173
- screen.getAllByRole('columnheader').map(header => header.textContent),
174
- ).toEqual(localizedNames);
175
-
176
- rerender(
177
- <InternationalizationProvider locale="en">
178
- <Calendar />
179
- </InternationalizationProvider>,
180
- );
181
- expect(
182
- screen.getAllByRole('columnheader').map(header => header.textContent),
183
- ).toEqual(englishNames);
184
- });
185
-
186
- it('rotates localized day names by numeric weekday index', () => {
187
- const localizedNames = standaloneShortWeekdayNamesByLocale.es;
188
-
189
- render(
190
- <InternationalizationProvider locale="es-ES">
191
- <Calendar weekStartsOn={1} />
192
- </InternationalizationProvider>,
193
- );
194
-
195
- expect(
196
- screen.getAllByRole('columnheader').map(header => header.textContent),
197
- ).toEqual([...localizedNames.slice(1), localizedNames[0]]);
198
- });
199
-
200
- it('updates the month header and subsequent navigation with provider locale', async () => {
201
- const user = userEvent.setup();
202
- const renderCalendar = (locale: 'en-US' | 'es-ES') => (
203
- <InternationalizationProvider locale={locale}>
204
- <Calendar focusDate="2026-01-01" />
205
- </InternationalizationProvider>
206
- );
207
- const {rerender} = render(renderCalendar('en-US'));
208
-
209
- expect(screen.getByText('January 2026')).toBeInTheDocument();
210
-
211
- rerender(renderCalendar('es-ES'));
212
- expect(screen.getByText('enero de 2026')).toBeInTheDocument();
213
-
214
- const nextButton =
215
- document.querySelector<HTMLButtonElement>('[data-nav="next"]');
216
- expect(nextButton).not.toBeNull();
217
- await user.click(nextButton!);
218
- expect(screen.getByText('febrero de 2026')).toBeInTheDocument();
219
- });
220
-
221
- it('displays correct number of day cells', () => {
222
- render(<Calendar />);
223
-
224
- // 6 rows * 7 days = 42 cells (default fixed row count)
225
- const buttons = screen.getAllByRole('gridcell');
226
- expect(buttons.length).toBe(42);
227
- });
228
-
229
- // ─── Selection ───────────────────────────────────────────────
230
-
231
- it('highlights selected date', () => {
232
- render(<Calendar value="2026-01-15" focusDate="2026-01-01" />);
233
-
234
- const day15 = getDayButton(15);
235
- // In an ARIA grid, selection state lives on the gridcell, not the button
236
- // (a plain button role does not permit aria-selected).
237
- const gridcell15 = day15.closest('[role="gridcell"]');
238
- expect(gridcell15).toHaveAttribute('aria-selected', 'true');
239
- expect(day15).not.toHaveAttribute('aria-selected');
240
- });
241
-
242
- it('calls onChange when date is selected', async () => {
243
- const user = userEvent.setup();
244
- const handleChange = vi.fn();
245
-
246
- render(<Calendar onChange={handleChange} focusDate="2026-01-01" />);
247
-
248
- const day15 = getDayButton(15);
249
- await user.click(day15);
250
-
251
- expect(handleChange).toHaveBeenCalledTimes(1);
252
- expect(handleChange).toHaveBeenCalledWith('2026-01-15', expect.any(Date));
253
- });
254
-
255
- it('shows years 1-99 as themselves, not as 1900-1999', async () => {
256
- const user = userEvent.setup();
257
- const handleChange = vi.fn();
258
-
259
- render(
260
- <Calendar
261
- value="0001-01-15"
262
- onChange={handleChange}
263
- focusDate="0001-01-01"
264
- />,
265
- );
266
-
267
- expect(screen.getByRole('grid', {name: 'January 1'})).toBeInTheDocument();
268
- const day15 = getDayButton(15, 'January', 1);
269
- expect(day15).toHaveAccessibleName(/^Monday, January 15, 1\b/);
270
- expect(day15.closest('[role="gridcell"]')).toHaveAttribute(
271
- 'aria-selected',
272
- 'true',
273
- );
274
-
275
- await user.click(getDayButton(20, 'January', 1));
276
- expect(handleChange).toHaveBeenCalledWith('0001-01-20', expect.any(Date));
277
- expect(handleChange.mock.calls[0][1].getFullYear()).toBe(1);
278
- });
279
-
280
- it('keeps null single selection empty until the parent accepts a date', async () => {
281
- const user = userEvent.setup();
282
- const onChange = vi.fn();
283
- const calendar = (value: ISODateString | null) => (
284
- <Calendar
285
- value={value}
286
- onChange={onChange}
287
- defaultValue="2026-01-10"
288
- focusDate="2026-01-01"
289
- />
290
- );
291
- const {rerender} = render(calendar(null));
292
- expect(screen.queryAllByRole('gridcell', {selected: true})).toHaveLength(0);
293
-
294
- const day15 = getDayButton(15);
295
- await user.click(day15);
296
- expect(onChange).toHaveBeenCalledWith('2026-01-15', expect.any(Date));
297
- expect(screen.queryAllByRole('gridcell', {selected: true})).toHaveLength(0);
298
-
299
- rerender(calendar('2026-01-15'));
300
- expect(screen.getByRole('gridcell', {selected: true})).toContainElement(
301
- day15,
302
- );
303
-
304
- rerender(calendar(null));
305
- expect(screen.queryAllByRole('gridcell', {selected: true})).toHaveLength(0);
306
- });
307
-
308
- it('keeps null range selection controlled while allowing two-click selection', async () => {
309
- const user = userEvent.setup();
310
- const onChange = vi.fn();
311
- const calendar = (value: DateRange | null) => (
312
- <Calendar
313
- mode="range"
314
- value={value}
315
- onChange={onChange}
316
- defaultValue={{start: '2026-01-10', end: '2026-01-12'}}
317
- focusDate="2026-01-01"
318
- />
319
- );
320
- const {rerender} = render(calendar(null));
321
- expect(screen.queryAllByRole('gridcell', {selected: true})).toHaveLength(0);
322
-
323
- await user.click(getDayButton(15));
324
- await user.click(getDayButton(17));
325
- expect(onChange).toHaveBeenCalledWith({
326
- start: '2026-01-15',
327
- end: '2026-01-17',
328
- });
329
- expect(screen.queryAllByRole('gridcell', {selected: true})).toHaveLength(0);
330
-
331
- rerender(calendar({start: '2026-01-15', end: '2026-01-17'}));
332
- expect(screen.getAllByRole('gridcell', {selected: true})).toHaveLength(3);
333
-
334
- rerender(calendar(null));
335
- expect(screen.queryAllByRole('gridcell', {selected: true})).toHaveLength(0);
336
- });
337
-
338
- // ─── Navigation ──────────────────────────────────────────────
339
-
340
- it('navigates to previous month', async () => {
341
- const user = userEvent.setup();
342
-
343
- render(<Calendar focusDate="2026-02-01" />);
344
-
345
- // Verify we start on February
346
- expect(screen.getByText('February 2026')).toBeInTheDocument();
347
-
348
- const prevButton = getButton('Previous month');
349
- await user.click(prevButton);
350
-
351
- expect(screen.getByText('January 2026')).toBeInTheDocument();
352
- });
353
-
354
- it('navigates to next month', async () => {
355
- const user = userEvent.setup();
356
-
357
- render(<Calendar focusDate="2026-01-01" />);
358
-
359
- // Verify we start on January
360
- expect(screen.getByText('January 2026')).toBeInTheDocument();
361
-
362
- const nextButton = getButton('Next month');
363
- await user.click(nextButton);
364
-
365
- expect(screen.getByText('February 2026')).toBeInTheDocument();
366
- });
367
-
368
- it('calls onFocusDateChange when navigating', async () => {
369
- const user = userEvent.setup();
370
- const handleFocusChange = vi.fn();
371
-
372
- render(
373
- <Calendar focusDate="2026-01-01" onFocusDateChange={handleFocusChange} />,
374
- );
375
-
376
- const nextButton = getButton('Next month');
377
- await user.click(nextButton);
378
-
379
- expect(handleFocusChange).toHaveBeenCalledWith('2026-02-01');
380
- });
381
-
382
- // ─── Date Constraints ────────────────────────────────────────
383
-
384
- it('respects min date constraint', () => {
385
- const onChange = vi.fn();
386
- render(
387
- <Calendar focusDate="2026-01-01" min="2026-01-10" onChange={onChange} />,
388
- );
389
-
390
- // Day 5 should be disabled (before min)
391
- const day5 = getDayButton(5);
392
- expect(day5).toHaveAttribute('aria-disabled', 'true');
393
- // spec:AST-085 FR1: focusable through aria-disabled, not natively disabled;
394
- // a click still selects nothing.
395
- expect(day5).not.toHaveAttribute('disabled');
396
- day5.focus();
397
- expect(day5).toHaveFocus();
398
- day5.click();
399
- expect(onChange).not.toHaveBeenCalled();
400
-
401
- // Day 15 should be enabled (after min)
402
- const day15 = getDayButton(15);
403
- expect(day15).not.toHaveAttribute('aria-disabled', 'true');
404
- });
405
-
406
- it('respects max date constraint', () => {
407
- render(<Calendar focusDate="2026-01-01" max="2026-01-20" />);
408
-
409
- const day25 = getDayButton(25);
410
- expect(day25).toHaveAttribute('aria-disabled', 'true');
411
-
412
- const day15 = getDayButton(15);
413
- expect(day15).not.toHaveAttribute('aria-disabled', 'true');
414
- });
415
-
416
- // ─── Initial Visible Month ───────────────────────────────────
417
-
418
- describe('opens on a month inside the min/max window', () => {
419
- beforeEach(() => {
420
- vi.useFakeTimers({toFake: ['Date']});
421
- vi.setSystemTime(new Date(2026, 7, 21, 12, 0, 0));
422
- });
423
- afterEach(() => {
424
- vi.useRealTimers();
425
- });
426
-
427
- it('opens on today when today is inside the window', () => {
428
- render(<Calendar min="2026-01-01" max="2026-12-31" />);
429
-
430
- expect(screen.getByText('August 2026')).toBeInTheDocument();
431
- });
432
-
433
- it('opens on min when the window is entirely in the future', () => {
434
- render(<Calendar min="2027-03-04" max="2027-06-30" />);
435
-
436
- expect(screen.getByText('March 2027')).toBeInTheDocument();
437
- expect(getDayButton(4, 'March', 2027)).not.toHaveAttribute(
438
- 'aria-disabled',
439
- 'true',
440
- );
441
- });
442
-
443
- it('opens on max when the window is entirely in the past', () => {
444
- render(<Calendar min="2019-01-01" max="2019-04-30" />);
445
-
446
- expect(screen.getByText('April 2019')).toBeInTheDocument();
447
- expect(getDayButton(30, 'April', 2019)).not.toHaveAttribute(
448
- 'aria-disabled',
449
- 'true',
450
- );
451
- });
452
-
453
- it('keeps max in the last pane in the two-month layout', () => {
454
- render(<Calendar numberOfMonths={2} min="2019-01-01" max="2019-04-30" />);
455
-
456
- expect(screen.getByText('March 2019 – April 2019')).toBeInTheDocument();
457
- });
458
-
459
- it('still honors an explicit focusDate outside the window', () => {
460
- render(
461
- <Calendar focusDate="2026-01-01" min="2027-03-04" max="2027-06-30" />,
462
- );
463
-
464
- expect(screen.getByText('January 2026')).toBeInTheDocument();
465
- });
466
-
467
- it('still opens on the selected value outside the window', () => {
468
- render(<Calendar defaultValue="2031-07-04" min="2019-01-01" />);
469
-
470
- expect(screen.getByText('July 2031')).toBeInTheDocument();
471
- });
472
- });
473
-
474
- it('respects custom dateConstraints', () => {
475
- // Only allow weekdays
476
- const isWeekday = (date: Date) => {
477
- const day = date.getDay();
478
- return day !== 0 && day !== 6;
479
- };
480
-
481
- render(<Calendar focusDate="2026-01-01" dateConstraints={[isWeekday]} />);
482
-
483
- // January 4, 2026 is a Sunday - should be disabled
484
- const sunday = getDayButton(4);
485
- expect(sunday).toHaveAttribute('aria-disabled', 'true');
486
- });
487
-
488
- it('caps the end date to maxRangeSpan once a start is picked', async () => {
489
- const user = userEvent.setup();
490
-
491
- render(<Calendar mode="range" focusDate="2026-01-01" maxRangeSpan={7} />);
492
-
493
- // Before a start is picked every day is selectable.
494
- expect(getDayButton(20)).not.toHaveAttribute('aria-disabled', 'true');
495
-
496
- // Pick Jan 10 as the start. A 7-day window spans Jan 4–16 (start ± 6).
497
- await user.click(getDayButton(10));
498
-
499
- expect(getDayButton(16)).not.toHaveAttribute('aria-disabled', 'true'); // 6 days after — the edge
500
- expect(getDayButton(17)).toHaveAttribute('aria-disabled', 'true'); // 7 days after — beyond the cap
501
- expect(getDayButton(4)).not.toHaveAttribute('aria-disabled', 'true'); // 6 days before — symmetric
502
- expect(getDayButton(3)).toHaveAttribute('aria-disabled', 'true'); // 7 days before — beyond the cap
503
- });
504
-
505
- it('keeps one Tab stop when the span cap disables the day that held it', async () => {
506
- const user = userEvent.setup();
507
-
508
- render(<Calendar mode="range" focusDate="2026-01-01" maxRangeSpan={7} />);
509
-
510
- // Arrow from Jan 1 to Jan 25 so Jan 25 holds the grid's Tab stop.
511
- getDayButton(1).focus();
512
- await user.keyboard('{ArrowDown}{ArrowDown}{ArrowDown}');
513
- for (let i = 0; i < 3; i += 1) {
514
- await user.keyboard('{ArrowRight}');
515
- }
516
- expect(getDayButton(25)).toHaveFocus();
517
-
518
- // Picking Jan 10 as the start disables Jan 25 (beyond the 7-day cap).
519
- await user.click(getDayButton(10));
520
- expect(getDayButton(25)).toHaveAttribute('aria-disabled', 'true');
521
-
522
- // spec:AST-085 FR1: a disabled day stays focusable but never keeps the
523
- // grid's Tab stop, so the grid still has exactly one, on an enabled day.
524
- const grid = screen.getByRole('grid');
525
- const stops = Array.from(
526
- grid.querySelectorAll<HTMLElement>('button[data-date][tabindex="0"]'),
527
- );
528
- expect(stops).toHaveLength(1);
529
- expect(stops[0]).not.toHaveAttribute('aria-disabled', 'true');
530
- expect(getDayButton(25)).toHaveAttribute('tabindex', '-1');
531
- });
532
-
533
- it('enforces minRangeSpan once a start is picked', async () => {
534
- const user = userEvent.setup();
535
-
536
- render(<Calendar mode="range" focusDate="2026-01-01" minRangeSpan={3} />);
537
-
538
- // Pick Jan 10. A 3-day minimum forbids ends closer than 2 days away.
539
- await user.click(getDayButton(10));
540
-
541
- // The picked start itself stays enabled — it is the active selection
542
- // anchor, not an unreachable end.
543
- expect(getDayButton(10)).not.toHaveAttribute('aria-disabled', 'true');
544
- expect(getDayButton(11)).toHaveAttribute('aria-disabled', 'true'); // 1 day apart — too short
545
- expect(getDayButton(12)).not.toHaveAttribute('aria-disabled', 'true'); // 3-day span — allowed
546
- expect(getDayButton(8)).not.toHaveAttribute('aria-disabled', 'true'); // 3-day span the other way
547
- expect(getDayButton(9)).toHaveAttribute('aria-disabled', 'true'); // 2-day span — too short
548
- });
549
-
550
- it('commits a same-day range with the default minimum', async () => {
551
- const user = userEvent.setup();
552
- const handleChange = vi.fn();
553
-
554
- render(
555
- <Calendar mode="range" focusDate="2026-01-01" onChange={handleChange} />,
556
- );
557
-
558
- await user.click(getDayButton(10));
559
- await user.click(getDayButton(10));
560
-
561
- expect(handleChange).toHaveBeenCalledWith({
562
- start: '2026-01-10',
563
- end: '2026-01-10',
564
- });
565
- });
566
-
567
- it('commits a same-day range when the minimum permits it, including with a maximum', async () => {
568
- const user = userEvent.setup();
569
- const handleChange = vi.fn();
570
-
571
- render(
572
- <Calendar
573
- mode="range"
574
- focusDate="2026-01-01"
575
- onChange={handleChange}
576
- minRangeSpan={1}
577
- maxRangeSpan={7}
578
- />,
579
- );
580
-
581
- await user.click(getDayButton(10));
582
- await user.click(getDayButton(10));
583
-
584
- expect(handleChange).toHaveBeenCalledWith({
585
- start: '2026-01-10',
586
- end: '2026-01-10',
587
- });
588
- });
589
-
590
- it('clears the in-progress start when the anchor is clicked again', async () => {
591
- const user = userEvent.setup();
592
- const handleChange = vi.fn();
593
-
594
- render(
595
- <Calendar
596
- mode="range"
597
- focusDate="2026-01-01"
598
- onChange={handleChange}
599
- minRangeSpan={3}
600
- />,
601
- );
602
-
603
- // Pick Jan 10 as the start, then click it again.
604
- await user.click(getDayButton(10));
605
- await user.click(getDayButton(10));
606
-
607
- // No zero-length range is committed…
608
- expect(handleChange).not.toHaveBeenCalled();
609
-
610
- // …and the start is cleared: the days that minRangeSpan disabled around
611
- // the old anchor are selectable again, so a new start can be placed there.
612
- expect(getDayButton(11)).not.toHaveAttribute('aria-disabled', 'true');
613
- expect(getDayButton(9)).not.toHaveAttribute('aria-disabled', 'true');
614
- });
615
-
616
- it('announces the cleared range in the provider locale', async () => {
617
- const user = userEvent.setup();
618
-
619
- render(
620
- <InternationalizationProvider locale="ja-JP">
621
- <Calendar mode="range" focusDate="2026-01-01" />
622
- </InternationalizationProvider>,
623
- );
624
-
625
- // The day button's own accessible name is already localized through the
626
- // provider. The announcement has to use the same date string: formatting
627
- // it without the locale silently falls back to the host locale, so a
628
- // Japanese user hears an English date.
629
- const anchor = document.querySelector<HTMLButtonElement>(
630
- 'button[data-date="2026-01-10"]',
631
- );
632
- const localizedDate = anchor?.getAttribute('aria-label');
633
- expect(localizedDate).toBeTruthy();
634
-
635
- await user.click(anchor as HTMLButtonElement);
636
- await user.click(anchor as HTMLButtonElement);
637
-
638
- await waitFor(() => {
639
- expect(politeRegion()?.textContent).toContain(localizedDate);
640
- });
641
- });
642
-
643
- it('does not apply range-span constraints in single mode', async () => {
644
- const user = userEvent.setup();
645
-
646
- render(<Calendar focusDate="2026-01-01" maxRangeSpan={7} />);
647
-
648
- // A picked single date must not disable far-away days.
649
- await user.click(getDayButton(10));
650
- expect(getDayButton(25)).not.toHaveAttribute('aria-disabled', 'true');
651
- });
652
-
653
- it('keeps a controlled value that is wider than maxRangeSpan (selection-only)', () => {
654
- // The span constraint governs which days are pickable, not validation of
655
- // an already-set value — so a 15-day value under a 7-day cap stays
656
- // rendered and is never silently rewritten.
657
- render(
658
- <Calendar
659
- mode="range"
660
- value={{start: '2026-01-05', end: '2026-01-20'}}
661
- focusDate="2026-01-01"
662
- maxRangeSpan={7}
663
- />,
664
- );
665
-
666
- // No selection is in progress (both endpoints are set), so no anchor →
667
- // every day is pickable and both endpoints render selected.
668
- expect(getDayButton(20)).not.toHaveAttribute('aria-disabled', 'true');
669
- expect(getDayButton(5).closest('[role="gridcell"]')).toHaveAttribute(
670
- 'aria-selected',
671
- 'true',
672
- );
673
- expect(getDayButton(20).closest('[role="gridcell"]')).toHaveAttribute(
674
- 'aria-selected',
675
- 'true',
676
- );
677
- });
678
-
679
- // ─── Multi-Month ─────────────────────────────────────────────
680
-
681
- it('renders two months when numberOfMonths={2}', () => {
682
- render(<Calendar numberOfMonths={2} focusDate="2026-01-01" />);
683
-
684
- // The header shows both months
685
- expect(screen.getByText(/January 2026.*February 2026/)).toBeInTheDocument();
686
- });
687
-
688
- it('navigation advances both months together', async () => {
689
- const user = userEvent.setup();
690
-
691
- render(<Calendar numberOfMonths={2} focusDate="2026-01-01" />);
692
-
693
- const nextButton = getButton('Next month');
694
- await user.click(nextButton);
695
-
696
- expect(screen.getByText(/February 2026.*March 2026/)).toBeInTheDocument();
697
- });
698
-
699
- it('clamps out-of-range numberOfMonths to a single month', () => {
700
- // 1000 would otherwise try to render 1000 month grids and lock the page up.
701
- render(
702
- <Calendar
703
- numberOfMonths={1000 as unknown as 1 | 2}
704
- focusDate="2026-01-01"
705
- />,
706
- );
707
-
708
- // Only the focused month renders — no second month, no range separator.
709
- expect(screen.getByText('January 2026')).toBeInTheDocument();
710
- expect(screen.queryByText(/February 2026/)).not.toBeInTheDocument();
711
- });
712
-
713
- it('clamps numberOfMonths={0} to a single month', () => {
714
- render(
715
- <Calendar
716
- numberOfMonths={0 as unknown as 1 | 2}
717
- focusDate="2026-01-01"
718
- />,
719
- );
720
-
721
- // 0 previously rendered no months at all; now falls back to one.
722
- expect(screen.getByText('January 2026')).toBeInTheDocument();
723
- expect(screen.getAllByRole('gridcell').length).toBeGreaterThan(0);
724
- });
725
-
726
- // ─── Display Options ─────────────────────────────────────────
727
-
728
- it('shows week numbers when hasWeekNumbers is true', () => {
729
- render(<Calendar hasWeekNumbers focusDate="2026-01-01" />);
730
-
731
- // Look for week number cells - they should be in the grid but not buttons
732
- // Week numbers for January 2026 include week 1, 2, 3, 4, 5
733
- const weekNumberCells = screen.getAllByText(/^[1-5]$/);
734
- // Should have more than just day numbers (week numbers add extra cells)
735
- expect(weekNumberCells.length).toBeGreaterThan(5);
736
- });
737
-
738
- it('respects weekStartsOn option', () => {
739
- render(<Calendar weekStartsOn={1} />);
740
-
741
- // First day name should be Monday
742
- const dayNames = screen.getAllByText(/^(Mo|Tu|We|Th|Fr|Sa|Su)$/);
743
- expect(dayNames[0]).toHaveTextContent('Mo');
744
- });
745
-
746
- it('accepts a three-letter day name for weekStartsOn', () => {
747
- render(<Calendar weekStartsOn="mon" />);
748
-
749
- // "mon" should behave exactly like the numeric 1 (Monday first).
750
- const dayNames = screen.getAllByText(/^(Mo|Tu|We|Th|Fr|Sa|Su)$/);
751
- expect(dayNames[0]).toHaveTextContent('Mo');
752
- });
753
-
754
- it('treats weekStartsOn day names case-insensitively', () => {
755
- render(<Calendar weekStartsOn={'WED' as 'wed'} />);
756
-
757
- const dayNames = screen.getAllByText(/^(Mo|Tu|We|Th|Fr|Sa|Su)$/);
758
- expect(dayNames[0]).toHaveTextContent('We');
759
- });
760
-
761
- // ─── Range Mode ──────────────────────────────────────────────
762
-
763
- it('supports range selection mode', async () => {
764
- const user = userEvent.setup();
765
- const handleChange = vi.fn();
766
-
767
- render(
768
- <Calendar mode="range" onChange={handleChange} focusDate="2026-01-01" />,
769
- );
770
-
771
- // Click start date
772
- const day10 = getDayButton(10);
773
- await user.click(day10);
774
-
775
- // Click end date
776
- const day15 = getDayButton(15);
777
- await user.click(day15);
778
-
779
- expect(handleChange).toHaveBeenCalledWith({
780
- start: '2026-01-10',
781
- end: '2026-01-15',
782
- });
783
- });
784
-
785
- it('handles reverse range selection (end before start)', async () => {
786
- const user = userEvent.setup();
787
- const handleChange = vi.fn();
788
-
789
- render(
790
- <Calendar mode="range" onChange={handleChange} focusDate="2026-01-01" />,
791
- );
792
-
793
- // Click later date first
794
- const day20 = getDayButton(20);
795
- await user.click(day20);
796
-
797
- // Click earlier date
798
- const day10 = getDayButton(10);
799
- await user.click(day10);
800
-
801
- // Should swap to ensure start <= end
802
- expect(handleChange).toHaveBeenCalledWith({
803
- start: '2026-01-10',
804
- end: '2026-01-20',
805
- });
806
- });
807
-
808
- it('highlights range when value is provided', () => {
809
- render(
810
- <Calendar
811
- mode="range"
812
- value={{start: '2026-01-10', end: '2026-01-15'}}
813
- focusDate="2026-01-01"
814
- />,
815
- );
816
-
817
- const day10 = getDayButton(10);
818
- const day12 = getDayButton(12);
819
- const day15 = getDayButton(15);
820
-
821
- // Selection state lives on the gridcell wrapper, not the day button.
822
- expect(day10.closest('[role="gridcell"]')).toHaveAttribute(
823
- 'aria-selected',
824
- 'true',
825
- );
826
- expect(day12.closest('[role="gridcell"]')).toHaveAttribute(
827
- 'aria-selected',
828
- 'true',
829
- );
830
- expect(day15.closest('[role="gridcell"]')).toHaveAttribute(
831
- 'aria-selected',
832
- 'true',
833
- );
834
- expect(day10).not.toHaveAttribute('aria-selected');
835
- expect(day12).not.toHaveAttribute('aria-selected');
836
- expect(day15).not.toHaveAttribute('aria-selected');
837
- });
838
-
839
- it('caps the range highlight next to a disabled mid-range day (#2715)', () => {
840
- // Disable Jan 13. With Jan 10–15 selected, day 12 (immediately before the
841
- // disabled day) should get a rounded end cap on its inline-end edge, and
842
- // day 14 (immediately after) a rounded cap on its inline-start edge — so
843
- // the highlight reads as terminating at the disabled gap rather than
844
- // running square-edged into it.
845
- const disableJan13 = (d: Date) =>
846
- !(d.getFullYear() === 2026 && d.getMonth() === 0 && d.getDate() === 13);
847
- render(
848
- <Calendar
849
- mode="range"
850
- value={{start: '2026-01-10', end: '2026-01-15'}}
851
- focusDate="2026-01-01"
852
- dateConstraints={[disableJan13]}
853
- />,
854
- );
855
-
856
- // The range background is an absolutely-positioned sibling div inside the
857
- // same gridcell as the day button.
858
- const rangeBgFor = (day: number): HTMLElement => {
859
- const button = getDayButton(day);
860
- const cell = button.closest('[role="gridcell"]') as HTMLElement;
861
- // First child div is the range background (rendered before the button).
862
- return cell.firstElementChild as HTMLElement;
863
- };
864
-
865
- const day12Bg = rangeBgFor(12);
866
- const day14Bg = rangeBgFor(14);
867
-
868
- // Capped edges have a border radius; the un-capped edge stays square.
869
- // Radii are logical (inline start/end), so they follow reading direction.
870
- expect(getComputedStyle(day12Bg).borderStartEndRadius).not.toBe('');
871
- expect(getComputedStyle(day12Bg).borderStartEndRadius).not.toBe('0px');
872
- expect(getComputedStyle(day14Bg).borderStartStartRadius).not.toBe('');
873
- expect(getComputedStyle(day14Bg).borderStartStartRadius).not.toBe('0px');
874
- });
875
-
876
- it('does not range-highlight adjacent-month spillover days in two-month view', () => {
877
- // #2715: with July 1–31 selected and July+August visible, July 26–31 also
878
- // render as outside days in the August pane. Those spillover copies must
879
- // not carry the range-highlight state (data-in-range) even though their
880
- // dates fall inside the selected range.
881
- render(
882
- <Calendar
883
- mode="range"
884
- numberOfMonths={2}
885
- focusDate="2026-07-01"
886
- value={{start: '2026-07-01', end: '2026-07-31'}}
887
- />,
888
- );
889
-
890
- const spillover = [
891
- '2026-07-26',
892
- '2026-07-27',
893
- '2026-07-28',
894
- '2026-07-29',
895
- '2026-07-30',
896
- '2026-07-31',
897
- ];
898
-
899
- const allDayButtons = Array.from(
900
- document.querySelectorAll<HTMLButtonElement>('button[data-date]'),
901
- );
902
-
903
- for (const iso of spillover) {
904
- const matches = allDayButtons.filter(
905
- b => b.getAttribute('data-date') === iso,
906
- );
907
- // Renders once in the July pane and once as a spillover in August.
908
- expect(matches.length).toBeGreaterThanOrEqual(2);
909
- const outsideCopies = matches.filter(
910
- b => b.getAttribute('aria-disabled') === 'true',
911
- );
912
- expect(outsideCopies.length).toBeGreaterThanOrEqual(1);
913
- for (const b of outsideCopies) {
914
- expect(b).not.toHaveAttribute('data-in-range');
915
- }
916
- }
917
- });
918
-
919
- // ─── Accessibility ───────────────────────────────────────────
920
-
921
- it('has accessible grid structure', () => {
922
- render(<Calendar focusDate="2026-01-01" />);
923
-
924
- expect(screen.getByRole('grid')).toBeInTheDocument();
925
- expect(screen.getAllByRole('row').length).toBeGreaterThan(0);
926
- expect(screen.getAllByRole('gridcell').length).toBeGreaterThan(0);
927
- });
928
-
929
- it('renders a valid APG grid: one grid, header row of columnheaders inside it, week rows of gridcells', () => {
930
- render(<Calendar focusDate="2026-01-01" />);
931
-
932
- const grids = screen.getAllByRole('grid');
933
- expect(grids.length).toBe(1);
934
- const grid = grids[0];
935
-
936
- // The columnheaders live INSIDE the grid.
937
- const columnHeaders = screen.getAllByRole('columnheader');
938
- expect(columnHeaders.length).toBe(7);
939
- for (const header of columnHeaders) {
940
- expect(grid.contains(header)).toBe(true);
941
- }
942
-
943
- // The grid's rows: first is the header row of columnheaders, the rest are
944
- // week rows whose direct children are gridcells.
945
- const rows = within(grid).getAllByRole('row');
946
- // 1 header row + 6 week rows (fixed 6-row grid).
947
- expect(rows.length).toBe(7);
948
-
949
- const [headerRow, ...weekRows] = rows;
950
-
951
- // Header row's direct children are the 7 columnheaders.
952
- const headerChildren = Array.from(headerRow.children);
953
- const headerColHeaders = headerChildren.filter(
954
- child => child.getAttribute('role') === 'columnheader',
955
- );
956
- expect(headerColHeaders.length).toBe(7);
957
-
958
- // Each week row's direct children are gridcells (7 per row).
959
- for (const row of weekRows) {
960
- const gridcellChildren = Array.from(row.children).filter(
961
- child => child.getAttribute('role') === 'gridcell',
962
- );
963
- expect(gridcellChildren.length).toBe(7);
964
- }
965
- });
966
-
967
- it('renders week-number cells as rowheader when hasWeekNumbers is set', () => {
968
- render(<Calendar hasWeekNumbers focusDate="2026-01-01" />);
969
-
970
- const grid = screen.getByRole('grid');
971
- const rowHeaders = within(grid).getAllByRole('rowheader');
972
- // One rowheader (week number) per week row.
973
- expect(rowHeaders.length).toBeGreaterThanOrEqual(5);
974
- // Week numbers are numeric.
975
- for (const header of rowHeaders) {
976
- expect(header.textContent).toMatch(/^\d+$/);
977
- }
978
- });
979
-
980
- it('gridcell wrappers are direct children of week rows, and the button is inside the gridcell', () => {
981
- render(<Calendar focusDate="2026-01-01" />);
982
-
983
- const grid = screen.getByRole('grid');
984
- const gridcells = within(grid).getAllByRole('gridcell');
985
- for (const cell of gridcells) {
986
- // The gridcell's parent is a role="row".
987
- const parent = cell.parentElement;
988
- expect(parent?.getAttribute('role')).toBe('row');
989
- // The day button (if present) is a descendant of the gridcell.
990
- const button = cell.querySelector('button');
991
- if (button) {
992
- expect(cell.contains(button)).toBe(true);
993
- expect(button).not.toHaveAttribute('role', 'gridcell');
994
- }
995
- }
996
- });
997
-
998
- it('has navigation buttons with accessible labels', () => {
999
- render(<Calendar />);
1000
-
1001
- expect(getButton('Previous month')).toBeInTheDocument();
1002
- expect(getButton('Next month')).toBeInTheDocument();
1003
- });
1004
-
1005
- // ─── Month Change Announcements ──────────────────────────────
1006
-
1007
- describe('month change announcements', () => {
1008
- it('does not announce on initial render', () => {
1009
- render(<Calendar focusDate="2026-01-01" />);
1010
- // The live region is only created lazily on first announce; mounting the
1011
- // calendar must not speak the initial month.
1012
- expect(politeRegion()).toBeNull();
1013
- });
1014
-
1015
- it('announces the new month politely when clicking next', async () => {
1016
- const user = userEvent.setup();
1017
- render(<Calendar focusDate="2026-01-01" />);
1018
-
1019
- await user.click(screen.getByRole('button', {name: 'Next month'}));
1020
-
1021
- await waitFor(() => {
1022
- expect(politeRegion()).toHaveTextContent('February 2026');
1023
- });
1024
- });
1025
-
1026
- it('announces the new month politely when clicking previous', async () => {
1027
- const user = userEvent.setup();
1028
- render(<Calendar focusDate="2026-02-01" />);
1029
-
1030
- await user.click(screen.getByRole('button', {name: 'Previous month'}));
1031
-
1032
- await waitFor(() => {
1033
- expect(politeRegion()).toHaveTextContent('January 2026');
1034
- });
1035
- });
1036
-
1037
- it('moves the focused day by a month with PageDown and PageUp, into the month now shown', async () => {
1038
- const user = userEvent.setup();
1039
- render(<Calendar focusDate="2026-01-31" />);
1040
-
1041
- getDayButton(31).focus();
1042
- await user.keyboard('{PageDown}');
1043
- await waitFor(() => {
1044
- expect(politeRegion()).toHaveTextContent('February 2026');
1045
- });
1046
- // A month, not a week: Jan 31 lands on the last day of February.
1047
- await waitFor(() => {
1048
- expect(document.activeElement).toHaveAttribute(
1049
- 'aria-label',
1050
- expect.stringMatching(/February 28, 2026/),
1051
- );
1052
- });
1053
-
1054
- await user.keyboard('{PageUp}');
1055
- await waitFor(() => {
1056
- expect(politeRegion()).toHaveTextContent('January 2026');
1057
- });
1058
- await waitFor(() => {
1059
- expect(document.activeElement).toHaveAttribute(
1060
- 'aria-label',
1061
- expect.stringMatching(/January 28, 2026/),
1062
- );
1063
- });
1064
- });
1065
-
1066
- it("pages from the first of two months onto the right day, not the second grid's fallback", async () => {
1067
- const user = userEvent.setup();
1068
- render(<Calendar focusDate="2026-01-01" numberOfMonths={2} />);
1069
-
1070
- getDayButton(15).focus();
1071
- await user.keyboard('{PageDown}');
1072
- await waitFor(() => {
1073
- expect(document.activeElement).toHaveAttribute(
1074
- 'aria-label',
1075
- expect.stringMatching(/February 15, 2026/),
1076
- );
1077
- });
1078
- expect(document.activeElement).not.toHaveAttribute('aria-disabled');
1079
-
1080
- await user.keyboard('{PageUp}');
1081
- await waitFor(() => {
1082
- expect(document.activeElement).toHaveAttribute(
1083
- 'aria-label',
1084
- expect.stringMatching(/January 15, 2026/),
1085
- );
1086
- });
1087
- expect(document.activeElement).not.toHaveAttribute('aria-disabled');
1088
- });
1089
-
1090
- it('skips borrowed adjacent-month days and crosses into their month instead', async () => {
1091
- const user = userEvent.setup();
1092
- render(<Calendar focusDate="2026-01-01" />);
1093
-
1094
- // January 1, 2026 is a Thursday: the first row borrows December 28–31.
1095
- getDayButton(1).focus();
1096
- await user.keyboard('{ArrowLeft}');
1097
- await waitFor(() => {
1098
- expect(politeRegion()).toHaveTextContent('December 2025');
1099
- });
1100
- await waitFor(() => {
1101
- expect(document.activeElement).toHaveAttribute(
1102
- 'data-date',
1103
- '2025-12-31',
1104
- );
1105
- });
1106
- expect(document.activeElement).not.toHaveAttribute('aria-disabled');
1107
- });
1108
-
1109
- it('in a two-month view an arrow from the first month lands on the real day, never a borrowed one', async () => {
1110
- const user = userEvent.setup();
1111
- render(<Calendar focusDate="2026-01-01" numberOfMonths={2} />);
1112
-
1113
- // January 28 (Wednesday) → ArrowDown → February 4, shown in the second
1114
- // grid: no page, and never the first day of a new month.
1115
- getDayButton(28).focus();
1116
- await user.keyboard('{ArrowDown}');
1117
- await waitFor(() => {
1118
- expect(document.activeElement).toHaveAttribute(
1119
- 'data-date',
1120
- '2026-02-04',
1121
- );
1122
- });
1123
- expect(document.activeElement).not.toHaveAttribute('aria-disabled');
1124
- // No page happened: January is still the first grid.
1125
- expect(screen.getAllByRole('grid')).toHaveLength(2);
1126
- expect(getDayButton(28)).toBeInTheDocument();
1127
-
1128
- // February 24 (Tuesday) → ArrowDown → March 3: the view pages so March
1129
- // is the second month, and focus lands on the real March 3.
1130
- getDayButton(24, 'February').focus();
1131
- await user.keyboard('{ArrowDown}');
1132
- await waitFor(() => {
1133
- expect(document.activeElement).toHaveAttribute(
1134
- 'data-date',
1135
- '2026-03-03',
1136
- );
1137
- });
1138
- expect(document.activeElement).not.toHaveAttribute('aria-disabled');
1139
- });
1140
-
1141
- it('pages from a borrowed adjacent-month day onto the real day in the month already shown', async () => {
1142
- const user = userEvent.setup();
1143
- render(<Calendar focusDate="2026-01-01" />);
1144
-
1145
- // A pointer can still land on the borrowed December 28 in the first
1146
- // row (the keyboard skips it).
1147
- const borrowed = document.querySelector<HTMLElement>(
1148
- 'button[data-date="2025-12-28"]',
1149
- )!;
1150
- borrowed.focus();
1151
- expect(document.activeElement).toBe(borrowed);
1152
-
1153
- // PageDown targets January 28, which January's grid already shows: no
1154
- // month change, focus moves there and never to a borrowed copy.
1155
- await user.keyboard('{PageDown}');
1156
- await waitFor(() => {
1157
- expect(document.activeElement).toHaveAttribute(
1158
- 'data-date',
1159
- '2026-01-28',
1160
- );
1161
- });
1162
- expect(screen.getByRole('grid')).toHaveAttribute(
1163
- 'aria-label',
1164
- 'January 2026',
1165
- );
1166
- expect(document.activeElement).not.toHaveAttribute('aria-disabled');
1167
- });
1168
-
1169
- it('an arrow past max changes nothing and leaves no pending target behind', async () => {
1170
- const user = userEvent.setup();
1171
- const {rerender} = render(
1172
- <Calendar focusDate="2026-01-01" max="2026-01-31" />,
1173
- );
1174
- const last = getDayButton(31);
1175
- last.focus();
1176
- await user.keyboard('{ArrowRight}');
1177
- // January stays, focus stays on the max day.
1178
- expect(screen.getByRole('button', {name: 'Next month'})).toBeDisabled();
1179
- expect(document.activeElement).toBe(getDayButton(31));
1180
-
1181
- // Later the range widens and the user clicks Next: no stale target
1182
- // pulls focus into the grid.
1183
- rerender(<Calendar focusDate="2026-01-01" max="2026-02-28" />);
1184
- const next = screen.getByRole('button', {name: 'Next month'});
1185
- await user.click(next);
1186
- await waitFor(() => {
1187
- expect(politeRegion()).toHaveTextContent('February 2026');
1188
- });
1189
- expect(document.activeElement).toBe(next);
1190
- });
1191
-
1192
- it('a page into a month with no enabled day changes nothing and keeps focus', async () => {
1193
- const user = userEvent.setup();
1194
- // Only January 1–15 is enabled: February has no enabled day at all.
1195
- const earlyJanuaryOnly = (date: Date) =>
1196
- date.getFullYear() === 2026 &&
1197
- date.getMonth() === 0 &&
1198
- date.getDate() <= 15;
1199
- render(
1200
- <Calendar
1201
- focusDate="2026-01-01"
1202
- dateConstraints={[earlyJanuaryOnly]}
1203
- />,
1204
- );
1205
- getDayButton(10).focus();
1206
- await user.keyboard('{PageDown}');
1207
- expect(screen.getByRole('grid')).toHaveAttribute(
1208
- 'aria-label',
1209
- 'January 2026',
1210
- );
1211
- expect(document.activeElement).toBe(getDayButton(10));
1212
- });
1213
-
1214
- it('a page onto a day disabled by a constraint moves the month and focuses its first enabled day', async () => {
1215
- const user = userEvent.setup();
1216
- // February 1–14 disabled; February 15 onwards enabled.
1217
- const noEarlyFebruary = (date: Date) =>
1218
- !(date.getMonth() === 1 && date.getDate() < 15);
1219
- render(
1220
- <Calendar focusDate="2026-01-01" dateConstraints={[noEarlyFebruary]} />,
1221
- );
1222
- getDayButton(10).focus();
1223
- await user.keyboard('{PageDown}');
1224
- await waitFor(() => {
1225
- expect(document.activeElement).toHaveAttribute(
1226
- 'data-date',
1227
- '2026-02-15',
1228
- );
1229
- });
1230
- expect(screen.getByRole('grid')).toHaveAttribute(
1231
- 'aria-label',
1232
- 'February 2026',
1233
- );
1234
- });
1235
-
1236
- it('in a two-month view PageDown from the second month moves both months and a later Next click selects no stale day', async () => {
1237
- const user = userEvent.setup();
1238
- const onChange = vi.fn();
1239
- render(
1240
- <Calendar
1241
- focusDate="2026-01-01"
1242
- numberOfMonths={2}
1243
- onChange={onChange}
1244
- />,
1245
- );
1246
- getDayButton(10, 'February').focus();
1247
- await user.keyboard('{PageDown}');
1248
- // March 10 is in no shown grid, so the months move (Feb + Mar) and
1249
- // focus lands on March 10.
1250
- await waitFor(() => {
1251
- expect(document.activeElement).toHaveAttribute(
1252
- 'data-date',
1253
- '2026-03-10',
1254
- );
1255
- });
1256
- expect(
1257
- screen.getAllByRole('grid').map(g => g.getAttribute('aria-label')),
1258
- ).toEqual(['February 2026', 'March 2026']);
1259
- // A later Next click pages again without selecting anything.
1260
- await user.click(getButton('Next month'));
1261
- await waitFor(() => {
1262
- expect(
1263
- screen.getAllByRole('grid').map(g => g.getAttribute('aria-label')),
1264
- ).toEqual(['March 2026', 'April 2026']);
1265
- });
1266
- expect(onChange).not.toHaveBeenCalled();
1267
- });
1268
-
1269
- it('an arrow toward a direction where every remaining day is disabled changes nothing', async () => {
1270
- const user = userEvent.setup();
1271
- // Only January 2026 is enabled: nothing after January 31 can take focus
1272
- // (the walk looks a year ahead, so the constraint pins the year too).
1273
- const januaryOnly = (date: Date) =>
1274
- date.getFullYear() === 2026 && date.getMonth() === 0;
1275
- render(
1276
- <Calendar focusDate="2026-01-01" dateConstraints={[januaryOnly]} />,
1277
- );
1278
- getDayButton(28).focus();
1279
- await user.keyboard('{ArrowDown}');
1280
- // No month change, no focus drop: still January 28.
1281
- expect(screen.getByRole('grid')).toHaveAttribute(
1282
- 'aria-label',
1283
- 'January 2026',
1284
- );
1285
- expect(document.activeElement).toBe(getDayButton(28));
1286
- });
1287
-
1288
- it('an arrow resolves the next enabled day in its direction first: weekdays-only ArrowRight from Friday January 30 reaches Monday February 2', async () => {
1289
- const user = userEvent.setup();
1290
- const weekdaysOnly = (date: Date) =>
1291
- date.getDay() !== 0 && date.getDay() !== 6;
1292
- render(
1293
- <Calendar focusDate="2026-01-01" dateConstraints={[weekdaysOnly]} />,
1294
- );
1295
- getDayButton(30).focus();
1296
- await user.keyboard('{ArrowRight}');
1297
- await waitFor(() => {
1298
- expect(document.activeElement).toHaveAttribute(
1299
- 'data-date',
1300
- '2026-02-02',
1301
- );
1302
- });
1303
- // The month paged with it: February's grid is the one shown.
1304
- expect(screen.getByRole('grid')).toHaveAttribute(
1305
- 'aria-label',
1306
- 'February 2026',
1307
- );
1308
- });
1309
-
1310
- it('an arrow whose next day in range does not exist changes nothing: max January 25, ArrowDown from January 21', async () => {
1311
- const user = userEvent.setup();
1312
- render(<Calendar focusDate="2026-01-01" max="2026-01-25" />);
1313
- getDayButton(21).focus();
1314
- await user.keyboard('{ArrowDown}');
1315
- expect(politeRegion()?.textContent ?? '').not.toContain('February 2026');
1316
- expect(document.activeElement).toBe(getDayButton(21));
1317
- });
1318
-
1319
- it('a controlled owner that refuses the month change leaves no stale target to steal focus or Enter later', async () => {
1320
- const user = userEvent.setup();
1321
- const onChange = vi.fn();
1322
- function RefusingOwner() {
1323
- const [focusDate, setFocusDate] = useState<ISODateString>('2026-01-01');
1324
- const [allow, setAllow] = useState(false);
1325
- return (
1326
- <>
1327
- <button type="button" onClick={() => setAllow(true)}>
1328
- allow
1329
- </button>
1330
- <Calendar
1331
- focusDate={focusDate}
1332
- onFocusDateChange={next => {
1333
- if (allow) {
1334
- setFocusDate(next);
1335
- }
1336
- }}
1337
- onChange={onChange}
1338
- />
1339
- </>
1340
- );
1341
- }
1342
- render(<RefusingOwner />);
1343
- getDayButton(15).focus();
1344
- // PageDown asks for February; the owner refuses, so January stays and
1345
- // focus does not move.
1346
- await user.keyboard('{PageDown}');
1347
- expect(screen.getByRole('grid')).toHaveAttribute(
1348
- 'aria-label',
1349
- 'January 2026',
1350
- );
1351
- expect(document.activeElement).toBe(getDayButton(15));
1352
- // Later the owner lets February show (through the Next button): the
1353
- // old February 15 target must not grab focus, and Enter on whatever is
1354
- // focused must not pick it.
1355
- await user.click(screen.getByRole('button', {name: 'allow'}));
1356
- await user.click(getButton('Next month'));
1357
- await waitFor(() => {
1358
- expect(screen.getByRole('grid')).toHaveAttribute(
1359
- 'aria-label',
1360
- 'February 2026',
1361
- );
1362
- });
1363
- expect(document.activeElement).not.toBe(getDayButton(15, 'February'));
1364
- expect(onChange).not.toHaveBeenCalled();
1365
- });
1366
-
1367
- it('a refused target is dropped when focus leaves the day grid, so a later Next click plus Enter picks nothing', async () => {
1368
- const user = userEvent.setup();
1369
- const onChange = vi.fn();
1370
- function Owner({allow}: {allow: boolean}) {
1371
- const [focusDate, setFocusDate] = useState<ISODateString>('2026-01-01');
1372
- return (
1373
- <Calendar
1374
- focusDate={focusDate}
1375
- onFocusDateChange={next => {
1376
- if (allow) {
1377
- setFocusDate(next);
1378
- }
1379
- }}
1380
- onChange={onChange}
1381
- />
1382
- );
1383
- }
1384
- const {rerender} = render(<Owner allow={false} />);
1385
- getDayButton(15).focus();
1386
- // Refused: January stays, focus stays on January 15.
1387
- await user.keyboard('{PageDown}');
1388
- expect(document.activeElement).toBe(getDayButton(15));
1389
- // Focus moves off the day grid onto the Next button; the owner then
1390
- // allows month changes without any focus change of its own.
1391
- act(() => getButton('Next month').focus());
1392
- rerender(<Owner allow />);
1393
- await user.click(getButton('Next month'));
1394
- await waitFor(() => {
1395
- expect(screen.getByRole('grid')).toHaveAttribute(
1396
- 'aria-label',
1397
- 'February 2026',
1398
- );
1399
- });
1400
- // The stale February 15 target must not have taken focus; Enter on
1401
- // whatever is focused picks nothing.
1402
- expect(document.activeElement).not.toBe(getDayButton(15, 'February'));
1403
- await user.keyboard('{Enter}');
1404
- expect(onChange).not.toHaveBeenCalled();
1405
- });
1406
-
1407
- it('a refused page target is dropped by an arrow to another day, so showing the months later does not select it', async () => {
1408
- const user = userEvent.setup();
1409
- const onChange = vi.fn();
1410
- function Owner({focusDate}: {focusDate: ISODateString}) {
1411
- // A controlled owner that ignores every requested change: the shown
1412
- // months move only when the test re-renders it with a new prop, with
1413
- // no focus change of its own.
1414
- return (
1415
- <Calendar
1416
- focusDate={focusDate}
1417
- numberOfMonths={2}
1418
- onFocusDateChange={() => {}}
1419
- onChange={onChange}
1420
- />
1421
- );
1422
- }
1423
- const {rerender} = render(<Owner focusDate="2026-01-01" />);
1424
- getDayButton(10, 'February').focus();
1425
- // Declined: Jan–Feb stay; focus stays on February 10.
1426
- await user.keyboard('{PageDown}');
1427
- expect(document.activeElement).toBe(getDayButton(10, 'February'));
1428
- // An arrow to February 11 is a focus move to a day other than the
1429
- // target, so the stale March 10 target is dropped.
1430
- await user.keyboard('{ArrowRight}');
1431
- expect(document.activeElement).toBe(getDayButton(11, 'February'));
1432
- // The owner now shows February–March without touching focus.
1433
- rerender(<Owner focusDate="2026-02-01" />);
1434
- await waitFor(() => {
1435
- expect(
1436
- screen.getAllByRole('grid').map(g => g.getAttribute('aria-label')),
1437
- ).toEqual(['February 2026', 'March 2026']);
1438
- });
1439
- expect(document.activeElement).toBe(getDayButton(11, 'February'));
1440
- await user.keyboard('{Enter}');
1441
- expect(onChange).not.toHaveBeenCalledWith('2026-03-10');
1442
- });
1443
-
1444
- it("the pending target becomes the grid's Tab stop: after a page into the second grid and after a page that moves the months, only it has tabindex 0", async () => {
1445
- const user = userEvent.setup();
1446
- render(<Calendar focusDate="2026-01-01" numberOfMonths={2} />);
1447
- // Per grid: the day buttons with tabindex 0 (each grid keeps at most one;
1448
- // a borrowed copy in the other grid may share the date).
1449
- const stops = (gridName: string) =>
1450
- Array.from(
1451
- screen
1452
- .getByRole('grid', {name: gridName})
1453
- .querySelectorAll<HTMLElement>('button[data-date]'),
1454
- ).filter(button => button.tabIndex === 0);
1455
- // PageDown from January 15 lands on February 15 in the second grid —
1456
- // not February's default stop (its first day), so the stop must move.
1457
- getDayButton(15).focus();
1458
- await user.keyboard('{PageDown}');
1459
- await waitFor(() => {
1460
- expect(document.activeElement).toHaveAttribute(
1461
- 'data-date',
1462
- '2026-02-15',
1463
- );
1464
- });
1465
- expect(
1466
- stops('February 2026').map(b => b.getAttribute('data-date')),
1467
- ).toEqual(['2026-02-15']);
1468
- expect(stops('January 2026')).toHaveLength(1);
1469
- // PageDown again moves both months; March 15 is March's one stop.
1470
- await user.keyboard('{PageDown}');
1471
- await waitFor(() => {
1472
- expect(document.activeElement).toHaveAttribute(
1473
- 'data-date',
1474
- '2026-03-15',
1475
- );
1476
- });
1477
- expect(stops('March 2026').map(b => b.getAttribute('data-date'))).toEqual(
1478
- ['2026-03-15'],
1479
- );
1480
- expect(stops('February 2026')).toHaveLength(1);
1481
- });
1482
-
1483
- it('a page whose target lies past max changes nothing and keeps focus', async () => {
1484
- const user = userEvent.setup();
1485
- render(<Calendar focusDate="2026-01-01" max="2026-02-10" />);
1486
- getDayButton(15).focus();
1487
- // February 15 is past max: no page, no focus drop.
1488
- await user.keyboard('{PageDown}');
1489
- // No announcement was made (the live region never mounted) and January
1490
- // is still the month shown.
1491
- expect(politeRegion()?.textContent ?? '').not.toContain('February 2026');
1492
- expect(getDayButton(15)).toHaveAttribute('data-date', '2026-01-15');
1493
- expect(document.activeElement).toBe(getDayButton(15));
1494
- });
1495
-
1496
- it('in a two-month view a boundary blocks only out-of-range targets, not month movement', async () => {
1497
- const user = userEvent.setup();
1498
- render(
1499
- <Calendar focusDate="2026-01-01" min="2026-01-01" numberOfMonths={2} />,
1500
- );
1501
- // ArrowUp from February 3 reaches January 27 — in range, in the first
1502
- // grid — even though Previous is disabled at the January minimum.
1503
- getDayButton(3, 'February').focus();
1504
- await user.keyboard('{ArrowUp}');
1505
- await waitFor(() => {
1506
- expect(document.activeElement).toHaveAttribute(
1507
- 'data-date',
1508
- '2026-01-27',
1509
- );
1510
- });
1511
- // PageDown from January 15 reaches February 15, already visible: no
1512
- // month change, focus moves to it.
1513
- getDayButton(15).focus();
1514
- await user.keyboard('{PageDown}');
1515
- await waitFor(() => {
1516
- expect(document.activeElement).toHaveAttribute(
1517
- 'data-date',
1518
- '2026-02-15',
1519
- );
1520
- });
1521
- expect(getDayButton(15)).toBeInTheDocument();
1522
- });
1523
-
1524
- it('announces the next month when paging the grid with PageDown', async () => {
1525
- const user = userEvent.setup();
1526
- render(<Calendar focusDate="2026-01-01" />);
1527
-
1528
- // PageDown from a focused day pages the visible grid to the next month.
1529
- getDayButton(15).focus();
1530
- await user.keyboard('{PageDown}');
1531
-
1532
- await waitFor(() => {
1533
- expect(politeRegion()).toHaveTextContent('February 2026');
1534
- });
1535
- });
1536
-
1537
- it('announces the newly visible month when navigated via the handle', async () => {
1538
- let handle: CalendarHandle | null = null;
1539
- render(
1540
- <Calendar
1541
- focusDate="2026-01-01"
1542
- handleRef={h => {
1543
- handle = h;
1544
- }}
1545
- />,
1546
- );
1547
-
1548
- act(() => {
1549
- handle?.navigateTo('2026-03-01');
1550
- });
1551
-
1552
- await waitFor(() => {
1553
- expect(politeRegion()).toHaveTextContent('March 2026');
1554
- });
1555
- });
1556
-
1557
- it('announces both months in a two-month view', async () => {
1558
- const user = userEvent.setup();
1559
- render(<Calendar numberOfMonths={2} focusDate="2026-01-01" />);
1560
-
1561
- await user.click(screen.getByRole('button', {name: 'Next month'}));
1562
-
1563
- await waitFor(() => {
1564
- expect(politeRegion()).toHaveTextContent('February 2026 – March 2026');
1565
- });
1566
- });
1567
-
1568
- it('does not announce when selecting a date leaves the visible month unchanged', async () => {
1569
- const user = userEvent.setup();
1570
- render(<Calendar focusDate="2026-01-01" />);
1571
-
1572
- // Selecting an in-month day does not move the grid, so nothing should be
1573
- // announced (the live region stays uncreated).
1574
- await user.click(getDayButton(15));
1575
-
1576
- // Allow the announce rAF a chance to run before asserting silence.
1577
- await act(async () => {
1578
- await new Promise(resolve => requestAnimationFrame(resolve));
1579
- });
1580
- expect(politeRegion()).toBeNull();
1581
- });
1582
- });
1583
-
1584
- // ─── Selection Semantics for AT (WCAG 4.1.2 / 1.3.1) ────────
1585
-
1586
- describe('selection state in day accessible names', () => {
1587
- it("appends 'selected' to the selected day's button name in single mode", () => {
1588
- render(<Calendar value="2026-01-15" focusDate="2026-01-01" />);
1589
-
1590
- // Roving focus lands on the day <button>, which cannot carry
1591
- // aria-selected (invalid on role="button") — the selection state must
1592
- // be encoded in the button's accessible name instead.
1593
- expect(getDayButton(15).getAttribute('aria-label')).toBe(
1594
- 'Thursday, January 15, 2026, selected',
1595
- );
1596
- // Unselected days carry the plain date name.
1597
- expect(getDayButton(20).getAttribute('aria-label')).toBe(
1598
- 'Tuesday, January 20, 2026',
1599
- );
1600
- });
1601
-
1602
- it('marks range start, end, and in-range days in their accessible names', () => {
1603
- render(
1604
- <Calendar
1605
- mode="range"
1606
- value={{start: '2026-01-10', end: '2026-01-15'}}
1607
- focusDate="2026-01-01"
1608
- />,
1609
- );
1610
-
1611
- expect(getDayButton(10).getAttribute('aria-label')).toBe(
1612
- 'Saturday, January 10, 2026, range start',
1613
- );
1614
- expect(getDayButton(15).getAttribute('aria-label')).toBe(
1615
- 'Thursday, January 15, 2026, range end',
1616
- );
1617
- expect(getDayButton(12).getAttribute('aria-label')).toBe(
1618
- 'Monday, January 12, 2026, in range',
1619
- );
1620
- // Days outside the range keep the plain date name.
1621
- expect(getDayButton(20).getAttribute('aria-label')).toBe(
1622
- 'Tuesday, January 20, 2026',
1623
- );
1624
- });
1625
-
1626
- it('labels a one-day range as both range start and range end', () => {
1627
- render(
1628
- <Calendar
1629
- mode="range"
1630
- value={{start: '2026-01-10', end: '2026-01-10'}}
1631
- focusDate="2026-01-01"
1632
- />,
1633
- );
1634
-
1635
- expect(getDayButton(10).getAttribute('aria-label')).toBe(
1636
- 'Saturday, January 10, 2026, range start and range end',
1637
- );
1638
- });
1639
-
1640
- it("labels the in-progress first pick as 'range start' only", async () => {
1641
- const user = userEvent.setup();
1642
- render(<Calendar mode="range" focusDate="2026-01-01" />);
1643
-
1644
- await user.click(getDayButton(10));
1645
-
1646
- // While the range is in progress the picked day is only the start —
1647
- // not a completed one-day range.
1648
- expect(getDayButton(10).getAttribute('aria-label')).toBe(
1649
- 'Saturday, January 10, 2026, range start',
1650
- );
1651
- });
1652
- });
1653
-
1654
- describe('range selection announcements', () => {
1655
- it('announces the start pick and prompts for an end date', async () => {
1656
- const user = userEvent.setup();
1657
- render(<Calendar mode="range" focusDate="2026-01-01" />);
1658
-
1659
- await user.click(getDayButton(10));
1660
-
1661
- await waitFor(() => {
1662
- expect(politeRegion()).toHaveTextContent(
1663
- 'Start date Saturday, January 10, 2026. Select an end date.',
1664
- );
1665
- });
1666
- });
1667
-
1668
- it('announces the completed range after the second pick', async () => {
1669
- const user = userEvent.setup();
1670
- render(<Calendar mode="range" focusDate="2026-01-01" />);
1671
-
1672
- await user.click(getDayButton(10));
1673
- await user.click(getDayButton(15));
1674
-
1675
- await waitFor(() => {
1676
- expect(politeRegion()).toHaveTextContent(
1677
- 'Selected range: Saturday, January 10, 2026 to Thursday, January 15, 2026.',
1678
- );
1679
- });
1680
- });
1681
-
1682
- it('announces the completed range in chronological order for a reverse pick', async () => {
1683
- const user = userEvent.setup();
1684
- render(<Calendar mode="range" focusDate="2026-01-01" />);
1685
-
1686
- await user.click(getDayButton(20));
1687
- await user.click(getDayButton(10));
1688
-
1689
- await waitFor(() => {
1690
- expect(politeRegion()).toHaveTextContent(
1691
- 'Selected range: Saturday, January 10, 2026 to Tuesday, January 20, 2026.',
1692
- );
1693
- });
1694
- });
1695
- });
1696
-
1697
- describe('aria-multiselectable', () => {
1698
- it('does not set aria-multiselectable in single mode', () => {
1699
- render(<Calendar focusDate="2026-01-01" />);
1700
-
1701
- expect(screen.getByRole('grid')).not.toHaveAttribute(
1702
- 'aria-multiselectable',
1703
- );
1704
- });
1705
-
1706
- it('sets aria-multiselectable on both grids in a two-month range view', () => {
1707
- render(
1708
- <Calendar mode="range" numberOfMonths={2} focusDate="2026-01-01" />,
1709
- );
1710
-
1711
- const grids = screen.getAllByRole('grid');
1712
- expect(grids.length).toBe(2);
1713
- for (const grid of grids) {
1714
- expect(grid).toHaveAttribute('aria-multiselectable', 'true');
1715
- }
1716
- });
1717
- });
1718
-
1719
- // ─── Bug Regression Tests ───────────────────────────────────
1720
-
1721
- it('day buttons have data-date attribute with ISO string', () => {
1722
- render(<Calendar focusDate="2026-01-01" />);
1723
-
1724
- const day15 = getDayButton(15);
1725
- expect(day15).toHaveAttribute('data-date', '2026-01-15');
1726
- });
1727
-
1728
- it('ArrowDown moves focus +7 days, not to same day in next month', async () => {
1729
- const user = userEvent.setup();
1730
- const handleFocusChange = vi.fn();
1731
-
1732
- render(<ControlledFocusCalendar onFocusDateChange={handleFocusChange} />);
1733
-
1734
- // Focus Jan 28
1735
- const day28 = getDayButton(28);
1736
- await user.click(day28);
1737
- day28.focus();
1738
-
1739
- // Press ArrowDown — should move to Feb 4 (+7 days), not Feb 28. The
1740
- // borrowed February row in January's grid is skipped; the grid navigates
1741
- // to February and focuses the real day there.
1742
- await user.keyboard('{ArrowDown}');
1743
-
1744
- expect(handleFocusChange).toHaveBeenCalledWith('2026-02-01');
1745
- await waitFor(() => {
1746
- expect(document.activeElement).toHaveAttribute('data-date', '2026-02-04');
1747
- });
1748
- expect(document.activeElement).not.toHaveAttribute('aria-disabled');
1749
- });
1750
-
1751
- it('ArrowDown lands on the same weekday +7 days even when earlier days are disabled (complex-2)', async () => {
1752
- const user = userEvent.setup();
1753
-
1754
- // min disables Jan 1–4 (HTML-disabled). Jan 8 is a Thursday; ArrowDown must
1755
- // land on Jan 15 (the same weekday, +7 days), not a shifted date caused by
1756
- // the removed enabled cells.
1757
- render(<Calendar focusDate="2026-01-01" min="2026-01-05" />);
1758
-
1759
- const day1 = getDayButton(1);
1760
- expect(day1).toHaveAttribute('aria-disabled', 'true');
1761
-
1762
- const day8 = getDayButton(8);
1763
- day8.focus();
1764
-
1765
- await user.keyboard('{ArrowDown}');
1766
- expect(document.activeElement).toHaveAttribute('data-date', '2026-01-15');
1767
-
1768
- await user.keyboard('{ArrowDown}');
1769
- expect(document.activeElement).toHaveAttribute('data-date', '2026-01-22');
1770
- });
1771
-
1772
- it('ArrowUp skips a disabled cell in the same column to the next enabled row (complex-2)', async () => {
1773
- const user = userEvent.setup();
1774
-
1775
- // max disables Jan 22 onward. Focus Feb 5 handling is out of scope; instead
1776
- // use dateConstraints to disable a single mid-grid day and verify column
1777
- // geometry is preserved (ArrowUp from Jan 15 skips disabled Jan 8 → Jan 1).
1778
- const disableJan8 = (date: Date) =>
1779
- !(
1780
- date.getFullYear() === 2026 &&
1781
- date.getMonth() === 0 &&
1782
- date.getDate() === 8
1783
- );
1784
-
1785
- render(<Calendar focusDate="2026-01-01" dateConstraints={[disableJan8]} />);
1786
-
1787
- const day8 = getDayButton(8);
1788
- expect(day8).toHaveAttribute('aria-disabled', 'true');
1789
-
1790
- const day15 = getDayButton(15);
1791
- day15.focus();
1792
-
1793
- // ArrowUp: same column one row up is Jan 8 (disabled) → skip to Jan 1.
1794
- await user.keyboard('{ArrowUp}');
1795
- expect(document.activeElement).toHaveAttribute('data-date', '2026-01-01');
1796
- });
1797
-
1798
- it('cross-month arrow nav resolves the focused date from data-date (locale-safe)', async () => {
1799
- // Regression for complex-4: getFocusedDate must read the machine-readable
1800
- // data-date attribute, not parse the human-readable aria-label with
1801
- // new Date() (which is locale-dependent). We prove the resolution path by
1802
- // corrupting the aria-label to something new Date() cannot parse — cross-
1803
- // month navigation must still report the correct ISO date.
1804
- const user = userEvent.setup();
1805
- const handleFocusChange = vi.fn();
1806
-
1807
- render(<ControlledFocusCalendar onFocusDateChange={handleFocusChange} />);
1808
-
1809
- const day28 = getDayButton(28);
1810
- await user.click(day28);
1811
- day28.focus();
1812
- // Simulate a non-English/unparseable aria-label while keeping data-date.
1813
- day28.setAttribute('aria-label', '2026年1月28日 水曜日');
1814
-
1815
- await user.keyboard('{ArrowDown}');
1816
-
1817
- // Feb 4 (+7 days) — resolved via data-date despite the unparseable label.
1818
- expect(handleFocusChange).toHaveBeenCalledWith('2026-02-01');
1819
- await waitFor(() => {
1820
- expect(document.activeElement).toHaveAttribute('data-date', '2026-02-04');
1821
- });
1822
- });
1823
-
1824
- it('prev button is disabled when focusDate month contains min', () => {
1825
- render(<Calendar focusDate="2026-01-01" min="2026-01-15" />);
1826
-
1827
- const prevButton = getButton('Previous month');
1828
- expect(prevButton).toBeDisabled();
1829
- });
1830
-
1831
- it('next button is disabled when focusDate month contains max', () => {
1832
- render(<Calendar focusDate="2026-01-01" max="2026-01-15" />);
1833
-
1834
- const nextButton = getButton('Next month');
1835
- expect(nextButton).toBeDisabled();
1836
- });
1837
-
1838
- it('outside days are not clickable when hasOutsideDays is true', async () => {
1839
- const user = userEvent.setup();
1840
- const handleChange = vi.fn();
1841
-
1842
- render(
1843
- <Calendar
1844
- focusDate="2026-01-01"
1845
- hasOutsideDays
1846
- onChange={handleChange}
1847
- />,
1848
- );
1849
-
1850
- // January 2026 starts on Thursday, so Dec 28-31 are outside days
1851
- // Find an outside day button (December day visible in January grid)
1852
- const outsideDays = screen.getAllByRole('gridcell').filter(cell => {
1853
- const button = cell.querySelector('button');
1854
- return button?.getAttribute('aria-disabled') === 'true';
1855
- });
1856
-
1857
- // Click the first outside day
1858
- if (outsideDays[0]) {
1859
- const button = outsideDays[0].querySelector('button');
1860
- if (button) {
1861
- await user.click(button);
1862
- }
1863
- }
1864
-
1865
- expect(handleChange).not.toHaveBeenCalled();
1866
- });
1867
-
1868
- it('Escape cancels range selection in progress', async () => {
1869
- const user = userEvent.setup();
1870
- const handleChange = vi.fn();
1871
-
1872
- render(
1873
- <Calendar mode="range" onChange={handleChange} focusDate="2026-01-01" />,
1874
- );
1875
-
1876
- // Click start date to begin range selection
1877
- const day10 = getDayButton(10);
1878
- await user.click(day10);
1879
-
1880
- // Press Escape to cancel
1881
- await user.keyboard('{Escape}');
1882
-
1883
- // Click another date — should start a NEW range, not complete the old one
1884
- const day20 = getDayButton(20);
1885
- await user.click(day20);
1886
-
1887
- // onChange should NOT have been called (no range completed)
1888
- expect(handleChange).not.toHaveBeenCalled();
1889
- });
1890
-
1891
- it('day name headers have role="columnheader"', () => {
1892
- render(<Calendar focusDate="2026-01-01" />);
1893
-
1894
- const columnHeaders = screen.getAllByRole('columnheader');
1895
- expect(columnHeaders.length).toBe(7);
1896
-
1897
- // Verify they contain day name abbreviations
1898
- const dayNames = columnHeaders.map(h => h.textContent);
1899
- expect(dayNames).toEqual(['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']);
1900
- });
1901
-
1902
- it('button inside gridcell does not duplicate role="gridcell"', () => {
1903
- render(<Calendar focusDate="2026-01-01" />);
1904
-
1905
- const gridcells = screen.getAllByRole('gridcell');
1906
- for (const cell of gridcells) {
1907
- const button = cell.querySelector('button');
1908
- if (button) {
1909
- expect(button).not.toHaveAttribute('role', 'gridcell');
1910
- }
1911
- }
1912
- });
1913
-
1914
- // ─── RTL (#3388) ─────────────────────────────────────────────
1915
-
1916
- describe('RTL month navigation', () => {
1917
- // jsdom does not apply compiled StyleX CSS, so the RTL scaleX mirror is
1918
- // only observable in a browser (see the dir="rtl" Storybook story). These
1919
- // tests pin the structure the mirror relies on: both nav chevrons render
1920
- // inside the navIcon wrapper (which composes the shared rtlStyles.mirror
1921
- // transform), and navigation semantics stay identical under dir="rtl".
1922
- it('wraps both nav chevrons in the navIcon wrapper', () => {
1923
- render(<Calendar focusDate="2026-01-01" />);
1924
-
1925
- const {className: navIconClass} = stylex.props(calendarStyles.navIcon);
1926
- expect(navIconClass).toBeTruthy();
1927
- const navIconAtoms = navIconClass!.split(' ');
1928
-
1929
- for (const name of ['Previous month', 'Next month']) {
1930
- const button = getButton(name);
1931
- const wrappers = Array.from(button.querySelectorAll('span')).filter(
1932
- span => navIconAtoms.every(atom => span.classList.contains(atom)),
1933
- );
1934
- expect(wrappers.length).toBe(1);
1935
- }
1936
- });
1937
-
1938
- it('keeps navigation semantics unchanged under dir="rtl"', async () => {
1939
- const user = userEvent.setup();
1940
-
1941
- // Scope month-label queries to the rendered tree: month navigation also
1942
- // announces the month name through the body-level polite live region,
1943
- // and whether that text has landed by assertion time depends on jsdom's
1944
- // 16ms rAF frame phase — an unscoped getByText intermittently finds two
1945
- // matches ("February 2026" in both the header and the live region).
1946
- const {container} = render(
1947
- <div dir="rtl">
1948
- <Calendar focusDate="2026-02-01" />
1949
- </div>,
1950
- );
1951
-
1952
- expect(within(container).getByText('February 2026')).toBeInTheDocument();
1953
-
1954
- // DOM order and handlers must not change in RTL: flexbox already
1955
- // places "Previous month" at the visual right; only the glyph mirrors.
1956
- await user.click(getButton('Previous month'));
1957
- expect(within(container).getByText('January 2026')).toBeInTheDocument();
1958
-
1959
- await user.click(getButton('Next month'));
1960
- expect(within(container).getByText('February 2026')).toBeInTheDocument();
1961
- });
1962
- });
1963
-
1964
- // ─── Day-cell marker theming (#4286) ─────────────────────────
1965
- describe('day-cell marker theme state', () => {
1966
- // Pin "today" to a mid-month date so the ±2-day range helpers below stay
1967
- // within a single rendered month. With the real clock, running near a month
1968
- // boundary (e.g. the 1st) pushed today-2 into the previous month, so the
1969
- // rendered grid didn't contain today's cell and the marker assertions
1970
- // flaked. Fake only Date (timers stay real; these tests are synchronous).
1971
- beforeEach(() => {
1972
- vi.useFakeTimers({toFake: ['Date']});
1973
- vi.setSystemTime(new Date(2026, 5, 15, 12, 0, 0));
1974
- });
1975
- afterEach(() => {
1976
- vi.useRealTimers();
1977
- });
1978
- // Tests use the (now-pinned) "today" since Calendar derives it internally.
1979
- // Helpers pin the exact ISO strings.
1980
- function todayISO(): ISODateString {
1981
- const n = new Date();
1982
- return `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, '0')}-${String(n.getDate()).padStart(2, '0')}` as ISODateString;
1983
- }
1984
- function isoOffsetFromToday(deltaDays: number): ISODateString {
1985
- const n = new Date();
1986
- n.setDate(n.getDate() + deltaDays);
1987
- return `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, '0')}-${String(n.getDate()).padStart(2, '0')}` as ISODateString;
1988
- }
1989
- function todayCell(): HTMLElement {
1990
- const el = document.querySelector<HTMLElement>(
1991
- `button[data-date="${todayISO()}"]`,
1992
- );
1993
- expect(el).not.toBeNull();
1994
- return el as HTMLElement;
1995
- }
1996
-
1997
- it('reflects marker="today-only" for a plain today cell (no selection)', () => {
1998
- render(<Calendar />);
1999
- const cell = todayCell();
2000
- expect(cell).toHaveAttribute('data-marker', 'today-only');
2001
- expect(cell).toHaveAttribute('data-today', 'today');
2002
- expect(cell).not.toHaveAttribute('data-selected');
2003
- expect(cell).not.toHaveAttribute('data-in-range');
2004
- });
2005
-
2006
- it('reflects marker="today-in-range" when today is strictly inside a range', () => {
2007
- render(
2008
- <Calendar
2009
- mode="range"
2010
- value={{start: isoOffsetFromToday(-2), end: isoOffsetFromToday(2)}}
2011
- />,
2012
- );
2013
- const cell = todayCell();
2014
- // Today is inside the range but not an endpoint: the today-in-range ring
2015
- // is shown, so `marker` reflects that compound state precisely.
2016
- expect(cell).toHaveAttribute('data-marker', 'today-in-range');
2017
- expect(cell).toHaveAttribute('data-in-range', 'in-range');
2018
- expect(cell).not.toHaveAttribute('data-selected');
2019
- });
2020
-
2021
- it('shows no marker state when today is the single-selected date', () => {
2022
- render(<Calendar mode="single" value={todayISO()} />);
2023
- const cell = todayCell();
2024
- // A single-mode selected cell shows no ring by default — `marker` is
2025
- // absent, while `selected` (which owns the selected treatment) is present.
2026
- expect(cell).not.toHaveAttribute('data-marker');
2027
- expect(cell).toHaveAttribute('data-selected', 'selected');
2028
- expect(cell).toHaveAttribute('data-today', 'today');
2029
- });
2030
-
2031
- it('preserves the today-in-range ring on a today range endpoint', () => {
2032
- render(
2033
- <Calendar
2034
- mode="range"
2035
- value={{start: todayISO(), end: isoOffsetFromToday(3)}}
2036
- />,
2037
- );
2038
- const cell = todayCell();
2039
- // A range endpoint is NOT `isSelected` (that flag is single-mode only),
2040
- // so by default the today-in-range ring IS drawn on a today endpoint
2041
- // alongside the endpoint styling. `marker` mirrors that exactly — this
2042
- // asserts the default rendering is preserved, byte-for-byte.
2043
- expect(cell).toHaveAttribute('data-marker', 'today-in-range');
2044
- expect(cell).toHaveAttribute('data-in-range', 'in-range');
2045
- });
2046
-
2047
- it('omits the marker state for non-today cells', () => {
2048
- render(<Calendar />);
2049
- const other = document.querySelector(
2050
- `button[data-date="${isoOffsetFromToday(1)}"]`,
2051
- );
2052
- // Guard against the +1 day landing in an adjacent month with outside days
2053
- // hidden; if present it must carry no marker.
2054
- if (other) {
2055
- expect(other).not.toHaveAttribute('data-marker');
2056
- }
2057
- });
2058
-
2059
- it('exposes the marker states as themeable defineTheme targets', () => {
2060
- // jsdom can't resolve the @layer cascade, so the DOM-reflection tests
2061
- // above cover that the right state renders; this asserts the state is
2062
- // reachable by a theme via the sanctioned defineTheme channel.
2063
- const theme = defineTheme({
2064
- name: 'calendar-marker-test',
2065
- components: {
2066
- 'calendar-day': {
2067
- 'marker:today-only': {
2068
- boxShadow: 'inset 0 0 0 2px var(--color-accent)',
2069
- },
2070
- 'marker:today-in-range': {
2071
- boxShadow: 'inset 0 0 0 2px var(--color-text-primary)',
2072
- },
2073
- },
2074
- },
2075
- });
2076
- const css = generateThemeTestCSS(theme);
2077
- expect(css).toContain('.astryx-calendar-day[data-marker="today-only"]');
2078
- expect(css).toContain(
2079
- '.astryx-calendar-day[data-marker="today-in-range"]',
2080
- );
2081
- expect(css).toContain('box-shadow: inset 0 0 0 2px var(--color-accent)');
2082
- expect(css).toContain(
2083
- 'box-shadow: inset 0 0 0 2px var(--color-text-primary)',
2084
- );
2085
- });
2086
- });
2087
-
2088
- // ─── Theming targets ─────────────────────────────────────────
2089
- describe('theming targets', () => {
2090
- it('renders the astryx-calendar-nav target on both month-nav buttons', () => {
2091
- render(<Calendar focusDate="2026-01-01" />);
2092
-
2093
- const prev = getButton('Previous month');
2094
- const next = getButton('Next month');
2095
-
2096
- // Dedicated, stable theme target — scoped to the nav controls, not the
2097
- // global astryx-button handle that hits every Button in the app.
2098
- expect(prev).toHaveClass('astryx-calendar-nav');
2099
- expect(next).toHaveClass('astryx-calendar-nav');
2100
-
2101
- // Direction is reflected so a theme can target one arrow alone.
2102
- expect(prev).toHaveAttribute('data-nav', 'prev');
2103
- expect(next).toHaveAttribute('data-nav', 'next');
2104
- });
2105
-
2106
- it('reflects the disabled nav state as a data attribute at the range edges', () => {
2107
- // Clamp navigation so "Previous month" is disabled and "Next" is not.
2108
- render(
2109
- <Calendar focusDate="2026-01-15" min="2026-01-01" max="2026-03-31" />,
2110
- );
2111
-
2112
- const prev = getButton('Previous month');
2113
- const next = getButton('Next month');
2114
-
2115
- expect(prev).toHaveAttribute('data-disabled', 'disabled');
2116
- expect(next).not.toHaveAttribute('data-disabled');
2117
- });
2118
-
2119
- it('keeps the default nav rendering unchanged (still a ghost icon button)', () => {
2120
- render(<Calendar focusDate="2026-01-01" />);
2121
-
2122
- // The new target is additive — the nav still carries the stock Button
2123
- // classes, so default appearance is preserved.
2124
- const prev = getButton('Previous month');
2125
- expect(prev).toHaveClass('astryx-button');
2126
- expect(prev).toHaveAttribute('data-variant', 'ghost');
2127
- expect(prev.tagName).toBe('BUTTON');
2128
- });
2129
-
2130
- it('renders the astryx-calendar-day target with its reflected states', () => {
2131
- render(
2132
- <Calendar mode="single" value="2026-01-15" focusDate="2026-01-01" />,
2133
- );
2134
-
2135
- const selected = getDayButton(15);
2136
- expect(selected).toHaveClass('astryx-calendar-day');
2137
- expect(selected).toHaveAttribute('data-selected', 'selected');
2138
-
2139
- // A non-selected weekday cell still carries the base target and no
2140
- // selected/today reflection.
2141
- const plain = getDayButton(20);
2142
- expect(plain).toHaveClass('astryx-calendar-day');
2143
- expect(plain).not.toHaveAttribute('data-selected');
2144
- });
2145
-
2146
- it('exposes calendar-nav as a themeable defineTheme target', () => {
2147
- // The generated CSS is what proves the target is reachable by a theme:
2148
- // jsdom cannot resolve the @layer cascade, so the DOM-class assertions
2149
- // above and this generation assertion together cover the seam.
2150
- const theme = defineTheme({
2151
- name: 'calendar-nav-test',
2152
- components: {
2153
- 'calendar-nav': {
2154
- base: {color: 'var(--color-accent)'},
2155
- 'nav:next': {backgroundColor: 'var(--color-accent-muted)'},
2156
- },
2157
- },
2158
- });
2159
- const css = generateThemeTestCSS(theme);
2160
- expect(css).toContain('.astryx-calendar-nav {');
2161
- expect(css).toContain('color: var(--color-accent)');
2162
- expect(css).toContain('.astryx-calendar-nav[data-nav="next"]');
2163
- expect(css).toContain('background-color: var(--color-accent-muted)');
2164
- });
2165
- });
2166
- });
2167
-
2168
- // jsdom cannot emulate forced-colors rendering, so this asserts that the
2169
- // compiled output includes the forced-colors rules; visual behavior needs
2170
- // manual verification under Windows High Contrast.
2171
- describe('forced colors (WCAG 1.4.11)', () => {
2172
- it('compiles a forced-colors fill so the selected date survives Windows High Contrast', () => {
2173
- render(
2174
- <Calendar mode="single" value="2026-01-15" focusDate="2026-01-01" />,
2175
- );
2176
-
2177
- const css = getForcedColorsRules();
2178
- // Without these the accent fill is stripped and the selected date renders
2179
- // identically to every other day in the month.
2180
- expect(css).toContain('background-color: highlight;');
2181
- expect(css).toContain('color: highlighttext;');
2182
- // A <button> keeps the native ButtonFace surface and ignores the authored
2183
- // Highlight fill unless it opts out of UA remapping.
2184
- expect(getAllInjectedCss()).toContain('forced-color-adjust: none;');
2185
- });
2186
- });