@dxos/react-ui-tabs 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/index.mjs +146 -187
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +146 -187
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/Tabs.d.ts +6 -1
- package/dist/types/src/Tabs.d.ts.map +1 -1
- package/dist/types/src/Tabs.stories.d.ts +11 -1
- package/dist/types/src/Tabs.stories.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +21 -18
- package/src/Tabs.stories.tsx +2 -2
- package/src/Tabs.tsx +90 -76
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-tabs",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.ef1bc66f44",
|
|
4
4
|
"description": "Components for facilitating a Tabs pattern.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/dxos/dxos"
|
|
10
|
+
},
|
|
7
11
|
"license": "MIT",
|
|
8
12
|
"author": "DXOS.org",
|
|
9
|
-
"sideEffects":
|
|
13
|
+
"sideEffects": false,
|
|
10
14
|
"type": "module",
|
|
11
15
|
"exports": {
|
|
12
16
|
".": {
|
|
@@ -25,33 +29,32 @@
|
|
|
25
29
|
"src"
|
|
26
30
|
],
|
|
27
31
|
"dependencies": {
|
|
28
|
-
"@fluentui/react-tabster": "
|
|
29
|
-
"@preact-signals/safe-react": "^0.9.0",
|
|
32
|
+
"@fluentui/react-tabster": "9.26.11",
|
|
30
33
|
"@radix-ui/primitive": "1.1.1",
|
|
31
34
|
"@radix-ui/react-context": "1.1.1",
|
|
32
35
|
"@radix-ui/react-primitive": "2.0.2",
|
|
33
36
|
"@radix-ui/react-slot": "1.1.2",
|
|
34
37
|
"@radix-ui/react-tabs": "1.1.3",
|
|
35
38
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
|
36
|
-
"@dxos/react-ui-attention": "0.8.4-main.
|
|
37
|
-
"@dxos/util": "0.8.4-main.
|
|
39
|
+
"@dxos/react-ui-attention": "0.8.4-main.ef1bc66f44",
|
|
40
|
+
"@dxos/util": "0.8.4-main.ef1bc66f44"
|
|
38
41
|
},
|
|
39
42
|
"devDependencies": {
|
|
40
|
-
"@types/react": "~19.2.
|
|
41
|
-
"@types/react-dom": "~19.2.
|
|
42
|
-
"react": "~19.2.
|
|
43
|
-
"react-dom": "~19.2.
|
|
43
|
+
"@types/react": "~19.2.7",
|
|
44
|
+
"@types/react-dom": "~19.2.3",
|
|
45
|
+
"react": "~19.2.3",
|
|
46
|
+
"react-dom": "~19.2.3",
|
|
44
47
|
"vite": "7.1.9",
|
|
45
|
-
"@dxos/
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/
|
|
48
|
+
"@dxos/react-ui": "0.8.4-main.ef1bc66f44",
|
|
49
|
+
"@dxos/storybook-utils": "0.8.4-main.ef1bc66f44",
|
|
50
|
+
"@dxos/ui-theme": "0.8.4-main.ef1bc66f44",
|
|
51
|
+
"@dxos/random": "0.8.4-main.ef1bc66f44"
|
|
49
52
|
},
|
|
50
53
|
"peerDependencies": {
|
|
51
|
-
"react": "
|
|
52
|
-
"react-dom": "
|
|
53
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
54
|
-
"@dxos/
|
|
54
|
+
"react": "~19.2.3",
|
|
55
|
+
"react-dom": "~19.2.3",
|
|
56
|
+
"@dxos/react-ui": "0.8.4-main.ef1bc66f44",
|
|
57
|
+
"@dxos/ui-theme": "0.8.4-main.ef1bc66f44"
|
|
55
58
|
},
|
|
56
59
|
"publishConfig": {
|
|
57
60
|
"access": "public"
|
package/src/Tabs.stories.tsx
CHANGED
|
@@ -17,7 +17,7 @@ export const DefaultStory = () => {
|
|
|
17
17
|
return (
|
|
18
18
|
<Dialog.Root open>
|
|
19
19
|
<Dialog.Overlay blockAlign='start'>
|
|
20
|
-
<Dialog.Content
|
|
20
|
+
<Dialog.Content size='xl'>
|
|
21
21
|
<NaturalTabs.Root orientation='vertical' defaultValue={Object.keys(content)[3]} defaultActivePart='list'>
|
|
22
22
|
<NaturalTabs.Viewport>
|
|
23
23
|
<NaturalTabs.Tablist>
|
|
@@ -60,7 +60,7 @@ const meta = {
|
|
|
60
60
|
title: 'ui/react-ui-tabs/Tabs',
|
|
61
61
|
component: NaturalTabs.Root,
|
|
62
62
|
render: DefaultStory,
|
|
63
|
-
decorators: [withTheme],
|
|
63
|
+
decorators: [withTheme()],
|
|
64
64
|
} satisfies Meta<typeof DefaultStory>;
|
|
65
65
|
|
|
66
66
|
export default meta;
|
package/src/Tabs.tsx
CHANGED
|
@@ -10,14 +10,21 @@ import React, {
|
|
|
10
10
|
Activity,
|
|
11
11
|
type ComponentPropsWithoutRef,
|
|
12
12
|
type MouseEvent,
|
|
13
|
+
forwardRef,
|
|
13
14
|
useCallback,
|
|
14
15
|
useLayoutEffect,
|
|
15
|
-
useRef,
|
|
16
16
|
} from 'react';
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
Button,
|
|
20
|
+
type ButtonProps,
|
|
21
|
+
IconButton,
|
|
22
|
+
type IconButtonProps,
|
|
23
|
+
type ThemedClassName,
|
|
24
|
+
useForwardedRef,
|
|
25
|
+
} from '@dxos/react-ui';
|
|
19
26
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
20
|
-
import { ghostSelectedContainerMd, mx } from '@dxos/
|
|
27
|
+
import { ghostSelectedContainerMd, mx } from '@dxos/ui-theme';
|
|
21
28
|
|
|
22
29
|
type TabsActivePart = 'list' | 'panel';
|
|
23
30
|
|
|
@@ -43,83 +50,90 @@ type TabsRootProps = ThemedClassName<TabsPrimitive.TabsProps> &
|
|
|
43
50
|
defaultActivePart: TabsActivePart;
|
|
44
51
|
}>;
|
|
45
52
|
|
|
46
|
-
const TabsRoot = (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const _1 = useArrowNavigationGroup();
|
|
63
|
-
const _2 = useFocusableGroup();
|
|
64
|
-
const [activePart = 'list', setActivePart] = useControllableState({
|
|
65
|
-
prop: propsActivePart,
|
|
66
|
-
onChange: onActivePartChange,
|
|
67
|
-
defaultProp: defaultActivePart,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const [value, setValue] = useControllableState({
|
|
71
|
-
prop: propsValue,
|
|
72
|
-
onChange: onValueChange,
|
|
73
|
-
defaultProp: defaultValue,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const handleValueChange = useCallback(
|
|
77
|
-
(nextValue: string) => {
|
|
78
|
-
setActivePart('panel');
|
|
79
|
-
setValue(nextValue);
|
|
53
|
+
const TabsRoot = forwardRef<HTMLDivElement, TabsRootProps>(
|
|
54
|
+
(
|
|
55
|
+
{
|
|
56
|
+
children,
|
|
57
|
+
classNames,
|
|
58
|
+
activePart: propsActivePart,
|
|
59
|
+
onActivePartChange,
|
|
60
|
+
defaultActivePart,
|
|
61
|
+
value: propsValue,
|
|
62
|
+
onValueChange,
|
|
63
|
+
defaultValue,
|
|
64
|
+
orientation = 'vertical',
|
|
65
|
+
activationMode = 'manual',
|
|
66
|
+
verticalVariant = 'stateful',
|
|
67
|
+
attendableId,
|
|
68
|
+
...props
|
|
80
69
|
},
|
|
81
|
-
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
70
|
+
forwardedRef,
|
|
71
|
+
) => {
|
|
72
|
+
// const tabsRoot = useRef<HTMLDivElement | null>(null);
|
|
73
|
+
const tabsRoot = useForwardedRef(forwardedRef);
|
|
74
|
+
|
|
75
|
+
// TODO(thure): Without these, we get Groupper/Mover `API used before initialization`, but why?
|
|
76
|
+
const _1 = useArrowNavigationGroup();
|
|
77
|
+
const _2 = useFocusableGroup();
|
|
78
|
+
const [activePart = 'list', setActivePart] = useControllableState({
|
|
79
|
+
prop: propsActivePart,
|
|
80
|
+
onChange: onActivePartChange,
|
|
81
|
+
defaultProp: defaultActivePart,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const [value, setValue] = useControllableState({
|
|
85
|
+
prop: propsValue,
|
|
86
|
+
onChange: onValueChange,
|
|
87
|
+
defaultProp: defaultValue,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const handleValueChange = useCallback(
|
|
91
|
+
(nextValue: string) => {
|
|
92
|
+
setActivePart('panel');
|
|
93
|
+
setValue(nextValue);
|
|
94
|
+
},
|
|
95
|
+
[value],
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const { findFirstFocusable } = useFocusFinders();
|
|
99
|
+
|
|
100
|
+
useLayoutEffect(() => {
|
|
101
|
+
if (tabsRoot.current) {
|
|
102
|
+
findFirstFocusable(tabsRoot.current)?.focus();
|
|
103
|
+
}
|
|
104
|
+
}, [activePart]);
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<TabsContextProvider
|
|
105
108
|
orientation={orientation}
|
|
106
|
-
{
|
|
109
|
+
activePart={activePart}
|
|
110
|
+
setActivePart={setActivePart}
|
|
107
111
|
value={value}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
'overflow-hidden',
|
|
111
|
-
orientation === 'vertical' &&
|
|
112
|
-
verticalVariant === 'stateful' &&
|
|
113
|
-
'[&[data-active=list]_[role=tabpanel]]:invisible @md:[&[data-active=list]_[role=tabpanel]]:visible',
|
|
114
|
-
classNames,
|
|
115
|
-
)}
|
|
116
|
-
ref={tabsRoot}
|
|
112
|
+
attendableId={attendableId}
|
|
113
|
+
verticalVariant={verticalVariant}
|
|
117
114
|
>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
115
|
+
<TabsPrimitive.Root
|
|
116
|
+
activationMode={activationMode}
|
|
117
|
+
data-active={activePart}
|
|
118
|
+
orientation={orientation}
|
|
119
|
+
{...props}
|
|
120
|
+
value={value}
|
|
121
|
+
onValueChange={handleValueChange}
|
|
122
|
+
className={mx(
|
|
123
|
+
'overflow-hidden',
|
|
124
|
+
orientation === 'vertical' &&
|
|
125
|
+
verticalVariant === 'stateful' &&
|
|
126
|
+
'[&[data-active=list]_[role=tabpanel]]:invisible @md:[&[data-active=list]_[role=tabpanel]]:visible',
|
|
127
|
+
classNames,
|
|
128
|
+
)}
|
|
129
|
+
ref={tabsRoot}
|
|
130
|
+
>
|
|
131
|
+
{children}
|
|
132
|
+
</TabsPrimitive.Root>
|
|
133
|
+
</TabsContextProvider>
|
|
134
|
+
);
|
|
135
|
+
},
|
|
136
|
+
);
|
|
123
137
|
|
|
124
138
|
type TabsViewportProps = ThemedClassName<ComponentPropsWithoutRef<'div'>>;
|
|
125
139
|
|