@rovula/ui 0.0.61 → 0.0.63
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/Dropdown/Dropdown.d.ts +5 -1
- package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +4 -0
- package/dist/cjs/types/components/Search/Search.stories.d.ts +2 -0
- package/dist/cjs/types/components/Tabs/Tabs.d.ts +1 -0
- package/dist/cjs/types/components/Tabs/Tabs.stories.d.ts +2 -0
- package/dist/cjs/types/components/Tree/Tree.stories.d.ts +1 -0
- package/dist/cjs/types/components/Tree/type.d.ts +1 -0
- package/dist/cjs/types/hooks/index.d.ts +1 -0
- package/dist/cjs/types/hooks/usePrevious.d.ts +2 -0
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/components/Dropdown/Dropdown.js +42 -3
- package/dist/components/Input/Input.js +2 -1
- package/dist/components/Tabs/Tabs.js +48 -44
- package/dist/components/Tree/Tree.js +26 -1
- package/dist/components/Tree/Tree.stories.js +12 -0
- package/dist/esm/bundle.js +3 -3
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Dropdown/Dropdown.d.ts +5 -1
- package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +4 -0
- package/dist/esm/types/components/Search/Search.stories.d.ts +2 -0
- package/dist/esm/types/components/Tabs/Tabs.d.ts +1 -0
- package/dist/esm/types/components/Tabs/Tabs.stories.d.ts +2 -0
- package/dist/esm/types/components/Tree/Tree.stories.d.ts +1 -0
- package/dist/esm/types/components/Tree/type.d.ts +1 -0
- package/dist/esm/types/hooks/index.d.ts +1 -0
- package/dist/esm/types/hooks/usePrevious.d.ts +2 -0
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/usePrevious.js +9 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.js +2 -0
- package/package.json +1 -1
- package/src/components/Dropdown/Dropdown.tsx +54 -3
- package/src/components/Input/Input.tsx +2 -0
- package/src/components/Tabs/Tabs.tsx +57 -42
- package/src/components/Tree/Tree.stories.tsx +35 -0
- package/src/components/Tree/Tree.tsx +33 -0
- package/src/components/Tree/type.ts +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/usePrevious.ts +13 -0
- package/src/index.ts +3 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { ReactNode } from "react";
|
|
1
|
+
import React, { CSSProperties, ReactNode } from "react";
|
|
2
2
|
import { InputProps } from "../TextInput/TextInput";
|
|
3
3
|
type RenderLabelCallbackArg = {
|
|
4
4
|
value: string;
|
|
@@ -36,6 +36,8 @@ export type DropdownProps = {
|
|
|
36
36
|
optionsFiltered: Options[];
|
|
37
37
|
selectedOption: Options | null | undefined;
|
|
38
38
|
onClick: (option: Options) => void;
|
|
39
|
+
style?: CSSProperties;
|
|
40
|
+
dropdownRef?: React.RefObject<HTMLUListElement>;
|
|
39
41
|
}) => ReactNode;
|
|
40
42
|
} & Omit<InputProps, "value" | "onSelect">;
|
|
41
43
|
declare const Dropdown: React.ForwardRefExoticComponent<{
|
|
@@ -63,6 +65,8 @@ declare const Dropdown: React.ForwardRefExoticComponent<{
|
|
|
63
65
|
optionsFiltered: Options[];
|
|
64
66
|
selectedOption: Options | null | undefined;
|
|
65
67
|
onClick: (option: Options) => void;
|
|
68
|
+
style?: CSSProperties;
|
|
69
|
+
dropdownRef?: React.RefObject<HTMLUListElement>;
|
|
66
70
|
}) => ReactNode) | undefined;
|
|
67
71
|
} & Omit<InputProps, "onSelect" | "value"> & React.RefAttributes<HTMLInputElement>>;
|
|
68
72
|
export default Dropdown;
|
|
@@ -27,6 +27,8 @@ declare const meta: {
|
|
|
27
27
|
optionsFiltered: Options[];
|
|
28
28
|
selectedOption: Options | null | undefined;
|
|
29
29
|
onClick: (option: Options) => void;
|
|
30
|
+
style?: React.CSSProperties | undefined;
|
|
31
|
+
dropdownRef?: React.RefObject<HTMLUListElement> | undefined;
|
|
30
32
|
}) => React.ReactNode) | undefined;
|
|
31
33
|
} & Omit<import("../..").InputProps, "onSelect" | "value"> & React.RefAttributes<HTMLInputElement>>;
|
|
32
34
|
tags: string[];
|
|
@@ -58,6 +60,8 @@ declare const meta: {
|
|
|
58
60
|
optionsFiltered: Options[];
|
|
59
61
|
selectedOption: Options | null | undefined;
|
|
60
62
|
onClick: (option: Options) => void;
|
|
63
|
+
style?: React.CSSProperties | undefined;
|
|
64
|
+
dropdownRef?: React.RefObject<HTMLUListElement> | undefined;
|
|
61
65
|
}) => React.ReactNode) | undefined;
|
|
62
66
|
suppressHydrationWarning?: boolean | undefined;
|
|
63
67
|
color?: string | undefined;
|
|
@@ -322,6 +322,8 @@ declare const meta: {
|
|
|
322
322
|
optionsFiltered: Options[];
|
|
323
323
|
selectedOption: Options | null | undefined;
|
|
324
324
|
onClick: (option: Options) => void;
|
|
325
|
+
style?: React.CSSProperties | undefined;
|
|
326
|
+
dropdownRef?: React.RefObject<HTMLUListElement> | undefined;
|
|
325
327
|
}) => React.ReactNode) | undefined;
|
|
326
328
|
optionContainerClassName?: string | undefined;
|
|
327
329
|
optionItemClassName?: string | undefined;
|
|
@@ -30,6 +30,7 @@ declare const meta: {
|
|
|
30
30
|
leftAction?: React.ReactNode;
|
|
31
31
|
rightAction?: React.ReactNode;
|
|
32
32
|
disabled?: boolean | undefined;
|
|
33
|
+
keepMounted?: boolean | undefined;
|
|
33
34
|
onAddTab?: (() => void) | undefined;
|
|
34
35
|
onTabChange?: ((tabIndex: number) => void) | undefined;
|
|
35
36
|
}>;
|
|
@@ -66,6 +67,7 @@ declare const meta: {
|
|
|
66
67
|
leftAction?: React.ReactNode;
|
|
67
68
|
rightAction?: React.ReactNode;
|
|
68
69
|
disabled?: boolean | undefined;
|
|
70
|
+
keepMounted?: boolean | undefined;
|
|
69
71
|
onAddTab?: (() => void) | undefined;
|
|
70
72
|
onTabChange?: ((tabIndex: number) => void) | undefined;
|
|
71
73
|
}>) => import("react/jsx-runtime").JSX.Element)[];
|
|
@@ -15,3 +15,4 @@ export declare const MaximumLevel: StoryObj<typeof Tree>;
|
|
|
15
15
|
export declare const Leaf: StoryObj<typeof Tree>;
|
|
16
16
|
export declare const HideCheckboxMode: StoryObj<typeof Tree>;
|
|
17
17
|
export declare const RadioMode: StoryObj<typeof Tree>;
|
|
18
|
+
export declare const CheckAll: StoryObj<typeof Tree>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as usePrevious } from "./usePrevious";
|
|
@@ -40,4 +40,5 @@ export type { NavbarProps } from "./components/Navbar/Navbar";
|
|
|
40
40
|
export type { AvatarProps } from "./components/Avatar/Avatar";
|
|
41
41
|
export type { AvatarGroupProps } from "./components/Avatar/AvatarGroup";
|
|
42
42
|
export { resloveTimestamp, getStartDateOfDay, getEndDateOfDay, getStartEndTimestampOfDay, getTimestampUTC, } from "./utils/datetime";
|
|
43
|
+
export * from "./hooks";
|
|
43
44
|
export { cn } from "./utils/cn";
|
|
@@ -10,7 +10,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
-
import { Fragment, forwardRef, useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
13
|
+
import { Fragment, forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from "react";
|
|
14
|
+
import * as Portal from "@radix-ui/react-portal";
|
|
14
15
|
import TextInput from "../TextInput/TextInput";
|
|
15
16
|
import { customInputVariant, dropdownIconVariant, iconWrapperVariant, } from "./Dropdown.styles";
|
|
16
17
|
import { ChevronDownIcon } from "@heroicons/react/16/solid";
|
|
@@ -22,6 +23,10 @@ const Dropdown = forwardRef((_a, ref) => {
|
|
|
22
23
|
const [selectedOption, setSelectedOption] = useState(null);
|
|
23
24
|
const [textValue, setTextValue] = useState("");
|
|
24
25
|
const keyCode = useRef("");
|
|
26
|
+
const dropdownRef = useRef(null);
|
|
27
|
+
const inputRef = useRef(null);
|
|
28
|
+
const [dropdownStyles, setDropdownStyles] = useState({});
|
|
29
|
+
useImperativeHandle(ref, () => inputRef === null || inputRef === void 0 ? void 0 : inputRef.current);
|
|
25
30
|
useEffect(() => {
|
|
26
31
|
var _a;
|
|
27
32
|
setSelectedOption(value);
|
|
@@ -46,15 +51,49 @@ const Dropdown = forwardRef((_a, ref) => {
|
|
|
46
51
|
((_a = option.label) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(textValue === null || textValue === void 0 ? void 0 : textValue.toLowerCase()));
|
|
47
52
|
});
|
|
48
53
|
}, [options, filterMode, textValue]);
|
|
54
|
+
const updateDropdownPosition = useCallback(() => {
|
|
55
|
+
var _a;
|
|
56
|
+
if (inputRef.current) {
|
|
57
|
+
const rect = inputRef.current.getBoundingClientRect();
|
|
58
|
+
const dropdownHeight = ((_a = dropdownRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) || 0;
|
|
59
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
60
|
+
const spaceAbove = rect.top;
|
|
61
|
+
const position = spaceBelow >= dropdownHeight || spaceBelow > spaceAbove
|
|
62
|
+
? {
|
|
63
|
+
top: `${rect.bottom + window.scrollY}px`,
|
|
64
|
+
left: `${rect.left + window.scrollX}px`,
|
|
65
|
+
width: `${rect.width}px`,
|
|
66
|
+
}
|
|
67
|
+
: {
|
|
68
|
+
top: `${rect.top - dropdownHeight + window.scrollY}px`,
|
|
69
|
+
left: `${rect.left + window.scrollX}px`,
|
|
70
|
+
width: `${rect.width}px`,
|
|
71
|
+
};
|
|
72
|
+
setDropdownStyles(position);
|
|
73
|
+
}
|
|
74
|
+
}, []);
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (isFocused) {
|
|
77
|
+
updateDropdownPosition();
|
|
78
|
+
window.addEventListener("resize", updateDropdownPosition);
|
|
79
|
+
window.addEventListener("scroll", updateDropdownPosition, true);
|
|
80
|
+
}
|
|
81
|
+
return () => {
|
|
82
|
+
window.removeEventListener("resize", updateDropdownPosition);
|
|
83
|
+
window.removeEventListener("scroll", updateDropdownPosition, true);
|
|
84
|
+
};
|
|
85
|
+
}, [isFocused, updateDropdownPosition]);
|
|
49
86
|
const renderOptions = () => {
|
|
50
87
|
if (customRenderOptions) {
|
|
51
88
|
return customRenderOptions({
|
|
52
89
|
optionsFiltered,
|
|
53
90
|
selectedOption,
|
|
54
91
|
onClick: handleOptionClick,
|
|
92
|
+
style: dropdownStyles,
|
|
93
|
+
dropdownRef,
|
|
55
94
|
});
|
|
56
95
|
}
|
|
57
|
-
return (_jsxs("ul", { className: cn("absolute mt-1 w-full bg-base-popup border border-base-popup text-base-popup-foreground rounded-md shadow-md z-10 max-h-60 overflow-y-auto", optionContainerClassName), children: [optionsFiltered.map((option) => {
|
|
96
|
+
return (_jsxs("ul", { className: cn("absolute mt-1 w-full bg-base-popup border border-base-popup text-base-popup-foreground rounded-md shadow-md z-10 max-h-60 overflow-y-auto", optionContainerClassName), style: dropdownStyles, ref: dropdownRef, children: [optionsFiltered.map((option) => {
|
|
58
97
|
if (option.renderLabel) {
|
|
59
98
|
return (_jsx(Fragment, { children: option.renderLabel({
|
|
60
99
|
value: option.value,
|
|
@@ -106,6 +145,6 @@ const Dropdown = forwardRef((_a, ref) => {
|
|
|
106
145
|
keyCode.current = e.code;
|
|
107
146
|
(_a = props === null || props === void 0 ? void 0 : props.onKeyDown) === null || _a === void 0 ? void 0 : _a.call(props, e);
|
|
108
147
|
}, [props === null || props === void 0 ? void 0 : props.onKeyDown]);
|
|
109
|
-
return (_jsxs("div", { className: `relative ${fullwidth ? "w-full" : ""}`, children: [_jsx(TextInput, Object.assign({ hasClearIcon: false, endIcon: _jsx("div", { className: iconWrapperVariant({ size }), children: _jsx(ChevronDownIcon, { className: dropdownIconVariant({ size, isFocus: isFocused }) }) }) }, props, { ref:
|
|
148
|
+
return (_jsxs("div", { className: `relative ${fullwidth ? "w-full" : ""}`, children: [_jsx(TextInput, Object.assign({ hasClearIcon: false, endIcon: _jsx("div", { className: iconWrapperVariant({ size }), children: _jsx(ChevronDownIcon, { className: dropdownIconVariant({ size, isFocus: isFocused }) }) }) }, props, { ref: inputRef, readOnly: !filterMode, value: textValue, onChange: handleOnChangeText, label: label, placeholder: " ", type: "text", autoComplete: "off", rounded: rounded, variant: variant, helperText: helperText, errorMessage: errorMessage, fullwidth: fullwidth, error: error, required: required, id: _id, disabled: disabled, size: size, className: customInputVariant({ size }), onFocus: handleOnFocus, onBlur: handleOnBlur, onKeyDown: handleOnKeyDown })), isFocused && _jsx(Portal.Root, { children: renderOptions() })] }));
|
|
110
149
|
});
|
|
111
150
|
export default Dropdown;
|
|
@@ -14,7 +14,7 @@ import { forwardRef } from "react";
|
|
|
14
14
|
import { cn } from "@/utils/cn";
|
|
15
15
|
import { inputVariants } from "./Input.styles";
|
|
16
16
|
const Input = forwardRef((_a, ref) => {
|
|
17
|
-
var { className, type = "text", size = "md", variant = "outline", fullwidth = false, disabled = false, error = false, required = false, hiddenPlaceholder = false } = _a, props = __rest(_a, ["className", "type", "size", "variant", "fullwidth", "disabled", "error", "required", "hiddenPlaceholder"]);
|
|
17
|
+
var { className, type = "text", size = "md", variant = "outline", rounded = "normal", fullwidth = false, disabled = false, error = false, required = false, hiddenPlaceholder = false } = _a, props = __rest(_a, ["className", "type", "size", "variant", "rounded", "fullwidth", "disabled", "error", "required", "hiddenPlaceholder"]);
|
|
18
18
|
return (_jsx("input", Object.assign({ type: type, className: cn(inputVariants({
|
|
19
19
|
size,
|
|
20
20
|
variant,
|
|
@@ -22,6 +22,7 @@ const Input = forwardRef((_a, ref) => {
|
|
|
22
22
|
error,
|
|
23
23
|
hiddenPlaceholder,
|
|
24
24
|
disabled,
|
|
25
|
+
rounded,
|
|
25
26
|
}), className), ref: ref, disabled: disabled }, props)));
|
|
26
27
|
});
|
|
27
28
|
Input.displayName = "Input";
|
|
@@ -5,8 +5,7 @@ import "./Tabs.css";
|
|
|
5
5
|
import ActionButton from "../ActionButton/ActionButton";
|
|
6
6
|
import Icon from "../Icon/Icon";
|
|
7
7
|
import { Loading } from "@/index";
|
|
8
|
-
const Tabs = ({ tabs = [], value, initialTab = 0, tabBarSize = 38, enableBorderLine = true, enableAddTabButton = false, keepIconSpace = true, disabled = false, tabMode = "start", className, tabBarClassName, tabBarContainerClassName, tabBarWrapperClassName, tabButtonClassName, tabButtonActiveClassName, tabContentClassName, addTabButtonWrapperClassName, borderSliderClassName, leftAction, rightAction, onAddTab, onTabChange, }) => {
|
|
9
|
-
var _a;
|
|
8
|
+
const Tabs = ({ tabs = [], value, initialTab = 0, tabBarSize = 38, enableBorderLine = true, enableAddTabButton = false, keepIconSpace = true, disabled = false, keepMounted = false, tabMode = "start", className, tabBarClassName, tabBarContainerClassName, tabBarWrapperClassName, tabButtonClassName, tabButtonActiveClassName, tabContentClassName, addTabButtonWrapperClassName, borderSliderClassName, leftAction, rightAction, onAddTab, onTabChange, }) => {
|
|
10
9
|
const [activeTab, setActiveTab] = useState(initialTab);
|
|
11
10
|
const [sliderStyle, setSliderStyle] = useState({
|
|
12
11
|
width: "0px",
|
|
@@ -19,47 +18,46 @@ const Tabs = ({ tabs = [], value, initialTab = 0, tabBarSize = 38, enableBorderL
|
|
|
19
18
|
setActiveTab(value);
|
|
20
19
|
}
|
|
21
20
|
}, [value]);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// }, [activeTab, tabs, tabMode, keepIconSpace]);
|
|
21
|
+
const updateSliderStyle = () => {
|
|
22
|
+
const activeTabElement = tabRefs.current[activeTab];
|
|
23
|
+
if (activeTabElement) {
|
|
24
|
+
setSliderStyle({
|
|
25
|
+
width: `${activeTabElement.offsetWidth}px`,
|
|
26
|
+
transform: `translateX(${activeTabElement.offsetLeft}px)`,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
let timeout;
|
|
32
|
+
if (isInitialMount.current) {
|
|
33
|
+
isInitialMount.current = false;
|
|
34
|
+
// Set initial position without animation
|
|
35
|
+
const activeTabElement = tabRefs.current[activeTab];
|
|
36
|
+
if (activeTabElement) {
|
|
37
|
+
setSliderStyle({
|
|
38
|
+
width: "0px",
|
|
39
|
+
transform: `translateX(${activeTabElement.offsetLeft + activeTabElement.offsetWidth / 2}px)`,
|
|
40
|
+
});
|
|
41
|
+
// Trigger reflow
|
|
42
|
+
timeout = setTimeout(() => {
|
|
43
|
+
updateSliderStyle();
|
|
44
|
+
}, 50);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
updateSliderStyle();
|
|
49
|
+
}
|
|
50
|
+
const handleResize = () => {
|
|
51
|
+
updateSliderStyle();
|
|
52
|
+
};
|
|
53
|
+
window.addEventListener("resize", handleResize);
|
|
54
|
+
return () => {
|
|
55
|
+
window.removeEventListener("resize", handleResize);
|
|
56
|
+
if (timeout) {
|
|
57
|
+
clearTimeout(timeout);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}, [activeTab, tabs, tabMode, keepIconSpace]);
|
|
63
61
|
return (_jsxs("div", { className: cn("w-full", className), children: [_jsxs("div", { className: cn(" relative flex flex-row w-full", {
|
|
64
62
|
[`border-b-[1px] border-base-stroke`]: enableBorderLine,
|
|
65
63
|
"border-state-disable-outline": disabled,
|
|
@@ -84,6 +82,12 @@ const Tabs = ({ tabs = [], value, initialTab = 0, tabBarSize = 38, enableBorderL
|
|
|
84
82
|
onTabChange === null || onTabChange === void 0 ? void 0 : onTabChange(index);
|
|
85
83
|
}, children: [(keepIconSpace || tab.startTabContent) && (_jsx("div", { className: "h-full w-3 flex items-center justify-center", children: tab.isLoading ? _jsx(Loading, {}) : tab.startTabContent })), tab.label, (keepIconSpace || tab.endTabContent) && (_jsx("div", { className: "h-full w-3 flex items-center justify-center", children: tab.endTabContent }))] }, index))), _jsx("div", { className: cn(`absolute left-0 bottom-0 h-[2px] rounded-full bg-foreground transition-all duration-300 ease-in-out`, {
|
|
86
84
|
"bg-state-disable-solid": disabled,
|
|
87
|
-
}, borderSliderClassName), style: sliderStyle })] }) }), enableAddTabButton && (_jsx("div", { className: cn("sticky right-0 flex content-center items-center mx-4", addTabButtonWrapperClassName), children: _jsx(ActionButton, { variant: "outline", size: "sm", onClick: () => onAddTab === null || onAddTab === void 0 ? void 0 : onAddTab(), disabled: disabled, children: _jsx(Icon, { name: "plus" }) }) })), rightAction] }), _jsx("div", { className: cn("mt-4 text-foreground", tabContentClassName), role: "tabpanel", id: `tab-content-${activeTab}`, "aria-labelledby": `tab-${activeTab}`, children: (
|
|
85
|
+
}, borderSliderClassName), style: sliderStyle })] }) }), enableAddTabButton && (_jsx("div", { className: cn("sticky right-0 flex content-center items-center mx-4", addTabButtonWrapperClassName), children: _jsx(ActionButton, { variant: "outline", size: "sm", onClick: () => onAddTab === null || onAddTab === void 0 ? void 0 : onAddTab(), disabled: disabled, children: _jsx(Icon, { name: "plus" }) }) })), rightAction] }), _jsx("div", { className: cn("mt-4 text-foreground", tabContentClassName), role: "tabpanel", id: `tab-content-${activeTab}`, "aria-labelledby": `tab-${activeTab}`, children: tabs.map((tab, idx) => {
|
|
86
|
+
var _a;
|
|
87
|
+
if (!keepMounted && activeTab !== idx) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return (_jsx("div", { className: `transition ${activeTab === idx ? "block" : "hidden"}`, children: tab.content }, (_a = tab.id) !== null && _a !== void 0 ? _a : idx));
|
|
91
|
+
}) })] }));
|
|
88
92
|
};
|
|
89
93
|
export default Tabs;
|
|
@@ -2,7 +2,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { useCallback, useEffect, useState } from "react";
|
|
3
3
|
import TreeItem from "./TreeItem";
|
|
4
4
|
import { cn } from "@/utils/cn";
|
|
5
|
-
|
|
5
|
+
import { usePrevious } from "@/hooks";
|
|
6
|
+
const Tree = ({ classes, data, defaultExpandedId, defaultCheckedId, checkedId, loadingId, lineSize, horizontalLineWidth, expandButtonSize, spacing, renderIcon, renderRightSection, renderElement, renderTitle, onExpandChange, onCheckedChange, onClickItem, onCheckedItem, defaultExpandAll = false, defaultCheckAll = false, hierarchicalCheck = false, showIcon = true, disabled, enableSeparatorLine = true, checkable = true, maxLevel, mode = "checkbox", autoDisabled = false, checkedAll = false, }) => {
|
|
6
7
|
const [checkedState, setCheckedState] = useState({});
|
|
7
8
|
const [expandedState, setExpandedState] = useState({});
|
|
8
9
|
const traverseTree = (nodes, callback) => {
|
|
@@ -52,6 +53,7 @@ const Tree = ({ classes, data, defaultExpandedId, defaultCheckedId, checkedId, l
|
|
|
52
53
|
setCheckedState(checkedId.reduce((prev, cur) => (Object.assign(Object.assign({}, prev), { [cur]: true })), {}));
|
|
53
54
|
}
|
|
54
55
|
}, [checkedId]);
|
|
56
|
+
// For usecase loaded data a children coming after.
|
|
55
57
|
useEffect(() => {
|
|
56
58
|
if (!hierarchicalCheck) {
|
|
57
59
|
return;
|
|
@@ -76,6 +78,29 @@ const Tree = ({ classes, data, defaultExpandedId, defaultCheckedId, checkedId, l
|
|
|
76
78
|
return Object.assign(Object.assign({}, prev), state);
|
|
77
79
|
});
|
|
78
80
|
}, [data, hierarchicalCheck]);
|
|
81
|
+
const prevCheckedAll = usePrevious(checkedAll);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (prevCheckedAll === undefined || prevCheckedAll === checkedAll)
|
|
84
|
+
return;
|
|
85
|
+
if (checkedAll) {
|
|
86
|
+
const newState = {};
|
|
87
|
+
traverseTree(data, (node) => {
|
|
88
|
+
if (node.id) {
|
|
89
|
+
newState[node.id] = true;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
setCheckedState(newState);
|
|
93
|
+
onCheckedChange === null || onCheckedChange === void 0 ? void 0 : onCheckedChange(newState, undefined, null);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
let newState = {};
|
|
97
|
+
setCheckedState((prev) => {
|
|
98
|
+
newState = Object.keys(prev).reduce((p, key) => (Object.assign(Object.assign({}, p), { [key]: false })), {});
|
|
99
|
+
return newState;
|
|
100
|
+
});
|
|
101
|
+
onCheckedChange === null || onCheckedChange === void 0 ? void 0 : onCheckedChange(newState, undefined, null);
|
|
102
|
+
}
|
|
103
|
+
}, [data, checkedAll, prevCheckedAll]);
|
|
79
104
|
const handleExpandChange = useCallback((id, expanded, itemData) => {
|
|
80
105
|
onExpandChange === null || onExpandChange === void 0 ? void 0 : onExpandChange(id, expanded, itemData);
|
|
81
106
|
setExpandedState((prev) => (Object.assign(Object.assign({}, prev), { [id]: expanded })));
|
|
@@ -210,3 +210,15 @@ export const RadioMode = {
|
|
|
210
210
|
} }))] }));
|
|
211
211
|
},
|
|
212
212
|
};
|
|
213
|
+
export const CheckAll = {
|
|
214
|
+
args: {
|
|
215
|
+
data: exampleData,
|
|
216
|
+
},
|
|
217
|
+
render: (args) => {
|
|
218
|
+
const [isCheckedAll, setIsCheckedAll] = useState(false);
|
|
219
|
+
const [checkedId, onCheckedId] = useState([]);
|
|
220
|
+
return (_jsxs("div", { className: "flex flex-col gap-4 w-full", children: [_jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "outline", onClick: () => setIsCheckedAll(!isCheckedAll), children: [isCheckedAll ? "Unchecked" : "Checked", " All"] }), _jsx(Button, { variant: "outline", onClick: () => onCheckedId([]), children: "Clear" })] }), _jsx(Tree, Object.assign({}, args, { hierarchicalCheck: true, checkedAll: isCheckedAll, checkedId: checkedId, onCheckedChange: (state) => {
|
|
221
|
+
onCheckedId(Object.keys(state).filter((key) => state === null || state === void 0 ? void 0 : state[key]));
|
|
222
|
+
} }))] }));
|
|
223
|
+
},
|
|
224
|
+
};
|