@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.
Files changed (43) hide show
  1. package/dist/cjs/bundle.js +3 -3
  2. package/dist/cjs/bundle.js.map +1 -1
  3. package/dist/cjs/types/components/Dropdown/Dropdown.d.ts +5 -1
  4. package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +4 -0
  5. package/dist/cjs/types/components/Search/Search.stories.d.ts +2 -0
  6. package/dist/cjs/types/components/Tabs/Tabs.d.ts +1 -0
  7. package/dist/cjs/types/components/Tabs/Tabs.stories.d.ts +2 -0
  8. package/dist/cjs/types/components/Tree/Tree.stories.d.ts +1 -0
  9. package/dist/cjs/types/components/Tree/type.d.ts +1 -0
  10. package/dist/cjs/types/hooks/index.d.ts +1 -0
  11. package/dist/cjs/types/hooks/usePrevious.d.ts +2 -0
  12. package/dist/cjs/types/index.d.ts +1 -0
  13. package/dist/components/Dropdown/Dropdown.js +42 -3
  14. package/dist/components/Input/Input.js +2 -1
  15. package/dist/components/Tabs/Tabs.js +48 -44
  16. package/dist/components/Tree/Tree.js +26 -1
  17. package/dist/components/Tree/Tree.stories.js +12 -0
  18. package/dist/esm/bundle.js +3 -3
  19. package/dist/esm/bundle.js.map +1 -1
  20. package/dist/esm/types/components/Dropdown/Dropdown.d.ts +5 -1
  21. package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +4 -0
  22. package/dist/esm/types/components/Search/Search.stories.d.ts +2 -0
  23. package/dist/esm/types/components/Tabs/Tabs.d.ts +1 -0
  24. package/dist/esm/types/components/Tabs/Tabs.stories.d.ts +2 -0
  25. package/dist/esm/types/components/Tree/Tree.stories.d.ts +1 -0
  26. package/dist/esm/types/components/Tree/type.d.ts +1 -0
  27. package/dist/esm/types/hooks/index.d.ts +1 -0
  28. package/dist/esm/types/hooks/usePrevious.d.ts +2 -0
  29. package/dist/esm/types/index.d.ts +1 -0
  30. package/dist/hooks/index.js +1 -0
  31. package/dist/hooks/usePrevious.js +9 -0
  32. package/dist/index.d.ts +10 -2
  33. package/dist/index.js +2 -0
  34. package/package.json +1 -1
  35. package/src/components/Dropdown/Dropdown.tsx +54 -3
  36. package/src/components/Input/Input.tsx +2 -0
  37. package/src/components/Tabs/Tabs.tsx +57 -42
  38. package/src/components/Tree/Tree.stories.tsx +35 -0
  39. package/src/components/Tree/Tree.tsx +33 -0
  40. package/src/components/Tree/type.ts +1 -0
  41. package/src/hooks/index.ts +1 -0
  42. package/src/hooks/usePrevious.ts +13 -0
  43. 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 @@ type TabsProps = {
30
30
  leftAction?: React.ReactNode;
31
31
  rightAction?: React.ReactNode;
32
32
  disabled?: boolean;
33
+ keepMounted?: boolean;
33
34
  onAddTab?: () => void;
34
35
  onTabChange?: (tabIndex: number) => void;
35
36
  };
@@ -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>;
@@ -94,4 +94,5 @@ export interface TreeProps extends Pick<TreeItemProps, "renderIcon" | "renderRig
94
94
  maxLevel?: number;
95
95
  mode?: "checkbox" | "radio";
96
96
  autoDisabled?: boolean;
97
+ checkedAll?: boolean;
97
98
  }
@@ -0,0 +1 @@
1
+ export { default as usePrevious } from "./usePrevious";
@@ -0,0 +1,2 @@
1
+ declare function usePrevious<T>(value: T): T | undefined;
2
+ export default 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: ref, 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 && renderOptions()] }));
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
- // const updateSliderStyle = () => {
23
- // const activeTabElement = tabRefs.current[activeTab];
24
- // if (activeTabElement) {
25
- // setSliderStyle({
26
- // width: `${activeTabElement.offsetWidth}px`,
27
- // transform: `translateX(${activeTabElement.offsetLeft}px)`,
28
- // });
29
- // }
30
- // };
31
- // useEffect(() => {
32
- // let timer: NodeJS.Timeout;
33
- // if (isInitialMount.current) {
34
- // isInitialMount.current = false;
35
- // // Set initial position without animation
36
- // const activeTabElement = tabRefs.current[activeTab];
37
- // if (activeTabElement) {
38
- // setSliderStyle({
39
- // width: "0px",
40
- // transform: `translateX(${
41
- // activeTabElement.offsetLeft + activeTabElement.offsetWidth / 2
42
- // }px)`,
43
- // });
44
- // // Trigger reflow
45
- // timer = setTimeout(() => {
46
- // updateSliderStyle();
47
- // }, 50);
48
- // }
49
- // } else {
50
- // updateSliderStyle();
51
- // }
52
- // const handleResize = () => {
53
- // updateSliderStyle();
54
- // };
55
- // window.addEventListener("resize", handleResize);
56
- // return () => {
57
- // window.removeEventListener("resize", handleResize);
58
- // if (timer) {
59
- // clearTimeout(timer);
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: (_a = tabs[activeTab]) === null || _a === void 0 ? void 0 : _a.content })] }));
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
- 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, }) => {
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
+ };