rift-ds 1.14.0 → 1.16.0

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 (284) hide show
  1. package/README.md +4 -4
  2. package/behaviors/LinkProvider.d.ts +3 -0
  3. package/behaviors/LocaleProvider.d.ts +27 -0
  4. package/behaviors/LocaleProvider.js +16 -0
  5. package/behaviors/direction.css +19 -0
  6. package/behaviors/direction.d.ts +40 -0
  7. package/behaviors/direction.js +56 -0
  8. package/behaviors/focusable.d.ts +2 -1
  9. package/behaviors/locale.d.ts +47 -0
  10. package/behaviors/locale.js +87 -0
  11. package/behaviors/shortcut-keys.d.ts +49 -0
  12. package/behaviors/shortcut-keys.js +129 -0
  13. package/behaviors/shortcuts.d.ts +75 -0
  14. package/behaviors/shortcuts.js +160 -0
  15. package/behaviors/useAnchoredPosition.d.ts +17 -4
  16. package/behaviors/useAnchoredPosition.js +8 -3
  17. package/behaviors/useFocusScope.d.ts +6 -0
  18. package/behaviors/useFocusScope.js +2 -0
  19. package/behaviors/useLayer.d.ts +9 -0
  20. package/behaviors/useLayer.js +4 -0
  21. package/behaviors/useScrollLock.d.ts +4 -0
  22. package/bin/rift-ds.mjs +3 -0
  23. package/chat/ChatWidget.css +24 -24
  24. package/chat/ChatWidget.js +4 -2
  25. package/chat/suggestions.d.ts +12 -0
  26. package/components/Accordion/Accordion.css +1 -1
  27. package/components/AgentPlan/AgentPlan.css +2 -2
  28. package/components/AgentRail/AgentRail.css +4 -4
  29. package/components/AgentRail/AgentRail.js +1 -1
  30. package/components/AgentStatus/AgentStatus.css +1 -1
  31. package/components/AiButton/AiButton.css +4 -4
  32. package/components/AiButton/AiButton.js +2 -1
  33. package/components/AlertDialog/AlertDialog.css +1 -1
  34. package/components/AnchorNav/AnchorNav.css +6 -6
  35. package/components/AnchorNav/AnchorNav.js +4 -2
  36. package/components/AnimatedNumber/AnimatedNumber.d.ts +6 -0
  37. package/components/AnimatedNumber/AnimatedNumber.js +12 -5
  38. package/components/AppLayout/AppLayout.css +3 -3
  39. package/components/AppSidebar/AppSidebar.css +20 -20
  40. package/components/AppSidebar/AppSidebar.js +6 -4
  41. package/components/ArtifactCard/ArtifactCard.css +1 -1
  42. package/components/ArtifactCard/ArtifactCard.js +2 -1
  43. package/components/ArtifactPanel/ArtifactPanel.js +2 -1
  44. package/components/Attachment/Attachment.css +4 -4
  45. package/components/Attachment/AttachmentDropZone.js +2 -1
  46. package/components/Attachment/AttachmentGroup.d.ts +2 -0
  47. package/components/Attachment/AttachmentGroup.js +4 -1
  48. package/components/Attachment/AttachmentViewer.d.ts +2 -0
  49. package/components/Attachment/AttachmentViewer.js +8 -13
  50. package/components/Attachment/fileTypes.d.ts +5 -3
  51. package/components/Attachment/fileTypes.js +8 -3
  52. package/components/Avatar/Avatar.css +1 -1
  53. package/components/AvatarGroup/AvatarGroup.css +1 -1
  54. package/components/BentoTile/BentoTile.css +15 -3
  55. package/components/BottomNav/BottomNav.css +6 -6
  56. package/components/BottomNav/BottomNav.js +3 -1
  57. package/components/Breadcrumb/Breadcrumb.js +2 -2
  58. package/components/Button/Button.css +1 -1
  59. package/components/Button/Button.js +4 -2
  60. package/components/Card/Card.css +3 -3
  61. package/components/CardStack/CardStack.js +4 -2
  62. package/components/Carousel/Carousel.css +5 -2
  63. package/components/Carousel/Carousel.js +11 -7
  64. package/components/Chart/AreaChart.d.ts +2 -0
  65. package/components/Chart/AreaChart.js +15 -6
  66. package/components/Chart/BarChart.d.ts +2 -0
  67. package/components/Chart/BarChart.js +15 -5
  68. package/components/Chart/Chart.css +6 -6
  69. package/components/Chart/ComboChart.d.ts +2 -0
  70. package/components/Chart/ComboChart.js +16 -6
  71. package/components/Chart/LineChart.d.ts +2 -0
  72. package/components/Chart/LineChart.js +15 -6
  73. package/components/Chart/PieChart.d.ts +2 -0
  74. package/components/Chart/PieChart.js +9 -5
  75. package/components/Chart/RadarChart.d.ts +2 -0
  76. package/components/Chart/RadarChart.js +15 -6
  77. package/components/Chart/RadialChart.d.ts +2 -0
  78. package/components/Chart/RadialChart.js +9 -5
  79. package/components/Chart/ScatterChart.d.ts +2 -0
  80. package/components/Chart/ScatterChart.js +17 -7
  81. package/components/Chart/StackedBarChart.d.ts +2 -0
  82. package/components/Chart/StackedBarChart.js +15 -7
  83. package/components/Chart/Treemap.d.ts +2 -0
  84. package/components/Chart/Treemap.js +9 -5
  85. package/components/ChatMarker/ChatMarker.js +2 -1
  86. package/components/ChatMessage/ChatMessage.css +2 -2
  87. package/components/ChatThread/ChatThread.css +1 -1
  88. package/components/Checkbox/Checkbox.css +4 -2
  89. package/components/CircularButton/CircularButton.d.ts +2 -2
  90. package/components/CircularButton/CircularButton.js +2 -1
  91. package/components/CodeDiff/CodeDiff.css +2 -2
  92. package/components/ColorPicker/ColorPicker.css +5 -4
  93. package/components/ColourSwatch/ColourSwatch.css +1 -1
  94. package/components/CommandPalette/CommandPalette.d.ts +13 -1
  95. package/components/CommandPalette/CommandPalette.js +12 -13
  96. package/components/CommandPaletteTrigger/CommandPaletteTrigger.css +1 -1
  97. package/components/CommandPaletteTrigger/CommandPaletteTrigger.d.ts +11 -1
  98. package/components/CommandPaletteTrigger/CommandPaletteTrigger.js +14 -5
  99. package/components/Composer/Composer.css +4 -4
  100. package/components/Composer/Composer.d.ts +2 -0
  101. package/components/Composer/Composer.js +6 -2
  102. package/components/ContactCard/ContactCard.css +1 -1
  103. package/components/ContactCard/ContactCard.js +4 -3
  104. package/components/ContextMenu/ContextMenu.css +10 -7
  105. package/components/ContextMenu/ContextMenu.d.ts +3 -0
  106. package/components/ContextMenu/ContextMenu.js +15 -9
  107. package/components/ContributionGraph/ContributionGraph.css +2 -2
  108. package/components/ContributionGraph/ContributionGraph.d.ts +7 -1
  109. package/components/ContributionGraph/ContributionGraph.js +6 -4
  110. package/components/DataTable/DataTable.css +1 -1
  111. package/components/DataTable/DataTable.d.ts +9 -3
  112. package/components/DataTable/DataTable.js +39 -29
  113. package/components/DataTable/columnTypes.d.ts +2 -2
  114. package/components/DataTable/columnTypes.js +9 -9
  115. package/components/DateInput/DateInput.css +4 -4
  116. package/components/DatePicker/DatePicker.d.ts +23 -7
  117. package/components/DatePicker/DatePicker.js +41 -34
  118. package/components/Dialog/Dialog.css +1 -1
  119. package/components/DocumentChip/DocumentChip.css +1 -1
  120. package/components/DocumentChip/DocumentChip.js +2 -1
  121. package/components/Drawer/Drawer.css +46 -12
  122. package/components/Drawer/Drawer.d.ts +12 -2
  123. package/components/Drawer/Drawer.js +12 -1
  124. package/components/Dropdown/ChosenMark.css +1 -1
  125. package/components/Dropdown/Dropdown.css +1 -1
  126. package/components/Dropdown/Dropdown.js +4 -3
  127. package/components/DropdownMenu/DropdownMenu.css +8 -5
  128. package/components/DropdownMenu/DropdownMenu.d.ts +6 -1
  129. package/components/DropdownMenu/DropdownMenu.js +15 -9
  130. package/components/DropdownMenu/ShortcutHint.d.ts +12 -0
  131. package/components/DropdownMenu/ShortcutHint.js +17 -0
  132. package/components/EmptyState/EmptyState.js +2 -1
  133. package/components/EntityCard/EntityCard.js +2 -1
  134. package/components/EventCalendar/EventCalendar.css +1 -1
  135. package/components/EventCalendar/EventCalendar.d.ts +21 -6
  136. package/components/EventCalendar/EventCalendar.js +33 -31
  137. package/components/FileInput/FileInput.d.ts +2 -0
  138. package/components/FileInput/FileInput.js +4 -1
  139. package/components/FilterBar/FilterBar.js +2 -1
  140. package/components/FunnelChart/FunnelChart.d.ts +2 -0
  141. package/components/FunnelChart/FunnelChart.js +11 -7
  142. package/components/GanttChart/GanttChart.css +1 -0
  143. package/components/GanttChart/GanttChart.js +2 -1
  144. package/components/Gauge/Gauge.css +1 -1
  145. package/components/Gauge/Gauge.d.ts +2 -0
  146. package/components/Gauge/Gauge.js +3 -1
  147. package/components/Globe/Globe.css +1 -0
  148. package/components/HoverCard/HoverCard.css +1 -0
  149. package/components/HoverCard/HoverCard.d.ts +2 -2
  150. package/components/ImageCompare/ImageCompare.css +1 -0
  151. package/components/Input/Input.css +8 -8
  152. package/components/Input/Input.js +3 -2
  153. package/components/Inspector/Inspector.css +12 -11
  154. package/components/Inspector/InspectorSlider.d.ts +2 -0
  155. package/components/Inspector/InspectorSlider.js +8 -1
  156. package/components/Instructions/Instructions.css +1 -1
  157. package/components/Instructions/Instructions.js +2 -1
  158. package/components/InterruptCard/InterruptCard.css +1 -1
  159. package/components/InterruptCard/InterruptCard.js +2 -1
  160. package/components/Kbd/Kbd.css +21 -0
  161. package/components/Kbd/Kbd.d.ts +14 -4
  162. package/components/Kbd/Kbd.js +10 -1
  163. package/components/LegendTile/LegendTile.d.ts +6 -1
  164. package/components/LegendTile/LegendTile.js +3 -2
  165. package/components/Lightbox/Lightbox.css +3 -3
  166. package/components/Lightbox/Lightbox.js +6 -14
  167. package/components/LinkList/LinkList.js +3 -2
  168. package/components/MapCallout/MapCallout.css +1 -0
  169. package/components/MegaMenu/MegaMenu.css +271 -0
  170. package/components/MegaMenu/MegaMenu.d.ts +72 -0
  171. package/components/MegaMenu/MegaMenu.js +71 -0
  172. package/components/Mention/Mention.js +2 -1
  173. package/components/MessageActions/MessageActions.js +2 -1
  174. package/components/MessageCard/MessageCard.css +1 -1
  175. package/components/MessageCard/MessageCard.js +2 -1
  176. package/components/Meter/Meter.css +1 -1
  177. package/components/Meter/Meter.d.ts +2 -0
  178. package/components/Meter/Meter.js +3 -1
  179. package/components/MotionSwatch/MotionSwatch.css +3 -3
  180. package/components/Nav/Nav.d.ts +7 -2
  181. package/components/NavList/NavList.css +3 -3
  182. package/components/NotificationCenter/NotificationCenter.d.ts +2 -0
  183. package/components/NotificationCenter/NotificationCenter.js +7 -2
  184. package/components/Pagination/Pagination.d.ts +2 -0
  185. package/components/Pagination/Pagination.js +6 -2
  186. package/components/PinInput/PinInput.js +3 -2
  187. package/components/Popover/Popover.d.ts +2 -2
  188. package/components/ProgressBar/ProgressBar.css +1 -1
  189. package/components/ProgressBar/ProgressBar.d.ts +2 -0
  190. package/components/ProgressBar/ProgressBar.js +3 -5
  191. package/components/ProgressiveBlur/ProgressiveBlur.css +102 -0
  192. package/components/ProgressiveBlur/ProgressiveBlur.d.ts +30 -0
  193. package/components/ProgressiveBlur/ProgressiveBlur.js +27 -0
  194. package/components/PromptSuggestions/PromptSuggestions.css +11 -4
  195. package/components/PromptSuggestions/PromptSuggestions.js +3 -1
  196. package/components/Prose/Prose.css +3 -0
  197. package/components/QuestionCard/QuestionCard.css +4 -3
  198. package/components/QuestionCard/QuestionCard.js +2 -8
  199. package/components/Quote/Quote.css +4 -4
  200. package/components/RadioButton/RadioButton.css +5 -3
  201. package/components/Rating/Rating.js +4 -3
  202. package/components/Reasoning/Reasoning.css +8 -8
  203. package/components/Reasoning/Reasoning.js +1 -0
  204. package/components/RichDropdown/RichDropdown.css +4 -3
  205. package/components/SegmentedControl/SegmentedControl.css +1 -1
  206. package/components/SegmentedControl/SegmentedControl.js +5 -3
  207. package/components/SidebarPanel/SidebarPanel.css +7 -7
  208. package/components/SidebarPanel/SidebarPanel.js +2 -2
  209. package/components/SiteHeader/SiteHeader.css +305 -0
  210. package/components/SiteHeader/SiteHeader.d.ts +117 -0
  211. package/components/SiteHeader/SiteHeader.js +329 -0
  212. package/components/Skeleton/Skeleton.css +2 -2
  213. package/components/Skeleton/Skeleton.js +1 -0
  214. package/components/Slider/Slider.css +16 -1
  215. package/components/Slider/Slider.js +1 -1
  216. package/components/SourceChip/SourceChip.d.ts +2 -0
  217. package/components/SourceChip/SourceChip.js +6 -2
  218. package/components/SourceTrail/SourceTrail.css +1 -1
  219. package/components/SpacingSwatch/SpacingSwatch.css +3 -3
  220. package/components/SplitButton/SplitButton.css +2 -2
  221. package/components/SplitButton/SplitButton.js +1 -0
  222. package/components/SplitPane/SplitPane.js +3 -2
  223. package/components/Stat/Stat.css +1 -1
  224. package/components/Stat/Stat.d.ts +2 -0
  225. package/components/Stat/Stat.js +3 -1
  226. package/components/Stepper/Stepper.css +5 -5
  227. package/components/Stepper/Stepper.d.ts +2 -0
  228. package/components/Stepper/Stepper.js +5 -1
  229. package/components/StreamingText/StreamingText.css +1 -1
  230. package/components/Table/Table.css +2 -2
  231. package/components/Table/Table.d.ts +2 -2
  232. package/components/Table/Table.js +4 -2
  233. package/components/TableToolbar/TableToolbar.js +2 -1
  234. package/components/Tabs/Tabs.js +3 -2
  235. package/components/ThreadPanel/ThreadPanel.css +19 -5
  236. package/components/ThreadPanel/ThreadPanel.d.ts +6 -1
  237. package/components/ThreadPanel/ThreadPanel.js +11 -7
  238. package/components/ThreadTabs/ThreadTabs.css +8 -1
  239. package/components/ThreadTabs/ThreadTabs.js +4 -2
  240. package/components/TimePicker/TimePicker.css +1 -1
  241. package/components/TimePicker/TimePicker.d.ts +17 -4
  242. package/components/TimePicker/TimePicker.js +21 -3
  243. package/components/Timeline/Timeline.css +8 -8
  244. package/components/Timeline/Timeline.d.ts +2 -0
  245. package/components/Timeline/Timeline.js +5 -2
  246. package/components/Toast/Toast.css +5 -5
  247. package/components/Toast/Toast.js +3 -2
  248. package/components/ToggleGroup/ToggleGroup.css +1 -1
  249. package/components/ToggleSwitch/ToggleSwitch.css +5 -5
  250. package/components/ToggleSwitch/ToggleSwitch.js +1 -0
  251. package/components/ToolCall/ToolCall.css +3 -3
  252. package/components/Toolbar/Toolbar.js +4 -2
  253. package/components/Tooltip/Tooltip.css +1 -0
  254. package/components/Tooltip/Tooltip.d.ts +2 -2
  255. package/components/TopAppBar/TopAppBar.css +2 -2
  256. package/components/TopAppBar/TopAppBar.js +3 -1
  257. package/components/TreeView/TreeView.css +1 -1
  258. package/components/TreeView/TreeView.js +4 -3
  259. package/components/UsageCard/UsageCard.d.ts +2 -0
  260. package/components/UsageCard/UsageCard.js +3 -0
  261. package/components/Widget/Widget.css +1 -1
  262. package/components/Widget/Widget.d.ts +2 -0
  263. package/components/Widget/Widget.js +3 -2
  264. package/components/WorldMap/WorldMap.css +1 -0
  265. package/components/registry.json +26 -2
  266. package/components/registry.json.d.ts +26 -2
  267. package/components/registry.json.js +1 -1
  268. package/fonts/material-symbols.css +13 -1
  269. package/fonts/presets/anton-400-latin-ext.woff2 +0 -0
  270. package/fonts/presets/anton-400-latin.woff2 +0 -0
  271. package/fonts/presets/work-sans-300-700-latin-ext.woff2 +0 -0
  272. package/fonts/presets/work-sans-300-700-latin.woff2 +0 -0
  273. package/index.d.ts +4 -0
  274. package/index.js +9 -0
  275. package/package.json +9 -1
  276. package/tokens/motion.d.ts +2 -0
  277. package/tokens/motion.js +2 -0
  278. package/tokens/presets/marquee.css +299 -0
  279. package/tokens/presets/presets.css +1 -0
  280. package/tokens/registry.json +6 -0
  281. package/tokens/registry.json.d.ts +6 -0
  282. package/tokens/registry.json.js +1 -1
  283. package/tokens/tokens-dark.css +18 -0
  284. package/tokens/tokens-light.css +18 -0
package/README.md CHANGED
@@ -13,7 +13,7 @@ An open source React design system built for AI products and coding agents: comp
13
13
 
14
14
  ## Why Rift DS
15
15
 
16
- - **<!-- component-count -->159<!-- /component-count --> components.** Buttons, forms and tables through to charts, navigation and overlays, each typed and documented with live examples. Every one forwards a ref and your own attributes to its element, state you can own works controlled or uncontrolled (a modal opens when your app says so, by design), and every word a component writes has a prop you can localise. The build checks the first two on every component, and the words wherever they sit in markup. React and React DOM are the only required peer dependencies.
16
+ - **<!-- component-count -->162<!-- /component-count --> components.** Buttons, forms and tables through to charts, navigation and overlays, each typed and documented with live examples. Every one forwards a ref and your own attributes to its element, state you can own works controlled or uncontrolled (a modal opens when your app says so, by design), and every word a component writes has a prop you can localise. The build checks the first two on every component, and the words wherever they sit in markup. React and React DOM are the only required peer dependencies.
17
17
  - **AI patterns, the whole chat and templates, ready to use.** Composer, streaming chat thread, tool calls, reasoning and thread panel are in the box, the complete AI chat ships assembled as one widget that one command scaffolds, and the docs site has complete template screens built from them.
18
18
  - **Fully themeable.** The shipped themes are complete looks to start from, each in light and dark. One `data-brand` attribute applies a theme, and a few CSS overrides make your own.
19
19
  - **Ready for coding agents.** One command installs the agent skills, and a public MCP endpoint serves every component's props, so your agent builds with the library as it actually is. No key, no account.
@@ -91,7 +91,7 @@ Every component's prop contract is also plain markdown (append `.md` to its docs
91
91
 
92
92
  ## Theming
93
93
 
94
- Theming is CSS custom properties; there is no configuration API and no provider (one exception: wrap your tree in `ToastProvider` if, and only if, you use the toast queue via `useToast`). Complete looks ship as generated stylesheets: import the aggregate once and one attribute rethemes everything, light and dark, typefaces included (each preset self-hosts its faces).
94
+ Theming is CSS custom properties; there is no configuration API and no theme provider (one required exception: wrap your tree in `ToastProvider` if, and only if, you use the toast queue via `useToast`). Two providers are optional: `LinkProvider` hands every component your router's link, and `LocaleProvider` sets the locale numbers, dates and calendars are written in (`en-US` without it, never the browser's). Key bindings go through `useShortcut` from `rift-ds/behaviors/shortcuts`, the listener the components use, so a shortcut stays out of text fields and open overlays. For a right-to-left language, set `dir="rtl"` on `<html>`: every component lays itself out from it. Complete looks ship as generated stylesheets: import the aggregate once and one attribute rethemes everything, light and dark, typefaces included (each preset self-hosts its faces).
95
95
 
96
96
  ```tsx
97
97
  import 'rift-ds/tokens/presets/presets.css';
@@ -107,13 +107,13 @@ import 'rift-ds/tokens/presets/presets.css';
107
107
 
108
108
  ## Components
109
109
 
110
- <!-- component-count -->159<!-- /component-count --> components, including a chat set for AI products (Chat thread, Composer, Tool call, Reasoning, Thread panel) and Shader field, a WebGL2 ambient background whose light sources read your colour tokens at runtime, so it re-themes with everything else. Details and live examples are on the [docs site](https://rift-ds.com/components).
110
+ <!-- component-count -->162<!-- /component-count --> components, including a chat set for AI products (Chat thread, Composer, Tool call, Reasoning, Thread panel) and Shader field, a WebGL2 ambient background whose light sources read your colour tokens at runtime, so it re-themes with everything else. Details and live examples are on the [docs site](https://rift-ds.com/components).
111
111
 
112
112
  <details>
113
113
  <summary>The full list</summary>
114
114
 
115
115
  <!-- component-list:start -->
116
- Accordion · Agent plan · Agent rail · Agent status · AI button · Alert · Alert dialog · Anchor nav · Animated number · App layout · App sidebar · Area chart · Artifact card · Artifact panel · Attachment drop zone · Attachment group · Attachment tile · Attachment viewer · Avatar · Avatar group · Badge · Banner · Bar chart · Bento tile · Bento tile art · Bottom nav · Breadcrumb · Button · Button group · Card · Card stack · Carousel · Chat header · Chat marker · Chat message · Chat thread · Checkbox · Chip · Circular button · Code block · Code diff · Colour picker · Combo chart · Combobox · Command palette · Command palette trigger · Composer · Contact card · Context menu · Contribution graph · Data table · Date input · Date picker · Dialog · Divider · Document chip · Drawer · Dropdown · Dropdown menu · Empty state · Entity card · Event calendar · Field · Figure · File input · Filter bar · Funnel chart · Gantt chart · Gauge · Globe · Hover card · Image compare · Input · Inspector colour picker · Inspector dropdown · Inspector input · Inspector section · Inspector segments · Inspector slider · Inspector toggle switch · Instructions · Interrupt card · Kbd · Legend tile · Lightbox · Line chart · Link list · Map callout · Map legend · Mention · Message actions · Message card · Meter · Model picker · Nav · Nav list · Notification centre · Number input · Pagination · Panel · Pie chart · Pin input · Pixel avatar · Popover · Progress bar · Prompt suggestions · Prose · Question card · Quote · Radar chart · Radial chart · Radio button · Rating · Reasoning · Rich dropdown · Scatter chart · Section title · Segmented control · Selection card · Shader field · Sidebar panel · Skeleton · Slider · Source chip · Source trail · Sparkline · Spinner · Split button · Split pane · Stacked bar chart · Stat · Status dot · Stepper · Streaming text · Swatch · Table · Table toolbar · Tabs · Tag input · Textarea · Theme picker · Theme toggle · Thread panel · Thread tabs · Time picker · Timeline · Toast · Toggle group · Toggle switch · Tool call · Toolbar · Tooltip · Top app bar · Tree view · Treemap · Usage card · Waveform · Widget · World map
116
+ Accordion · Agent plan · Agent rail · Agent status · AI button · Alert · Alert dialog · Anchor nav · Animated number · App layout · App sidebar · Area chart · Artifact card · Artifact panel · Attachment drop zone · Attachment group · Attachment tile · Attachment viewer · Avatar · Avatar group · Badge · Banner · Bar chart · Bento tile · Bento tile art · Bottom nav · Breadcrumb · Button · Button group · Card · Card stack · Carousel · Chat header · Chat marker · Chat message · Chat thread · Checkbox · Chip · Circular button · Code block · Code diff · Colour picker · Combo chart · Combobox · Command palette · Command palette trigger · Composer · Contact card · Context menu · Contribution graph · Data table · Date input · Date picker · Dialog · Divider · Document chip · Drawer · Dropdown · Dropdown menu · Empty state · Entity card · Event calendar · Field · Figure · File input · Filter bar · Funnel chart · Gantt chart · Gauge · Globe · Hover card · Image compare · Input · Inspector colour picker · Inspector dropdown · Inspector input · Inspector section · Inspector segments · Inspector slider · Inspector toggle switch · Instructions · Interrupt card · Kbd · Legend tile · Lightbox · Line chart · Link list · Map callout · Map legend · Mega menu · Mention · Message actions · Message card · Meter · Model picker · Nav · Nav list · Notification centre · Number input · Pagination · Panel · Pie chart · Pin input · Pixel avatar · Popover · Progress bar · Progressive blur · Prompt suggestions · Prose · Question card · Quote · Radar chart · Radial chart · Radio button · Rating · Reasoning · Rich dropdown · Scatter chart · Section title · Segmented control · Selection card · Shader field · Sidebar panel · Site header · Skeleton · Slider · Source chip · Source trail · Sparkline · Spinner · Split button · Split pane · Stacked bar chart · Stat · Status dot · Stepper · Streaming text · Swatch · Table · Table toolbar · Tabs · Tag input · Textarea · Theme picker · Theme toggle · Thread panel · Thread tabs · Time picker · Timeline · Toast · Toggle group · Toggle switch · Tool call · Toolbar · Tooltip · Top app bar · Tree view · Treemap · Usage card · Waveform · Widget · World map
117
117
  <!-- component-list:end -->
118
118
 
119
119
  </details>
@@ -27,6 +27,9 @@ export interface LinkProviderProps {
27
27
  * read a provider and take the prop alone (design.md's Components intro
28
28
  * names them, and scripts/validate-component-contract.mjs keeps them off
29
29
  * the provider).
30
+ *
31
+ * Published as the `./behaviors/LinkProvider` subpath because consumers
32
+ * mount it; with the scroll lock it is one of only two behaviors that are.
30
33
  */
31
34
  export declare function LinkProvider({ linkComponent, children }: LinkProviderProps): React.JSX.Element;
32
35
  /**
@@ -0,0 +1,27 @@
1
+ import { default as React } from 'react';
2
+ export interface LocaleProviderProps {
3
+ /**
4
+ * The BCP 47 locale every rift-ds component under this provider formats
5
+ * numbers, dates and calendars in, such as `de-DE`. Named like the
6
+ * instance prop it stands in for.
7
+ */
8
+ locale: string;
9
+ /** The part of the app it applies to, usually the whole app. */
10
+ children?: React.ReactNode;
11
+ }
12
+ /**
13
+ * Sets the locale for every client-rendered rift-ds component below it that
14
+ * formats a number or a date, or lays out a calendar: grouping and decimal
15
+ * marks, month and weekday names, the first day of the week, and the
16
+ * 12- or 24-hour clock. A component's own `locale` prop wins over it. The
17
+ * components that can render on the server cannot read a provider and take
18
+ * the prop alone. Words stay props of their own: the locale formats, it
19
+ * never translates.
20
+ */
21
+ export declare function LocaleProvider({ locale, children }: LocaleProviderProps): React.JSX.Element;
22
+ /**
23
+ * The locale to format in: the component's own `locale` prop, else the
24
+ * nearest LocaleProvider's, else `en-US`. Never the runtime's default, so
25
+ * the server and the browser always agree.
26
+ */
27
+ export declare function useLocale(override?: string): string;
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext } from "react";
4
+ import { DEFAULT_LOCALE } from "./locale.js";
5
+ const LocaleContext = createContext(null);
6
+ function LocaleProvider({ locale, children }) {
7
+ return /* @__PURE__ */ jsx(LocaleContext.Provider, { value: locale, children });
8
+ }
9
+ function useLocale(override) {
10
+ const provided = useContext(LocaleContext);
11
+ return override ?? provided ?? DEFAULT_LOCALE;
12
+ }
13
+ export {
14
+ LocaleProvider,
15
+ useLocale
16
+ };
@@ -0,0 +1,19 @@
1
+ /* ============================================
2
+ READING DIRECTION SIGN
3
+ `--ds-inline-sign` is 1 in a left-to-right context and -1 in a
4
+ right-to-left one, read from the element's own direction (`:dir()`),
5
+ so a `dir` attribute anywhere up the tree sets it. A component that
6
+ moves along the inline axis (a slide-in, a thumb, a shimmer's sweep, an
7
+ optical nudge) multiplies its offset by it, always with the fallback
8
+ `var(--ds-inline-sign, 1)`, and imports this file. Logical properties
9
+ cover placement; this covers motion, which CSS has no logical form for.
10
+ design.md's "Layout follows the reading direction" owns the contract.
11
+ ============================================ */
12
+
13
+ :dir(ltr) {
14
+ --ds-inline-sign: 1;
15
+ }
16
+
17
+ :dir(rtl) {
18
+ --ds-inline-sign: -1;
19
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The reading direction, for the code that moves along the inline axis:
3
+ * arrow keys, drags and anything placed in pixels. Stylesheets read it
4
+ * through logical properties and `--ds-inline-sign` (direction.css); script
5
+ * reads it here, from the element itself at the moment it acts, so a `dir`
6
+ * attribute anywhere up the tree applies and a change to it needs no
7
+ * re-render. No React and no browser API at import time, so a server
8
+ * component can import it too. design.md's "Layout follows the reading
9
+ * direction" owns the contract.
10
+ */
11
+ /** Whether `element` lays out right to left. False on the server and for a missing element. */
12
+ export declare function isRtl(element: Element | null | undefined): boolean;
13
+ /** 1 when `element` reads left to right, -1 when it reads right to left: the sign to multiply a horizontal pointer delta by. */
14
+ export declare const inlineSign: (element: Element | null | undefined) => 1 | -1;
15
+ /**
16
+ * An arrow key along the inline axis as a step through the reading order:
17
+ * `1` for the next item (ArrowRight in English, ArrowLeft in Arabic), `-1`
18
+ * for the previous one, and 0 for any other key.
19
+ */
20
+ export declare function inlineStep(key: string, element: Element | null | undefined): -1 | 0 | 1;
21
+ /**
22
+ * The Material Symbols ligatures that point along the reading direction and
23
+ * so mirror in a right-to-left context: a "next" chevron points left in
24
+ * Arabic. A component that draws one adds the `ds-mirror-rtl` class (the
25
+ * rule lives in src/fonts/material-symbols.css, which every icon imports);
26
+ * `mirrorClass` decides it for an icon a consumer passes by name.
27
+ */
28
+ export declare const DIRECTIONAL_ICONS: Set<string>;
29
+ /** Whether the icon named `name` points along the reading direction and should mirror in a right-to-left context. */
30
+ export declare const mirrorsInRtl: (name: unknown) => boolean;
31
+ /**
32
+ * A key as it would be pressed in a left-to-right layout: ArrowLeft and
33
+ * ArrowRight swap when `element` reads right to left, and every other key
34
+ * passes through. A component that steps along the inline axis switches on
35
+ * this instead of the raw key, so "the next tab" is ArrowRight in English
36
+ * and ArrowLeft in Arabic with no second branch.
37
+ */
38
+ export declare function logicalArrowKey(key: string, element: Element | null | undefined): string;
39
+ /** `ds-mirror-rtl` when the icon named `name` mirrors in a right-to-left context, else an empty string, for a className. */
40
+ export declare const mirrorClass: (name: unknown) => string;
@@ -0,0 +1,56 @@
1
+ function isRtl(element) {
2
+ if (!element || typeof getComputedStyle === "undefined") return false;
3
+ return getComputedStyle(element).direction === "rtl";
4
+ }
5
+ const inlineSign = (element) => isRtl(element) ? -1 : 1;
6
+ const DIRECTIONAL_ICONS = /* @__PURE__ */ new Set([
7
+ "chevron_left",
8
+ "chevron_right",
9
+ "arrow_back",
10
+ "arrow_forward",
11
+ "arrow_back_ios",
12
+ "arrow_forward_ios",
13
+ "arrow_back_ios_new",
14
+ "first_page",
15
+ "last_page",
16
+ "keyboard_arrow_left",
17
+ "keyboard_arrow_right",
18
+ "keyboard_double_arrow_left",
19
+ "keyboard_double_arrow_right",
20
+ "navigate_before",
21
+ "navigate_next",
22
+ "east",
23
+ "west",
24
+ "trending_flat",
25
+ "subdirectory_arrow_right",
26
+ "subdirectory_arrow_left",
27
+ "reply",
28
+ "forward",
29
+ "undo",
30
+ "redo",
31
+ "logout",
32
+ "login",
33
+ "send",
34
+ "menu_open",
35
+ "format_indent_increase",
36
+ "format_indent_decrease",
37
+ "view_sidebar",
38
+ "left_panel_open",
39
+ "left_panel_close",
40
+ "right_panel_open",
41
+ "right_panel_close"
42
+ ]);
43
+ const mirrorsInRtl = (name) => typeof name === "string" && DIRECTIONAL_ICONS.has(name);
44
+ function logicalArrowKey(key, element) {
45
+ if (key !== "ArrowLeft" && key !== "ArrowRight" || !isRtl(element)) return key;
46
+ return key === "ArrowLeft" ? "ArrowRight" : "ArrowLeft";
47
+ }
48
+ const mirrorClass = (name) => mirrorsInRtl(name) ? "ds-mirror-rtl" : "";
49
+ export {
50
+ DIRECTIONAL_ICONS,
51
+ inlineSign,
52
+ isRtl,
53
+ logicalArrowKey,
54
+ mirrorClass,
55
+ mirrorsInRtl
56
+ };
@@ -2,7 +2,8 @@
2
2
  * Shared focusability queries for the overlay behavior layer.
3
3
  *
4
4
  * One home for the selector the modal components previously each carried a
5
- * copy of. Plain DOM utilities — no React, safe to import anywhere.
5
+ * copy of. Plain DOM utilities — no React, safe to import anywhere. It
6
+ * serves non-overlay keyboard work too: Toolbar's arrow-key model reads it.
6
7
  */
7
8
  /** Everything a focus trap must cycle through. */
8
9
  export declare const FOCUSABLE = "button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Locale data every formatting component shares. Server-safe: no React and
3
+ * no browser API, so a component that renders from a Server Component can
4
+ * import it too. The client half (the provider and the hook) is
5
+ * LocaleProvider.tsx.
6
+ *
7
+ * The rule it carries: a component never formats in the runtime's default
8
+ * locale. The server and the browser can disagree on it, which prints
9
+ * `1,234` on one and `1.234` on the other and breaks hydration, and a
10
+ * consumer could not choose it. Every number, date and calendar convention
11
+ * a component prints is resolved from a locale the consumer can set, which
12
+ * falls back to DEFAULT_LOCALE. scripts/validate-locale-formatting.mjs
13
+ * enforces it.
14
+ */
15
+ /** The locale a component formats in when neither its `locale` prop nor a LocaleProvider sets one. */
16
+ export declare const DEFAULT_LOCALE = "en-US";
17
+ /** A day of the week as `Date.getDay()` numbers it: 0 is Sunday, 6 is Saturday. */
18
+ export type Weekday = 0 | 1 | 2 | 3 | 4 | 5 | 6;
19
+ /**
20
+ * The first day of the week in `locale`, as a `Date.getDay()` number:
21
+ * Sunday (0) in en-US, Monday (1) in de-DE, Saturday (6) in ar-EG. Read
22
+ * from the runtime's CLDR week data where it has it, else from the region.
23
+ */
24
+ export declare function weekStartOf(locale: string): Weekday;
25
+ /** A Sunday-first list of seven, reordered to start on `start`. */
26
+ export declare function rotateWeek<T>(sundayFirst: readonly T[], start: Weekday): T[];
27
+ /** How many days `day` sits after the week's first day: 0 for the first column, 6 for the last. */
28
+ export declare const weekdayOffset: (day: number, start: Weekday) => number;
29
+ /** The seven weekday names in `locale`, Sunday first, at the given width. */
30
+ export declare function weekdayNamesIn(locale: string, width: 'long' | 'short' | 'narrow'): string[];
31
+ /** Whether `locale` is written in English, the language every built-in label defaults to. */
32
+ export declare function isEnglish(locale: string): boolean;
33
+ /** Whether `locale` writes times on a 12-hour clock (en-US) rather than a 24-hour one (en-GB, de-DE). */
34
+ export declare function uses12HourClock(locale: string): boolean;
35
+ /**
36
+ * A number as `locale` writes it, grouped and with its own decimal mark:
37
+ * `1,234.5` in en-US, `1.234,5` in de-DE. Formats are cached per locale.
38
+ */
39
+ export declare function formatNumber(value: number, locale: string): string;
40
+ /**
41
+ * A number on a chart's value axis as `locale` writes it, grouped only from
42
+ * five digits up (`12,000` but `2024`), so a tick that happens to be a year
43
+ * never reads as a quantity.
44
+ */
45
+ export declare function formatAxisNumber(value: number, locale: string): string;
46
+ /** A whole percentage, given as 0 to 100, as `locale` writes it: `64%` in en-US, `٦٤٪` in ar-EG, `64 %` in de-DE. */
47
+ export declare function formatPercent(percent: number, locale: string): string;
@@ -0,0 +1,87 @@
1
+ const DEFAULT_LOCALE = "en-US";
2
+ const SUNDAY_FIRST = new Set(
3
+ "AG AS BD BR BS BT BW BZ CA CN CO DM DO ET GT GU HK HN ID IL IN JM JP KE KH KR LA MH MM MO MT MX MZ NI NP PA PE PH PK PR PT PY SA SG SV TH TT TW UM US VE VI WS YE ZA ZW".split(" ")
4
+ );
5
+ const SATURDAY_FIRST = new Set("AE AF BH DJ DZ EG IQ IR JO KW LY OM QA SD SY".split(" "));
6
+ const weekStartCache = /* @__PURE__ */ new Map();
7
+ function weekStartOf(locale) {
8
+ const cached = weekStartCache.get(locale);
9
+ if (cached !== void 0) return cached;
10
+ let start = 1;
11
+ try {
12
+ const intlLocale = new Intl.Locale(locale);
13
+ const info = intlLocale.getWeekInfo?.() ?? intlLocale.weekInfo;
14
+ if (info) {
15
+ start = info.firstDay % 7;
16
+ } else {
17
+ const region = intlLocale.maximize().region ?? "";
18
+ start = SUNDAY_FIRST.has(region) ? 0 : SATURDAY_FIRST.has(region) ? 6 : 1;
19
+ }
20
+ } catch {
21
+ start = 1;
22
+ }
23
+ weekStartCache.set(locale, start);
24
+ return start;
25
+ }
26
+ function rotateWeek(sundayFirst, start) {
27
+ return [...sundayFirst.slice(start), ...sundayFirst.slice(0, start)];
28
+ }
29
+ const weekdayOffset = (day, start) => (day - start + 7) % 7;
30
+ function weekdayNamesIn(locale, width) {
31
+ const format = new Intl.DateTimeFormat(locale, { weekday: width, timeZone: "UTC" });
32
+ return Array.from({ length: 7 }, (_, day) => format.format(Date.UTC(2023, 0, 1 + day)));
33
+ }
34
+ function isEnglish(locale) {
35
+ try {
36
+ return new Intl.Locale(locale).language === "en";
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+ function uses12HourClock(locale) {
42
+ const cycle = new Intl.DateTimeFormat(locale, { hour: "numeric" }).resolvedOptions().hourCycle;
43
+ return cycle === "h11" || cycle === "h12";
44
+ }
45
+ const numberFormats = /* @__PURE__ */ new Map();
46
+ function formatNumber(value, locale) {
47
+ let format = numberFormats.get(locale);
48
+ if (!format) {
49
+ format = new Intl.NumberFormat(locale, { maximumFractionDigits: 3 });
50
+ numberFormats.set(locale, format);
51
+ }
52
+ return format.format(value);
53
+ }
54
+ const axisFormats = /* @__PURE__ */ new Map();
55
+ function formatAxisNumber(value, locale) {
56
+ let format = axisFormats.get(locale);
57
+ if (!format) {
58
+ format = new Intl.NumberFormat(locale, {
59
+ maximumFractionDigits: 3,
60
+ // 'min2' is CLDR's grouping for short numbers; the type lags the spec.
61
+ useGrouping: "min2"
62
+ });
63
+ axisFormats.set(locale, format);
64
+ }
65
+ return format.format(value);
66
+ }
67
+ const percentFormats = /* @__PURE__ */ new Map();
68
+ function formatPercent(percent, locale) {
69
+ let format = percentFormats.get(locale);
70
+ if (!format) {
71
+ format = new Intl.NumberFormat(locale, { style: "percent", maximumFractionDigits: 0 });
72
+ percentFormats.set(locale, format);
73
+ }
74
+ return format.format(percent / 100);
75
+ }
76
+ export {
77
+ DEFAULT_LOCALE,
78
+ formatAxisNumber,
79
+ formatNumber,
80
+ formatPercent,
81
+ isEnglish,
82
+ rotateWeek,
83
+ uses12HourClock,
84
+ weekStartOf,
85
+ weekdayNamesIn,
86
+ weekdayOffset
87
+ };
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The shortcut grammar and how a shortcut is drawn, with no React and no
3
+ * browser API, so a component that renders from a Server Component can
4
+ * draw or announce a shortcut too. The listener and the hooks are
5
+ * shortcuts.ts, which owns the grammar's description.
6
+ */
7
+ /** A shortcut in the grammar above, such as `mod+k`, `shift+?` or `g i`. */
8
+ export type Shortcut = string;
9
+ /** The platform a shortcut is read and drawn for: `apple` maps `mod` to ⌘, `other` to Ctrl. */
10
+ export type ShortcutPlatform = 'apple' | 'other';
11
+ /** The legends a shortcut is drawn with, by modifier or key name. Merged over the platform's defaults. */
12
+ export type ShortcutKeyLabels = Partial<Record<string, string>>;
13
+ /** One step of a shortcut: its key and the modifiers held with it. */
14
+ export type Step = {
15
+ key: string;
16
+ mod: boolean;
17
+ ctrl: boolean;
18
+ meta: boolean;
19
+ alt: boolean;
20
+ shift: boolean;
21
+ };
22
+ export declare const KEY_ALIASES: Record<string, string>;
23
+ /** A shortcut's steps, parsed once. A step written `ctrl++` would be ambiguous, so `plus` names the key. */
24
+ export declare const parseShortcut: (shortcut: Shortcut) => Step[];
25
+ /** The platform this code runs on, read from the browser. `other` on the server. */
26
+ export declare const detectPlatform: () => ShortcutPlatform;
27
+ /**
28
+ * A shortcut as keycap legends, one array per step: `mod+shift+p` is
29
+ * `[['⇧', '⌘', 'P']]` on a Mac and `[['Ctrl', 'Shift', 'P']]` elsewhere.
30
+ * `labels` replaces any legend, such as `{ ctrl: 'Strg' }` for a German
31
+ * keyboard.
32
+ */
33
+ export declare function shortcutKeys(shortcut: Shortcut, platform: ShortcutPlatform, labels?: ShortcutKeyLabels): string[][];
34
+ /**
35
+ * A shortcut as one line of text, for a menu row: `⇧⌘P` on a Mac and
36
+ * `Ctrl+Shift+P` elsewhere, the steps of a sequence spaced apart.
37
+ */
38
+ export declare function formatShortcut(shortcut: Shortcut, platform: ShortcutPlatform, labels?: ShortcutKeyLabels): string;
39
+ /**
40
+ * A single-step shortcut as an `aria-keyshortcuts` value (`Meta+K` on a Mac,
41
+ * `Control+K` elsewhere). A sequence has no ARIA form, so it gives undefined.
42
+ */
43
+ export declare function shortcutAria(shortcut: Shortcut, platform: ShortcutPlatform): string | undefined;
44
+ /**
45
+ * A shortcut as an `aria-keyshortcuts` value for both platforms at once
46
+ * (`Meta+K Control+K` for `mod+k`), for markup that renders on the server or
47
+ * before the platform is known. Undefined for a sequence.
48
+ */
49
+ export declare function shortcutAriaAnyPlatform(shortcut: Shortcut): string | undefined;
@@ -0,0 +1,129 @@
1
+ const KEY_ALIASES = {
2
+ esc: "escape",
3
+ return: "enter",
4
+ up: "arrowup",
5
+ down: "arrowdown",
6
+ left: "arrowleft",
7
+ right: "arrowright",
8
+ del: "delete",
9
+ plus: "+",
10
+ " ": "space",
11
+ cmd: "meta",
12
+ command: "meta",
13
+ option: "alt",
14
+ control: "ctrl"
15
+ };
16
+ const MODIFIERS = /* @__PURE__ */ new Set(["mod", "ctrl", "meta", "alt", "shift"]);
17
+ const parseStep = (text) => {
18
+ const step = { key: "", mod: false, ctrl: false, meta: false, alt: false, shift: false };
19
+ for (const raw of text.toLowerCase().split("+")) {
20
+ const part = KEY_ALIASES[raw] ?? raw;
21
+ if (MODIFIERS.has(part)) step[part] = true;
22
+ else step.key = part;
23
+ }
24
+ return step;
25
+ };
26
+ const parseShortcut = (shortcut) => shortcut.trim().split(/\s+/).filter(Boolean).map(parseStep);
27
+ const detectPlatform = () => {
28
+ if (typeof navigator === "undefined") return "other";
29
+ const nav = navigator;
30
+ const name = nav.userAgentData?.platform || nav.platform || nav.userAgent || "";
31
+ return /mac|iphone|ipad|ipod/i.test(name) ? "apple" : "other";
32
+ };
33
+ const APPLE_LABELS = {
34
+ mod: "⌘",
35
+ meta: "⌘",
36
+ ctrl: "⌃",
37
+ alt: "⌥",
38
+ shift: "⇧",
39
+ enter: "↩",
40
+ escape: "Esc",
41
+ backspace: "⌫",
42
+ delete: "⌦",
43
+ tab: "⇥",
44
+ space: "Space"
45
+ };
46
+ const OTHER_LABELS = {
47
+ mod: "Ctrl",
48
+ meta: "Meta",
49
+ ctrl: "Ctrl",
50
+ alt: "Alt",
51
+ shift: "Shift",
52
+ enter: "Enter",
53
+ escape: "Esc",
54
+ backspace: "Backspace",
55
+ delete: "Del",
56
+ tab: "Tab",
57
+ space: "Space"
58
+ };
59
+ const SHARED_LABELS = {
60
+ arrowup: "↑",
61
+ arrowdown: "↓",
62
+ arrowleft: "←",
63
+ arrowright: "→",
64
+ home: "Home",
65
+ end: "End",
66
+ pageup: "PgUp",
67
+ pagedown: "PgDn"
68
+ };
69
+ const APPLE_ORDER = ["ctrl", "alt", "shift", "mod", "meta"];
70
+ const OTHER_ORDER = ["mod", "ctrl", "meta", "alt", "shift"];
71
+ function shortcutKeys(shortcut, platform, labels = {}) {
72
+ const table = { ...SHARED_LABELS, ...platform === "apple" ? APPLE_LABELS : OTHER_LABELS };
73
+ const legend = (name) => labels[name] ?? table[name] ?? (/^f\d+$/.test(name) ? name.toUpperCase() : name.length === 1 ? name.toUpperCase() : name);
74
+ return parseShortcut(shortcut).map((step) => {
75
+ const order = platform === "apple" ? APPLE_ORDER : OTHER_ORDER;
76
+ const mods = order.filter((mod) => step[mod]);
77
+ const unique = mods.filter((mod, i) => !mods.slice(0, i).some((m) => legend(m) === legend(mod)));
78
+ return [...unique.map(legend), legend(step.key)];
79
+ });
80
+ }
81
+ function formatShortcut(shortcut, platform, labels = {}) {
82
+ return shortcutKeys(shortcut, platform, labels).map((keys) => keys.join(platform === "apple" ? "" : "+")).join(" ");
83
+ }
84
+ const ARIA_KEYS = {
85
+ ctrl: "Control",
86
+ meta: "Meta",
87
+ alt: "Alt",
88
+ shift: "Shift",
89
+ escape: "Escape",
90
+ enter: "Enter",
91
+ space: "Space",
92
+ tab: "Tab",
93
+ backspace: "Backspace",
94
+ delete: "Delete",
95
+ arrowup: "ArrowUp",
96
+ arrowdown: "ArrowDown",
97
+ arrowleft: "ArrowLeft",
98
+ arrowright: "ArrowRight",
99
+ home: "Home",
100
+ end: "End",
101
+ pageup: "PageUp",
102
+ pagedown: "PageDown"
103
+ };
104
+ function shortcutAria(shortcut, platform) {
105
+ const steps = parseShortcut(shortcut);
106
+ if (steps.length !== 1) return void 0;
107
+ const [step] = steps;
108
+ const names = [
109
+ step.ctrl || step.mod && platform === "other" ? "Control" : null,
110
+ step.meta || step.mod && platform === "apple" ? "Meta" : null,
111
+ step.alt ? "Alt" : null,
112
+ step.shift ? "Shift" : null,
113
+ ARIA_KEYS[step.key] ?? (step.key.length === 1 ? step.key.toUpperCase() : step.key)
114
+ ].filter(Boolean);
115
+ return names.join("+");
116
+ }
117
+ function shortcutAriaAnyPlatform(shortcut) {
118
+ const forms = [shortcutAria(shortcut, "apple"), shortcutAria(shortcut, "other")].filter(Boolean);
119
+ return forms.length > 0 ? [...new Set(forms)].join(" ") : void 0;
120
+ }
121
+ export {
122
+ KEY_ALIASES,
123
+ detectPlatform,
124
+ formatShortcut,
125
+ parseShortcut,
126
+ shortcutAria,
127
+ shortcutAriaAnyPlatform,
128
+ shortcutKeys
129
+ };
@@ -0,0 +1,75 @@
1
+ import { Shortcut, ShortcutPlatform } from './shortcut-keys';
2
+ export { detectPlatform, formatShortcut, parseShortcut, shortcutAria, shortcutKeys, type Shortcut, type ShortcutKeyLabels, type ShortcutPlatform, } from './shortcut-keys';
3
+ /**
4
+ * Keyboard shortcuts: the one document keydown listener every app-level key
5
+ * binding goes through, the grammar a shortcut is written in, and the way it
6
+ * is drawn on each platform.
7
+ *
8
+ * A shortcut is a string: steps separated by spaces, each step modifiers and
9
+ * a key joined by `+`. `mod+k` is ⌘K on Apple platforms and Ctrl+K
10
+ * elsewhere; `shift+?`, `alt+arrowup`, `escape`; `g i` is G then I. Keys are
11
+ * a character or a name (enter, escape, space, tab, backspace, delete, the
12
+ * arrows, home, end, pageup, pagedown, f1 to f12, plus).
13
+ *
14
+ * Who hears a key, in order:
15
+ * - Nothing does while an IME is composing, or once a component has handled
16
+ * the key itself (`event.preventDefault()`), so a list's own arrow keys or
17
+ * an input's own Escape never also fire a shortcut. Escape is the layer
18
+ * stack's while any overlay is open (useLayer), so an `escape` shortcut
19
+ * is for closing something that is not a library overlay.
20
+ * - Nothing does while focus is in a text field, unless the shortcut opts in
21
+ * with `allowInInput` (a palette's Cmd+K should work from a search box).
22
+ * - A `global` shortcut always does.
23
+ * - A `scope`d shortcut does while focus is inside its element, or while
24
+ * nothing has focus and the element sits on the surface in front (the open
25
+ * modal, else the page). Lightbox's arrows are scoped to its panel.
26
+ * - Any other shortcut belongs to the page: it does only while no modal is
27
+ * open and focus is not inside an open overlay (a menu, a popover), the
28
+ * same topmost-only rule the layer stack applies to Escape.
29
+ * When several match, the longest sequence wins, then the shortcut
30
+ * registered last. A matched key's default is prevented.
31
+ *
32
+ * Exactly one document listener exists while any shortcut is registered, and
33
+ * none otherwise. scripts/validate-overlay-listeners.mjs holds every other
34
+ * document key listener in the library and the site to this module.
35
+ */
36
+ export interface ShortcutOptions {
37
+ /** What the shortcut does, in a few words, for a help list built from `useRegisteredShortcuts`. */
38
+ description?: string;
39
+ /** The heading a help list files the shortcut under, such as "Navigation". */
40
+ group?: string;
41
+ /** Whether the shortcut is live. Default true. */
42
+ enabled?: boolean;
43
+ /** Fires only while focus is inside this element (see the module's rules). */
44
+ scope?: React.RefObject<HTMLElement | null>;
45
+ /** Fires whatever is open or focused, outside text fields. Default false. */
46
+ global?: boolean;
47
+ /** Fires while focus is in a text field too. Default false. */
48
+ allowInInput?: boolean;
49
+ }
50
+ /**
51
+ * The platform shortcuts are drawn for. The server and the first client
52
+ * render both say `other`, then the client settles on its own, so drawing a
53
+ * shortcut never breaks hydration.
54
+ */
55
+ export declare function usePlatform(): ShortcutPlatform;
56
+ /**
57
+ * Binds a shortcut (or several, as an array) to `handler` while the component
58
+ * is mounted and `enabled` is not false. The handler and options are read at
59
+ * key time, so passing new ones each render never re-registers the shortcut.
60
+ */
61
+ export declare function useShortcut(shortcut: Shortcut | Shortcut[], handler: (event: KeyboardEvent) => void, options?: ShortcutOptions): void;
62
+ /** A live shortcut as a help list reads it. */
63
+ export interface RegisteredShortcut {
64
+ /** The shortcuts that run it, in the grammar. */
65
+ shortcuts: Shortcut[];
66
+ /** What it does, from the binding's `description`. */
67
+ description: string;
68
+ /** Its heading, from the binding's `group`. */
69
+ group?: string;
70
+ }
71
+ /**
72
+ * Every live shortcut that has a description, in registration order, for a
73
+ * "keyboard shortcuts" help dialog. Updates as shortcuts mount and unmount.
74
+ */
75
+ export declare function useRegisteredShortcuts(): RegisteredShortcut[];