@dxos/react-ui 0.8.4-main.e8ec1fe → 0.8.4-main.ef1bc66f44
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.
- package/dist/lib/browser/chunk-EJYV4HAH.mjs +774 -0
- package/dist/lib/browser/chunk-EJYV4HAH.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +3197 -66
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +34 -45
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/chunk-YTLZCZ2M.mjs +776 -0
- package/dist/lib/node-esm/chunk-YTLZCZ2M.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +3197 -66
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +34 -45
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/types/src/components/AnchoredOverflow/AnchoredOverflow.d.ts +7 -0
- package/dist/types/src/components/AnchoredOverflow/AnchoredOverflow.d.ts.map +1 -1
- package/dist/types/src/components/Button/Button.d.ts +1 -1
- package/dist/types/src/components/Button/Button.d.ts.map +1 -1
- package/dist/types/src/components/Button/IconButton.d.ts +2 -1
- package/dist/types/src/components/Button/IconButton.d.ts.map +1 -1
- package/dist/types/src/components/Button/ToggleGroup.d.ts +4 -4
- package/dist/types/src/components/Button/ToggleGroup.stories.d.ts +4 -4
- package/dist/types/src/components/DensityProvider/DensityProvider.d.ts +1 -1
- package/dist/types/src/components/DensityProvider/DensityProvider.d.ts.map +1 -1
- package/dist/types/src/components/Dialog/Dialog.d.ts +24 -9
- package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
- package/dist/types/src/components/Dialog/Dialog.stories.d.ts +7 -5
- package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -1
- package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts +1 -1
- package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts.map +1 -1
- package/dist/types/src/components/Icon/Icon.d.ts +1 -1
- package/dist/types/src/components/Icon/Icon.d.ts.map +1 -1
- package/dist/types/src/components/Input/Input.d.ts +5 -2
- package/dist/types/src/components/Input/Input.d.ts.map +1 -1
- package/dist/types/src/components/Input/Input.stories.d.ts +2 -2
- package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
- package/dist/types/src/components/List/List.d.ts +1 -1
- package/dist/types/src/components/List/List.d.ts.map +1 -1
- package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
- package/dist/types/src/components/Main/Main.d.ts +8 -9
- package/dist/types/src/components/Main/Main.d.ts.map +1 -1
- package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
- package/dist/types/src/components/{Menus → Menu}/ContextMenu.d.ts +6 -6
- package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -0
- package/dist/types/src/components/Menu/ContextMenu.stories.d.ts.map +1 -0
- package/dist/types/src/components/{Menus → Menu}/DropdownMenu.d.ts +3 -4
- package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -0
- package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -0
- package/dist/types/src/components/Menu/index.d.ts.map +1 -0
- package/dist/types/src/components/Message/Message.d.ts +1 -1
- package/dist/types/src/components/Message/Message.d.ts.map +1 -1
- package/dist/types/src/components/Message/Message.stories.d.ts +1 -1
- package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
- package/dist/types/src/components/Popover/Popover.d.ts +1 -1
- package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
- package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +25 -26
- package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
- package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +46 -8
- package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
- package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +4 -2
- package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
- package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +2 -1
- package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/Select/Select.d.ts +9 -9
- package/dist/types/src/components/Separator/Separator.d.ts +1 -1
- package/dist/types/src/components/Skeleton/Skeleton.d.ts +12 -0
- package/dist/types/src/components/Skeleton/Skeleton.d.ts.map +1 -0
- package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts +17 -0
- package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts.map +1 -0
- package/dist/types/src/components/Skeleton/index.d.ts +2 -0
- package/dist/types/src/components/Skeleton/index.d.ts.map +1 -0
- package/dist/types/src/components/Splitter/Splitter.d.ts +26 -0
- package/dist/types/src/components/Splitter/Splitter.d.ts.map +1 -0
- package/dist/types/src/components/Splitter/Splitter.stories.d.ts +7 -0
- package/dist/types/src/components/Splitter/Splitter.stories.d.ts.map +1 -0
- package/dist/types/src/components/Splitter/index.d.ts +2 -0
- package/dist/types/src/components/Splitter/index.d.ts.map +1 -0
- package/dist/types/src/components/Tag/Tag.d.ts +1 -1
- package/dist/types/src/components/Tag/Tag.d.ts.map +1 -1
- package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +2 -2
- package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
- package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +1 -8
- package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
- package/dist/types/src/components/ThemeProvider/index.d.ts +2 -1
- package/dist/types/src/components/ThemeProvider/index.d.ts.map +1 -1
- package/dist/types/src/components/Toast/Toast.d.ts +4 -4
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +13 -12
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +3 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/exemplars/generics.stories.d.ts +17 -0
- package/dist/types/src/exemplars/generics.stories.d.ts.map +1 -0
- package/dist/types/src/exemplars/slot.stories.d.ts +14 -0
- package/dist/types/src/exemplars/slot.stories.d.ts.map +1 -0
- package/dist/types/src/exemplars/tabster.stories.d.ts +8 -0
- package/dist/types/src/exemplars/tabster.stories.d.ts.map +1 -0
- package/dist/types/src/hooks/useDensityContext.d.ts +1 -1
- package/dist/types/src/hooks/useDensityContext.d.ts.map +1 -1
- package/dist/types/src/hooks/useElevationContext.d.ts +1 -1
- package/dist/types/src/hooks/useElevationContext.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/playground/Controls.stories.d.ts.map +1 -1
- package/dist/types/src/primitives/Container/Container.d.ts +23 -0
- package/dist/types/src/primitives/Container/Container.d.ts.map +1 -0
- package/dist/types/src/primitives/Container/Container.stories.d.ts +11 -0
- package/dist/types/src/primitives/Container/Container.stories.d.ts.map +1 -0
- package/dist/types/src/primitives/Container/Layout.d.ts +18 -0
- package/dist/types/src/primitives/Container/Layout.d.ts.map +1 -0
- package/dist/types/src/primitives/Container/Layout.stories.d.ts +10 -0
- package/dist/types/src/primitives/Container/Layout.stories.d.ts.map +1 -0
- package/dist/types/src/primitives/Container/index.d.ts +3 -0
- package/dist/types/src/primitives/Container/index.d.ts.map +1 -0
- package/dist/types/src/primitives/Flex/Flex.d.ts +8 -0
- package/dist/types/src/primitives/Flex/Flex.d.ts.map +1 -0
- package/dist/types/src/primitives/Flex/index.d.ts +2 -0
- package/dist/types/src/primitives/Flex/index.d.ts.map +1 -0
- package/dist/types/src/primitives/index.d.ts +3 -0
- package/dist/types/src/primitives/index.d.ts.map +1 -0
- package/dist/types/src/testing/decorators/withLayout.d.ts +3 -3
- package/dist/types/src/testing/decorators/withLayout.d.ts.map +1 -1
- package/dist/types/src/testing/decorators/withLayoutVariants.d.ts +1 -1
- package/dist/types/src/testing/decorators/withLayoutVariants.d.ts.map +1 -1
- package/dist/types/src/testing/decorators/withTheme.d.ts +3 -2
- package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -2
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +37 -32
- package/src/components/AnchoredOverflow/AnchoredOverflow.tsx +8 -0
- package/src/components/Avatars/Avatar.stories.tsx +4 -4
- package/src/components/Avatars/Avatar.tsx +1 -1
- package/src/components/Avatars/AvatarGroup.stories.tsx +2 -2
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +2 -2
- package/src/components/Button/Button.stories.tsx +2 -2
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Button/IconButton.stories.tsx +2 -2
- package/src/components/Button/IconButton.tsx +8 -3
- package/src/components/Button/Toggle.stories.tsx +2 -2
- package/src/components/Button/ToggleGroup.stories.tsx +2 -2
- package/src/components/Clipboard/CopyButton.tsx +3 -3
- package/src/components/DensityProvider/DensityProvider.tsx +1 -1
- package/src/components/Dialog/AlertDialog.stories.tsx +2 -2
- package/src/components/Dialog/Dialog.stories.tsx +57 -23
- package/src/components/Dialog/Dialog.tsx +181 -40
- package/src/components/ElevationProvider/ElevationProvider.tsx +1 -1
- package/src/components/Icon/Icon.stories.tsx +3 -3
- package/src/components/Icon/Icon.tsx +1 -1
- package/src/components/Input/Input.stories.tsx +12 -11
- package/src/components/Input/Input.tsx +13 -5
- package/src/components/Link/Link.stories.tsx +2 -2
- package/src/components/List/List.stories.tsx +18 -14
- package/src/components/List/List.tsx +1 -1
- package/src/components/List/Tree.stories.tsx +2 -2
- package/src/components/List/Treegrid.stories.tsx +2 -2
- package/src/components/List/Treegrid.tsx +1 -1
- package/src/components/Main/Main.stories.tsx +41 -20
- package/src/components/Main/Main.tsx +92 -45
- package/src/components/{Menus → Menu}/ContextMenu.stories.tsx +2 -2
- package/src/components/{Menus → Menu}/DropdownMenu.stories.tsx +2 -2
- package/src/components/{Menus → Menu}/DropdownMenu.tsx +61 -57
- package/src/components/Message/Message.stories.tsx +3 -3
- package/src/components/Message/Message.tsx +30 -5
- package/src/components/Popover/Popover.stories.tsx +2 -2
- package/src/components/Popover/Popover.tsx +35 -33
- package/src/components/ScrollArea/ScrollArea.stories.tsx +166 -40
- package/src/components/ScrollArea/ScrollArea.tsx +86 -80
- package/src/components/ScrollArea/index.ts +1 -1
- package/src/components/ScrollContainer/ScrollContainer.stories.tsx +3 -2
- package/src/components/ScrollContainer/ScrollContainer.tsx +99 -92
- package/src/components/Select/Select.stories.tsx +2 -2
- package/src/components/Skeleton/Skeleton.stories.tsx +52 -0
- package/src/components/Skeleton/Skeleton.tsx +26 -0
- package/src/components/Skeleton/index.ts +5 -0
- package/src/components/Splitter/Splitter.stories.tsx +73 -0
- package/src/components/Splitter/Splitter.tsx +123 -0
- package/src/components/Splitter/index.ts +5 -0
- package/src/components/Status/Status.stories.tsx +2 -2
- package/src/components/Tag/Tag.stories.tsx +4 -4
- package/src/components/Tag/Tag.tsx +1 -1
- package/src/components/ThemeProvider/ThemeProvider.tsx +2 -3
- package/src/components/ThemeProvider/TranslationsProvider.tsx +1 -16
- package/src/components/ThemeProvider/index.ts +3 -3
- package/src/components/Toast/Toast.stories.tsx +2 -2
- package/src/components/Toolbar/Toolbar.stories.tsx +2 -2
- package/src/components/Toolbar/Toolbar.tsx +31 -12
- package/src/components/Tooltip/Tooltip.stories.tsx +2 -2
- package/src/components/Tooltip/Tooltip.tsx +22 -20
- package/src/components/index.ts +3 -1
- package/src/exemplars/generics.stories.tsx +44 -0
- package/src/exemplars/slot.stories.tsx +108 -0
- package/src/exemplars/tabster.stories.tsx +127 -0
- package/src/hooks/useDensityContext.ts +1 -1
- package/src/hooks/useElevationContext.ts +1 -1
- package/src/index.ts +2 -1
- package/src/playground/Controls.stories.tsx +3 -4
- package/src/playground/Custom.stories.tsx +2 -2
- package/src/playground/Typography.stories.tsx +2 -2
- package/src/primitives/Container/Container.stories.tsx +67 -0
- package/src/primitives/Container/Container.tsx +82 -0
- package/src/primitives/Container/Layout.stories.tsx +57 -0
- package/src/primitives/Container/Layout.tsx +61 -0
- package/src/primitives/Container/index.ts +6 -0
- package/src/primitives/Flex/Flex.tsx +26 -0
- package/src/primitives/Flex/index.ts +5 -0
- package/src/primitives/index.ts +6 -0
- package/src/testing/decorators/withLayout.tsx +22 -15
- package/src/testing/decorators/withLayoutVariants.tsx +3 -3
- package/src/testing/decorators/withTheme.tsx +21 -18
- package/src/util/index.ts +2 -2
- package/dist/lib/browser/chunk-53MI2QCM.mjs +0 -4707
- package/dist/lib/browser/chunk-53MI2QCM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ID67AFFF.mjs +0 -4709
- package/dist/lib/node-esm/chunk-ID67AFFF.mjs.map +0 -7
- package/dist/types/src/components/Menus/ContextMenu.d.ts.map +0 -1
- package/dist/types/src/components/Menus/ContextMenu.stories.d.ts.map +0 -1
- package/dist/types/src/components/Menus/DropdownMenu.d.ts.map +0 -1
- package/dist/types/src/components/Menus/DropdownMenu.stories.d.ts.map +0 -1
- package/dist/types/src/components/Menus/index.d.ts.map +0 -1
- package/dist/types/src/util/ThemedClassName.d.ts +0 -5
- package/dist/types/src/util/ThemedClassName.d.ts.map +0 -1
- package/dist/types/src/util/domino.d.ts +0 -18
- package/dist/types/src/util/domino.d.ts.map +0 -1
- package/src/util/ThemedClassName.ts +0 -7
- package/src/util/domino.ts +0 -53
- /package/dist/types/src/components/{Menus → Menu}/ContextMenu.stories.d.ts +0 -0
- /package/dist/types/src/components/{Menus → Menu}/DropdownMenu.stories.d.ts +0 -0
- /package/dist/types/src/components/{Menus → Menu}/index.d.ts +0 -0
- /package/src/components/{Menus → Menu}/ContextMenu.tsx +0 -0
- /package/src/components/{Menus → Menu}/index.ts +0 -0
|
@@ -45,16 +45,17 @@ 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
|
);
|
|
51
52
|
};
|
|
52
53
|
|
|
53
54
|
const meta = {
|
|
54
|
-
title: 'ui/react-ui-core/ScrollContainer',
|
|
55
|
+
title: 'ui/react-ui-core/components/ScrollContainer',
|
|
55
56
|
component: ScrollContainer.Root,
|
|
56
57
|
render: DefaultStory,
|
|
57
|
-
decorators: [withTheme, withLayout({
|
|
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,16 +12,18 @@ 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/
|
|
22
|
+
import { mx } from '@dxos/ui-theme';
|
|
23
23
|
|
|
24
24
|
import { type ThemedClassName } from '../../util';
|
|
25
25
|
import { IconButton } from '../Button';
|
|
26
|
+
import { ScrollArea } from '../ScrollArea';
|
|
26
27
|
|
|
27
28
|
const isBottom = (el: HTMLElement | null) => {
|
|
28
29
|
return !!(el && el.scrollHeight - el.scrollTop === el.clientHeight);
|
|
@@ -51,98 +52,101 @@ type RootProps = ThemedClassName<
|
|
|
51
52
|
PropsWithChildren<{
|
|
52
53
|
pin?: boolean;
|
|
53
54
|
fade?: boolean;
|
|
55
|
+
behavior?: ScrollBehavior;
|
|
54
56
|
}>
|
|
55
57
|
>;
|
|
56
58
|
|
|
57
59
|
/**
|
|
58
60
|
* Scroll container that automatically scrolls to the bottom when new content is added.
|
|
59
61
|
*/
|
|
60
|
-
const Root = forwardRef<ScrollController, RootProps>(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
62
|
+
const Root = forwardRef<ScrollController, RootProps>(
|
|
63
|
+
({ children, classNames, pin, fade, behavior: behaviorProp = 'smooth' }, forwardedRef) => {
|
|
64
|
+
const scrollerRef = useRef<HTMLDivElement>(null);
|
|
65
|
+
const autoScrollRef = useRef(false);
|
|
66
|
+
const [overflow, setOverflow] = useState(false);
|
|
67
|
+
const [pinned, setPinned] = useState(pin);
|
|
68
|
+
|
|
69
|
+
const timeoutRef = useRef<NodeJS.Timeout>(undefined);
|
|
70
|
+
const scrollToBottom = useCallback((behavior: ScrollBehavior = behaviorProp) => {
|
|
71
|
+
if (scrollerRef.current) {
|
|
72
|
+
// Temporarily hide scrollbar to prevent flicker.
|
|
73
|
+
autoScrollRef.current = true;
|
|
74
|
+
scrollerRef.current.classList.add('scrollbar-none');
|
|
75
|
+
scrollerRef.current.scrollTo({
|
|
76
|
+
top: scrollerRef.current.scrollHeight,
|
|
77
|
+
behavior,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
clearTimeout(timeoutRef.current);
|
|
81
|
+
if (behavior !== 'instant') {
|
|
82
|
+
timeoutRef.current = setTimeout(() => {
|
|
83
|
+
scrollerRef.current?.classList.remove('scrollbar-none');
|
|
84
|
+
autoScrollRef.current = false;
|
|
85
|
+
}, 500);
|
|
86
|
+
}
|
|
87
|
+
setPinned(true);
|
|
83
88
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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);
|
|
89
|
+
}, []);
|
|
90
|
+
|
|
91
|
+
const controller = useMemo(
|
|
92
|
+
() => ({
|
|
93
|
+
viewport: scrollerRef.current,
|
|
94
|
+
scrollToTop: () => {
|
|
95
|
+
invariant(scrollerRef.current);
|
|
96
|
+
scrollerRef.current.scrollTo({ top: 0, behavior: 'smooth' });
|
|
97
|
+
setPinned(false);
|
|
98
|
+
},
|
|
99
|
+
scrollToBottom: () => {
|
|
100
|
+
scrollToBottom('smooth');
|
|
101
|
+
},
|
|
120
102
|
}),
|
|
103
|
+
[scrollToBottom, scrollerRef.current],
|
|
121
104
|
);
|
|
122
|
-
}, []);
|
|
123
105
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
106
|
+
// Scroll controller imperative ref.
|
|
107
|
+
useImperativeHandle(forwardedRef, () => controller, [controller]);
|
|
108
|
+
|
|
109
|
+
// Listen for scroll events.
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
if (!scrollerRef.current) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return combine(
|
|
116
|
+
// Check if user scrolls.
|
|
117
|
+
addEventListener(scrollerRef.current, 'wheel', () => {
|
|
118
|
+
setPinned(isBottom(scrollerRef.current));
|
|
119
|
+
}),
|
|
120
|
+
// Check if scrolls.
|
|
121
|
+
addEventListener(scrollerRef.current, 'scroll', () => {
|
|
122
|
+
setOverflow((scrollerRef.current?.scrollTop ?? 0) > 0);
|
|
123
|
+
}),
|
|
124
|
+
);
|
|
125
|
+
}, []);
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<ScrollContainerProvider pinned={pinned} controller={controller} scrollToBottom={scrollToBottom}>
|
|
129
|
+
<div className='relative grid flex-1 min-bs-0 overflow-hidden'>
|
|
130
|
+
{fade && (
|
|
131
|
+
<div
|
|
132
|
+
role='none'
|
|
133
|
+
data-visible={overflow}
|
|
134
|
+
className={mx(
|
|
135
|
+
// NOTE: Gradients may not be visible with dark reader extensions.
|
|
136
|
+
'z-10 absolute block-start-0 inset-inline-0 bs-24 is-full',
|
|
137
|
+
'opacity-0 duration-200 transition-opacity data-[visible="true"]:opacity-100',
|
|
138
|
+
'bg-gradient-to-b from-[--surface-bg] to-transparent pointer-events-none',
|
|
139
|
+
)}
|
|
140
|
+
/>
|
|
141
|
+
)}
|
|
142
|
+
<ScrollArea.Root classNames={mx('min-bs-0', classNames)} ref={scrollerRef} thin>
|
|
143
|
+
<ScrollArea.Viewport>{children}</ScrollArea.Viewport>
|
|
144
|
+
</ScrollArea.Root>
|
|
141
145
|
</div>
|
|
142
|
-
</
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
</ScrollContainerProvider>
|
|
147
|
+
);
|
|
148
|
+
},
|
|
149
|
+
);
|
|
146
150
|
|
|
147
151
|
Root.displayName = 'ScrollContainer.Root';
|
|
148
152
|
|
|
@@ -150,25 +154,26 @@ Root.displayName = 'ScrollContainer.Root';
|
|
|
150
154
|
// Viewport
|
|
151
155
|
//
|
|
152
156
|
|
|
157
|
+
const VIEWPORT_NAME = 'ScrollContainer.Viewport';
|
|
158
|
+
|
|
153
159
|
type ViewportProps = ThemedClassName<PropsWithChildren<Omit<HTMLAttributes<HTMLDivElement>, 'className'>>>;
|
|
154
160
|
|
|
155
161
|
const Viewport = forwardRef<HTMLDivElement, ViewportProps>(({ classNames, children, ...props }, forwardedRef) => {
|
|
156
162
|
const contentRef = useForwardedRef(forwardedRef);
|
|
157
|
-
const { pinned, scrollToBottom } = useScrollContainerContext(
|
|
163
|
+
const { pinned, scrollToBottom } = useScrollContainerContext(VIEWPORT_NAME);
|
|
158
164
|
|
|
159
165
|
useEffect(() => {
|
|
160
166
|
if (!pinned || !contentRef.current) {
|
|
161
167
|
return;
|
|
162
168
|
}
|
|
163
169
|
|
|
170
|
+
// Scroll instantly otherwise it might move while we're scrolling.
|
|
171
|
+
scrollToBottom();
|
|
172
|
+
|
|
164
173
|
// Setup resize observer to detect content changes.
|
|
165
174
|
const resizeObserver = new ResizeObserver(() => scrollToBottom());
|
|
166
|
-
scrollToBottom('instant');
|
|
167
|
-
|
|
168
175
|
resizeObserver.observe(contentRef.current);
|
|
169
|
-
return () =>
|
|
170
|
-
resizeObserver.disconnect();
|
|
171
|
-
};
|
|
176
|
+
return () => resizeObserver.disconnect();
|
|
172
177
|
}, [pinned, scrollToBottom]);
|
|
173
178
|
|
|
174
179
|
return (
|
|
@@ -178,16 +183,18 @@ const Viewport = forwardRef<HTMLDivElement, ViewportProps>(({ classNames, childr
|
|
|
178
183
|
);
|
|
179
184
|
});
|
|
180
185
|
|
|
181
|
-
Viewport.displayName =
|
|
186
|
+
Viewport.displayName = VIEWPORT_NAME;
|
|
182
187
|
|
|
183
188
|
//
|
|
184
189
|
// ScrollDownButton
|
|
185
190
|
//
|
|
186
191
|
|
|
192
|
+
const SCROLL_DOWN_BUTTON_NAME = 'ScrollContainer.ScrollDownButton';
|
|
193
|
+
|
|
187
194
|
type ScrollDownButtonProps = ThemedClassName;
|
|
188
195
|
|
|
189
196
|
const ScrollDownButton = ({ classNames }: ScrollDownButtonProps) => {
|
|
190
|
-
const { pinned, scrollToBottom } = useScrollContainerContext(
|
|
197
|
+
const { pinned, scrollToBottom } = useScrollContainerContext(SCROLL_DOWN_BUTTON_NAME);
|
|
191
198
|
|
|
192
199
|
return (
|
|
193
200
|
<div
|
|
@@ -210,7 +217,7 @@ const ScrollDownButton = ({ classNames }: ScrollDownButtonProps) => {
|
|
|
210
217
|
);
|
|
211
218
|
};
|
|
212
219
|
|
|
213
|
-
ScrollDownButton.displayName =
|
|
220
|
+
ScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
|
|
214
221
|
|
|
215
222
|
//
|
|
216
223
|
// ScrollContainer
|
|
@@ -42,9 +42,9 @@ const DefaultStory = ({ items = [] }: StoryProps) => {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
const meta = {
|
|
45
|
-
title: 'ui/react-ui-core/Select',
|
|
45
|
+
title: 'ui/react-ui-core/components/Select',
|
|
46
46
|
render: DefaultStory,
|
|
47
|
-
decorators: [withTheme, withLayoutVariants()],
|
|
47
|
+
decorators: [withTheme(), withLayoutVariants()],
|
|
48
48
|
} satisfies Meta<typeof DefaultStory>;
|
|
49
49
|
|
|
50
50
|
export default meta;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { withTheme } from '../../testing';
|
|
8
|
+
|
|
9
|
+
import { Skeleton } from './Skeleton';
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
title: 'ui/react-ui-core/components/Skeleton',
|
|
13
|
+
component: Skeleton,
|
|
14
|
+
decorators: [withTheme()],
|
|
15
|
+
parameters: {
|
|
16
|
+
layout: 'centered',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const Default = {
|
|
21
|
+
render: () => (
|
|
22
|
+
<div className='flex flex-col gap-4 p-4 border border-separator rounded-sm'>
|
|
23
|
+
<div className='flex is-fit items-center gap-4'>
|
|
24
|
+
<Skeleton classNames='size-10 shrink-0 rounded-full' />
|
|
25
|
+
<div className='grid gap-2'>
|
|
26
|
+
<Skeleton classNames='bs-4 is-[150px]' />
|
|
27
|
+
<Skeleton classNames='bs-4 is-[100px]' />
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const Card = {
|
|
35
|
+
render: () => (
|
|
36
|
+
<div className='flex flex-col gap-3 is-96 p-4 border border-separator rounded-sm'>
|
|
37
|
+
<div className='flex items-center gap-3'>
|
|
38
|
+
<Skeleton variant='circle' classNames='bs-12 is-12 rounded-full' />
|
|
39
|
+
<div className='flex flex-col gap-2 flex-1'>
|
|
40
|
+
<Skeleton classNames='bs-4 is-24' />
|
|
41
|
+
<Skeleton classNames='bs-3 is-32' />
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
<Skeleton classNames='bs-32 is-full rounded' />
|
|
45
|
+
<div className='flex flex-col gap-2'>
|
|
46
|
+
<Skeleton classNames='bs-3 is-full' />
|
|
47
|
+
<Skeleton classNames='bs-3 is-5/6' />
|
|
48
|
+
<Skeleton classNames='bs-3 is-4/6' />
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
),
|
|
52
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { type ComponentPropsWithRef, forwardRef } from 'react';
|
|
6
|
+
|
|
7
|
+
import { useThemeContext } from '../../hooks';
|
|
8
|
+
import { type ThemedClassName } from '../../util';
|
|
9
|
+
|
|
10
|
+
type SkeletonProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {
|
|
11
|
+
variant?: 'default' | 'circle' | 'text';
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A skeleton loading component that displays a placeholder while content is loading.
|
|
16
|
+
*/
|
|
17
|
+
const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(
|
|
18
|
+
({ classNames, variant = 'default', ...props }, forwardedRef) => {
|
|
19
|
+
const { tx } = useThemeContext();
|
|
20
|
+
return <div {...props} className={tx('skeleton.root', 'skeleton', { variant }, classNames)} ref={forwardedRef} />;
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export { Skeleton };
|
|
25
|
+
|
|
26
|
+
export type { SkeletonProps };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React, { useState } from 'react';
|
|
7
|
+
|
|
8
|
+
import { Layout } from '../../primitives';
|
|
9
|
+
import { withLayout, withTheme } from '../../testing';
|
|
10
|
+
import { ScrollArea } from '../ScrollArea';
|
|
11
|
+
import { Toolbar } from '../Toolbar';
|
|
12
|
+
|
|
13
|
+
import { Splitter, type SplitterRootProps } from './Splitter';
|
|
14
|
+
|
|
15
|
+
const Panel = ({ label }: { label: string }) => {
|
|
16
|
+
return (
|
|
17
|
+
<Layout.Main toolbar>
|
|
18
|
+
<Toolbar.Root>{label}</Toolbar.Root>
|
|
19
|
+
<ScrollArea.Root orientation='vertical'>
|
|
20
|
+
<ScrollArea.Viewport>
|
|
21
|
+
{Array.from({ length: 100 }).map((_, i) => (
|
|
22
|
+
<div key={i} className='p-1'>
|
|
23
|
+
{label}-{i}
|
|
24
|
+
</div>
|
|
25
|
+
))}
|
|
26
|
+
</ScrollArea.Viewport>
|
|
27
|
+
</ScrollArea.Root>
|
|
28
|
+
</Layout.Main>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const DefaultStory = (props: SplitterRootProps) => {
|
|
33
|
+
const [mode, setMode] = useState(props.mode ?? 'both');
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className='grid grid-rows-[min-content_1fr] bs-full overflow-hidden'>
|
|
37
|
+
<Toolbar.Root>
|
|
38
|
+
<Toolbar.Button onClick={() => setMode('upper')}>A</Toolbar.Button>
|
|
39
|
+
<Toolbar.Button onClick={() => setMode('both')}>A + B</Toolbar.Button>
|
|
40
|
+
<Toolbar.Button onClick={() => setMode('lower')}>B</Toolbar.Button>
|
|
41
|
+
</Toolbar.Root>
|
|
42
|
+
<Splitter.Root mode={mode} ratio={props.ratio} classNames='divide-y divide-subduedSeparator'>
|
|
43
|
+
<Splitter.Panel position='upper'>
|
|
44
|
+
<Panel label='A' />
|
|
45
|
+
</Splitter.Panel>
|
|
46
|
+
<Splitter.Panel position='lower'>
|
|
47
|
+
<Panel label='B' />
|
|
48
|
+
</Splitter.Panel>
|
|
49
|
+
</Splitter.Root>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const meta: Meta<SplitterRootProps> = {
|
|
55
|
+
title: 'ui/react-ui-core/components/Splitter',
|
|
56
|
+
component: Splitter.Root,
|
|
57
|
+
render: DefaultStory,
|
|
58
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
59
|
+
parameters: {
|
|
60
|
+
layout: 'fullscreen',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default meta;
|
|
65
|
+
|
|
66
|
+
type Story = StoryObj<SplitterRootProps>;
|
|
67
|
+
|
|
68
|
+
export const Default: Story = {
|
|
69
|
+
args: {
|
|
70
|
+
mode: 'both',
|
|
71
|
+
ratio: 0.5,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { createContextScope } from '@radix-ui/react-context';
|
|
6
|
+
import React, { type ComponentPropsWithoutRef, forwardRef } from 'react';
|
|
7
|
+
|
|
8
|
+
import { mx } from '@dxos/ui-theme';
|
|
9
|
+
|
|
10
|
+
import { type ThemedClassName } from '../../util';
|
|
11
|
+
|
|
12
|
+
type ScopedProps<P> = P & { __scopeSplitter?: any };
|
|
13
|
+
|
|
14
|
+
// TODO(burdon): Generalize styles.
|
|
15
|
+
// TODO(burdon): Enalbe resize.
|
|
16
|
+
// TODO(burdon): Generalize horizontal/vertical and change to start/end.
|
|
17
|
+
type Mode = 'upper' | 'lower' | 'both';
|
|
18
|
+
|
|
19
|
+
type SplitterContextValue = {
|
|
20
|
+
mode: Mode;
|
|
21
|
+
ratio: number;
|
|
22
|
+
transition: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const SPLITTER_NAME = 'Splitter';
|
|
26
|
+
|
|
27
|
+
const [createSplitterContext, createSplitterScope] = createContextScope(SPLITTER_NAME);
|
|
28
|
+
|
|
29
|
+
const [SplitterProvider, useSplitterContext] = createSplitterContext<SplitterContextValue>(SPLITTER_NAME);
|
|
30
|
+
|
|
31
|
+
//
|
|
32
|
+
// Root
|
|
33
|
+
//
|
|
34
|
+
|
|
35
|
+
const ROOT_NAME = 'Splitter.Root';
|
|
36
|
+
|
|
37
|
+
type RootProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> & Partial<SplitterContextValue>;
|
|
38
|
+
|
|
39
|
+
const Root = forwardRef<HTMLDivElement, ScopedProps<RootProps>>(
|
|
40
|
+
(
|
|
41
|
+
{ __scopeSplitter, classNames, mode = 'upper', ratio = 0.5, transition = 250, children, ...rootProps },
|
|
42
|
+
forwardedRef,
|
|
43
|
+
) => {
|
|
44
|
+
return (
|
|
45
|
+
<SplitterProvider scope={__scopeSplitter} mode={mode} ratio={ratio} transition={transition}>
|
|
46
|
+
<div
|
|
47
|
+
role='none'
|
|
48
|
+
{...rootProps}
|
|
49
|
+
ref={forwardedRef}
|
|
50
|
+
className={mx('relative bs-full overflow-hidden', classNames)}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</div>
|
|
54
|
+
</SplitterProvider>
|
|
55
|
+
);
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
Root.displayName = ROOT_NAME;
|
|
60
|
+
|
|
61
|
+
//
|
|
62
|
+
// Panel
|
|
63
|
+
//
|
|
64
|
+
|
|
65
|
+
const PANEL_NAME = 'Splitter.Panel';
|
|
66
|
+
|
|
67
|
+
interface PanelProps extends ThemedClassName<ComponentPropsWithoutRef<'div'>> {
|
|
68
|
+
position: 'upper' | 'lower';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const Panel = forwardRef<HTMLDivElement, ScopedProps<PanelProps>>(
|
|
72
|
+
({ __scopeSplitter, classNames, children, position, style, ...panelProps }, forwardedRef) => {
|
|
73
|
+
const context = useSplitterContext(PANEL_NAME, __scopeSplitter);
|
|
74
|
+
const { mode, ratio, transition } = context;
|
|
75
|
+
|
|
76
|
+
// Calculate position and height based on mode and ratio.
|
|
77
|
+
const isUpper = position === 'upper';
|
|
78
|
+
const top = isUpper ? '0%' : mode === 'upper' ? '100%' : mode === 'lower' ? '0%' : `${ratio * 100}%`;
|
|
79
|
+
|
|
80
|
+
const height = isUpper
|
|
81
|
+
? mode === 'upper'
|
|
82
|
+
? '100%'
|
|
83
|
+
: mode === 'lower'
|
|
84
|
+
? '0%'
|
|
85
|
+
: `${ratio * 100}%`
|
|
86
|
+
: mode === 'lower'
|
|
87
|
+
? '100%'
|
|
88
|
+
: mode === 'upper'
|
|
89
|
+
? '0%'
|
|
90
|
+
: `${(1 - ratio) * 100}%`;
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div
|
|
94
|
+
{...panelProps}
|
|
95
|
+
ref={forwardedRef}
|
|
96
|
+
className={mx('absolute inset-inline-0 flex flex-col overflow-hidden', classNames)}
|
|
97
|
+
style={{
|
|
98
|
+
top,
|
|
99
|
+
height,
|
|
100
|
+
transition: `top ${transition}ms, height ${transition}ms ease-out`,
|
|
101
|
+
...style,
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
{children}
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
Panel.displayName = PANEL_NAME;
|
|
111
|
+
|
|
112
|
+
//
|
|
113
|
+
// Splitter
|
|
114
|
+
//
|
|
115
|
+
|
|
116
|
+
const Splitter = {
|
|
117
|
+
Root,
|
|
118
|
+
Panel,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export { Splitter, createSplitterScope };
|
|
122
|
+
|
|
123
|
+
export type { Mode as SplitterMode, RootProps as SplitterRootProps, PanelProps as SplitterPanelProps };
|
|
@@ -10,9 +10,9 @@ import { withTheme } from '../../testing';
|
|
|
10
10
|
import { Status } from './Status';
|
|
11
11
|
|
|
12
12
|
const meta = {
|
|
13
|
-
title: 'ui/react-ui-core/Status',
|
|
13
|
+
title: 'ui/react-ui-core/components/Status',
|
|
14
14
|
component: Status,
|
|
15
|
-
decorators: [withTheme],
|
|
15
|
+
decorators: [withTheme()],
|
|
16
16
|
} satisfies Meta<typeof Status>;
|
|
17
17
|
|
|
18
18
|
export default meta;
|
|
@@ -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/
|
|
9
|
-
import { type ChromaticPalette, type MessageValence } from '@dxos/
|
|
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
|
|
|
@@ -15,7 +15,7 @@ import { Tag } from './Tag';
|
|
|
15
15
|
const palettes = ['neutral', 'success', 'info', 'warning', 'error', ...hues] as (ChromaticPalette | MessageValence)[];
|
|
16
16
|
|
|
17
17
|
const meta = {
|
|
18
|
-
title: 'ui/react-ui-core/Tag',
|
|
18
|
+
title: 'ui/react-ui-core/components/Tag',
|
|
19
19
|
component: Tag,
|
|
20
20
|
render: () => (
|
|
21
21
|
<div role='grid' className='grid grid-cols-5 gap-2 max-is-screen-md'>
|
|
@@ -26,7 +26,7 @@ const meta = {
|
|
|
26
26
|
))}
|
|
27
27
|
</div>
|
|
28
28
|
),
|
|
29
|
-
decorators: [withTheme],
|
|
29
|
+
decorators: [withTheme()],
|
|
30
30
|
parameters: {
|
|
31
31
|
chromatic: {
|
|
32
32
|
disableSnapshot: false,
|
|
@@ -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/
|
|
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/
|
|
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,14 +14,13 @@ 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;
|
|
22
20
|
hasIosKeyboard: boolean;
|
|
23
21
|
safeAreaPadding?: SafeAreaPadding;
|
|
24
22
|
noCache?: boolean;
|
|
23
|
+
platform?: 'mobile' | 'desktop';
|
|
25
24
|
};
|
|
26
25
|
|
|
27
26
|
/**
|