@rovula/ui 0.0.47 → 0.0.48

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.
@@ -293,13 +293,8 @@ declare const meta: {
293
293
  export default meta;
294
294
  export declare const Default: {
295
295
  args: {
296
- defaultValue: number[];
297
- max: number;
298
- step: number;
299
- name: string;
300
- minStepsBetweenThumbs: number;
296
+ checked: boolean;
301
297
  disabled: boolean;
302
- inverted: boolean;
303
298
  };
304
299
  render: (args: {}) => import("react/jsx-runtime").JSX.Element;
305
300
  };
@@ -0,0 +1,45 @@
1
+ import { FC, ReactNode } from "react";
2
+ export type TreeData = {
3
+ id: string;
4
+ title: string;
5
+ icon?: ReactNode;
6
+ children?: TreeData[];
7
+ };
8
+ export interface TreeItemProps extends TreeData {
9
+ isFirstLevel?: boolean;
10
+ isLastItem: boolean;
11
+ checkIsExpanded: (id: string) => boolean;
12
+ checkIsChecked: (id: string) => boolean;
13
+ onExpandChange?: (id: string, expanded: boolean) => void;
14
+ onCheckedChange?: (id: string, checked: boolean) => void;
15
+ }
16
+ export type TreeProps = {
17
+ data: TreeData[];
18
+ defaultExpandedId?: string[];
19
+ defaultCheckedId?: string[];
20
+ checkedId?: string[];
21
+ onCheckedChange?: (checkedId: string[]) => void;
22
+ defaultExpandAll?: boolean;
23
+ defaultCheckAll?: boolean;
24
+ hierarchicalCheck?: boolean;
25
+ };
26
+ export declare const Tree: FC<TreeProps>;
27
+ /**
28
+ * TODO
29
+ * -----
30
+ * - Custom style
31
+ * - Custom icon, elm and render props -> callback with selected*expanded
32
+ * - OnClick item
33
+ * - OnClick expandButton
34
+ * - disabled props
35
+ * - right section icon
36
+ * - props for show icon, line
37
+ * - props for render item
38
+ * - OnLoad mode
39
+ * -----
40
+ * - props onLoad item
41
+ * - props for hasChildren * for check to trigger on load
42
+ * - animate expand
43
+ * - check duplicate reversive on updateChildren
44
+ * - write storybook
45
+ */
@@ -0,0 +1,5 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Tree } from "./Tree";
3
+ declare const meta: Meta<typeof Tree>;
4
+ export default meta;
5
+ export declare const Default: StoryObj<typeof Tree>;
@@ -18,7 +18,7 @@ const switchBaseClasses = "group inline-flex h-3 w-[32px] shrink-0 cursor-pointe
18
18
  const switchStateClasses = {
19
19
  unchecked: "data-[state=unchecked]:bg-[var(--switch-default-color)] hover:data-[state=unchecked]:bg-[var(--switch-hover-color)]",
20
20
  checked: "data-[state=checked]:bg-[var(--switch-active-color)] hover:data-[state=checked]:bg-[var(--switch-active-hover-color)]",
21
- disabled: "data-[disabled]:cursor-not-allowed data-[disabled]:bg-[var(--switch-disabled-color)] data-[disabled]:pointer-events-none",
21
+ disabled: "data-[disabled]:cursor-not-allowed data-[disabled]:!bg-[var(--switch-disabled-color)] data-[disabled]:pointer-events-none",
22
22
  };
23
23
  const thumbBaseClasses = "block size-4 rounded-full shadow-lg transition-transform";
24
24
  const thumbStateClasses = {
@@ -26,7 +26,7 @@ const thumbStateClasses = {
26
26
  checked: "data-[state=checked]:bg-[var(--switch-thumb-active-color)] data-[state=checked]:translate-x-4",
27
27
  hover: "group-hover:ring group-hover:data-[state=checked]:ring-[var(--switch-thumb-active-hover-ring)] group-hover:data-[state=unchecked]:ring-[var(--switch-thumb-hover-ring)]",
28
28
  hoverColor: "group-hover:data-[state=checked]:bg-[var(--switch-thumb-active-hover-color)] group-hover:data-[state=unchecked]:bg-[var(--switch-thumb-hover-color)]",
29
- disabled: "group-disabled:bg-[--switch-thumb-disabled-color]",
29
+ disabled: "group-disabled:!bg-[--switch-thumb-disabled-color]",
30
30
  };
31
31
  const Switch = React.forwardRef((_a, ref) => {
32
32
  var { className } = _a, props = __rest(_a, ["className"]);
@@ -10,19 +10,14 @@ const meta = {
10
10
  layout: "fullscreen",
11
11
  },
12
12
  decorators: [
13
- (Story) => (_jsx("div", { className: "p-5 flex w-full", children: _jsx(Story, {}) })),
13
+ (Story) => (_jsx("div", { className: "p-5 flex w-full bg-base-bg2", children: _jsx(Story, {}) })),
14
14
  ],
15
15
  };
16
16
  export default meta;
17
17
  export const Default = {
18
18
  args: {
19
- defaultValue: [50],
20
- max: 100,
21
- step: 1,
22
- name: "test",
23
- minStepsBetweenThumbs: 1,
19
+ checked: false,
24
20
  disabled: false,
25
- inverted: false,
26
21
  },
27
22
  render: (args) => {
28
23
  console.log("args ", args);
@@ -0,0 +1,138 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ActionButton, Checkbox, Icon, cn } from "@/index";
3
+ import { useCallback, useMemo, useState, useEffect, } from "react";
4
+ const TreeItem = ({ id, title, children, isFirstLevel = false, isLastItem, checkIsExpanded, checkIsChecked, onExpandChange, onCheckedChange, }) => {
5
+ const isChecked = useMemo(() => checkIsChecked(id), [checkIsChecked, id]);
6
+ const isExpanded = useMemo(() => checkIsExpanded(id), [checkIsExpanded, id]);
7
+ const hasChildren = useMemo(() => !!(children === null || children === void 0 ? void 0 : children.length), [children]);
8
+ const handleExpandToggle = useCallback(() => {
9
+ onExpandChange === null || onExpandChange === void 0 ? void 0 : onExpandChange(id, !isExpanded);
10
+ }, [id, isExpanded, onExpandChange]);
11
+ // TODO move to props
12
+ const lineSize = 2;
13
+ const horizontalLineWidth = 4;
14
+ const expandButtonSize = 30;
15
+ const spacing = 2;
16
+ const styles = {
17
+ branch: {
18
+ height: isLastItem
19
+ ? `calc(50% + ${lineSize}px)`
20
+ : `calc(100% + ${lineSize}px)`,
21
+ width: lineSize,
22
+ marginTop: -lineSize,
23
+ borderBottomLeftRadius: lineSize / 2,
24
+ },
25
+ horizontalLine: {
26
+ height: lineSize,
27
+ width: lineSize +
28
+ horizontalLineWidth +
29
+ (hasChildren ? 0 : expandButtonSize + spacing),
30
+ marginLeft: -lineSize + 0.1,
31
+ borderBottomLeftRadius: lineSize / 2,
32
+ },
33
+ expandButton: {
34
+ width: expandButtonSize,
35
+ height: expandButtonSize,
36
+ },
37
+ childPadding: {
38
+ paddingLeft: isFirstLevel
39
+ ? expandButtonSize / 2 - lineSize / 2
40
+ : expandButtonSize / 2 + horizontalLineWidth - lineSize / 2,
41
+ },
42
+ };
43
+ return (_jsxs("div", { className: "flex flex-row w-full", children: [_jsx("div", { className: cn("bg-grey-150", { "h-1/2": isLastItem }), style: styles.branch }), _jsxs("div", { className: "flex flex-col w-full", children: [_jsxs("div", { className: "flex items-center py-2 min-h-10", children: [!isFirstLevel && (_jsx("div", { className: "bg-grey-150", style: styles.horizontalLine })), isFirstLevel && !hasChildren && (_jsx("div", { className: "flex mr-[2px]", style: styles.expandButton })), hasChildren && (_jsx("div", { className: "flex mr-[2px]", style: styles.expandButton, children: _jsx(ActionButton, { variant: "icon", size: "sm", onClick: handleExpandToggle, children: _jsx(Icon, { name: isExpanded ? "chevron-down" : "chevron-right" }) }) })), _jsx(Checkbox, { id: id, className: "size-[16pt]", checked: isChecked, onCheckedChange: (newChecked) => onCheckedChange === null || onCheckedChange === void 0 ? void 0 : onCheckedChange(id, newChecked) }), _jsxs("div", { className: "ml-2 gap-1 flex items-center text-foreground", children: [_jsx(Icon, { name: isExpanded ? "folder-open" : "folder", className: "fill-warning" }), _jsx("label", { htmlFor: id, className: "flex-1 cursor-pointer text-subtitle5 text-ellipsis", children: title })] })] }), isExpanded && hasChildren && (_jsx("div", { className: "flex flex-col", style: styles.childPadding, children: children === null || children === void 0 ? void 0 : children.map((child, idx) => (_jsx(TreeItem, Object.assign({}, child, { isLastItem: idx === children.length - 1, checkIsExpanded: checkIsExpanded, checkIsChecked: checkIsChecked, onExpandChange: onExpandChange, onCheckedChange: onCheckedChange }), child.id))) }))] })] }));
44
+ };
45
+ export const Tree = ({ data, defaultExpandedId = [], defaultCheckedId = [], checkedId, onCheckedChange, defaultExpandAll = false, defaultCheckAll = false, hierarchicalCheck = false, }) => {
46
+ const [checkedState, setCheckedState] = useState({});
47
+ const [expandedState, setExpandedState] = useState({});
48
+ const traverseTree = (nodes, callback) => {
49
+ nodes.forEach((node) => {
50
+ callback(node);
51
+ if (node.children) {
52
+ traverseTree(node.children, callback);
53
+ }
54
+ });
55
+ };
56
+ useEffect(() => {
57
+ if (defaultExpandAll) {
58
+ const allExpanded = {};
59
+ traverseTree(data, (node) => {
60
+ allExpanded[node.id] = true;
61
+ });
62
+ setExpandedState(allExpanded);
63
+ }
64
+ else {
65
+ const initialExpandedState = defaultExpandedId.reduce((acc, id) => {
66
+ acc[id] = true;
67
+ return acc;
68
+ }, {});
69
+ setExpandedState(initialExpandedState);
70
+ }
71
+ }, [data, defaultExpandedId, defaultExpandAll]);
72
+ useEffect(() => {
73
+ if (defaultCheckAll) {
74
+ const allChecked = {};
75
+ traverseTree(data, (node) => {
76
+ allChecked[node.id] = true;
77
+ });
78
+ setCheckedState(allChecked);
79
+ }
80
+ else if (!checkedId) {
81
+ const initialCheckedState = defaultCheckedId.reduce((acc, id) => {
82
+ acc[id] = true;
83
+ return acc;
84
+ }, {});
85
+ setCheckedState(initialCheckedState);
86
+ }
87
+ }, [data, defaultCheckedId, checkedId, defaultCheckAll]);
88
+ const handleExpandChange = useCallback((id, expanded) => {
89
+ setExpandedState((prev) => (Object.assign(Object.assign({}, prev), { [id]: expanded })));
90
+ }, []);
91
+ const handleCheckedChange = useCallback((id, checked) => {
92
+ let newState = Object.assign(Object.assign({}, checkedState), { [id]: checked });
93
+ if (hierarchicalCheck) {
94
+ const updateCheckedState = (nodeId, isChecked, state) => {
95
+ state[nodeId] = isChecked;
96
+ // Update children recursively
97
+ const updateChildren = (parentId, isChecked) => {
98
+ traverseTree(data, (node) => {
99
+ if (node.id === parentId && node.children) {
100
+ node.children.forEach((child) => {
101
+ state[child.id] = isChecked;
102
+ updateChildren(child.id, isChecked);
103
+ });
104
+ }
105
+ });
106
+ };
107
+ // Update parents recursively
108
+ const updateParents = (childId, state) => {
109
+ traverseTree(data, (node) => {
110
+ var _a;
111
+ if ((_a = node.children) === null || _a === void 0 ? void 0 : _a.some((child) => child.id === childId)) {
112
+ const allChildrenChecked = node.children.every((child) => state[child.id]);
113
+ state[node.id] = allChildrenChecked;
114
+ updateParents(node.id, state);
115
+ }
116
+ });
117
+ };
118
+ updateChildren(nodeId, isChecked);
119
+ updateParents(nodeId, state);
120
+ return state;
121
+ };
122
+ newState = updateCheckedState(id, checked, newState);
123
+ }
124
+ setCheckedState(newState);
125
+ if (onCheckedChange) {
126
+ const checkedIds = Object.keys(newState).filter((key) => newState[key]);
127
+ onCheckedChange(checkedIds);
128
+ }
129
+ }, [checkedState, data, onCheckedChange, hierarchicalCheck]);
130
+ const checkIsExpanded = useCallback((id) => !!expandedState[id], [expandedState]);
131
+ const checkIsChecked = useCallback((id) => {
132
+ if (checkedId) {
133
+ return checkedId.includes(id);
134
+ }
135
+ return !!checkedState[id];
136
+ }, [checkedId, checkedState]);
137
+ return (_jsx("div", { className: "w-full", children: data.map((item, idx) => (_jsx(TreeItem, Object.assign({}, item, { isFirstLevel: true, isLastItem: idx === data.length - 1, checkIsExpanded: checkIsExpanded, checkIsChecked: checkIsChecked, onExpandChange: handleExpandChange, onCheckedChange: handleCheckedChange }), item.id))) }));
138
+ };
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Tree } from "./Tree";
3
+ // Example data for testing the Tree component (as plain objects)
4
+ const exampleData = [
5
+ {
6
+ id: "1",
7
+ title: "Parent Folder 1",
8
+ children: [
9
+ {
10
+ id: "1.1",
11
+ title: "Child Folder 1.1",
12
+ children: [
13
+ { id: "1.1.1", title: "Sub Folder 1.1.1" },
14
+ { id: "1.1.2", title: "Sub Folder 1.1.2" },
15
+ ],
16
+ },
17
+ { id: "1.2", title: "Child Folder 1.2" },
18
+ ],
19
+ },
20
+ {
21
+ id: "2",
22
+ title: "Parent Folder 2",
23
+ children: [{ id: "2.1", title: "Child Folder 2.1" }],
24
+ },
25
+ { id: "3", title: "Parent Folder 3" },
26
+ ];
27
+ // Storybook metadata
28
+ const meta = {
29
+ title: "Components/Tree",
30
+ component: Tree,
31
+ tags: ["autodocs"],
32
+ parameters: {
33
+ layout: "fullscreen",
34
+ },
35
+ decorators: [
36
+ (Story) => (_jsx("div", { className: "p-5 flex w-full bg-base-bg", children: _jsx(Story, {}) })),
37
+ ],
38
+ };
39
+ export default meta;
40
+ // Default story
41
+ export const Default = {
42
+ args: {
43
+ data: exampleData,
44
+ defaultExpandedId: ["1", "1.1"],
45
+ defaultCheckedId: ["1.1"],
46
+ defaultExpandAll: true,
47
+ defaultCheckAll: true,
48
+ hierarchicalCheck: true,
49
+ },
50
+ render: (args) => {
51
+ return (_jsx("div", { className: "flex flex-row gap-4 w-full", children: _jsx(Tree, Object.assign({}, args)) }));
52
+ },
53
+ };
@@ -699,6 +699,9 @@ input[type=number] {
699
699
  .mr-4{
700
700
  margin-right: 1rem;
701
701
  }
702
+ .mr-\[2px\]{
703
+ margin-right: 2px;
704
+ }
702
705
  .mt-1{
703
706
  margin-top: 0.25rem;
704
707
  }
@@ -777,6 +780,10 @@ input[type=number] {
777
780
  width: 14px;
778
781
  height: 14px;
779
782
  }
783
+ .size-\[16pt\]{
784
+ width: 16pt;
785
+ height: 16pt;
786
+ }
780
787
  .size-\[30px\]{
781
788
  width: 30px;
782
789
  height: 30px;
@@ -789,6 +796,9 @@ input[type=number] {
789
796
  width: 100%;
790
797
  height: 100%;
791
798
  }
799
+ .h-1\/2{
800
+ height: 50%;
801
+ }
792
802
  .h-10{
793
803
  height: 2.5rem;
794
804
  }
@@ -859,6 +869,9 @@ input[type=number] {
859
869
  .max-h-screen{
860
870
  max-height: 100vh;
861
871
  }
872
+ .min-h-10{
873
+ min-height: 2.5rem;
874
+ }
862
875
  .w-1\/2{
863
876
  width: 50%;
864
877
  }
@@ -1132,6 +1145,9 @@ input[type=number] {
1132
1145
  text-overflow: ellipsis;
1133
1146
  white-space: nowrap;
1134
1147
  }
1148
+ .text-ellipsis{
1149
+ text-overflow: ellipsis;
1150
+ }
1135
1151
  .rounded{
1136
1152
  border-radius: 0.25rem;
1137
1153
  }
@@ -2719,6 +2735,9 @@ input[type=number] {
2719
2735
  .fill-primary-default{
2720
2736
  fill: color-mix(in srgb, var(--state-color-primary-default) calc(100% * 1), transparent);
2721
2737
  }
2738
+ .fill-warning{
2739
+ fill: color-mix(in srgb, var(--state-color-warning-default) calc(100% * 1), transparent);
2740
+ }
2722
2741
  .stroke-input-default-stroke{
2723
2742
  stroke: color-mix(in srgb, var(--input-color-default-stroke) calc(100% * 1), transparent);
2724
2743
  }
@@ -4974,8 +4993,8 @@ input[type=number] {
4974
4993
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
4975
4994
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
4976
4995
  }
4977
- .group:disabled .group-disabled\:bg-\[--switch-thumb-disabled-color\]{
4978
- background-color: var(--switch-thumb-disabled-color);
4996
+ .group:disabled .group-disabled\:\!bg-\[--switch-thumb-disabled-color\]{
4997
+ background-color: var(--switch-thumb-disabled-color) !important;
4979
4998
  }
4980
4999
  .peer:-moz-placeholder-shown ~ .peer-placeholder-shown\:top-2{
4981
5000
  top: 0.5rem;
@@ -5237,8 +5256,8 @@ input[type=number] {
5237
5256
  .data-\[disabled\]\:\!bg-\[var\(--dropdown-menu-disabled-bg\)\][data-disabled]{
5238
5257
  background-color: var(--dropdown-menu-disabled-bg) !important;
5239
5258
  }
5240
- .data-\[disabled\]\:bg-\[var\(--switch-disabled-color\)\][data-disabled]{
5241
- background-color: var(--switch-disabled-color);
5259
+ .data-\[disabled\]\:\!bg-\[var\(--switch-disabled-color\)\][data-disabled]{
5260
+ background-color: var(--switch-disabled-color) !important;
5242
5261
  }
5243
5262
  .data-\[loading\=true\]\:bg-button-error-flat-active[data-loading=true]{
5244
5263
  --tw-bg-opacity: 1;