@dxos/react-ui 0.10.0 → 0.11.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 (354) hide show
  1. package/dist/lib/chunk-parse-stack.mjs +1566 -0
  2. package/dist/lib/chunk-parse-stack.mjs.map +1 -0
  3. package/dist/lib/index.mjs +5220 -0
  4. package/dist/lib/index.mjs.map +1 -0
  5. package/dist/lib/testing.mjs +144 -0
  6. package/dist/lib/testing.mjs.map +1 -0
  7. package/dist/lib/translations.mjs +38 -0
  8. package/dist/lib/translations.mjs.map +1 -0
  9. package/dist/types/src/components/Avatars/Avatar.d.ts +1 -6
  10. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  11. package/dist/types/src/components/Avatars/AvatarContext.d.ts +9 -0
  12. package/dist/types/src/components/Avatars/AvatarContext.d.ts.map +1 -0
  13. package/dist/types/src/components/Avatars/index.d.ts +1 -0
  14. package/dist/types/src/components/Avatars/index.d.ts.map +1 -1
  15. package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts +1 -1
  16. package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  17. package/dist/types/src/components/Breadcrumb/Breadcrumb.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Breadcrumb/Breadcrumb.theme.d.ts.map +1 -1
  19. package/dist/types/src/components/Button/Button.d.ts +1 -6
  20. package/dist/types/src/components/Button/Button.d.ts.map +1 -1
  21. package/dist/types/src/components/Button/ButtonGroupContext.d.ts +9 -0
  22. package/dist/types/src/components/Button/ButtonGroupContext.d.ts.map +1 -0
  23. package/dist/types/src/components/Button/IconButton.d.ts.map +1 -1
  24. package/dist/types/src/components/Button/IconButton.stories.d.ts.map +1 -1
  25. package/dist/types/src/components/Button/IconButton.theme.d.ts +1 -0
  26. package/dist/types/src/components/Button/IconButton.theme.d.ts.map +1 -1
  27. package/dist/types/src/components/Button/SystemIconButton.d.ts +1 -1
  28. package/dist/types/src/components/Button/SystemIconButton.d.ts.map +1 -1
  29. package/dist/types/src/components/Button/index.d.ts +1 -0
  30. package/dist/types/src/components/Button/index.d.ts.map +1 -1
  31. package/dist/types/src/components/Calendar/Calendar.d.ts +0 -2
  32. package/dist/types/src/components/Calendar/Calendar.d.ts.map +1 -1
  33. package/dist/types/src/components/Calendar/index.d.ts +1 -0
  34. package/dist/types/src/components/Calendar/index.d.ts.map +1 -1
  35. package/dist/types/src/components/Calendar/parse-calendar-date.d.ts +3 -0
  36. package/dist/types/src/components/Calendar/parse-calendar-date.d.ts.map +1 -0
  37. package/dist/types/src/components/Card/Card.d.ts +42 -15
  38. package/dist/types/src/components/Card/Card.d.ts.map +1 -1
  39. package/dist/types/src/components/Card/Card.theme.d.ts +0 -1
  40. package/dist/types/src/components/Card/Card.theme.d.ts.map +1 -1
  41. package/dist/types/src/components/Carousel/Carousel.d.ts +2 -4
  42. package/dist/types/src/components/Carousel/Carousel.d.ts.map +1 -1
  43. package/dist/types/src/components/Carousel/CarouselContext.d.ts +8 -0
  44. package/dist/types/src/components/Carousel/CarouselContext.d.ts.map +1 -0
  45. package/dist/types/src/components/Carousel/index.d.ts +1 -0
  46. package/dist/types/src/components/Carousel/index.d.ts.map +1 -1
  47. package/dist/types/src/components/Clipboard/ClipboardContext.d.ts +7 -0
  48. package/dist/types/src/components/Clipboard/ClipboardContext.d.ts.map +1 -0
  49. package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts +0 -6
  50. package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts.map +1 -1
  51. package/dist/types/src/components/Clipboard/index.d.ts +1 -1
  52. package/dist/types/src/components/Clipboard/index.d.ts.map +1 -1
  53. package/dist/types/src/components/Column/Column.d.ts +7 -12
  54. package/dist/types/src/components/Column/Column.d.ts.map +1 -1
  55. package/dist/types/src/components/Column/Column.stories.d.ts +2 -2
  56. package/dist/types/src/components/Column/Column.theme.d.ts +0 -1
  57. package/dist/types/src/components/Column/Column.theme.d.ts.map +1 -1
  58. package/dist/types/src/components/Column/ColumnContext.d.ts +9 -0
  59. package/dist/types/src/components/Column/ColumnContext.d.ts.map +1 -0
  60. package/dist/types/src/components/Column/index.d.ts +1 -0
  61. package/dist/types/src/components/Column/index.d.ts.map +1 -1
  62. package/dist/types/src/components/Column/withColumn.d.ts +40 -4
  63. package/dist/types/src/components/Column/withColumn.d.ts.map +1 -1
  64. package/dist/types/src/components/DatePicker/DatePicker.d.ts +0 -10
  65. package/dist/types/src/components/DatePicker/DatePicker.d.ts.map +1 -1
  66. package/dist/types/src/components/DatePicker/DatePickerContext.d.ts +13 -0
  67. package/dist/types/src/components/DatePicker/DatePickerContext.d.ts.map +1 -0
  68. package/dist/types/src/components/DatePicker/index.d.ts +1 -0
  69. package/dist/types/src/components/DatePicker/index.d.ts.map +1 -1
  70. package/dist/types/src/components/Dialog/AlertDialog.d.ts +3 -3
  71. package/dist/types/src/components/Dialog/Dialog.d.ts +3 -3
  72. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts +5 -10
  73. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts.map +1 -1
  74. package/dist/types/src/components/ErrorFallback/index.d.ts +1 -0
  75. package/dist/types/src/components/ErrorFallback/index.d.ts.map +1 -1
  76. package/dist/types/src/components/ErrorFallback/parse-stack.d.ts +8 -0
  77. package/dist/types/src/components/ErrorFallback/parse-stack.d.ts.map +1 -0
  78. package/dist/types/src/components/Focus/Focus.d.ts +2 -10
  79. package/dist/types/src/components/Focus/Focus.d.ts.map +1 -1
  80. package/dist/types/src/components/Focus/FocusContext.d.ts +10 -0
  81. package/dist/types/src/components/Focus/FocusContext.d.ts.map +1 -0
  82. package/dist/types/src/components/Focus/index.d.ts +1 -0
  83. package/dist/types/src/components/Focus/index.d.ts.map +1 -1
  84. package/dist/types/src/components/Input/Input.d.ts +9 -10
  85. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  86. package/dist/types/src/components/Input/Input.stories.d.ts +7 -2
  87. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  88. package/dist/types/src/components/Input/Input.theme.d.ts +13 -0
  89. package/dist/types/src/components/Input/Input.theme.d.ts.map +1 -1
  90. package/dist/types/src/components/Input/InputTriggerContext.d.ts +15 -0
  91. package/dist/types/src/components/Input/InputTriggerContext.d.ts.map +1 -0
  92. package/dist/types/src/components/Input/SegmentedInput.d.ts.map +1 -1
  93. package/dist/types/src/components/Input/index.d.ts +1 -0
  94. package/dist/types/src/components/Input/index.d.ts.map +1 -1
  95. package/dist/types/src/components/Main/Main.d.ts +2 -35
  96. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  97. package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
  98. package/dist/types/src/components/Main/Main.theme.d.ts.map +1 -1
  99. package/dist/types/src/components/Main/MainContext.d.ts +38 -0
  100. package/dist/types/src/components/Main/MainContext.d.ts.map +1 -0
  101. package/dist/types/src/components/Main/index.d.ts +1 -0
  102. package/dist/types/src/components/Main/index.d.ts.map +1 -1
  103. package/dist/types/src/components/MediaPlayer/MediaPlayer.d.ts +1 -17
  104. package/dist/types/src/components/MediaPlayer/MediaPlayer.d.ts.map +1 -1
  105. package/dist/types/src/components/MediaPlayer/index.d.ts +1 -0
  106. package/dist/types/src/components/MediaPlayer/index.d.ts.map +1 -1
  107. package/dist/types/src/components/MediaPlayer/media-kind.d.ts +18 -0
  108. package/dist/types/src/components/MediaPlayer/media-kind.d.ts.map +1 -0
  109. package/dist/types/src/components/Menu/DropdownMenu.d.ts +6 -22
  110. package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -1
  111. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts +1 -11
  112. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -1
  113. package/dist/types/src/components/Menu/DropdownMenuContext.d.ts +27 -0
  114. package/dist/types/src/components/Menu/DropdownMenuContext.d.ts.map +1 -0
  115. package/dist/types/src/components/Menu/index.d.ts +1 -0
  116. package/dist/types/src/components/Menu/index.d.ts.map +1 -1
  117. package/dist/types/src/components/Message/Message.d.ts +11 -6
  118. package/dist/types/src/components/Message/Message.d.ts.map +1 -1
  119. package/dist/types/src/components/Message/Message.stories.d.ts +4 -1
  120. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  121. package/dist/types/src/components/Message/Message.theme.d.ts.map +1 -1
  122. package/dist/types/src/components/Message/index.d.ts +1 -0
  123. package/dist/types/src/components/Message/index.d.ts.map +1 -1
  124. package/dist/types/src/components/Message/message-icons.d.ts +3 -0
  125. package/dist/types/src/components/Message/message-icons.d.ts.map +1 -0
  126. package/dist/types/src/components/Panel/Panel.d.ts +4 -4
  127. package/dist/types/src/components/Panel/Panel.stories.d.ts.map +1 -1
  128. package/dist/types/src/components/Panel/Panel.theme.d.ts +1 -1
  129. package/dist/types/src/components/Panel/Panel.theme.d.ts.map +1 -1
  130. package/dist/types/src/components/Popover/Popover.d.ts +6 -10
  131. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  132. package/dist/types/src/components/Popover/PopoverContext.d.ts +29 -0
  133. package/dist/types/src/components/Popover/PopoverContext.d.ts.map +1 -0
  134. package/dist/types/src/components/Popover/index.d.ts +1 -0
  135. package/dist/types/src/components/Popover/index.d.ts.map +1 -1
  136. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +2 -2
  137. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +2 -2
  138. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +3 -16
  139. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
  140. package/dist/types/src/components/ScrollContainer/ScrollContainerContext.d.ts +16 -0
  141. package/dist/types/src/components/ScrollContainer/ScrollContainerContext.d.ts.map +1 -0
  142. package/dist/types/src/components/ScrollContainer/index.d.ts +1 -0
  143. package/dist/types/src/components/ScrollContainer/index.d.ts.map +1 -1
  144. package/dist/types/src/components/Slider/Slider.d.ts +25 -0
  145. package/dist/types/src/components/Slider/Slider.d.ts.map +1 -0
  146. package/dist/types/src/components/Slider/Slider.stories.d.ts +29 -0
  147. package/dist/types/src/components/Slider/Slider.stories.d.ts.map +1 -0
  148. package/dist/types/src/components/Slider/Slider.test.d.ts +2 -0
  149. package/dist/types/src/components/Slider/Slider.test.d.ts.map +1 -0
  150. package/dist/types/src/components/Slider/Slider.theme.d.ts +7 -0
  151. package/dist/types/src/components/Slider/Slider.theme.d.ts.map +1 -0
  152. package/dist/types/src/components/Slider/index.d.ts +2 -0
  153. package/dist/types/src/components/Slider/index.d.ts.map +1 -0
  154. package/dist/types/src/components/Splitter/Splitter.d.ts +3 -3
  155. package/dist/types/src/components/Status/Status.d.ts.map +1 -1
  156. package/dist/types/src/components/Toolbar/Toolbar.d.ts +4 -2
  157. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  158. package/dist/types/src/components/Toolbar/Toolbar.theme.d.ts.map +1 -1
  159. package/dist/types/src/components/Tooltip/TextTooltip.d.ts.map +1 -1
  160. package/dist/types/src/components/Tooltip/Tooltip.d.ts +2 -23
  161. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  162. package/dist/types/src/components/Tooltip/TooltipContext.d.ts +35 -0
  163. package/dist/types/src/components/Tooltip/TooltipContext.d.ts.map +1 -0
  164. package/dist/types/src/components/Tooltip/index.d.ts +1 -0
  165. package/dist/types/src/components/Tooltip/index.d.ts.map +1 -1
  166. package/dist/types/src/components/index.d.ts +1 -0
  167. package/dist/types/src/components/index.d.ts.map +1 -1
  168. package/dist/types/src/exemplars/generics.stories.d.ts +1 -1
  169. package/dist/types/src/hooks/useIconHref.d.ts +8 -0
  170. package/dist/types/src/hooks/useIconHref.d.ts.map +1 -1
  171. package/dist/types/src/hooks/useThemeContext.d.ts +2 -1
  172. package/dist/types/src/hooks/useThemeContext.d.ts.map +1 -1
  173. package/dist/types/src/hooks/useThemeContext.test.d.ts +2 -0
  174. package/dist/types/src/hooks/useThemeContext.test.d.ts.map +1 -0
  175. package/dist/types/src/playground/Density.stories.d.ts +11 -0
  176. package/dist/types/src/playground/Density.stories.d.ts.map +1 -0
  177. package/dist/types/src/playground/Elevation.stories.d.ts +14 -0
  178. package/dist/types/src/playground/Elevation.stories.d.ts.map +1 -0
  179. package/dist/types/src/primitives/Container/Container.d.ts +1 -1
  180. package/dist/types/src/primitives/Container/Container.d.ts.map +1 -1
  181. package/dist/types/src/primitives/DensityProvider/DensityContext.d.ts +6 -0
  182. package/dist/types/src/primitives/DensityProvider/DensityContext.d.ts.map +1 -0
  183. package/dist/types/src/primitives/DensityProvider/DensityProvider.d.ts +10 -4
  184. package/dist/types/src/primitives/DensityProvider/DensityProvider.d.ts.map +1 -1
  185. package/dist/types/src/primitives/DensityProvider/index.d.ts +1 -0
  186. package/dist/types/src/primitives/DensityProvider/index.d.ts.map +1 -1
  187. package/dist/types/src/primitives/Flex/Flex.d.ts +1 -1
  188. package/dist/types/src/primitives/Flex/Flex.d.ts.map +1 -1
  189. package/dist/types/src/primitives/Grid/Grid.d.ts +1 -1
  190. package/dist/types/src/primitives/Grid/Grid.d.ts.map +1 -1
  191. package/dist/types/src/primitives/ThemeProvider/IconRegistry.d.ts +15 -0
  192. package/dist/types/src/primitives/ThemeProvider/IconRegistry.d.ts.map +1 -0
  193. package/dist/types/src/primitives/ThemeProvider/ThemeProvider.d.ts +1 -2
  194. package/dist/types/src/primitives/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  195. package/dist/types/src/primitives/ThemeProvider/ThemeProvider.stories.d.ts +1 -1
  196. package/dist/types/src/primitives/ThemeProvider/TranslationsContext.d.ts +112 -0
  197. package/dist/types/src/primitives/ThemeProvider/TranslationsContext.d.ts.map +1 -0
  198. package/dist/types/src/primitives/ThemeProvider/TranslationsProvider.d.ts +0 -109
  199. package/dist/types/src/primitives/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  200. package/dist/types/src/primitives/ThemeProvider/icon-registry.d.ts +34 -0
  201. package/dist/types/src/primitives/ThemeProvider/icon-registry.d.ts.map +1 -0
  202. package/dist/types/src/primitives/ThemeProvider/index.d.ts +3 -1
  203. package/dist/types/src/primitives/ThemeProvider/index.d.ts.map +1 -1
  204. package/dist/types/src/testing/decorators/withTheme.d.ts +1 -1
  205. package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
  206. package/dist/types/src/theme/defaultTheme.d.ts.map +1 -1
  207. package/dist/types/src/theme/index.d.ts +1 -0
  208. package/dist/types/src/theme/index.d.ts.map +1 -1
  209. package/dist/types/src/util/slots.d.ts +6 -3
  210. package/dist/types/src/util/slots.d.ts.map +1 -1
  211. package/dist/types/src/util/slots.stories.d.ts +14 -0
  212. package/dist/types/src/util/slots.stories.d.ts.map +1 -0
  213. package/dist/types/tsconfig.tsbuildinfo +1 -1
  214. package/package.json +25 -27
  215. package/src/components/Avatars/Avatar.tsx +1 -11
  216. package/src/components/Avatars/AvatarContext.ts +16 -0
  217. package/src/components/Avatars/index.ts +2 -0
  218. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +27 -25
  219. package/src/components/Breadcrumb/Breadcrumb.theme.ts +7 -5
  220. package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
  221. package/src/components/Button/Button.tsx +2 -11
  222. package/src/components/Button/ButtonGroupContext.ts +17 -0
  223. package/src/components/Button/IconButton.stories.tsx +2 -3
  224. package/src/components/Button/IconButton.theme.ts +15 -2
  225. package/src/components/Button/IconButton.tsx +6 -1
  226. package/src/components/Button/SystemIconButton.tsx +23 -16
  227. package/src/components/Button/index.ts +2 -0
  228. package/src/components/Calendar/Calendar.theme.ts +5 -5
  229. package/src/components/Calendar/Calendar.tsx +1 -3
  230. package/src/components/Calendar/index.ts +2 -0
  231. package/src/components/Calendar/parse-calendar-date.ts +9 -0
  232. package/src/components/Card/Card.theme.ts +48 -38
  233. package/src/components/Card/Card.tsx +77 -16
  234. package/src/components/Carousel/Carousel.tsx +4 -11
  235. package/src/components/Carousel/CarouselContext.ts +17 -0
  236. package/src/components/Carousel/index.ts +2 -0
  237. package/src/components/Clipboard/ClipboardContext.ts +20 -0
  238. package/src/components/Clipboard/ClipboardProvider.tsx +2 -12
  239. package/src/components/Clipboard/CopyButton.tsx +1 -1
  240. package/src/components/Clipboard/index.ts +1 -1
  241. package/src/components/Column/Column.stories.tsx +2 -2
  242. package/src/components/Column/Column.theme.ts +2 -11
  243. package/src/components/Column/Column.tsx +35 -57
  244. package/src/components/Column/ColumnContext.ts +22 -0
  245. package/src/components/Column/index.ts +2 -0
  246. package/src/components/Column/withColumn.ts +41 -4
  247. package/src/components/DatePicker/DatePicker.theme.ts +2 -2
  248. package/src/components/DatePicker/DatePicker.tsx +1 -14
  249. package/src/components/DatePicker/DatePickerContext.ts +21 -0
  250. package/src/components/DatePicker/index.ts +2 -0
  251. package/src/components/ErrorFallback/ErrorStack.tsx +8 -28
  252. package/src/components/ErrorFallback/index.ts +1 -0
  253. package/src/components/ErrorFallback/parse-stack.ts +33 -0
  254. package/src/components/Focus/Focus.stories.tsx +6 -6
  255. package/src/components/Focus/Focus.tsx +2 -30
  256. package/src/components/Focus/FocusContext.ts +22 -0
  257. package/src/components/Focus/index.ts +2 -0
  258. package/src/components/Image/Image.tsx +1 -1
  259. package/src/components/Input/Input.stories.tsx +63 -48
  260. package/src/components/Input/Input.theme.ts +33 -27
  261. package/src/components/Input/Input.tsx +46 -43
  262. package/src/components/Input/InputTriggerContext.ts +45 -0
  263. package/src/components/Input/SegmentedInput.tsx +2 -1
  264. package/src/components/Input/index.ts +2 -0
  265. package/src/components/Main/Main.stories.tsx +2 -1
  266. package/src/components/Main/Main.theme.ts +10 -1
  267. package/src/components/Main/Main.tsx +1 -115
  268. package/src/components/Main/MainContext.ts +126 -0
  269. package/src/components/Main/index.ts +2 -0
  270. package/src/components/MediaPlayer/MediaPlayer.tsx +16 -47
  271. package/src/components/MediaPlayer/index.ts +2 -0
  272. package/src/components/MediaPlayer/media-kind.ts +41 -0
  273. package/src/components/Menu/DropdownMenu.tsx +27 -44
  274. package/src/components/Menu/DropdownMenuContext.ts +35 -0
  275. package/src/components/Menu/Menu.theme.ts +3 -3
  276. package/src/components/Menu/index.ts +2 -0
  277. package/src/components/Message/Message.stories.tsx +32 -15
  278. package/src/components/Message/Message.theme.ts +8 -2
  279. package/src/components/Message/Message.tsx +47 -23
  280. package/src/components/Message/index.ts +2 -0
  281. package/src/components/Message/message-icons.ts +16 -0
  282. package/src/components/Panel/Panel.stories.tsx +15 -2
  283. package/src/components/Panel/Panel.theme.ts +15 -6
  284. package/src/components/Popover/Popover.theme.ts +1 -1
  285. package/src/components/Popover/Popover.tsx +22 -37
  286. package/src/components/Popover/PopoverContext.ts +32 -0
  287. package/src/components/Popover/index.ts +2 -0
  288. package/src/components/ScrollContainer/ScrollContainer.stories.tsx +1 -1
  289. package/src/components/ScrollContainer/ScrollContainer.tsx +1 -18
  290. package/src/components/ScrollContainer/ScrollContainerContext.ts +25 -0
  291. package/src/components/ScrollContainer/index.ts +2 -0
  292. package/src/components/Select/Select.theme.ts +2 -2
  293. package/src/components/Slider/Slider.stories.tsx +107 -0
  294. package/src/components/Slider/Slider.test.tsx +105 -0
  295. package/src/components/Slider/Slider.theme.ts +38 -0
  296. package/src/components/Slider/Slider.tsx +64 -0
  297. package/src/components/Slider/index.ts +5 -0
  298. package/src/components/Status/Status.theme.ts +1 -1
  299. package/src/components/Status/Status.tsx +0 -1
  300. package/src/components/Tag/Tag.stories.tsx +1 -1
  301. package/src/components/Toolbar/Toolbar.theme.ts +14 -5
  302. package/src/components/Toolbar/Toolbar.tsx +5 -1
  303. package/src/components/Tooltip/TextTooltip.tsx +2 -1
  304. package/src/components/Tooltip/Tooltip.tsx +12 -35
  305. package/src/components/Tooltip/TooltipContext.ts +41 -0
  306. package/src/components/Tooltip/index.ts +2 -0
  307. package/src/components/index.ts +1 -0
  308. package/src/hooks/useIconHref.ts +26 -5
  309. package/src/hooks/useThemeContext.test.tsx +33 -0
  310. package/src/hooks/useThemeContext.ts +28 -3
  311. package/src/playground/Density.stories.tsx +41 -0
  312. package/src/playground/Elevation.stories.tsx +348 -0
  313. package/src/primitives/DensityProvider/DensityContext.ts +15 -0
  314. package/src/primitives/DensityProvider/DensityProvider.tsx +12 -6
  315. package/src/primitives/DensityProvider/index.ts +1 -0
  316. package/src/primitives/Flex/Flex.stories.tsx +1 -1
  317. package/src/primitives/Grid/Grid.stories.tsx +1 -1
  318. package/src/primitives/ThemeProvider/IconRegistry.tsx +42 -0
  319. package/src/primitives/ThemeProvider/ThemeProvider.tsx +16 -15
  320. package/src/primitives/ThemeProvider/TranslationsContext.ts +24 -0
  321. package/src/primitives/ThemeProvider/TranslationsProvider.tsx +4 -16
  322. package/src/primitives/ThemeProvider/icon-registry.ts +272 -0
  323. package/src/primitives/ThemeProvider/index.ts +9 -1
  324. package/src/testing/decorators/withLayout.tsx +4 -4
  325. package/src/testing/decorators/withLayoutVariants.tsx +3 -3
  326. package/src/testing/decorators/withTheme.tsx +1 -2
  327. package/src/theme/defaultTheme.ts +2 -0
  328. package/src/theme/index.ts +1 -0
  329. package/src/util/slots.stories.tsx +80 -0
  330. package/src/util/slots.ts +14 -5
  331. package/dist/lib/browser/chunk-CMHHVHX3.mjs +0 -46
  332. package/dist/lib/browser/chunk-CMHHVHX3.mjs.map +0 -7
  333. package/dist/lib/browser/chunk-GTHV4WYK.mjs +0 -1499
  334. package/dist/lib/browser/chunk-GTHV4WYK.mjs.map +0 -7
  335. package/dist/lib/browser/index.mjs +0 -5632
  336. package/dist/lib/browser/index.mjs.map +0 -7
  337. package/dist/lib/browser/meta.json +0 -1
  338. package/dist/lib/browser/testing/index.mjs +0 -133
  339. package/dist/lib/browser/testing/index.mjs.map +0 -7
  340. package/dist/lib/browser/translations.mjs +0 -9
  341. package/dist/lib/browser/translations.mjs.map +0 -7
  342. package/dist/lib/node-esm/chunk-3VSKWNCQ.mjs +0 -1501
  343. package/dist/lib/node-esm/chunk-3VSKWNCQ.mjs.map +0 -7
  344. package/dist/lib/node-esm/chunk-P4KFQGJI.mjs +0 -48
  345. package/dist/lib/node-esm/chunk-P4KFQGJI.mjs.map +0 -7
  346. package/dist/lib/node-esm/index.mjs +0 -5633
  347. package/dist/lib/node-esm/index.mjs.map +0 -7
  348. package/dist/lib/node-esm/meta.json +0 -1
  349. package/dist/lib/node-esm/testing/index.mjs +0 -134
  350. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  351. package/dist/lib/node-esm/translations.mjs +0 -10
  352. package/dist/lib/node-esm/translations.mjs.map +0 -7
  353. package/src/components/Column/AUDIT.md +0 -148
  354. package/src/components/Focus/AUDIT.md +0 -43
@@ -8,6 +8,7 @@ import React from 'react';
8
8
  import { type MessageValence } from '@dxos/ui-types';
9
9
 
10
10
  import { withLayoutVariants, withTheme } from '../../testing';
11
+ import { Icon } from '../Icon';
11
12
  import {
12
13
  type CheckboxProps,
13
14
  type DateInputProps,
@@ -93,19 +94,6 @@ export default meta;
93
94
 
94
95
  type Story = StoryObj<StoryArgs & Variant>;
95
96
 
96
- export const Density: Story = {
97
- render: () => (
98
- <div className='flex flex-col gap-4'>
99
- {(['lg', 'md', 'sm', 'xs'] as const).map((density) => (
100
- <Input.Root key={density}>
101
- <Input.Label>{`density="${density}"`}</Input.Label>
102
- <Input.TextInput density={density} placeholder={`This is a density:${density} input`} />
103
- </Input.Root>
104
- ))}
105
- </div>
106
- ),
107
- };
108
-
109
97
  export const Subdued: Story = {
110
98
  args: {
111
99
  kind: 'text',
@@ -179,6 +167,68 @@ export const TextArea: Story = {
179
167
  },
180
168
  };
181
169
 
170
+ /**
171
+ * Native HTML input types. `Input.TextInput` accepts every standard
172
+ * `<input type="…">` value via its `type` prop; this story exercises the most
173
+ * commonly used ones so the rendering across themes/browsers can be
174
+ * inspected at a glance.
175
+ */
176
+ const TEXT_INPUT_TYPES: { type: string; placeholder: string }[] = [
177
+ { type: 'text', placeholder: 'Plain text' },
178
+ { type: 'email', placeholder: 'name@example.com' },
179
+ { type: 'password', placeholder: '••••••••' },
180
+ { type: 'search', placeholder: 'Search…' },
181
+ { type: 'tel', placeholder: '+1 (555) 555-5555' },
182
+ { type: 'url', placeholder: 'https://example.com' },
183
+ { type: 'number', placeholder: '42' },
184
+ { type: 'date', placeholder: '' },
185
+ { type: 'time', placeholder: '' },
186
+ { type: 'datetime-local', placeholder: '' },
187
+ { type: 'month', placeholder: '' },
188
+ { type: 'week', placeholder: '' },
189
+ ];
190
+
191
+ export const _TextInput: Story = {
192
+ render: () => (
193
+ <div className='flex flex-col gap-3 min-w-[24rem]'>
194
+ {TEXT_INPUT_TYPES.map(({ type, placeholder }) => (
195
+ <Input.Root key={type}>
196
+ <Input.Label>{`type="${type}"`}</Input.Label>
197
+ <Input.TextInput type={type} placeholder={placeholder} />
198
+ </Input.Root>
199
+ ))}
200
+ </div>
201
+ ),
202
+ };
203
+
204
+ /**
205
+ * MUI-style adornments: text or icon placed inside the input container. The container carries the
206
+ * surface/border/focus (via `focus-within`) and the field renders bare. `subdued` drops the box for a
207
+ * borderless row (compose a bottom rule via `classNames`).
208
+ */
209
+ export const TextInputAdornments: Story = {
210
+ render: () => (
211
+ <div className='flex flex-col gap-4 min-w-[28rem]'>
212
+ <Input.Root>
213
+ <Input.Label>Start icon</Input.Label>
214
+ <Input.TextInput start={<Icon icon='ph--magnifying-glass--regular' size={4} />} placeholder='Search…' />
215
+ </Input.Root>
216
+ <Input.Root>
217
+ <Input.Label>End text</Input.Label>
218
+ <Input.TextInput end={<span className='text-sm'>.dxos.org</span>} placeholder='workspace' />
219
+ </Input.Root>
220
+ <Input.Root>
221
+ <Input.Label>Both</Input.Label>
222
+ <Input.TextInput
223
+ start={<span className='text-sm'>$</span>}
224
+ end={<Icon icon='ph--currency-circle-dollar--regular' size={4} />}
225
+ placeholder='0.00'
226
+ />
227
+ </Input.Root>
228
+ </div>
229
+ ),
230
+ };
231
+
182
232
  export const PinInput: Story = {
183
233
  args: {
184
234
  kind: 'pin',
@@ -282,38 +332,3 @@ export const Switch: Story = {
282
332
  description: 'On or off',
283
333
  },
284
334
  };
285
-
286
- /**
287
- * Native HTML input types. `Input.TextInput` accepts every standard
288
- * `<input type="…">` value via its `type` prop; this story exercises the most
289
- * commonly used ones so the rendering across themes/browsers can be
290
- * inspected at a glance.
291
- */
292
- const TEXT_INPUT_TYPES: { type: string; placeholder: string }[] = [
293
- { type: 'text', placeholder: 'Plain text' },
294
- { type: 'email', placeholder: 'name@example.com' },
295
- { type: 'password', placeholder: '••••••••' },
296
- { type: 'search', placeholder: 'Search…' },
297
- { type: 'tel', placeholder: '+1 (555) 555-5555' },
298
- { type: 'url', placeholder: 'https://example.com' },
299
- { type: 'number', placeholder: '42' },
300
- { type: 'date', placeholder: '' },
301
- { type: 'time', placeholder: '' },
302
- { type: 'datetime-local', placeholder: '' },
303
- { type: 'month', placeholder: '' },
304
- { type: 'week', placeholder: '' },
305
- { type: 'color', placeholder: '' },
306
- ];
307
-
308
- export const TextInputTypes: Story = {
309
- render: () => (
310
- <div className='flex flex-col gap-3 min-w-[24rem]'>
311
- {TEXT_INPUT_TYPES.map(({ type, placeholder }) => (
312
- <Input.Root key={type}>
313
- <Input.Label>{`type="${type}"`}</Input.Label>
314
- <Input.TextInput type={type} placeholder={placeholder} />
315
- </Input.Root>
316
- ))}
317
- </div>
318
- ),
319
- };
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { densityDimensions, staticDisabled } from '@dxos/ui-theme';
5
+ import { staticDisabled } from '@dxos/ui-theme';
6
6
  import { getSize, mx, sizeValue, snapSize, textValence } from '@dxos/ui-theme';
7
7
  import {
8
8
  type ComponentFragment,
@@ -48,19 +48,23 @@ const valence = (valence?: MessageValence) => {
48
48
  }
49
49
  };
50
50
 
51
+ // Height and inline padding come from the density knobs (theme/spacing.css) rather than utilities,
52
+ // so a density class on any ancestor resizes the control without a matching React prop.
53
+ const controlSize = 'min-h-(--dx-control) px-(--dx-control-pad) leading-(--dx-control-leading)';
54
+
51
55
  const sharedSubduedInputStyles: ComponentFragment<InputStyleProps> = (props) => [
52
56
  '[[data-drag-autoscroll="active"]_&]:pointer-events-none',
53
57
  'py-0 w-full bg-transparent text-current placeholder-placeholder',
54
58
  'dx-focus-subdued',
55
- densityDimensions(props.density),
59
+ controlSize,
56
60
  props.disabled && staticDisabled,
57
61
  ];
58
62
 
59
63
  const sharedDefaultInputStyles: ComponentFragment<InputStyleProps> = (props) => [
60
64
  '[[data-drag-autoscroll="active"]_&]:pointer-events-none',
61
- 'py-0 w-full text-base-fg rounded-xs placeholder-placeholder',
62
- textInputSurfaceFocus,
63
- densityDimensions(props.density),
65
+ 'py-0 w-full text-base-fg placeholder-placeholder',
66
+ 'dx-input',
67
+ controlSize,
64
68
  props.disabled ? staticDisabled : textInputSurfaceHover,
65
69
  ];
66
70
 
@@ -80,15 +84,26 @@ const input: ComponentFunction<InputStyleProps> = (props, ...etc) =>
80
84
  ? mx(...sharedSubduedInputStyles(props), ...etc)
81
85
  : props.variant === 'static'
82
86
  ? mx(...sharedStaticInputStyles(props), ...etc)
83
- : mx(
84
- ...sharedDefaultInputStyles(props),
85
- !props.disabled && 'dx-focus-ring',
86
- valence(props.validationValence),
87
- ...etc,
88
- );
87
+ : mx(...sharedDefaultInputStyles(props), valence(props.validationValence), ...etc);
89
88
 
90
89
  const textArea: ComponentFunction<InputStyleProps> = (props, ...etc) => input(props, ...etc);
91
90
 
91
+ // Container that carries the input surface/border/focus when the field has adornments; the inner
92
+ // `<input>` renders "bare" (subdued) so the box wraps the whole row (start adornment · field · end).
93
+ const container: ComponentFunction<InputStyleProps> = (props, ...etc) =>
94
+ props.variant === 'subdued' || props.variant === 'static'
95
+ ? mx('flex items-center w-full', props.disabled && staticDisabled, ...etc)
96
+ : mx(
97
+ // `p-0` cancels dx-input's default padding: the inset comes from the adornments and the inner field.
98
+ 'flex items-center w-full dx-input p-0',
99
+ valence(props.validationValence),
100
+ props.disabled ? staticDisabled : textInputSurfaceHover,
101
+ ...etc,
102
+ );
103
+
104
+ const adornment: ComponentFunction<Partial<{ side: 'start' | 'end' }>> = (props, ...etc) =>
105
+ mx('shrink-0 flex items-center gap-1 text-description', props.side === 'start' ? 'ps-2' : 'pe-2', ...etc);
106
+
92
107
  const checkbox: ComponentFunction<InputStyleProps> = ({ size = 4 }, ...etc) =>
93
108
  mx('dx-checkbox dx-focus-ring', getSize(size), ...etc);
94
109
 
@@ -100,13 +115,7 @@ const switch_: ComponentFunction<InputStyleProps> = (_props, ...etc) => mx('dx-c
100
115
  const pin: ComponentFunction<InputStyleProps> = (props, ...etc) =>
101
116
  mx(
102
117
  'font-mono selection:bg-transparent mx-auto',
103
- props.density === 'lg'
104
- ? 'text-lg'
105
- : props.density === 'sm'
106
- ? 'text-sm'
107
- : props.density === 'xs'
108
- ? 'text-xs'
109
- : 'text-base pointer-fine:text-sm',
118
+ props.density === 'lg' ? 'text-lg' : props.density === 'sm' ? 'text-sm' : 'text-base pointer-fine:text-sm',
110
119
  props.disabled && 'cursor-not-allowed',
111
120
  ...etc,
112
121
  );
@@ -114,14 +123,9 @@ const pin: ComponentFunction<InputStyleProps> = (props, ...etc) =>
114
123
  const segment: ComponentFunction<InputStyleProps> = (props, ...etc) =>
115
124
  mx(
116
125
  'flex items-center justify-center tabular-nums',
117
- props.density === 'lg'
118
- ? 'size-12 rounded-xs'
119
- : props.density === 'sm'
120
- ? 'size-7 rounded-xs'
121
- : props.density === 'xs'
122
- ? 'size-6 rounded-xs'
123
- : 'size-10 pointer-fine:size-8 rounded-xs',
124
- 'bg-input-surface text-base-fg transition-colors border border-separator',
126
+ // A PIN segment is a square control, so it takes the density height on both axes.
127
+ 'size-(--dx-control) rounded-xs',
128
+ 'bg-input-surface text-base-fg transition-colors border border-input-separator',
125
129
  'data-[focused]:bg-attention-surface data-[focused]:border-focus-ring-subtle',
126
130
  'data-[focused]:ring-2 data-[focused]:ring-offset-0 data-[focused]:ring-focus-ring-subtle',
127
131
  valence(props.validationValence),
@@ -143,7 +147,7 @@ const validation: ComponentFunction<InputMetaStyleProps> = (props, ...etc) =>
143
147
 
144
148
  const triggerIcon: ComponentFunction<{}> = (_p, ...etc) =>
145
149
  mx(
146
- 'shrink-0 inline-flex items-center justify-center size-7 rounded-xs',
150
+ 'shrink-0 inline-flex items-center justify-center size-(--dx-control-sm) rounded-xs',
147
151
  'bg-input-surface text-subdued hover:text-base-fg hover:bg-hover-surface',
148
152
  'dx-focus-ring',
149
153
  ...etc,
@@ -154,6 +158,8 @@ const block: ComponentFunction<InputStyleProps> = (props, ...etc) =>
154
158
 
155
159
  export const inputTheme = {
156
160
  input,
161
+ container,
162
+ adornment,
157
163
  textArea,
158
164
  pin,
159
165
  segment,
@@ -3,15 +3,14 @@
3
3
  //
4
4
 
5
5
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
6
- import { createContext } from '@radix-ui/react-context';
7
6
  import { useControllableState } from '@radix-ui/react-use-controllable-state';
8
7
  import React, {
9
8
  type ComponentPropsWithRef,
10
9
  type ForwardRefExoticComponent,
11
10
  PropsWithChildren,
11
+ type ReactNode,
12
12
  forwardRef,
13
13
  useCallback,
14
- useEffect,
15
14
  useRef,
16
15
  useState,
17
16
  } from 'react';
@@ -46,6 +45,7 @@ import { useDensityContext, useElevationContext, useThemeContext } from '../../h
46
45
  import { type ThemedClassName } from '../../util';
47
46
  import { IconButton, IconButtonProps } from '../Button';
48
47
  import { Icon } from '../Icon';
48
+ import { type InputTriggerHandler, InputTriggerProvider, useInputTriggerContext } from './InputTriggerContext';
49
49
  import {
50
50
  SegmentedDate,
51
51
  type SegmentedDateProps,
@@ -59,40 +59,6 @@ type InputVariant = 'default' | 'subdued';
59
59
 
60
60
  type InputSharedProps = Partial<{ density: Density; elevation: Elevation; variant: InputVariant }>;
61
61
 
62
- //
63
- // Trigger context — lets a sibling `Input.TriggerIcon` open a picker registered by a field inside
64
- // the same `Input.Root`. Each registered handler is keyed; the most recent registration wins.
65
- //
66
-
67
- type InputTriggerHandler = () => void;
68
-
69
- type InputTriggerContextValue = {
70
- registerTrigger: (handler: InputTriggerHandler) => () => void;
71
- trigger: () => void;
72
- hasTrigger: boolean;
73
- };
74
-
75
- // Default context makes the trigger registry a no-op outside `Input.Root` (consumers opt in).
76
- const [InputTriggerProvider, useInputTriggerContext] = createContext<InputTriggerContextValue>(INPUT_NAME, {
77
- registerTrigger: () => () => {},
78
- trigger: () => {},
79
- hasTrigger: false,
80
- });
81
-
82
- /**
83
- * Field hook. Pass an opener function; while the field is mounted, an `Input.TriggerIcon`
84
- * sibling will call this opener on press. Returns a no-op when used outside `Input.Root`.
85
- */
86
- const useInputTrigger = (handler: InputTriggerHandler | undefined) => {
87
- const ctx = useInputTriggerContext('useInputTrigger');
88
- useEffect(() => {
89
- if (!handler) {
90
- return;
91
- }
92
- return ctx.registerTrigger(handler);
93
- }, [ctx, handler]);
94
- };
95
-
96
62
  //
97
63
  // Root — wraps the @dxos/react-input primitive root with the trigger registry.
98
64
  //
@@ -281,11 +247,28 @@ type AutoFillProps = {
281
247
  noAutoFill?: boolean;
282
248
  };
283
249
 
284
- type TextInputProps = InputSharedProps & ThemedClassName<TextInputPrimitiveProps> & AutoFillProps;
250
+ type AdornmentProps = {
251
+ /** Content rendered inside the input container before the field (icon or text). */
252
+ start?: ReactNode;
253
+ /** Content rendered inside the input container after the field (icon, text, or button). */
254
+ end?: ReactNode;
255
+ };
256
+
257
+ type TextInputProps = InputSharedProps & ThemedClassName<TextInputPrimitiveProps> & AutoFillProps & AdornmentProps;
285
258
 
286
259
  const TextInput = forwardRef<HTMLInputElement, InputScopedProps<TextInputProps>>(
287
260
  (
288
- { __inputScope, classNames, density: densityProp, elevation: elevationProp, variant, noAutoFill, ...props },
261
+ {
262
+ __inputScope,
263
+ classNames,
264
+ density: densityProp,
265
+ elevation: elevationProp,
266
+ variant,
267
+ noAutoFill,
268
+ start,
269
+ end,
270
+ ...props
271
+ },
289
272
  forwardedRef,
290
273
  ) => {
291
274
  const { hasIosKeyboard } = useThemeContext();
@@ -293,27 +276,48 @@ const TextInput = forwardRef<HTMLInputElement, InputScopedProps<TextInputProps>>
293
276
  const density = useDensityContext(densityProp);
294
277
  const elevation = useElevationContext(elevationProp);
295
278
  const { validationValence } = useInputContext(INPUT_NAME, __inputScope);
279
+ const adorned = start != null || end != null;
296
280
 
297
- return (
281
+ const field = (
298
282
  <TextInputPrimitive
299
283
  {...props}
300
284
  // TODO(wittjosiah): Factor out autofill properies.
301
285
  {...{ 'data-1p-ignore': noAutoFill }}
286
+ // Sizing comes from the `--dx-control*` knobs; `data-density` is what applies a per-control
287
+ // override of them (see theme/spacing.css), so a `density` prop still works standalone.
288
+ data-density={density}
302
289
  className={tx(
303
290
  'input.input',
304
291
  {
305
- variant,
292
+ // When adorned the surrounding container owns the surface/border/focus, so the field is
293
+ // rendered "bare" (subdued) regardless of the requested variant.
294
+ variant: adorned ? 'subdued' : variant,
306
295
  disabled: props.disabled,
307
296
  density,
308
297
  elevation,
309
298
  validationValence,
310
299
  },
311
- classNames,
300
+ adorned ? undefined : classNames,
312
301
  )}
313
302
  {...(props.autoFocus && !hasIosKeyboard && { autoFocus: true })}
314
303
  ref={forwardedRef}
315
304
  />
316
305
  );
306
+
307
+ if (!adorned) {
308
+ return field;
309
+ }
310
+
311
+ return (
312
+ <div
313
+ data-density={density}
314
+ className={tx('input.container', { variant, disabled: props.disabled, density, validationValence }, classNames)}
315
+ >
316
+ {start != null && <span className={tx('input.adornment', { side: 'start' })}>{start}</span>}
317
+ {field}
318
+ {end != null && <span className={tx('input.adornment', { side: 'end' })}>{end}</span>}
319
+ </div>
320
+ );
317
321
  },
318
322
  );
319
323
 
@@ -336,6 +340,7 @@ const TextArea = forwardRef<HTMLTextAreaElement, InputScopedProps<TextAreaProps>
336
340
  return (
337
341
  <TextAreaPrimitive
338
342
  {...props}
343
+ data-density={density}
339
344
  className={tx(
340
345
  'input.textArea',
341
346
  {
@@ -522,8 +527,6 @@ export const Input = {
522
527
  DescriptionAndValidation,
523
528
  };
524
529
 
525
- export { useInputTrigger };
526
-
527
530
  export type {
528
531
  CheckboxProps,
529
532
  DateInputProps,
@@ -0,0 +1,45 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { createContext } from '@radix-ui/react-context';
6
+ import { useEffect } from 'react';
7
+
8
+ import { INPUT_NAME } from '@dxos/react-input';
9
+
10
+ // Kept out of `Input.tsx`: react-refresh only fast-refreshes a module whose exports are all
11
+ // components, so a context and its hook exported beside them force a full page reload on every edit.
12
+
13
+ //
14
+ // Trigger context — lets a sibling `Input.TriggerIcon` open a picker registered by a field inside
15
+ // the same `Input.Root`. Each registered handler is keyed; the most recent registration wins.
16
+ //
17
+
18
+ export type InputTriggerHandler = () => void;
19
+
20
+ export type InputTriggerContextValue = {
21
+ registerTrigger: (handler: InputTriggerHandler) => () => void;
22
+ trigger: () => void;
23
+ hasTrigger: boolean;
24
+ };
25
+
26
+ // Default context makes the trigger registry a no-op outside `Input.Root` (consumers opt in).
27
+ export const [InputTriggerProvider, useInputTriggerContext] = createContext<InputTriggerContextValue>(INPUT_NAME, {
28
+ registerTrigger: () => () => {},
29
+ trigger: () => {},
30
+ hasTrigger: false,
31
+ });
32
+
33
+ /**
34
+ * Field hook. Pass an opener function; while the field is mounted, an `Input.TriggerIcon`
35
+ * sibling will call this opener on press. Returns a no-op when used outside `Input.Root`.
36
+ */
37
+ export const useInputTrigger = (handler: InputTriggerHandler | undefined) => {
38
+ const ctx = useInputTriggerContext('useInputTrigger');
39
+ useEffect(() => {
40
+ if (!handler) {
41
+ return;
42
+ }
43
+ return ctx.registerTrigger(handler);
44
+ }, [ctx, handler]);
45
+ };
@@ -20,7 +20,8 @@ import { useDensityContext, useElevationContext, useThemeContext } from '../../h
20
20
  import { type ThemedClassName } from '../../util';
21
21
  import { DatePicker } from '../DatePicker';
22
22
  import { Popover } from '../Popover';
23
- import { type InputSharedProps, useInputTrigger } from './Input';
23
+ import { type InputSharedProps } from './Input';
24
+ import { useInputTrigger } from './InputTriggerContext';
24
25
 
25
26
  //
26
27
  // Value <-> @internationalized/date adapters.
@@ -2,5 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ export { useInputTrigger } from './InputTriggerContext';
6
+
5
7
  export * from './Input';
6
8
  export * from './SegmentedInput';
@@ -8,7 +8,8 @@ import React from 'react';
8
8
  import { withLayout, withTheme } from '../../testing';
9
9
  import { IconButton } from '../Button';
10
10
  import { Toolbar } from '../Toolbar';
11
- import { Main, useSidebars } from './Main';
11
+ import { Main } from './Main';
12
+ import { useSidebars } from './MainContext';
12
13
 
13
14
  type StoryMainArgs = {};
14
15
 
@@ -14,8 +14,17 @@ export type MainStyleProps = Partial<{
14
14
  handlesFocus: boolean;
15
15
  }>;
16
16
 
17
+ // The app canvas is the base zone: it paints the level and publishes `--surface-bg`, which every
18
+ // aspect inside it (bars, wells, hover/current rows) derives from.
17
19
  const content: ComponentFunction<MainStyleProps> = ({ bounce }, ...etc) =>
18
- mx(padding, mainPaddingTransitions, bounce && 'dx-main-bounce-layout', 'dx-focus-ring-main', ...etc);
20
+ mx(
21
+ padding,
22
+ mainPaddingTransitions,
23
+ bounce && 'dx-main-bounce-layout',
24
+ 'dx-base-surface',
25
+ 'dx-focus-ring-main',
26
+ ...etc,
27
+ );
19
28
 
20
29
  const sidebar: ComponentFunction<MainStyleProps> = (_, ...etc) =>
21
30
  mx('dx-main-sidebar', 'dx-focus-ring-inset-over-all', ...etc);
@@ -2,19 +2,14 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { useFocusableGroup } from '@fluentui/react-tabster';
6
- import { createContext } from '@radix-ui/react-context';
7
5
  import { DialogContent, Root as DialogRoot, DialogTitle } from '@radix-ui/react-dialog';
8
6
  import { Primitive } from '@radix-ui/react-primitive';
9
7
  import { Slot } from '@radix-ui/react-slot';
10
8
  import { useControllableState } from '@radix-ui/react-use-controllable-state';
11
9
  import React, {
12
- type ComponentPropsWithoutRef,
13
10
  type ComponentPropsWithRef,
14
- type Dispatch,
15
11
  type KeyboardEvent,
16
12
  type PropsWithChildren,
17
- type SetStateAction,
18
13
  forwardRef,
19
14
  useCallback,
20
15
  useEffect,
@@ -23,7 +18,6 @@ import React, {
23
18
  } from 'react';
24
19
 
25
20
  import { addEventListener } from '@dxos/async';
26
- import { log } from '@dxos/log';
27
21
  import { useForwardedRef, useMediaQuery } from '@dxos/react-hooks';
28
22
  import { osTranslations } from '@dxos/ui-theme';
29
23
 
@@ -31,9 +25,9 @@ import { useThemeContext } from '../../hooks';
31
25
  import { type Label, toLocalizedString, useTranslation } from '../../primitives';
32
26
  import { type MainStyleProps } from '../../theme';
33
27
  import { type ThemedClassName } from '../../util';
28
+ import { MAIN_NAME, MainProvider, type SidebarState, useLandmarkMover, useMainContext } from './MainContext';
34
29
  import { useSwipeToDismiss } from './useSwipeToDismiss';
35
30
 
36
- const MAIN_NAME = 'Main';
37
31
  const MAIN_ROOT_NAME = 'Main.Root';
38
32
  const MAIN_OVERLAY_NAME = 'Main.Overlay';
39
33
  const MAIN_CONTENT_NAME = 'Main.Content';
@@ -44,112 +38,6 @@ const handleOpenAutoFocus = (event: Event) => {
44
38
  !document.body.hasAttribute('data-w-keyboard') && event.preventDefault();
45
39
  };
46
40
 
47
- //
48
- // Landmark
49
- //
50
-
51
- const landmarkAttr = 'data-main-landmark';
52
-
53
- /**
54
- * Facilitates moving focus between landmarks.
55
- * Ref https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/landmark_role
56
- */
57
- const useLandmarkMover = (propsOnKeyDown: ComponentPropsWithoutRef<'div'>['onKeyDown'], landmark: string) => {
58
- const handleKeyDown = useCallback(
59
- (event: KeyboardEvent<HTMLDivElement>) => {
60
- const target = event.target as HTMLDivElement;
61
- if (event.target === event.currentTarget && event.key === 'Tab' && target.hasAttribute(landmarkAttr)) {
62
- event.preventDefault();
63
- const landmarks = Array.from(document.querySelectorAll(`[${landmarkAttr}]:not([inert])`))
64
- .map((el) => (el.hasAttribute(landmarkAttr) ? parseInt(el.getAttribute(landmarkAttr)!) : NaN))
65
- .sort();
66
- const l = landmarks.length;
67
- const cursor = landmarks.indexOf(parseInt(target.getAttribute(landmarkAttr)!));
68
- const nextLandmark = landmarks[(cursor + l + (event.getModifierState('Shift') ? -1 : 1)) % l];
69
- (document.querySelector(`[${landmarkAttr}="${nextLandmark}"]`) as HTMLDivElement | null)?.focus();
70
- }
71
- propsOnKeyDown?.(event);
72
- },
73
- [propsOnKeyDown],
74
- );
75
-
76
- // TODO(thure): This was disconnected once before in #8818;
77
- // if this should change again to support the browser extension, please ensure the change doesn’t break web, desktop and mobile.
78
- const focusableGroupAttrs = useFocusableGroup({ tabBehavior: 'limited', ignoreDefaultKeydown: { Tab: true } });
79
-
80
- return {
81
- [landmarkAttr]: landmark,
82
- tabIndex: 0,
83
- onKeyDown: handleKeyDown,
84
- ...focusableGroupAttrs,
85
- };
86
- };
87
-
88
- //
89
- // Context
90
- //
91
-
92
- // TODO(burdon): Define collapsed state.
93
- type SidebarState = 'expanded' | 'collapsed' | 'closed';
94
-
95
- type MainContextValue = {
96
- resizing: boolean;
97
-
98
- // Navigation
99
- navigationSidebarState: SidebarState;
100
- setNavigationSidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
101
-
102
- // Complementary
103
- complementarySidebarState: SidebarState;
104
- setComplementarySidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
105
- };
106
-
107
- const [MainProvider, useMainContext] = createContext<MainContextValue>(MAIN_NAME, {
108
- resizing: false,
109
-
110
- navigationSidebarState: 'closed',
111
- setNavigationSidebarState: (_nextState) => {
112
- log.warn('Not initialized');
113
- },
114
-
115
- complementarySidebarState: 'closed',
116
- setComplementarySidebarState: (_nextState) => {
117
- log.warn('Not initialized');
118
- },
119
- });
120
-
121
- const useSidebars = (consumerName: string) => {
122
- const {
123
- navigationSidebarState,
124
- setNavigationSidebarState,
125
-
126
- complementarySidebarState,
127
- setComplementarySidebarState,
128
- } = useMainContext(consumerName);
129
-
130
- return {
131
- navigationSidebarState,
132
- setNavigationSidebarState,
133
- toggleNavigationSidebar: useCallback(
134
- () => setNavigationSidebarState(navigationSidebarState === 'expanded' ? 'closed' : 'expanded'),
135
- [navigationSidebarState, setNavigationSidebarState],
136
- ),
137
- openNavigationSidebar: useCallback(() => setNavigationSidebarState('expanded'), []),
138
- collapseNavigationSidebar: useCallback(() => setNavigationSidebarState('collapsed'), []),
139
- closeNavigationSidebar: useCallback(() => setNavigationSidebarState('closed'), []),
140
-
141
- complementarySidebarState,
142
- setComplementarySidebarState,
143
- toggleComplementarySidebar: useCallback(
144
- () => setComplementarySidebarState(complementarySidebarState === 'expanded' ? 'closed' : 'expanded'),
145
- [complementarySidebarState, setComplementarySidebarState],
146
- ),
147
- openComplementarySidebar: useCallback(() => setComplementarySidebarState('expanded'), []),
148
- collapseComplementarySidebar: useCallback(() => setComplementarySidebarState('collapsed'), []),
149
- closeComplementarySidebar: useCallback(() => setComplementarySidebarState('closed'), []),
150
- };
151
- };
152
-
153
41
  //
154
42
  // Root
155
43
  //
@@ -428,6 +316,4 @@ export const Main = {
428
316
  ComplementarySidebar: MainComplementarySidebar,
429
317
  };
430
318
 
431
- export { useLandmarkMover, useMainContext, useSidebars };
432
-
433
319
  export type { MainContentProps, MainNavigationSidebarProps, MainOverlayProps, MainRootProps, SidebarState };