@khanacademy/wonder-blocks-form 3.1.11 → 3.1.13
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/CHANGELOG.md +41 -0
- package/dist/components/checkbox-core.d.ts +16 -0
- package/dist/components/checkbox-core.js.flow +26 -0
- package/dist/components/checkbox-group.d.ts +84 -0
- package/dist/components/checkbox-group.js.flow +103 -0
- package/dist/components/checkbox.d.ts +83 -0
- package/dist/components/checkbox.js.flow +106 -0
- package/dist/components/choice-internal.d.ts +63 -0
- package/dist/components/choice-internal.js.flow +100 -0
- package/dist/components/choice.d.ts +127 -0
- package/dist/components/choice.js.flow +161 -0
- package/dist/components/field-heading.d.ts +50 -0
- package/dist/components/field-heading.js.flow +64 -0
- package/dist/components/group-styles.d.ts +3 -0
- package/dist/components/group-styles.js.flow +10 -0
- package/dist/components/labeled-text-field.d.ts +169 -0
- package/dist/components/labeled-text-field.js.flow +211 -0
- package/dist/components/radio-core.d.ts +15 -0
- package/dist/components/radio-core.js.flow +26 -0
- package/dist/components/radio-group.d.ts +85 -0
- package/dist/components/radio-group.js.flow +104 -0
- package/dist/components/radio.d.ts +68 -0
- package/dist/components/radio.js.flow +92 -0
- package/dist/components/text-field.d.ts +146 -0
- package/dist/components/text-field.js.flow +186 -0
- package/dist/es/index.js +258 -224
- package/dist/index.d.ts +7 -0
- package/dist/index.js +281 -249
- package/dist/index.js.flow +21 -2
- package/dist/util/types.d.ts +62 -0
- package/dist/util/types.js.flow +138 -0
- package/package.json +10 -10
- package/src/__tests__/{custom-snapshot.test.js → custom-snapshot.test.tsx} +8 -9
- package/src/components/__tests__/{checkbox-group.test.js → checkbox-group.test.tsx} +5 -5
- package/src/components/__tests__/{field-heading.test.js → field-heading.test.tsx} +0 -1
- package/src/components/__tests__/{labeled-text-field.test.js → labeled-text-field.test.tsx} +4 -5
- package/src/components/__tests__/{radio-group.test.js → radio-group.test.tsx} +8 -8
- package/src/components/__tests__/{text-field.test.js → text-field.test.tsx} +22 -18
- package/src/components/{checkbox-core.js → checkbox-core.tsx} +12 -15
- package/src/components/{checkbox-group.js → checkbox-group.tsx} +20 -23
- package/src/components/{checkbox.js → checkbox.tsx} +18 -32
- package/src/components/{choice-internal.js → choice-internal.tsx} +25 -39
- package/src/components/{choice.js → choice.tsx} +24 -37
- package/src/components/{field-heading.js → field-heading.tsx} +16 -23
- package/src/components/{group-styles.js → group-styles.ts} +0 -1
- package/src/components/{labeled-text-field.js → labeled-text-field.tsx} +54 -69
- package/src/components/{radio-core.js → radio-core.tsx} +13 -16
- package/src/components/{radio-group.js → radio-group.tsx} +20 -23
- package/src/components/{radio.js → radio.tsx} +18 -32
- package/src/components/{text-field.js → text-field.tsx} +53 -64
- package/src/{index.js → index.ts} +0 -1
- package/src/util/{types.js → types.ts} +32 -35
- package/tsconfig.json +19 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/src/__docs__/_overview_.stories.mdx +0 -15
- package/src/components/__docs__/checkbox-accessibility.stories.mdx +0 -147
- package/src/components/__docs__/checkbox-group.stories.js +0 -300
- package/src/components/__docs__/checkbox.stories.js +0 -167
- package/src/components/__docs__/choice.stories.js +0 -86
- package/src/components/__docs__/labeled-text-field.argtypes.js +0 -248
- package/src/components/__docs__/labeled-text-field.stories.js +0 -709
- package/src/components/__docs__/radio-group.stories.js +0 -217
- package/src/components/__docs__/radio.stories.js +0 -161
- package/src/components/__docs__/text-field.argtypes.js +0 -206
- package/src/components/__docs__/text-field.stories.js +0 -780
- /package/src/__tests__/__snapshots__/{custom-snapshot.test.js.snap → custom-snapshot.test.tsx.snap} +0 -0
package/dist/index.js.flow
CHANGED
|
@@ -1,2 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Flowtype definitions for index
|
|
3
|
+
* Generated by Flowgen from a Typescript Definition
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
|
+
* @flow
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import Checkbox from "./components/checkbox";
|
|
9
|
+
import Choice from "./components/choice";
|
|
10
|
+
import CheckboxGroup from "./components/checkbox-group";
|
|
11
|
+
import RadioGroup from "./components/radio-group";
|
|
12
|
+
import TextField from "./components/text-field";
|
|
13
|
+
import LabeledTextField from "./components/labeled-text-field";
|
|
14
|
+
declare export {
|
|
15
|
+
Checkbox,
|
|
16
|
+
Choice,
|
|
17
|
+
CheckboxGroup,
|
|
18
|
+
RadioGroup,
|
|
19
|
+
TextField,
|
|
20
|
+
LabeledTextField,
|
|
21
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
|
|
2
|
+
import Choice from "../components/choice";
|
|
3
|
+
export type ChoiceCoreProps = AriaProps & {
|
|
4
|
+
/** Whether this component is checked */
|
|
5
|
+
checked: boolean;
|
|
6
|
+
/** Whether this component is disabled */
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
/** Whether this component should show an error state */
|
|
9
|
+
error: boolean;
|
|
10
|
+
/** Name for the checkbox or radio button group */
|
|
11
|
+
groupName?: string;
|
|
12
|
+
/** Unique identifier attached to the HTML input element. If used, need to
|
|
13
|
+
* guarantee that the ID is unique within everything rendered on a page.
|
|
14
|
+
* Used to match <label> with <input> elements for screenreaders. */
|
|
15
|
+
id?: string;
|
|
16
|
+
/** Optional test ID for e2e testing */
|
|
17
|
+
testId?: string;
|
|
18
|
+
};
|
|
19
|
+
export type ChoiceComponentProps = ChoiceCoreProps & {
|
|
20
|
+
/** Callback when this component is selected. The newCheckedState is the
|
|
21
|
+
* new checked state of the component. */
|
|
22
|
+
onChange: (newCheckedState: boolean) => unknown;
|
|
23
|
+
/** Optional label for the field. */
|
|
24
|
+
label?: string;
|
|
25
|
+
/** Optional description for the field. */
|
|
26
|
+
description?: string;
|
|
27
|
+
/** Ignored because only applicable to Choice components in a group. */
|
|
28
|
+
value?: string;
|
|
29
|
+
/** Optional styling for the container. Does not style the component. */
|
|
30
|
+
style?: StyleType;
|
|
31
|
+
};
|
|
32
|
+
export type SharedGroupProps = {
|
|
33
|
+
/** Children should be Choice components. */
|
|
34
|
+
children: Choice;
|
|
35
|
+
/** Group name for this checkbox or radio group. Should be unique for all
|
|
36
|
+
* such groups displayed on a page. */
|
|
37
|
+
groupName: string;
|
|
38
|
+
/** Optional label for the group. This label is optional to allow for
|
|
39
|
+
* greater flexibility in implementing checkbox and radio groups. */
|
|
40
|
+
label?: string;
|
|
41
|
+
/** Optional description for the group. */
|
|
42
|
+
description?: string;
|
|
43
|
+
/** Optional error message. If supplied, the group will be displayed in an
|
|
44
|
+
* error state, along with this error message. If no error state is desired,
|
|
45
|
+
* simply do not supply this prop, or pass along null. */
|
|
46
|
+
errorMessage?: string;
|
|
47
|
+
/** Custom styling for this group of checkboxes. */
|
|
48
|
+
style?: StyleType;
|
|
49
|
+
};
|
|
50
|
+
export type CheckboxGroupProps = {
|
|
51
|
+
/** Callback for when selection of the group has changed. Passes the newly
|
|
52
|
+
* selected values. */
|
|
53
|
+
onChange: (selectedValues: Array<string>) => unknown;
|
|
54
|
+
/** An array of the values of the selected values in this checkbox group. */
|
|
55
|
+
selectedValues: Array<string>;
|
|
56
|
+
};
|
|
57
|
+
export type RadioGroupProps = {
|
|
58
|
+
/** Callback for when the selected value of the radio group has changed. */
|
|
59
|
+
onChange: (selectedValue: string) => unknown;
|
|
60
|
+
/** Value of the selected radio item. */
|
|
61
|
+
selectedValue: string;
|
|
62
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flowtype definitions for types
|
|
3
|
+
* Generated by Flowgen from a Typescript Definition
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
|
+
* @flow
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
|
|
9
|
+
import Choice from "../components/choice";
|
|
10
|
+
export type ChoiceCoreProps = {
|
|
11
|
+
...AriaProps,
|
|
12
|
+
...{
|
|
13
|
+
/**
|
|
14
|
+
* Whether this component is checked
|
|
15
|
+
*/
|
|
16
|
+
checked: boolean,
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Whether this component is disabled
|
|
20
|
+
*/
|
|
21
|
+
disabled: boolean,
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Whether this component should show an error state
|
|
25
|
+
*/
|
|
26
|
+
error: boolean,
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Name for the checkbox or radio button group
|
|
30
|
+
*/
|
|
31
|
+
groupName?: string,
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Unique identifier attached to the HTML input element. If used, need to
|
|
35
|
+
* guarantee that the ID is unique within everything rendered on a page.
|
|
36
|
+
* Used to match <label> with <input> elements for screenreaders.
|
|
37
|
+
*/
|
|
38
|
+
id?: string,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Optional test ID for e2e testing
|
|
42
|
+
*/
|
|
43
|
+
testId?: string,
|
|
44
|
+
...
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
export type ChoiceComponentProps = {
|
|
48
|
+
...ChoiceCoreProps,
|
|
49
|
+
...{
|
|
50
|
+
/**
|
|
51
|
+
* Callback when this component is selected. The newCheckedState is the
|
|
52
|
+
* new checked state of the component.
|
|
53
|
+
*/
|
|
54
|
+
onChange: (newCheckedState: boolean) => mixed,
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Optional label for the field.
|
|
58
|
+
*/
|
|
59
|
+
label?: string,
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Optional description for the field.
|
|
63
|
+
*/
|
|
64
|
+
description?: string,
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Ignored because only applicable to Choice components in a group.
|
|
68
|
+
*/
|
|
69
|
+
value?: string,
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Optional styling for the container. Does not style the component.
|
|
73
|
+
*/
|
|
74
|
+
style?: StyleType,
|
|
75
|
+
...
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
export type SharedGroupProps = {
|
|
79
|
+
/**
|
|
80
|
+
* Children should be Choice components.
|
|
81
|
+
*/
|
|
82
|
+
children: Choice,
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Group name for this checkbox or radio group. Should be unique for all
|
|
86
|
+
* such groups displayed on a page.
|
|
87
|
+
*/
|
|
88
|
+
groupName: string,
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Optional label for the group. This label is optional to allow for
|
|
92
|
+
* greater flexibility in implementing checkbox and radio groups.
|
|
93
|
+
*/
|
|
94
|
+
label?: string,
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Optional description for the group.
|
|
98
|
+
*/
|
|
99
|
+
description?: string,
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Optional error message. If supplied, the group will be displayed in an
|
|
103
|
+
* error state, along with this error message. If no error state is desired,
|
|
104
|
+
* simply do not supply this prop, or pass along null.
|
|
105
|
+
*/
|
|
106
|
+
errorMessage?: string,
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Custom styling for this group of checkboxes.
|
|
110
|
+
*/
|
|
111
|
+
style?: StyleType,
|
|
112
|
+
...
|
|
113
|
+
};
|
|
114
|
+
export type CheckboxGroupProps = {
|
|
115
|
+
/**
|
|
116
|
+
* Callback for when selection of the group has changed. Passes the newly
|
|
117
|
+
* selected values.
|
|
118
|
+
*/
|
|
119
|
+
onChange: (selectedValues: Array<string>) => mixed,
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* An array of the values of the selected values in this checkbox group.
|
|
123
|
+
*/
|
|
124
|
+
selectedValues: Array<string>,
|
|
125
|
+
...
|
|
126
|
+
};
|
|
127
|
+
export type RadioGroupProps = {
|
|
128
|
+
/**
|
|
129
|
+
* Callback for when the selected value of the radio group has changed.
|
|
130
|
+
*/
|
|
131
|
+
onChange: (selectedValue: string) => mixed,
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Value of the selected radio item.
|
|
135
|
+
*/
|
|
136
|
+
selectedValue: string,
|
|
137
|
+
...
|
|
138
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-form",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.13",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"description": "Form components for Wonder Blocks.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/es/index.js",
|
|
8
|
-
"
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
11
|
},
|
|
@@ -16,19 +16,19 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@babel/runtime": "^7.18.6",
|
|
19
|
-
"@khanacademy/wonder-blocks-clickable": "^2.4.
|
|
20
|
-
"@khanacademy/wonder-blocks-color": "^1.2.
|
|
21
|
-
"@khanacademy/wonder-blocks-core": "^4.
|
|
22
|
-
"@khanacademy/wonder-blocks-icon": "^1.2.
|
|
23
|
-
"@khanacademy/wonder-blocks-layout": "^1.4.
|
|
24
|
-
"@khanacademy/wonder-blocks-spacing": "^3.0.
|
|
25
|
-
"@khanacademy/wonder-blocks-typography": "^1.1.
|
|
19
|
+
"@khanacademy/wonder-blocks-clickable": "^2.4.7",
|
|
20
|
+
"@khanacademy/wonder-blocks-color": "^1.2.2",
|
|
21
|
+
"@khanacademy/wonder-blocks-core": "^4.9.0",
|
|
22
|
+
"@khanacademy/wonder-blocks-icon": "^1.2.39",
|
|
23
|
+
"@khanacademy/wonder-blocks-layout": "^1.4.18",
|
|
24
|
+
"@khanacademy/wonder-blocks-spacing": "^3.0.6",
|
|
25
|
+
"@khanacademy/wonder-blocks-typography": "^1.1.40"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"aphrodite": "^1.2.5",
|
|
29
29
|
"react": "16.14.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"wb-dev-build-settings": "^0.7.
|
|
32
|
+
"wb-dev-build-settings": "^0.7.3"
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import renderer from "react-test-renderer";
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as renderer from "react-test-renderer";
|
|
4
3
|
|
|
5
4
|
import CheckboxCore from "../components/checkbox-core";
|
|
6
5
|
import RadioCore from "../components/radio-core";
|
|
@@ -10,9 +9,9 @@ const clickableStates = ["default", "hovered", "pressed"];
|
|
|
10
9
|
const checkedStates = [false, true];
|
|
11
10
|
|
|
12
11
|
describe("CheckboxCore", () => {
|
|
13
|
-
states.forEach((state) => {
|
|
14
|
-
clickableStates.forEach((clickableState) => {
|
|
15
|
-
checkedStates.forEach((checked) => {
|
|
12
|
+
states.forEach((state: any) => {
|
|
13
|
+
clickableStates.forEach((clickableState: any) => {
|
|
14
|
+
checkedStates.forEach((checked: any) => {
|
|
16
15
|
test(`type:${state} state:${clickableState} checked:${String(
|
|
17
16
|
checked,
|
|
18
17
|
)}`, () => {
|
|
@@ -38,9 +37,9 @@ describe("CheckboxCore", () => {
|
|
|
38
37
|
});
|
|
39
38
|
|
|
40
39
|
describe("RadioCore", () => {
|
|
41
|
-
states.forEach((state) => {
|
|
42
|
-
clickableStates.forEach((clickableState) => {
|
|
43
|
-
checkedStates.forEach((checked) => {
|
|
40
|
+
states.forEach((state: any) => {
|
|
41
|
+
clickableStates.forEach((clickableState: any) => {
|
|
42
|
+
checkedStates.forEach((checked: any) => {
|
|
44
43
|
test(`type:${state} state:${clickableState} checked:${String(
|
|
45
44
|
checked,
|
|
46
45
|
)}`, () => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//@flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {render, screen} from "@testing-library/react";
|
|
4
3
|
import userEvent from "@testing-library/user-event";
|
|
@@ -8,12 +7,12 @@ import Choice from "../choice";
|
|
|
8
7
|
|
|
9
8
|
describe("CheckboxGroup", () => {
|
|
10
9
|
describe("behavior", () => {
|
|
11
|
-
const TestComponent = ({errorMessage}: {
|
|
10
|
+
const TestComponent = ({errorMessage}: {errorMessage?: string}) => {
|
|
12
11
|
const [selectedValues, setSelectedValue] = React.useState([
|
|
13
12
|
"a",
|
|
14
13
|
"b",
|
|
15
14
|
]);
|
|
16
|
-
const handleChange = (selectedValues) => {
|
|
15
|
+
const handleChange = (selectedValues: any) => {
|
|
17
16
|
setSelectedValue(selectedValues);
|
|
18
17
|
};
|
|
19
18
|
return (
|
|
@@ -144,9 +143,10 @@ describe("CheckboxGroup", () => {
|
|
|
144
143
|
selectedValues={[]}
|
|
145
144
|
>
|
|
146
145
|
<Choice label="a" value="a" aria-labelledby="test-a" />
|
|
147
|
-
{
|
|
146
|
+
{/* eslint-disable-next-line no-constant-condition */}
|
|
147
|
+
{false ? (
|
|
148
148
|
<Choice label="b" value="b" aria-labelledby="test-b" />
|
|
149
|
-
)}
|
|
149
|
+
) : null}
|
|
150
150
|
<Choice label="c" value="c" aria-labelledby="test-c" />
|
|
151
151
|
{undefined}
|
|
152
152
|
{null}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//@flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {render, screen, fireEvent} from "@testing-library/react";
|
|
4
3
|
import userEvent from "@testing-library/user-event";
|
|
@@ -219,7 +218,7 @@ describe("LabeledTextField", () => {
|
|
|
219
218
|
|
|
220
219
|
it("validate prop is called when input changes", () => {
|
|
221
220
|
// Arrange
|
|
222
|
-
const validate = jest.fn((value: string):
|
|
221
|
+
const validate = jest.fn((value: string): any => {});
|
|
223
222
|
render(
|
|
224
223
|
<LabeledTextField
|
|
225
224
|
label="Label"
|
|
@@ -243,10 +242,10 @@ describe("LabeledTextField", () => {
|
|
|
243
242
|
|
|
244
243
|
it("onValidate prop is called on new validated input", () => {
|
|
245
244
|
// Arrange
|
|
246
|
-
const handleValidate = jest.fn((errorMessage
|
|
245
|
+
const handleValidate = jest.fn((errorMessage?: string | null) => {});
|
|
247
246
|
const errorMessage = "Password must be at least 8 characters long";
|
|
248
247
|
|
|
249
|
-
const validate = (value: string):
|
|
248
|
+
const validate = (value: string): string | null | undefined => {
|
|
250
249
|
if (value.length < 8) {
|
|
251
250
|
return errorMessage;
|
|
252
251
|
}
|
|
@@ -293,7 +292,7 @@ describe("LabeledTextField", () => {
|
|
|
293
292
|
it("onKeyDown prop is called on keyboard keypress", () => {
|
|
294
293
|
// Arrange
|
|
295
294
|
const handleKeyDown = jest.fn(
|
|
296
|
-
(event:
|
|
295
|
+
(event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
297
296
|
return event.key;
|
|
298
297
|
},
|
|
299
298
|
);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//@flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {render, screen} from "@testing-library/react";
|
|
4
3
|
import userEvent from "@testing-library/user-event";
|
|
@@ -10,12 +9,12 @@ describe("RadioGroup", () => {
|
|
|
10
9
|
const TestComponent = ({
|
|
11
10
|
errorMessage,
|
|
12
11
|
onChange,
|
|
13
|
-
}: {
|
|
14
|
-
errorMessage?: string
|
|
15
|
-
onChange?: () =>
|
|
16
|
-
|
|
12
|
+
}: {
|
|
13
|
+
errorMessage?: string;
|
|
14
|
+
onChange?: () => unknown;
|
|
15
|
+
}) => {
|
|
17
16
|
const [selectedValue, setSelectedValue] = React.useState("a");
|
|
18
|
-
const handleChange = (selectedValue) => {
|
|
17
|
+
const handleChange = (selectedValue: any) => {
|
|
19
18
|
setSelectedValue(selectedValue);
|
|
20
19
|
onChange?.();
|
|
21
20
|
};
|
|
@@ -164,9 +163,10 @@ describe("RadioGroup", () => {
|
|
|
164
163
|
selectedValue={"a"}
|
|
165
164
|
>
|
|
166
165
|
<Choice label="a" value="a" aria-labelledby="test-a" />
|
|
167
|
-
{
|
|
166
|
+
{/* eslint-disable-next-line no-constant-condition */}
|
|
167
|
+
{false ? (
|
|
168
168
|
<Choice label="b" value="b" aria-labelledby="test-b" />
|
|
169
|
-
)}
|
|
169
|
+
) : null}
|
|
170
170
|
<Choice label="c" value="c" aria-labelledby="test-c" />
|
|
171
171
|
{undefined}
|
|
172
172
|
{null}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {fireEvent, render, screen} from "@testing-library/react";
|
|
4
3
|
import userEvent from "@testing-library/user-event";
|
|
@@ -78,7 +77,7 @@ describe("TextField", () => {
|
|
|
78
77
|
|
|
79
78
|
it("id prop is passed to the input element", () => {
|
|
80
79
|
// Arrange
|
|
81
|
-
const id
|
|
80
|
+
const id = "tf-1";
|
|
82
81
|
|
|
83
82
|
// Act
|
|
84
83
|
render(<TextField id={id} value="" onChange={() => {}} />);
|
|
@@ -155,12 +154,13 @@ describe("TextField", () => {
|
|
|
155
154
|
|
|
156
155
|
it("validate is called when value changes", () => {
|
|
157
156
|
// Arrange
|
|
158
|
-
const handleValidate = jest.fn((value: string)
|
|
157
|
+
const handleValidate = jest.fn((value: string) => {});
|
|
159
158
|
|
|
160
159
|
render(
|
|
161
160
|
<TextField
|
|
162
161
|
id={"tf-1"}
|
|
163
162
|
value="Text"
|
|
163
|
+
// @ts-expect-error: handleValidate is not the correc type
|
|
164
164
|
validate={handleValidate}
|
|
165
165
|
onChange={() => {}}
|
|
166
166
|
/>,
|
|
@@ -177,11 +177,13 @@ describe("TextField", () => {
|
|
|
177
177
|
|
|
178
178
|
it("validate is given a valid input", () => {
|
|
179
179
|
// Arrange
|
|
180
|
-
const handleValidate = jest.fn(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
180
|
+
const handleValidate = jest.fn(
|
|
181
|
+
(value: string): string | null | undefined => {
|
|
182
|
+
if (value.length < 8) {
|
|
183
|
+
return "Value is too short";
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
);
|
|
185
187
|
|
|
186
188
|
render(
|
|
187
189
|
<TextField
|
|
@@ -204,11 +206,13 @@ describe("TextField", () => {
|
|
|
204
206
|
it("validate is given an invalid input", () => {
|
|
205
207
|
// Arrange
|
|
206
208
|
const errorMessage = "Value is too short";
|
|
207
|
-
const handleValidate = jest.fn(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
209
|
+
const handleValidate = jest.fn(
|
|
210
|
+
(value: string): string | null | undefined => {
|
|
211
|
+
if (value.length < 8) {
|
|
212
|
+
return errorMessage;
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
);
|
|
212
216
|
|
|
213
217
|
render(
|
|
214
218
|
<TextField
|
|
@@ -231,8 +235,8 @@ describe("TextField", () => {
|
|
|
231
235
|
it("onValidate is called after input validate", () => {
|
|
232
236
|
// Arrange
|
|
233
237
|
const errorMessage = "Value is too short";
|
|
234
|
-
const handleValidate = jest.fn((errorMessage
|
|
235
|
-
const validate = jest.fn((value: string):
|
|
238
|
+
const handleValidate = jest.fn((errorMessage?: string | null) => {});
|
|
239
|
+
const validate = jest.fn((value: string): string | null | undefined => {
|
|
236
240
|
if (value.length < 8) {
|
|
237
241
|
return errorMessage;
|
|
238
242
|
}
|
|
@@ -260,8 +264,8 @@ describe("TextField", () => {
|
|
|
260
264
|
it("onValidate is called on input's initial value", () => {
|
|
261
265
|
// Arrange
|
|
262
266
|
const errorMessage = "Value is too short";
|
|
263
|
-
const handleValidate = jest.fn((errorMessage
|
|
264
|
-
const validate = jest.fn((value: string):
|
|
267
|
+
const handleValidate = jest.fn((errorMessage?: string | null) => {});
|
|
268
|
+
const validate = jest.fn((value: string): string | null | undefined => {
|
|
265
269
|
if (value.length < 8) {
|
|
266
270
|
return errorMessage;
|
|
267
271
|
}
|
|
@@ -285,7 +289,7 @@ describe("TextField", () => {
|
|
|
285
289
|
it("onKeyDown is called after keyboard key press", () => {
|
|
286
290
|
// Arrange
|
|
287
291
|
const handleOnKeyDown = jest.fn(
|
|
288
|
-
(event:
|
|
292
|
+
(event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
289
293
|
return event.key;
|
|
290
294
|
},
|
|
291
295
|
);
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
1
|
import * as React from "react";
|
|
4
2
|
import {StyleSheet} from "aphrodite";
|
|
5
3
|
|
|
@@ -11,13 +9,12 @@ import type {IconAsset} from "@khanacademy/wonder-blocks-icon";
|
|
|
11
9
|
|
|
12
10
|
import type {ChoiceCoreProps} from "../util/types";
|
|
13
11
|
|
|
14
|
-
type Props = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|};
|
|
12
|
+
type Props = ChoiceCoreProps & {
|
|
13
|
+
hovered: boolean;
|
|
14
|
+
focused: boolean;
|
|
15
|
+
pressed: boolean;
|
|
16
|
+
waiting: boolean;
|
|
17
|
+
};
|
|
21
18
|
|
|
22
19
|
const {blue, red, white, offWhite, offBlack16, offBlack32, offBlack50} = Color;
|
|
23
20
|
|
|
@@ -36,7 +33,7 @@ export default class CheckboxCore extends React.Component<Props> {
|
|
|
36
33
|
return;
|
|
37
34
|
};
|
|
38
35
|
|
|
39
|
-
render(): React.
|
|
36
|
+
render(): React.ReactElement {
|
|
40
37
|
const {
|
|
41
38
|
checked,
|
|
42
39
|
disabled,
|
|
@@ -66,7 +63,7 @@ export default class CheckboxCore extends React.Component<Props> {
|
|
|
66
63
|
|
|
67
64
|
const props = {
|
|
68
65
|
"data-test-id": testId,
|
|
69
|
-
};
|
|
66
|
+
} as const;
|
|
70
67
|
|
|
71
68
|
return (
|
|
72
69
|
<React.Fragment>
|
|
@@ -149,11 +146,11 @@ const colors = {
|
|
|
149
146
|
base: red,
|
|
150
147
|
active: activeRed,
|
|
151
148
|
},
|
|
152
|
-
};
|
|
149
|
+
} as const;
|
|
153
150
|
|
|
154
|
-
const styles = {};
|
|
151
|
+
const styles: Record<string, any> = {};
|
|
155
152
|
|
|
156
|
-
const _generateStyles = (checked, error) => {
|
|
153
|
+
const _generateStyles = (checked: boolean, error: boolean) => {
|
|
157
154
|
// "hash" the parameters
|
|
158
155
|
const styleKey = `${String(checked)}-${String(error)}`;
|
|
159
156
|
if (styles[styleKey]) {
|
|
@@ -162,7 +159,7 @@ const _generateStyles = (checked, error) => {
|
|
|
162
159
|
|
|
163
160
|
const palette = error ? colors.error : colors.default;
|
|
164
161
|
|
|
165
|
-
let newStyles = {};
|
|
162
|
+
let newStyles: Record<string, any> = {};
|
|
166
163
|
if (checked) {
|
|
167
164
|
newStyles = {
|
|
168
165
|
default: {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
1
|
import * as React from "react";
|
|
4
2
|
|
|
5
3
|
import {View, addStyle} from "@khanacademy/wonder-blocks-core";
|
|
@@ -9,60 +7,57 @@ import {LabelMedium, LabelSmall} from "@khanacademy/wonder-blocks-typography";
|
|
|
9
7
|
import type {StyleType} from "@khanacademy/wonder-blocks-core";
|
|
10
8
|
|
|
11
9
|
import styles from "./group-styles";
|
|
12
|
-
import
|
|
10
|
+
import Choice from "./choice";
|
|
13
11
|
|
|
14
12
|
// Keep synced with CheckboxGroupProps in ../util/types.js
|
|
15
|
-
type CheckboxGroupProps = {
|
|
13
|
+
type CheckboxGroupProps = {
|
|
16
14
|
/**
|
|
17
15
|
* Children should be Choice components.
|
|
18
16
|
*/
|
|
19
|
-
children: Array
|
|
20
|
-
|
|
17
|
+
children: Array<
|
|
18
|
+
| React.ReactElement<React.ComponentProps<typeof Choice>>
|
|
19
|
+
| false
|
|
20
|
+
| null
|
|
21
|
+
| undefined
|
|
22
|
+
>;
|
|
21
23
|
/**
|
|
22
24
|
* Group name for this checkbox or radio group. Should be unique for all
|
|
23
25
|
* such groups displayed on a page.
|
|
24
26
|
*/
|
|
25
|
-
groupName: string
|
|
26
|
-
|
|
27
|
+
groupName: string;
|
|
27
28
|
/**
|
|
28
29
|
* Optional label for the group. This label is optional to allow for
|
|
29
30
|
* greater flexibility in implementing checkbox and radio groups.
|
|
30
31
|
*/
|
|
31
|
-
label?: React.
|
|
32
|
-
|
|
32
|
+
label?: React.ReactNode;
|
|
33
33
|
/**
|
|
34
34
|
* Optional description for the group.
|
|
35
35
|
*/
|
|
36
|
-
description?: React.
|
|
37
|
-
|
|
36
|
+
description?: React.ReactNode;
|
|
38
37
|
/**
|
|
39
38
|
* Optional error message. If supplied, the group will be displayed in an
|
|
40
39
|
* error state, along with this error message. If no error state is desired,
|
|
41
40
|
* simply do not supply this prop, or pass along null.
|
|
42
41
|
*/
|
|
43
|
-
errorMessage?:
|
|
44
|
-
|
|
42
|
+
errorMessage?: string | null | undefined;
|
|
45
43
|
/**
|
|
46
44
|
* Custom styling for this group of checkboxes.
|
|
47
45
|
*/
|
|
48
|
-
style?: StyleType
|
|
49
|
-
|
|
46
|
+
style?: StyleType;
|
|
50
47
|
/**
|
|
51
48
|
* Callback for when selection of the group has changed. Passes the newly
|
|
52
49
|
* selected values.
|
|
53
50
|
*/
|
|
54
|
-
onChange: (selectedValues: Array<string>) =>
|
|
55
|
-
|
|
51
|
+
onChange: (selectedValues: Array<string>) => unknown;
|
|
56
52
|
/**
|
|
57
53
|
* An array of the values of the selected values in this checkbox group.
|
|
58
54
|
*/
|
|
59
|
-
selectedValues: Array<string
|
|
60
|
-
|
|
55
|
+
selectedValues: Array<string>;
|
|
61
56
|
/**
|
|
62
57
|
* Test ID used for e2e testing.
|
|
63
58
|
*/
|
|
64
|
-
testId?: string
|
|
65
|
-
|
|
59
|
+
testId?: string;
|
|
60
|
+
};
|
|
66
61
|
|
|
67
62
|
const StyledFieldset = addStyle<"fieldset">("fieldset");
|
|
68
63
|
const StyledLegend = addStyle<"legend">("legend");
|
|
@@ -116,7 +111,7 @@ export default class CheckboxGroup extends React.Component<CheckboxGroupProps> {
|
|
|
116
111
|
}
|
|
117
112
|
}
|
|
118
113
|
|
|
119
|
-
render(): React.
|
|
114
|
+
render(): React.ReactElement {
|
|
120
115
|
const {
|
|
121
116
|
children,
|
|
122
117
|
label,
|
|
@@ -154,8 +149,10 @@ export default class CheckboxGroup extends React.Component<CheckboxGroupProps> {
|
|
|
154
149
|
)}
|
|
155
150
|
|
|
156
151
|
{allChildren.map((child, index) => {
|
|
152
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'props' does not exist on type 'ReactChild | ReactFragment | ReactPortal'.
|
|
157
153
|
const {style, value} = child.props;
|
|
158
154
|
const checked = selectedValues.includes(value);
|
|
155
|
+
// @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
|
|
159
156
|
return React.cloneElement(child, {
|
|
160
157
|
checked: checked,
|
|
161
158
|
error: !!errorMessage,
|