@rovula/ui 0.0.57 → 0.0.59
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.js +3 -3
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Tree/type.d.ts +7 -6
- package/dist/components/Tabs/Tabs.js +43 -36
- package/dist/components/Tabs/Tabs.stories.js +38 -2
- package/dist/components/Tree/Tree.js +28 -4
- package/dist/components/Tree/Tree.stories.js +1 -1
- package/dist/components/Tree/TreeItem.js +7 -7
- package/dist/esm/bundle.js +2 -2
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Tree/type.d.ts +7 -6
- package/dist/index.d.ts +7 -6
- package/package.json +1 -1
- package/src/components/Tabs/Tabs.stories.tsx +60 -3
- package/src/components/Tabs/Tabs.tsx +43 -38
- package/src/components/Tree/Tree.stories.tsx +1 -0
- package/src/components/Tree/Tree.tsx +35 -4
- package/src/components/Tree/TreeItem.tsx +8 -7
- package/src/components/Tree/type.ts +10 -6
|
@@ -5,7 +5,8 @@ export type TreeData<T = {}> = {
|
|
|
5
5
|
icon?: ReactNode;
|
|
6
6
|
disabled?: boolean;
|
|
7
7
|
isLeaf?: boolean;
|
|
8
|
-
|
|
8
|
+
itemData?: any;
|
|
9
|
+
onClickItem?: (id: string, itemData?: any) => void;
|
|
9
10
|
children?: TreeData<T>[];
|
|
10
11
|
renderIcon?: (params: {
|
|
11
12
|
id: string;
|
|
@@ -31,9 +32,9 @@ export interface TreeItemProps extends TreeData {
|
|
|
31
32
|
checkIsChecked: (id: string) => boolean;
|
|
32
33
|
checkAutoDisabled: (id: string) => boolean;
|
|
33
34
|
checkIsLoading?: (id: string) => void;
|
|
34
|
-
onExpandChange?: (id: string, expanded: boolean) => void;
|
|
35
|
+
onExpandChange?: (id: string, expanded: boolean, itemData: any) => void;
|
|
35
36
|
onCheckedChange?: (id: string, checked: boolean) => void;
|
|
36
|
-
notifyClickItem?: (id: string) => void;
|
|
37
|
+
notifyClickItem?: (id: string, itemData: any) => void;
|
|
37
38
|
renderRightSection?: (params: {
|
|
38
39
|
id: string;
|
|
39
40
|
expanded: boolean;
|
|
@@ -82,9 +83,9 @@ export interface TreeProps extends Pick<TreeItemProps, "renderIcon" | "renderRig
|
|
|
82
83
|
defaultCheckedId?: string[];
|
|
83
84
|
checkedId?: string[];
|
|
84
85
|
loadingId?: string[];
|
|
85
|
-
onExpandChange?: (id: string, expanded: boolean) => void;
|
|
86
|
-
onCheckedChange?: (checkedState: Record<string, boolean
|
|
87
|
-
onClickItem?: (id: string) => void;
|
|
86
|
+
onExpandChange?: (id: string, expanded: boolean, itemData: any) => void;
|
|
87
|
+
onCheckedChange?: (checkedState: Record<string, boolean>, id?: string) => void;
|
|
88
|
+
onClickItem?: (id: string, itemData: any) => void;
|
|
88
89
|
onCheckedItem?: (id: string, checked: boolean) => void;
|
|
89
90
|
defaultExpandAll?: boolean;
|
|
90
91
|
defaultCheckAll?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -621,7 +621,8 @@ type TreeData<T = {}> = {
|
|
|
621
621
|
icon?: ReactNode;
|
|
622
622
|
disabled?: boolean;
|
|
623
623
|
isLeaf?: boolean;
|
|
624
|
-
|
|
624
|
+
itemData?: any;
|
|
625
|
+
onClickItem?: (id: string, itemData?: any) => void;
|
|
625
626
|
children?: TreeData<T>[];
|
|
626
627
|
renderIcon?: (params: {
|
|
627
628
|
id: string;
|
|
@@ -647,9 +648,9 @@ interface TreeItemProps extends TreeData {
|
|
|
647
648
|
checkIsChecked: (id: string) => boolean;
|
|
648
649
|
checkAutoDisabled: (id: string) => boolean;
|
|
649
650
|
checkIsLoading?: (id: string) => void;
|
|
650
|
-
onExpandChange?: (id: string, expanded: boolean) => void;
|
|
651
|
+
onExpandChange?: (id: string, expanded: boolean, itemData: any) => void;
|
|
651
652
|
onCheckedChange?: (id: string, checked: boolean) => void;
|
|
652
|
-
notifyClickItem?: (id: string) => void;
|
|
653
|
+
notifyClickItem?: (id: string, itemData: any) => void;
|
|
653
654
|
renderRightSection?: (params: {
|
|
654
655
|
id: string;
|
|
655
656
|
expanded: boolean;
|
|
@@ -698,9 +699,9 @@ interface TreeProps extends Pick<TreeItemProps, "renderIcon" | "renderRightSecti
|
|
|
698
699
|
defaultCheckedId?: string[];
|
|
699
700
|
checkedId?: string[];
|
|
700
701
|
loadingId?: string[];
|
|
701
|
-
onExpandChange?: (id: string, expanded: boolean) => void;
|
|
702
|
-
onCheckedChange?: (checkedState: Record<string, boolean
|
|
703
|
-
onClickItem?: (id: string) => void;
|
|
702
|
+
onExpandChange?: (id: string, expanded: boolean, itemData: any) => void;
|
|
703
|
+
onCheckedChange?: (checkedState: Record<string, boolean>, id?: string) => void;
|
|
704
|
+
onClickItem?: (id: string, itemData: any) => void;
|
|
704
705
|
onCheckedItem?: (id: string, checked: boolean) => void;
|
|
705
706
|
defaultExpandAll?: boolean;
|
|
706
707
|
defaultCheckAll?: boolean;
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
3
|
import Tabs from "./Tabs";
|
|
4
4
|
import { ChevronDownIcon, ArchiveBoxIcon } from "@heroicons/react/16/solid";
|
|
5
5
|
import ActionButton from "../ActionButton/ActionButton";
|
|
6
6
|
import Icon from "../Icon/Icon";
|
|
7
7
|
import { useArgs } from "@storybook/preview-api";
|
|
8
|
-
import { Button } from "@/index";
|
|
8
|
+
import { Button, Tree } from "@/index";
|
|
9
|
+
import { exampleData } from "../Tree/example-data";
|
|
9
10
|
|
|
10
11
|
const meta = {
|
|
11
12
|
title: "Components/Tabs",
|
|
@@ -211,11 +212,67 @@ export const Disabled = {
|
|
|
211
212
|
},
|
|
212
213
|
} satisfies StoryObj;
|
|
213
214
|
|
|
215
|
+
const TabContent = ({ tab }: any) => {
|
|
216
|
+
useEffect(() => {
|
|
217
|
+
console.log("tab ", tab, " Mount");
|
|
218
|
+
|
|
219
|
+
return () => {
|
|
220
|
+
console.log("tab ", tab, " DidMount");
|
|
221
|
+
};
|
|
222
|
+
}, [tab]);
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
<div>
|
|
226
|
+
<p>Tab {tab} content</p>
|
|
227
|
+
<input />
|
|
228
|
+
<Tree data={exampleData} />
|
|
229
|
+
</div>
|
|
230
|
+
);
|
|
231
|
+
};
|
|
232
|
+
|
|
214
233
|
export const Controller = {
|
|
215
234
|
args: {
|
|
216
235
|
initialTab: 1,
|
|
217
236
|
value: 0,
|
|
218
|
-
tabs
|
|
237
|
+
tabs: [
|
|
238
|
+
// {
|
|
239
|
+
// label: "Tab1",
|
|
240
|
+
// content: <TabContent tab={1} />,
|
|
241
|
+
// },
|
|
242
|
+
// {
|
|
243
|
+
// label: "Tab2",
|
|
244
|
+
// content: <TabContent tab={2} />,
|
|
245
|
+
// },
|
|
246
|
+
// {
|
|
247
|
+
// label: "Tab3",
|
|
248
|
+
// content: <TabContent tab={3} />,
|
|
249
|
+
// },
|
|
250
|
+
|
|
251
|
+
{
|
|
252
|
+
label: "Tab1",
|
|
253
|
+
content: (
|
|
254
|
+
<div key={`tab-content-key-1`}>
|
|
255
|
+
fdfsdfdsfsdf <input />
|
|
256
|
+
</div>
|
|
257
|
+
),
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
label: "Tab2",
|
|
261
|
+
content: (
|
|
262
|
+
<div key={`tab-content-key-2`}>
|
|
263
|
+
fdfsdfdsfsdf <input />
|
|
264
|
+
</div>
|
|
265
|
+
),
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
label: "Tab3",
|
|
269
|
+
content: (
|
|
270
|
+
<div key={`tab-content-key-3`}>
|
|
271
|
+
fdfsdfdsfsdf <input />
|
|
272
|
+
</div>
|
|
273
|
+
),
|
|
274
|
+
},
|
|
275
|
+
],
|
|
219
276
|
enableAddTabButton: true,
|
|
220
277
|
},
|
|
221
278
|
render: (args) => {
|
|
@@ -78,46 +78,53 @@ const Tabs: React.FC<TabsProps> = ({
|
|
|
78
78
|
}
|
|
79
79
|
}, [value]);
|
|
80
80
|
|
|
81
|
-
const updateSliderStyle = () => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
};
|
|
81
|
+
// const updateSliderStyle = () => {
|
|
82
|
+
// const activeTabElement = tabRefs.current[activeTab];
|
|
83
|
+
// if (activeTabElement) {
|
|
84
|
+
// setSliderStyle({
|
|
85
|
+
// width: `${activeTabElement.offsetWidth}px`,
|
|
86
|
+
// transform: `translateX(${activeTabElement.offsetLeft}px)`,
|
|
87
|
+
// });
|
|
88
|
+
// }
|
|
89
|
+
// };
|
|
90
90
|
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
|
|
93
|
-
isInitialMount.current = false;
|
|
91
|
+
// useEffect(() => {
|
|
92
|
+
// let timer: NodeJS.Timeout;
|
|
94
93
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (activeTabElement) {
|
|
98
|
-
setSliderStyle({
|
|
99
|
-
width: "0px",
|
|
100
|
-
transform: `translateX(${
|
|
101
|
-
activeTabElement.offsetLeft + activeTabElement.offsetWidth / 2
|
|
102
|
-
}px)`,
|
|
103
|
-
});
|
|
94
|
+
// if (isInitialMount.current) {
|
|
95
|
+
// isInitialMount.current = false;
|
|
104
96
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
97
|
+
// // Set initial position without animation
|
|
98
|
+
// const activeTabElement = tabRefs.current[activeTab];
|
|
99
|
+
// if (activeTabElement) {
|
|
100
|
+
// setSliderStyle({
|
|
101
|
+
// width: "0px",
|
|
102
|
+
// transform: `translateX(${
|
|
103
|
+
// activeTabElement.offsetLeft + activeTabElement.offsetWidth / 2
|
|
104
|
+
// }px)`,
|
|
105
|
+
// });
|
|
113
106
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
107
|
+
// // Trigger reflow
|
|
108
|
+
// timer = setTimeout(() => {
|
|
109
|
+
// updateSliderStyle();
|
|
110
|
+
// }, 50);
|
|
111
|
+
// }
|
|
112
|
+
// } else {
|
|
113
|
+
// updateSliderStyle();
|
|
114
|
+
// }
|
|
117
115
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
116
|
+
// const handleResize = () => {
|
|
117
|
+
// updateSliderStyle();
|
|
118
|
+
// };
|
|
119
|
+
|
|
120
|
+
// window.addEventListener("resize", handleResize);
|
|
121
|
+
// return () => {
|
|
122
|
+
// window.removeEventListener("resize", handleResize);
|
|
123
|
+
// if (timer) {
|
|
124
|
+
// clearTimeout(timer);
|
|
125
|
+
// }
|
|
126
|
+
// };
|
|
127
|
+
// }, [activeTab, tabs, tabMode, keepIconSpace]);
|
|
121
128
|
|
|
122
129
|
return (
|
|
123
130
|
<div className={cn("w-full", className)}>
|
|
@@ -233,9 +240,7 @@ const Tabs: React.FC<TabsProps> = ({
|
|
|
233
240
|
id={`tab-content-${activeTab}`}
|
|
234
241
|
aria-labelledby={`tab-${activeTab}`}
|
|
235
242
|
>
|
|
236
|
-
|
|
237
|
-
{tabs[activeTab]?.content}
|
|
238
|
-
</div>
|
|
243
|
+
{tabs[activeTab]?.content}
|
|
239
244
|
</div>
|
|
240
245
|
</div>
|
|
241
246
|
);
|
|
@@ -93,9 +93,40 @@ const Tree: FC<TreeProps> = ({
|
|
|
93
93
|
}
|
|
94
94
|
}, [checkedId]);
|
|
95
95
|
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (!hierarchicalCheck) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const state: Record<string, boolean> = {};
|
|
102
|
+
const updateChildren = (parentId: string, isChecked: boolean) => {
|
|
103
|
+
traverseTree(data, (node) => {
|
|
104
|
+
if (node.id === parentId && node.children) {
|
|
105
|
+
node.children.forEach((child) => {
|
|
106
|
+
state[child.id] = isChecked;
|
|
107
|
+
updateChildren(child.id, isChecked);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
setCheckedState((prev) => {
|
|
114
|
+
Object.keys(prev)
|
|
115
|
+
.filter((key) => prev[key])
|
|
116
|
+
.map((id) => {
|
|
117
|
+
updateChildren(id, true);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
...prev,
|
|
122
|
+
...state,
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
}, [data, hierarchicalCheck]);
|
|
126
|
+
|
|
96
127
|
const handleExpandChange = useCallback(
|
|
97
|
-
(id: string, expanded: boolean) => {
|
|
98
|
-
onExpandChange?.(id, expanded);
|
|
128
|
+
(id: string, expanded: boolean, itemData: any) => {
|
|
129
|
+
onExpandChange?.(id, expanded, itemData);
|
|
99
130
|
setExpandedState((prev) => ({ ...prev, [id]: expanded }));
|
|
100
131
|
},
|
|
101
132
|
[onExpandChange]
|
|
@@ -108,7 +139,7 @@ const Tree: FC<TreeProps> = ({
|
|
|
108
139
|
|
|
109
140
|
onCheckedItem?.(id, checked);
|
|
110
141
|
setCheckedState(newState);
|
|
111
|
-
onCheckedChange?.(newState);
|
|
142
|
+
onCheckedChange?.(newState, id);
|
|
112
143
|
|
|
113
144
|
return;
|
|
114
145
|
}
|
|
@@ -163,7 +194,7 @@ const Tree: FC<TreeProps> = ({
|
|
|
163
194
|
setCheckedState(newState);
|
|
164
195
|
|
|
165
196
|
if (onCheckedChange) {
|
|
166
|
-
onCheckedChange?.(newState);
|
|
197
|
+
onCheckedChange?.(newState, id);
|
|
167
198
|
}
|
|
168
199
|
},
|
|
169
200
|
[
|
|
@@ -36,6 +36,7 @@ const TreeItem: FC<TreeItemProps> = ({
|
|
|
36
36
|
currentLevel = 1,
|
|
37
37
|
maxLevel = 10,
|
|
38
38
|
notifyClickItem,
|
|
39
|
+
itemData,
|
|
39
40
|
}) => {
|
|
40
41
|
const isLoading = useMemo(() => checkIsLoading?.(id), [checkIsLoading, id]);
|
|
41
42
|
const isChecked = useMemo(() => checkIsChecked(id), [checkIsChecked, id]);
|
|
@@ -93,8 +94,8 @@ const TreeItem: FC<TreeItemProps> = ({
|
|
|
93
94
|
);
|
|
94
95
|
|
|
95
96
|
const handleExpandToggle = useCallback(() => {
|
|
96
|
-
onExpandChange?.(id, !isExpanded);
|
|
97
|
-
}, [id, isExpanded, onExpandChange]);
|
|
97
|
+
onExpandChange?.(id, !isExpanded, itemData);
|
|
98
|
+
}, [id, isExpanded, onExpandChange, itemData]);
|
|
98
99
|
|
|
99
100
|
useEffect(() => {
|
|
100
101
|
if (isExpanded && !isLoading && !hasChildren) {
|
|
@@ -103,9 +104,9 @@ const TreeItem: FC<TreeItemProps> = ({
|
|
|
103
104
|
}, [isLoading, handleExpandToggle]);
|
|
104
105
|
|
|
105
106
|
const handleOnClickItem = useCallback(() => {
|
|
106
|
-
onClickItem?.(id);
|
|
107
|
-
notifyClickItem?.(id);
|
|
108
|
-
}, [onClickItem, notifyClickItem,
|
|
107
|
+
onClickItem?.(id, itemData);
|
|
108
|
+
notifyClickItem?.(id, itemData);
|
|
109
|
+
}, [id, isExpanded, onClickItem, notifyClickItem, itemData]);
|
|
109
110
|
|
|
110
111
|
const defaultIcon = (
|
|
111
112
|
<Icon
|
|
@@ -254,7 +255,7 @@ const TreeItem: FC<TreeItemProps> = ({
|
|
|
254
255
|
{isExpanded && hasChildren && currentLevel < (maxLevel || Infinity) && (
|
|
255
256
|
<div
|
|
256
257
|
className={cn(
|
|
257
|
-
"flex flex-row overflow-hidden
|
|
258
|
+
"flex flex-row overflow-hidden",
|
|
258
259
|
classes?.expandedChildrenWrapper
|
|
259
260
|
)}
|
|
260
261
|
>
|
|
@@ -269,7 +270,7 @@ const TreeItem: FC<TreeItemProps> = ({
|
|
|
269
270
|
)}
|
|
270
271
|
<div
|
|
271
272
|
className={cn(
|
|
272
|
-
"flex flex-col overflow-hidden
|
|
273
|
+
"flex flex-col overflow-hidden",
|
|
273
274
|
classes?.expandedChildrenWrapperInner
|
|
274
275
|
)}
|
|
275
276
|
style={styles.childPadding}
|
|
@@ -6,7 +6,8 @@ export type TreeData<T = {}> = {
|
|
|
6
6
|
icon?: ReactNode;
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
isLeaf?: boolean;
|
|
9
|
-
|
|
9
|
+
itemData?: any;
|
|
10
|
+
onClickItem?: (id: string, itemData?: any) => void;
|
|
10
11
|
children?: TreeData<T>[]; // Recursively include additional data
|
|
11
12
|
renderIcon?: (params: {
|
|
12
13
|
id: string;
|
|
@@ -33,9 +34,9 @@ export interface TreeItemProps extends TreeData {
|
|
|
33
34
|
checkIsChecked: (id: string) => boolean;
|
|
34
35
|
checkAutoDisabled: (id: string) => boolean;
|
|
35
36
|
checkIsLoading?: (id: string) => void;
|
|
36
|
-
onExpandChange?: (id: string, expanded: boolean) => void;
|
|
37
|
+
onExpandChange?: (id: string, expanded: boolean, itemData: any) => void;
|
|
37
38
|
onCheckedChange?: (id: string, checked: boolean) => void;
|
|
38
|
-
notifyClickItem?: (id: string) => void;
|
|
39
|
+
notifyClickItem?: (id: string, itemData: any) => void;
|
|
39
40
|
renderRightSection?: (params: {
|
|
40
41
|
id: string;
|
|
41
42
|
expanded: boolean;
|
|
@@ -100,9 +101,12 @@ export interface TreeProps
|
|
|
100
101
|
defaultCheckedId?: string[];
|
|
101
102
|
checkedId?: string[];
|
|
102
103
|
loadingId?: string[];
|
|
103
|
-
onExpandChange?: (id: string, expanded: boolean) => void;
|
|
104
|
-
onCheckedChange?: (
|
|
105
|
-
|
|
104
|
+
onExpandChange?: (id: string, expanded: boolean, itemData: any) => void;
|
|
105
|
+
onCheckedChange?: (
|
|
106
|
+
checkedState: Record<string, boolean>,
|
|
107
|
+
id?: string
|
|
108
|
+
) => void;
|
|
109
|
+
onClickItem?: (id: string, itemData: any) => void;
|
|
106
110
|
onCheckedItem?: (id: string, checked: boolean) => void;
|
|
107
111
|
defaultExpandAll?: boolean;
|
|
108
112
|
defaultCheckAll?: boolean;
|