@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.
Files changed (66) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/components/checkbox-core.d.ts +16 -0
  3. package/dist/components/checkbox-core.js.flow +26 -0
  4. package/dist/components/checkbox-group.d.ts +84 -0
  5. package/dist/components/checkbox-group.js.flow +103 -0
  6. package/dist/components/checkbox.d.ts +83 -0
  7. package/dist/components/checkbox.js.flow +106 -0
  8. package/dist/components/choice-internal.d.ts +63 -0
  9. package/dist/components/choice-internal.js.flow +100 -0
  10. package/dist/components/choice.d.ts +127 -0
  11. package/dist/components/choice.js.flow +161 -0
  12. package/dist/components/field-heading.d.ts +50 -0
  13. package/dist/components/field-heading.js.flow +64 -0
  14. package/dist/components/group-styles.d.ts +3 -0
  15. package/dist/components/group-styles.js.flow +10 -0
  16. package/dist/components/labeled-text-field.d.ts +169 -0
  17. package/dist/components/labeled-text-field.js.flow +211 -0
  18. package/dist/components/radio-core.d.ts +15 -0
  19. package/dist/components/radio-core.js.flow +26 -0
  20. package/dist/components/radio-group.d.ts +85 -0
  21. package/dist/components/radio-group.js.flow +104 -0
  22. package/dist/components/radio.d.ts +68 -0
  23. package/dist/components/radio.js.flow +92 -0
  24. package/dist/components/text-field.d.ts +146 -0
  25. package/dist/components/text-field.js.flow +186 -0
  26. package/dist/es/index.js +258 -224
  27. package/dist/index.d.ts +7 -0
  28. package/dist/index.js +281 -249
  29. package/dist/index.js.flow +21 -2
  30. package/dist/util/types.d.ts +62 -0
  31. package/dist/util/types.js.flow +138 -0
  32. package/package.json +10 -10
  33. package/src/__tests__/{custom-snapshot.test.js → custom-snapshot.test.tsx} +8 -9
  34. package/src/components/__tests__/{checkbox-group.test.js → checkbox-group.test.tsx} +5 -5
  35. package/src/components/__tests__/{field-heading.test.js → field-heading.test.tsx} +0 -1
  36. package/src/components/__tests__/{labeled-text-field.test.js → labeled-text-field.test.tsx} +4 -5
  37. package/src/components/__tests__/{radio-group.test.js → radio-group.test.tsx} +8 -8
  38. package/src/components/__tests__/{text-field.test.js → text-field.test.tsx} +22 -18
  39. package/src/components/{checkbox-core.js → checkbox-core.tsx} +12 -15
  40. package/src/components/{checkbox-group.js → checkbox-group.tsx} +20 -23
  41. package/src/components/{checkbox.js → checkbox.tsx} +18 -32
  42. package/src/components/{choice-internal.js → choice-internal.tsx} +25 -39
  43. package/src/components/{choice.js → choice.tsx} +24 -37
  44. package/src/components/{field-heading.js → field-heading.tsx} +16 -23
  45. package/src/components/{group-styles.js → group-styles.ts} +0 -1
  46. package/src/components/{labeled-text-field.js → labeled-text-field.tsx} +54 -69
  47. package/src/components/{radio-core.js → radio-core.tsx} +13 -16
  48. package/src/components/{radio-group.js → radio-group.tsx} +20 -23
  49. package/src/components/{radio.js → radio.tsx} +18 -32
  50. package/src/components/{text-field.js → text-field.tsx} +53 -64
  51. package/src/{index.js → index.ts} +0 -1
  52. package/src/util/{types.js → types.ts} +32 -35
  53. package/tsconfig.json +19 -0
  54. package/tsconfig.tsbuildinfo +1 -0
  55. package/src/__docs__/_overview_.stories.mdx +0 -15
  56. package/src/components/__docs__/checkbox-accessibility.stories.mdx +0 -147
  57. package/src/components/__docs__/checkbox-group.stories.js +0 -300
  58. package/src/components/__docs__/checkbox.stories.js +0 -167
  59. package/src/components/__docs__/choice.stories.js +0 -86
  60. package/src/components/__docs__/labeled-text-field.argtypes.js +0 -248
  61. package/src/components/__docs__/labeled-text-field.stories.js +0 -709
  62. package/src/components/__docs__/radio-group.stories.js +0 -217
  63. package/src/components/__docs__/radio.stories.js +0 -161
  64. package/src/components/__docs__/text-field.argtypes.js +0 -206
  65. package/src/components/__docs__/text-field.stories.js +0 -780
  66. /package/src/__tests__/__snapshots__/{custom-snapshot.test.js.snap → custom-snapshot.test.tsx.snap} +0 -0
@@ -1,217 +0,0 @@
1
- // @flow
2
- import * as React from "react";
3
- import {StyleSheet} from "aphrodite";
4
-
5
- import {Choice, RadioGroup} from "@khanacademy/wonder-blocks-form";
6
- import {LabelLarge} from "@khanacademy/wonder-blocks-typography";
7
-
8
- import type {StoryComponentType} from "@storybook/react";
9
-
10
- import ComponentInfo from "../../../../../.storybook/components/component-info";
11
- import {name, version} from "../../../package.json";
12
-
13
- export default {
14
- title: "Form / RadioGroup",
15
- component: RadioGroup,
16
- parameters: {
17
- componentSubtitle: ((
18
- <ComponentInfo name={name} version={version} />
19
- ): any),
20
- },
21
- };
22
-
23
- export const Default: StoryComponentType = (args) => {
24
- return (
25
- <RadioGroup {...args}>
26
- <Choice label="Bulbasaur" value="bulbasaur" />
27
- <Choice
28
- label="Charmander"
29
- value="charmander"
30
- description="Oops, we ran out of Charmanders"
31
- disabled
32
- />
33
- <Choice label="Squirtle" value="squirtle" />
34
- <Choice label="Pikachu" value="pikachu" />
35
- </RadioGroup>
36
- );
37
- };
38
-
39
- Default.args = {
40
- // Required
41
- groupName: "pokemon",
42
- selectedValue: "bulbasaur",
43
- onChange: () => {},
44
- // Optional
45
- label: "Pokemon",
46
- description: "Your first Pokemon.",
47
- };
48
-
49
- export const Basic: StoryComponentType = () => {
50
- const [selectedValue, setSelectedValue] = React.useState("");
51
-
52
- return (
53
- <RadioGroup
54
- groupName="pokemon"
55
- label="Pokemon"
56
- description="Your first Pokemon."
57
- onChange={setSelectedValue}
58
- selectedValue={selectedValue}
59
- >
60
- <Choice label="Bulbasaur" value="bulbasaur" />
61
- <Choice
62
- label="Charmander"
63
- value="charmander"
64
- description="Oops, we ran out of Charmanders"
65
- disabled
66
- />
67
- <Choice label="Squirtle" value="squirtle" />
68
- <Choice label="Pikachu" value="pikachu" />
69
- </RadioGroup>
70
- );
71
- };
72
-
73
- Basic.parameters = {
74
- docs: {
75
- storyDescription: `This is a basic example of a radio group.
76
- The Wonder Blocks \`RadioGroup\` component takes \`Choice\`
77
- components as children. One of the \`Choice\` components here
78
- includes a description.`,
79
- },
80
- };
81
-
82
- export const Error: StoryComponentType = () => {
83
- const emptyError = "You must select an option to continue.";
84
- const [selectedValue, setSelectedValue] = React.useState("");
85
- const [error, setError] = React.useState(emptyError);
86
-
87
- // This returns an error message if no option is selected,
88
- // and it returns undefined otherwise. We use undefined instead of
89
- // null here because null would result in a flow error, whereas
90
- // undefined would be the same as not passing in anything to the
91
- // radio group's `errorMessage` prop.
92
- const checkForError = (input) => {
93
- if (!input) {
94
- return emptyError;
95
- }
96
- };
97
-
98
- const handleChange = (input) => {
99
- const errorMessage = checkForError(input);
100
- setSelectedValue(input);
101
- setError(errorMessage);
102
- };
103
-
104
- return (
105
- <RadioGroup
106
- groupName="pokemon"
107
- label="Pokemon"
108
- description="Your first Pokemon."
109
- onChange={handleChange}
110
- selectedValue={selectedValue}
111
- errorMessage={error}
112
- >
113
- <Choice label="Bulbasaur" value="bulbasaur" />
114
- <Choice label="Charmander" value="charmander" />
115
- <Choice label="Squirtle" value="squirtle" />
116
- <Choice label="Pikachu" value="pikachu" />
117
- </RadioGroup>
118
- );
119
- };
120
-
121
- Error.parameters = {
122
- docs: {
123
- storyDescription: `This is what a radio group looks like
124
- if it has an error. It displays the error that is passed into the
125
- \`errorMessage\` prop, provided the error is not null. It also
126
- uses the error styling for all the radio buttons. Here, the error
127
- message is saved as a state, updated in the change handler, and then
128
- passed in as the \`errorMessage\` prop.`,
129
- },
130
- };
131
-
132
- export const MultipleChoiceStyling: StoryComponentType = () => {
133
- const [selectedValue, setSelectedValue] = React.useState("");
134
-
135
- return (
136
- <>
137
- <LabelLarge style={styles.prompt}>
138
- Select your blood type
139
- </LabelLarge>
140
- <RadioGroup
141
- groupName="science-classes"
142
- onChange={setSelectedValue}
143
- selectedValue={selectedValue}
144
- >
145
- <Choice label="A" value="1" style={styles.choice} />
146
- <Choice label="B" value="2" style={styles.choice} />
147
- <Choice label="AB" value="3" style={styles.choice} />
148
- <Choice
149
- label="O"
150
- value="4"
151
- style={[styles.choice, styles.lastChoice]}
152
- />
153
- </RadioGroup>
154
- </>
155
- );
156
- };
157
-
158
- MultipleChoiceStyling.parameters = {
159
- docs: {
160
- storyDescription: `This example shows how to use custom styling
161
- to change the appearance of the radio group to look more like
162
- a multiple choice question. Here, there is a line in
163
- between each question, which is achieved using the
164
- \`{borderTop: "solid 1px #CCC"}\` style on each \`Choice\`
165
- component.`,
166
- },
167
- };
168
-
169
- export const FiltersOutFalsyChildren: StoryComponentType = () => {
170
- return (
171
- <RadioGroup
172
- groupName="pokemon"
173
- selectedValue="bulbasaur"
174
- onChange={() => {}}
175
- label="Pokemon"
176
- description="Your first Pokemon."
177
- >
178
- <Choice label="Bulbasaur" value="bulbasaur" />
179
- <Choice
180
- label="Charmander"
181
- value="charmander"
182
- description="Oops, we ran out of Charmanders"
183
- disabled
184
- />
185
- <Choice label="Squirtle" value="squirtle" />
186
- {false && <Choice label="Pikachu" value="pikachu" />}
187
- </RadioGroup>
188
- );
189
- };
190
-
191
- FiltersOutFalsyChildren.parameters = {
192
- docs: {
193
- storyDescription: `This example shows that children can be falsy values and
194
- that those falsy values are filtered out when rendering children. In this
195
- case, one of the children is \`{false && <Choice .../>}\` which results in
196
- that choice being filtered out.`,
197
- },
198
- chromatic: {
199
- // The unit tests already verify that false-y children aren't rendered.
200
- disableSnapshot: true,
201
- },
202
- };
203
-
204
- const styles = StyleSheet.create({
205
- choice: {
206
- margin: 0,
207
- height: 48,
208
- borderTop: "solid 1px #CCC",
209
- justifyContent: "center",
210
- },
211
- lastChoice: {
212
- borderBottom: "solid 1px #CCC",
213
- },
214
- prompt: {
215
- marginBottom: 16,
216
- },
217
- });
@@ -1,161 +0,0 @@
1
- // @flow
2
- import * as React from "react";
3
- import {StyleSheet} from "aphrodite";
4
-
5
- import {View} from "@khanacademy/wonder-blocks-core";
6
- import {LabelMedium, LabelSmall} from "@khanacademy/wonder-blocks-typography";
7
- import type {StoryComponentType} from "@storybook/react";
8
-
9
- import ComponentInfo from "../../../../../.storybook/components/component-info";
10
- import {name, version} from "../../../package.json";
11
-
12
- import Radio from "../radio";
13
-
14
- export default {
15
- title: "Form / Radio (internal)",
16
- component: Radio,
17
- parameters: {
18
- componentSubtitle: ((
19
- <ComponentInfo name={name} version={version} />
20
- ): any),
21
- },
22
- };
23
-
24
- export const Default: StoryComponentType = (args) => <Radio {...args} />;
25
-
26
- Default.args = {
27
- checked: false,
28
- onChange: () => {},
29
- };
30
-
31
- Default.parameters = {
32
- chromatic: {
33
- // We already have screenshots of another story that covers
34
- // this and more cases.
35
- disableSnapshot: true,
36
- },
37
- };
38
-
39
- export const Controlled: StoryComponentType = () => {
40
- const [checked, setChecked] = React.useState(false);
41
- return <Radio checked={checked} onChange={setChecked} />;
42
- };
43
-
44
- Controlled.parameters = {
45
- chromatic: {
46
- // Disabling because this doesn't test visuals, it tests
47
- // that the `checked` state works as expected.
48
- disableSnapshot: true,
49
- },
50
- docs: {
51
- storyDescription: `Use state to keep track of whether
52
- the radio button has been checked. A radio button cannot be unchecked
53
- by the user once it has been checked. It would become unchecked if a
54
- different radio button is selected as part of a radio group.`,
55
- },
56
- };
57
-
58
- export const Variants: StoryComponentType = () => (
59
- <View style={styles.row}>
60
- <Radio checked={false} style={styles.marginRight} onChange={() => {}} />
61
- <Radio checked={true} style={styles.marginRight} onChange={() => {}} />
62
- <Radio
63
- error={true}
64
- checked={false}
65
- style={styles.marginRight}
66
- onChange={() => {}}
67
- />
68
- <Radio
69
- error={true}
70
- checked={true}
71
- style={styles.marginRight}
72
- onChange={() => {}}
73
- />
74
- <Radio
75
- disabled={true}
76
- checked={false}
77
- style={styles.marginRight}
78
- onChange={() => {}}
79
- />
80
- <Radio disabled={true} checked={true} onChange={() => {}} />
81
- </View>
82
- );
83
-
84
- Variants.parameters = {
85
- docs: {
86
- storyDescription: `The radio button has various styles for
87
- clickable states. Here are sets of default radio buttons,
88
- radio buttons in an error state, and disabled radio buttons.`,
89
- },
90
- };
91
-
92
- export const WithLabel: StoryComponentType = () => {
93
- const [checked, setChecked] = React.useState(false);
94
-
95
- return (
96
- <Radio
97
- label="Easy"
98
- description="Opt for a less difficult exercise set."
99
- checked={checked}
100
- onChange={setChecked}
101
- />
102
- );
103
- };
104
-
105
- WithLabel.parameters = {
106
- docs: {
107
- storyDescription: `The radio button can have an optional label
108
- and description. This allows it to be used as a settings-like item,
109
- as opposed to its usage in a radio grid.`,
110
- },
111
- };
112
-
113
- export const AdditionalClickTarget: StoryComponentType = () => {
114
- const [checked, setChecked] = React.useState(false);
115
- const headingText = "Functions";
116
- const descriptionText = `A great cook knows how to take basic
117
- ingredients and prepare a delicious meal. In this topic, you will
118
- become function-chefs! You will learn how to combine functions
119
- with arithmetic operations and how to compose functions.`;
120
-
121
- return (
122
- <View style={styles.wrapper}>
123
- <View style={styles.topic}>
124
- <label htmlFor="topic-123">
125
- <LabelMedium>{headingText}</LabelMedium>
126
- </label>
127
- <LabelSmall>{descriptionText}</LabelSmall>
128
- </View>
129
- <Radio checked={checked} id="topic-123" onChange={setChecked} />
130
- </View>
131
- );
132
- };
133
-
134
- AdditionalClickTarget.parameters = {
135
- docs: {
136
- storyDescription: `Sometimes one may wish to use a radio button
137
- in a different context (label may not be right next to the
138
- radio button), like in this example content item. Use a
139
- \`<label htmlFor={id}>\` element where the id matches the \`id\`
140
- prop of the Radio. This is for accessibility purposes,
141
- and doing this also automatically makes the label a click target
142
- for the radio button.`,
143
- },
144
- };
145
-
146
- const styles = StyleSheet.create({
147
- row: {
148
- flexDirection: "row",
149
- },
150
- marginRight: {
151
- marginRight: 16,
152
- },
153
- wrapper: {
154
- flexDirection: "row",
155
- alignItems: "center",
156
- justifyContent: "space-evenly",
157
- },
158
- topic: {
159
- maxWidth: 600,
160
- },
161
- });
@@ -1,206 +0,0 @@
1
- // @flow
2
-
3
- export default {
4
- id: {
5
- description: "The unique identifier for the input.",
6
- type: {required: true},
7
- table: {
8
- type: {
9
- summary: "string",
10
- },
11
- },
12
- control: {
13
- type: "text",
14
- },
15
- },
16
- type: {
17
- description:
18
- "Determines the type of input. Defaults to text. This may change the appearance or type of characters allowed.",
19
- table: {
20
- type: {
21
- summary: `"text" | "password" | "email" | "number" | "tel"`,
22
- },
23
- defaultValue: {
24
- summary: "text",
25
- },
26
- },
27
- options: ["text", "password", "email", "number", "tel"],
28
- control: {
29
- type: "select",
30
- },
31
- },
32
- value: {
33
- description: "The input value.",
34
- type: {required: true},
35
- table: {
36
- type: {
37
- summary: "string",
38
- },
39
- },
40
- control: {type: "text"},
41
- },
42
- autoComplete: {
43
- description: "Specifies if the input field allows autocomplete.",
44
- table: {
45
- type: {
46
- summary: "string",
47
- detail: `There is a large number of options, including "on", "off", "username", "current-password", and many others.`,
48
- },
49
- },
50
- control: {
51
- type: "text",
52
- },
53
- },
54
- disabled: {
55
- description: "Makes a read-only input field that cannot be focused.",
56
- table: {
57
- type: {
58
- summary: "boolean",
59
- },
60
- defaultValue: {
61
- summary: "false",
62
- },
63
- },
64
- control: {
65
- type: "boolean",
66
- },
67
- },
68
- light: {
69
- description:
70
- "Change the default focus ring color to fit a dark background.",
71
- table: {
72
- type: {
73
- summary: "boolean",
74
- },
75
- defaultValue: {
76
- summary: "false",
77
- },
78
- },
79
- control: {
80
- type: "boolean",
81
- },
82
- },
83
- required: {
84
- description:
85
- "Whether this field is required to to continue, or the error message to render if this field is left blank. Pass in a message instead of `true` if possible.",
86
- table: {
87
- type: {
88
- summary: "boolean | string",
89
- detail: "The string will not be used if a `validate` prop is passed in.",
90
- },
91
- },
92
- control: {
93
- type: "null",
94
- },
95
- },
96
- placeholder: {
97
- description: "Provide hints or examples of what to enter.",
98
- table: {
99
- type: {
100
- summary: "string",
101
- },
102
- },
103
- control: {
104
- type: "text",
105
- },
106
- },
107
- readOnly: {
108
- description: "Specifies if the input field is read-only.",
109
- table: {
110
- type: {
111
- summary: "boolean",
112
- },
113
- },
114
- control: {
115
- type: "boolean",
116
- },
117
- },
118
- style: {
119
- description: "Custom styles for the input.",
120
- table: {
121
- type: {
122
- summary: "StyleType",
123
- },
124
- },
125
- },
126
- testId: {
127
- description: "Optional test ID for e2e testing.",
128
- table: {
129
- type: {
130
- summary: "string",
131
- },
132
- },
133
- control: {
134
- type: "text",
135
- },
136
- },
137
- validate: {
138
- description:
139
- "Provide a validation for the input value. Return a string error message or null | void for a valid input.",
140
- table: {
141
- type: {
142
- summary: "(value: string) => ?string",
143
- },
144
- },
145
- control: {
146
- type: "null",
147
- },
148
- },
149
-
150
- /**
151
- * Events
152
- */
153
- onValidate: {
154
- description: "Called right after the TextField input is validated.",
155
- table: {
156
- category: "Events",
157
- type: {
158
- summary: "(errorMessage: ?string) => mixed",
159
- },
160
- },
161
- },
162
- onChange: {
163
- description:
164
- "Called when the value has changed. Use this in conjunction with the `value` prop to update the string rendered in the input field.",
165
- type: {required: true},
166
- table: {
167
- category: "Events",
168
- type: {
169
- summary: "(newValue: string) => mixed",
170
- },
171
- },
172
- },
173
- onKeyDown: {
174
- action: "keyDown",
175
- description: "Called when a key is pressed.",
176
- table: {
177
- category: "Events",
178
- type: {
179
- summary:
180
- "(event: SyntheticKeyboardEvent<HTMLInputElement>) => mixed",
181
- },
182
- },
183
- },
184
- onFocus: {
185
- action: "focus",
186
- description: "Called when the element has been focused.",
187
- table: {
188
- category: "Events",
189
- type: {
190
- summary:
191
- "(event: SyntheticFocusEvent<HTMLInputElement>) => mixed",
192
- },
193
- },
194
- },
195
- onBlur: {
196
- action: "blur",
197
- description: "Called when the element has been blurred.",
198
- table: {
199
- category: "Events",
200
- type: {
201
- summary:
202
- "(event: SyntheticFocusEvent<HTMLInputElement>) => mixed",
203
- },
204
- },
205
- },
206
- };