@thecb/components 6.1.0-beta.0 → 6.1.0-beta.4
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 +94 -26
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +94 -26
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/atoms/checkbox/Checkbox.theme.js +4 -3
- package/src/components/atoms/dropdown/Dropdown.js +12 -6
- package/src/components/atoms/form-layouts/FormInput.js +22 -4
- package/src/components/atoms/form-layouts/FormLayouts.theme.js +3 -3
- package/src/components/atoms/form-select/FormSelect.js +8 -2
- package/src/components/molecules/account-and-routing-modal/AccountAndRoutingModal.theme.js +1 -1
- package/src/components/molecules/modal/Modal.js +73 -57
- package/src/components/molecules/modal/Modal.stories.js +52 -3
- package/src/components/molecules/obligation/modules/AutopayModalModule.theme.js +1 -1
- package/src/components/molecules/periscope-dashboard-iframe/PeriscopeDashboardIframe.js +5 -2
- package/src/components/molecules/terms-and-conditions-modal/TermsAndConditionsModal.js +3 -1
- package/src/components/molecules/terms-and-conditions-modal/TermsAndConditionsModal.theme.js +1 -1
- package/src/constants/colors.js +3 -1
- package/src/util/focusFirstInvalidInputHook.js +20 -0
- package/src/util/general.js +45 -1
- package/src/util/index.js +2 -1
package/package.json
CHANGED
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
SEASHELL_WHITE,
|
|
6
6
|
MATISSE_BLUE,
|
|
7
7
|
RED,
|
|
8
|
-
CHARADE_GREY
|
|
8
|
+
CHARADE_GREY,
|
|
9
|
+
STORM_GREY
|
|
9
10
|
} from "../../../constants/colors";
|
|
10
11
|
|
|
11
12
|
const backgroundColor = { default: `${TRANSPARENT}` };
|
|
@@ -29,7 +30,7 @@ const disabledCheckedStyles = {
|
|
|
29
30
|
const disabledStyles = {
|
|
30
31
|
default: `
|
|
31
32
|
background: ${SEASHELL_WHITE};
|
|
32
|
-
border: 1px solid ${
|
|
33
|
+
border: 1px solid ${STORM_GREY};
|
|
33
34
|
`
|
|
34
35
|
};
|
|
35
36
|
const checkedStyles = {
|
|
@@ -41,7 +42,7 @@ const checkedStyles = {
|
|
|
41
42
|
const defaultStyles = {
|
|
42
43
|
default: `
|
|
43
44
|
background: ${WHITE};
|
|
44
|
-
border: 1px solid ${
|
|
45
|
+
border: 1px solid ${STORM_GREY};
|
|
45
46
|
`
|
|
46
47
|
};
|
|
47
48
|
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import React, { useEffect, Fragment, useState, useRef, createRef } from "react";
|
|
2
2
|
import { Box, Stack } from "../layouts";
|
|
3
3
|
import Text from "../text";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
noop,
|
|
6
|
+
inputDisabledStyle,
|
|
7
|
+
inputPlaceholderTextStyle
|
|
8
|
+
} from "../../../util/general";
|
|
5
9
|
import DropdownIcon from "./DropdownIcon";
|
|
6
10
|
import styled from "styled-components";
|
|
7
11
|
// support for Array.prototype.at() in older browsers
|
|
@@ -12,7 +16,8 @@ import {
|
|
|
12
16
|
GREY_CHATEAU,
|
|
13
17
|
STORM_GREY,
|
|
14
18
|
MINESHAFT_GREY,
|
|
15
|
-
ERROR_COLOR
|
|
19
|
+
ERROR_COLOR,
|
|
20
|
+
CHARADE_GREY
|
|
16
21
|
} from "../../../constants/colors";
|
|
17
22
|
import { fallbackValues } from "./Dropdown.theme";
|
|
18
23
|
import { themeComponent } from "../../../util/themeUtils";
|
|
@@ -98,6 +103,7 @@ const Dropdown = ({
|
|
|
98
103
|
hasTitles = false,
|
|
99
104
|
autoEraseTypeAhead = true,
|
|
100
105
|
ariaLabelledby,
|
|
106
|
+
ariaDescribedby,
|
|
101
107
|
autocompleteValue = "", // browser autofill value, like country-name or address-level1 for state
|
|
102
108
|
smoothScroll = true
|
|
103
109
|
}) => {
|
|
@@ -287,6 +293,7 @@ const Dropdown = ({
|
|
|
287
293
|
aria-owns={`${ariaLabelledby}_listbox`}
|
|
288
294
|
aria-haspopup="listbox"
|
|
289
295
|
aria-labelledby={ariaLabelledby}
|
|
296
|
+
aria-describedby={ariaDescribedby}
|
|
290
297
|
aria-expanded={isOpen}
|
|
291
298
|
autocomplete={autocompleteValue}
|
|
292
299
|
background={isOpen ? themeValues.hoverColor : WHITE}
|
|
@@ -300,10 +307,9 @@ const Dropdown = ({
|
|
|
300
307
|
: GREY_CHATEAU
|
|
301
308
|
}
|
|
302
309
|
extraStyles={
|
|
303
|
-
disabled
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
pointer-events: none;`
|
|
310
|
+
disabled
|
|
311
|
+
? `${inputPlaceholderTextStyle}${inputDisabledStyle}`
|
|
312
|
+
: inputPlaceholderTextStyle
|
|
307
313
|
}
|
|
308
314
|
hoverStyles={`background-color: ${themeValues.hoverColor};`}
|
|
309
315
|
isOpen={isOpen}
|
|
@@ -3,6 +3,7 @@ import styled, { ThemeContext, css } from "styled-components";
|
|
|
3
3
|
import { FormattedInput } from "formatted-input";
|
|
4
4
|
import { fallbackValues } from "./FormLayouts.theme.js";
|
|
5
5
|
import { themeComponent } from "../../../util/themeUtils";
|
|
6
|
+
import { createIdFromString } from "../../../util/general.js";
|
|
6
7
|
import Text from "../text";
|
|
7
8
|
import { Box, Cluster, Stack } from "../layouts";
|
|
8
9
|
import { FONT_WEIGHT_REGULAR } from "../../../constants/style_constants";
|
|
@@ -132,7 +133,7 @@ const FormInput = ({
|
|
|
132
133
|
&::first-letter {
|
|
133
134
|
text-transform: uppercase;
|
|
134
135
|
}`}
|
|
135
|
-
id={labelTextWhenNoError
|
|
136
|
+
id={createIdFromString(labelTextWhenNoError)}
|
|
136
137
|
>
|
|
137
138
|
{labelTextWhenNoError}
|
|
138
139
|
</Text>
|
|
@@ -157,7 +158,7 @@ const FormInput = ({
|
|
|
157
158
|
&::first-letter {
|
|
158
159
|
text-transform: uppercase;
|
|
159
160
|
}`}
|
|
160
|
-
id={labelTextWhenNoError
|
|
161
|
+
id={createIdFromString(labelTextWhenNoError)}
|
|
161
162
|
>
|
|
162
163
|
{labelTextWhenNoError}
|
|
163
164
|
</Text>
|
|
@@ -188,7 +189,15 @@ const FormInput = ({
|
|
|
188
189
|
<Box padding="0">
|
|
189
190
|
{formatter ? (
|
|
190
191
|
<FormattedInputField
|
|
191
|
-
aria-labelledby={labelTextWhenNoError
|
|
192
|
+
aria-labelledby={createIdFromString(labelTextWhenNoError)}
|
|
193
|
+
aria-describedby={createIdFromString(
|
|
194
|
+
labelTextWhenNoError,
|
|
195
|
+
"error message"
|
|
196
|
+
)}
|
|
197
|
+
aria-invalid={
|
|
198
|
+
(field.dirty && field.hasErrors) ||
|
|
199
|
+
(field.hasErrors && showErrors)
|
|
200
|
+
}
|
|
192
201
|
onChange={e => fieldActions.set(e)}
|
|
193
202
|
type={type}
|
|
194
203
|
value={field.rawValue}
|
|
@@ -205,7 +214,15 @@ const FormInput = ({
|
|
|
205
214
|
/>
|
|
206
215
|
) : (
|
|
207
216
|
<InputField
|
|
208
|
-
aria-labelledby={labelTextWhenNoError
|
|
217
|
+
aria-labelledby={createIdFromString(labelTextWhenNoError)}
|
|
218
|
+
aria-describedby={createIdFromString(
|
|
219
|
+
labelTextWhenNoError,
|
|
220
|
+
"error message"
|
|
221
|
+
)}
|
|
222
|
+
aria-invalid={
|
|
223
|
+
(field.dirty && field.hasErrors) ||
|
|
224
|
+
(field.hasErrors && showErrors)
|
|
225
|
+
}
|
|
209
226
|
onChange={e => fieldActions.set(e.target.value)}
|
|
210
227
|
type={type === "password" && showPassword ? "text" : type}
|
|
211
228
|
value={field.rawValue}
|
|
@@ -233,6 +250,7 @@ const FormInput = ({
|
|
|
233
250
|
&::first-letter {
|
|
234
251
|
text-transform: uppercase;
|
|
235
252
|
}`}
|
|
253
|
+
id={createIdFromString(labelTextWhenNoError, "error message")}
|
|
236
254
|
>
|
|
237
255
|
{errorMessages[field.errors[0]]}
|
|
238
256
|
</Text>
|
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
SEASHELL_WHITE,
|
|
6
6
|
MINESHAFT_GREY,
|
|
7
7
|
DUSTY_GREY,
|
|
8
|
-
GREY_CHATEAU,
|
|
9
8
|
ATHENS_GREY,
|
|
10
|
-
INFO_BLUE
|
|
9
|
+
INFO_BLUE,
|
|
10
|
+
STORM_GREY
|
|
11
11
|
} from "../../../constants/colors";
|
|
12
12
|
import { FONT_WEIGHT_REGULAR } from "../../../constants/style_constants";
|
|
13
13
|
|
|
@@ -25,7 +25,7 @@ const inputBackgroundColor = {
|
|
|
25
25
|
};
|
|
26
26
|
const color = { default: `${MINESHAFT_GREY}`, disabled: `${DUSTY_GREY}` };
|
|
27
27
|
const labelColor = { default: `${CHARADE_GREY}`, disabled: `${CHARADE_GREY}` };
|
|
28
|
-
const borderColor = { default: `${
|
|
28
|
+
const borderColor = { default: `${STORM_GREY}`, disabled: `${STORM_GREY}` };
|
|
29
29
|
const lineHeight = { default: "1rem", disabled: "1rem" };
|
|
30
30
|
const fontSize = { default: "0.875rem", disabled: "0.875rem" };
|
|
31
31
|
const errorFontSize = { default: "0.75rem", disabled: "0.75rem" };
|
|
@@ -6,6 +6,7 @@ import { SelectContainer } from "./FormSelect.styled";
|
|
|
6
6
|
import { fallbackValues } from "./FormSelect.theme";
|
|
7
7
|
import { themeComponent } from "../../../util/themeUtils";
|
|
8
8
|
import { Box, Cluster, Stack } from "../layouts";
|
|
9
|
+
import { createIdFromString } from "../../../util/general";
|
|
9
10
|
|
|
10
11
|
const FormSelect = ({
|
|
11
12
|
fieldActions,
|
|
@@ -53,14 +54,18 @@ const FormSelect = ({
|
|
|
53
54
|
&::first-letter {
|
|
54
55
|
text-transform: uppercase;
|
|
55
56
|
}`}
|
|
56
|
-
id={labelTextWhenNoError
|
|
57
|
+
id={createIdFromString(labelTextWhenNoError)}
|
|
57
58
|
>
|
|
58
59
|
{labelTextWhenNoError}
|
|
59
60
|
</Text>
|
|
60
61
|
</Cluster>
|
|
61
62
|
</Box>
|
|
62
63
|
<Dropdown
|
|
63
|
-
ariaLabelledby={labelTextWhenNoError
|
|
64
|
+
ariaLabelledby={createIdFromString(labelTextWhenNoError)}
|
|
65
|
+
ariaDescribedby={createIdFromString(
|
|
66
|
+
labelTextWhenNoError,
|
|
67
|
+
"error message"
|
|
68
|
+
)}
|
|
64
69
|
maxHeight={dropdownMaxHeight}
|
|
65
70
|
hasTitles={hasTitles}
|
|
66
71
|
placeholder={options[0] ? options[0].text : ""}
|
|
@@ -90,6 +95,7 @@ const FormSelect = ({
|
|
|
90
95
|
&::first-letter {
|
|
91
96
|
text-transform: uppercase;
|
|
92
97
|
}`}
|
|
98
|
+
id={createIdFromString(labelTextWhenNoError, "error message")}
|
|
93
99
|
>
|
|
94
100
|
{errorMessages[field.errors[0]]}
|
|
95
101
|
</Text>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FONT_WEIGHT_REGULAR } from "../../../constants/style_constants";
|
|
2
2
|
|
|
3
|
-
const linkColor = { default: "#
|
|
3
|
+
const linkColor = { default: "#3176AA" };
|
|
4
4
|
const fontSize = { default: "1rem" };
|
|
5
5
|
const lineHeight = { default: "1.5rem" };
|
|
6
6
|
const fontWeight = {
|
|
@@ -23,6 +23,7 @@ const getApplicationNode = () => document.getElementById("root");
|
|
|
23
23
|
const Modal = ({
|
|
24
24
|
hideModal,
|
|
25
25
|
continueAction,
|
|
26
|
+
isContinueActionDisabled = false,
|
|
26
27
|
cancelAction,
|
|
27
28
|
modalOpen,
|
|
28
29
|
modalHeaderText,
|
|
@@ -34,6 +35,7 @@ const Modal = ({
|
|
|
34
35
|
useDangerButton = false,
|
|
35
36
|
defaultWrapper = true,
|
|
36
37
|
onlyCloseButton = false,
|
|
38
|
+
noButtons = false, // for instances where modal is closed automatically
|
|
37
39
|
maxHeight,
|
|
38
40
|
underlayClickExits = true,
|
|
39
41
|
noBorder,
|
|
@@ -98,69 +100,83 @@ const Modal = ({
|
|
|
98
100
|
align="center"
|
|
99
101
|
childGap="0rem"
|
|
100
102
|
>
|
|
101
|
-
{!
|
|
102
|
-
|
|
103
|
-
{
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
103
|
+
{!noButtons && (
|
|
104
|
+
<>
|
|
105
|
+
{!onlyCloseButton ? (
|
|
106
|
+
<Fragment>
|
|
107
|
+
{isMobile ? (
|
|
108
|
+
<Stack childGap="1rem" direction="row">
|
|
109
|
+
<Box width="100%" padding="0">
|
|
110
|
+
<ButtonWithAction
|
|
111
|
+
variant="secondary"
|
|
112
|
+
action={
|
|
113
|
+
cancelAction ? cancelAction : hideModal
|
|
114
|
+
}
|
|
115
|
+
text={cancelButtonText}
|
|
116
|
+
dataQa={cancelButtonText}
|
|
117
|
+
extraStyles={buttonExtraStyles}
|
|
118
|
+
className="modal-cancel-button"
|
|
119
|
+
/>
|
|
120
|
+
</Box>
|
|
121
|
+
<Box width="100%" padding="0">
|
|
122
|
+
<ButtonWithAction
|
|
123
|
+
variant={
|
|
124
|
+
useDangerButton ? "danger" : "primary"
|
|
125
|
+
}
|
|
126
|
+
action={continueAction}
|
|
127
|
+
text={continueButtonText}
|
|
128
|
+
dataQa={continueButtonText}
|
|
129
|
+
isLoading={isLoading}
|
|
130
|
+
disabled={isContinueActionDisabled}
|
|
131
|
+
extraStyles={buttonExtraStyles}
|
|
132
|
+
className="modal-continue-button"
|
|
133
|
+
/>
|
|
134
|
+
</Box>
|
|
135
|
+
</Stack>
|
|
136
|
+
) : (
|
|
137
|
+
<Stack
|
|
138
|
+
childGap="1rem"
|
|
139
|
+
direction="row"
|
|
140
|
+
justify="flex-end"
|
|
141
|
+
>
|
|
142
|
+
<ButtonWithAction
|
|
143
|
+
variant="secondary"
|
|
144
|
+
action={
|
|
145
|
+
cancelAction ? cancelAction : hideModal
|
|
146
|
+
}
|
|
147
|
+
text={cancelButtonText}
|
|
148
|
+
dataQa={cancelButtonText}
|
|
149
|
+
extraStyles={buttonExtraStyles}
|
|
150
|
+
className="modal-cancel-button"
|
|
151
|
+
/>
|
|
152
|
+
<ButtonWithAction
|
|
153
|
+
variant={
|
|
154
|
+
useDangerButton ? "danger" : "primary"
|
|
155
|
+
}
|
|
156
|
+
action={continueAction}
|
|
157
|
+
text={continueButtonText}
|
|
158
|
+
dataQa={continueButtonText}
|
|
159
|
+
isLoading={isLoading}
|
|
160
|
+
disabled={isContinueActionDisabled}
|
|
161
|
+
extraStyles={buttonExtraStyles}
|
|
162
|
+
className="modal-continue-button"
|
|
163
|
+
/>
|
|
164
|
+
</Stack>
|
|
165
|
+
)}
|
|
166
|
+
</Fragment>
|
|
127
167
|
) : (
|
|
128
|
-
<
|
|
129
|
-
childGap="1rem"
|
|
130
|
-
direction="row"
|
|
131
|
-
justify="flex-end"
|
|
132
|
-
>
|
|
168
|
+
<Box padding="0.5rem">
|
|
133
169
|
<ButtonWithAction
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
text=
|
|
137
|
-
dataQa=
|
|
170
|
+
action={hideModal}
|
|
171
|
+
variant="primary"
|
|
172
|
+
text="Close"
|
|
173
|
+
dataQa="Close"
|
|
138
174
|
extraStyles={buttonExtraStyles}
|
|
139
175
|
className="modal-cancel-button"
|
|
140
176
|
/>
|
|
141
|
-
|
|
142
|
-
variant={useDangerButton ? "danger" : "primary"}
|
|
143
|
-
action={continueAction}
|
|
144
|
-
text={continueButtonText}
|
|
145
|
-
dataQa={continueButtonText}
|
|
146
|
-
isLoading={isLoading}
|
|
147
|
-
extraStyles={buttonExtraStyles}
|
|
148
|
-
className="modal-continue-button"
|
|
149
|
-
/>
|
|
150
|
-
</Stack>
|
|
177
|
+
</Box>
|
|
151
178
|
)}
|
|
152
|
-
|
|
153
|
-
) : (
|
|
154
|
-
<Box padding="0.5rem">
|
|
155
|
-
<ButtonWithAction
|
|
156
|
-
action={hideModal}
|
|
157
|
-
variant="primary"
|
|
158
|
-
text="Close"
|
|
159
|
-
dataQa="Close"
|
|
160
|
-
extraStyles={buttonExtraStyles}
|
|
161
|
-
className="modal-cancel-button"
|
|
162
|
-
/>
|
|
163
|
-
</Box>
|
|
179
|
+
</>
|
|
164
180
|
)}
|
|
165
181
|
</Stack>
|
|
166
182
|
</Box>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
import { text, boolean } from "@storybook/addon-knobs";
|
|
3
3
|
import Modal from "./Modal";
|
|
4
4
|
|
|
@@ -6,7 +6,8 @@ import page from "../../../../.storybook/page";
|
|
|
6
6
|
|
|
7
7
|
import Text from "../../atoms/text";
|
|
8
8
|
import { noop } from "../../../util/general";
|
|
9
|
-
|
|
9
|
+
import Spinner from "../../atoms/spinner/Spinner";
|
|
10
|
+
import { Center } from "../../atoms/layouts";
|
|
10
11
|
const groupId = "props";
|
|
11
12
|
export const modal = () => (
|
|
12
13
|
<Modal
|
|
@@ -23,7 +24,7 @@ export const modal = () => (
|
|
|
23
24
|
)}
|
|
24
25
|
hideModal={noop}
|
|
25
26
|
continueAction={noop}
|
|
26
|
-
modalOpen={boolean("modalOpen",
|
|
27
|
+
modalOpen={boolean("modalOpen", true, groupId)}
|
|
27
28
|
modalHeaderText={text("modalHeaderText", "Modal Header Text", groupId)}
|
|
28
29
|
modalBodyText={text("modalBodyText", "Modal Body Text", groupId)}
|
|
29
30
|
cancelButtonText={text("cancelButtonText", "Cancel", groupId)}
|
|
@@ -37,6 +38,54 @@ export const modal = () => (
|
|
|
37
38
|
/>
|
|
38
39
|
);
|
|
39
40
|
|
|
41
|
+
modal.storyName = "Standard Modal";
|
|
42
|
+
|
|
43
|
+
export const modalWithoutButtons = () => {
|
|
44
|
+
const [isModalOpen, setIsModalOpen] = useState(true);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
// some async action or timer closes the modal instead
|
|
48
|
+
setIsModalOpen(false);
|
|
49
|
+
}, 3000);
|
|
50
|
+
}, []);
|
|
51
|
+
return (
|
|
52
|
+
<Modal
|
|
53
|
+
ModalLink={() => (
|
|
54
|
+
<Text
|
|
55
|
+
tabIndex={0}
|
|
56
|
+
onClick={noop}
|
|
57
|
+
color={"#347BB2"}
|
|
58
|
+
fontSize="18px"
|
|
59
|
+
lineHeight="2rem"
|
|
60
|
+
extraStyles={`cursor: pointer;`}
|
|
61
|
+
>
|
|
62
|
+
Modal Link
|
|
63
|
+
</Text>
|
|
64
|
+
)}
|
|
65
|
+
hideModal={noop}
|
|
66
|
+
continueAction={noop}
|
|
67
|
+
modalOpen={isModalOpen}
|
|
68
|
+
modalHeaderText={text(
|
|
69
|
+
"modalHeaderText",
|
|
70
|
+
"Modal Without Buttons",
|
|
71
|
+
groupId
|
|
72
|
+
)}
|
|
73
|
+
modalBodyText={
|
|
74
|
+
<Center tabIndex={0}>
|
|
75
|
+
<Spinner size="100" />
|
|
76
|
+
</Center>
|
|
77
|
+
}
|
|
78
|
+
modalHeaderBg={text("modalHeaderBg", "white", groupId)}
|
|
79
|
+
modalBodyBg={text("modalBodyBg", "#F6F6F9", groupId)}
|
|
80
|
+
defaultWrapper={boolean("defaultWrapper", true, groupId)}
|
|
81
|
+
noButtons={boolean("noButtons", true, groupId)}
|
|
82
|
+
maxHeight={text("maxHeight", null, groupId)}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
modalWithoutButtons.storyName = "Modal Without Buttons";
|
|
88
|
+
|
|
40
89
|
const story = page({
|
|
41
90
|
title: "Components|Molecules/Modal",
|
|
42
91
|
Component: Modal
|
|
@@ -3,7 +3,7 @@ import { FONT_WEIGHT_REGULAR } from "../../../../constants/style_constants";
|
|
|
3
3
|
const color = "#15749D";
|
|
4
4
|
const hoverColor = "#116285";
|
|
5
5
|
const activeColor = "#0E506D";
|
|
6
|
-
const linkColor = "#
|
|
6
|
+
const linkColor = "#3176AA";
|
|
7
7
|
const fontWeight = FONT_WEIGHT_REGULAR;
|
|
8
8
|
const modalLinkHoverFocus = `outline: none;
|
|
9
9
|
cursor: pointer;
|
|
@@ -50,6 +50,7 @@ const PeriscopeDashboardIframe = ({
|
|
|
50
50
|
time.timer = setTimeout(() => {
|
|
51
51
|
periscopeDataRequestFailure();
|
|
52
52
|
}, 10000);
|
|
53
|
+
return () => clearTimeout(time.timer);
|
|
53
54
|
}, []);
|
|
54
55
|
|
|
55
56
|
const Dashboard = height => url => (
|
|
@@ -68,8 +69,10 @@ const PeriscopeDashboardIframe = ({
|
|
|
68
69
|
const validatePeriscope = message => {
|
|
69
70
|
if (isValidMessage(message)) {
|
|
70
71
|
setHeight(message.data.dashboard_height + 100);
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
if (!periscopeDataSuccess) {
|
|
73
|
+
clearTimeout(time.timer);
|
|
74
|
+
periscopeDataRequestSuccess();
|
|
75
|
+
}
|
|
73
76
|
}
|
|
74
77
|
};
|
|
75
78
|
|
|
@@ -28,7 +28,9 @@ const TermsAndConditionsModal = ({
|
|
|
28
28
|
borderRadius="3px"
|
|
29
29
|
extraStyles="overflow: scroll; max-height: 20rem;"
|
|
30
30
|
>
|
|
31
|
-
<Text variant="p"
|
|
31
|
+
<Text variant="p" extraStyles={`& a { text-decoration: underline; }`}>
|
|
32
|
+
{terms}
|
|
33
|
+
</Text>
|
|
32
34
|
</Box>
|
|
33
35
|
}
|
|
34
36
|
defaultWrapper={false}
|
package/src/components/molecules/terms-and-conditions-modal/TermsAndConditionsModal.theme.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "../../../constants/style_constants";
|
|
5
5
|
|
|
6
6
|
const backgroundColor = { default: "#ffffff", footer: "#ffffff" };
|
|
7
|
-
const linkColor = { default: "#
|
|
7
|
+
const linkColor = { default: "#3176AA", footer: "#ffffff" };
|
|
8
8
|
const border = { default: "#cdcdcd", footer: "#cdcdcd" };
|
|
9
9
|
const fontSize = { default: "1rem", footer: "0.875rem" };
|
|
10
10
|
const lineHeight = { default: "1.5rem", footer: "1.25rem" };
|
package/src/constants/colors.js
CHANGED
|
@@ -53,6 +53,7 @@ const INFO_BLUE = "#E4F4FD";
|
|
|
53
53
|
const HOVER_LIGHT_BLUE = "#EFFAFF";
|
|
54
54
|
const MATISSE_BLUE = "#15749D";
|
|
55
55
|
const ROYAL_BLUE = "#3181E3";
|
|
56
|
+
const ASTRAL_BLUE = "#3176AA";
|
|
56
57
|
// GREEN
|
|
57
58
|
const FOREST_GREEN = "#19b03F";
|
|
58
59
|
const MEADOW_GREEN = "#16C98D";
|
|
@@ -74,7 +75,7 @@ const APRICOT_ORANGE = "#FFE8D8";
|
|
|
74
75
|
const RED = "#FF0000";
|
|
75
76
|
const CRIMSON_RED = "#ED1C24";
|
|
76
77
|
const THUNDERBIRD_RED = "#C3191F";
|
|
77
|
-
const RAZZMATAZZ_RED = "#
|
|
78
|
+
const RAZZMATAZZ_RED = "#D11053";
|
|
78
79
|
const FANTASY_RED = "#FCF4F4";
|
|
79
80
|
const COSMOS_RED = "#FFD0D3";
|
|
80
81
|
const BLUSH_RED = "#FFF0F5";
|
|
@@ -159,6 +160,7 @@ export {
|
|
|
159
160
|
HOVER_LIGHT_BLUE,
|
|
160
161
|
MATISSE_BLUE,
|
|
161
162
|
ROYAL_BLUE,
|
|
163
|
+
ASTRAL_BLUE,
|
|
162
164
|
FOREST_GREEN,
|
|
163
165
|
MEADOW_GREEN,
|
|
164
166
|
POLAR_GREEN,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
const useFocusInvalidInput = (showErrors = false) => {
|
|
4
|
+
console.log("hey show errors", showErrors);
|
|
5
|
+
// Only move focus when "showErrors" is true
|
|
6
|
+
// "showErrors" is managed by container page of form
|
|
7
|
+
// typically set to "true" on attempted form submission, if errors exist
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
console.log("inside use effect show errors", showErrors);
|
|
10
|
+
if (showErrors) {
|
|
11
|
+
const inputsWithErrors = document.querySelectorAll(
|
|
12
|
+
"input[aria-invalid=true]"
|
|
13
|
+
);
|
|
14
|
+
console.log("inputs with errors is", inputsWithErrors);
|
|
15
|
+
inputsWithErrors?.[0]?.focus();
|
|
16
|
+
}
|
|
17
|
+
}, [showErrors]);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default useFocusInvalidInput;
|
package/src/util/general.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { Fragment } from "react";
|
|
2
2
|
import numeral from "numeral";
|
|
3
|
+
import { CHARADE_GREY } from "../constants/colors";
|
|
3
4
|
|
|
4
5
|
export const noop = () => {};
|
|
5
6
|
|
|
@@ -18,6 +19,19 @@ const createUniqueId = () =>
|
|
|
18
19
|
.toString(36)
|
|
19
20
|
.substr(2, 9);
|
|
20
21
|
|
|
22
|
+
export const createIdFromString = (text, postscript, unique = false) => {
|
|
23
|
+
if (text === undefined) {
|
|
24
|
+
return createUniqueId();
|
|
25
|
+
} else {
|
|
26
|
+
// "first name", undefined, false -> "first-name"
|
|
27
|
+
// "email address", "error message", false -> "email-address-error-message"
|
|
28
|
+
// "shopping cart", "order item", true -> "shopping-cart-order-item_2ahtlz608"
|
|
29
|
+
return `${text?.replace(/\s+/g, "-")}${
|
|
30
|
+
postscript ? `-${postscript?.replace(/\s+/g, "-")}` : ``
|
|
31
|
+
}${unique ? createUniqueId() : ``}`;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
21
35
|
export const safeChildren = (children, replacement = []) => {
|
|
22
36
|
const unsafeValues = [false, undefined, NaN, null];
|
|
23
37
|
if (children && children instanceof Array) {
|
|
@@ -32,8 +46,18 @@ export const safeChildren = (children, replacement = []) => {
|
|
|
32
46
|
return unsafeValues.includes(children) ? replacement : children;
|
|
33
47
|
};
|
|
34
48
|
|
|
35
|
-
export const generateClickHandler = (
|
|
49
|
+
export const generateClickHandler = (
|
|
50
|
+
form,
|
|
51
|
+
handleErrors,
|
|
52
|
+
submitForm,
|
|
53
|
+
resetErrors
|
|
54
|
+
) => e => {
|
|
36
55
|
e.preventDefault();
|
|
56
|
+
if (resetErrors) {
|
|
57
|
+
// if provided, will reset error state tracker
|
|
58
|
+
// allows hooks that depend on error state to re-run
|
|
59
|
+
resetErrors();
|
|
60
|
+
}
|
|
37
61
|
const formHasError = Object.values(form.fields).reduce(
|
|
38
62
|
(acc, curr) => acc || curr.hasErrors,
|
|
39
63
|
false
|
|
@@ -96,3 +120,23 @@ export const screenReaderOnlyStyle = `
|
|
|
96
120
|
height: 1px;
|
|
97
121
|
overflow: hidden;
|
|
98
122
|
`;
|
|
123
|
+
|
|
124
|
+
export const inputPlaceholderTextStyle = `
|
|
125
|
+
::-webkit-input-placeholder {
|
|
126
|
+
color: ${CHARADE_GREY};
|
|
127
|
+
}
|
|
128
|
+
::-moz-placeholder {
|
|
129
|
+
color: ${CHARADE_GREY};
|
|
130
|
+
}
|
|
131
|
+
::-ms-placeholder {
|
|
132
|
+
color: ${CHARADE_GREY};
|
|
133
|
+
}
|
|
134
|
+
::placeholder {
|
|
135
|
+
color: ${CHARADE_GREY};
|
|
136
|
+
}
|
|
137
|
+
`;
|
|
138
|
+
export const inputDisabledStyle = `
|
|
139
|
+
color: #6e727e;
|
|
140
|
+
background-color: #f7f7f7;
|
|
141
|
+
pointer-events: none;
|
|
142
|
+
`;
|
package/src/util/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as formats from "./formats";
|
|
2
2
|
import * as general from "./general";
|
|
3
3
|
import * as theme from "./themeUtils";
|
|
4
|
+
import useFocusInvalidInput from "./focusFirstInvalidInputHook";
|
|
4
5
|
|
|
5
|
-
export { formats, general, theme };
|
|
6
|
+
export { formats, general, theme, useFocusInvalidInput };
|