@rovula/ui 0.0.52 → 0.0.53
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/cjs/bundle.css +50 -10
- package/dist/cjs/bundle.js +2 -2
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Tabs/Tabs.d.ts +14 -1
- package/dist/cjs/types/components/Tabs/Tabs.stories.d.ts +81 -2
- package/dist/cjs/types/components/Tree/Tree.stories.d.ts +3 -0
- package/dist/cjs/types/components/Tree/example-data.d.ts +5 -0
- package/dist/cjs/types/components/Tree/type.d.ts +13 -4
- package/dist/components/Tabs/Tabs.js +35 -18
- package/dist/components/Tabs/Tabs.stories.js +70 -3
- package/dist/components/Tree/Tree.js +6 -4
- package/dist/components/Tree/Tree.stories.js +34 -2090
- package/dist/components/Tree/TreeItem.js +16 -8
- package/dist/components/Tree/example-data.js +2125 -0
- package/dist/esm/bundle.css +50 -10
- package/dist/esm/bundle.js +2 -2
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Tabs/Tabs.d.ts +14 -1
- package/dist/esm/types/components/Tabs/Tabs.stories.d.ts +81 -2
- package/dist/esm/types/components/Tree/Tree.stories.d.ts +3 -0
- package/dist/esm/types/components/Tree/example-data.d.ts +5 -0
- package/dist/esm/types/components/Tree/type.d.ts +13 -4
- package/dist/index.d.ts +26 -5
- package/dist/src/theme/global.css +36 -13
- package/package.json +6 -1
- package/src/components/Tabs/Tabs.css +21 -0
- package/src/components/Tabs/Tabs.stories.tsx +140 -4
- package/src/components/Tabs/Tabs.tsx +134 -50
- package/src/components/Tree/Tree.stories.tsx +58 -2125
- package/src/components/Tree/Tree.tsx +15 -2
- package/src/components/Tree/TreeItem.tsx +47 -17
- package/src/components/Tree/example-data.ts +2162 -0
- package/src/components/Tree/type.ts +17 -4
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import React, { useState, useRef, useEffect } from "react";
|
|
2
2
|
import { cn } from "@/utils/cn";
|
|
3
|
+
import "./Tabs.css";
|
|
4
|
+
import ActionButton from "../ActionButton/ActionButton";
|
|
5
|
+
import Icon from "../Icon/Icon";
|
|
6
|
+
import { Loading } from "@/index";
|
|
3
7
|
|
|
4
8
|
type Tab = {
|
|
5
9
|
label: string;
|
|
6
10
|
startTabContent?: React.ReactElement;
|
|
7
11
|
endTabContent?: React.ReactElement;
|
|
8
12
|
content: React.ReactNode;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
isLoading?: boolean;
|
|
9
15
|
};
|
|
10
16
|
|
|
11
17
|
type TabsProps = {
|
|
@@ -14,12 +20,22 @@ type TabsProps = {
|
|
|
14
20
|
tabBarSize?: number;
|
|
15
21
|
tabMode?: "start" | "justify";
|
|
16
22
|
enableBorderLine?: boolean;
|
|
23
|
+
enableAddTabButton?: boolean;
|
|
24
|
+
keepIconSpace?: boolean;
|
|
17
25
|
className?: string;
|
|
18
26
|
tabBarClassName?: string;
|
|
27
|
+
tabBarContainerClassName?: string;
|
|
28
|
+
tabBarWrapperClassName?: string;
|
|
19
29
|
tabButtonClassName?: string;
|
|
20
30
|
tabButtonActiveClassName?: string;
|
|
21
31
|
tabContentClassName?: string;
|
|
22
|
-
|
|
32
|
+
addTabButtonWrapperClassName?: string;
|
|
33
|
+
borderSliderClassName?: string;
|
|
34
|
+
leftAction?: React.ReactNode;
|
|
35
|
+
rightAction?: React.ReactNode;
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
onAddTab?: () => void;
|
|
38
|
+
onTabChange?: (tabIndex: number) => void;
|
|
23
39
|
};
|
|
24
40
|
|
|
25
41
|
const Tabs: React.FC<TabsProps> = ({
|
|
@@ -27,13 +43,23 @@ const Tabs: React.FC<TabsProps> = ({
|
|
|
27
43
|
initialTab = 0,
|
|
28
44
|
tabBarSize = 38,
|
|
29
45
|
enableBorderLine = true,
|
|
46
|
+
enableAddTabButton = false,
|
|
47
|
+
keepIconSpace = true,
|
|
48
|
+
disabled = false,
|
|
30
49
|
tabMode = "start",
|
|
31
50
|
className,
|
|
32
51
|
tabBarClassName,
|
|
52
|
+
tabBarContainerClassName,
|
|
53
|
+
tabBarWrapperClassName,
|
|
33
54
|
tabButtonClassName,
|
|
34
55
|
tabButtonActiveClassName,
|
|
35
56
|
tabContentClassName,
|
|
36
|
-
|
|
57
|
+
addTabButtonWrapperClassName,
|
|
58
|
+
borderSliderClassName,
|
|
59
|
+
leftAction,
|
|
60
|
+
rightAction,
|
|
61
|
+
onAddTab,
|
|
62
|
+
onTabChange,
|
|
37
63
|
}) => {
|
|
38
64
|
const [activeTab, setActiveTab] = useState(initialTab);
|
|
39
65
|
const [sliderStyle, setSliderStyle] = useState({
|
|
@@ -76,66 +102,124 @@ const Tabs: React.FC<TabsProps> = ({
|
|
|
76
102
|
updateSliderStyle();
|
|
77
103
|
}
|
|
78
104
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
105
|
+
const handleResize = () => {
|
|
106
|
+
updateSliderStyle();
|
|
107
|
+
};
|
|
82
108
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}, [activeTab, tabs, tabMode]);
|
|
109
|
+
window.addEventListener("resize", handleResize);
|
|
110
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
111
|
+
}, [activeTab, tabs, tabMode, keepIconSpace]);
|
|
86
112
|
|
|
87
113
|
return (
|
|
88
114
|
<div className={cn("w-full", className)}>
|
|
89
115
|
<div
|
|
90
|
-
className={cn(
|
|
91
|
-
`
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
tabBarClassName
|
|
97
|
-
)}
|
|
98
|
-
style={{
|
|
99
|
-
justifyContent: tabMode === "justify" ? "stretch" : tabMode,
|
|
100
|
-
}}
|
|
101
|
-
role="tablist"
|
|
116
|
+
className={cn(" relative flex flex-row w-full", {
|
|
117
|
+
[`border-b-[1px] border-base-stroke`]: enableBorderLine,
|
|
118
|
+
"border-state-disable-outline": disabled,
|
|
119
|
+
"flex-1": tabMode === "justify",
|
|
120
|
+
tabBarContainerClassName,
|
|
121
|
+
})}
|
|
102
122
|
>
|
|
103
|
-
{
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
123
|
+
{leftAction}
|
|
124
|
+
<div
|
|
125
|
+
className={cn(
|
|
126
|
+
"relative flex flex-row overflow-x-auto",
|
|
127
|
+
{
|
|
128
|
+
"flex-1": tabMode === "justify",
|
|
129
|
+
},
|
|
130
|
+
tabBarWrapperClassName
|
|
131
|
+
)}
|
|
132
|
+
>
|
|
133
|
+
<div
|
|
111
134
|
className={cn(
|
|
112
|
-
"
|
|
135
|
+
"tabs-scrollbar overflow-x-auto w-full",
|
|
136
|
+
`relative flex gap-3 h-[${tabBarSize}px] box-border`,
|
|
113
137
|
{
|
|
114
|
-
"
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
[tabButtonClassName ?? ""]: true,
|
|
118
|
-
[tabButtonActiveClassName ?? ""]: index === activeTab,
|
|
119
|
-
"flex-1": tabMode === "justify",
|
|
120
|
-
}
|
|
138
|
+
"gap-0": tabMode === "justify",
|
|
139
|
+
},
|
|
140
|
+
tabBarClassName
|
|
121
141
|
)}
|
|
122
|
-
|
|
142
|
+
style={{
|
|
143
|
+
justifyContent: tabMode === "justify" ? "stretch" : tabMode,
|
|
144
|
+
}}
|
|
145
|
+
role="tablist"
|
|
123
146
|
>
|
|
124
|
-
{tab
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
147
|
+
{tabs.map((tab, index) => (
|
|
148
|
+
<button
|
|
149
|
+
key={index}
|
|
150
|
+
ref={(el) => (tabRefs.current[index] = el)}
|
|
151
|
+
role="tab"
|
|
152
|
+
aria-selected={index === activeTab}
|
|
153
|
+
aria-controls={`tab-content-${index}`}
|
|
154
|
+
disabled={disabled || tab.disabled}
|
|
155
|
+
id={`tab-${index}`}
|
|
156
|
+
className={cn(
|
|
157
|
+
"flex justify-center flex-row items-center py-3 cursor-pointer transition-colors duration-300 box-border gap-1 flex-shrink-0 typography-subtitile6",
|
|
158
|
+
{
|
|
159
|
+
"text-foreground": index === activeTab,
|
|
160
|
+
"text-text-grey-medium hover:text-text-grey-dark active:text-text-dark":
|
|
161
|
+
index !== activeTab,
|
|
162
|
+
"text-state-disable-solid pointer-events-none":
|
|
163
|
+
disabled || tab.disabled,
|
|
164
|
+
"text-state-disable-outline":
|
|
165
|
+
(index === activeTab && disabled) || tab.disabled,
|
|
166
|
+
[tabButtonClassName ?? ""]: true,
|
|
167
|
+
[tabButtonActiveClassName ?? ""]: index === activeTab,
|
|
168
|
+
"flex-1": tabMode === "justify",
|
|
169
|
+
}
|
|
170
|
+
)}
|
|
171
|
+
onClick={() => {
|
|
172
|
+
setActiveTab(index);
|
|
173
|
+
onTabChange?.(index);
|
|
174
|
+
}}
|
|
175
|
+
>
|
|
176
|
+
{(keepIconSpace || tab.startTabContent) && (
|
|
177
|
+
<div className="h-full w-3 flex items-center justify-center">
|
|
178
|
+
{tab.isLoading ? <Loading /> : tab.startTabContent}
|
|
179
|
+
</div>
|
|
180
|
+
)}
|
|
181
|
+
{tab.label}
|
|
182
|
+
{(keepIconSpace || tab.endTabContent) && (
|
|
183
|
+
<div className="h-full w-3 flex items-center justify-center">
|
|
184
|
+
{tab.endTabContent}
|
|
185
|
+
</div>
|
|
186
|
+
)}
|
|
187
|
+
</button>
|
|
188
|
+
))}
|
|
189
|
+
<div
|
|
190
|
+
className={cn(
|
|
191
|
+
`absolute left-0 bottom-0 h-[2px] rounded-full bg-foreground transition-all duration-300 ease-in-out`,
|
|
192
|
+
{
|
|
193
|
+
"bg-state-disable-solid": disabled,
|
|
194
|
+
},
|
|
195
|
+
borderSliderClassName
|
|
196
|
+
)}
|
|
197
|
+
style={sliderStyle}
|
|
198
|
+
/>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
{enableAddTabButton && (
|
|
202
|
+
<div
|
|
203
|
+
className={cn(
|
|
204
|
+
"sticky right-0 flex content-center items-center mx-4",
|
|
205
|
+
addTabButtonWrapperClassName
|
|
206
|
+
)}
|
|
207
|
+
>
|
|
208
|
+
<ActionButton
|
|
209
|
+
variant="outline"
|
|
210
|
+
size="sm"
|
|
211
|
+
onClick={() => onAddTab?.()}
|
|
212
|
+
disabled={disabled}
|
|
213
|
+
>
|
|
214
|
+
<Icon name="plus" />
|
|
215
|
+
</ActionButton>
|
|
216
|
+
</div>
|
|
217
|
+
)}
|
|
218
|
+
{rightAction}
|
|
136
219
|
</div>
|
|
220
|
+
|
|
137
221
|
<div
|
|
138
|
-
className={cn("mt-4", tabContentClassName)}
|
|
222
|
+
className={cn("mt-4 text-foreground", tabContentClassName)}
|
|
139
223
|
role="tabpanel"
|
|
140
224
|
id={`tab-content-${activeTab}`}
|
|
141
225
|
aria-labelledby={`tab-${activeTab}`}
|