@astryxdesign/core 0.6.2 → 0.6.3-canary.0788c49

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 (558) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/dist/BottomSheet/BottomSheet.d.ts +1 -1
  3. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  4. package/dist/BottomSheet/BottomSheet.js +3 -1
  5. package/dist/BottomSheet/BottomSheetPanel.d.ts +7 -5
  6. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  7. package/dist/BottomSheet/BottomSheetPanel.js +56 -19
  8. package/dist/Button/Button.d.ts.map +1 -1
  9. package/dist/Button/Button.js +13 -28
  10. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  11. package/dist/Chat/ChatComposer.js +10 -5
  12. package/dist/Chat/ChatComposerDrawer.d.ts +19 -5
  13. package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
  14. package/dist/Chat/ChatComposerDrawer.js +48 -23
  15. package/dist/Chat/ChatComposerInput.d.ts +11 -3
  16. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  17. package/dist/Chat/ChatComposerInput.js +63 -16
  18. package/dist/Chat/ChatDictationButton.d.ts +3 -2
  19. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  20. package/dist/Chat/ChatDictationButton.js +6 -4
  21. package/dist/Chat/ChatLayout.d.ts +19 -0
  22. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  23. package/dist/Chat/ChatLayout.js +19 -0
  24. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  25. package/dist/Chat/ChatLayoutScrollButton.js +44 -34
  26. package/dist/Chat/ChatMessageBubble.d.ts +2 -0
  27. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  28. package/dist/Chat/ChatMessageBubble.js +5 -3
  29. package/dist/Chat/ChatMessageList.d.ts +2 -1
  30. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  31. package/dist/Chat/ChatMessageList.js +4 -3
  32. package/dist/Chat/ChatMessageMetadata.d.ts +5 -4
  33. package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
  34. package/dist/Chat/ChatMessageMetadata.js +12 -9
  35. package/dist/Chat/ChatSendButton.d.ts +2 -1
  36. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  37. package/dist/Chat/ChatSendButton.js +6 -4
  38. package/dist/Chat/index.d.ts +1 -1
  39. package/dist/Chat/index.d.ts.map +1 -1
  40. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  41. package/dist/CheckboxInput/CheckboxInput.js +12 -2
  42. package/dist/Citation/Citation.d.ts +1 -1
  43. package/dist/Citation/Citation.d.ts.map +1 -1
  44. package/dist/Citation/Citation.js +3 -2
  45. package/dist/CodeBlock/highlightRanges.d.ts.map +1 -1
  46. package/dist/CodeBlock/highlightRanges.js +14 -3
  47. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  48. package/dist/Collapsible/Collapsible.js +6 -1
  49. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  50. package/dist/CommandPalette/CommandPaletteInput.js +1 -1
  51. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  52. package/dist/ComplexSelector/ComplexSelector.js +1 -1
  53. package/dist/DateInput/DateInput.d.ts.map +1 -1
  54. package/dist/DateInput/DateInput.js +4 -4
  55. package/dist/DateInput/NativeDateField.d.ts.map +1 -1
  56. package/dist/DateInput/NativeDateField.js +16 -16
  57. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  58. package/dist/DateInput/TouchDateField.js +2 -2
  59. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  60. package/dist/DateRangeInput/DateRangeInput.js +4 -4
  61. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  62. package/dist/DateTimeInput/DateTimeInput.js +8 -8
  63. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  64. package/dist/DateTimeInput/TouchDateTimeField.js +4 -4
  65. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +9 -3
  66. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -1
  67. package/dist/DateTimeInput/nativePickerSegmentStyles.js +3 -3
  68. package/dist/Dialog/DialogHeader.d.ts +8 -1
  69. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  70. package/dist/Dialog/DialogHeader.js +13 -4
  71. package/dist/Field/InputClearButton.d.ts +4 -2
  72. package/dist/Field/InputClearButton.d.ts.map +1 -1
  73. package/dist/Field/InputClearButton.js +4 -2
  74. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  75. package/dist/Field/PanelSearchInput.js +1 -1
  76. package/dist/FileInput/FileInput.d.ts.map +1 -1
  77. package/dist/FileInput/FileInput.js +7 -7
  78. package/dist/Icon/Icon.d.ts +6 -31
  79. package/dist/Icon/Icon.d.ts.map +1 -1
  80. package/dist/Icon/Icon.js +8 -71
  81. package/dist/Icon/IconDefaultSizeContext.d.ts +4 -0
  82. package/dist/Icon/IconDefaultSizeContext.d.ts.map +1 -0
  83. package/dist/Icon/IconDefaultSizeContext.js +18 -0
  84. package/dist/Icon/IconSize.stylex.d.ts +65 -0
  85. package/dist/Icon/IconSize.stylex.d.ts.map +1 -0
  86. package/dist/Icon/IconSize.stylex.js +75 -0
  87. package/dist/Item/Item.d.ts +1 -1
  88. package/dist/Item/Item.d.ts.map +1 -1
  89. package/dist/Item/Item.js +4 -3
  90. package/dist/Kbd/Kbd.d.ts +5 -3
  91. package/dist/Kbd/Kbd.d.ts.map +1 -1
  92. package/dist/Kbd/Kbd.js +36 -42
  93. package/dist/Link/Link.d.ts.map +1 -1
  94. package/dist/Link/Link.js +6 -2
  95. package/dist/Link/useLinkComponent.d.ts +5 -15
  96. package/dist/Link/useLinkComponent.d.ts.map +1 -1
  97. package/dist/Link/useLinkComponent.js +34 -51
  98. package/dist/List/List.d.ts +19 -1
  99. package/dist/List/List.d.ts.map +1 -1
  100. package/dist/List/List.js +9 -2
  101. package/dist/List/ListContext.d.ts +1 -0
  102. package/dist/List/ListContext.d.ts.map +1 -1
  103. package/dist/List/ListContext.js +2 -1
  104. package/dist/List/ListItem.d.ts +1 -1
  105. package/dist/List/ListItem.d.ts.map +1 -1
  106. package/dist/List/ListItem.js +9 -2
  107. package/dist/Markdown/Markdown.d.ts +8 -2
  108. package/dist/Markdown/Markdown.d.ts.map +1 -1
  109. package/dist/Markdown/Markdown.fr23.bench.d.ts +2 -0
  110. package/dist/Markdown/Markdown.fr23.bench.d.ts.map +1 -0
  111. package/dist/Markdown/Markdown.fr23.bench.js +150 -0
  112. package/dist/Markdown/Markdown.fr23.sampling.d.ts +2 -0
  113. package/dist/Markdown/Markdown.fr23.sampling.d.ts.map +1 -0
  114. package/dist/Markdown/Markdown.fr23.sampling.js +43 -0
  115. package/dist/Markdown/Markdown.js +262 -109
  116. package/dist/Markdown/ast.d.ts +162 -0
  117. package/dist/Markdown/ast.d.ts.map +1 -0
  118. package/dist/Markdown/ast.js +74 -0
  119. package/dist/Markdown/index.d.ts +5 -3
  120. package/dist/Markdown/index.d.ts.map +1 -1
  121. package/dist/Markdown/index.js +3 -2
  122. package/dist/Markdown/parser/index.d.ts +10 -0
  123. package/dist/Markdown/parser/index.d.ts.map +1 -0
  124. package/dist/Markdown/parser/index.js +10 -0
  125. package/dist/Markdown/parser.d.ts +126 -58
  126. package/dist/Markdown/parser.d.ts.map +1 -1
  127. package/dist/Markdown/parser.js +726 -177
  128. package/dist/Markdown/plugins/frontmatter.d.ts +32 -0
  129. package/dist/Markdown/plugins/frontmatter.d.ts.map +1 -0
  130. package/dist/Markdown/plugins/frontmatter.js +132 -0
  131. package/dist/Markdown/plugins/index.d.ts +17 -0
  132. package/dist/Markdown/plugins/index.d.ts.map +1 -0
  133. package/dist/Markdown/plugins/index.js +14 -0
  134. package/dist/Markdown/plugins/protocol.d.ts +191 -0
  135. package/dist/Markdown/plugins/protocol.d.ts.map +1 -0
  136. package/dist/Markdown/plugins/protocol.js +957 -0
  137. package/dist/Markdown/plugins/semanticFence.d.ts +36 -0
  138. package/dist/Markdown/plugins/semanticFence.d.ts.map +1 -0
  139. package/dist/Markdown/plugins/semanticFence.js +213 -0
  140. package/dist/Markdown/plugins/softBreaks.d.ts +3 -0
  141. package/dist/Markdown/plugins/softBreaks.d.ts.map +1 -0
  142. package/dist/Markdown/plugins/softBreaks.js +172 -0
  143. package/dist/Markdown/plugins/sourceDecoration.d.ts +76 -0
  144. package/dist/Markdown/plugins/sourceDecoration.d.ts.map +1 -0
  145. package/dist/Markdown/plugins/sourceDecoration.js +393 -0
  146. package/dist/Markdown/plugins/textTransform.d.ts +30 -0
  147. package/dist/Markdown/plugins/textTransform.d.ts.map +1 -0
  148. package/dist/Markdown/plugins/textTransform.js +374 -0
  149. package/dist/Markdown/remark.d.ts +196 -0
  150. package/dist/Markdown/remark.d.ts.map +1 -0
  151. package/dist/Markdown/remark.js +1062 -0
  152. package/dist/Markdown/url.d.ts +6 -0
  153. package/dist/Markdown/url.d.ts.map +1 -0
  154. package/dist/Markdown/url.js +31 -0
  155. package/dist/Markdown/utils.d.ts +4 -2
  156. package/dist/Markdown/utils.d.ts.map +1 -1
  157. package/dist/Markdown/utils.js +2 -1
  158. package/dist/MetadataList/MetadataList.js +3 -3
  159. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  160. package/dist/NumberInput/NumberInput.js +4 -4
  161. package/dist/Outline/index.d.ts +1 -0
  162. package/dist/Outline/index.d.ts.map +1 -1
  163. package/dist/Outline/parseOutlineFromMarkdown.d.ts +7 -1
  164. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  165. package/dist/Outline/parseOutlineFromMarkdown.js +14 -8
  166. package/dist/Outline/useOutlineFromMarkdown.d.ts +3 -1
  167. package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
  168. package/dist/Outline/useOutlineFromMarkdown.js +8 -3
  169. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  170. package/dist/PowerSearch/PowerSearchEditPopover.js +46 -30
  171. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  172. package/dist/PowerSearch/PowerSearchValueEditor.js +5 -0
  173. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  174. package/dist/ProgressBar/ProgressBar.js +36 -31
  175. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  176. package/dist/RadioList/RadioListItem.js +13 -1
  177. package/dist/ScrollableArea/ScrollableArea.d.ts +1 -0
  178. package/dist/ScrollableArea/ScrollableArea.d.ts.map +1 -1
  179. package/dist/ScrollableArea/ScrollableArea.js +1 -0
  180. package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
  181. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  182. package/dist/SegmentedControl/SegmentedControl.js +1 -0
  183. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  184. package/dist/SegmentedControl/SegmentedControlItem.js +5 -5
  185. package/dist/Selector/Selector.d.ts +9 -7
  186. package/dist/Selector/Selector.d.ts.map +1 -1
  187. package/dist/Selector/Selector.js +16 -7
  188. package/dist/SideNav/SideNav.d.ts +2 -1
  189. package/dist/SideNav/SideNav.d.ts.map +1 -1
  190. package/dist/SideNav/SideNav.js +9 -3
  191. package/dist/Slider/Slider.d.ts.map +1 -1
  192. package/dist/Slider/Slider.js +28 -12
  193. package/dist/Spinner/Spinner.d.ts.map +1 -1
  194. package/dist/Spinner/Spinner.js +23 -7
  195. package/dist/Switch/Switch.d.ts.map +1 -1
  196. package/dist/Switch/Switch.js +11 -0
  197. package/dist/TabList/Tab.d.ts +1 -1
  198. package/dist/TabList/Tab.d.ts.map +1 -1
  199. package/dist/TabList/Tab.js +20 -7
  200. package/dist/Table/Table.d.ts +1 -0
  201. package/dist/Table/Table.d.ts.map +1 -1
  202. package/dist/Table/Table.js +29 -13
  203. package/dist/TextArea/TextArea.d.ts.map +1 -1
  204. package/dist/TextArea/TextArea.js +1 -1
  205. package/dist/TextInput/TextInput.d.ts.map +1 -1
  206. package/dist/TextInput/TextInput.js +2 -2
  207. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  208. package/dist/TimeInput/TimeInput.js +4 -4
  209. package/dist/Timer/Timer.d.ts +49 -0
  210. package/dist/Timer/Timer.d.ts.map +1 -0
  211. package/dist/Timer/Timer.js +158 -0
  212. package/dist/Timer/index.d.ts +9 -0
  213. package/dist/Timer/index.d.ts.map +1 -0
  214. package/dist/Timer/index.js +10 -0
  215. package/dist/ToggleButton/ToggleButton.d.ts +9 -6
  216. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  217. package/dist/ToggleButton/ToggleButton.js +15 -27
  218. package/dist/TopNav/TopNavMenu.d.ts +1 -1
  219. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  220. package/dist/TopNav/TopNavMenu.js +3 -2
  221. package/dist/TreeList/TreeList.d.ts.map +1 -1
  222. package/dist/TreeList/TreeList.js +3 -0
  223. package/dist/TreeList/TreeListItem.d.ts +6 -1
  224. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  225. package/dist/TreeList/TreeListItem.js +12 -2
  226. package/dist/TreeList/TreeListTypes.d.ts +8 -1
  227. package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
  228. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  229. package/dist/Typeahead/BaseTypeahead.js +16 -7
  230. package/dist/astryx.css +27 -11
  231. package/dist/hooks/scrollKeyboardDelegation.d.ts +3 -0
  232. package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -0
  233. package/dist/hooks/scrollKeyboardDelegation.js +146 -0
  234. package/dist/hooks/useClickableContainer.d.ts +10 -1
  235. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  236. package/dist/hooks/useClickableContainer.js +15 -4
  237. package/dist/hooks/useScrollableArea.d.ts +6 -2
  238. package/dist/hooks/useScrollableArea.d.ts.map +1 -1
  239. package/dist/hooks/useScrollableArea.js +17 -5
  240. package/dist/index.d.ts +1 -0
  241. package/dist/index.d.ts.map +1 -1
  242. package/dist/index.js +3 -0
  243. package/dist/theme/declarationBoundary.d.ts +17 -0
  244. package/dist/theme/declarationBoundary.d.ts.map +1 -0
  245. package/dist/theme/declarationBoundary.js +343 -0
  246. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  247. package/dist/theme/derivedVarRegistry.js +4 -0
  248. package/dist/theme/generateThemeRules.d.ts +13 -7
  249. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  250. package/dist/theme/generateThemeRules.js +140 -34
  251. package/dist/utils/interactionOverlay.stylex.d.ts +8 -0
  252. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  253. package/dist/utils/interactionOverlay.stylex.js +9 -0
  254. package/dist/utils/safeUrl.d.ts +11 -0
  255. package/dist/utils/safeUrl.d.ts.map +1 -0
  256. package/dist/utils/safeUrl.js +78 -0
  257. package/locales/af-ZA.json +530 -1
  258. package/locales/ar-SA.json +490 -1
  259. package/locales/ca-ES.json +514 -1
  260. package/locales/cs-CZ.json +498 -1
  261. package/locales/da-DK.json +522 -1
  262. package/locales/de-DE.json +522 -1
  263. package/locales/el-GR.json +498 -1
  264. package/locales/es-ES.json +510 -1
  265. package/locales/fi-FI.json +498 -1
  266. package/locales/fr-FR.json +534 -1
  267. package/locales/he-IL.json +498 -1
  268. package/locales/hu-HU.json +498 -1
  269. package/locales/it-IT.json +510 -1
  270. package/locales/ja-JP.json +490 -1
  271. package/locales/ko-KR.json +498 -1
  272. package/locales/nl-NL.json +534 -1
  273. package/locales/no-NO.json +510 -1
  274. package/locales/pl-PL.json +506 -1
  275. package/locales/pt-BR.json +506 -1
  276. package/locales/pt-PT.json +506 -1
  277. package/locales/ro-RO.json +506 -1
  278. package/locales/ru-RU.json +498 -1
  279. package/locales/sr-SP.json +498 -1
  280. package/locales/sv-SE.json +502 -1
  281. package/locales/tr-TR.json +498 -1
  282. package/locales/uk-UA.json +498 -1
  283. package/locales/vi-VN.json +502 -1
  284. package/locales/zh-CN.json +490 -1
  285. package/locales/zh-TW.json +490 -1
  286. package/package.json +24 -4
  287. package/src/BottomSheet/BottomSheet.doc.mjs +8 -1
  288. package/src/BottomSheet/BottomSheet.spec.md +46 -20
  289. package/src/BottomSheet/BottomSheet.test.tsx +6 -3
  290. package/src/BottomSheet/BottomSheet.tsx +3 -1
  291. package/src/BottomSheet/BottomSheetKeyboard.test.tsx +195 -0
  292. package/src/BottomSheet/BottomSheetPanel.test.tsx +11 -1
  293. package/src/BottomSheet/BottomSheetPanel.tsx +49 -16
  294. package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +344 -0
  295. package/src/Button/Button.doc.mjs +5 -5
  296. package/src/Button/Button.tsx +15 -13
  297. package/src/Button/__tests__/Button.a11y.chromium.spec.ts +17 -1
  298. package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -29
  299. package/src/Button/__tests__/Button.a11y.renders.tsx +9 -2
  300. package/src/Button/__tests__/Button.a11y.states.ts +9 -0
  301. package/src/Chat/ChatComposer.doc.mjs +14 -0
  302. package/src/Chat/ChatComposer.spec.md +230 -0
  303. package/src/Chat/ChatComposer.test.tsx +57 -0
  304. package/src/Chat/ChatComposer.tsx +21 -9
  305. package/src/Chat/ChatComposerDrawer.doc.mjs +63 -5
  306. package/src/Chat/ChatComposerDrawer.spec.md +267 -0
  307. package/src/Chat/ChatComposerDrawer.test.tsx +81 -12
  308. package/src/Chat/ChatComposerDrawer.tsx +38 -9
  309. package/src/Chat/ChatComposerInput.doc.mjs +114 -26
  310. package/src/Chat/ChatComposerInput.spec.md +185 -0
  311. package/src/Chat/ChatComposerInput.test.tsx +113 -3
  312. package/src/Chat/ChatComposerInput.tsx +78 -13
  313. package/src/Chat/ChatComposerTokenElement.spec.md +152 -0
  314. package/src/Chat/ChatComposerTokenElement.test.tsx +85 -0
  315. package/src/Chat/ChatDictationButton.doc.mjs +3 -3
  316. package/src/Chat/ChatDictationButton.spec.md +160 -0
  317. package/src/Chat/ChatDictationButton.test.tsx +92 -27
  318. package/src/Chat/ChatDictationButton.tsx +8 -6
  319. package/src/Chat/ChatLayout.doc.mjs +12 -4
  320. package/src/Chat/ChatLayout.spec.md +271 -0
  321. package/src/Chat/ChatLayout.test.tsx +28 -0
  322. package/src/Chat/ChatLayout.tsx +19 -0
  323. package/src/Chat/ChatLayoutScrollButton.spec.md +338 -0
  324. package/src/Chat/ChatLayoutScrollButton.test.tsx +31 -0
  325. package/src/Chat/ChatLayoutScrollButton.tsx +31 -14
  326. package/src/Chat/ChatMessageBubble.doc.mjs +28 -15
  327. package/src/Chat/ChatMessageBubble.spec.md +263 -0
  328. package/src/Chat/ChatMessageBubble.test.tsx +93 -0
  329. package/src/Chat/ChatMessageBubble.tsx +8 -3
  330. package/src/Chat/ChatMessageList.spec.md +222 -0
  331. package/src/Chat/ChatMessageList.test.tsx +64 -2
  332. package/src/Chat/ChatMessageList.tsx +4 -3
  333. package/src/Chat/ChatMessageMetadata.doc.mjs +57 -3
  334. package/src/Chat/ChatMessageMetadata.spec.md +220 -0
  335. package/src/Chat/ChatMessageMetadata.test.tsx +34 -0
  336. package/src/Chat/ChatMessageMetadata.tsx +13 -13
  337. package/src/Chat/ChatSendButton.doc.mjs +32 -0
  338. package/src/Chat/ChatSendButton.spec.md +227 -0
  339. package/src/Chat/ChatSendButton.test.tsx +128 -8
  340. package/src/Chat/ChatSendButton.tsx +6 -4
  341. package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +514 -0
  342. package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +740 -0
  343. package/src/Chat/__tests__/ChatMessageBubble.a11y.chromium.spec.ts +457 -0
  344. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.test.ts +91 -0
  345. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.ts +91 -0
  346. package/src/Chat/__tests__/ChatMessageList.a11y.chromium.spec.ts +456 -0
  347. package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +413 -0
  348. package/src/Chat/__tests__/ChatSendButton.a11y.chromium.spec.ts +1522 -0
  349. package/src/Chat/index.ts +1 -0
  350. package/src/CheckboxInput/CheckboxInput.doc.mjs +11 -0
  351. package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
  352. package/src/CheckboxInput/CheckboxInput.tsx +21 -1
  353. package/src/Citation/Citation.doc.mjs +2 -2
  354. package/src/Citation/Citation.test.tsx +17 -0
  355. package/src/Citation/Citation.tsx +4 -2
  356. package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
  357. package/src/ClickableCard/ClickableCard.test.tsx +102 -5
  358. package/src/CodeBlock/highlightRanges.test.ts +143 -1
  359. package/src/CodeBlock/highlightRanges.ts +15 -5
  360. package/src/Collapsible/Collapsible.doc.mjs +11 -0
  361. package/src/Collapsible/Collapsible.test.tsx +21 -0
  362. package/src/Collapsible/Collapsible.tsx +5 -0
  363. package/src/CommandPalette/CommandPaletteInput.tsx +6 -1
  364. package/src/ComplexSelector/ComplexSelector.tsx +6 -1
  365. package/src/DateInput/DateInput.tsx +6 -1
  366. package/src/DateInput/NativeDateField.tsx +24 -8
  367. package/src/DateInput/TouchDateField.tsx +6 -2
  368. package/src/DateRangeInput/DateRangeInput.tsx +6 -1
  369. package/src/DateTimeInput/DateTimeInput.tsx +6 -1
  370. package/src/DateTimeInput/TouchDateTimeField.tsx +6 -1
  371. package/src/DateTimeInput/nativePickerSegmentStyles.ts +24 -8
  372. package/src/Dialog/Dialog.doc.mjs +2 -0
  373. package/src/Dialog/DialogHeader.doc.mjs +22 -0
  374. package/src/Dialog/DialogHeader.test.tsx +167 -3
  375. package/src/Dialog/DialogHeader.tsx +37 -6
  376. package/src/Dialog/modules/DialogHeader.spec.md +101 -42
  377. package/src/DropdownMenu/DropdownMenu.test.tsx +5 -2
  378. package/src/Field/InputClearButton.test.tsx +17 -3
  379. package/src/Field/InputClearButton.tsx +5 -2
  380. package/src/Field/PanelSearchInput.tsx +5 -2
  381. package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +1 -1
  382. package/src/FileInput/FileInput.tsx +11 -2
  383. package/src/Icon/Icon.doc.mjs +7 -5
  384. package/src/Icon/Icon.spec.md +81 -40
  385. package/src/Icon/Icon.test.tsx +6 -3
  386. package/src/Icon/Icon.tsx +20 -68
  387. package/src/Icon/IconDefaultSizeContext.ts +23 -0
  388. package/src/Icon/IconSize.stylex.ts +70 -0
  389. package/src/IconButton/IconButton.doc.mjs +3 -3
  390. package/src/IconButton/IconButton.test.tsx +40 -0
  391. package/src/Item/Item.doc.mjs +6 -2
  392. package/src/Item/Item.tsx +9 -3
  393. package/src/Kbd/Kbd.doc.mjs +3 -3
  394. package/src/Kbd/Kbd.test.tsx +57 -1
  395. package/src/Kbd/Kbd.tsx +57 -37
  396. package/src/Layout/LayoutFooter.doc.mjs +17 -0
  397. package/src/Link/Link.doc.mjs +17 -4
  398. package/src/Link/Link.test.tsx +24 -0
  399. package/src/Link/Link.tsx +5 -0
  400. package/src/Link/LinkProvider.doc.mjs +2 -2
  401. package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +261 -0
  402. package/src/Link/useLinkComponent.test.tsx +333 -0
  403. package/src/Link/useLinkComponent.ts +29 -57
  404. package/src/List/List.doc.mjs +6 -0
  405. package/src/List/List.spec.md +200 -0
  406. package/src/List/List.test.tsx +117 -1
  407. package/src/List/List.tsx +22 -2
  408. package/src/List/ListContext.tsx +3 -1
  409. package/src/List/ListItem.doc.mjs +2 -2
  410. package/src/List/ListItem.source-build.test.mjs +41 -0
  411. package/src/List/ListItem.tsx +26 -2
  412. package/src/Markdown/Markdown.doc.mjs +300 -2
  413. package/src/Markdown/Markdown.fr23.bench.ts +174 -0
  414. package/src/Markdown/Markdown.fr23.perf.test.ts +249 -0
  415. package/src/Markdown/Markdown.fr23.sampling.ts +49 -0
  416. package/src/Markdown/Markdown.helpers.perf.test.ts +489 -0
  417. package/src/Markdown/Markdown.public.test.ts +130 -3
  418. package/src/Markdown/Markdown.renderBoundary.test.tsx +72 -0
  419. package/src/Markdown/Markdown.spec.md +210 -45
  420. package/src/Markdown/Markdown.test.tsx +87 -3
  421. package/src/Markdown/Markdown.tsx +414 -135
  422. package/src/Markdown/ast.test.ts +307 -0
  423. package/src/Markdown/ast.ts +337 -0
  424. package/src/Markdown/incremental.test.ts +43 -0
  425. package/src/Markdown/index.ts +37 -1
  426. package/src/Markdown/modules/remark.spec.md +269 -0
  427. package/src/Markdown/modules/softBreaks.spec.md +137 -0
  428. package/src/Markdown/parser/index.ts +64 -0
  429. package/src/Markdown/parser.public.test.ts +103 -0
  430. package/src/Markdown/parser.test.ts +38 -6
  431. package/src/Markdown/parser.ts +1221 -242
  432. package/src/Markdown/plugins/frontmatter.test.tsx +125 -0
  433. package/src/Markdown/plugins/frontmatter.ts +198 -0
  434. package/src/Markdown/plugins/index.ts +54 -0
  435. package/src/Markdown/plugins/protocol.test.tsx +1022 -0
  436. package/src/Markdown/plugins/protocol.ts +1618 -0
  437. package/src/Markdown/plugins/semanticFence.test.tsx +546 -0
  438. package/src/Markdown/plugins/semanticFence.ts +424 -0
  439. package/src/Markdown/plugins/softBreaks.test.tsx +172 -0
  440. package/src/Markdown/plugins/softBreaks.ts +169 -0
  441. package/src/Markdown/plugins/sourceDecoration.test.tsx +799 -0
  442. package/src/Markdown/plugins/sourceDecoration.ts +539 -0
  443. package/src/Markdown/plugins/textTransform.test.ts +467 -0
  444. package/src/Markdown/plugins/textTransform.ts +554 -0
  445. package/src/Markdown/remark.test.tsx +1877 -0
  446. package/src/Markdown/remark.ts +1574 -0
  447. package/src/Markdown/url.ts +36 -0
  448. package/src/Markdown/utils.ts +13 -1
  449. package/src/MetadataList/MetadataList.test.tsx +4 -2
  450. package/src/MetadataList/MetadataList.tsx +3 -3
  451. package/src/MultiSelector/MultiSelector.test.tsx +1 -35
  452. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +128 -0
  453. package/src/NumberInput/NumberInput.tsx +6 -1
  454. package/src/Outline/Outline.doc.mjs +7 -5
  455. package/src/Outline/Outline.spec.md +1 -1
  456. package/src/Outline/index.ts +1 -0
  457. package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +142 -0
  458. package/src/Outline/parseOutlineFromMarkdown.ts +40 -10
  459. package/src/Outline/useOutlineFromMarkdown.ts +15 -3
  460. package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
  461. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +150 -1
  462. package/src/PowerSearch/PowerSearchEditPopover.tsx +51 -28
  463. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +51 -0
  464. package/src/PowerSearch/PowerSearchValueEditor.tsx +4 -0
  465. package/src/ProgressBar/ProgressBar.test.tsx +29 -11
  466. package/src/ProgressBar/ProgressBar.tsx +59 -72
  467. package/src/RadioList/RadioList.doc.mjs +11 -0
  468. package/src/RadioList/RadioList.test.tsx +32 -0
  469. package/src/RadioList/RadioListItem.tsx +25 -1
  470. package/src/ScrollableArea/ScrollableArea.tsx +1 -0
  471. package/src/ScrollableArea/modules/useScrollableArea.spec.md +50 -22
  472. package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
  473. package/src/SegmentedControl/SegmentedControl.test.tsx +61 -0
  474. package/src/SegmentedControl/SegmentedControl.tsx +2 -1
  475. package/src/SegmentedControl/SegmentedControlItem.tsx +6 -9
  476. package/src/Selector/Selector.doc.mjs +3 -3
  477. package/src/Selector/Selector.spec.md +51 -49
  478. package/src/Selector/Selector.test.tsx +61 -55
  479. package/src/Selector/Selector.tsx +34 -15
  480. package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +130 -0
  481. package/src/Selector/__tests__/Listbox.a11y.dom.ts +38 -0
  482. package/src/Selector/__tests__/Listbox.a11y.inventory.test.ts +63 -0
  483. package/src/Selector/__tests__/Listbox.a11y.known-failures.ts +37 -0
  484. package/src/Selector/__tests__/Listbox.a11y.states.ts +232 -0
  485. package/src/Selector/__tests__/Selector.a11y.chromium.spec.ts +45 -0
  486. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +121 -0
  487. package/src/SideNav/SideNav.doc.mjs +1 -1
  488. package/src/SideNav/SideNav.test.tsx +10 -0
  489. package/src/SideNav/SideNav.tsx +14 -2
  490. package/src/Slider/Slider.doc.mjs +17 -3
  491. package/src/Slider/Slider.test.tsx +221 -0
  492. package/src/Slider/Slider.tsx +40 -9
  493. package/src/Spinner/Spinner.test.tsx +4 -0
  494. package/src/Spinner/Spinner.tsx +31 -18
  495. package/src/Switch/Switch.doc.mjs +11 -0
  496. package/src/Switch/Switch.test.tsx +16 -0
  497. package/src/Switch/Switch.tsx +28 -0
  498. package/src/TabList/Tab.tsx +35 -7
  499. package/src/TabList/TabList.doc.mjs +11 -0
  500. package/src/TabList/TabList.spec.md +204 -0
  501. package/src/TabList/TabList.test.tsx +66 -0
  502. package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +1 -34
  503. package/src/Table/Table.doc.mjs +1 -1
  504. package/src/Table/Table.spec.md +54 -40
  505. package/src/Table/Table.test.tsx +83 -10
  506. package/src/Table/Table.tsx +30 -22
  507. package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +137 -0
  508. package/src/TextArea/TextArea.tsx +6 -1
  509. package/src/TextInput/TextInput.test.tsx +20 -1
  510. package/src/TextInput/TextInput.tsx +6 -1
  511. package/src/TimeInput/TimeInput.tsx +6 -1
  512. package/src/Timer/Timer.doc.mjs +183 -0
  513. package/src/Timer/Timer.spec.md +215 -0
  514. package/src/Timer/Timer.test.tsx +302 -0
  515. package/src/Timer/Timer.tsx +258 -0
  516. package/src/Timer/index.ts +11 -0
  517. package/src/ToggleButton/ToggleButton.doc.mjs +3 -3
  518. package/src/ToggleButton/ToggleButton.test.tsx +299 -4
  519. package/src/ToggleButton/ToggleButton.tsx +26 -33
  520. package/src/ToggleButton/ToggleButtonGroup.doc.mjs +3 -3
  521. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +209 -0
  522. package/src/Token/Token.doc.mjs +2 -2
  523. package/src/Tokenizer/Tokenizer.spec.md +142 -75
  524. package/src/TopNav/TopNavMenu.doc.mjs +2 -2
  525. package/src/TopNav/TopNavMenu.test.tsx +30 -0
  526. package/src/TopNav/TopNavMenu.tsx +7 -2
  527. package/src/TreeList/TreeList.doc.mjs +3 -3
  528. package/src/TreeList/TreeList.spec.md +123 -75
  529. package/src/TreeList/TreeList.test.tsx +29 -0
  530. package/src/TreeList/TreeList.tsx +3 -0
  531. package/src/TreeList/TreeListItem.tsx +15 -1
  532. package/src/TreeList/TreeListTypes.ts +11 -1
  533. package/src/Typeahead/BaseTypeahead.spec.md +4 -3
  534. package/src/Typeahead/BaseTypeahead.tsx +21 -7
  535. package/src/Typeahead/Typeahead.test.tsx +53 -0
  536. package/src/__tests__/PressedState.a11y.chromium.spec.ts +813 -0
  537. package/src/__tests__/pressState.ts +93 -0
  538. package/src/hooks/scrollKeyboardDelegation.test.ts +155 -0
  539. package/src/hooks/scrollKeyboardDelegation.ts +233 -0
  540. package/src/hooks/useClickableContainer.test.tsx +236 -0
  541. package/src/hooks/useClickableContainer.ts +20 -4
  542. package/src/hooks/useScrollableArea.doc.mjs +15 -3
  543. package/src/hooks/useScrollableArea.test.tsx +59 -1
  544. package/src/hooks/useScrollableArea.ts +34 -10
  545. package/src/index.ts +3 -0
  546. package/src/inputFontFloor.test.ts +106 -0
  547. package/src/tailwind-theme.css +0 -6
  548. package/src/theme/Theme.test.tsx +32 -0
  549. package/src/theme/declarationBoundary.test.ts +126 -0
  550. package/src/theme/declarationBoundary.ts +347 -0
  551. package/src/theme/derivedVarRegistry.test.ts +7 -0
  552. package/src/theme/derivedVarRegistry.ts +1 -0
  553. package/src/theme/generateThemeRules.test.ts +526 -1
  554. package/src/theme/generateThemeRules.ts +228 -50
  555. package/src/theme/tokenValueCompat.test.ts +4 -1
  556. package/src/utils/interactionOverlay.stylex.ts +20 -0
  557. package/src/utils/safeUrl.test.ts +88 -0
  558. package/src/utils/safeUrl.ts +85 -0
@@ -0,0 +1,36 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file url.ts
5
+ * @input Untrusted Markdown link or image destination
6
+ * @output Parser-compatible acceptance and normalized render-safe destinations
7
+ * @position Shared URL policy for parser, transforms, and renderer
8
+ */
9
+
10
+ import {isSafeUrl, sanitizeUrl} from '../utils/safeUrl';
11
+
12
+ const RENDER_DANGEROUS_URL_PATTERN = /^(?:javascript:|data:|vbscript:)/i;
13
+
14
+ function normalizeMarkdownUrl(url: string): string {
15
+ // Browsers ignore embedded controls in schemes, so normalize before checking.
16
+ // eslint-disable-next-line no-control-regex -- control chars are the bypass
17
+ return url.replace(/[\x00-\x1f\x7f]/g, '').trim();
18
+ }
19
+
20
+ /** Preserve the released parser policy for no-plugin output compatibility. */
21
+ export function isSafeMarkdownParserUrl(url: string): boolean {
22
+ return isSafeUrl(url);
23
+ }
24
+
25
+ /** Navigation and image rendering deliberately have different policies. */
26
+ export function sanitizeMarkdownLinkUrl(url: string): string | null {
27
+ const normalized = sanitizeUrl(url);
28
+ return normalized === '' ? null : normalized;
29
+ }
30
+
31
+ export function sanitizeMarkdownUrl(url: string): string | null {
32
+ const normalized = normalizeMarkdownUrl(url);
33
+ return normalized !== '' && !RENDER_DANGEROUS_URL_PATTERN.test(normalized)
34
+ ? normalized
35
+ : null;
36
+ }
@@ -2,10 +2,20 @@
2
2
 
3
3
  /**
4
4
  * @file utils.ts
5
- * @output Server-safe re-exports of pure Markdown parser functions
5
+ * @output Server-safe exports for Markdown parsing and AST traversal
6
6
  * @position Subpath entry point: `@astryxdesign/core/Markdown/utils`
7
7
  */
8
8
 
9
+ export {visitMarkdownNodes} from './ast';
10
+ export type {
11
+ MarkdownAstExtensionNode,
12
+ MarkdownAstPhrasingContent,
13
+ MarkdownAstBlockContent,
14
+ MarkdownAstRoot,
15
+ MarkdownAstNodeMap,
16
+ MarkdownAstNode,
17
+ } from './ast';
18
+
9
19
  export {
10
20
  parseMarkdown,
11
21
  parseInline,
@@ -26,5 +36,7 @@ export type {
26
36
  TableAlignment,
27
37
  ParseOptions,
28
38
  MathParseOptions,
39
+ IncrementalParseOptions,
40
+ IncrementalMathParseOptions,
29
41
  IncrementalState,
30
42
  } from './parser';
@@ -148,7 +148,9 @@ describe('MetadataList', () => {
148
148
  </MetadataList>,
149
149
  );
150
150
 
151
- expect(gridTemplateOf(container)).toContain('repeat(3, auto 1fr)');
151
+ expect(gridTemplateOf(container)).toContain(
152
+ 'repeat(3, auto minmax(0, 1fr))',
153
+ );
152
154
  });
153
155
 
154
156
  it('leaves the grid to the static rule for columns="multi"', () => {
@@ -178,7 +180,7 @@ describe('MetadataList', () => {
178
180
  </MetadataList>,
179
181
  );
180
182
 
181
- expect(gridTemplateOf(container)).toContain('120px 1fr');
183
+ expect(gridTemplateOf(container)).toContain('120px minmax(0, 1fr)');
182
184
  });
183
185
  });
184
186
  });
@@ -113,7 +113,7 @@ const styles = stylex.create({
113
113
  // Vertical orientation — grid layout for label-value pairs
114
114
  gridSingle: {
115
115
  display: 'grid',
116
- gridTemplateColumns: 'auto 1fr',
116
+ gridTemplateColumns: 'auto minmax(0, 1fr)',
117
117
  gap: `${spacingVars['--spacing-2']} ${spacingVars['--spacing-4']}`,
118
118
  alignItems: 'baseline',
119
119
  },
@@ -263,7 +263,7 @@ export function MetadataList({
263
263
  if (typeof columns === 'number' && columns > 1) {
264
264
  return isStacked
265
265
  ? `repeat(${columns}, 1fr)`
266
- : `repeat(${columns}, auto 1fr)`;
266
+ : `repeat(${columns}, auto minmax(0, 1fr))`;
267
267
  }
268
268
  // A custom label width only applies to the label track of side labels.
269
269
  if (!isStacked && labelConfig.width != null) {
@@ -271,7 +271,7 @@ export function MetadataList({
271
271
  typeof labelConfig.width === 'number'
272
272
  ? `${labelConfig.width}px`
273
273
  : labelConfig.width;
274
- return `${width} 1fr`;
274
+ return `${width} minmax(0, 1fr)`;
275
275
  }
276
276
  return null;
277
277
  };
@@ -478,39 +478,6 @@ describe('MultiSelector', () => {
478
478
  expect(trigger).toHaveAttribute('aria-required', 'true');
479
479
  });
480
480
 
481
- it('renders listbox with aria-multiselectable', async () => {
482
- const user = userEvent.setup();
483
- render(
484
- <MultiSelector
485
- label="Fruit"
486
- options={defaultOptions}
487
- value={[]}
488
- onChange={() => {}}
489
- />,
490
- );
491
-
492
- await user.click(screen.getByRole('combobox'));
493
- const listbox = screen.getByRole('listbox', h);
494
- expect(listbox).toHaveAttribute('aria-multiselectable', 'true');
495
- });
496
-
497
- it('marks selected options with aria-selected', async () => {
498
- const user = userEvent.setup();
499
- render(
500
- <MultiSelector
501
- label="Fruit"
502
- options={defaultOptions}
503
- value={['Apple']}
504
- onChange={() => {}}
505
- />,
506
- );
507
-
508
- await user.click(screen.getByRole('combobox'));
509
- const options = screen.getAllByRole('option', h);
510
- expect(options[0]).toHaveAttribute('aria-selected', 'true');
511
- expect(options[1]).toHaveAttribute('aria-selected', 'false');
512
- });
513
-
514
481
  it('shows error status with aria-invalid', () => {
515
482
  render(
516
483
  <MultiSelector
@@ -1393,8 +1360,7 @@ describe('MultiSelector', () => {
1393
1360
  await user.click(screen.getByRole('combobox'));
1394
1361
  const options = screen.getAllByRole('option', h);
1395
1362
  expect(options).toHaveLength(3);
1396
- const group = screen.getByRole('group', h);
1397
- expect(group).toHaveAttribute('aria-label', 'Citrus');
1363
+ expect(screen.getByText('Citrus')).toBeInTheDocument();
1398
1364
  });
1399
1365
 
1400
1366
  it('shows loading state with a spinner and aria-busy', () => {
@@ -0,0 +1,128 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file MultiSelector.listbox.a11y.test.tsx
5
+ * @input Uses MultiSelector, its part/state inventory, and the shared Listbox contract
6
+ * @output DOM evidence for real multi-select listbox, group, and option parts
7
+ * @position Component-facing binding; API, form, composition, and styling stay local.
8
+ */
9
+
10
+ import {cleanup, render, screen, within} from '@testing-library/react';
11
+ import userEvent from '@testing-library/user-event';
12
+ import {describe, expect, it} from 'vitest';
13
+ import {
14
+ expectAccessibilitySpec,
15
+ LISTBOX_PATTERN,
16
+ } from '@astryxdesign/a11y-spec';
17
+ import {MultiSelector} from '../MultiSelector';
18
+ import {
19
+ LISTBOX_SCENARIOS,
20
+ listboxParts,
21
+ } from '../../Selector/__tests__/Listbox.a11y.states';
22
+ import {installListboxDialogStubs} from '../../Selector/__tests__/Listbox.a11y.dom';
23
+
24
+ installListboxDialogStubs();
25
+
26
+ const scenarios = LISTBOX_SCENARIOS.filter(
27
+ scenario => scenario.component === 'MultiSelector',
28
+ );
29
+
30
+ describe('MultiSelector Listbox semantic binding', () => {
31
+ it.each(scenarios)('$id', async scenario => {
32
+ for (const part of listboxParts(scenario)) {
33
+ await expectAccessibilitySpec({
34
+ spec: LISTBOX_PATTERN,
35
+ binding: `MultiSelector.${part.role}`,
36
+ state: part.state,
37
+ facts: part.facts,
38
+ render: async () => {
39
+ render(
40
+ <div dir={scenario.direction ?? 'ltr'}>
41
+ <MultiSelector
42
+ label="Fruit"
43
+ options={scenario.options}
44
+ value={scenario.values}
45
+ onChange={() => {}}
46
+ hasSearch={scenario.hasSearch}
47
+ hasSelectAll={scenario.hasSelectAll}
48
+ presentation={scenario.presentation}
49
+ isLoading={scenario.isLoading}
50
+ isLabelHidden={scenario.hiddenLabel}
51
+ renderOption={
52
+ scenario.customContent
53
+ ? option => <span>{option.label} details</span>
54
+ : undefined
55
+ }
56
+ isDefaultOpen
57
+ />
58
+ </div>,
59
+ );
60
+ await screen.findByRole('listbox', {hidden: true});
61
+ if (scenario.query != null) {
62
+ await userEvent
63
+ .setup()
64
+ .type(
65
+ screen.getByRole('combobox', {hidden: true}),
66
+ scenario.query,
67
+ );
68
+ }
69
+ },
70
+ subject: () =>
71
+ part.role === 'listbox'
72
+ ? screen.getByRole('listbox', {hidden: true})
73
+ : part.role === 'group'
74
+ ? within(
75
+ screen.getByRole('listbox', {hidden: true}),
76
+ ).getAllByRole('group', {hidden: true})[
77
+ scenario.groups.indexOf(part.name ?? '')
78
+ ]
79
+ : within(screen.getByRole('listbox', {hidden: true})).getByRole(
80
+ 'option',
81
+ {name: part.name, hidden: true},
82
+ ),
83
+ related: () => {
84
+ const listbox = screen.getByRole('listbox', {hidden: true});
85
+ expect(
86
+ within(listbox).getAllByRole('option', {hidden: true}),
87
+ ).toHaveLength(scenario.expectedOptions.length);
88
+ return {
89
+ listbox,
90
+ ...Object.fromEntries(
91
+ scenario.expectedOptions.map(option => [
92
+ `option:${option.value}`,
93
+ within(listbox).getByRole('option', {
94
+ name: option.name,
95
+ hidden: true,
96
+ }),
97
+ ]),
98
+ ),
99
+ ...Object.fromEntries(
100
+ scenario.groups.map((name, index) => [
101
+ `group:${name}`,
102
+ within(listbox).getAllByRole('group', {hidden: true})[index],
103
+ ]),
104
+ ),
105
+ };
106
+ },
107
+ cleanup,
108
+ });
109
+ }
110
+ });
111
+
112
+ it('keeps the bounded state matrix and select-all states explicit', () => {
113
+ expect(scenarios.map(scenario => scenario.id)).toEqual([
114
+ 'multiple-unset',
115
+ 'multiple-selected',
116
+ 'multiple-disabled-selected',
117
+ 'multiple-grouped',
118
+ 'multiple-filtered',
119
+ 'multiple-custom-rtl',
120
+ 'multiple-sheet',
121
+ 'multiple-sheet-search',
122
+ 'multiple-loading',
123
+ 'multiple-select-all-none',
124
+ 'multiple-select-all-partial',
125
+ 'multiple-select-all-all',
126
+ ]);
127
+ });
128
+ });
@@ -105,9 +105,14 @@ const styles = stylex.create({
105
105
  borderStyle: 'none',
106
106
  padding: 0,
107
107
  fontFamily: typographyVars['--font-family-body'],
108
+ // The 16px floor is iOS-only: iOS Safari zooms the page when a focused
109
+ // control sits under 16px, and only iOS WebKit implements
110
+ // -webkit-touch-callout to key the coarse-pointer floor to it.
108
111
  fontSize: {
109
112
  default: typeScaleVars['--text-body-size'],
110
- '@media (pointer: coarse)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
113
+ '@media (pointer: coarse)': {
114
+ '@supports (-webkit-touch-callout: none)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
115
+ },
111
116
  },
112
117
  lineHeight: typeScaleVars['--text-body-leading'],
113
118
  color: colorVars['--color-text-primary'],
@@ -196,11 +196,13 @@ function ControlledOutline() {
196
196
  code: `
197
197
  import {Outline, useOutlineFromMarkdown} from '@astryxdesign/core/Outline';
198
198
 
199
- function MarkdownOutline({markdown}) {
200
- // Derives {id, label, level} items from headings in the source.
201
- // The Markdown component renders the same generated ids on its
202
- // headings, so outline links scroll without any extra wiring.
203
- const items = useOutlineFromMarkdown(markdown);
199
+ function MarkdownOutline({markdown, plugins, isStreaming}) {
200
+ // Pass the same plugins and finality to Markdown and Outline so transformed
201
+ // headings share labels and ids while content streams.
202
+ const items = useOutlineFromMarkdown(markdown, {
203
+ plugins,
204
+ isFinal: !isStreaming,
205
+ });
204
206
  return <Outline items={items} />;
205
207
  }
206
208
  `,
@@ -12,7 +12,7 @@ owners: [cixzhang]
12
12
  review_triggers: [theming]
13
13
  verified_by:
14
14
  [packages/core/src/Outline/Outline.test.tsx, scripts/check-knowledge.mjs]
15
- modules: []
15
+ modules: [module:Outline/parseOutlineFromMarkdown]
16
16
  families: []
17
17
  design_specs: []
18
18
  architecture: [architecture:component-theming-surface]
@@ -15,5 +15,6 @@ export {Outline} from './Outline';
15
15
  export type {OutlineProps} from './Outline';
16
16
  export type {OutlineItem} from './types';
17
17
  export {parseOutlineFromMarkdown} from './parseOutlineFromMarkdown';
18
+ export type {ParseOutlineFromMarkdownOptions} from './parseOutlineFromMarkdown';
18
19
  export {useOutlineFromMarkdown} from './useOutlineFromMarkdown';
19
20
  export {useOutlineFromDOM} from './useOutlineFromDOM';
@@ -0,0 +1,142 @@
1
+ ---
2
+ schema_version: 3
3
+ template_version: 1
4
+ kind: module
5
+ id: module:Outline/parseOutlineFromMarkdown
6
+ authority: current
7
+ archive_reason: null
8
+ superseded_by: null
9
+ approved_by: cixzhang
10
+ approved_at: 2026-09-15
11
+ owners: [cixzhang]
12
+ review_triggers: [public-api, behavior]
13
+ verified_by: [packages/core/src/Outline/parseOutlineFromMarkdown.test.ts]
14
+ parent_component: component:Outline
15
+ references:
16
+ [architecture:public-component-api, component:Markdown, spec:AST-036]
17
+ ---
18
+
19
+ # parseOutlineFromMarkdown module contract
20
+
21
+ ## Intent
22
+
23
+ `parseOutlineFromMarkdown` and `useOutlineFromMarkdown` derive same-document
24
+ heading navigation from the same Markdown parse configuration, ordered immutable
25
+ transforms, text projection, and collision allocator used by the rendered document.
26
+ This focused module owns that utility behavior without deciding the draft Outline
27
+ component's anatomy or theming.
28
+
29
+ ## Compatibility and migration
30
+
31
+ - Released default preserved: `yes`
32
+ - Compatibility class: additive parser options; calls without plugins preserve
33
+ released labels, levels, IDs, and return types
34
+ - Migration decision: `spec:AST-036`
35
+
36
+ ## Ownership boundary
37
+
38
+ **Owns**
39
+
40
+ - Deriving ordered `OutlineItem` values from Markdown headings.
41
+ - Accepting the same parser-affecting options and ordered plugin list as Markdown.
42
+ - Applying the same validated immutable transforms before selecting headings.
43
+ - Using the same extension text projection and collision-safe slug allocation as
44
+ Markdown heading rendering.
45
+
46
+ **Does not own / non-goals**
47
+
48
+ - Outline component structure, active state, targets, layout, or theming.
49
+ - Plugin rendering, block-extension navigation entries, or renderer-derived text.
50
+ - A second parser, plugin registry, or independent heading-ID policy.
51
+
52
+ ## Public API and concepts
53
+
54
+ `parseOutlineFromMarkdown(source, options?)` performs direct derivation.
55
+ `useOutlineFromMarkdown(source, options?)` memoizes the same derivation for React
56
+ callers. `options.plugins` uses the canonical opaque Markdown plugin entries. The
57
+ same ordered transforms run before heading selection; inline extension-node `toText`
58
+ projections then contribute to heading labels and IDs.
59
+
60
+ ## Behavioral contract
61
+
62
+ | ID | Invariant | Basis | Acceptance and implementation state |
63
+ | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ----------------------------------- |
64
+ | FR1 | Both utilities accept the same Markdown parser options and ordered plugin list as the rendered Markdown document. | `spec:AST-036` FR13, FR16 | pending implementation |
65
+ | FR2 | Both utilities apply the same validated immutable transforms before selecting headings, without allowing renderer output to affect identity. | `spec:AST-036` FR13, FR16 | pending implementation |
66
+ | FR3 | Plugin-enabled labels and IDs use the same extension `toText` projection, slugger, and cross-base collision allocator as Markdown, producing unique matching targets. | `spec:AST-036` FR16 | pending implementation |
67
+ | FR4 | An extension node never creates an Outline entry of its own, and extension containers do not change heading traversal: entries come from the same blocks Markdown assigns heading IDs to, so a heading nested in a container is omitted exactly as one nested in a blockquote or list item is. A container never restarts, extends, or re-scopes heading identity or slug allocation. | `spec:AST-036` FR16, FR25 | pending implementation |
68
+ | FR5 | Omitting plugins and passing an empty list preserve released heading selection, labels, levels, IDs, return type, and memoization behavior. | `spec:AST-036` FR2 | pending implementation |
69
+ | FR6 | The hook memoizes against source and every parse-affecting or transform-affecting option so changed configuration cannot return stale headings. | `component:Markdown` FR15–FR16 | pending implementation |
70
+ | FR7 | A transform that removes a heading removes its Outline entry, and a transform that inserts a synthetic heading adds one, in both surfaces identically. Source-backed heading depth cannot change, so an entry's level always matches the rendered heading. | `spec:AST-036` FR26 | pending implementation |
71
+ | FR8 | When a plugin fails, derivation uses the same last valid root the rendered document uses, so labels, levels, and IDs still agree. Failures are reported through the shared diagnostic channel; this module adds no failure mode, fallback, or throw of its own. | `spec:AST-036` FR12, FR29 | pending implementation |
72
+ | FR9 | Derivation runs on the canonical tree through the shared parse path and requires no DOM, renderer, client boundary, or second parser. Because transforms are idempotent under streaming, an outline derived from a growing source prefix converges rather than oscillates. | `spec:AST-036` FR32, FR33, FR36 | pending implementation |
73
+
74
+ ### Transformation and precedence order
75
+
76
+ Markdown parse configuration → ordered immutable transforms → heading nodes →
77
+ shared perceivable-text projection → shared slug normalization → document-order
78
+ collision allocation → Outline items.
79
+
80
+ ### Performance and resources
81
+
82
+ - The hook recomputes only when source or parser/transform configuration changes.
83
+ - Renderer output does not enter heading identity.
84
+ - No DOM, renderer mount, registry, Remark runtime, or optional plugin resource is
85
+ required.
86
+
87
+ ## Accessibility contract
88
+
89
+ Each derived label is the same perceivable heading text used for Markdown identity,
90
+ and each derived ID targets the matching rendered heading. This module adds no
91
+ interaction or ARIA behavior; the Outline component owns navigation presentation.
92
+
93
+ ## Design relationships
94
+
95
+ No visual representation is owned by this parser utility.
96
+
97
+ ## Parent and system relationships
98
+
99
+ - `component:Markdown` owns aggregate parsing, heading rendering, and the shared
100
+ projection/collision rules.
101
+ - `spec:AST-036` owns the canonical plugin protocol and cross-surface parity.
102
+ - Draft `component:Outline` owns presentation only after its separate anatomy and
103
+ theming decisions become current.
104
+
105
+ ## Verification map
106
+
107
+ | Contract | Verification | Representative states | Mutation or failure expectation |
108
+ | -------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
109
+ | FR1–FR6 | Outline parser tests, plugin transform parity tests, and Core typecheck | transformed, formatted, and extension headings; headings nested in extension containers, blockquotes, and list items; duplicate and cross-base slugs; omitted/empty plugins | A transform is skipped, a label/ID diverges from Markdown, a container changes which headings have identity, or default output changes. |
110
+ | FR7–FR9 | Heading insert/remove parity, failure parity, and streaming derivation | headings removed with/without sections; inserted synthetic headings; failing transform; growing source prefix; server derivation | Outline/document disagreement, divergent fallback, a throw, stale IDs, or streamed oscillation. |
111
+
112
+ ## Decision log
113
+
114
+ ### DEC-1 — Markdown owns heading identity; Outline projects it
115
+
116
+ **Reference:** `module:Outline/parseOutlineFromMarkdown/DEC-1`
117
+ **Decider:** cixzhang, 2026-09-15
118
+
119
+ Outline utilities consume Markdown's parse configuration, ordered transforms, text
120
+ projection, and collision allocator rather than defining a second heading-identity
121
+ system. This keeps labels and link targets aligned without coupling plugin renderer
122
+ output to navigation identity.
123
+
124
+ ### DEC-2 — One traversal survives containers and heading edits
125
+
126
+ **Reference:** `module:Outline/parseOutlineFromMarkdown/DEC-2`
127
+ **Decider:** cixzhang, 2026-09-16
128
+
129
+ Extension containers hold ordinary Markdown but do not change which headings have identity. Markdown assigns IDs by one traversal and this module reads the same one, so Outline never links to a heading Markdown did not identify. A heading inside a container remains omitted like one inside a blockquote or list item, and the extension node is never an Outline entry. Widening traversal is a separate decision.
130
+
131
+ Transforms may remove and insert headings, so Outline follows the rendered document rather than source: a dropped heading disappears, an inserted heading appears, and immutable source-backed depth keeps levels aligned. Both surfaces run the same pipeline rather than independent rules.
132
+
133
+ Rejected: a container-only traversal exception; extension nodes as Outline entries; source-only derivation; module-local plugin failure fallback.
134
+
135
+ ## Open questions
136
+
137
+ None.
138
+
139
+ ## Content boundary
140
+
141
+ This file does not duplicate plugin protocol details, Markdown parser mechanics,
142
+ consumer examples, or the draft Outline component's anatomy and theming contract.
@@ -2,10 +2,9 @@
2
2
 
3
3
  /**
4
4
  * @file parseOutlineFromMarkdown.ts
5
- * @input Uses Markdown parser internals (parseMarkdown + heading slug
6
- * helpers) and OutlineItem type
5
+ * @input Uses Markdown's canonical AST parser and heading slug helpers
7
6
  * @output Exports parseOutlineFromMarkdown for extracting heading outlines from Markdown
8
- * @position Pure utility; consumed by useOutlineFromMarkdown and public exports
7
+ * @position Pure compatibility utility; consumed by useOutlineFromMarkdown and public exports
9
8
  *
10
9
  * SYNC: When modified, update these files to stay in sync:
11
10
  * - /packages/core/src/Outline/Outline.doc.mjs
@@ -13,11 +12,19 @@
13
12
  */
14
13
 
15
14
  import {
16
- parseMarkdown,
17
- inlineText,
15
+ parseMarkdownAstInternal,
18
16
  slugify,
19
17
  uniqueSlug,
20
18
  } from '../Markdown/parser';
19
+ import {markdownAstText} from '../Markdown/ast';
20
+ import {
21
+ markdownExtensionText,
22
+ prepareMarkdownPlugins,
23
+ } from '../Markdown/plugins/protocol';
24
+ import type {
25
+ MarkdownExtensionNode,
26
+ MarkdownPluginEntry,
27
+ } from '../Markdown/plugins/protocol';
21
28
  import type {OutlineItem} from './types';
22
29
 
23
30
  /**
@@ -28,16 +35,39 @@ import type {OutlineItem} from './types';
28
35
  * Ids come from the parser's shared slug helpers, so they always match the
29
36
  * `id` attributes Markdown renders on its headings.
30
37
  */
31
- export function parseOutlineFromMarkdown(markdown: string): OutlineItem[] {
38
+ export interface ParseOutlineFromMarkdownOptions<
39
+ Node extends MarkdownExtensionNode = never,
40
+ > {
41
+ readonly plugins?: ReadonlyArray<MarkdownPluginEntry<Node>>;
42
+ /** Match Markdown's transform finality while content is streaming. */
43
+ readonly isFinal?: boolean;
44
+ }
45
+
46
+ export function parseOutlineFromMarkdown<
47
+ Node extends MarkdownExtensionNode = never,
48
+ >(
49
+ markdown: string,
50
+ options?: ParseOutlineFromMarkdownOptions<Node>,
51
+ ): OutlineItem[] {
52
+ const prepared =
53
+ options?.plugins == null
54
+ ? undefined
55
+ : prepareMarkdownPlugins(options.plugins);
32
56
  const counts = new Map<string, number>();
33
- return parseMarkdown(markdown)
34
- .filter(block => block.type === 'heading')
57
+ return parseMarkdownAstInternal(
58
+ markdown,
59
+ {plugins: options?.plugins},
60
+ options?.isFinal ?? true,
61
+ )
62
+ .children.filter(block => block.type === 'heading')
35
63
  .map(block => {
36
- const label = inlineText(block.children).trim();
64
+ const label = markdownAstText(block.children, node =>
65
+ markdownExtensionText(prepared, node),
66
+ ).trim();
37
67
  return {
38
68
  id: uniqueSlug(slugify(label), counts),
39
69
  label,
40
- level: block.level,
70
+ level: block.depth,
41
71
  };
42
72
  });
43
73
  }
@@ -4,7 +4,7 @@
4
4
 
5
5
  /**
6
6
  * @file useOutlineFromMarkdown.ts
7
- * @input Uses React, parseOutlineFromMarkdown
7
+ * @input Uses React, parseOutlineFromMarkdown, and optional Markdown plugins
8
8
  * @output Exports useOutlineFromMarkdown hook
9
9
  * @position Hook utility; consumed by applications and Outline examples
10
10
  *
@@ -15,9 +15,21 @@
15
15
 
16
16
  import {useMemo} from 'react';
17
17
  import {parseOutlineFromMarkdown} from './parseOutlineFromMarkdown';
18
+ import type {ParseOutlineFromMarkdownOptions} from './parseOutlineFromMarkdown';
19
+ import type {MarkdownExtensionNode} from '../Markdown/plugins/protocol';
18
20
  import type {OutlineItem} from './types';
19
21
 
20
22
  /** Extract a stable outline from a Markdown string. */
21
- export function useOutlineFromMarkdown(markdown: string): OutlineItem[] {
22
- return useMemo(() => parseOutlineFromMarkdown(markdown), [markdown]);
23
+ export function useOutlineFromMarkdown<
24
+ Node extends MarkdownExtensionNode = never,
25
+ >(
26
+ markdown: string,
27
+ options?: ParseOutlineFromMarkdownOptions<Node>,
28
+ ): OutlineItem[] {
29
+ const plugins = options?.plugins;
30
+ const isFinal = options?.isFinal;
31
+ return useMemo(
32
+ () => parseOutlineFromMarkdown(markdown, {plugins, isFinal}),
33
+ [markdown, plugins, isFinal],
34
+ );
23
35
  }
@@ -188,12 +188,12 @@ export const docs = {
188
188
  },
189
189
  {
190
190
  name: 'onFocus',
191
- type: '(e: FocusEvent<HTMLInputElement>) => void',
191
+ type: '(e: React.FocusEvent) => void',
192
192
  description: 'Fires when focus enters the search input.',
193
193
  },
194
194
  {
195
195
  name: 'onBlur',
196
- type: '(e: FocusEvent<HTMLInputElement>) => void',
196
+ type: '(e: React.FocusEvent) => void',
197
197
  description: 'Fires when focus leaves the search input.',
198
198
  },
199
199
  {