@dxos/react-ui 0.8.4-main.66e292d → 0.8.4-main.69d29f4

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 (149) hide show
  1. package/dist/lib/browser/chunk-CEKVHJ27.mjs +774 -0
  2. package/dist/lib/browser/chunk-CEKVHJ27.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +3065 -66
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +31 -43
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node-esm/chunk-2NHEX4AD.mjs +776 -0
  9. package/dist/lib/node-esm/chunk-2NHEX4AD.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +3065 -66
  11. package/dist/lib/node-esm/index.mjs.map +4 -4
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +31 -43
  14. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  15. package/dist/types/src/components/Button/Button.d.ts +1 -1
  16. package/dist/types/src/components/Button/Button.d.ts.map +1 -1
  17. package/dist/types/src/components/Button/IconButton.d.ts +2 -1
  18. package/dist/types/src/components/Button/IconButton.d.ts.map +1 -1
  19. package/dist/types/src/components/Button/ToggleGroup.d.ts +4 -4
  20. package/dist/types/src/components/Button/ToggleGroup.stories.d.ts +4 -4
  21. package/dist/types/src/components/DensityProvider/DensityProvider.d.ts +1 -1
  22. package/dist/types/src/components/DensityProvider/DensityProvider.d.ts.map +1 -1
  23. package/dist/types/src/components/Dialog/Dialog.d.ts +18 -9
  24. package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
  25. package/dist/types/src/components/Dialog/Dialog.stories.d.ts +7 -5
  26. package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -1
  27. package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts +1 -1
  28. package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts.map +1 -1
  29. package/dist/types/src/components/Icon/Icon.d.ts +1 -1
  30. package/dist/types/src/components/Icon/Icon.d.ts.map +1 -1
  31. package/dist/types/src/components/Input/Input.d.ts +5 -2
  32. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  33. package/dist/types/src/components/Input/Input.stories.d.ts +1 -1
  34. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  35. package/dist/types/src/components/List/List.d.ts +1 -1
  36. package/dist/types/src/components/List/List.d.ts.map +1 -1
  37. package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
  38. package/dist/types/src/components/{Menus → Menu}/ContextMenu.d.ts +6 -6
  39. package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -0
  40. package/dist/types/src/components/Menu/ContextMenu.stories.d.ts.map +1 -0
  41. package/dist/types/src/components/{Menus → Menu}/DropdownMenu.d.ts +1 -1
  42. package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -0
  43. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -0
  44. package/dist/types/src/components/Menu/index.d.ts.map +1 -0
  45. package/dist/types/src/components/Message/Message.d.ts +1 -1
  46. package/dist/types/src/components/Message/Message.d.ts.map +1 -1
  47. package/dist/types/src/components/Message/Message.stories.d.ts +1 -1
  48. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  49. package/dist/types/src/components/Popover/Popover.d.ts +1 -1
  50. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  51. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +9 -7
  52. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  53. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +4 -0
  54. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  55. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +4 -2
  56. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
  57. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +2 -1
  58. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -1
  59. package/dist/types/src/components/Select/Select.d.ts +9 -9
  60. package/dist/types/src/components/Separator/Separator.d.ts +1 -1
  61. package/dist/types/src/components/Tag/Tag.d.ts +1 -1
  62. package/dist/types/src/components/Tag/Tag.d.ts.map +1 -1
  63. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +1 -2
  64. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  65. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +1 -8
  66. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  67. package/dist/types/src/components/ThemeProvider/index.d.ts +2 -1
  68. package/dist/types/src/components/ThemeProvider/index.d.ts.map +1 -1
  69. package/dist/types/src/components/Toast/Toast.d.ts +4 -4
  70. package/dist/types/src/components/Toolbar/Toolbar.d.ts +10 -10
  71. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  72. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  73. package/dist/types/src/components/index.d.ts +1 -1
  74. package/dist/types/src/components/index.d.ts.map +1 -1
  75. package/dist/types/src/hooks/useDensityContext.d.ts +1 -1
  76. package/dist/types/src/hooks/useDensityContext.d.ts.map +1 -1
  77. package/dist/types/src/hooks/useElevationContext.d.ts +1 -1
  78. package/dist/types/src/hooks/useElevationContext.d.ts.map +1 -1
  79. package/dist/types/src/index.d.ts +1 -1
  80. package/dist/types/src/index.d.ts.map +1 -1
  81. package/dist/types/src/testing/decorators/withLayout.d.ts +3 -3
  82. package/dist/types/src/testing/decorators/withLayout.d.ts.map +1 -1
  83. package/dist/types/src/testing/decorators/withLayoutVariants.d.ts +1 -1
  84. package/dist/types/src/testing/decorators/withLayoutVariants.d.ts.map +1 -1
  85. package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
  86. package/dist/types/src/util/index.d.ts +1 -2
  87. package/dist/types/src/util/index.d.ts.map +1 -1
  88. package/dist/types/tsconfig.tsbuildinfo +1 -1
  89. package/package.json +31 -26
  90. package/src/components/Avatars/Avatar.stories.tsx +2 -2
  91. package/src/components/Avatars/Avatar.tsx +1 -1
  92. package/src/components/Button/Button.tsx +1 -1
  93. package/src/components/Button/IconButton.tsx +8 -3
  94. package/src/components/Clipboard/CopyButton.tsx +3 -3
  95. package/src/components/DensityProvider/DensityProvider.tsx +1 -1
  96. package/src/components/Dialog/Dialog.stories.tsx +47 -17
  97. package/src/components/Dialog/Dialog.tsx +140 -40
  98. package/src/components/ElevationProvider/ElevationProvider.tsx +1 -1
  99. package/src/components/Icon/Icon.stories.tsx +1 -1
  100. package/src/components/Icon/Icon.tsx +1 -1
  101. package/src/components/Input/Input.stories.tsx +2 -2
  102. package/src/components/Input/Input.tsx +13 -4
  103. package/src/components/List/List.stories.tsx +16 -12
  104. package/src/components/List/List.tsx +1 -1
  105. package/src/components/{Menus → Menu}/DropdownMenu.tsx +57 -55
  106. package/src/components/Message/Message.stories.tsx +1 -1
  107. package/src/components/Message/Message.tsx +30 -5
  108. package/src/components/Popover/Popover.tsx +35 -33
  109. package/src/components/ScrollArea/ScrollArea.stories.tsx +53 -3
  110. package/src/components/ScrollArea/ScrollArea.tsx +50 -4
  111. package/src/components/ScrollContainer/ScrollContainer.stories.tsx +2 -1
  112. package/src/components/ScrollContainer/ScrollContainer.tsx +90 -88
  113. package/src/components/Tag/Tag.stories.tsx +2 -2
  114. package/src/components/Tag/Tag.tsx +1 -1
  115. package/src/components/ThemeProvider/ThemeProvider.tsx +1 -3
  116. package/src/components/ThemeProvider/TranslationsProvider.tsx +1 -16
  117. package/src/components/ThemeProvider/index.ts +3 -3
  118. package/src/components/Toolbar/Toolbar.tsx +23 -8
  119. package/src/components/Tooltip/Tooltip.tsx +22 -20
  120. package/src/components/index.ts +1 -1
  121. package/src/hooks/useDensityContext.ts +1 -1
  122. package/src/hooks/useElevationContext.ts +1 -1
  123. package/src/index.ts +1 -1
  124. package/src/testing/decorators/withLayout.tsx +22 -15
  125. package/src/testing/decorators/withLayoutVariants.tsx +3 -3
  126. package/src/testing/decorators/withTheme.tsx +3 -2
  127. package/src/util/index.ts +2 -2
  128. package/dist/lib/browser/chunk-N5GDJTT2.mjs +0 -4707
  129. package/dist/lib/browser/chunk-N5GDJTT2.mjs.map +0 -7
  130. package/dist/lib/node-esm/chunk-SP7VQH72.mjs +0 -4709
  131. package/dist/lib/node-esm/chunk-SP7VQH72.mjs.map +0 -7
  132. package/dist/types/src/components/Menus/ContextMenu.d.ts.map +0 -1
  133. package/dist/types/src/components/Menus/ContextMenu.stories.d.ts.map +0 -1
  134. package/dist/types/src/components/Menus/DropdownMenu.d.ts.map +0 -1
  135. package/dist/types/src/components/Menus/DropdownMenu.stories.d.ts.map +0 -1
  136. package/dist/types/src/components/Menus/index.d.ts.map +0 -1
  137. package/dist/types/src/util/ThemedClassName.d.ts +0 -5
  138. package/dist/types/src/util/ThemedClassName.d.ts.map +0 -1
  139. package/dist/types/src/util/domino.d.ts +0 -18
  140. package/dist/types/src/util/domino.d.ts.map +0 -1
  141. package/src/util/ThemedClassName.ts +0 -7
  142. package/src/util/domino.ts +0 -53
  143. /package/dist/types/src/components/{Menus → Menu}/ContextMenu.stories.d.ts +0 -0
  144. /package/dist/types/src/components/{Menus → Menu}/DropdownMenu.stories.d.ts +0 -0
  145. /package/dist/types/src/components/{Menus → Menu}/index.d.ts +0 -0
  146. /package/src/components/{Menus → Menu}/ContextMenu.stories.tsx +0 -0
  147. /package/src/components/{Menus → Menu}/ContextMenu.tsx +0 -0
  148. /package/src/components/{Menus → Menu}/DropdownMenu.stories.tsx +0 -0
  149. /package/src/components/{Menus → Menu}/index.ts +0 -0
@@ -14,18 +14,21 @@ import {
14
14
  Viewport as ScrollAreaPrimitiveViewport,
15
15
  type ScrollAreaViewportProps as ScrollAreaPrimitiveViewportProps,
16
16
  } from '@radix-ui/react-scroll-area';
17
- import React, { forwardRef } from 'react';
17
+ import React, { type PropsWithChildren, forwardRef } from 'react';
18
+
19
+ import { mx } from '@dxos/ui-theme';
18
20
 
19
21
  import { useThemeContext } from '../../hooks';
20
22
  import { type ThemedClassName } from '../../util';
21
23
 
22
24
  type ScrollAreaVariant = 'coarse' | 'fine';
23
25
 
26
+ //
27
+ // Root
28
+ //
29
+
24
30
  type ScrollAreaRootProps = ThemedClassName<ScrollAreaPrimitiveRootProps>;
25
31
 
26
- /**
27
- * @deprecated
28
- */
29
32
  const ScrollAreaRoot = forwardRef<HTMLDivElement, ScrollAreaRootProps>(({ classNames, ...props }, forwardedRef) => {
30
33
  const { tx } = useThemeContext();
31
34
  return (
@@ -37,6 +40,10 @@ const ScrollAreaRoot = forwardRef<HTMLDivElement, ScrollAreaRootProps>(({ classN
37
40
  );
38
41
  });
39
42
 
43
+ //
44
+ // Viewport
45
+ //
46
+
40
47
  type ScrollAreaViewportProps = ThemedClassName<ScrollAreaPrimitiveViewportProps>;
41
48
 
42
49
  const ScrollAreaViewport = forwardRef<HTMLDivElement, ScrollAreaViewportProps>(
@@ -52,6 +59,10 @@ const ScrollAreaViewport = forwardRef<HTMLDivElement, ScrollAreaViewportProps>(
52
59
  },
53
60
  );
54
61
 
62
+ //
63
+ // Scrollbar
64
+ //
65
+
55
66
  type ScrollAreaScrollbarProps = ThemedClassName<ScrollAreaPrimitiveScrollbarProps> & { variant?: ScrollAreaVariant };
56
67
 
57
68
  const ScrollAreaScrollbar = forwardRef<HTMLDivElement, ScrollAreaScrollbarProps>(
@@ -68,6 +79,10 @@ const ScrollAreaScrollbar = forwardRef<HTMLDivElement, ScrollAreaScrollbarProps>
68
79
  },
69
80
  );
70
81
 
82
+ //
83
+ // Thumb
84
+ //
85
+
71
86
  type ScrollAreaThumbProps = ThemedClassName<ScrollAreaPrimitiveThumbProps>;
72
87
 
73
88
  const ScrollAreaThumb = forwardRef<HTMLDivElement, ScrollAreaThumbProps>(({ classNames, ...props }, forwardedRef) => {
@@ -81,6 +96,10 @@ const ScrollAreaThumb = forwardRef<HTMLDivElement, ScrollAreaThumbProps>(({ clas
81
96
  );
82
97
  });
83
98
 
99
+ //
100
+ // Corner
101
+ //
102
+
84
103
  type ScrollAreaCornerProps = ThemedClassName<ScrollAreaPrimitiveCornerProps>;
85
104
 
86
105
  const ScrollAreaCorner = forwardRef<HTMLDivElement, ScrollAreaCornerProps>(({ classNames, ...props }, forwardedRef) => {
@@ -94,12 +113,38 @@ const ScrollAreaCorner = forwardRef<HTMLDivElement, ScrollAreaCornerProps>(({ cl
94
113
  );
95
114
  });
96
115
 
116
+ //
117
+ // Expander
118
+ //
119
+
120
+ type ScrollAreaExpanderProps = ThemedClassName<PropsWithChildren>;
121
+
122
+ /**
123
+ * Size-locking wrapper required for inner ScrollArea to function correctly.
124
+ * NOTE: Radix ScrollArea.Viewport applies `display: table` to its immediate child,
125
+ * causing the content to participate in table layout and escape the intended fixed-size viewport.
126
+ */
127
+ const ScrollAreaExpander = ({ classNames, children }: ScrollAreaExpanderProps) => {
128
+ return (
129
+ <div role='none' className={mx('relative bs-full is-full overflow-hidden', classNames)}>
130
+ <div role='none' className='absolute inset-0 overflow-hidden'>
131
+ {children}
132
+ </div>
133
+ </div>
134
+ );
135
+ };
136
+
137
+ //
138
+ // ScrollArea
139
+ //
140
+
97
141
  export const ScrollArea = {
98
142
  Root: ScrollAreaRoot,
99
143
  Viewport: ScrollAreaViewport,
100
144
  Scrollbar: ScrollAreaScrollbar,
101
145
  Thumb: ScrollAreaThumb,
102
146
  Corner: ScrollAreaCorner,
147
+ Expander: ScrollAreaExpander,
103
148
  };
104
149
 
105
150
  export type {
@@ -108,4 +153,5 @@ export type {
108
153
  ScrollAreaScrollbarProps,
109
154
  ScrollAreaThumbProps,
110
155
  ScrollAreaCornerProps,
156
+ ScrollAreaExpanderProps,
111
157
  };
@@ -45,6 +45,7 @@ const DefaultStory = (props: ScrollContainerRootProps) => {
45
45
  </div>
46
46
  ))}
47
47
  </ScrollContainer.Viewport>
48
+ <ScrollContainer.ScrollDownButton />
48
49
  </ScrollContainer.Root>
49
50
  </div>
50
51
  );
@@ -54,7 +55,7 @@ const meta = {
54
55
  title: 'ui/react-ui-core/ScrollContainer',
55
56
  component: ScrollContainer.Root,
56
57
  render: DefaultStory,
57
- decorators: [withTheme, withLayout({ container: 'column', classNames: 'is-[30rem]' })],
58
+ decorators: [withTheme, withLayout({ layout: 'column', classNames: 'is-[30rem]' })],
58
59
  } satisfies Meta<typeof DefaultStory>;
59
60
 
60
61
  export default meta;
@@ -2,7 +2,6 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { useState } from '@preact-signals/safe-react/react';
6
5
  import { createContext } from '@radix-ui/react-context';
7
6
  import React, {
8
7
  type HTMLAttributes,
@@ -13,13 +12,14 @@ import React, {
13
12
  useImperativeHandle,
14
13
  useMemo,
15
14
  useRef,
15
+ useState,
16
16
  } from 'react';
17
17
 
18
18
  // TODO(burdon): Move these deps to @dxos/dom-util.
19
19
  import { addEventListener, combine } from '@dxos/async';
20
20
  import { invariant } from '@dxos/invariant';
21
21
  import { useForwardedRef } from '@dxos/react-hooks';
22
- import { mx } from '@dxos/react-ui-theme';
22
+ import { mx } from '@dxos/ui-theme';
23
23
 
24
24
  import { type ThemedClassName } from '../../util';
25
25
  import { IconButton } from '../Button';
@@ -51,98 +51,101 @@ type RootProps = ThemedClassName<
51
51
  PropsWithChildren<{
52
52
  pin?: boolean;
53
53
  fade?: boolean;
54
+ behavior?: ScrollBehavior;
54
55
  }>
55
56
  >;
56
57
 
57
58
  /**
58
59
  * Scroll container that automatically scrolls to the bottom when new content is added.
59
60
  */
60
- const Root = forwardRef<ScrollController, RootProps>(({ children, classNames, pin, fade }, forwardedRef) => {
61
- const scrollerRef = useRef<HTMLDivElement>(null);
62
- const autoScrollRef = useRef(false);
63
- const [overflow, setOverflow] = useState(false);
64
- const [pinned, setPinned] = useState(pin);
65
-
66
- const timeoutRef = useRef<NodeJS.Timeout>(undefined);
67
- const scrollToBottom = useCallback((behavior: ScrollBehavior = 'instant') => {
68
- if (scrollerRef.current) {
69
- // Temporarily hide scrollbar to prevent flicker.
70
- autoScrollRef.current = true;
71
- scrollerRef.current.classList.add('scrollbar-none');
72
- scrollerRef.current.scrollTo({
73
- top: scrollerRef.current.scrollHeight,
74
- behavior,
75
- });
76
-
77
- clearTimeout(timeoutRef.current);
78
- if (behavior !== 'instant') {
79
- timeoutRef.current = setTimeout(() => {
80
- scrollerRef.current?.classList.remove('scrollbar-none');
81
- autoScrollRef.current = false;
82
- }, 500);
61
+ const Root = forwardRef<ScrollController, RootProps>(
62
+ ({ children, classNames, pin, fade, behavior: behaviorProp = 'smooth' }, forwardedRef) => {
63
+ const scrollerRef = useRef<HTMLDivElement>(null);
64
+ const autoScrollRef = useRef(false);
65
+ const [overflow, setOverflow] = useState(false);
66
+ const [pinned, setPinned] = useState(pin);
67
+
68
+ const timeoutRef = useRef<NodeJS.Timeout>(undefined);
69
+ const scrollToBottom = useCallback((behavior: ScrollBehavior = behaviorProp) => {
70
+ if (scrollerRef.current) {
71
+ // Temporarily hide scrollbar to prevent flicker.
72
+ autoScrollRef.current = true;
73
+ scrollerRef.current.classList.add('scrollbar-none');
74
+ scrollerRef.current.scrollTo({
75
+ top: scrollerRef.current.scrollHeight,
76
+ behavior,
77
+ });
78
+
79
+ clearTimeout(timeoutRef.current);
80
+ if (behavior !== 'instant') {
81
+ timeoutRef.current = setTimeout(() => {
82
+ scrollerRef.current?.classList.remove('scrollbar-none');
83
+ autoScrollRef.current = false;
84
+ }, 500);
85
+ }
86
+ setPinned(true);
83
87
  }
84
- setPinned(true);
85
- }
86
- }, []);
87
-
88
- const controller = useMemo(
89
- () => ({
90
- viewport: scrollerRef.current,
91
- scrollToTop: () => {
92
- invariant(scrollerRef.current);
93
- scrollerRef.current.scrollTo({ top: 0, behavior: 'smooth' });
94
- setPinned(false);
95
- },
96
- scrollToBottom: () => {
97
- scrollToBottom('smooth');
98
- },
99
- }),
100
- [scrollToBottom, scrollerRef.current],
101
- );
102
-
103
- // Scroll controller imperative ref.
104
- useImperativeHandle(forwardedRef, () => controller, [controller]);
105
-
106
- // Listen for scroll events.
107
- useEffect(() => {
108
- if (!scrollerRef.current) {
109
- return;
110
- }
111
-
112
- return combine(
113
- // Check if user scrolls.
114
- addEventListener(scrollerRef.current, 'wheel', () => {
115
- setPinned(isBottom(scrollerRef.current));
116
- }),
117
- // Check if scrolls.
118
- addEventListener(scrollerRef.current, 'scroll', () => {
119
- setOverflow((scrollerRef.current?.scrollTop ?? 0) > 0);
88
+ }, []);
89
+
90
+ const controller = useMemo(
91
+ () => ({
92
+ viewport: scrollerRef.current,
93
+ scrollToTop: () => {
94
+ invariant(scrollerRef.current);
95
+ scrollerRef.current.scrollTo({ top: 0, behavior: 'smooth' });
96
+ setPinned(false);
97
+ },
98
+ scrollToBottom: () => {
99
+ scrollToBottom('smooth');
100
+ },
120
101
  }),
102
+ [scrollToBottom, scrollerRef.current],
121
103
  );
122
- }, []);
123
104
 
124
- return (
125
- <ScrollContainerProvider pinned={pinned} controller={controller} scrollToBottom={scrollToBottom}>
126
- <div className='relative grid flex-1 min-bs-0 overflow-hidden'>
127
- {fade && (
128
- <div
129
- role='none'
130
- data-visible={overflow}
131
- className={mx(
132
- // NOTE: Gradients may not be visible with dark reader extensions.
133
- 'z-10 absolute block-start-0 inset-inline-0 bs-24 is-full',
134
- 'opacity-0 duration-200 transition-opacity data-[visible="true"]:opacity-100',
135
- 'bg-gradient-to-b from-[--surface-bg] to-transparent pointer-events-none',
136
- )}
137
- />
138
- )}
139
- <div className={mx('flex flex-col min-bs-0 overflow-y-auto scrollbar-thin', classNames)} ref={scrollerRef}>
140
- {children}
105
+ // Scroll controller imperative ref.
106
+ useImperativeHandle(forwardedRef, () => controller, [controller]);
107
+
108
+ // Listen for scroll events.
109
+ useEffect(() => {
110
+ if (!scrollerRef.current) {
111
+ return;
112
+ }
113
+
114
+ return combine(
115
+ // Check if user scrolls.
116
+ addEventListener(scrollerRef.current, 'wheel', () => {
117
+ setPinned(isBottom(scrollerRef.current));
118
+ }),
119
+ // Check if scrolls.
120
+ addEventListener(scrollerRef.current, 'scroll', () => {
121
+ setOverflow((scrollerRef.current?.scrollTop ?? 0) > 0);
122
+ }),
123
+ );
124
+ }, []);
125
+
126
+ return (
127
+ <ScrollContainerProvider pinned={pinned} controller={controller} scrollToBottom={scrollToBottom}>
128
+ <div className='relative grid flex-1 min-bs-0 overflow-hidden'>
129
+ {fade && (
130
+ <div
131
+ role='none'
132
+ data-visible={overflow}
133
+ className={mx(
134
+ // NOTE: Gradients may not be visible with dark reader extensions.
135
+ 'z-10 absolute block-start-0 inset-inline-0 bs-24 is-full',
136
+ 'opacity-0 duration-200 transition-opacity data-[visible="true"]:opacity-100',
137
+ 'bg-gradient-to-b from-[--surface-bg] to-transparent pointer-events-none',
138
+ )}
139
+ />
140
+ )}
141
+ <div className={mx('flex flex-col min-bs-0 overflow-y-auto scrollbar-thin', classNames)} ref={scrollerRef}>
142
+ {children}
143
+ </div>
141
144
  </div>
142
- </div>
143
- </ScrollContainerProvider>
144
- );
145
- });
145
+ </ScrollContainerProvider>
146
+ );
147
+ },
148
+ );
146
149
 
147
150
  Root.displayName = 'ScrollContainer.Root';
148
151
 
@@ -161,14 +164,13 @@ const Viewport = forwardRef<HTMLDivElement, ViewportProps>(({ classNames, childr
161
164
  return;
162
165
  }
163
166
 
167
+ // Scroll instantly otherwise it might move while we're scrolling.
168
+ scrollToBottom();
169
+
164
170
  // Setup resize observer to detect content changes.
165
171
  const resizeObserver = new ResizeObserver(() => scrollToBottom());
166
- scrollToBottom('instant');
167
-
168
172
  resizeObserver.observe(contentRef.current);
169
- return () => {
170
- resizeObserver.disconnect();
171
- };
173
+ return () => resizeObserver.disconnect();
172
174
  }, [pinned, scrollToBottom]);
173
175
 
174
176
  return (
@@ -5,8 +5,8 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React from 'react';
7
7
 
8
- import { hues } from '@dxos/react-ui-theme';
9
- import { type ChromaticPalette, type MessageValence } from '@dxos/react-ui-types';
8
+ import { hues } from '@dxos/ui-theme';
9
+ import { type ChromaticPalette, type MessageValence } from '@dxos/ui-types';
10
10
 
11
11
  import { withTheme } from '../../testing';
12
12
 
@@ -6,7 +6,7 @@ import { Primitive } from '@radix-ui/react-primitive';
6
6
  import { Slot } from '@radix-ui/react-slot';
7
7
  import React, { type ComponentPropsWithRef, forwardRef } from 'react';
8
8
 
9
- import { type ChromaticPalette, type MessageValence, type NeutralPalette } from '@dxos/react-ui-types';
9
+ import { type ChromaticPalette, type MessageValence, type NeutralPalette } from '@dxos/ui-types';
10
10
 
11
11
  import { useThemeContext } from '../../hooks';
12
12
  import { type ThemedClassName } from '../../util';
@@ -5,7 +5,7 @@
5
5
  import { createKeyborg } from 'keyborg';
6
6
  import React, { type PropsWithChildren, createContext, useEffect, useMemo } from 'react';
7
7
 
8
- import { type Density, type Elevation, type ThemeFunction } from '@dxos/react-ui-types';
8
+ import { type Density, type Elevation, type ThemeFunction, type ThemeMode } from '@dxos/ui-types';
9
9
 
10
10
  import { type SafeAreaPadding, useSafeArea } from '../../hooks';
11
11
  import { hasIosKeyboard } from '../../util';
@@ -14,8 +14,6 @@ import { ElevationProvider } from '../ElevationProvider';
14
14
 
15
15
  import { TranslationsProvider, type TranslationsProviderProps } from './TranslationsProvider';
16
16
 
17
- export type ThemeMode = 'dark' | 'light';
18
-
19
17
  export type ThemeContextValue = {
20
18
  tx: ThemeFunction<any>;
21
19
  themeMode: ThemeMode;
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { type Locale, enUS as dtLocaleEnUs } from 'date-fns/locale';
6
- import i18Next, { type Resource, type TFunction } from 'i18next';
6
+ import i18Next, { type Resource } from 'i18next';
7
7
  import React, { type ReactNode, Suspense, createContext, useContext, useEffect, useState } from 'react';
8
8
  import { initReactI18next, useTranslation as useI18NextTranslation } from 'react-i18next';
9
9
 
@@ -11,21 +11,6 @@ const initialLng = 'en-US';
11
11
  const initialNs = 'dxos-common';
12
12
  const initialDtLocale = dtLocaleEnUs;
13
13
 
14
- // TODO(thure): `Parameters<TFunction>` causes typechecking issues because `TFunction` has so many signatures.
15
- export type Label = string | [string, { ns: string; count?: number; defaultValue?: string }];
16
-
17
- export const isLabel = (o: any): o is Label =>
18
- typeof o === 'string' ||
19
- (Array.isArray(o) &&
20
- o.length === 2 &&
21
- typeof o[0] === 'string' &&
22
- !!o[1] &&
23
- typeof o[1] === 'object' &&
24
- 'ns' in o[1] &&
25
- typeof o[1].ns === 'string');
26
-
27
- export const toLocalizedString = (label: Label, t: TFunction) => (Array.isArray(label) ? t(...label) : label);
28
-
29
14
  export const resources = {
30
15
  [initialLng]: {
31
16
  [initialNs]: {
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- export * from './ThemeProvider';
6
- export { type Label, isLabel, toLocalizedString, useTranslation } from './TranslationsProvider';
5
+ export { type Label, isLabel, toLocalizedString } from '@dxos/ui-types';
7
6
 
8
- // TODO(burdon): Use `@internal` with barrel exports (rather than picking individual exports?)
7
+ export * from './ThemeProvider';
8
+ export { useTranslation } from './TranslationsProvider';
@@ -24,18 +24,22 @@ import { Separator, type SeparatorProps } from '../Separator';
24
24
 
25
25
  type ToolbarRootProps = ThemedClassName<
26
26
  ToolbarPrimitive.ToolbarProps & {
27
- textBlockWidth?: boolean;
28
- layoutManaged?: boolean;
29
27
  disabled?: boolean;
28
+ layoutManaged?: boolean; // TODO(burdon): Replace with Toolbar.Content to allow inner layout management?
29
+ textBlockWidth?: boolean;
30
30
  }
31
31
  >;
32
32
 
33
+ // TODO(burdon): Implement asChild.
33
34
  const ToolbarRoot = forwardRef<HTMLDivElement, ToolbarRootProps>(
34
- ({ classNames, children, layoutManaged, textBlockWidth: textBlockWidthParam, disabled, ...props }, forwardedRef) => {
35
+ ({ classNames, children, disabled, layoutManaged, textBlockWidth: textBlockWidthProp, ...props }, forwardedRef) => {
35
36
  const { tx } = useThemeContext();
36
- const InnerRoot = textBlockWidthParam ? 'div' : Fragment;
37
- const innerRootProps = textBlockWidthParam
38
- ? { role: 'none', className: tx('toolbar.inner', 'toolbar', { layoutManaged }, classNames) }
37
+ const InnerRoot = textBlockWidthProp ? 'div' : Fragment;
38
+ const innerRootProps = textBlockWidthProp
39
+ ? {
40
+ role: 'none',
41
+ className: tx('toolbar.inner', 'toolbar', { layoutManaged }, classNames),
42
+ }
39
43
  : {};
40
44
 
41
45
  return (
@@ -66,7 +70,7 @@ type ToolbarIconButtonProps = IconButtonProps;
66
70
  const ToolbarIconButton = forwardRef<HTMLButtonElement, ToolbarIconButtonProps>((props, forwardedRef) => {
67
71
  return (
68
72
  <ToolbarPrimitive.Button asChild>
69
- <IconButton {...props} ref={forwardedRef} />
73
+ <IconButton {...props} noTooltip ref={forwardedRef} />
70
74
  </ToolbarPrimitive.Button>
71
75
  );
72
76
  });
@@ -125,7 +129,18 @@ const ToolbarToggleGroupIconItem = forwardRef<HTMLButtonElement, ToolbarToggleGr
125
129
  ({ variant, density, elevation, classNames, icon, label, iconOnly, ...props }, forwardedRef) => {
126
130
  return (
127
131
  <ToolbarPrimitive.ToolbarToggleItem {...props} asChild>
128
- <IconButton {...{ variant, density, elevation, classNames, icon, label, iconOnly }} ref={forwardedRef} />
132
+ <IconButton
133
+ {...{
134
+ variant,
135
+ density,
136
+ elevation,
137
+ classNames,
138
+ icon,
139
+ label,
140
+ iconOnly,
141
+ }}
142
+ ref={forwardedRef}
143
+ />
129
144
  </ToolbarPrimitive.ToolbarToggleItem>
130
145
  );
131
146
  },
@@ -41,9 +41,9 @@ type TooltipScopedProps<P = {}> = P & { __scopeTooltip?: Scope };
41
41
  const [createTooltipContext, createTooltipScope] = createContextScope('Tooltip', [createPopperScope]);
42
42
  const usePopperScope = createPopperScope();
43
43
 
44
- /* -------------------------------------------------------------------------------------------------
45
- * Tooltip
46
- * ----------------------------------------------------------------------------------------------- */
44
+ //
45
+ // Tooltip
46
+ //
47
47
 
48
48
  const DEFAULT_DELAY_DURATION = 700;
49
49
  const TOOLTIP_OPEN = 'tooltip.open';
@@ -228,9 +228,9 @@ const TooltipProvider: FC<TooltipProviderProps> = (props: TooltipScopedProps<Too
228
228
 
229
229
  TooltipProvider.displayName = TOOLTIP_NAME;
230
230
 
231
- /* -------------------------------------------------------------------------------------------------
232
- * TooltipVirtualTrigger
233
- * ----------------------------------------------------------------------------------------------- */
231
+ //
232
+ // TooltipVirtualTrigger
233
+ //
234
234
 
235
235
  const TooltipVirtualTrigger = ({
236
236
  virtualRef,
@@ -240,9 +240,9 @@ const TooltipVirtualTrigger = ({
240
240
  return <PopperPrimitive.Anchor asChild {...popperScope} virtualRef={virtualRef} />;
241
241
  };
242
242
 
243
- /* -------------------------------------------------------------------------------------------------
244
- * TooltipTrigger
245
- * ----------------------------------------------------------------------------------------------- */
243
+ //
244
+ // TooltipTrigger
245
+ //
246
246
 
247
247
  const TRIGGER_NAME = 'TooltipTrigger';
248
248
 
@@ -322,9 +322,9 @@ const TooltipTrigger = forwardRef<TooltipTriggerElement, TooltipTriggerProps>(
322
322
 
323
323
  TooltipTrigger.displayName = TRIGGER_NAME;
324
324
 
325
- /* -------------------------------------------------------------------------------------------------
326
- * TooltipPortal
327
- * ----------------------------------------------------------------------------------------------- */
325
+ //
326
+ // TooltipPortal
327
+ //
328
328
 
329
329
  const PORTAL_NAME = 'TooltipPortal';
330
330
 
@@ -363,9 +363,9 @@ const TooltipPortal: FC<TooltipPortalProps> = (props: TooltipScopedProps<Tooltip
363
363
 
364
364
  TooltipPortal.displayName = PORTAL_NAME;
365
365
 
366
- /* -------------------------------------------------------------------------------------------------
367
- * TooltipContent
368
- * ----------------------------------------------------------------------------------------------- */
366
+ //
367
+ // TooltipContent
368
+ //
369
369
 
370
370
  const CONTENT_NAME = 'TooltipContent';
371
371
 
@@ -574,9 +574,9 @@ const TooltipContentImpl = forwardRef<TooltipContentImplElement, TooltipContentI
574
574
 
575
575
  TooltipContent.displayName = CONTENT_NAME;
576
576
 
577
- /* -------------------------------------------------------------------------------------------------
578
- * TooltipArrow
579
- * ----------------------------------------------------------------------------------------------- */
577
+ //
578
+ // TooltipArrow
579
+ //
580
580
 
581
581
  const ARROW_NAME = 'TooltipArrow';
582
582
 
@@ -599,8 +599,6 @@ const TooltipArrow = forwardRef<TooltipArrowElement, TooltipArrowProps>(
599
599
 
600
600
  TooltipArrow.displayName = ARROW_NAME;
601
601
 
602
- /* ----------------------------------------------------------------------------------------------- */
603
-
604
602
  type TooltipSide = NonNullable<TooltipContentProps['side']>;
605
603
 
606
604
  const getExitSideFromRect = (point: Point, rect: DOMRect): TooltipSide => {
@@ -755,6 +753,10 @@ const getHullPresorted = <P extends Point>(points: Readonly<Array<P>>): Array<P>
755
753
  }
756
754
  };
757
755
 
756
+ //
757
+ // Tooltip
758
+ //
759
+
758
760
  export const Tooltip = {
759
761
  Provider: TooltipProvider,
760
762
  Trigger: TooltipTrigger,
@@ -13,7 +13,7 @@ export * from './Input';
13
13
  export * from './Link';
14
14
  export * from './List';
15
15
  export * from './Main';
16
- export * from './Menus';
16
+ export * from './Menu';
17
17
  export * from './Message';
18
18
  export * from './Popover';
19
19
  export * from './Status';
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { useContext } from 'react';
6
6
 
7
- import { type Density } from '@dxos/react-ui-types';
7
+ import { type Density } from '@dxos/ui-types';
8
8
 
9
9
  import { DensityContext } from '../components';
10
10
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { useContext } from 'react';
6
6
 
7
- import { type Elevation } from '@dxos/react-ui-types';
7
+ import { type Elevation } from '@dxos/ui-types';
8
8
 
9
9
  import { ElevationContext } from '../components';
10
10
 
package/src/index.ts CHANGED
@@ -6,7 +6,7 @@ export { type Resource, type TFunction } from 'i18next';
6
6
  export { Trans } from 'react-i18next';
7
7
 
8
8
  export * from '@dxos/react-hooks';
9
- export * from '@dxos/react-ui-types';
9
+ export * from '@dxos/ui-types';
10
10
 
11
11
  export * from './components';
12
12
  export * from './hooks';