@luscii-healthtech/web-ui 2.4.1 → 2.5.2
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/components/CheckboxList/CheckboxGroup.d.ts +1 -1
- package/dist/components/CheckboxList/CheckboxList.types.d.ts +2 -0
- package/dist/components/List/List.d.ts +1 -0
- package/dist/components/List/List.types.d.ts +0 -3
- package/dist/web-ui.cjs.development.js +40 -30
- package/dist/web-ui.cjs.development.js.map +1 -1
- package/dist/web-ui.cjs.production.min.js +1 -1
- package/dist/web-ui.cjs.production.min.js.map +1 -1
- package/dist/web-ui.esm.js +40 -30
- package/dist/web-ui.esm.js.map +1 -1
- package/package.json +2 -1
- package/src/components/CheckboxList/CheckboxGroup.tsx +97 -58
- package/src/components/CheckboxList/CheckboxList.tsx +34 -17
- package/src/components/CheckboxList/CheckboxList.types.ts +27 -25
- package/src/components/List/List.scss +23 -0
- package/src/components/List/List.tsx +10 -6
- package/src/components/List/List.types.ts +0 -4
- package/src/components/Toaster/Toaster.scss +1 -1
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.5.2",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
"@fontsource/roboto": "^4.5.7",
|
|
104
104
|
"@hookform/error-message": "^2.0.0",
|
|
105
105
|
"@reach/router": "^1.3.4",
|
|
106
|
+
"@types/react-dragula": "^1.1.0",
|
|
106
107
|
"@typescript-eslint/eslint-plugin": "^5.29.0",
|
|
107
108
|
"classnames": "^2.3.1",
|
|
108
109
|
"clipboard": "^2.0.11",
|
|
@@ -1,82 +1,121 @@
|
|
|
1
1
|
import React, { useEffect, useState } from "react";
|
|
2
2
|
import classNames from "classnames";
|
|
3
3
|
|
|
4
|
-
|
|
5
4
|
import { Text } from "../Text/Text";
|
|
6
5
|
import { Checkbox } from "../..";
|
|
7
6
|
import { ChevronRightIcon } from "../Icons/ChevronRightIcon";
|
|
8
7
|
import { ChevronDownIcon } from "../Icons/ChevronDownIcon";
|
|
9
8
|
|
|
10
|
-
import {CheckboxGroupProps, CheckboxState } from "./CheckboxList.types";
|
|
9
|
+
import { CheckboxGroupProps, CheckboxState } from "./CheckboxList.types";
|
|
11
10
|
import { CheckboxListItem } from "./CheckboxListItem";
|
|
12
11
|
|
|
13
12
|
export const CheckboxGroup = ({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
title,
|
|
14
|
+
items,
|
|
15
|
+
onChange,
|
|
16
|
+
className,
|
|
17
|
+
isCollapsed = true,
|
|
18
|
+
}: CheckboxGroupProps): JSX.Element => {
|
|
19
|
+
const [groupCheckboxState, setGroupCheckboxState] = useState<CheckboxState>(
|
|
20
|
+
CheckboxState.UNCHECKED
|
|
21
|
+
);
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
const [collapsed, setCollapsed] = useState(isCollapsed);
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (items?.length > 0) {
|
|
27
|
+
const indeterminate = items.some(
|
|
28
|
+
(item) => item.isChecked !== items[0].isChecked
|
|
29
|
+
);
|
|
30
|
+
if (!indeterminate && items[0].isChecked) {
|
|
31
|
+
setGroupCheckboxState(CheckboxState.CHECKED);
|
|
32
|
+
} else if (!indeterminate && !items[0].isChecked) {
|
|
33
|
+
setGroupCheckboxState(CheckboxState.UNCHECKED);
|
|
34
|
+
} else {
|
|
35
|
+
setGroupCheckboxState(CheckboxState.INDETERMINATE);
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
setGroupCheckboxState(CheckboxState.UNCHECKED);
|
|
39
|
+
}
|
|
40
|
+
}, [items]);
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
const handleGroupClick = (
|
|
43
|
+
event:
|
|
44
|
+
| React.MouseEvent<HTMLDivElement>
|
|
45
|
+
| React.ChangeEvent<HTMLInputElement>
|
|
46
|
+
) => {
|
|
47
|
+
event.stopPropagation();
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
if (
|
|
50
|
+
(groupCheckboxState === CheckboxState.CHECKED ||
|
|
51
|
+
groupCheckboxState === CheckboxState.INDETERMINATE) &&
|
|
52
|
+
onChange
|
|
53
|
+
) {
|
|
54
|
+
//if checked or indeterminate >> make all items unchecked
|
|
55
|
+
items.forEach((item) =>
|
|
56
|
+
onChange({ id: item.id, newCheckedValue: false })
|
|
57
|
+
);
|
|
58
|
+
} else if (onChange) {
|
|
59
|
+
// else if unchecked >> make all items checked
|
|
60
|
+
items.forEach((item) => onChange({ id: item.id, newCheckedValue: true }));
|
|
61
|
+
}
|
|
62
|
+
};
|
|
50
63
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
const handleGroupCollapse = (
|
|
65
|
+
event:
|
|
66
|
+
| React.MouseEvent<HTMLDivElement>
|
|
67
|
+
| React.MouseEvent<SVGSVGElement>
|
|
68
|
+
| undefined
|
|
69
|
+
) => {
|
|
70
|
+
if (event) {
|
|
71
|
+
event.stopPropagation();
|
|
72
|
+
}
|
|
55
73
|
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
setCollapsed(!collapsed);
|
|
75
|
+
};
|
|
58
76
|
|
|
59
|
-
|
|
60
|
-
|
|
77
|
+
const checkedItemsCount = items?.filter((item) => item?.isChecked).length;
|
|
78
|
+
const groupTitle =
|
|
79
|
+
checkedItemsCount > 0 ? `${title} (${checkedItemsCount})` : title;
|
|
61
80
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
81
|
+
return (
|
|
82
|
+
<div className={classNames("flex flex-col", className)}>
|
|
83
|
+
{title && (
|
|
65
84
|
<div className={"flex flex-row my-1 items-center w-full space-between"}>
|
|
66
|
-
<div
|
|
67
|
-
|
|
68
|
-
|
|
85
|
+
<div
|
|
86
|
+
className={
|
|
87
|
+
"h-6 cursor-pointer mr-auto flex flex-row items-center text-slate-300 hover:text-slate-500 transition duration-300"
|
|
88
|
+
}
|
|
89
|
+
onClick={handleGroupCollapse}
|
|
90
|
+
>
|
|
91
|
+
{collapsed ? (
|
|
92
|
+
<ChevronRightIcon onClick={handleGroupCollapse} />
|
|
93
|
+
) : (
|
|
94
|
+
<ChevronDownIcon onClick={handleGroupCollapse} />
|
|
95
|
+
)}
|
|
96
|
+
<Text type={"strong"} text={groupTitle || ""} className={" ml-4"} />{" "}
|
|
97
|
+
:
|
|
69
98
|
</div>
|
|
70
|
-
<Checkbox
|
|
71
|
-
|
|
72
|
-
|
|
99
|
+
<Checkbox
|
|
100
|
+
onChange={handleGroupClick}
|
|
101
|
+
className={"ml-auto"}
|
|
102
|
+
isChecked={groupCheckboxState === CheckboxState.CHECKED}
|
|
103
|
+
isIndeterminate={groupCheckboxState === CheckboxState.INDETERMINATE}
|
|
104
|
+
/>
|
|
73
105
|
</div>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
{!collapsed &&
|
|
77
|
-
items.map((item) => (<CheckboxListItem key={item.id} id={item.id} label={item.label} onChange={onChange} isChecked={item.isChecked} className={"ml-10 my-1"}/>))
|
|
78
|
-
}
|
|
106
|
+
)}
|
|
79
107
|
|
|
80
|
-
|
|
81
|
-
|
|
108
|
+
{!collapsed &&
|
|
109
|
+
items.map((item) => (
|
|
110
|
+
<CheckboxListItem
|
|
111
|
+
key={item.id}
|
|
112
|
+
id={item.id}
|
|
113
|
+
label={item.label}
|
|
114
|
+
onChange={onChange}
|
|
115
|
+
isChecked={item.isChecked}
|
|
116
|
+
className={"ml-10 my-1"}
|
|
117
|
+
/>
|
|
118
|
+
))}
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
82
121
|
};
|
|
@@ -5,25 +5,42 @@ import { CheckboxListItem } from "./CheckboxListItem";
|
|
|
5
5
|
import { CheckboxListProps } from "./CheckboxList.types";
|
|
6
6
|
import { CheckboxGroup } from "./CheckboxGroup";
|
|
7
7
|
|
|
8
|
-
export {CheckboxListProps};
|
|
8
|
+
export { CheckboxListProps };
|
|
9
9
|
|
|
10
10
|
export const CheckboxList = ({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
groups,
|
|
12
|
+
onChange,
|
|
13
|
+
className,
|
|
14
|
+
}: CheckboxListProps): JSX.Element => {
|
|
15
|
+
return (
|
|
16
|
+
<div className={classNames("flex flex-col", className)}>
|
|
17
|
+
{groups?.length > 0 &&
|
|
18
|
+
groups.map((group) => {
|
|
19
|
+
if (group.title) {
|
|
20
|
+
return (
|
|
21
|
+
<CheckboxGroup
|
|
22
|
+
key={group.title}
|
|
23
|
+
items={group.items}
|
|
24
|
+
title={group.title}
|
|
25
|
+
isCollapsed={group.isCollapsed}
|
|
26
|
+
onChange={onChange}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
} else {
|
|
30
|
+
return group.items.map((item) => (
|
|
31
|
+
<CheckboxListItem
|
|
32
|
+
key={item.id}
|
|
33
|
+
id={item.id}
|
|
34
|
+
label={item.label}
|
|
35
|
+
onChange={onChange}
|
|
36
|
+
isChecked={item.isChecked}
|
|
37
|
+
className={"my-1"}
|
|
38
|
+
/>
|
|
39
|
+
));
|
|
40
|
+
}
|
|
41
|
+
})}
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
27
44
|
};
|
|
28
45
|
|
|
29
46
|
export default CheckboxList;
|
|
@@ -1,45 +1,47 @@
|
|
|
1
1
|
export enum CheckboxState {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
CHECKED = "checked",
|
|
3
|
+
INDETERMINATE = "indeterminate",
|
|
4
|
+
UNCHECKED = "unchecked",
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export interface CheckboxListProps {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
groups: CheckboxGroup[];
|
|
9
|
+
onChange: (event: CheckboxChangeEvent) => void;
|
|
10
|
+
className?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface CheckboxGroupProps {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
//If you don't specify a title than it will just be a non-collapsible list
|
|
15
|
+
title?: string;
|
|
16
|
+
items: CheckboxListItem[];
|
|
17
|
+
onChange: (event: CheckboxChangeEvent) => void;
|
|
18
|
+
className?: string;
|
|
19
|
+
isCollapsed?: boolean;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export interface CheckboxGroupItemProps {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
id: string;
|
|
24
|
+
label: string;
|
|
25
|
+
isChecked?: boolean;
|
|
26
|
+
onChange: (event: CheckboxChangeEvent) => void;
|
|
27
|
+
className?: string;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export interface CheckboxListItem {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
id: string;
|
|
32
|
+
label: string;
|
|
33
|
+
isChecked?: boolean;
|
|
34
|
+
className?: string;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export interface CheckboxGroup {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
//If you don't specify a title than it will just be a non-collapsible list
|
|
39
|
+
title?: string;
|
|
40
|
+
items: CheckboxListItem[];
|
|
41
|
+
isCollapsed?: boolean;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export interface CheckboxChangeEvent {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
id: string;
|
|
46
|
+
newCheckedValue: boolean;
|
|
45
47
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
li {
|
|
2
|
+
&.gu-mirror {
|
|
3
|
+
@apply shadow-xl m-0 fixed z-9999;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
&.gu-hide {
|
|
7
|
+
@apply hidden;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
&.gu-unselectable {
|
|
11
|
+
@apply select-none;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&.gu-transit {
|
|
15
|
+
@apply bg-blue-50;
|
|
16
|
+
@apply outline-dropTarget;
|
|
17
|
+
filter: none;
|
|
18
|
+
@apply opacity-100 rounded-none border-none; // TODO we only need these to override them in cVitals-Web
|
|
19
|
+
}
|
|
20
|
+
&.gu-transit > * {
|
|
21
|
+
@apply invisible;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -10,10 +10,11 @@ import {
|
|
|
10
10
|
ListProps,
|
|
11
11
|
ListItemProps,
|
|
12
12
|
OnAssetLoadErrorPayload,
|
|
13
|
-
Dragula,
|
|
14
13
|
} from "./List.types";
|
|
15
14
|
import { ListSkeleton } from "./ListSkeleton";
|
|
16
15
|
|
|
16
|
+
import "./List.scss";
|
|
17
|
+
|
|
17
18
|
export { ListProps, ListItemProps, OnAssetLoadErrorPayload };
|
|
18
19
|
|
|
19
20
|
export const List = ({
|
|
@@ -27,19 +28,19 @@ export const List = ({
|
|
|
27
28
|
isLoading,
|
|
28
29
|
}: ListProps): JSX.Element => {
|
|
29
30
|
const listRef = useRef<HTMLUListElement | null>(null);
|
|
30
|
-
const dragulaRef = useRef<
|
|
31
|
+
const dragulaRef = useRef<dragula.Drake | null>(null);
|
|
31
32
|
const hasHeader = !!(title || headerButton);
|
|
32
33
|
|
|
33
34
|
useEffect(() => {
|
|
34
35
|
dragulaRef.current?.destroy?.();
|
|
35
|
-
if (onDragEnd && items.length) {
|
|
36
|
+
if (listRef.current && onDragEnd && items.length) {
|
|
36
37
|
dragulaRef.current = setupDragging();
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
return () => {
|
|
40
41
|
dragulaRef.current?.destroy?.();
|
|
41
42
|
};
|
|
42
|
-
}, [items]);
|
|
43
|
+
}, [items, listRef]);
|
|
43
44
|
|
|
44
45
|
const handleDragEnd = (element: HTMLElement) => {
|
|
45
46
|
const draggedItemId = element.dataset["id"];
|
|
@@ -61,11 +62,14 @@ export const List = ({
|
|
|
61
62
|
}
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
const setupDragging = ():
|
|
65
|
+
const setupDragging = (): dragula.Drake | null => {
|
|
66
|
+
if (!listRef.current) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
65
69
|
const dragulaInstance = dragula([listRef.current], {
|
|
66
70
|
revertOnSpill: true,
|
|
67
71
|
});
|
|
68
|
-
dragulaInstance.on("dragend", handleDragEnd);
|
|
72
|
+
dragulaInstance.on("dragend", handleDragEnd as (Element) => void);
|
|
69
73
|
|
|
70
74
|
return dragulaInstance;
|
|
71
75
|
};
|