@astryxdesign/core 0.4.6 → 0.4.7-canary.20bae6c

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 (377) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/AppShell/AppShell.d.ts.map +1 -1
  3. package/dist/AppShell/AppShell.js +3 -2
  4. package/dist/AspectRatio/AspectRatio.d.ts +24 -0
  5. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  6. package/dist/AspectRatio/AspectRatio.js +23 -4
  7. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  8. package/dist/AvatarGroup/AvatarGroup.js +3 -2
  9. package/dist/BottomSheet/BottomSheet.d.ts +1 -0
  10. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  11. package/dist/BottomSheet/BottomSheet.js +54 -15
  12. package/dist/BottomSheet/BottomSheetEdgeTint.d.ts +6 -0
  13. package/dist/BottomSheet/BottomSheetEdgeTint.d.ts.map +1 -0
  14. package/dist/BottomSheet/BottomSheetEdgeTint.js +62 -0
  15. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  16. package/dist/BottomSheet/BottomSheetPanel.js +1 -0
  17. package/dist/BottomSheet/BottomSheetSwitcher.d.ts +1 -0
  18. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  19. package/dist/BottomSheet/BottomSheetSwitcher.js +13 -6
  20. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  21. package/dist/BottomSheet/useSheetGestures.js +23 -5
  22. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  23. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
  24. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  25. package/dist/ButtonGroup/ButtonGroup.js +12 -4
  26. package/dist/Calendar/Calendar.d.ts +3 -1
  27. package/dist/Calendar/Calendar.d.ts.map +1 -1
  28. package/dist/Calendar/Calendar.js +13 -14
  29. package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
  30. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
  31. package/dist/Calendar/getInitialFocusDate.js +62 -0
  32. package/dist/Carousel/Carousel.d.ts.map +1 -1
  33. package/dist/Carousel/Carousel.js +3 -3
  34. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  35. package/dist/Chat/ChatLayout.js +3 -3
  36. package/dist/Chat/ChatMessageList.d.ts +22 -3
  37. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  38. package/dist/Chat/ChatMessageList.js +6 -3
  39. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  40. package/dist/CheckboxInput/CheckboxInput.js +3 -2
  41. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  42. package/dist/ClickableCard/ClickableCard.js +3 -3
  43. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  44. package/dist/CommandPalette/CommandPaletteInput.js +3 -2
  45. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  46. package/dist/CommandPalette/CommandPaletteItem.js +3 -2
  47. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  48. package/dist/ContextMenu/ContextMenu.js +4 -3
  49. package/dist/DateInput/DateInput.d.ts.map +1 -1
  50. package/dist/DateInput/DateInput.js +3 -2
  51. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  52. package/dist/DateInput/TouchDateField.js +34 -1
  53. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  54. package/dist/DateTimeInput/DateTimeInput.js +3 -2
  55. package/dist/Dialog/Dialog.d.ts +7 -1
  56. package/dist/Dialog/Dialog.d.ts.map +1 -1
  57. package/dist/Dialog/Dialog.js +89 -58
  58. package/dist/FileInput/FileInput.d.ts.map +1 -1
  59. package/dist/FileInput/FileInput.js +3 -2
  60. package/dist/Heading/Heading.d.ts.map +1 -1
  61. package/dist/Heading/Heading.js +6 -2
  62. package/dist/HoverCard/HoverCard.d.ts +6 -0
  63. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  64. package/dist/HoverCard/useHoverCard.d.ts +5 -0
  65. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  66. package/dist/HoverCard/useHoverCard.js +67 -25
  67. package/dist/Item/Item.d.ts.map +1 -1
  68. package/dist/Item/Item.js +4 -2
  69. package/dist/Kbd/Kbd.d.ts.map +1 -1
  70. package/dist/Kbd/Kbd.js +10 -3
  71. package/dist/Layer/LayerDepthContext.d.ts +52 -0
  72. package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
  73. package/dist/Layer/LayerDepthContext.js +66 -0
  74. package/dist/Layer/index.d.ts +3 -0
  75. package/dist/Layer/index.d.ts.map +1 -1
  76. package/dist/Layer/index.js +4 -0
  77. package/dist/Layer/layerStack.d.ts +98 -0
  78. package/dist/Layer/layerStack.d.ts.map +1 -0
  79. package/dist/Layer/layerStack.js +306 -0
  80. package/dist/Layer/useLayerDismissal.d.ts +93 -0
  81. package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
  82. package/dist/Layer/useLayerDismissal.js +91 -0
  83. package/dist/Lightbox/Lightbox.d.ts +1 -0
  84. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  85. package/dist/Lightbox/Lightbox.js +103 -81
  86. package/dist/Markdown/index.d.ts +1 -1
  87. package/dist/Markdown/index.d.ts.map +1 -1
  88. package/dist/Markdown/parser.d.ts +38 -1
  89. package/dist/Markdown/parser.d.ts.map +1 -1
  90. package/dist/Markdown/parser.js +149 -23
  91. package/dist/MobileNav/MobileNav.d.ts +6 -1
  92. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  93. package/dist/MobileNav/MobileNav.js +61 -36
  94. package/dist/MultiSelector/MultiSelector.d.ts +15 -1
  95. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  96. package/dist/MultiSelector/MultiSelector.js +17 -6
  97. package/dist/MultiSelector/index.d.ts +1 -1
  98. package/dist/MultiSelector/index.d.ts.map +1 -1
  99. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  100. package/dist/NavMenu/NavHeadingMenu.js +3 -2
  101. package/dist/Outline/Outline.d.ts.map +1 -1
  102. package/dist/Outline/Outline.js +3 -2
  103. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  104. package/dist/OverflowList/OverflowList.js +3 -2
  105. package/dist/Overlay/Overlay.d.ts.map +1 -1
  106. package/dist/Overlay/Overlay.js +3 -2
  107. package/dist/Popover/usePopover.d.ts.map +1 -1
  108. package/dist/Popover/usePopover.js +20 -17
  109. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  110. package/dist/PowerSearch/PowerSearch.js +3 -4
  111. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  112. package/dist/Resizable/ResizeHandle.js +3 -2
  113. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  114. package/dist/SegmentedControl/SegmentedControl.js +3 -2
  115. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  116. package/dist/SelectableCard/SelectableCard.js +3 -3
  117. package/dist/Selector/Selector.d.ts.map +1 -1
  118. package/dist/Selector/Selector.js +5 -0
  119. package/dist/SideNav/SideNav.d.ts.map +1 -1
  120. package/dist/SideNav/SideNav.js +4 -3
  121. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  122. package/dist/SideNav/SideNavItem.js +4 -3
  123. package/dist/Slider/Slider.d.ts.map +1 -1
  124. package/dist/Slider/Slider.js +3 -3
  125. package/dist/Stepper/Step.d.ts +140 -0
  126. package/dist/Stepper/Step.d.ts.map +1 -0
  127. package/dist/Stepper/Step.js +1045 -0
  128. package/dist/Stepper/StepStatus.d.ts +24 -0
  129. package/dist/Stepper/StepStatus.d.ts.map +1 -0
  130. package/dist/Stepper/StepStatus.js +1 -0
  131. package/dist/Stepper/Stepper.d.ts +93 -0
  132. package/dist/Stepper/Stepper.d.ts.map +1 -0
  133. package/dist/Stepper/Stepper.js +184 -0
  134. package/dist/Stepper/StepperContext.d.ts +41 -0
  135. package/dist/Stepper/StepperContext.d.ts.map +1 -0
  136. package/dist/Stepper/StepperContext.js +34 -0
  137. package/dist/Stepper/index.d.ts +8 -0
  138. package/dist/Stepper/index.d.ts.map +1 -0
  139. package/dist/Stepper/index.js +7 -0
  140. package/dist/Stepper/stepper.stylex.d.ts +15 -0
  141. package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
  142. package/dist/Stepper/stepper.stylex.js +20 -0
  143. package/dist/Switch/Switch.d.ts.map +1 -1
  144. package/dist/Switch/Switch.js +3 -2
  145. package/dist/TabList/Tab.d.ts.map +1 -1
  146. package/dist/TabList/Tab.js +5 -1
  147. package/dist/TabList/TabList.d.ts.map +1 -1
  148. package/dist/TabList/TabList.js +3 -3
  149. package/dist/Table/BaseTable.d.ts.map +1 -1
  150. package/dist/Table/BaseTable.js +4 -1
  151. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  152. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
  153. package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
  154. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  155. package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
  156. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  157. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  158. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  159. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
  160. package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
  161. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  162. package/dist/Table/plugins/selection/useTableSelection.js +19 -5
  163. package/dist/Table/types.d.ts +22 -4
  164. package/dist/Table/types.d.ts.map +1 -1
  165. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  166. package/dist/Table/useBaseTablePlugins.js +5 -0
  167. package/dist/Text/Text.d.ts.map +1 -1
  168. package/dist/Text/Text.js +6 -2
  169. package/dist/TextArea/TextArea.d.ts.map +1 -1
  170. package/dist/TextArea/TextArea.js +3 -2
  171. package/dist/TextInput/TextInput.d.ts.map +1 -1
  172. package/dist/TextInput/TextInput.js +3 -2
  173. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  174. package/dist/TimeInput/TimeInput.js +3 -2
  175. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  176. package/dist/Timestamp/Timestamp.js +5 -3
  177. package/dist/Token/TokenLink.d.ts.map +1 -1
  178. package/dist/Token/TokenLink.js +2 -2
  179. package/dist/Tooltip/Tooltip.d.ts +5 -0
  180. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  181. package/dist/Tooltip/useTooltip.d.ts +5 -0
  182. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  183. package/dist/Tooltip/useTooltip.js +39 -24
  184. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  185. package/dist/TopNav/TopNavMegaMenu.js +3 -3
  186. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  187. package/dist/Typeahead/BaseTypeahead.js +3 -3
  188. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  189. package/dist/Typeahead/Typeahead.js +3 -2
  190. package/dist/astryx.css +43 -1
  191. package/dist/hooks/index.d.ts +1 -0
  192. package/dist/hooks/index.d.ts.map +1 -1
  193. package/dist/hooks/index.js +1 -0
  194. package/dist/hooks/useFocusTrap.d.ts +7 -4
  195. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  196. package/dist/hooks/useFocusTrap.js +52 -91
  197. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  198. package/dist/hooks/useHotkeys.js +10 -3
  199. package/dist/hooks/useListFocus.d.ts +5 -2
  200. package/dist/hooks/useListFocus.d.ts.map +1 -1
  201. package/dist/hooks/useListFocus.js +12 -6
  202. package/dist/hooks/useMergedRefs.d.ts +18 -0
  203. package/dist/hooks/useMergedRefs.d.ts.map +1 -0
  204. package/dist/hooks/useMergedRefs.js +25 -0
  205. package/dist/index.d.ts +1 -0
  206. package/dist/index.d.ts.map +1 -1
  207. package/dist/index.js +1 -0
  208. package/dist/utils/timeParser.d.ts +1 -1
  209. package/dist/utils/timeParser.d.ts.map +1 -1
  210. package/dist/utils/timeParser.js +26 -12
  211. package/locales/en.json +27 -7
  212. package/locales/pseudo.json +15 -0
  213. package/package.json +8 -3
  214. package/src/AppShell/AppShell.tsx +3 -2
  215. package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
  216. package/src/AspectRatio/AspectRatio.test.tsx +57 -10
  217. package/src/AspectRatio/AspectRatio.tsx +40 -1
  218. package/src/Avatar/Avatar.doc.mjs +2 -1
  219. package/src/AvatarGroup/AvatarGroup.tsx +3 -2
  220. package/src/BottomSheet/BottomSheet.test.tsx +123 -0
  221. package/src/BottomSheet/BottomSheet.tsx +36 -4
  222. package/src/BottomSheet/BottomSheetEdgeTint.test.tsx +225 -0
  223. package/src/BottomSheet/BottomSheetEdgeTint.tsx +82 -0
  224. package/src/BottomSheet/BottomSheetPanel.test.tsx +66 -0
  225. package/src/BottomSheet/BottomSheetPanel.tsx +19 -0
  226. package/src/BottomSheet/BottomSheetSwitcher.tsx +16 -2
  227. package/src/BottomSheet/useSheetGestures.test.ts +27 -0
  228. package/src/BottomSheet/useSheetGestures.ts +25 -5
  229. package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
  230. package/src/Button/Button.doc.mjs +22 -0
  231. package/src/ButtonGroup/ButtonGroup.doc.mjs +7 -1
  232. package/src/ButtonGroup/ButtonGroup.test.tsx +185 -1
  233. package/src/ButtonGroup/ButtonGroup.tsx +11 -3
  234. package/src/Calendar/Calendar.doc.mjs +4 -3
  235. package/src/Calendar/Calendar.test.tsx +52 -0
  236. package/src/Calendar/Calendar.tsx +18 -15
  237. package/src/Calendar/getInitialFocusDate.test.ts +94 -0
  238. package/src/Calendar/getInitialFocusDate.ts +93 -0
  239. package/src/Carousel/Carousel.tsx +3 -2
  240. package/src/Chat/ChatLayout.tsx +3 -2
  241. package/src/Chat/ChatMessageList.doc.mjs +9 -1
  242. package/src/Chat/ChatMessageList.test.tsx +46 -0
  243. package/src/Chat/ChatMessageList.tsx +28 -4
  244. package/src/CheckboxInput/CheckboxInput.tsx +3 -2
  245. package/src/ClickableCard/ClickableCard.tsx +3 -2
  246. package/src/CodeBlock/CodeBlock.doc.mjs +6 -0
  247. package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
  248. package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
  249. package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
  250. package/src/ContextMenu/ContextMenu.tsx +4 -3
  251. package/src/DateInput/DateInput.tsx +3 -2
  252. package/src/DateInput/DateInputTouch.test.tsx +36 -0
  253. package/src/DateInput/TouchDateField.tsx +35 -1
  254. package/src/DateTimeInput/DateTimeInput.tsx +2 -2
  255. package/src/Dialog/Dialog.doc.mjs +8 -3
  256. package/src/Dialog/Dialog.test.tsx +261 -1
  257. package/src/Dialog/Dialog.tsx +109 -58
  258. package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
  259. package/src/Field/Field.doc.mjs +13 -2
  260. package/src/FileInput/FileInput.tsx +3 -2
  261. package/src/Heading/Heading.test.tsx +23 -1
  262. package/src/Heading/Heading.tsx +6 -2
  263. package/src/HoverCard/HoverCard.doc.mjs +5 -0
  264. package/src/HoverCard/HoverCard.tsx +6 -0
  265. package/src/HoverCard/useHoverCard.tsx +81 -30
  266. package/src/Item/Item.tsx +5 -4
  267. package/src/Kbd/Kbd.test.tsx +17 -0
  268. package/src/Kbd/Kbd.tsx +10 -3
  269. package/src/Layer/LayerDepthContext.tsx +62 -0
  270. package/src/Layer/index.ts +9 -0
  271. package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
  272. package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
  273. package/src/Layer/layerStack.ts +362 -0
  274. package/src/Layer/useLayerDismissal.test.tsx +469 -0
  275. package/src/Layer/useLayerDismissal.ts +173 -0
  276. package/src/Layout/Layout.doc.mjs +2 -2
  277. package/src/Lightbox/Lightbox.doc.mjs +12 -0
  278. package/src/Lightbox/Lightbox.tsx +124 -102
  279. package/src/Link/Link.doc.mjs +39 -0
  280. package/src/Markdown/index.ts +1 -0
  281. package/src/Markdown/parser.perf.test.ts +71 -1
  282. package/src/Markdown/parser.test.ts +145 -2
  283. package/src/Markdown/parser.ts +208 -22
  284. package/src/MobileNav/MobileNav.tsx +62 -36
  285. package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
  286. package/src/MultiSelector/MultiSelector.doc.mjs +27 -0
  287. package/src/MultiSelector/MultiSelector.test.tsx +105 -0
  288. package/src/MultiSelector/MultiSelector.tsx +50 -6
  289. package/src/MultiSelector/index.ts +1 -0
  290. package/src/NavMenu/NavHeadingMenu.tsx +3 -2
  291. package/src/NumberInput/NumberInput.doc.mjs +5 -0
  292. package/src/Outline/Outline.tsx +3 -2
  293. package/src/OverflowList/OverflowList.tsx +3 -2
  294. package/src/Overlay/Overlay.tsx +3 -2
  295. package/src/Popover/Popover.test.tsx +27 -1
  296. package/src/Popover/usePopover.tsx +31 -28
  297. package/src/PowerSearch/PowerSearch.doc.mjs +26 -0
  298. package/src/PowerSearch/PowerSearch.tsx +5 -2
  299. package/src/Resizable/ResizeHandle.tsx +3 -2
  300. package/src/SegmentedControl/SegmentedControl.tsx +3 -2
  301. package/src/SelectableCard/SelectableCard.tsx +3 -2
  302. package/src/Selector/Selector.doc.mjs +12 -1
  303. package/src/Selector/Selector.test.tsx +21 -0
  304. package/src/Selector/Selector.tsx +11 -1
  305. package/src/SideNav/SideNav.doc.mjs +6 -6
  306. package/src/SideNav/SideNav.tsx +4 -2
  307. package/src/SideNav/SideNavItem.tsx +4 -2
  308. package/src/Slider/Slider.tsx +3 -2
  309. package/src/Stepper/Step.doc.mjs +98 -0
  310. package/src/Stepper/Step.tsx +1638 -0
  311. package/src/Stepper/StepStatus.ts +26 -0
  312. package/src/Stepper/Stepper.doc.mjs +370 -0
  313. package/src/Stepper/Stepper.test.tsx +1024 -0
  314. package/src/Stepper/Stepper.tsx +258 -0
  315. package/src/Stepper/StepperContext.ts +71 -0
  316. package/src/Stepper/index.ts +18 -0
  317. package/src/Stepper/stepper.stylex.ts +19 -0
  318. package/src/Switch/Switch.tsx +3 -2
  319. package/src/TabList/Tab.tsx +5 -1
  320. package/src/TabList/TabList.test.tsx +21 -4
  321. package/src/TabList/TabList.tsx +3 -2
  322. package/src/Table/BaseTable.tsx +6 -3
  323. package/src/Table/Table.test.tsx +35 -0
  324. package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
  325. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
  326. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
  327. package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
  328. package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
  329. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
  330. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
  331. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
  332. package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
  333. package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
  334. package/src/Table/types.ts +22 -4
  335. package/src/Table/useBaseTablePlugins.ts +5 -0
  336. package/src/Table/useTableGroupedRows.doc.mjs +5 -4
  337. package/src/Table/useTablePagination.doc.mjs +7 -0
  338. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  339. package/src/Table/useTableSelection.doc.mjs +31 -0
  340. package/src/Text/Text.test.tsx +23 -1
  341. package/src/Text/Text.tsx +6 -2
  342. package/src/TextArea/TextArea.tsx +3 -2
  343. package/src/TextInput/TextInput.doc.mjs +10 -0
  344. package/src/TextInput/TextInput.tsx +3 -2
  345. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  346. package/src/TimeInput/TimeInput.tsx +2 -2
  347. package/src/Timestamp/Timestamp.tsx +4 -2
  348. package/src/Toast/Toast.doc.mjs +6 -0
  349. package/src/Token/TokenLink.tsx +2 -2
  350. package/src/Tokenizer/Tokenizer.doc.mjs +16 -0
  351. package/src/Toolbar/Toolbar.doc.mjs +5 -0
  352. package/src/Tooltip/Tooltip.doc.mjs +5 -0
  353. package/src/Tooltip/Tooltip.test.tsx +32 -0
  354. package/src/Tooltip/Tooltip.tsx +5 -0
  355. package/src/Tooltip/useTooltip.tsx +47 -24
  356. package/src/TopNav/TopNavMegaMenu.tsx +3 -2
  357. package/src/Typeahead/BaseTypeahead.tsx +3 -2
  358. package/src/Typeahead/Typeahead.doc.mjs +5 -0
  359. package/src/Typeahead/Typeahead.tsx +3 -2
  360. package/src/__tests__/complexComponentContract.test.tsx +81 -0
  361. package/src/hooks/index.ts +2 -0
  362. package/src/hooks/useContainerReveal.doc.mjs +2 -2
  363. package/src/hooks/useFocusTrap.ts +54 -107
  364. package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
  365. package/src/hooks/useHotkeys.test.ts +18 -0
  366. package/src/hooks/useHotkeys.ts +10 -3
  367. package/src/hooks/useListFocus.doc.mjs +2 -2
  368. package/src/hooks/useListFocus.test.tsx +65 -3
  369. package/src/hooks/useListFocus.ts +15 -7
  370. package/src/hooks/useMergedRefs.doc.mjs +79 -0
  371. package/src/hooks/useMergedRefs.test.tsx +62 -0
  372. package/src/hooks/useMergedRefs.ts +36 -0
  373. package/src/index.ts +1 -0
  374. package/src/theme/MediaTheme.doc.mjs +5 -5
  375. package/src/utils/timeParser.test.ts +6 -1
  376. package/src/utils/timeParser.ts +35 -13
  377. package/src/__tests__/inputWidthContract.test.tsx +0 -69
@@ -12,6 +12,7 @@
12
12
  * - /packages/core/src/Lightbox/Lightbox.doc.mjs (props table, features, implementation notes)
13
13
  * - /packages/core/src/Lightbox/Lightbox.test.tsx (tests for new/changed behavior)
14
14
  * - /packages/core/src/Lightbox/index.ts (exports if types change)
15
+ * - /packages/core/src/Layer/useLayerDismissal.ts (dismissal stack)
15
16
  * - /apps/storybook/stories/Lightbox.stories.tsx (storybook stories)
16
17
  * - /packages/cli/assets/templates/blocks/components/Lightbox/ (showcase blocks)
17
18
  */
@@ -24,12 +25,14 @@ import { IconButton } from "../IconButton/index.js";
24
25
  import { useAnnounce } from "../hooks/useAnnounce.js";
25
26
  import { useScrollLock } from "../hooks/useScrollLock.js";
26
27
  import { useIsomorphicLayoutEffect } from "../hooks/useIsomorphicLayoutEffect.js";
27
- import { mergeProps, mergeRefs, rtlStyles } from "../utils/index.js";
28
+ import { mergeProps, rtlStyles } from "../utils/index.js";
28
29
  import { themeProps } from "../utils/themeProps.js";
29
30
  import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
30
31
  import { overlayPaddingReset } from "../Layout/padding.stylex.js";
32
+ import { LayerDepthProvider } from "../Layer/LayerDepthContext.js";
33
+ import { useLayerDismissal } from "../Layer/useLayerDismissal.js";
31
34
  import { useTranslator } from "../i18n/index.js";
32
-
35
+ import { useMergedRefs } from "../hooks/useMergedRefs.js";
33
36
  /**
34
37
  * Media type for lightbox items.
35
38
  */
@@ -198,6 +201,7 @@ export function Lightbox({
198
201
  }) {
199
202
  const t = useTranslator();
200
203
  const dialogRef = useRef(null);
204
+ const mergedDialogRef = useMergedRefs(ref, dialogRef);
201
205
  const containerRef = useRef(null);
202
206
  const imageWrapperRef = useRef(null);
203
207
  const triggerElementRef = useRef(null);
@@ -299,12 +303,28 @@ export function Lightbox({
299
303
  const handleClose = useCallback(() => {
300
304
  onOpenChange(false);
301
305
  }, [onOpenChange]);
306
+ const {
307
+ shouldDismissOnCloseRequest
308
+ } = useLayerDismissal({
309
+ isActive: isOpen,
310
+ onDismiss: handleClose
311
+ });
302
312
 
303
- // Escape key
313
+ // The native `cancel` event is the browser's own close-watcher firing: an
314
+ // Android back gesture, or a close request the stack never saw a press for.
315
+ // Escape presses the stack owns never arrive here — it preventDefault()s
316
+ // those, which suppresses the close watcher.
317
+ //
318
+ // Always preventDefault so the browser cannot close a controlled <dialog>
319
+ // behind React's back, then answer with the stack's own rules: top-most
320
+ // only, and never while an IME composition is in progress.
304
321
  const handleCancel = useCallback(e => {
305
322
  e.preventDefault();
323
+ if (!shouldDismissOnCloseRequest()) {
324
+ return;
325
+ }
306
326
  handleClose();
307
- }, [handleClose]);
327
+ }, [handleClose, shouldDismissOnCloseRequest]);
308
328
 
309
329
  // Backdrop click. The layout container fills the whole transparent dialog,
310
330
  // so clicks on the visual backdrop (the dark area around the media) land on
@@ -438,7 +458,7 @@ export function Lightbox({
438
458
  return null;
439
459
  }
440
460
  return /*#__PURE__*/_jsx("dialog", {
441
- ref: mergeRefs(ref, dialogRef),
461
+ ref: mergedDialogRef,
442
462
  onCancel: handleCancel,
443
463
  onClick: e => {
444
464
  handleBackdropClick(e);
@@ -451,88 +471,90 @@ export function Lightbox({
451
471
  "aria-label": currentItem.alt || t('@astryx.lightbox.mediaViewer'),
452
472
  ...mergeProps(themeProps('lightbox'), stylex.props(styles.dialog, overlayPaddingReset.reset, xstyle), className, style),
453
473
  ...props,
454
- children: /*#__PURE__*/_jsxs("div", {
455
- ref: containerRef,
456
- ...{
457
- className: "x78zum5 xdt5ytf x6s0dn4 xl56j7k xh8yej3 x5yr21d x1n2onr6"
458
- },
459
- children: [/*#__PURE__*/_jsx(IconButton, {
460
- icon: /*#__PURE__*/_jsx(Icon, {
461
- icon: "close",
462
- size: "sm",
463
- color: "inherit"
464
- }),
465
- label: t('@astryx.lightbox.close'),
466
- variant: "ghost",
467
- onClick: handleClose,
468
- xstyle: [styles.closeButton, styles.controlButton]
469
- }), isGallery && /*#__PURE__*/_jsx(IconButton, {
470
- icon: /*#__PURE__*/_jsx(Icon, {
471
- icon: "chevronLeft",
472
- size: "sm",
473
- color: "inherit",
474
- xstyle: rtlStyles.mirror
475
- }),
476
- label: t('@astryx.lightbox.previous'),
477
- variant: "ghost",
478
- isDisabled: !canPrev,
479
- onClick: goToPrev,
480
- xstyle: [styles.navButton, styles.navPrev, styles.controlButton]
481
- }), /*#__PURE__*/_jsxs("div", {
474
+ children: /*#__PURE__*/_jsx(LayerDepthProvider, {
475
+ children: /*#__PURE__*/_jsxs("div", {
476
+ ref: containerRef,
482
477
  ...{
483
- className: "x78zum5 xdt5ytf x6s0dn4 x193iq5w xmz0i5r xb3r6kr"
478
+ className: "x78zum5 xdt5ytf x6s0dn4 xl56j7k xh8yej3 x5yr21d x1n2onr6"
484
479
  },
485
- children: [/*#__PURE__*/_jsx("div", {
486
- ref: imageWrapperRef
487
- // The wrapper is a keyboard-operable zoom toggle when zoom is
488
- // enabled: Enter/Space toggles, aria-pressed reflects state.
489
- ,
490
- role: isZoomTarget ? 'button' : undefined,
491
- tabIndex: isZoomTarget ? 0 : undefined,
492
- "aria-pressed": isZoomTarget ? isZoomed : undefined,
493
- "aria-label": isZoomTarget ? t('@astryx.lightbox.zoom') : undefined,
494
- ...stylex.props(styles.imageWrapper, isZoomTarget && focusOutlineStyles.focusVisible, !isVideo && hasZoom && !isZoomed && styles.imageWrapperZoomable, !isVideo && isZoomed && styles.imageWrapperZoomed, !isVideo && isDragging && styles.imageWrapperDragging),
495
- onDoubleClick: isVideo ? undefined : handleDoubleClick,
496
- onKeyDown: isZoomTarget ? handleImageKeyDown : undefined,
497
- onPointerDown: isVideo ? undefined : handlePointerDown,
498
- children: isVideo ? /*#__PURE__*/_jsx("video", {
499
- src: currentItem.src,
500
- "aria-label": currentItem.alt,
501
- controls: true,
502
- autoPlay: hasAutoPlay,
480
+ children: [/*#__PURE__*/_jsx(IconButton, {
481
+ icon: /*#__PURE__*/_jsx(Icon, {
482
+ icon: "close",
483
+ size: "sm",
484
+ color: "inherit"
485
+ }),
486
+ label: t('@astryx.lightbox.close'),
487
+ variant: "ghost",
488
+ onClick: handleClose,
489
+ xstyle: [styles.closeButton, styles.controlButton]
490
+ }), isGallery && /*#__PURE__*/_jsx(IconButton, {
491
+ icon: /*#__PURE__*/_jsx(Icon, {
492
+ icon: "chevronLeft",
493
+ size: "sm",
494
+ color: "inherit",
495
+ xstyle: rtlStyles.mirror
496
+ }),
497
+ label: t('@astryx.lightbox.previous'),
498
+ variant: "ghost",
499
+ isDisabled: !canPrev,
500
+ onClick: goToPrev,
501
+ xstyle: [styles.navButton, styles.navPrev, styles.controlButton]
502
+ }), /*#__PURE__*/_jsxs("div", {
503
+ ...{
504
+ className: "x78zum5 xdt5ytf x6s0dn4 x193iq5w xmz0i5r xb3r6kr"
505
+ },
506
+ children: [/*#__PURE__*/_jsx("div", {
507
+ ref: imageWrapperRef
508
+ // The wrapper is a keyboard-operable zoom toggle when zoom is
509
+ // enabled: Enter/Space toggles, aria-pressed reflects state.
510
+ ,
511
+ role: isZoomTarget ? 'button' : undefined,
512
+ tabIndex: isZoomTarget ? 0 : undefined,
513
+ "aria-pressed": isZoomTarget ? isZoomed : undefined,
514
+ "aria-label": isZoomTarget ? t('@astryx.lightbox.zoom') : undefined,
515
+ ...stylex.props(styles.imageWrapper, isZoomTarget && focusOutlineStyles.focusVisible, !isVideo && hasZoom && !isZoomed && styles.imageWrapperZoomable, !isVideo && isZoomed && styles.imageWrapperZoomed, !isVideo && isDragging && styles.imageWrapperDragging),
516
+ onDoubleClick: isVideo ? undefined : handleDoubleClick,
517
+ onKeyDown: isZoomTarget ? handleImageKeyDown : undefined,
518
+ onPointerDown: isVideo ? undefined : handlePointerDown,
519
+ children: isVideo ? /*#__PURE__*/_jsx("video", {
520
+ src: currentItem.src,
521
+ "aria-label": currentItem.alt,
522
+ controls: true,
523
+ autoPlay: hasAutoPlay,
524
+ ...{
525
+ className: "x193iq5w xmz0i5r x19kjcj4 x1a2a7pz"
526
+ }
527
+ }) : /*#__PURE__*/_jsx("img", {
528
+ src: currentItem.src,
529
+ alt: currentItem.alt,
530
+ draggable: false,
531
+ ...stylex.props(styles.image, isDragging && styles.imageDragging, imageTransform != null && dynamicStyles.imageTransform(imageTransform))
532
+ })
533
+ }), currentItem.caption && /*#__PURE__*/_jsx("div", {
503
534
  ...{
504
- className: "x193iq5w xmz0i5r x19kjcj4 x1a2a7pz"
505
- }
506
- }) : /*#__PURE__*/_jsx("img", {
507
- src: currentItem.src,
508
- alt: currentItem.alt,
509
- draggable: false,
510
- ...stylex.props(styles.image, isDragging && styles.imageDragging, imageTransform != null && dynamicStyles.imageTransform(imageTransform))
511
- })
512
- }), currentItem.caption && /*#__PURE__*/_jsx("div", {
535
+ className: "x9e3rv5 x18juvz8 xf74fhv x2b8uid x1xye8es x18d9i69 xrrkdod xrlsmeg x2lah0s"
536
+ },
537
+ children: currentItem.caption
538
+ })]
539
+ }), isGallery && /*#__PURE__*/_jsx(IconButton, {
540
+ icon: /*#__PURE__*/_jsx(Icon, {
541
+ icon: "chevronRight",
542
+ size: "sm",
543
+ color: "inherit",
544
+ xstyle: rtlStyles.mirror
545
+ }),
546
+ label: t('@astryx.lightbox.next'),
547
+ variant: "ghost",
548
+ isDisabled: !canNext,
549
+ onClick: goToNext,
550
+ xstyle: [styles.navButton, styles.navNext, styles.controlButton]
551
+ }), isGallery && mediaArray.length > 1 && /*#__PURE__*/_jsxs("div", {
513
552
  ...{
514
- className: "x9e3rv5 x18juvz8 xf74fhv x2b8uid x1xye8es x18d9i69 xrrkdod xrlsmeg x2lah0s"
553
+ className: "x10l6tqk xyx6v2t x1ybfrjj x9e3rv5 xjm74w1 xw6l6zx x1vjfegm"
515
554
  },
516
- children: currentItem.caption
555
+ children: [index + 1, " / ", mediaArray.length]
517
556
  })]
518
- }), isGallery && /*#__PURE__*/_jsx(IconButton, {
519
- icon: /*#__PURE__*/_jsx(Icon, {
520
- icon: "chevronRight",
521
- size: "sm",
522
- color: "inherit",
523
- xstyle: rtlStyles.mirror
524
- }),
525
- label: t('@astryx.lightbox.next'),
526
- variant: "ghost",
527
- isDisabled: !canNext,
528
- onClick: goToNext,
529
- xstyle: [styles.navButton, styles.navNext, styles.controlButton]
530
- }), isGallery && mediaArray.length > 1 && /*#__PURE__*/_jsxs("div", {
531
- ...{
532
- className: "x10l6tqk xyx6v2t x1ybfrjj x9e3rv5 xjm74w1 xw6l6zx x1vjfegm"
533
- },
534
- children: [index + 1, " / ", mediaArray.length]
535
- })]
557
+ })
536
558
  })
537
559
  });
538
560
  }
@@ -6,5 +6,5 @@
6
6
  export { Markdown } from './Markdown';
7
7
  export type { MarkdownProps, MarkdownSource, MarkdownComponents, MarkdownInlinePlugin, } from './Markdown';
8
8
  export { parseMarkdown, parseMarkdownIncremental, createIncrementalState, parseInline, } from './parser';
9
- export type { BlockNode, InlineNode, ListItemNode, TableCellNode, TableAlignment, IncrementalState as IncrementalParseState, } from './parser';
9
+ export type { BlockNode, InlineNode, SourceRange, ListItemNode, TableCellNode, TableAlignment, IncrementalState as IncrementalParseState, } from './parser';
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Markdown/index.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AACpC,YAAY,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,aAAa,EACb,wBAAwB,EACxB,sBAAsB,EACtB,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,SAAS,EACT,UAAU,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,gBAAgB,IAAI,qBAAqB,GAC1C,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Markdown/index.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AACpC,YAAY,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,aAAa,EACb,wBAAwB,EACxB,sBAAsB,EACtB,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,SAAS,EACT,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,gBAAgB,IAAI,qBAAqB,GAC1C,MAAM,UAAU,CAAC"}
@@ -35,7 +35,14 @@ export type InlineNode = {
35
35
  } | {
36
36
  type: 'break';
37
37
  };
38
- export type BlockNode = {
38
+ export type BlockNode = BlockNodeKind & {
39
+ /**
40
+ * Where this block came from in the source, when parsed with the
41
+ * `sourceRanges` option. Top-level blocks only.
42
+ */
43
+ range?: SourceRange;
44
+ };
45
+ type BlockNodeKind = {
39
46
  type: 'heading';
40
47
  level: 1 | 2 | 3 | 4 | 5 | 6;
41
48
  children: InlineNode[];
@@ -69,6 +76,19 @@ export type BlockNode = {
69
76
  src: string;
70
77
  alt: string;
71
78
  };
79
+ /**
80
+ * Where a block sits in the source string handed to `parseMarkdown`:
81
+ * `source.slice(start, end)` is the block, and `end` excludes the block's
82
+ * trailing blank lines.
83
+ *
84
+ * An object rather than a `[start, end]` tuple so a second way of addressing
85
+ * the same block — line numbers, once a consumer needs them — can be added as
86
+ * optional fields without breaking anyone.
87
+ */
88
+ export type SourceRange = {
89
+ readonly start: number;
90
+ readonly end: number;
91
+ };
72
92
  export type ListItemNode = {
73
93
  checked?: boolean;
74
94
  children: BlockNode[];
@@ -100,6 +120,16 @@ export type ParseOptions = {
100
120
  * suffix is not rejected (Astryx accepts any plausible TLD shape).
101
121
  */
102
122
  autolink?: 'gfm';
123
+ /**
124
+ * When true, every top-level block carries a `range` — the offsets it
125
+ * occupies in the string passed in. Lets a consumer that still holds the
126
+ * source slice the original markdown for a block instead of reconstructing
127
+ * it from the parsed node (or from the rendered DOM). Off by default: the
128
+ * field is absent unless asked for, so nothing that compares nodes changes.
129
+ *
130
+ * Blocks nested inside a list item or a blockquote do not carry one.
131
+ */
132
+ sourceRanges?: boolean;
103
133
  };
104
134
  export declare function parseInline(text: string, sourceIds?: ReadonlySet<string>): InlineNode[];
105
135
  export declare function parseInline(text: string, options: ParseOptions): InlineNode[];
@@ -117,6 +147,12 @@ export interface IncrementalState {
117
147
  * with newly-arriving content.
118
148
  */
119
149
  autolink?: 'gfm';
150
+ /**
151
+ * The `sourceRanges` option the cached `settledBlocks` were parsed with.
152
+ * Flipping it invalidates them the same way `autolink` does: they either
153
+ * lack the ranges the caller now asks for, or carry ones it did not.
154
+ */
155
+ sourceRanges?: boolean;
120
156
  /**
121
157
  * Signature of the link reference definitions the cached `settledBlocks`
122
158
  * were parsed with. Definitions are document-global and typically arrive
@@ -143,4 +179,5 @@ export declare function slugify(value: string): string;
143
179
  * document shares a single numbering sequence.
144
180
  */
145
181
  export declare function uniqueSlug(baseSlug: string, counts: Map<string, number>): string;
182
+ export {};
146
183
  //# sourceMappingURL=parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/Markdown/parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/Markdown/parser.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,16 @@
13
13
  // Types
14
14
  // ---------------------------------------------------------------------------
15
15
 
16
+ /**
17
+ * Where a block sits in the source string handed to `parseMarkdown`:
18
+ * `source.slice(start, end)` is the block, and `end` excludes the block's
19
+ * trailing blank lines.
20
+ *
21
+ * An object rather than a `[start, end]` tuple so a second way of addressing
22
+ * the same block — line numbers, once a consumer needs them — can be added as
23
+ * optional fields without breaking anyone.
24
+ */
25
+
16
26
  // ---------------------------------------------------------------------------
17
27
  // Parse options
18
28
  // ---------------------------------------------------------------------------
@@ -47,7 +57,8 @@ function resolveOptions(arg) {
47
57
  const opts = arg;
48
58
  return {
49
59
  sourceIds: opts.sourceIds,
50
- autolink: opts.autolink
60
+ autolink: opts.autolink,
61
+ sourceRanges: opts.sourceRanges
51
62
  };
52
63
  }
53
64
 
@@ -168,10 +179,17 @@ function extractLinkDefinitions(input) {
168
179
  cleaned: input
169
180
  };
170
181
  }
171
- const cleaned = lines.filter((_, index) => keep[index]).join('\n');
182
+ const lineMap = [];
183
+ for (let index = 0; index < lines.length; index++) {
184
+ if (keep[index]) {
185
+ lineMap.push(index);
186
+ }
187
+ }
188
+ const cleaned = lineMap.map(index => lines[index]).join('\n');
172
189
  return {
173
190
  defs,
174
- cleaned
191
+ cleaned,
192
+ lineMap
175
193
  };
176
194
  }
177
195
 
@@ -965,6 +983,19 @@ function isTableSeparator(line) {
965
983
  return nonEmpty.length > 0 && nonEmpty.every(cell => /^:?-+:?$/.test(cell));
966
984
  }
967
985
 
986
+ /**
987
+ * The same options for content parsed out of an enclosing block. Ranges are a
988
+ * top-level contract: a list item's or a blockquote's children are parsed from
989
+ * text the caller reassembled (markers and `>` prefixes stripped), so an
990
+ * offset into it would not address the document.
991
+ */
992
+ function nested(opts) {
993
+ return opts.sourceRanges ? {
994
+ ...opts,
995
+ sourceRanges: false
996
+ } : opts;
997
+ }
998
+
968
999
  /**
969
1000
  * Returns true when a line could start a new block — used to stop paragraph
970
1001
  * continuation. Every regex here uses bounded or single-class quantifiers
@@ -1095,7 +1126,7 @@ function parseList(lines, startIndex, ordered, opts) {
1095
1126
  }
1096
1127
  items.push({
1097
1128
  checked,
1098
- children: parseMarkdownImpl(itemText, opts)
1129
+ children: parseMarkdownImpl(itemText, nested(opts))
1099
1130
  });
1100
1131
 
1101
1132
  // CommonMark loose list: blank line(s) between items of the same style
@@ -1140,7 +1171,8 @@ function parseMarkdownImpl(input, baseOpts) {
1140
1171
  // parse.
1141
1172
  const {
1142
1173
  defs,
1143
- cleaned
1174
+ cleaned,
1175
+ lineMap
1144
1176
  } = extractLinkDefinitions(input);
1145
1177
  const inherited = baseOpts.linkDefs;
1146
1178
  let linkDefs;
@@ -1157,8 +1189,22 @@ function parseMarkdownImpl(input, baseOpts) {
1157
1189
  } : baseOpts;
1158
1190
  const lines = cleaned.split('\n');
1159
1191
  const blocks = [];
1192
+ // The line each block started on, parallel to `blocks`. Only collected when
1193
+ // ranges were asked for; a block's end is resolved after the loop, since the
1194
+ // branch that produced it has already moved `index` past whatever it read.
1195
+ const blockStartLines = opts.sourceRanges ? [] : null;
1196
+ // Set only by a block that consumes blank lines as content, where the
1197
+ // positional end derivation would trim them away.
1198
+ const blockEndLines = opts.sourceRanges ? [] : null;
1199
+ let blockStartLine = 0;
1200
+ const pushBlock = (node, endLine) => {
1201
+ blocks.push(node);
1202
+ blockStartLines?.push(blockStartLine);
1203
+ blockEndLines?.push(endLine);
1204
+ };
1160
1205
  let index = 0;
1161
1206
  while (index < lines.length) {
1207
+ blockStartLine = index;
1162
1208
  const line = lines[index];
1163
1209
  if (line.trim() === '') {
1164
1210
  index++;
@@ -1177,18 +1223,21 @@ function parseMarkdownImpl(input, baseOpts) {
1177
1223
  index++;
1178
1224
  }
1179
1225
  index++; // skip closing fence
1180
- blocks.push({
1226
+ // A fence owns its blank lines, and an unterminated one (mid-stream)
1227
+ // can end on them, so it states its own end rather than letting the
1228
+ // positional derivation trim them off.
1229
+ pushBlock({
1181
1230
  type: 'codeblock',
1182
1231
  language,
1183
1232
  content: codeLines.join('\n')
1184
- });
1233
+ }, Math.min(index, lines.length) - 1);
1185
1234
  continue;
1186
1235
  }
1187
1236
 
1188
1237
  // --- Heading ---
1189
1238
  const headingMatch = line.match(/^(#{1,6}) +(.*)/);
1190
1239
  if (headingMatch) {
1191
- blocks.push({
1240
+ pushBlock({
1192
1241
  type: 'heading',
1193
1242
  level: headingMatch[1].length,
1194
1243
  children: parseInlineEntry(headingMatch[2], opts)
@@ -1199,7 +1248,7 @@ function parseMarkdownImpl(input, baseOpts) {
1199
1248
 
1200
1249
  // --- HR (must precede list check to handle `- - -`, `* * *`, `_ _ _`) ---
1201
1250
  if (isHorizontalRule(line)) {
1202
- blocks.push({
1251
+ pushBlock({
1203
1252
  type: 'hr'
1204
1253
  });
1205
1254
  index++;
@@ -1209,7 +1258,7 @@ function parseMarkdownImpl(input, baseOpts) {
1209
1258
  // --- Standalone image ---
1210
1259
  const imageMatch = line.match(/^!\[([^\]]*)\]\(([^)]+)\)/);
1211
1260
  if (imageMatch && line.trim() === imageMatch[0]) {
1212
- blocks.push({
1261
+ pushBlock({
1213
1262
  type: 'image',
1214
1263
  alt: imageMatch[1],
1215
1264
  src: imageMatch[2]
@@ -1221,7 +1270,7 @@ function parseMarkdownImpl(input, baseOpts) {
1221
1270
  // --- Table (with or without leading pipe) ---
1222
1271
  if (index + 1 < lines.length && line.includes('|') && isTableSeparator(lines[index + 1])) {
1223
1272
  const tableResult = parseTable(lines, index, opts);
1224
- blocks.push(tableResult.node);
1273
+ pushBlock(tableResult.node);
1225
1274
  index = tableResult.nextIndex;
1226
1275
  continue;
1227
1276
  }
@@ -1233,9 +1282,9 @@ function parseMarkdownImpl(input, baseOpts) {
1233
1282
  quoteLines.push(lines[index].replace(/^> ?/, ''));
1234
1283
  index++;
1235
1284
  }
1236
- blocks.push({
1285
+ pushBlock({
1237
1286
  type: 'blockquote',
1238
- children: parseMarkdownImpl(quoteLines.join('\n'), opts)
1287
+ children: parseMarkdownImpl(quoteLines.join('\n'), nested(opts))
1239
1288
  });
1240
1289
  continue;
1241
1290
  }
@@ -1243,7 +1292,7 @@ function parseMarkdownImpl(input, baseOpts) {
1243
1292
  // --- Unordered list ---
1244
1293
  if (/^ {0,9}[-*+] /.test(line)) {
1245
1294
  const listResult = parseList(lines, index, false, opts);
1246
- blocks.push(listResult.node);
1295
+ pushBlock(listResult.node);
1247
1296
  index = listResult.nextIndex;
1248
1297
  continue;
1249
1298
  }
@@ -1251,7 +1300,7 @@ function parseMarkdownImpl(input, baseOpts) {
1251
1300
  // --- Ordered list ---
1252
1301
  if (/^ {0,9}\d+[.)] /.test(line)) {
1253
1302
  const listResult = parseList(lines, index, true, opts);
1254
- blocks.push(listResult.node);
1303
+ pushBlock(listResult.node);
1255
1304
  index = listResult.nextIndex;
1256
1305
  continue;
1257
1306
  }
@@ -1263,14 +1312,63 @@ function parseMarkdownImpl(input, baseOpts) {
1263
1312
  paraLines.push(lines[index]);
1264
1313
  index++;
1265
1314
  }
1266
- blocks.push({
1315
+ pushBlock({
1267
1316
  type: 'paragraph',
1268
1317
  children: parseInlineEntry(paraLines.join('\n'), opts)
1269
1318
  });
1270
1319
  }
1320
+ if (blockStartLines != null) {
1321
+ stampSourceRanges(blocks, blockStartLines, blockEndLines ?? [], lines, lineMap, input, opts);
1322
+ }
1271
1323
  return blocks;
1272
1324
  }
1273
1325
 
1326
+ /**
1327
+ * Give each block the offsets it occupies in the original input.
1328
+ *
1329
+ * Blocks are contiguous and in source order, so a block runs from its own
1330
+ * first line to the line before the next block starts, minus the blank lines
1331
+ * between them. Offsets are computed against the *input*, not the text the
1332
+ * block loop saw: link reference definitions are stripped before parsing, and
1333
+ * `lineMap` says which input line each surviving line came from.
1334
+ */
1335
+ function stampSourceRanges(blocks, blockStartLines, blockEndLines, lines, lineMap, input, opts) {
1336
+ const base = opts.baseOffset ?? 0;
1337
+ // Offset of the first character of every line of the input.
1338
+ const inputLineStarts = [0];
1339
+ for (let i = 0; i < input.length; i++) {
1340
+ if (input[i] === '\n') {
1341
+ inputLineStarts.push(i + 1);
1342
+ }
1343
+ }
1344
+ // Stripping removes whole lines and never edits one, so a parsed line's
1345
+ // length is its input line's length.
1346
+ const lineStart = line => base + inputLineStarts[lineMap != null ? lineMap[line] : line];
1347
+ for (let i = 0; i < blocks.length; i++) {
1348
+ const startLine = blockStartLines[i];
1349
+ let endLine = blockEndLines[i];
1350
+ if (endLine == null) {
1351
+ const nextStart = i + 1 < blocks.length ? blockStartLines[i + 1] : lines.length;
1352
+ endLine = nextStart - 1;
1353
+ while (endLine > startLine && lines[endLine].trim() === '') {
1354
+ endLine--;
1355
+ }
1356
+ }
1357
+ // Exactly the block's own lines, verbatim — a CRLF document's trailing
1358
+ // `\r` included, since the parser reads it as part of the line too and a
1359
+ // range that dropped it would slice to something that re-parses
1360
+ // differently.
1361
+ const end = lineStart(endLine) + lines[endLine].length;
1362
+ blocks[i] = {
1363
+ ...blocks[i],
1364
+ range: {
1365
+ start: lineStart(startLine),
1366
+ end
1367
+ }
1368
+ };
1369
+ }
1370
+ }
1371
+
1274
1372
  // ---------------------------------------------------------------------------
1275
1373
  // Incremental parsing
1276
1374
  // ---------------------------------------------------------------------------
@@ -1532,6 +1630,18 @@ function trimUnsettledStructural(text) {
1532
1630
  return lines.join('\n');
1533
1631
  }
1534
1632
 
1633
+ /**
1634
+ * The same options, for parsing a slice that starts at `offset` of the
1635
+ * document — so the slice's blocks report ranges into the whole document
1636
+ * rather than into the slice.
1637
+ */
1638
+ function atOffset(opts, offset) {
1639
+ return opts.sourceRanges ? {
1640
+ ...opts,
1641
+ baseOffset: offset
1642
+ } : opts;
1643
+ }
1644
+
1535
1645
  /**
1536
1646
  * Concatenate freshly-parsed delta blocks with previously-settled blocks,
1537
1647
  * merging adjacent same-style lists into a single loose list. The boundary
@@ -1552,7 +1662,15 @@ function mergeSettledBlocks(prev, delta) {
1552
1662
  start: prevLast.start,
1553
1663
  delimiter: prevLast.delimiter,
1554
1664
  loose: true,
1555
- items: [...prevLast.items, ...deltaFirst.items]
1665
+ items: [...prevLast.items, ...deltaFirst.items],
1666
+ // One list now, so one range: from where the first half started to
1667
+ // where the second half ended.
1668
+ ...(prevLast.range != null && deltaFirst.range != null ? {
1669
+ range: {
1670
+ start: prevLast.range.start,
1671
+ end: deltaFirst.range.end
1672
+ }
1673
+ } : null)
1556
1674
  };
1557
1675
  return [...prev.slice(0, -1), merged, ...delta.slice(1)];
1558
1676
  }
@@ -1560,15 +1678,16 @@ function mergeSettledBlocks(prev, delta) {
1560
1678
  }
1561
1679
  export function parseMarkdownIncremental(input, state, arg) {
1562
1680
  const opts = resolveOptions(arg);
1563
- // Invalidate cache when the autolink option flips — cached settled blocks
1564
- // were parsed with the previous setting and would otherwise be reused
1565
- // unchanged.
1566
- if (state.autolink !== opts.autolink) {
1681
+ // Invalidate cache when the autolink or sourceRanges option flips — cached
1682
+ // settled blocks were parsed with the previous setting and would otherwise
1683
+ // be reused unchanged.
1684
+ if (state.autolink !== opts.autolink || Boolean(state.sourceRanges) !== Boolean(opts.sourceRanges)) {
1567
1685
  state.prevInput = '';
1568
1686
  state.settledText = '';
1569
1687
  state.settledBlocks = [];
1570
1688
  state.settledUpTo = 0;
1571
1689
  state.autolink = opts.autolink;
1690
+ state.sourceRanges = opts.sourceRanges;
1572
1691
  }
1573
1692
  if (input === '') {
1574
1693
  state.prevInput = '';
@@ -1615,13 +1734,20 @@ export function parseMarkdownIncremental(input, state, arg) {
1615
1734
  } else if (state.settledText.length > 0 && settledText.startsWith(state.settledText)) {
1616
1735
  // Settled portion grew — parse only the new delta
1617
1736
  const delta = settledText.slice(state.settledText.length);
1618
- const deltaBlocks = parseMarkdownImpl(delta, parseOpts);
1737
+ const deltaBlocks = parseMarkdownImpl(delta, atOffset(parseOpts, state.settledText.length));
1619
1738
  settledBlocks = mergeSettledBlocks(state.settledBlocks, deltaBlocks);
1620
1739
  } else {
1621
1740
  // Content before the boundary changed — full re-parse of settled portion
1622
1741
  settledBlocks = parseMarkdownImpl(settledText, parseOpts);
1623
1742
  }
1624
- const unsettledBlocks = unsettledText ? parseMarkdownImpl(unsettledText, parseOpts) : [];
1743
+
1744
+ // The unsettled tail is trimmed before parsing, so its offset in the
1745
+ // document is where that trimmed text actually starts — not the boundary,
1746
+ // which is a line index. If it somehow can't be located, parse it without
1747
+ // ranges rather than report wrong ones. Only worth searching for when
1748
+ // ranges were asked for: this runs on every streamed chunk.
1749
+ const unsettledStart = unsettledText && opts.sourceRanges ? input.indexOf(unsettledText, settledText.length) : -1;
1750
+ const unsettledBlocks = unsettledText ? parseMarkdownImpl(unsettledText, unsettledStart >= 0 ? atOffset(parseOpts, unsettledStart) : nested(parseOpts)) : [];
1625
1751
  state.settledText = settledText;
1626
1752
  state.settledBlocks = settledBlocks;
1627
1753
  state.settledUpTo = boundary;