@astryxdesign/core 0.6.2 → 0.6.3-canary.0899f21

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 (549) 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.js +1 -1
  36. package/dist/Chat/index.d.ts +1 -1
  37. package/dist/Chat/index.d.ts.map +1 -1
  38. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  39. package/dist/CheckboxInput/CheckboxInput.js +12 -2
  40. package/dist/Citation/Citation.d.ts +1 -1
  41. package/dist/Citation/Citation.d.ts.map +1 -1
  42. package/dist/Citation/Citation.js +3 -2
  43. package/dist/CodeBlock/highlightRanges.d.ts.map +1 -1
  44. package/dist/CodeBlock/highlightRanges.js +14 -3
  45. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  46. package/dist/Collapsible/Collapsible.js +6 -1
  47. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  48. package/dist/CommandPalette/CommandPaletteInput.js +1 -1
  49. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  50. package/dist/ComplexSelector/ComplexSelector.js +1 -1
  51. package/dist/DateInput/DateInput.d.ts.map +1 -1
  52. package/dist/DateInput/DateInput.js +4 -4
  53. package/dist/DateInput/NativeDateField.d.ts.map +1 -1
  54. package/dist/DateInput/NativeDateField.js +16 -16
  55. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  56. package/dist/DateInput/TouchDateField.js +2 -2
  57. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  58. package/dist/DateRangeInput/DateRangeInput.js +4 -4
  59. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  60. package/dist/DateTimeInput/DateTimeInput.js +8 -8
  61. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  62. package/dist/DateTimeInput/TouchDateTimeField.js +4 -4
  63. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +9 -3
  64. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -1
  65. package/dist/DateTimeInput/nativePickerSegmentStyles.js +3 -3
  66. package/dist/Dialog/DialogHeader.d.ts +8 -1
  67. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  68. package/dist/Dialog/DialogHeader.js +13 -4
  69. package/dist/Field/InputClearButton.d.ts +4 -2
  70. package/dist/Field/InputClearButton.d.ts.map +1 -1
  71. package/dist/Field/InputClearButton.js +4 -2
  72. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  73. package/dist/Field/PanelSearchInput.js +1 -1
  74. package/dist/FileInput/FileInput.d.ts.map +1 -1
  75. package/dist/FileInput/FileInput.js +7 -7
  76. package/dist/Icon/Icon.d.ts +6 -31
  77. package/dist/Icon/Icon.d.ts.map +1 -1
  78. package/dist/Icon/Icon.js +8 -71
  79. package/dist/Icon/IconDefaultSizeContext.d.ts +4 -0
  80. package/dist/Icon/IconDefaultSizeContext.d.ts.map +1 -0
  81. package/dist/Icon/IconDefaultSizeContext.js +18 -0
  82. package/dist/Icon/IconSize.stylex.d.ts +65 -0
  83. package/dist/Icon/IconSize.stylex.d.ts.map +1 -0
  84. package/dist/Icon/IconSize.stylex.js +75 -0
  85. package/dist/Item/Item.d.ts +1 -1
  86. package/dist/Item/Item.d.ts.map +1 -1
  87. package/dist/Item/Item.js +4 -3
  88. package/dist/Kbd/Kbd.d.ts +5 -3
  89. package/dist/Kbd/Kbd.d.ts.map +1 -1
  90. package/dist/Kbd/Kbd.js +36 -42
  91. package/dist/Link/Link.d.ts.map +1 -1
  92. package/dist/Link/Link.js +6 -2
  93. package/dist/Link/useLinkComponent.d.ts +5 -15
  94. package/dist/Link/useLinkComponent.d.ts.map +1 -1
  95. package/dist/Link/useLinkComponent.js +34 -51
  96. package/dist/List/List.d.ts +19 -1
  97. package/dist/List/List.d.ts.map +1 -1
  98. package/dist/List/List.js +9 -2
  99. package/dist/List/ListContext.d.ts +1 -0
  100. package/dist/List/ListContext.d.ts.map +1 -1
  101. package/dist/List/ListContext.js +2 -1
  102. package/dist/List/ListItem.d.ts +1 -1
  103. package/dist/List/ListItem.d.ts.map +1 -1
  104. package/dist/List/ListItem.js +9 -2
  105. package/dist/Markdown/Markdown.d.ts +8 -2
  106. package/dist/Markdown/Markdown.d.ts.map +1 -1
  107. package/dist/Markdown/Markdown.fr23.bench.d.ts +2 -0
  108. package/dist/Markdown/Markdown.fr23.bench.d.ts.map +1 -0
  109. package/dist/Markdown/Markdown.fr23.bench.js +150 -0
  110. package/dist/Markdown/Markdown.fr23.sampling.d.ts +2 -0
  111. package/dist/Markdown/Markdown.fr23.sampling.d.ts.map +1 -0
  112. package/dist/Markdown/Markdown.fr23.sampling.js +43 -0
  113. package/dist/Markdown/Markdown.js +262 -109
  114. package/dist/Markdown/ast.d.ts +162 -0
  115. package/dist/Markdown/ast.d.ts.map +1 -0
  116. package/dist/Markdown/ast.js +74 -0
  117. package/dist/Markdown/index.d.ts +5 -3
  118. package/dist/Markdown/index.d.ts.map +1 -1
  119. package/dist/Markdown/index.js +3 -2
  120. package/dist/Markdown/parser/index.d.ts +10 -0
  121. package/dist/Markdown/parser/index.d.ts.map +1 -0
  122. package/dist/Markdown/parser/index.js +10 -0
  123. package/dist/Markdown/parser.d.ts +126 -58
  124. package/dist/Markdown/parser.d.ts.map +1 -1
  125. package/dist/Markdown/parser.js +716 -167
  126. package/dist/Markdown/plugins/frontmatter.d.ts +32 -0
  127. package/dist/Markdown/plugins/frontmatter.d.ts.map +1 -0
  128. package/dist/Markdown/plugins/frontmatter.js +132 -0
  129. package/dist/Markdown/plugins/index.d.ts +17 -0
  130. package/dist/Markdown/plugins/index.d.ts.map +1 -0
  131. package/dist/Markdown/plugins/index.js +14 -0
  132. package/dist/Markdown/plugins/protocol.d.ts +191 -0
  133. package/dist/Markdown/plugins/protocol.d.ts.map +1 -0
  134. package/dist/Markdown/plugins/protocol.js +957 -0
  135. package/dist/Markdown/plugins/semanticFence.d.ts +36 -0
  136. package/dist/Markdown/plugins/semanticFence.d.ts.map +1 -0
  137. package/dist/Markdown/plugins/semanticFence.js +213 -0
  138. package/dist/Markdown/plugins/softBreaks.d.ts +3 -0
  139. package/dist/Markdown/plugins/softBreaks.d.ts.map +1 -0
  140. package/dist/Markdown/plugins/softBreaks.js +172 -0
  141. package/dist/Markdown/plugins/sourceDecoration.d.ts +76 -0
  142. package/dist/Markdown/plugins/sourceDecoration.d.ts.map +1 -0
  143. package/dist/Markdown/plugins/sourceDecoration.js +393 -0
  144. package/dist/Markdown/plugins/textTransform.d.ts +30 -0
  145. package/dist/Markdown/plugins/textTransform.d.ts.map +1 -0
  146. package/dist/Markdown/plugins/textTransform.js +374 -0
  147. package/dist/Markdown/remark.d.ts +196 -0
  148. package/dist/Markdown/remark.d.ts.map +1 -0
  149. package/dist/Markdown/remark.js +1062 -0
  150. package/dist/Markdown/url.d.ts +6 -0
  151. package/dist/Markdown/url.d.ts.map +1 -0
  152. package/dist/Markdown/url.js +31 -0
  153. package/dist/Markdown/utils.d.ts +4 -2
  154. package/dist/Markdown/utils.d.ts.map +1 -1
  155. package/dist/Markdown/utils.js +2 -1
  156. package/dist/MetadataList/MetadataList.js +3 -3
  157. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  158. package/dist/NumberInput/NumberInput.js +4 -4
  159. package/dist/Outline/index.d.ts +1 -0
  160. package/dist/Outline/index.d.ts.map +1 -1
  161. package/dist/Outline/parseOutlineFromMarkdown.d.ts +7 -1
  162. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  163. package/dist/Outline/parseOutlineFromMarkdown.js +14 -8
  164. package/dist/Outline/useOutlineFromMarkdown.d.ts +3 -1
  165. package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
  166. package/dist/Outline/useOutlineFromMarkdown.js +8 -3
  167. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  168. package/dist/PowerSearch/PowerSearchEditPopover.js +46 -30
  169. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  170. package/dist/PowerSearch/PowerSearchValueEditor.js +5 -0
  171. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  172. package/dist/ProgressBar/ProgressBar.js +36 -31
  173. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  174. package/dist/RadioList/RadioListItem.js +13 -1
  175. package/dist/ScrollableArea/ScrollableArea.d.ts +1 -0
  176. package/dist/ScrollableArea/ScrollableArea.d.ts.map +1 -1
  177. package/dist/ScrollableArea/ScrollableArea.js +1 -0
  178. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  179. package/dist/SegmentedControl/SegmentedControlItem.js +5 -5
  180. package/dist/Selector/Selector.d.ts +9 -7
  181. package/dist/Selector/Selector.d.ts.map +1 -1
  182. package/dist/Selector/Selector.js +16 -7
  183. package/dist/SideNav/SideNav.d.ts +2 -1
  184. package/dist/SideNav/SideNav.d.ts.map +1 -1
  185. package/dist/SideNav/SideNav.js +9 -3
  186. package/dist/Slider/Slider.d.ts.map +1 -1
  187. package/dist/Slider/Slider.js +28 -12
  188. package/dist/Spinner/Spinner.d.ts.map +1 -1
  189. package/dist/Spinner/Spinner.js +23 -7
  190. package/dist/Switch/Switch.d.ts.map +1 -1
  191. package/dist/Switch/Switch.js +11 -0
  192. package/dist/TabList/Tab.d.ts +1 -1
  193. package/dist/TabList/Tab.d.ts.map +1 -1
  194. package/dist/TabList/Tab.js +20 -7
  195. package/dist/Table/Table.d.ts +1 -0
  196. package/dist/Table/Table.d.ts.map +1 -1
  197. package/dist/Table/Table.js +29 -13
  198. package/dist/TextArea/TextArea.d.ts.map +1 -1
  199. package/dist/TextArea/TextArea.js +1 -1
  200. package/dist/TextInput/TextInput.d.ts.map +1 -1
  201. package/dist/TextInput/TextInput.js +2 -2
  202. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  203. package/dist/TimeInput/TimeInput.js +4 -4
  204. package/dist/Timer/Timer.d.ts +49 -0
  205. package/dist/Timer/Timer.d.ts.map +1 -0
  206. package/dist/Timer/Timer.js +158 -0
  207. package/dist/Timer/index.d.ts +9 -0
  208. package/dist/Timer/index.d.ts.map +1 -0
  209. package/dist/Timer/index.js +10 -0
  210. package/dist/ToggleButton/ToggleButton.d.ts +9 -6
  211. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  212. package/dist/ToggleButton/ToggleButton.js +15 -27
  213. package/dist/TopNav/TopNavMenu.d.ts +1 -1
  214. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  215. package/dist/TopNav/TopNavMenu.js +3 -2
  216. package/dist/TreeList/TreeList.d.ts.map +1 -1
  217. package/dist/TreeList/TreeList.js +3 -0
  218. package/dist/TreeList/TreeListItem.d.ts +6 -1
  219. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  220. package/dist/TreeList/TreeListItem.js +12 -2
  221. package/dist/TreeList/TreeListTypes.d.ts +8 -1
  222. package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
  223. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  224. package/dist/Typeahead/BaseTypeahead.js +16 -7
  225. package/dist/astryx.css +27 -11
  226. package/dist/hooks/scrollKeyboardDelegation.d.ts +3 -0
  227. package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -0
  228. package/dist/hooks/scrollKeyboardDelegation.js +146 -0
  229. package/dist/hooks/useClickableContainer.d.ts +10 -1
  230. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  231. package/dist/hooks/useClickableContainer.js +15 -4
  232. package/dist/hooks/useScrollableArea.d.ts +6 -2
  233. package/dist/hooks/useScrollableArea.d.ts.map +1 -1
  234. package/dist/hooks/useScrollableArea.js +17 -5
  235. package/dist/index.d.ts +1 -0
  236. package/dist/index.d.ts.map +1 -1
  237. package/dist/index.js +3 -0
  238. package/dist/theme/declarationBoundary.d.ts +17 -0
  239. package/dist/theme/declarationBoundary.d.ts.map +1 -0
  240. package/dist/theme/declarationBoundary.js +343 -0
  241. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  242. package/dist/theme/derivedVarRegistry.js +4 -0
  243. package/dist/theme/generateThemeRules.d.ts +13 -7
  244. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  245. package/dist/theme/generateThemeRules.js +140 -34
  246. package/dist/utils/interactionOverlay.stylex.d.ts +8 -0
  247. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  248. package/dist/utils/interactionOverlay.stylex.js +9 -0
  249. package/dist/utils/safeUrl.d.ts +11 -0
  250. package/dist/utils/safeUrl.d.ts.map +1 -0
  251. package/dist/utils/safeUrl.js +78 -0
  252. package/locales/af-ZA.json +530 -1
  253. package/locales/ar-SA.json +490 -1
  254. package/locales/ca-ES.json +514 -1
  255. package/locales/cs-CZ.json +498 -1
  256. package/locales/da-DK.json +522 -1
  257. package/locales/de-DE.json +522 -1
  258. package/locales/el-GR.json +498 -1
  259. package/locales/es-ES.json +510 -1
  260. package/locales/fi-FI.json +498 -1
  261. package/locales/fr-FR.json +534 -1
  262. package/locales/he-IL.json +498 -1
  263. package/locales/hu-HU.json +498 -1
  264. package/locales/it-IT.json +510 -1
  265. package/locales/ja-JP.json +490 -1
  266. package/locales/ko-KR.json +498 -1
  267. package/locales/nl-NL.json +534 -1
  268. package/locales/no-NO.json +510 -1
  269. package/locales/pl-PL.json +506 -1
  270. package/locales/pt-BR.json +506 -1
  271. package/locales/pt-PT.json +506 -1
  272. package/locales/ro-RO.json +506 -1
  273. package/locales/ru-RU.json +498 -1
  274. package/locales/sr-SP.json +498 -1
  275. package/locales/sv-SE.json +502 -1
  276. package/locales/tr-TR.json +498 -1
  277. package/locales/uk-UA.json +498 -1
  278. package/locales/vi-VN.json +502 -1
  279. package/locales/zh-CN.json +490 -1
  280. package/locales/zh-TW.json +490 -1
  281. package/package.json +24 -4
  282. package/src/BottomSheet/BottomSheet.doc.mjs +8 -1
  283. package/src/BottomSheet/BottomSheet.spec.md +46 -20
  284. package/src/BottomSheet/BottomSheet.test.tsx +6 -3
  285. package/src/BottomSheet/BottomSheet.tsx +3 -1
  286. package/src/BottomSheet/BottomSheetKeyboard.test.tsx +195 -0
  287. package/src/BottomSheet/BottomSheetPanel.test.tsx +11 -1
  288. package/src/BottomSheet/BottomSheetPanel.tsx +49 -16
  289. package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +344 -0
  290. package/src/Button/Button.doc.mjs +5 -5
  291. package/src/Button/Button.tsx +15 -13
  292. package/src/Button/__tests__/Button.a11y.chromium.spec.ts +17 -1
  293. package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -29
  294. package/src/Button/__tests__/Button.a11y.renders.tsx +9 -2
  295. package/src/Button/__tests__/Button.a11y.states.ts +9 -0
  296. package/src/Chat/ChatComposer.doc.mjs +14 -0
  297. package/src/Chat/ChatComposer.spec.md +230 -0
  298. package/src/Chat/ChatComposer.test.tsx +57 -0
  299. package/src/Chat/ChatComposer.tsx +21 -9
  300. package/src/Chat/ChatComposerDrawer.doc.mjs +63 -5
  301. package/src/Chat/ChatComposerDrawer.spec.md +267 -0
  302. package/src/Chat/ChatComposerDrawer.test.tsx +81 -12
  303. package/src/Chat/ChatComposerDrawer.tsx +38 -9
  304. package/src/Chat/ChatComposerInput.doc.mjs +114 -26
  305. package/src/Chat/ChatComposerInput.spec.md +185 -0
  306. package/src/Chat/ChatComposerInput.test.tsx +113 -3
  307. package/src/Chat/ChatComposerInput.tsx +78 -13
  308. package/src/Chat/ChatComposerTokenElement.spec.md +152 -0
  309. package/src/Chat/ChatComposerTokenElement.test.tsx +85 -0
  310. package/src/Chat/ChatDictationButton.doc.mjs +3 -3
  311. package/src/Chat/ChatDictationButton.spec.md +160 -0
  312. package/src/Chat/ChatDictationButton.test.tsx +92 -27
  313. package/src/Chat/ChatDictationButton.tsx +8 -6
  314. package/src/Chat/ChatLayout.doc.mjs +12 -4
  315. package/src/Chat/ChatLayout.spec.md +271 -0
  316. package/src/Chat/ChatLayout.test.tsx +28 -0
  317. package/src/Chat/ChatLayout.tsx +19 -0
  318. package/src/Chat/ChatLayoutScrollButton.spec.md +338 -0
  319. package/src/Chat/ChatLayoutScrollButton.test.tsx +31 -0
  320. package/src/Chat/ChatLayoutScrollButton.tsx +31 -14
  321. package/src/Chat/ChatMessageBubble.doc.mjs +28 -15
  322. package/src/Chat/ChatMessageBubble.spec.md +263 -0
  323. package/src/Chat/ChatMessageBubble.test.tsx +93 -0
  324. package/src/Chat/ChatMessageBubble.tsx +8 -3
  325. package/src/Chat/ChatMessageList.spec.md +222 -0
  326. package/src/Chat/ChatMessageList.test.tsx +64 -2
  327. package/src/Chat/ChatMessageList.tsx +4 -3
  328. package/src/Chat/ChatMessageMetadata.doc.mjs +57 -3
  329. package/src/Chat/ChatMessageMetadata.spec.md +220 -0
  330. package/src/Chat/ChatMessageMetadata.test.tsx +34 -0
  331. package/src/Chat/ChatMessageMetadata.tsx +13 -13
  332. package/src/Chat/ChatSendButton.test.tsx +1 -4
  333. package/src/Chat/ChatSendButton.tsx +1 -1
  334. package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +514 -0
  335. package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +740 -0
  336. package/src/Chat/__tests__/ChatMessageBubble.a11y.chromium.spec.ts +457 -0
  337. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.test.ts +91 -0
  338. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.ts +91 -0
  339. package/src/Chat/__tests__/ChatMessageList.a11y.chromium.spec.ts +456 -0
  340. package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +413 -0
  341. package/src/Chat/index.ts +1 -0
  342. package/src/CheckboxInput/CheckboxInput.doc.mjs +11 -0
  343. package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
  344. package/src/CheckboxInput/CheckboxInput.tsx +21 -1
  345. package/src/Citation/Citation.doc.mjs +2 -2
  346. package/src/Citation/Citation.test.tsx +17 -0
  347. package/src/Citation/Citation.tsx +4 -2
  348. package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
  349. package/src/ClickableCard/ClickableCard.test.tsx +102 -5
  350. package/src/CodeBlock/highlightRanges.test.ts +143 -1
  351. package/src/CodeBlock/highlightRanges.ts +15 -5
  352. package/src/Collapsible/Collapsible.doc.mjs +11 -0
  353. package/src/Collapsible/Collapsible.test.tsx +21 -0
  354. package/src/Collapsible/Collapsible.tsx +5 -0
  355. package/src/CommandPalette/CommandPaletteInput.tsx +6 -1
  356. package/src/ComplexSelector/ComplexSelector.tsx +6 -1
  357. package/src/DateInput/DateInput.tsx +6 -1
  358. package/src/DateInput/NativeDateField.tsx +24 -8
  359. package/src/DateInput/TouchDateField.tsx +6 -2
  360. package/src/DateRangeInput/DateRangeInput.tsx +6 -1
  361. package/src/DateTimeInput/DateTimeInput.tsx +6 -1
  362. package/src/DateTimeInput/TouchDateTimeField.tsx +6 -1
  363. package/src/DateTimeInput/nativePickerSegmentStyles.ts +24 -8
  364. package/src/Dialog/Dialog.doc.mjs +2 -0
  365. package/src/Dialog/DialogHeader.doc.mjs +22 -0
  366. package/src/Dialog/DialogHeader.test.tsx +167 -3
  367. package/src/Dialog/DialogHeader.tsx +37 -6
  368. package/src/Dialog/modules/DialogHeader.spec.md +101 -42
  369. package/src/DropdownMenu/DropdownMenu.test.tsx +5 -2
  370. package/src/Field/InputClearButton.test.tsx +17 -3
  371. package/src/Field/InputClearButton.tsx +5 -2
  372. package/src/Field/PanelSearchInput.tsx +5 -2
  373. package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +1 -1
  374. package/src/FileInput/FileInput.tsx +11 -2
  375. package/src/Icon/Icon.doc.mjs +7 -5
  376. package/src/Icon/Icon.spec.md +81 -40
  377. package/src/Icon/Icon.test.tsx +6 -3
  378. package/src/Icon/Icon.tsx +20 -68
  379. package/src/Icon/IconDefaultSizeContext.ts +23 -0
  380. package/src/Icon/IconSize.stylex.ts +70 -0
  381. package/src/IconButton/IconButton.doc.mjs +3 -3
  382. package/src/IconButton/IconButton.test.tsx +40 -0
  383. package/src/Item/Item.doc.mjs +6 -2
  384. package/src/Item/Item.tsx +9 -3
  385. package/src/Kbd/Kbd.doc.mjs +3 -3
  386. package/src/Kbd/Kbd.test.tsx +57 -1
  387. package/src/Kbd/Kbd.tsx +57 -37
  388. package/src/Layout/LayoutFooter.doc.mjs +17 -0
  389. package/src/Link/Link.doc.mjs +17 -4
  390. package/src/Link/Link.test.tsx +24 -0
  391. package/src/Link/Link.tsx +5 -0
  392. package/src/Link/LinkProvider.doc.mjs +2 -2
  393. package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +261 -0
  394. package/src/Link/useLinkComponent.test.tsx +333 -0
  395. package/src/Link/useLinkComponent.ts +29 -57
  396. package/src/List/List.doc.mjs +6 -0
  397. package/src/List/List.spec.md +200 -0
  398. package/src/List/List.test.tsx +117 -1
  399. package/src/List/List.tsx +22 -2
  400. package/src/List/ListContext.tsx +3 -1
  401. package/src/List/ListItem.doc.mjs +2 -2
  402. package/src/List/ListItem.source-build.test.mjs +41 -0
  403. package/src/List/ListItem.tsx +26 -2
  404. package/src/Markdown/Markdown.doc.mjs +300 -2
  405. package/src/Markdown/Markdown.fr23.bench.ts +174 -0
  406. package/src/Markdown/Markdown.fr23.perf.test.ts +249 -0
  407. package/src/Markdown/Markdown.fr23.sampling.ts +49 -0
  408. package/src/Markdown/Markdown.helpers.perf.test.ts +489 -0
  409. package/src/Markdown/Markdown.public.test.ts +130 -3
  410. package/src/Markdown/Markdown.renderBoundary.test.tsx +72 -0
  411. package/src/Markdown/Markdown.spec.md +203 -45
  412. package/src/Markdown/Markdown.test.tsx +63 -0
  413. package/src/Markdown/Markdown.tsx +414 -135
  414. package/src/Markdown/ast.test.ts +307 -0
  415. package/src/Markdown/ast.ts +337 -0
  416. package/src/Markdown/incremental.test.ts +12 -0
  417. package/src/Markdown/index.ts +37 -1
  418. package/src/Markdown/modules/remark.spec.md +269 -0
  419. package/src/Markdown/modules/softBreaks.spec.md +137 -0
  420. package/src/Markdown/parser/index.ts +64 -0
  421. package/src/Markdown/parser.public.test.ts +103 -0
  422. package/src/Markdown/parser.test.ts +20 -0
  423. package/src/Markdown/parser.ts +1180 -235
  424. package/src/Markdown/plugins/frontmatter.test.tsx +125 -0
  425. package/src/Markdown/plugins/frontmatter.ts +198 -0
  426. package/src/Markdown/plugins/index.ts +54 -0
  427. package/src/Markdown/plugins/protocol.test.tsx +1022 -0
  428. package/src/Markdown/plugins/protocol.ts +1618 -0
  429. package/src/Markdown/plugins/semanticFence.test.tsx +546 -0
  430. package/src/Markdown/plugins/semanticFence.ts +424 -0
  431. package/src/Markdown/plugins/softBreaks.test.tsx +172 -0
  432. package/src/Markdown/plugins/softBreaks.ts +169 -0
  433. package/src/Markdown/plugins/sourceDecoration.test.tsx +799 -0
  434. package/src/Markdown/plugins/sourceDecoration.ts +539 -0
  435. package/src/Markdown/plugins/textTransform.test.ts +467 -0
  436. package/src/Markdown/plugins/textTransform.ts +554 -0
  437. package/src/Markdown/remark.test.tsx +1877 -0
  438. package/src/Markdown/remark.ts +1574 -0
  439. package/src/Markdown/url.ts +36 -0
  440. package/src/Markdown/utils.ts +13 -1
  441. package/src/MetadataList/MetadataList.test.tsx +4 -2
  442. package/src/MetadataList/MetadataList.tsx +3 -3
  443. package/src/MultiSelector/MultiSelector.test.tsx +1 -35
  444. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +128 -0
  445. package/src/NumberInput/NumberInput.tsx +6 -1
  446. package/src/Outline/Outline.doc.mjs +7 -5
  447. package/src/Outline/Outline.spec.md +1 -1
  448. package/src/Outline/index.ts +1 -0
  449. package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +142 -0
  450. package/src/Outline/parseOutlineFromMarkdown.ts +40 -10
  451. package/src/Outline/useOutlineFromMarkdown.ts +15 -3
  452. package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
  453. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +150 -1
  454. package/src/PowerSearch/PowerSearchEditPopover.tsx +51 -28
  455. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +51 -0
  456. package/src/PowerSearch/PowerSearchValueEditor.tsx +4 -0
  457. package/src/ProgressBar/ProgressBar.test.tsx +29 -11
  458. package/src/ProgressBar/ProgressBar.tsx +59 -72
  459. package/src/RadioList/RadioList.doc.mjs +11 -0
  460. package/src/RadioList/RadioList.test.tsx +32 -0
  461. package/src/RadioList/RadioListItem.tsx +25 -1
  462. package/src/ScrollableArea/ScrollableArea.tsx +1 -0
  463. package/src/ScrollableArea/modules/useScrollableArea.spec.md +50 -22
  464. package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
  465. package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
  466. package/src/SegmentedControl/SegmentedControlItem.tsx +6 -9
  467. package/src/Selector/Selector.doc.mjs +2 -2
  468. package/src/Selector/Selector.spec.md +51 -49
  469. package/src/Selector/Selector.test.tsx +61 -55
  470. package/src/Selector/Selector.tsx +34 -15
  471. package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +130 -0
  472. package/src/Selector/__tests__/Listbox.a11y.dom.ts +38 -0
  473. package/src/Selector/__tests__/Listbox.a11y.inventory.test.ts +63 -0
  474. package/src/Selector/__tests__/Listbox.a11y.known-failures.ts +37 -0
  475. package/src/Selector/__tests__/Listbox.a11y.states.ts +232 -0
  476. package/src/Selector/__tests__/Selector.a11y.chromium.spec.ts +45 -0
  477. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +121 -0
  478. package/src/SideNav/SideNav.doc.mjs +1 -1
  479. package/src/SideNav/SideNav.test.tsx +10 -0
  480. package/src/SideNav/SideNav.tsx +14 -2
  481. package/src/Slider/Slider.doc.mjs +17 -3
  482. package/src/Slider/Slider.test.tsx +221 -0
  483. package/src/Slider/Slider.tsx +40 -9
  484. package/src/Spinner/Spinner.test.tsx +4 -0
  485. package/src/Spinner/Spinner.tsx +31 -18
  486. package/src/Switch/Switch.doc.mjs +11 -0
  487. package/src/Switch/Switch.test.tsx +16 -0
  488. package/src/Switch/Switch.tsx +28 -0
  489. package/src/TabList/Tab.tsx +35 -7
  490. package/src/TabList/TabList.doc.mjs +11 -0
  491. package/src/TabList/TabList.spec.md +204 -0
  492. package/src/TabList/TabList.test.tsx +66 -0
  493. package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +1 -34
  494. package/src/Table/Table.doc.mjs +1 -1
  495. package/src/Table/Table.spec.md +54 -40
  496. package/src/Table/Table.test.tsx +83 -10
  497. package/src/Table/Table.tsx +30 -22
  498. package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +137 -0
  499. package/src/TextArea/TextArea.tsx +6 -1
  500. package/src/TextInput/TextInput.test.tsx +20 -1
  501. package/src/TextInput/TextInput.tsx +6 -1
  502. package/src/TimeInput/TimeInput.tsx +6 -1
  503. package/src/Timer/Timer.doc.mjs +183 -0
  504. package/src/Timer/Timer.spec.md +215 -0
  505. package/src/Timer/Timer.test.tsx +302 -0
  506. package/src/Timer/Timer.tsx +258 -0
  507. package/src/Timer/index.ts +11 -0
  508. package/src/ToggleButton/ToggleButton.doc.mjs +3 -3
  509. package/src/ToggleButton/ToggleButton.test.tsx +299 -4
  510. package/src/ToggleButton/ToggleButton.tsx +26 -33
  511. package/src/ToggleButton/ToggleButtonGroup.doc.mjs +3 -3
  512. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +209 -0
  513. package/src/Token/Token.doc.mjs +2 -2
  514. package/src/Tokenizer/Tokenizer.spec.md +142 -75
  515. package/src/TopNav/TopNavMenu.doc.mjs +2 -2
  516. package/src/TopNav/TopNavMenu.test.tsx +30 -0
  517. package/src/TopNav/TopNavMenu.tsx +7 -2
  518. package/src/TreeList/TreeList.doc.mjs +3 -3
  519. package/src/TreeList/TreeList.spec.md +123 -75
  520. package/src/TreeList/TreeList.test.tsx +29 -0
  521. package/src/TreeList/TreeList.tsx +3 -0
  522. package/src/TreeList/TreeListItem.tsx +15 -1
  523. package/src/TreeList/TreeListTypes.ts +11 -1
  524. package/src/Typeahead/BaseTypeahead.spec.md +4 -3
  525. package/src/Typeahead/BaseTypeahead.tsx +21 -7
  526. package/src/Typeahead/Typeahead.test.tsx +53 -0
  527. package/src/__tests__/PressedState.a11y.chromium.spec.ts +813 -0
  528. package/src/__tests__/pressState.ts +93 -0
  529. package/src/hooks/scrollKeyboardDelegation.test.ts +155 -0
  530. package/src/hooks/scrollKeyboardDelegation.ts +233 -0
  531. package/src/hooks/useClickableContainer.test.tsx +236 -0
  532. package/src/hooks/useClickableContainer.ts +20 -4
  533. package/src/hooks/useScrollableArea.doc.mjs +15 -3
  534. package/src/hooks/useScrollableArea.test.tsx +59 -1
  535. package/src/hooks/useScrollableArea.ts +34 -10
  536. package/src/index.ts +3 -0
  537. package/src/inputFontFloor.test.ts +106 -0
  538. package/src/tailwind-theme.css +0 -6
  539. package/src/theme/Theme.test.tsx +32 -0
  540. package/src/theme/declarationBoundary.test.ts +126 -0
  541. package/src/theme/declarationBoundary.ts +347 -0
  542. package/src/theme/derivedVarRegistry.test.ts +7 -0
  543. package/src/theme/derivedVarRegistry.ts +1 -0
  544. package/src/theme/generateThemeRules.test.ts +526 -1
  545. package/src/theme/generateThemeRules.ts +228 -50
  546. package/src/theme/tokenValueCompat.test.ts +4 -1
  547. package/src/utils/interactionOverlay.stylex.ts +20 -0
  548. package/src/utils/safeUrl.test.ts +88 -0
  549. package/src/utils/safeUrl.ts +85 -0
@@ -8,8 +8,8 @@
8
8
  * @output Unit tests for the shared clear-button primitive
9
9
  * @position Testing; validates InputClearButton.tsx — the single home for the
10
10
  * clearable input family's clear (✕) affordance and its theme target. Covers
11
- * the accessible name, the click callback, the decorative registry glyph,
12
- * both theme targets, the touch hit area, and xstyle forwarding.
11
+ * the accessible name, contextual hover tooltip, click callback, decorative
12
+ * registry glyph, both theme targets, touch hit area, and xstyle forwarding.
13
13
  *
14
14
  * SYNC: When InputClearButton.tsx changes, update tests to match new behavior.
15
15
  */
@@ -17,7 +17,7 @@
17
17
  import {readFileSync} from 'node:fs';
18
18
  import path from 'node:path';
19
19
  import {describe, it, expect, vi, afterEach} from 'vitest';
20
- import {render, screen, fireEvent} from '@testing-library/react';
20
+ import {render, screen, fireEvent, waitFor} from '@testing-library/react';
21
21
  import * as stylex from '@stylexjs/stylex';
22
22
  import {
23
23
  InputClearButton,
@@ -95,6 +95,20 @@ describe('InputClearButton public props', () => {
95
95
  });
96
96
 
97
97
  describe('InputClearButton', () => {
98
+ it('uses the contextual label for the tooltip and accessible name', async () => {
99
+ const showPopover = vi.spyOn(HTMLElement.prototype, 'showPopover');
100
+ render(<InputClearButton label="Clear Search" onClick={() => {}} />);
101
+
102
+ const button = screen.getByRole('button', {name: 'Clear Search'});
103
+ const tooltip = screen.getByRole('tooltip', {hidden: true});
104
+ expect(tooltip).toHaveTextContent(/^Clear Search$/);
105
+ expect(button.getAttribute('aria-describedby')).toBe(tooltip.id);
106
+
107
+ fireEvent.mouseEnter(button);
108
+ await waitFor(() => expect(showPopover).toHaveBeenCalled());
109
+ showPopover.mockRestore();
110
+ });
111
+
98
112
  it('renders a real button with the given accessible label', () => {
99
113
  render(<InputClearButton label="Clear" onClick={() => {}} />);
100
114
  const button = screen.getByRole('button', {name: 'Clear'});
@@ -4,8 +4,9 @@
4
4
 
5
5
  /**
6
6
  * @file InputClearButton.tsx
7
- * @input Uses React, Button, Icon
8
- * @output Exports the public InputClearButton and an internal popup-aware variant.
7
+ * @input Uses React, Button, and Icon
8
+ * @output Exports the public InputClearButton and an internal popup-aware variant,
9
+ * both with a contextual tooltip matching their required label.
9
10
  * @position Shared primitive. Every input that renders a clear affordance —
10
11
  * TextInput, NumberInput, TimeInput, DateInput, DateTimeInput,
11
12
  * DateRangeInput, Selector, MultiSelector, Typeahead, Tokenizer, FileInput —
@@ -66,6 +67,7 @@ const styles = stylex.create({
66
67
  });
67
68
 
68
69
  export interface InputClearButtonProps {
70
+ /** Contextual accessible name for the button, such as "Clear Search". */
69
71
  label: string;
70
72
  onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
71
73
  xstyle?: stylex.StyleXStyles;
@@ -104,6 +106,7 @@ function renderInputClearButton({
104
106
  variant="ghost"
105
107
  size="sm"
106
108
  label={label}
109
+ tooltip={label}
107
110
  className={buttonTargetClassName}
108
111
  icon={
109
112
  <Icon
@@ -119,10 +119,13 @@ const styles = stylex.create({
119
119
  color: colorVars['--color-text-primary'],
120
120
  fontFamily: typographyVars['--font-family-body'],
121
121
  // Matches the option rows below it, so the query reads as the first line of
122
- // the list. The coarse-pointer floor keeps iOS from zooming on focus.
122
+ // the list. The floor keeps iOS from zooming on focus — keyed to iOS
123
+ // alone, since only iOS WebKit implements -webkit-touch-callout.
123
124
  fontSize: {
124
125
  default: typeScaleVars['--text-label-size'],
125
- '@media (pointer: coarse)': `max(1rem, ${typeScaleVars['--text-label-size']})`,
126
+ '@media (pointer: coarse)': {
127
+ '@supports (-webkit-touch-callout: none)': `max(1rem, ${typeScaleVars['--text-label-size']})`,
128
+ },
126
129
  },
127
130
  lineHeight: typeScaleVars['--text-label-leading'],
128
131
  // The field draws the focus ring (see `field`), so the bare input must not
@@ -256,7 +256,7 @@ export const CORE_STATUS_MESSAGE_BINDING_STATES = [
256
256
  minValue: 0,
257
257
  maxValue: 100,
258
258
  },
259
- focusSelector: '[role="progressbar"] [tabindex="0"]',
259
+ focusSelector: '[tabindex="0"]',
260
260
  storyId: 'a11y-status-message-pattern--progress-mark-focused-update',
261
261
  },
262
262
  ] as const satisfies ReadonlyArray<CoreStatusMessageBindingDefinition>;
@@ -231,9 +231,14 @@ const styles = stylex.create({
231
231
  },
232
232
  placeholderText: {
233
233
  fontFamily: typographyVars['--font-family-body'],
234
+ // The 16px floor is iOS-only: iOS Safari zooms the page when a focused
235
+ // control sits under 16px, and only iOS WebKit implements
236
+ // -webkit-touch-callout to key the coarse-pointer floor to it.
234
237
  fontSize: {
235
238
  default: typeScaleVars['--text-body-size'],
236
- '@media (pointer: coarse)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
239
+ '@media (pointer: coarse)': {
240
+ '@supports (-webkit-touch-callout: none)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
241
+ },
237
242
  },
238
243
  lineHeight: typeScaleVars['--text-body-leading'],
239
244
  color: colorVars['--color-text-secondary'],
@@ -242,9 +247,13 @@ const styles = stylex.create({
242
247
  },
243
248
  fileNameText: {
244
249
  fontFamily: typographyVars['--font-family-body'],
250
+ // ...and the filename beside it keeps the same floor, so both lines the
251
+ // control shows stay the same size.
245
252
  fontSize: {
246
253
  default: typeScaleVars['--text-body-size'],
247
- '@media (pointer: coarse)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
254
+ '@media (pointer: coarse)': {
255
+ '@supports (-webkit-touch-callout: none)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
256
+ },
248
257
  },
249
258
  lineHeight: typeScaleVars['--text-body-leading'],
250
259
  color: colorVars['--color-text-primary'],
@@ -49,8 +49,9 @@ export const docs = {
49
49
  {
50
50
  name: 'size',
51
51
  type: "'xsm' | 'sm' | 'md' | 'lg'",
52
- description: 'Icon size.',
53
- default: "'md'",
52
+ description:
53
+ 'Icon size. An explicit value wins. When omitted, Icon uses the nearest default supplied by an owning Astryx component for its icon slot, then falls back to md when no contextual default exists.',
54
+ default: "Contextual; otherwise 'md'",
54
55
  },
55
56
  {
56
57
  name: 'label',
@@ -153,8 +154,9 @@ export const docsZh = {
153
154
  {
154
155
  name: 'size',
155
156
  type: "'xsm' | 'sm' | 'md' | 'lg'",
156
- description: '图标尺寸。',
157
- default: "'md'",
157
+ description:
158
+ '图标尺寸。显式值优先。省略时,Icon 使用最近的 Astryx 所属组件为其图标槽提供的默认尺寸;如果没有上下文默认值,则回退为 md。',
159
+ default: "上下文默认值;否则为 'md'",
158
160
  },
159
161
  {
160
162
  name: 'label',
@@ -294,7 +296,7 @@ export const docsDense = {
294
296
  propDescriptions: {
295
297
  icon: 'Semantic icon name or SVG component. Valid names: close, chevronDown, chevronLeft, chevronRight, chevronsLeft, chevronsRight, check, success, error, warning, info, calendar, clock, externalLink, menu, moreHorizontal, search, arrowUp, arrowDown, arrowsUpDown, funnel, eyeSlash, viewColumns, copy, checkDouble, wrench, stop, microphone. For others, pass an SVG component.',
296
298
  color: 'Color variant mapped to Astryx icon color tokens.',
297
- size: 'Icon size.',
299
+ size: "explicit Icon size; otherwise nearest owning-component default, then 'md' when no contextual default exists",
298
300
  label:
299
301
  'Accessible name for a meaningful, standalone icon. Sets role="img" + aria-label and drops the default aria-hidden. Omit (default) for decorative icons (stays aria-hidden). Empty string = decorative. The accessible-name/alt-text prop for icons.',
300
302
  xstyle:
@@ -10,12 +10,18 @@ approved_by: cixzhang
10
10
  approved_at: 2026-08-30
11
11
  owners: [cixzhang, imdreamrunner]
12
12
  review_triggers: [public-api, behavior, theming, accessibility]
13
- verified_by: [packages/core/src/Icon/Icon.test.tsx, scripts/check-knowledge.mjs]
13
+ verified_by:
14
+ [
15
+ packages/core/src/Icon/Icon.test.tsx,
16
+ packages/core/src/IconButton/IconButton.test.tsx,
17
+ scripts/check-knowledge.mjs,
18
+ ]
14
19
  modules: []
15
20
  families: []
16
21
  design_specs: []
17
22
  architecture:
18
23
  [
24
+ architecture:component-size-cascade,
19
25
  architecture:component-theming-surface,
20
26
  architecture:icon-resolution-and-component-slots,
21
27
  architecture:public-component-api,
@@ -33,11 +39,12 @@ semantics. Consumer usage remains documented in `Icon.doc.mjs`.
33
39
 
34
40
  ## Compatibility and migration
35
41
 
36
- - Released default preserved: `yes`
37
- - Compatibility class: additive documentation only; runtime, DOM, styling, and
38
- public API remain unchanged
42
+ - Released default preserved: `yes` for explicit sizes and standalone Icons
43
+ - Compatibility class: component-owned Icon slots may supply a contextual default;
44
+ explicit Icon sizes and the standalone `md` fallback remain unchanged
39
45
  - Controlled/uncontrolled behavior: not applicable
40
- - Migration decision: none; this record characterizes the released component
46
+ - Migration decision: no consumer migration; omit `size` when the owning Astryx
47
+ component should select the contextual default
41
48
 
42
49
  Consumer migration instructions belong in consumer docs and release notes.
43
50
 
@@ -46,6 +53,7 @@ Consumer migration instructions belong in consumer docs and release notes.
46
53
  **Owns**
47
54
 
48
55
  - Accepting a semantic icon key or a supplied icon component as the glyph source.
56
+ - Resolving explicit, component-owned contextual, and standalone size defaults.
49
57
  - Applying Icon's size, color, theming target, and accessibility semantics to
50
58
  the rendered glyph.
51
59
 
@@ -53,19 +61,22 @@ Consumer migration instructions belong in consumer docs and release notes.
53
61
 
54
62
  - The shared registry's key-resolution and fallback order — owned by the shared
55
63
  icon system.
64
+ - Which contextual default an owning Astryx component selects for its icon slot —
65
+ owned by that component or family contract.
56
66
  - The meaning of a glyph in product context or whether nearby text makes it
57
67
  decorative — owned by the product callsite.
58
68
  - Interaction, focus, or control naming — owned by the interactive parent.
59
69
  - The artwork supplied by a consumer or registered through a theme.
70
+ - A public Icon size-provider API; contextual transport is implementation detail.
60
71
 
61
72
  ## Public concepts
62
73
 
63
- | Concept | Closed values or states | Meaning | Availability by variant/orientation/state | Default | Owner | Stability | Invalid-value behavior |
64
- | ------------- | --------------------------------------------------------- | --------------------------------------------------------- | ----------------------------------------- | ---------- | ---------------- | --------- | ------------------------------------------------------ |
65
- | Glyph source | semantic key, namespaced extension key, or icon component | Selects the visual symbol. | Every render | Required | `component:Icon` | Stable | TypeScript rejects unsupported built-in string values. |
66
- | Size | `xsm`, `sm`, `md`, `lg` | Selects the icon box size. | Every rendered glyph | `md` | `component:Icon` | Stable | TypeScript rejects unsupported values. |
67
- | Color | documented semantic and palette values | Selects the glyph color or inherits it from context. | Every rendered glyph | `inherit` | `component:Icon` | Stable | TypeScript rejects unsupported values. |
68
- | Accessibility | decorative or meaningfully labelled | Controls whether assistive technology receives the glyph. | Every rendered glyph | Decorative | `component:Icon` | Stable | Empty labels use the decorative behavior. |
74
+ | Concept | Closed values or states | Meaning | Availability by variant/orientation/state | Default | Owner | Stability | Invalid-value behavior |
75
+ | ------------- | --------------------------------------------------------- | --------------------------------------------------------- | ----------------------------------------- | ----------------------------------------------- | ---------------- | --------- | ------------------------------------------------------ |
76
+ | Glyph source | semantic key, namespaced extension key, or icon component | Selects the visual symbol. | Every render | Required | `component:Icon` | Stable | TypeScript rejects unsupported built-in string values. |
77
+ | Size | `xsm`, `sm`, `md`, `lg` | Selects the icon box size. | Every rendered glyph | nearest component-owned default; otherwise `md` | `component:Icon` | Stable | TypeScript rejects unsupported values. |
78
+ | Color | documented semantic and palette values | Selects the glyph color or inherits it from context. | Every rendered glyph | `inherit` | `component:Icon` | Stable | TypeScript rejects unsupported values. |
79
+ | Accessibility | decorative or meaningfully labelled | Controls whether assistive technology receives the glyph. | Every rendered glyph | Decorative | `component:Icon` | Stable | Empty labels use the decorative behavior. |
69
80
 
70
81
  A namespaced key that does not resolve currently renders nothing. This is
71
82
  existing behavior, not an intentional fallback promise.
@@ -75,42 +86,51 @@ existing behavior, not an intentional fallback promise.
75
86
  Requirements identify their basis so observed code is not mistaken for an
76
87
  intentional decision.
77
88
 
78
- | ID | Candidate invariant | Basis | Draft review state |
79
- | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------- |
80
- | FR1 | Icon MUST present at most one glyph from the supplied semantic key, namespaced key, or icon component. | Documented promise and current tests. | Settled intent. |
81
- | FR2 | Every rendered glyph MUST carry the `icon` theming target with its selected size and color reflected as target data. | Current source, docs, and theming tests. | Settled intent. |
82
- | FR3 | Icon MUST apply the selected size as width and height for every glyph, plus font size where needed for 1em-based icon sources. This sizing contract MUST NOT promise an HTML or SVG element type. | Human decision, current source, and tests. | Settled intent. |
83
- | FR4 | Supported SVG and styling escape hatches MUST retain their established merge and override behavior. | Current source and regression tests. | Current compatibility behavior; verify before changing. |
89
+ | ID | Candidate invariant | Basis | Draft review state |
90
+ | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------- |
91
+ | FR1 | Icon MUST present at most one glyph from the supplied semantic key, namespaced key, or icon component. | Documented promise and current tests. | Settled intent. |
92
+ | FR2 | Every rendered glyph MUST carry the `icon` theming target with its resolved size and selected color reflected as target data. | Current source, docs, and theming tests. | Settled intent. |
93
+ | FR3 | Icon MUST apply the resolved size as width and height for every glyph, plus font size where needed for 1em-based icon sources. This sizing contract MUST NOT promise an HTML or SVG element type. | Human decision, current source, and tests. | Settled intent. |
94
+ | FR4 | Supported SVG and styling escape hatches MUST retain their established merge and override behavior. | Current source and regression tests. | Current compatibility behavior; verify before changing. |
95
+ | FR5 | An explicit Icon `size` MUST win. Without one, Icon MUST use the nearest default supplied by an owning Astryx component for its documented icon slot; without such a default, Icon MUST use `md`. | Component-size precedence and Button sizing decision. | Settled intent. |
84
96
 
85
97
  ### Allowed variation
86
98
 
87
99
  - **AV1 — Artwork.** The path, view box, and internal structure may vary by icon
88
100
  source or theme without changing Icon's one-part consumer anatomy.
89
- - **AV2 — Rendering strategy.** Icon may render a supplied component directly or
101
+ - **AV2 — Rendering strategy.** Icon may render a supplied icon component directly or
90
102
  use an internal wrapper for a resolved key; neither element shape is public
91
103
  anatomy.
92
104
  - **AV3 — Theme and consumer styling.** Existing theme and styling escape hatches
93
105
  may change visual CSS properties without changing glyph ownership.
106
+ - **AV4 — Contextual mapping.** An owning Astryx component may map its own public
107
+ size or variant to an Icon default. That mapping belongs to the owner and MUST
108
+ preserve explicit Icon sizes and the standalone fallback.
94
109
 
95
110
  ### Representative states
96
111
 
97
- | State | Required invariant | Allowed variation |
98
- | ------------------------- | ----------------------------------------------------- | ---------------------------------------------- |
99
- | Semantic key | One resolved glyph carries the `icon` target. | Theme, registry, or built-in artwork. |
100
- | Namespaced extension key | A resolved extension glyph carries the `icon` target. | Consumer- or library-owned artwork. |
101
- | Supplied icon component | The supplied glyph carries the `icon` target. | Component implementation and SVG internals. |
102
- | Unresolved namespaced key | No glyph is currently rendered. | No fallback behavior is established by intent. |
112
+ | State | Required invariant | Allowed variation |
113
+ | -------------------------------- | -------------------------------------------------------- | ---------------------------------------------- |
114
+ | Semantic key | One resolved glyph carries the `icon` target. | Theme, registry, or built-in artwork. |
115
+ | Namespaced extension key | A resolved extension glyph carries the `icon` target. | Consumer- or library-owned artwork. |
116
+ | Supplied icon component | The supplied glyph carries the `icon` target. | Component implementation and SVG internals. |
117
+ | Standalone Icon without `size` | The resolved size is `md`. | Glyph source and color. |
118
+ | Owned icon slot without `size` | The nearest documented component default is used. | The owning component's declared size mapping. |
119
+ | Explicit Icon size in owned slot | The explicit Icon size wins over the contextual default. | Any supported Icon size. |
120
+ | Unresolved namespaced key | No glyph is currently rendered. | No fallback behavior is established by intent. |
103
121
 
104
122
  ### Transformation and precedence order
105
123
 
106
- - **ORD1 — Presentation.** Apply the target, component size and color styles,
107
- then merge consumer `xstyle`, `className`, inline `style`, and supported
124
+ - **ORD1 — Size resolution.** Resolve explicit Icon `size` → nearest
125
+ component-owned contextual default → standalone `md` fallback.
126
+ - **ORD2 — Presentation.** Apply the target, resolved size, and component color
127
+ styles, then merge consumer `xstyle`, `className`, inline `style`, and supported
108
128
  pass-through props in their established order.
109
129
 
110
130
  ### Performance and resources
111
131
 
112
132
  - **PR1 — Render work.** Icon owns no listeners, observers, or layout
113
- measurement; semantic resolution is synchronous during render.
133
+ measurement; semantic and size resolution are synchronous during render.
114
134
 
115
135
  ## Accessibility contract
116
136
 
@@ -123,9 +143,9 @@ intentional decision.
123
143
 
124
144
  ## Design relationships
125
145
 
126
- | Anatomy or state | Design requirement | Representation authority | Hierarchy role | Component contract |
127
- | ---------------- | ------------------------------------------------------------------- | ------------------------------------------------------------- | ----------------- | ------------------ |
128
- | Glyph | Carries the selected visual symbol at the requested size and color. | Consumer or registry selects artwork; Icon owns presentation. | Context-dependent | FR1, FR2, FR3 |
146
+ | Anatomy or state | Design requirement | Representation authority | Hierarchy role | Component contract |
147
+ | ---------------- | ------------------------------------------------------------------ | ------------------------------------------------------------- | ----------------- | ------------------ |
148
+ | Glyph | Carries the resolved visual symbol at the resolved size and color. | Consumer or registry selects artwork; Icon owns presentation. | Context-dependent | FR1, FR2, FR3, FR5 |
129
149
 
130
150
  `Glyph` is the single conceptual consumer part in both source modes. Current
131
151
  implementation may render a supplied icon component directly or place a
@@ -144,26 +164,32 @@ not promise a `span`, `svg`, or other element type.
144
164
 
145
165
  ## Family and system relationships
146
166
 
167
+ - `architecture:component-size-cascade` owns the shared explicit → nearest
168
+ provider → component fallback pattern and requires provider ownership to be
169
+ declared. Icon retains its own `xsm | sm | md | lg` axis outside the standard
170
+ element-size cascade and adopts that precedence for component-owned defaults.
147
171
  - `architecture:component-theming-surface` owns the qualification and validation
148
172
  rules for the `icon` target.
149
173
  - `architecture:icon-resolution-and-component-slots` owns semantic-key and
150
174
  component-slot resolution before Icon renders the selected source.
151
175
  - `architecture:public-component-api` owns admission and compatibility rules for
152
- Icon's public props.
176
+ Icon's public props and observable defaults.
177
+ - The owning component or family specifies each contextual Icon-size mapping.
178
+ The Button family currently maps `sm` and `md` controls to `sm` Icons and `lg`
179
+ controls to `md` Icons.
153
180
  - Icon has no current family contract.
154
181
 
155
182
  ## Verification map
156
183
 
157
- | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
158
- | ------------------- | ------------------------------------------------------------ | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
159
- | FR1, FR3 | `Icon.test.tsx` source-mode and sizing suites | Built-in, themed, namespaced, component | Breaking source rendering or cross-mode sizing fails assertions. | `audit:Icon/behavior` |
160
- | FR2, FR4 | `Icon.test.tsx` target/styling suites plus source inspection | Both source modes; size and color variants | Removing the target or breaking override composition fails existing assertions; `data-size` and `data-color` reflection currently lack focused assertions. | `audit:Icon/theming` |
161
- | AR1, AR2, AR3 | `Icon.test.tsx` accessible-name suites | Decorative, labelled, explicit ARIA override | Changing default or labelled semantics fails accessibility assertions. | `audit:Icon/accessibility` |
162
- | Theming anatomy map | `scripts/check-knowledge.mjs` | Canonical consumer anatomy and current target | Missing, extra, prefixed, or stale mappings fail repository validation. | `audit:Icon/theming` |
184
+ | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
185
+ | ------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
186
+ | FR1, FR3, FR5 | `Icon.test.tsx` sizing suites and `IconButton.test.tsx` contextual-size suites | standalone default; Button sizes; explicit override; both modes | Breaking source rendering, standalone fallback, contextual mapping, explicit precedence, or cross-mode sizing fails assertions. | `audit:Icon/behavior` |
187
+ | FR2, FR4 | `Icon.test.tsx` target/styling suites plus source inspection | Both source modes; size and color variants | Removing the target or breaking override composition fails existing assertions; `data-color` reflection currently lacks focused assertions. | `audit:Icon/theming` |
188
+ | AR1, AR2, AR3 | `Icon.test.tsx` accessible-name suites | Decorative, labelled, explicit ARIA override | Changing default or labelled semantics fails accessibility assertions. | `audit:Icon/accessibility` |
189
+ | Theming anatomy map | `scripts/check-knowledge.mjs` | Canonical consumer anatomy and current target | Missing, extra, prefixed, or stale mappings fail repository validation. | `audit:Icon/theming` |
163
190
 
164
- Focused coverage for `data-size` and `data-color` on both glyph source modes is
165
- a checkable test gap; source inspection is the current evidence for that part of
166
- FR2.
191
+ Focused coverage for `data-color` on both glyph source modes is a checkable test
192
+ gap; source inspection is the current evidence for that part of FR2.
167
193
 
168
194
  ## Decision log
169
195
 
@@ -182,6 +208,21 @@ a `span`, `svg`, or other element.
182
208
  Rejected: separate wrapper and SVG anatomy entries, because those describe
183
209
  implementation strategies rather than stable consumer concepts.
184
210
 
211
+ ### DEC-2 — Owning components may provide contextual Icon defaults
212
+
213
+ **Reference:** `component:Icon/DEC-2`
214
+ **Decider:** cixzhang, 2026-09-23
215
+
216
+ A person should see an icon that is proportionate to the Astryx component that
217
+ owns its slot without every caller repeating a size. The owning component may
218
+ therefore provide the default while an explicit Icon size remains authoritative
219
+ and a standalone Icon remains `md`. Provider objects, hooks, and context shape
220
+ remain private implementation details rather than public API.
221
+
222
+ Rejected: an unconditional `md` default inside every composition, forcing every
223
+ caller to repeat the owner-derived size, and exposing the provider mechanism as
224
+ public API.
225
+
185
226
  ## Open questions
186
227
 
187
228
  None.
@@ -162,10 +162,13 @@ describe('Icon', () => {
162
162
  expect(icon).toHaveAttribute('aria-label', 'Home');
163
163
  });
164
164
 
165
- it('uses default color and size when not specified', () => {
165
+ it('uses default color and standalone size when not specified', () => {
166
166
  render(<Icon icon={TestIcon} data-testid="icon" />);
167
- // The component should render without errors with defaults
168
- expect(screen.getByTestId('icon')).toBeInTheDocument();
167
+
168
+ const icon = screen.getByTestId('icon');
169
+ expect(icon).toHaveAttribute('data-size', 'md');
170
+ expect(getComputedStyle(icon).width).toBe('1.25rem');
171
+ expect(getComputedStyle(icon).height).toBe('1.25rem');
169
172
  });
170
173
 
171
174
  it('applies aria-hidden by default in string (registry) mode', () => {
package/src/Icon/Icon.tsx CHANGED
@@ -31,6 +31,14 @@ import {getIcon} from './globalIconRegistry';
31
31
  import type {IconName, NamespacedIconName} from './globalIconRegistry';
32
32
  import {mergeProps} from '../utils';
33
33
  import {themeProps} from '../utils/themeProps';
34
+ import {useIconSize} from './IconDefaultSizeContext';
35
+ import {
36
+ iconBoxSizeStyles,
37
+ iconSizeStyles,
38
+ type IconSize,
39
+ } from './IconSize.stylex';
40
+
41
+ export type {IconSize} from './IconSize.stylex';
34
42
 
35
43
  // =============================================================================
36
44
  // Styles
@@ -110,75 +118,11 @@ const colorStyles = stylex.create({
110
118
  },
111
119
  });
112
120
 
113
- /**
114
- * Size styles for direct SVG icon components.
115
- * Uses width/height only — SVG components handle their own viewBox scaling.
116
- *
117
- * Sizes are expressed in `rem` (relative to the root font-size) so icons scale
118
- * in step with text when the document font-size changes, matching the rest of
119
- * the design system's rem-based type scale. Values are the px-equivalents at a
120
- * 16px root: 12px → 0.75rem, 16px → 1rem, 20px → 1.25rem, 24px → 1.5rem.
121
- */
122
- const sizeStyles = stylex.create({
123
- xsm: {
124
- width: '0.75rem',
125
- height: '0.75rem',
126
- },
127
- sm: {
128
- width: '1rem',
129
- height: '1rem',
130
- },
131
- md: {
132
- width: '1.25rem',
133
- height: '1.25rem',
134
- },
135
- lg: {
136
- width: '1.5rem',
137
- height: '1.5rem',
138
- },
139
- });
140
-
141
- /**
142
- * Size styles for string-based (registry) icons.
143
- * Includes fontSize so that 1em-based icons from the registry scale correctly.
144
- *
145
- * Expressed in `rem` for the same reason as {@link sizeStyles} — icons track the
146
- * root font-size instead of being locked to absolute pixels.
147
- */
148
- const spanSizeStyles = stylex.create({
149
- /* eslint-disable @astryx/no-hardcoded-styles -- fontSize here sizes 1em-based
150
- registry SVGs to the icon box; icons use their own 12/16/20/24 scale, not
151
- the 14px-anchored textSizeVars type scale. Values are rem so icons track
152
- the root font-size. */
153
- xsm: {
154
- width: '0.75rem',
155
- height: '0.75rem',
156
- fontSize: '0.75rem',
157
- },
158
- sm: {
159
- width: '1rem',
160
- height: '1rem',
161
- fontSize: '1rem',
162
- },
163
- md: {
164
- width: '1.25rem',
165
- height: '1.25rem',
166
- fontSize: '1.25rem',
167
- },
168
- lg: {
169
- width: '1.5rem',
170
- height: '1.5rem',
171
- fontSize: '1.5rem',
172
- },
173
- /* eslint-enable @astryx/no-hardcoded-styles */
174
- });
175
-
176
121
  // =============================================================================
177
122
  // Types
178
123
  // =============================================================================
179
124
 
180
125
  export type IconColor = keyof typeof colorStyles;
181
- export type IconSize = keyof typeof sizeStyles;
182
126
 
183
127
  /**
184
128
  * Type for icon components that can be passed to Icon.
@@ -215,7 +159,9 @@ export interface IconProps extends Omit<
215
159
  * - 'sm': 1rem (16px at a 16px root)
216
160
  * - 'md': 1.25rem (20px at a 16px root)
217
161
  * - 'lg': 1.5rem (24px at a 16px root)
218
- * @default 'md'
162
+ *
163
+ * An explicit value wins. When omitted, Icon uses the nearest default supplied
164
+ * by an owning Astryx component for its icon slot, then falls back to 'md'.
219
165
  */
220
166
  size?: IconSize;
221
167
  /**
@@ -297,7 +243,7 @@ function getIconA11yProps(
297
243
  export function Icon({
298
244
  icon,
299
245
  color = 'inherit',
300
- size = 'md',
246
+ size: sizeProp,
301
247
  label,
302
248
  ref,
303
249
  className,
@@ -305,6 +251,7 @@ export function Icon({
305
251
  xstyle,
306
252
  ...props
307
253
  }: IconProps) {
254
+ const size = useIconSize(sizeProp);
308
255
  // Derive ARIA from `label`: decorative (aria-hidden) by default, or a
309
256
  // meaningful image (role="img" + aria-label) when `label` is non-empty.
310
257
  const a11yProps = getIconA11yProps(label);
@@ -341,7 +288,12 @@ export function Icon({
341
288
  // precedence as escape hatches.
342
289
  {...mergeProps(
343
290
  themeProps('icon', {size, color}),
344
- stylex.props(styles.root, colorStyles[color], sizeStyles[size], xstyle),
291
+ stylex.props(
292
+ styles.root,
293
+ colorStyles[color],
294
+ iconSizeStyles[size],
295
+ xstyle,
296
+ ),
345
297
  className ?? undefined,
346
298
  style,
347
299
  )}
@@ -410,7 +362,7 @@ function IconFromRegistry({
410
362
  stylex.props(
411
363
  styles.span,
412
364
  colorStyles[color],
413
- spanSizeStyles[size],
365
+ iconBoxSizeStyles[size],
414
366
  xstyle,
415
367
  ),
416
368
  className ?? undefined,
@@ -0,0 +1,23 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file IconDefaultSizeContext.ts
7
+ * @input Uses React context and an optional Icon size prop
8
+ * @output Supplies a component-owned default size to descendant Icon instances
9
+ * @position Internal Icon sizing context; consumed by Icon and icon-slot owners
10
+ */
11
+
12
+ import {createContext, use} from 'react';
13
+ import type {IconSize} from './IconSize.stylex';
14
+
15
+ const IconDefaultSizeContext = createContext<IconSize | null>(null);
16
+ IconDefaultSizeContext.displayName = 'IconDefaultSizeContext';
17
+
18
+ export const IconDefaultSizeProvider = IconDefaultSizeContext.Provider;
19
+
20
+ export function useIconSize(size: IconSize | undefined): IconSize {
21
+ const contextualSize = use(IconDefaultSizeContext);
22
+ return size ?? contextualSize ?? 'md';
23
+ }
@@ -0,0 +1,70 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file IconSize.stylex.ts
5
+ * @input Defines the Icon size scale
6
+ * @output Exports shared Icon size types and StyleX styles
7
+ * @position Internal Icon sizing source; consumed by Icon and icon-slot owners
8
+ */
9
+
10
+ import * as stylex from '@stylexjs/stylex';
11
+
12
+ /**
13
+ * Icon sizes are expressed in `rem` so they scale with the root font-size.
14
+ * Values are the px-equivalents at a 16px root: 12, 16, 20, and 24px.
15
+ */
16
+ const iconSizeValues = {
17
+ xsm: '0.75rem',
18
+ sm: '1rem',
19
+ md: '1.25rem',
20
+ lg: '1.5rem',
21
+ } as const;
22
+
23
+ export type IconSize = keyof typeof iconSizeValues;
24
+
25
+ /** Size styles for direct SVG icon components. */
26
+ export const iconSizeStyles = stylex.create({
27
+ xsm: {
28
+ width: iconSizeValues.xsm,
29
+ height: iconSizeValues.xsm,
30
+ },
31
+ sm: {
32
+ width: iconSizeValues.sm,
33
+ height: iconSizeValues.sm,
34
+ },
35
+ md: {
36
+ width: iconSizeValues.md,
37
+ height: iconSizeValues.md,
38
+ },
39
+ lg: {
40
+ width: iconSizeValues.lg,
41
+ height: iconSizeValues.lg,
42
+ },
43
+ });
44
+
45
+ /**
46
+ * Size styles for icon boxes and string-based registry icons. `fontSize`
47
+ * keeps 1em-based icons in step with the box.
48
+ */
49
+ export const iconBoxSizeStyles = stylex.create({
50
+ xsm: {
51
+ width: iconSizeValues.xsm,
52
+ height: iconSizeValues.xsm,
53
+ fontSize: iconSizeValues.xsm,
54
+ },
55
+ sm: {
56
+ width: iconSizeValues.sm,
57
+ height: iconSizeValues.sm,
58
+ fontSize: iconSizeValues.sm,
59
+ },
60
+ md: {
61
+ width: iconSizeValues.md,
62
+ height: iconSizeValues.md,
63
+ fontSize: iconSizeValues.md,
64
+ },
65
+ lg: {
66
+ width: iconSizeValues.lg,
67
+ height: iconSizeValues.lg,
68
+ fontSize: iconSizeValues.lg,
69
+ },
70
+ });