@thecb/components 9.4.0-beta.0 → 9.5.0-beta.0
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/index.cjs.js +244 -168
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +244 -168
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/atoms/searchable-select/SearchableSelect.js +14 -20
- package/src/components/atoms/searchable-select/SearchableSelect.stories.js +2 -2
- package/src/components/molecules/radio-section/InnerRadioSection.js +207 -0
- package/src/components/molecules/radio-section/InnerRadioSection.theme.js +15 -0
- package/src/components/molecules/radio-section/RadioSection.js +78 -204
- package/src/components/molecules/radio-section/RadioSection.stories.js +85 -15
package/package.json
CHANGED
|
@@ -38,7 +38,6 @@ const SearchableSelect = ({
|
|
|
38
38
|
selectItem(value);
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
-
|
|
42
41
|
return (
|
|
43
42
|
<Box
|
|
44
43
|
padding="1rem"
|
|
@@ -61,25 +60,20 @@ const SearchableSelect = ({
|
|
|
61
60
|
extraStyles={`overflow-y: scroll; max-height: 250px;`}
|
|
62
61
|
>
|
|
63
62
|
<Stack>
|
|
64
|
-
{itemList
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
textExtraStyles={`margin: 0;`}
|
|
79
|
-
disabled={disabled}
|
|
80
|
-
extraStyles={`margin: 0.5rem;`}
|
|
81
|
-
/>
|
|
82
|
-
))}
|
|
63
|
+
{itemList.map(value => (
|
|
64
|
+
<Checkbox
|
|
65
|
+
key={value.name}
|
|
66
|
+
title={value.name}
|
|
67
|
+
name={value.name}
|
|
68
|
+
checked={
|
|
69
|
+
selectedItems?.find(item => item?.name === value?.name) ?? false
|
|
70
|
+
}
|
|
71
|
+
onChange={() => handleSelect(value)}
|
|
72
|
+
textExtraStyles={`margin: 0;`}
|
|
73
|
+
disabled={disabled}
|
|
74
|
+
extraStyles={`margin: 0.5rem;`}
|
|
75
|
+
/>
|
|
76
|
+
))}
|
|
83
77
|
</Stack>
|
|
84
78
|
</Box>
|
|
85
79
|
</Box>
|
|
@@ -14,8 +14,8 @@ const { mapStateToProps, mapDispatchToProps, reducer } = createFormState({
|
|
|
14
14
|
|
|
15
15
|
const items = [
|
|
16
16
|
{ name: "Foo", value: "foo-value" },
|
|
17
|
-
{ name: "
|
|
18
|
-
{ name: "
|
|
17
|
+
{ name: "Bar", value: "bar-value" },
|
|
18
|
+
{ name: "Baz", value: "baz-value" }
|
|
19
19
|
];
|
|
20
20
|
|
|
21
21
|
const FormWrapper = props => {
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import React, { Fragment } from "react";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
import { themeComponent } from "../../../util/themeUtils";
|
|
4
|
+
import { fallbackValues } from "./InnerRadioSection.theme";
|
|
5
|
+
import { AnimatePresence } from "framer-motion";
|
|
6
|
+
import RadioButton from "./radio-button/RadioButton";
|
|
7
|
+
import { Box, Cluster, Stack, Motion } from "../../atoms/layouts";
|
|
8
|
+
import { createIdFromString, noop } from "../../../util/general";
|
|
9
|
+
import Text from "../../atoms/text";
|
|
10
|
+
import { CHARADE_GREY } from "../../../constants/colors";
|
|
11
|
+
|
|
12
|
+
const idString = section =>
|
|
13
|
+
typeof section.title === "string"
|
|
14
|
+
? createIdFromString(section.title)
|
|
15
|
+
: section.id;
|
|
16
|
+
|
|
17
|
+
const InnerRadioSection = ({
|
|
18
|
+
themeValues,
|
|
19
|
+
isMobile,
|
|
20
|
+
supportsTouch,
|
|
21
|
+
section,
|
|
22
|
+
sectionIndex,
|
|
23
|
+
openSection = "",
|
|
24
|
+
toggleOpenSection,
|
|
25
|
+
staggeredAnimation = false,
|
|
26
|
+
initiallyOpen = true,
|
|
27
|
+
openHeight = "auto",
|
|
28
|
+
ariaDescribedBy,
|
|
29
|
+
focused,
|
|
30
|
+
setFocused,
|
|
31
|
+
sectionRefs,
|
|
32
|
+
ariaLabelledBy,
|
|
33
|
+
onKeyDown = noop
|
|
34
|
+
}) => {
|
|
35
|
+
const wrapper = {
|
|
36
|
+
open: {
|
|
37
|
+
height: openHeight,
|
|
38
|
+
opacity: 1,
|
|
39
|
+
transition: {
|
|
40
|
+
duration: 0.3,
|
|
41
|
+
ease: [0.04, 0.62, 0.23, 0.98],
|
|
42
|
+
staggerChildren: staggeredAnimation ? 0.15 : 0
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
closed: {
|
|
46
|
+
height: 0,
|
|
47
|
+
opacity: 0,
|
|
48
|
+
transition: {
|
|
49
|
+
duration: 0.3,
|
|
50
|
+
ease: [0.04, 0.62, 0.23, 0.98],
|
|
51
|
+
staggerChildren: staggeredAnimation ? 0.15 : 0,
|
|
52
|
+
staggerDirection: -1
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const borderStyles = `
|
|
58
|
+
border-width: 0 0 1px 0;
|
|
59
|
+
border-color: ${themeValues.borderColor};
|
|
60
|
+
border-style: solid;
|
|
61
|
+
border-radius: 0px;
|
|
62
|
+
transform-origin: 100% 0;
|
|
63
|
+
|
|
64
|
+
&:last-child {
|
|
65
|
+
border-width: 0;
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
const RightIcon = styled.img`
|
|
70
|
+
height: ${({ isMobile }) => (isMobile ? "14px" : "18px")};
|
|
71
|
+
width: ${({ isMobile }) => (isMobile ? "22px" : "28px")};
|
|
72
|
+
${({ fade }) => fade && "opacity: 0.4;"}
|
|
73
|
+
transition: opacity 0.3s ease;
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Motion
|
|
78
|
+
tabIndex={section.hideRadioButton || section.disabled ? "-1" : "0"}
|
|
79
|
+
ref={sectionRefs.current[sectionIndex]}
|
|
80
|
+
onBlur={() => !section.disabled && setFocused(null)}
|
|
81
|
+
onFocus={() => !section.disabled && setFocused(section.id)}
|
|
82
|
+
onKeyDown={onKeyDown}
|
|
83
|
+
hoverStyles={themeValues.focusStyles}
|
|
84
|
+
animate={openSection === section.id ? "open" : "closed"}
|
|
85
|
+
initial={initiallyOpen ? "open" : "closed"}
|
|
86
|
+
key={`item-${section.id}`}
|
|
87
|
+
extraStyles={borderStyles}
|
|
88
|
+
role="radio"
|
|
89
|
+
aria-checked={openSection === section.id}
|
|
90
|
+
aria-disabled={section.disabled}
|
|
91
|
+
aria-required={section.required}
|
|
92
|
+
aria-labelledby={ariaLabelledBy}
|
|
93
|
+
aria-describedby={ariaDescribedBy}
|
|
94
|
+
>
|
|
95
|
+
<Stack childGap="0">
|
|
96
|
+
<Box
|
|
97
|
+
padding={section.hideRadioButton ? "1.5rem" : "1.25rem 1.5rem"}
|
|
98
|
+
background={
|
|
99
|
+
section.disabled
|
|
100
|
+
? themeValues.headingDisabledColor
|
|
101
|
+
: themeValues.headingBackgroundColor
|
|
102
|
+
}
|
|
103
|
+
onClick={
|
|
104
|
+
(isMobile && supportsTouch) || section.disabled
|
|
105
|
+
? noop
|
|
106
|
+
: () => toggleOpenSection(section.id)
|
|
107
|
+
}
|
|
108
|
+
onTouchEnd={
|
|
109
|
+
isMobile && supportsTouch && !section.disabled
|
|
110
|
+
? () => toggleOpenSection(section.id)
|
|
111
|
+
: noop
|
|
112
|
+
}
|
|
113
|
+
key={`header-${section.id}`}
|
|
114
|
+
borderSize="0px"
|
|
115
|
+
borderColor={themeValues.borderColor}
|
|
116
|
+
borderWidthOverride={
|
|
117
|
+
openSection === section.id && !!section.content
|
|
118
|
+
? `0px 0px 1px 0px`
|
|
119
|
+
: ``
|
|
120
|
+
}
|
|
121
|
+
extraStyles={!section.disabled ? "cursor: pointer;" : ""}
|
|
122
|
+
dataQa={section.dataQa ? section.dataQa : section.id}
|
|
123
|
+
>
|
|
124
|
+
<Cluster justify="space-between" align="center" childGap="1px" nowrap>
|
|
125
|
+
<Cluster justify="flex-start" align="center" nowrap>
|
|
126
|
+
{!section.hideRadioButton && (
|
|
127
|
+
<Box padding="0">
|
|
128
|
+
<RadioButton
|
|
129
|
+
id={`radio-input-${idString(section)}`}
|
|
130
|
+
name={idString(section)}
|
|
131
|
+
ariaDescribedBy={ariaDescribedBy}
|
|
132
|
+
radioOn={openSection === section.id}
|
|
133
|
+
radioFocused={focused === section.id}
|
|
134
|
+
toggleRadio={
|
|
135
|
+
section.disabled
|
|
136
|
+
? noop
|
|
137
|
+
: () => toggleOpenSection(section.id)
|
|
138
|
+
}
|
|
139
|
+
tabIndex="-1"
|
|
140
|
+
isRequired={section.required}
|
|
141
|
+
/>
|
|
142
|
+
</Box>
|
|
143
|
+
)}
|
|
144
|
+
{section.titleIcon && (
|
|
145
|
+
<Cluster align="center">{section.titleIcon}</Cluster>
|
|
146
|
+
)}
|
|
147
|
+
<Box padding={section.titleIcon ? "0 0 0 8px" : "0"}>
|
|
148
|
+
<Text
|
|
149
|
+
as="label"
|
|
150
|
+
htmlFor={`radio-input-${idString(section)}`}
|
|
151
|
+
color={CHARADE_GREY}
|
|
152
|
+
>
|
|
153
|
+
{section.title}
|
|
154
|
+
</Text>
|
|
155
|
+
</Box>
|
|
156
|
+
</Cluster>
|
|
157
|
+
{section.rightIcons && (
|
|
158
|
+
<Cluster
|
|
159
|
+
id={`right-icons-${idString(section)}`}
|
|
160
|
+
childGap="0.5rem"
|
|
161
|
+
aria-label={section.rightIconsLabel || null}
|
|
162
|
+
role={section.rightIconsRole || null}
|
|
163
|
+
>
|
|
164
|
+
{section.rightIcons.map(icon => (
|
|
165
|
+
<RightIcon
|
|
166
|
+
src={icon.img}
|
|
167
|
+
key={icon.img}
|
|
168
|
+
fade={!icon.enabled}
|
|
169
|
+
isMobile={isMobile}
|
|
170
|
+
alt={icon.altText}
|
|
171
|
+
aria-disabled={!icon.enabled}
|
|
172
|
+
/>
|
|
173
|
+
))}
|
|
174
|
+
</Cluster>
|
|
175
|
+
)}
|
|
176
|
+
{section.rightTitleContent && (
|
|
177
|
+
<Fragment>{section.rightTitleContent}</Fragment>
|
|
178
|
+
)}
|
|
179
|
+
</Cluster>
|
|
180
|
+
</Box>
|
|
181
|
+
<AnimatePresence initial={false}>
|
|
182
|
+
{openSection === section.id && (
|
|
183
|
+
<Motion
|
|
184
|
+
key={`content-${section.id}`}
|
|
185
|
+
padding="0"
|
|
186
|
+
background={themeValues.bodyBackgroundColor}
|
|
187
|
+
layoutTransition
|
|
188
|
+
initial="closed"
|
|
189
|
+
animate="open"
|
|
190
|
+
exit="closed"
|
|
191
|
+
variants={wrapper}
|
|
192
|
+
extraStyles={`transform-origin: 100% 0;`}
|
|
193
|
+
>
|
|
194
|
+
{section.content}
|
|
195
|
+
</Motion>
|
|
196
|
+
)}
|
|
197
|
+
</AnimatePresence>
|
|
198
|
+
</Stack>
|
|
199
|
+
</Motion>
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export default themeComponent(
|
|
204
|
+
InnerRadioSection,
|
|
205
|
+
"InnerRadioSection",
|
|
206
|
+
fallbackValues
|
|
207
|
+
);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { WHITE, GREY_CHATEAU, ATHENS_GREY } from "../../../constants/colors";
|
|
2
|
+
|
|
3
|
+
const headingBackgroundColor = `${WHITE}`;
|
|
4
|
+
const headingDisabledColor = `${ATHENS_GREY}`;
|
|
5
|
+
const bodyBackgroundColor = "#eeeeee";
|
|
6
|
+
const borderColor = `${GREY_CHATEAU}`;
|
|
7
|
+
const focusStyles = `outline: none;`;
|
|
8
|
+
|
|
9
|
+
export const fallbackValues = {
|
|
10
|
+
headingBackgroundColor,
|
|
11
|
+
headingDisabledColor,
|
|
12
|
+
bodyBackgroundColor,
|
|
13
|
+
borderColor,
|
|
14
|
+
focusStyles
|
|
15
|
+
};
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import React, { createRef, Fragment, useRef, useState } from "react";
|
|
2
|
-
import styled from "styled-components";
|
|
3
2
|
import { themeComponent } from "../../../util/themeUtils";
|
|
4
3
|
import { fallbackValues } from "./RadioSection.theme";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import Text from "../../atoms/text";
|
|
10
|
-
import { CHARADE_GREY } from "../../../constants/colors";
|
|
4
|
+
import SolidDivider from "../../atoms/solid-divider/SolidDivider";
|
|
5
|
+
import { Box, Stack } from "../../atoms/layouts";
|
|
6
|
+
import { createIdFromString, wrapIndex } from "../../../util/general";
|
|
7
|
+
import { MANATEE_GREY } from "../../../constants/colors";
|
|
11
8
|
import {
|
|
12
9
|
ARROW_DOWN,
|
|
13
10
|
ARROW_LEFT,
|
|
@@ -16,27 +13,29 @@ import {
|
|
|
16
13
|
ENTER,
|
|
17
14
|
SPACEBAR
|
|
18
15
|
} from "../../../constants/keyboard";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
16
|
+
import InnerRadioSection from "./InnerRadioSection";
|
|
17
|
+
/**
|
|
18
|
+
- The RadioSection component takes either a flat array (via the 'sections'
|
|
19
|
+
prop) of section objects or a multidimensional array (via the 'groupedSections' prop) of section objects. Note that if using a multidimensional array, the nesting cannot exceed 2 levels deep.
|
|
20
|
+
- Each 'section' object should look like:
|
|
21
|
+
{
|
|
22
|
+
title: <React Component(s)>,
|
|
23
|
+
id: <String> "identifier of section",
|
|
24
|
+
disabled: boolean, (displays section and grayed out radio but disables interaction)
|
|
25
|
+
hideRadioButton: boolean, (keeps section displayed but hides radio and disables open/close function),
|
|
26
|
+
hidden: boolean, (hides section entirely)
|
|
27
|
+
dataQa: string,
|
|
28
|
+
content: <React Component(s)> e.g.: <Box><Stack>cool content stuff</Stack></Box> (any collection of components will work),
|
|
29
|
+
rightTitleContent: <React Component(s)> (rendered on the very right of the title section, use to supplement "rightIcons" with text, as in expired CC status, or render other custom content)
|
|
30
|
+
}
|
|
31
|
+
- It also takes an "openSection" which should equal the id of the section that
|
|
32
|
+
should be open, along with "toggleOpenSection"
|
|
33
|
+
- RadioSection will call "toggleOpenSection" with the id of the section
|
|
34
|
+
that it is in.
|
|
35
|
+
- It is up to the engineer to store the open section value in state up from the
|
|
36
|
+
component using a useState() hook or a reducer.
|
|
37
|
+
- The section itself comes with some motion to open/close. To add more motion
|
|
38
|
+
to the content, wrap your content with a Motion layout primitive and provide appropriate props.
|
|
40
39
|
*/
|
|
41
40
|
|
|
42
41
|
const idString = section =>
|
|
@@ -57,9 +56,11 @@ const RadioSection = ({
|
|
|
57
56
|
containerStyles = "",
|
|
58
57
|
ariaDescribedBy,
|
|
59
58
|
isSectionRequired = false,
|
|
59
|
+
groupedSections,
|
|
60
60
|
...rest
|
|
61
61
|
}) => {
|
|
62
62
|
const [focused, setFocused] = useState(null);
|
|
63
|
+
|
|
63
64
|
const sectionRefs = useRef(
|
|
64
65
|
[...Array(sections.length)].map(() => createRef())
|
|
65
66
|
);
|
|
@@ -93,47 +94,6 @@ const RadioSection = ({
|
|
|
93
94
|
}
|
|
94
95
|
};
|
|
95
96
|
|
|
96
|
-
const wrapper = {
|
|
97
|
-
open: {
|
|
98
|
-
height: openHeight,
|
|
99
|
-
opacity: 1,
|
|
100
|
-
transition: {
|
|
101
|
-
duration: 0.3,
|
|
102
|
-
ease: [0.04, 0.62, 0.23, 0.98],
|
|
103
|
-
staggerChildren: staggeredAnimation ? 0.15 : 0
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
closed: {
|
|
107
|
-
height: 0,
|
|
108
|
-
opacity: 0,
|
|
109
|
-
transition: {
|
|
110
|
-
duration: 0.3,
|
|
111
|
-
ease: [0.04, 0.62, 0.23, 0.98],
|
|
112
|
-
staggerChildren: staggeredAnimation ? 0.15 : 0,
|
|
113
|
-
staggerDirection: -1
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const borderStyles = `
|
|
119
|
-
border-width: 0 0 1px 0;
|
|
120
|
-
border-color: ${themeValues.borderColor};
|
|
121
|
-
border-style: solid;
|
|
122
|
-
border-radius: 0px;
|
|
123
|
-
transform-origin: 100% 0;
|
|
124
|
-
|
|
125
|
-
&:last-child {
|
|
126
|
-
border-width: 0;
|
|
127
|
-
}
|
|
128
|
-
`;
|
|
129
|
-
|
|
130
|
-
const RightIcon = styled.img`
|
|
131
|
-
height: ${({ isMobile }) => (isMobile ? "14px" : "18px")};
|
|
132
|
-
width: ${({ isMobile }) => (isMobile ? "22px" : "28px")};
|
|
133
|
-
${({ fade }) => fade && "opacity: 0.4;"}
|
|
134
|
-
transition: opacity 0.3s ease;
|
|
135
|
-
`;
|
|
136
|
-
|
|
137
97
|
return (
|
|
138
98
|
<Box
|
|
139
99
|
padding="1px"
|
|
@@ -147,144 +107,58 @@ const RadioSection = ({
|
|
|
147
107
|
aria-required={isSectionRequired}
|
|
148
108
|
{...rest}
|
|
149
109
|
>
|
|
150
|
-
{sections
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
key={`item-${section.id}`}
|
|
167
|
-
extraStyles={borderStyles}
|
|
168
|
-
role="radio"
|
|
169
|
-
aria-checked={openSection === section.id}
|
|
170
|
-
aria-disabled={section.disabled}
|
|
171
|
-
aria-required={section.required}
|
|
172
|
-
aria-labelledby={section.id}
|
|
173
|
-
aria-describedby={`right-icons-${idString(section)}`}
|
|
174
|
-
>
|
|
175
|
-
<Stack childGap="0">
|
|
176
|
-
<Box
|
|
177
|
-
padding={
|
|
178
|
-
section.hideRadioButton ? "1.5rem" : "1.25rem 1.5rem"
|
|
179
|
-
}
|
|
180
|
-
background={
|
|
181
|
-
section.disabled
|
|
182
|
-
? themeValues.headingDisabledColor
|
|
183
|
-
: themeValues.headingBackgroundColor
|
|
110
|
+
{!!sections &&
|
|
111
|
+
sections
|
|
112
|
+
.filter(section => !section.hidden)
|
|
113
|
+
.map((section, i) => (
|
|
114
|
+
<Fragment key={`radio-section-${sections.indexOf(section)}`}>
|
|
115
|
+
<InnerRadioSection
|
|
116
|
+
sectionIndex={i}
|
|
117
|
+
section={section}
|
|
118
|
+
sectionRefs={sectionRefs}
|
|
119
|
+
focused={focused}
|
|
120
|
+
setFocused={setFocused}
|
|
121
|
+
openHeight={openHeight}
|
|
122
|
+
openSection={openSection}
|
|
123
|
+
toggleOpenSection={toggleOpenSection}
|
|
124
|
+
onKeyDown={e =>
|
|
125
|
+
!section.disabled && handleKeyDown(section.id, e, i)
|
|
184
126
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
openSection === section.id && !!section.content
|
|
200
|
-
? `0px 0px 1px 0px`
|
|
201
|
-
: ``
|
|
202
|
-
}
|
|
203
|
-
extraStyles={!section.disabled ? "cursor: pointer;" : ""}
|
|
204
|
-
dataQa={section.dataQa ? section.dataQa : section.id}
|
|
127
|
+
ariaLabelledBy={section.id}
|
|
128
|
+
ariaDescribedBy={`right-icons-${idString(section)}`}
|
|
129
|
+
/>
|
|
130
|
+
</Fragment>
|
|
131
|
+
))}
|
|
132
|
+
{!!groupedSections &&
|
|
133
|
+
groupedSections.map(sectionGroup =>
|
|
134
|
+
sectionGroup
|
|
135
|
+
.filter(unfilteredSection => !unfilteredSection.hidden)
|
|
136
|
+
.map((section, i) => (
|
|
137
|
+
<Fragment
|
|
138
|
+
key={`radio-section-${groupedSections.indexOf(
|
|
139
|
+
sectionGroup
|
|
140
|
+
)}-${sectionGroup.indexOf(section)}}`}
|
|
205
141
|
>
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
section.disabled
|
|
223
|
-
? noop
|
|
224
|
-
: () => toggleOpenSection(section.id)
|
|
225
|
-
}
|
|
226
|
-
tabIndex="-1"
|
|
227
|
-
isRequired={section.required}
|
|
228
|
-
/>
|
|
229
|
-
</Box>
|
|
230
|
-
)}
|
|
231
|
-
{section.titleIcon && (
|
|
232
|
-
<Cluster align="center">{section.titleIcon}</Cluster>
|
|
233
|
-
)}
|
|
234
|
-
<Box padding={section.titleIcon ? "0 0 0 8px" : "0"}>
|
|
235
|
-
<Text
|
|
236
|
-
as="label"
|
|
237
|
-
htmlFor={`radio-input-${idString(section)}`}
|
|
238
|
-
color={CHARADE_GREY}
|
|
239
|
-
>
|
|
240
|
-
{section.title}
|
|
241
|
-
</Text>
|
|
242
|
-
</Box>
|
|
243
|
-
</Cluster>
|
|
244
|
-
{section.rightIcons && (
|
|
245
|
-
<Cluster
|
|
246
|
-
id={`right-icons-${idString(section)}`}
|
|
247
|
-
childGap="0.5rem"
|
|
248
|
-
aria-label={section.rightIconsLabel || null}
|
|
249
|
-
role={section.rightIconsRole || null}
|
|
250
|
-
>
|
|
251
|
-
{section.rightIcons.map(icon => (
|
|
252
|
-
<RightIcon
|
|
253
|
-
src={icon.img}
|
|
254
|
-
key={icon.img}
|
|
255
|
-
fade={!icon.enabled}
|
|
256
|
-
isMobile={isMobile}
|
|
257
|
-
alt={icon.altText}
|
|
258
|
-
aria-disabled={!icon.enabled}
|
|
259
|
-
/>
|
|
260
|
-
))}
|
|
261
|
-
</Cluster>
|
|
262
|
-
)}
|
|
263
|
-
{section.rightTitleContent && (
|
|
264
|
-
<Fragment>{section.rightTitleContent}</Fragment>
|
|
142
|
+
<InnerRadioSection
|
|
143
|
+
sectionIndex={i}
|
|
144
|
+
section={section}
|
|
145
|
+
sectionRefs={sectionRefs}
|
|
146
|
+
focused={focused}
|
|
147
|
+
setFocused={setFocused}
|
|
148
|
+
openHeight={openHeight}
|
|
149
|
+
ariaLabelledBy={section.id}
|
|
150
|
+
ariaDescribedBy={`right-icons-${idString(section)}`}
|
|
151
|
+
openSection={openSection}
|
|
152
|
+
toggleOpenSection={toggleOpenSection}
|
|
153
|
+
/>
|
|
154
|
+
{sectionGroup.indexOf(section) === sectionGroup.length - 1 &&
|
|
155
|
+
groupedSections.indexOf(sectionGroup) !==
|
|
156
|
+
groupedSections.length - 1 && (
|
|
157
|
+
<SolidDivider borderSize="2px" color={MANATEE_GREY} />
|
|
265
158
|
)}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
{openSection === section.id && (
|
|
270
|
-
<Motion
|
|
271
|
-
key={`content-${section.id}`}
|
|
272
|
-
padding="0"
|
|
273
|
-
background={themeValues.bodyBackgroundColor}
|
|
274
|
-
layoutTransition
|
|
275
|
-
initial="closed"
|
|
276
|
-
animate="open"
|
|
277
|
-
exit="closed"
|
|
278
|
-
variants={wrapper}
|
|
279
|
-
extraStyles={`transform-origin: 100% 0;`}
|
|
280
|
-
>
|
|
281
|
-
{section.content}
|
|
282
|
-
</Motion>
|
|
283
|
-
)}
|
|
284
|
-
</AnimatePresence>
|
|
285
|
-
</Stack>
|
|
286
|
-
</Motion>
|
|
287
|
-
))}
|
|
159
|
+
</Fragment>
|
|
160
|
+
))
|
|
161
|
+
)}
|
|
288
162
|
</Stack>
|
|
289
163
|
</Box>
|
|
290
164
|
);
|