@thecb/components 6.0.8 → 6.1.0-beta.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/index.cjs.js +53 -11
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +53 -11
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/.DS_Store +0 -0
- package/src/components/atoms/dropdown/Dropdown.js +2 -0
- package/src/components/atoms/form-layouts/FormInput.js +22 -4
- package/src/components/atoms/form-select/FormSelect.js +8 -2
- package/src/components/molecules/periscope-dashboard-iframe/PeriscopeDashboardIframe.js +5 -2
- package/src/util/focusFirstInvalidInputHook.js +17 -0
- package/src/util/general.js +13 -0
- package/src/util/index.js +2 -1
package/package.json
CHANGED
package/src/.DS_Store
ADDED
|
Binary file
|
|
@@ -103,6 +103,7 @@ const Dropdown = ({
|
|
|
103
103
|
hasTitles = false,
|
|
104
104
|
autoEraseTypeAhead = true,
|
|
105
105
|
ariaLabelledby,
|
|
106
|
+
ariaDescribedby,
|
|
106
107
|
autocompleteValue = "", // browser autofill value, like country-name or address-level1 for state
|
|
107
108
|
smoothScroll = true
|
|
108
109
|
}) => {
|
|
@@ -292,6 +293,7 @@ const Dropdown = ({
|
|
|
292
293
|
aria-owns={`${ariaLabelledby}_listbox`}
|
|
293
294
|
aria-haspopup="listbox"
|
|
294
295
|
aria-labelledby={ariaLabelledby}
|
|
296
|
+
aria-describedby={ariaDescribedby}
|
|
295
297
|
aria-expanded={isOpen}
|
|
296
298
|
autocomplete={autocompleteValue}
|
|
297
299
|
background={isOpen ? themeValues.hoverColor : WHITE}
|
|
@@ -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>
|
|
@@ -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>
|
|
@@ -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
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
const useFocusInvalidInput = (showErrors = false) => {
|
|
4
|
+
// Only move focus when "showErrors" is true
|
|
5
|
+
// "showErrors" is managed by container page of form
|
|
6
|
+
// typically set to "true" on attempted form submission, if errors exist
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
if (showErrors) {
|
|
9
|
+
const inputsWithErrors = document.querySelectorAll(
|
|
10
|
+
"input[aria-invalid=true]"
|
|
11
|
+
);
|
|
12
|
+
console.log("inputs with errors...", inputsWithErrors);
|
|
13
|
+
}
|
|
14
|
+
}, [showErrors]);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default useFocusInvalidInput;
|
package/src/util/general.js
CHANGED
|
@@ -19,6 +19,19 @@ const createUniqueId = () =>
|
|
|
19
19
|
.toString(36)
|
|
20
20
|
.substr(2, 9);
|
|
21
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
|
+
|
|
22
35
|
export const safeChildren = (children, replacement = []) => {
|
|
23
36
|
const unsafeValues = [false, undefined, NaN, null];
|
|
24
37
|
if (children && children instanceof Array) {
|
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 };
|