@uva-glass/component-library 2.5.0 → 2.5.1
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.
|
@@ -14,9 +14,11 @@ export interface CheckboxTreeProps {
|
|
|
14
14
|
checkboxTree: CheckboxBranch[];
|
|
15
15
|
/** Array of selected values. */
|
|
16
16
|
defaultValue?: string[];
|
|
17
|
+
/** `true` if the font-weight needs to be unset; otherwise, `false`. The default is `false`. */
|
|
18
|
+
noLabelFrontWeight?: boolean;
|
|
17
19
|
/** Returns array of selected values. */
|
|
18
20
|
onChange?: (value: string[]) => void;
|
|
19
21
|
}
|
|
20
22
|
/** Represents a component to render a tree of checkboxes. */
|
|
21
|
-
export declare const CheckboxTree: ({ title, checkboxTree, defaultValue, onChange }: CheckboxTreeProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export declare const CheckboxTree: ({ title, checkboxTree, defaultValue, noLabelFrontWeight, onChange, }: CheckboxTreeProps) => import("react/jsx-runtime").JSX.Element;
|
|
22
24
|
export {};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { jsxs as i, jsx as a } from "react/jsx-runtime";
|
|
2
|
-
import { useRef as
|
|
3
|
-
import { c as
|
|
4
|
-
import { Icon as
|
|
5
|
-
import { Button as
|
|
2
|
+
import { useRef as R, useEffect as N } from "react";
|
|
3
|
+
import { c as y } from "../../clsx-OuTLNxxd.js";
|
|
4
|
+
import { Icon as j } from "../Icon/Icon.js";
|
|
5
|
+
import { Button as I } from "../Buttons/Button.js";
|
|
6
6
|
import "../Buttons/LinkButton.js";
|
|
7
7
|
import "@react-aria/button";
|
|
8
|
-
import { Checkbox as
|
|
9
|
-
import { Label as
|
|
8
|
+
import { Checkbox as S } from "../Checkbox/Checkbox.js";
|
|
9
|
+
import { Label as C } from "../Label/Label.js";
|
|
10
10
|
import "@react-aria/dialog";
|
|
11
11
|
import "@react-aria/focus";
|
|
12
12
|
import "@react-aria/overlays";
|
|
13
13
|
import "../OverlayCloseButton/OverlayCloseButton.js";
|
|
14
|
-
import { FormField as
|
|
14
|
+
import { FormField as A } from "../FormField/FormField.js";
|
|
15
15
|
import "../GridRow/GridRow.js";
|
|
16
16
|
import "../IconButton/IconButton.js";
|
|
17
17
|
import "../Input/Input.js";
|
|
@@ -26,7 +26,7 @@ import "../SelectListbox/SelectListbox.js";
|
|
|
26
26
|
import "../SelectListbox/SelectProvider.js";
|
|
27
27
|
import "../Sortable/components/SortableItem.js";
|
|
28
28
|
import "../../SortableProvider-BUsvniX7.js";
|
|
29
|
-
import { useResponsive as
|
|
29
|
+
import { useResponsive as L } from "../hooks/useResponsive.js";
|
|
30
30
|
import '../../assets/CheckboxTree.css';const o = {
|
|
31
31
|
"checkbox-tree__header": "_checkbox-tree__header_xbe4e_1",
|
|
32
32
|
"checkbox-tree__branch": "_checkbox-tree__branch_xbe4e_8",
|
|
@@ -36,82 +36,88 @@ import '../../assets/CheckboxTree.css';const o = {
|
|
|
36
36
|
"checkbox-tree__leaves": "_checkbox-tree__leaves_xbe4e_39",
|
|
37
37
|
"checkbox-tree__leaves--expanded": "_checkbox-tree__leaves--expanded_xbe4e_48",
|
|
38
38
|
"checkbox-tree__leaf": "_checkbox-tree__leaf_xbe4e_52"
|
|
39
|
-
},
|
|
40
|
-
|
|
39
|
+
}, _e = ({
|
|
40
|
+
title: b,
|
|
41
|
+
checkboxTree: E,
|
|
42
|
+
defaultValue: l,
|
|
43
|
+
noLabelFrontWeight: x = !1,
|
|
44
|
+
onChange: m
|
|
45
|
+
}) => {
|
|
46
|
+
const s = R([]), { lessThan: n } = L(), _ = (r, e = document) => [].slice.call(e.querySelectorAll(r)), q = () => {
|
|
41
47
|
const r = s.current.reduce((e, t) => (t.name && t.checked && e.push(t.value), e), []);
|
|
42
|
-
|
|
43
|
-
},
|
|
48
|
+
m && m(r);
|
|
49
|
+
}, u = (r) => {
|
|
44
50
|
var e, t, d;
|
|
45
51
|
for (; r; ) {
|
|
46
|
-
const c = (t = (e = r.closest("[data-ul]")) == null ? void 0 : e.parentNode) == null ? void 0 : t.querySelector("input"),
|
|
52
|
+
const c = (t = (e = r.closest("[data-ul]")) == null ? void 0 : e.parentNode) == null ? void 0 : t.querySelector("input"), k = _(
|
|
47
53
|
"input",
|
|
48
54
|
(d = c == null ? void 0 : c.closest("[data-li]")) == null ? void 0 : d.querySelector("[data-ul]")
|
|
49
|
-
).reduce((
|
|
50
|
-
if (c && (c.checked = p, c.indeterminate = !p && p !==
|
|
55
|
+
).reduce((v, g) => (g.disabled || v.push(g.checked), v), []), p = k.every(Boolean), T = k.some(Boolean);
|
|
56
|
+
if (c && (c.checked = p, c.indeterminate = !p && p !== T), !c || r === c)
|
|
51
57
|
break;
|
|
52
58
|
r = c;
|
|
53
59
|
}
|
|
54
|
-
},
|
|
60
|
+
}, f = (r, e) => {
|
|
55
61
|
var d, c;
|
|
56
62
|
const t = e == null ? void 0 : e.querySelector("[data-ul]");
|
|
57
63
|
r.childNodes[0].classList.toggle(o["checkbox-tree__branch--icon--expanded"]), (c = e == null ? void 0 : e.closest("[data-li]")) == null || c.setAttribute(
|
|
58
64
|
"aria-expanded",
|
|
59
65
|
((d = e == null ? void 0 : e.closest("[data-li]")) == null ? void 0 : d.getAttribute("aria-expanded")) === "false" ? "true" : "false"
|
|
60
66
|
), t && t.classList.toggle(o["checkbox-tree__leaves--expanded"]);
|
|
61
|
-
},
|
|
67
|
+
}, F = (r) => {
|
|
62
68
|
var c;
|
|
63
69
|
const e = r.target;
|
|
64
70
|
if (!e || !e.parentNode || !e.parentNode.parentNode) return;
|
|
65
71
|
const t = e.parentNode.parentNode;
|
|
66
72
|
if (n.md && ((c = e.previousElementSibling) == null ? void 0 : c.tagName) === "BUTTON" && t.getAttribute("aria-expanded") === "false") {
|
|
67
|
-
r.preventDefault(),
|
|
73
|
+
r.preventDefault(), f(t.querySelector("button"), t);
|
|
68
74
|
return;
|
|
69
75
|
}
|
|
70
76
|
if (s.current.indexOf(e) === -1) return;
|
|
71
|
-
(e.parentNode.parentNode ? _("input", e.parentNode.parentNode) : []).forEach((h) => h.checked = h.disabled ? !1 : e.checked),
|
|
77
|
+
(e.parentNode.parentNode ? _("input", e.parentNode.parentNode) : []).forEach((h) => h.checked = h.disabled ? !1 : e.checked), u(e), q();
|
|
72
78
|
}, B = (r) => {
|
|
73
79
|
const e = r.target, t = e.closest("[data-li]");
|
|
74
|
-
|
|
80
|
+
f(e, t);
|
|
75
81
|
};
|
|
76
82
|
return N(() => {
|
|
77
83
|
s.current = _("input") || [];
|
|
78
84
|
}, []), N(() => {
|
|
79
85
|
l && s.current.forEach((r) => {
|
|
80
|
-
l.includes(r.value) && (r.checked = !0,
|
|
86
|
+
l.includes(r.value) && (r.checked = !0, u(r));
|
|
81
87
|
});
|
|
82
88
|
}, [l]), /* @__PURE__ */ i("div", { children: [
|
|
83
89
|
b && /* @__PURE__ */ a("span", { className: o["checkbox-tree__header"], children: b }),
|
|
84
|
-
/* @__PURE__ */ a("div", { onClick:
|
|
90
|
+
/* @__PURE__ */ a("div", { onClick: F, "data-ul": !0, role: "tree", tabIndex: 0, children: E.map(({ itemName: r, children: e }) => /* @__PURE__ */ i(
|
|
85
91
|
"div",
|
|
86
92
|
{
|
|
87
93
|
className: o["checkbox-tree__branch"],
|
|
88
94
|
"data-li": !0,
|
|
89
95
|
"aria-expanded": n.md ? "false" : "true",
|
|
90
96
|
children: [
|
|
91
|
-
/* @__PURE__ */ i(
|
|
92
|
-
/* @__PURE__ */ a(
|
|
93
|
-
|
|
97
|
+
/* @__PURE__ */ i(A, { inline: !0, className: o["checkbox-tree__branch--formfield"], children: [
|
|
98
|
+
/* @__PURE__ */ a(I, { variant: "blank", onClick: B, children: /* @__PURE__ */ a(
|
|
99
|
+
j,
|
|
94
100
|
{
|
|
95
101
|
name: "CheveronRight",
|
|
96
102
|
size: 16,
|
|
97
|
-
className:
|
|
103
|
+
className: y(o["checkbox-tree__branch--icon"], {
|
|
98
104
|
[o["checkbox-tree__branch--icon--expanded"]]: !n.md
|
|
99
105
|
})
|
|
100
106
|
}
|
|
101
107
|
) }),
|
|
102
|
-
/* @__PURE__ */ a(
|
|
103
|
-
/* @__PURE__ */ a(
|
|
108
|
+
/* @__PURE__ */ a(S, { id: r, disabled: e.every((t) => t.disabled) }),
|
|
109
|
+
/* @__PURE__ */ a(C, { htmlFor: r, noFontWeight: x, children: r })
|
|
104
110
|
] }),
|
|
105
111
|
/* @__PURE__ */ a(
|
|
106
112
|
"div",
|
|
107
113
|
{
|
|
108
|
-
className:
|
|
114
|
+
className: y(o["checkbox-tree__leaves"], {
|
|
109
115
|
[o["checkbox-tree__leaves--expanded"]]: !n.md
|
|
110
116
|
}),
|
|
111
117
|
"data-ul": !0,
|
|
112
|
-
children: e.map(({ itemName: t, itemValue: d, disabled: c }) => /* @__PURE__ */ a("div", { className: o["checkbox-tree__leaf"], "data-li": !0, children: /* @__PURE__ */ i(
|
|
113
|
-
/* @__PURE__ */ a(
|
|
114
|
-
/* @__PURE__ */ a(
|
|
118
|
+
children: e.map(({ itemName: t, itemValue: d, disabled: c }) => /* @__PURE__ */ a("div", { className: o["checkbox-tree__leaf"], "data-li": !0, children: /* @__PURE__ */ i(A, { inline: !0, className: o["checkbox-tree__branch--formfield"], children: [
|
|
119
|
+
/* @__PURE__ */ a(S, { id: t, name: t, value: d, disabled: c }),
|
|
120
|
+
/* @__PURE__ */ a(C, { htmlFor: t, noFontWeight: x, children: t })
|
|
115
121
|
] }) }, t))
|
|
116
122
|
}
|
|
117
123
|
)
|
|
@@ -122,6 +128,6 @@ import '../../assets/CheckboxTree.css';const o = {
|
|
|
122
128
|
] });
|
|
123
129
|
};
|
|
124
130
|
export {
|
|
125
|
-
|
|
131
|
+
_e as CheckboxTree
|
|
126
132
|
};
|
|
127
133
|
//# sourceMappingURL=CheckboxTree.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckboxTree.js","sources":["../../../src/components/CheckboxTree/CheckboxTree.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport clsx from 'clsx';\n\nimport type { MouseEventHandler } from 'react';\n\nimport styles from './CheckboxTree.module.css';\n\nimport { Button, Checkbox, FormField, Icon, Label } from 'components';\nimport { useResponsive } from 'components/hooks/useResponsive';\n\n// TODO: Currently the checkbox tree shows odd behavior when a disabled checkbox is checked. When deselecting the parent checkbox, the disabled checkbox is deselected, and will never be checked again. We'll leave this for now, until we run into a real world example where this is necessary.\n\ntype CheckboxLeaf = {\n itemName: string;\n itemValue: string;\n disabled?: boolean;\n};\n\ntype CheckboxBranch = {\n itemName: string;\n children: CheckboxLeaf[];\n};\n\nexport interface CheckboxTreeProps {\n /** The title of the component. */\n title?: string;\n /** Array of checkbox groups with a label and array of children (itemName, itemValue and disabled boolean). */\n checkboxTree: CheckboxBranch[];\n /** Array of selected values. */\n defaultValue?: string[];\n /** Returns array of selected values. */\n onChange?: (value: string[]) => void;\n}\n\n/** Represents a component to render a tree of checkboxes. */\nexport const CheckboxTree = ({ title, checkboxTree, defaultValue, onChange }: CheckboxTreeProps) => {\n const checkboxNodes = useRef<HTMLInputElement[]>([]);\n const { lessThan } = useResponsive();\n\n const nodeArray = (selector: string, parent = document) => [].slice.call(parent.querySelectorAll(selector));\n\n const setValue = () => {\n const values = checkboxNodes.current.reduce((values, checkbox) => {\n if (checkbox.name && checkbox.checked) {\n values.push(checkbox.value);\n }\n return values;\n }, [] as string[]);\n\n if (onChange) onChange(values);\n };\n\n const setCheckboxesState = (check: HTMLInputElement) => {\n while (check) {\n const parent = check.closest('[data-ul]')?.parentNode?.querySelector('input');\n const siblings: HTMLInputElement[] = nodeArray(\n 'input',\n parent?.closest('[data-li]')?.querySelector('[data-ul]') as Document | undefined\n );\n\n const checkStatus = siblings.reduce((status, check) => {\n if (!check.disabled) status.push(check.checked);\n return status;\n }, [] as boolean[]);\n\n const every = checkStatus.every(Boolean);\n const some = checkStatus.some(Boolean);\n\n if (parent) {\n parent.checked = every;\n parent.indeterminate = !every && every !== some;\n }\n\n if (!parent || check === parent) {\n break;\n }\n\n check = parent;\n }\n };\n\n const setExpandedAttributes = (trigger: HTMLButtonElement, container: Element | null) => {\n const children = container?.querySelector('[data-ul]');\n\n (trigger.childNodes[0] as Element).classList.toggle(styles['checkbox-tree__branch--icon--expanded']);\n container\n ?.closest('[data-li]')\n ?.setAttribute(\n 'aria-expanded',\n container?.closest('[data-li]')?.getAttribute('aria-expanded') === 'false' ? 'true' : 'false'\n );\n\n if (children) {\n children.classList.toggle(styles['checkbox-tree__leaves--expanded']);\n }\n };\n\n const handleChange: MouseEventHandler<HTMLDivElement> = (event) => {\n const check = event.target as HTMLInputElement;\n\n if (!check || !check.parentNode || !check.parentNode.parentNode) return;\n const parentCheckbox = check.parentNode.parentNode as HTMLElement;\n\n if (\n lessThan.md &&\n check.previousElementSibling?.tagName === 'BUTTON' &&\n parentCheckbox.getAttribute('aria-expanded') === 'false'\n ) {\n event.preventDefault();\n setExpandedAttributes(parentCheckbox.querySelector('button') as HTMLButtonElement, parentCheckbox);\n return;\n }\n\n if (checkboxNodes.current.indexOf(check) === -1) return;\n\n const children: HTMLInputElement[] = (check.parentNode.parentNode as Document)\n ? nodeArray('input', check.parentNode.parentNode as Document)\n : [];\n\n children.forEach((child) => {\n return (child.checked = child.disabled ? false : check.checked);\n });\n\n setCheckboxesState(check);\n setValue();\n };\n\n const handleExpanded: MouseEventHandler<HTMLButtonElement> = (event) => {\n const target = event.target as HTMLButtonElement;\n const parent = target.closest('[data-li]');\n setExpandedAttributes(target, parent);\n };\n\n useEffect(() => {\n checkboxNodes.current = nodeArray('input') || [];\n }, []);\n\n useEffect(() => {\n if (defaultValue) {\n checkboxNodes.current.forEach((checkbox) => {\n if (defaultValue.includes(checkbox.value)) {\n checkbox.checked = true;\n setCheckboxesState(checkbox);\n }\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [defaultValue]);\n\n return (\n <div>\n {title && <span className={styles['checkbox-tree__header']}>{title}</span>}\n {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */}\n <div onClick={handleChange} data-ul role=\"tree\" tabIndex={0}>\n {checkboxTree.map(({ itemName, children }) => (\n <div\n key={itemName}\n className={styles['checkbox-tree__branch']}\n data-li\n aria-expanded={lessThan.md ? 'false' : 'true'}\n >\n <FormField inline className={styles['checkbox-tree__branch--formfield']}>\n <Button variant=\"blank\" onClick={handleExpanded}>\n <Icon\n name=\"CheveronRight\"\n size={16}\n className={clsx(styles['checkbox-tree__branch--icon'], {\n [styles['checkbox-tree__branch--icon--expanded']]: !lessThan.md,\n })}\n />\n </Button>\n <Checkbox id={itemName} disabled={children.every((checkbox) => checkbox.disabled)} />\n <Label htmlFor={itemName}>{itemName}</Label>\n </FormField>\n <div\n className={clsx(styles['checkbox-tree__leaves'], {\n [styles['checkbox-tree__leaves--expanded']]: !lessThan.md,\n })}\n data-ul\n >\n {children.map(({ itemName, itemValue, disabled }) => (\n <div key={itemName} className={styles['checkbox-tree__leaf']} data-li>\n <FormField inline className={styles['checkbox-tree__branch--formfield']}>\n <Checkbox id={itemName} name={itemName} value={itemValue} disabled={disabled} />\n <Label htmlFor={itemName}>{itemName}</Label>\n </FormField>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n};\n"],"names":["CheckboxTree","title","checkboxTree","defaultValue","onChange","checkboxNodes","useRef","lessThan","useResponsive","nodeArray","selector","parent","setValue","values","checkbox","setCheckboxesState","check","_b","_a","checkStatus","_c","status","every","some","setExpandedAttributes","trigger","container","children","styles","handleChange","event","parentCheckbox","child","handleExpanded","target","useEffect","itemName","jsxs","FormField","jsx","Button","Icon","clsx","Checkbox","Label","itemValue","disabled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CheckboxTree.js","sources":["../../../src/components/CheckboxTree/CheckboxTree.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport clsx from 'clsx';\n\nimport type { MouseEventHandler } from 'react';\n\nimport styles from './CheckboxTree.module.css';\n\nimport { Button, Checkbox, FormField, Icon, Label } from 'components';\nimport { useResponsive } from 'components/hooks/useResponsive';\n\n// TODO: Currently the checkbox tree shows odd behavior when a disabled checkbox is checked. When deselecting the parent checkbox, the disabled checkbox is deselected, and will never be checked again. We'll leave this for now, until we run into a real world example where this is necessary.\n\ntype CheckboxLeaf = {\n itemName: string;\n itemValue: string;\n disabled?: boolean;\n};\n\ntype CheckboxBranch = {\n itemName: string;\n children: CheckboxLeaf[];\n};\n\nexport interface CheckboxTreeProps {\n /** The title of the component. */\n title?: string;\n /** Array of checkbox groups with a label and array of children (itemName, itemValue and disabled boolean). */\n checkboxTree: CheckboxBranch[];\n /** Array of selected values. */\n defaultValue?: string[];\n /** `true` if the font-weight needs to be unset; otherwise, `false`. The default is `false`. */\n noLabelFrontWeight?: boolean;\n /** Returns array of selected values. */\n onChange?: (value: string[]) => void;\n}\n\n/** Represents a component to render a tree of checkboxes. */\nexport const CheckboxTree = ({\n title,\n checkboxTree,\n defaultValue,\n noLabelFrontWeight = false,\n onChange,\n}: CheckboxTreeProps) => {\n const checkboxNodes = useRef<HTMLInputElement[]>([]);\n const { lessThan } = useResponsive();\n\n const nodeArray = (selector: string, parent = document) => [].slice.call(parent.querySelectorAll(selector));\n\n const setValue = () => {\n const values = checkboxNodes.current.reduce((values, checkbox) => {\n if (checkbox.name && checkbox.checked) {\n values.push(checkbox.value);\n }\n return values;\n }, [] as string[]);\n\n if (onChange) onChange(values);\n };\n\n const setCheckboxesState = (check: HTMLInputElement) => {\n while (check) {\n const parent = check.closest('[data-ul]')?.parentNode?.querySelector('input');\n const siblings: HTMLInputElement[] = nodeArray(\n 'input',\n parent?.closest('[data-li]')?.querySelector('[data-ul]') as Document | undefined\n );\n\n const checkStatus = siblings.reduce((status, check) => {\n if (!check.disabled) status.push(check.checked);\n return status;\n }, [] as boolean[]);\n\n const every = checkStatus.every(Boolean);\n const some = checkStatus.some(Boolean);\n\n if (parent) {\n parent.checked = every;\n parent.indeterminate = !every && every !== some;\n }\n\n if (!parent || check === parent) {\n break;\n }\n\n check = parent;\n }\n };\n\n const setExpandedAttributes = (trigger: HTMLButtonElement, container: Element | null) => {\n const children = container?.querySelector('[data-ul]');\n\n (trigger.childNodes[0] as Element).classList.toggle(styles['checkbox-tree__branch--icon--expanded']);\n container\n ?.closest('[data-li]')\n ?.setAttribute(\n 'aria-expanded',\n container?.closest('[data-li]')?.getAttribute('aria-expanded') === 'false' ? 'true' : 'false'\n );\n\n if (children) {\n children.classList.toggle(styles['checkbox-tree__leaves--expanded']);\n }\n };\n\n const handleChange: MouseEventHandler<HTMLDivElement> = (event) => {\n const check = event.target as HTMLInputElement;\n\n if (!check || !check.parentNode || !check.parentNode.parentNode) return;\n const parentCheckbox = check.parentNode.parentNode as HTMLElement;\n\n if (\n lessThan.md &&\n check.previousElementSibling?.tagName === 'BUTTON' &&\n parentCheckbox.getAttribute('aria-expanded') === 'false'\n ) {\n event.preventDefault();\n setExpandedAttributes(parentCheckbox.querySelector('button') as HTMLButtonElement, parentCheckbox);\n return;\n }\n\n if (checkboxNodes.current.indexOf(check) === -1) return;\n\n const children: HTMLInputElement[] = (check.parentNode.parentNode as Document)\n ? nodeArray('input', check.parentNode.parentNode as Document)\n : [];\n\n children.forEach((child) => {\n return (child.checked = child.disabled ? false : check.checked);\n });\n\n setCheckboxesState(check);\n setValue();\n };\n\n const handleExpanded: MouseEventHandler<HTMLButtonElement> = (event) => {\n const target = event.target as HTMLButtonElement;\n const parent = target.closest('[data-li]');\n setExpandedAttributes(target, parent);\n };\n\n useEffect(() => {\n checkboxNodes.current = nodeArray('input') || [];\n }, []);\n\n useEffect(() => {\n if (defaultValue) {\n checkboxNodes.current.forEach((checkbox) => {\n if (defaultValue.includes(checkbox.value)) {\n checkbox.checked = true;\n setCheckboxesState(checkbox);\n }\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [defaultValue]);\n\n return (\n <div>\n {title && <span className={styles['checkbox-tree__header']}>{title}</span>}\n {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */}\n <div onClick={handleChange} data-ul role=\"tree\" tabIndex={0}>\n {checkboxTree.map(({ itemName, children }) => (\n <div\n key={itemName}\n className={styles['checkbox-tree__branch']}\n data-li\n aria-expanded={lessThan.md ? 'false' : 'true'}\n >\n <FormField inline className={styles['checkbox-tree__branch--formfield']}>\n <Button variant=\"blank\" onClick={handleExpanded}>\n <Icon\n name=\"CheveronRight\"\n size={16}\n className={clsx(styles['checkbox-tree__branch--icon'], {\n [styles['checkbox-tree__branch--icon--expanded']]: !lessThan.md,\n })}\n />\n </Button>\n <Checkbox id={itemName} disabled={children.every((checkbox) => checkbox.disabled)} />\n <Label htmlFor={itemName} noFontWeight={noLabelFrontWeight}>\n {itemName}\n </Label>\n </FormField>\n <div\n className={clsx(styles['checkbox-tree__leaves'], {\n [styles['checkbox-tree__leaves--expanded']]: !lessThan.md,\n })}\n data-ul\n >\n {children.map(({ itemName, itemValue, disabled }) => (\n <div key={itemName} className={styles['checkbox-tree__leaf']} data-li>\n <FormField inline className={styles['checkbox-tree__branch--formfield']}>\n <Checkbox id={itemName} name={itemName} value={itemValue} disabled={disabled} />\n <Label htmlFor={itemName} noFontWeight={noLabelFrontWeight}>\n {itemName}\n </Label>\n </FormField>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n};\n"],"names":["CheckboxTree","title","checkboxTree","defaultValue","noLabelFrontWeight","onChange","checkboxNodes","useRef","lessThan","useResponsive","nodeArray","selector","parent","setValue","values","checkbox","setCheckboxesState","check","_b","_a","checkStatus","_c","status","every","some","setExpandedAttributes","trigger","container","children","styles","handleChange","event","parentCheckbox","child","handleExpanded","target","useEffect","itemName","jsxs","FormField","jsx","Button","Icon","clsx","Checkbox","Label","itemValue","disabled"],"mappings":"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"}
|