@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.
Files changed (33) hide show
  1. package/dist/cjs/bundle.css +50 -10
  2. package/dist/cjs/bundle.js +2 -2
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/Tabs/Tabs.d.ts +14 -1
  5. package/dist/cjs/types/components/Tabs/Tabs.stories.d.ts +81 -2
  6. package/dist/cjs/types/components/Tree/Tree.stories.d.ts +3 -0
  7. package/dist/cjs/types/components/Tree/example-data.d.ts +5 -0
  8. package/dist/cjs/types/components/Tree/type.d.ts +13 -4
  9. package/dist/components/Tabs/Tabs.js +35 -18
  10. package/dist/components/Tabs/Tabs.stories.js +70 -3
  11. package/dist/components/Tree/Tree.js +6 -4
  12. package/dist/components/Tree/Tree.stories.js +34 -2090
  13. package/dist/components/Tree/TreeItem.js +16 -8
  14. package/dist/components/Tree/example-data.js +2125 -0
  15. package/dist/esm/bundle.css +50 -10
  16. package/dist/esm/bundle.js +2 -2
  17. package/dist/esm/bundle.js.map +1 -1
  18. package/dist/esm/types/components/Tabs/Tabs.d.ts +14 -1
  19. package/dist/esm/types/components/Tabs/Tabs.stories.d.ts +81 -2
  20. package/dist/esm/types/components/Tree/Tree.stories.d.ts +3 -0
  21. package/dist/esm/types/components/Tree/example-data.d.ts +5 -0
  22. package/dist/esm/types/components/Tree/type.d.ts +13 -4
  23. package/dist/index.d.ts +26 -5
  24. package/dist/src/theme/global.css +36 -13
  25. package/package.json +6 -1
  26. package/src/components/Tabs/Tabs.css +21 -0
  27. package/src/components/Tabs/Tabs.stories.tsx +140 -4
  28. package/src/components/Tabs/Tabs.tsx +134 -50
  29. package/src/components/Tree/Tree.stories.tsx +58 -2125
  30. package/src/components/Tree/Tree.tsx +15 -2
  31. package/src/components/Tree/TreeItem.tsx +47 -17
  32. package/src/components/Tree/example-data.ts +2162 -0
  33. 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
- borderSliderClassname?: string;
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
- borderSliderClassname,
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
- // const handleResize = () => {
80
- // updateSliderStyle();
81
- // };
105
+ const handleResize = () => {
106
+ updateSliderStyle();
107
+ };
82
108
 
83
- // window.addEventListener("resize", handleResize);
84
- // return () => window.removeEventListener("resize", handleResize);
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
- `relative flex gap-6 h-[${tabBarSize}px] box-border`,
92
- {
93
- [`border-b-[1px] border-base-stroke`]: enableBorderLine,
94
- "gap-0": tabMode === "justify",
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
- {tabs.map((tab, index) => (
104
- <button
105
- key={index}
106
- ref={(el) => (tabRefs.current[index] = el)}
107
- role="tab"
108
- aria-selected={index === activeTab}
109
- aria-controls={`tab-content-${index}`}
110
- id={`tab-${index}`}
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
- "flex justify-center flex-row items-center py-4 px-1 cursor-pointer transition-colors duration-300 box-border gap-3",
135
+ "tabs-scrollbar overflow-x-auto w-full",
136
+ `relative flex gap-3 h-[${tabBarSize}px] box-border`,
113
137
  {
114
- "typography-small3 text-text-dark": index === activeTab,
115
- "typography-small1 text-text-grey-light hover:text-text-grey-dark active:text-text-dark":
116
- index !== activeTab,
117
- [tabButtonClassName ?? ""]: true,
118
- [tabButtonActiveClassName ?? ""]: index === activeTab,
119
- "flex-1": tabMode === "justify",
120
- }
138
+ "gap-0": tabMode === "justify",
139
+ },
140
+ tabBarClassName
121
141
  )}
122
- onClick={() => setActiveTab(index)}
142
+ style={{
143
+ justifyContent: tabMode === "justify" ? "stretch" : tabMode,
144
+ }}
145
+ role="tablist"
123
146
  >
124
- {tab.startTabContent}
125
- {tab.label}
126
- {tab.endTabContent}
127
- </button>
128
- ))}
129
- <div
130
- className={cn(
131
- `absolute -bottom-[1px] h-[1px] bg-primary transition-all duration-300 ease-in-out`,
132
- borderSliderClassname
133
- )}
134
- style={sliderStyle}
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}`}