@khanacademy/wonder-blocks-form 2.3.0 → 2.4.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/CHANGELOG.md +24 -0
- package/dist/es/index.js +216 -190
- package/dist/index.js +33 -7
- package/package.json +11 -12
- package/src/components/__tests__/checkbox-group.test.js +1 -0
- package/src/components/__tests__/field-heading.test.js +1 -0
- package/src/components/__tests__/labeled-text-field.test.js +140 -0
- package/src/components/__tests__/radio-group.test.js +1 -0
- package/src/components/__tests__/text-field.test.js +1 -18
- package/src/components/checkbox-core.js +1 -2
- package/src/components/field-heading.js +20 -2
- package/src/components/labeled-text-field.js +32 -6
- package/src/components/labeled-text-field.stories.js +98 -12
- package/src/components/text-field.js +43 -13
- package/src/components/text-field.stories.js +45 -18
- package/LICENSE +0 -21
|
@@ -16,7 +16,7 @@ export default {
|
|
|
16
16
|
title: "Form / LabeledTextField",
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export const
|
|
19
|
+
export const Text: StoryComponentType = () => {
|
|
20
20
|
const [value, setValue] = React.useState("Khan");
|
|
21
21
|
|
|
22
22
|
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
|
@@ -37,7 +37,56 @@ export const text: StoryComponentType = () => {
|
|
|
37
37
|
);
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
export const
|
|
40
|
+
export const RequiredWithDefaultText: StoryComponentType = () => {
|
|
41
|
+
const [value, setValue] = React.useState("");
|
|
42
|
+
|
|
43
|
+
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
|
44
|
+
if (event.key === "Enter") {
|
|
45
|
+
event.currentTarget.blur();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<LabeledTextField
|
|
51
|
+
label="Name"
|
|
52
|
+
description="Please enter your name"
|
|
53
|
+
value={value}
|
|
54
|
+
onChange={(newValue) => setValue(newValue)}
|
|
55
|
+
onKeyDown={handleKeyDown}
|
|
56
|
+
required={true}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const RequiredWithSpecifiedText: StoryComponentType = () => {
|
|
62
|
+
const [value, setValue] = React.useState("");
|
|
63
|
+
|
|
64
|
+
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
|
65
|
+
if (event.key === "Enter") {
|
|
66
|
+
event.currentTarget.blur();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<LabeledTextField
|
|
72
|
+
label="Name"
|
|
73
|
+
description="Please enter your name"
|
|
74
|
+
value={value}
|
|
75
|
+
onChange={(newValue) => setValue(newValue)}
|
|
76
|
+
onKeyDown={handleKeyDown}
|
|
77
|
+
required="This specific field is super required."
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
RequiredWithSpecifiedText.parameters = {
|
|
83
|
+
chromatic: {
|
|
84
|
+
// We have screenshots of other stories that cover this case.
|
|
85
|
+
disableSnapshot: true,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const Number: StoryComponentType = () => {
|
|
41
90
|
const [value, setValue] = React.useState("18");
|
|
42
91
|
|
|
43
92
|
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
|
@@ -59,7 +108,7 @@ export const number: StoryComponentType = () => {
|
|
|
59
108
|
);
|
|
60
109
|
};
|
|
61
110
|
|
|
62
|
-
export const
|
|
111
|
+
export const Password: StoryComponentType = () => {
|
|
63
112
|
const [value, setValue] = React.useState("Password123");
|
|
64
113
|
|
|
65
114
|
const validate = (value: string) => {
|
|
@@ -91,7 +140,7 @@ export const password: StoryComponentType = () => {
|
|
|
91
140
|
);
|
|
92
141
|
};
|
|
93
142
|
|
|
94
|
-
export const
|
|
143
|
+
export const Email: StoryComponentType = () => {
|
|
95
144
|
const [value, setValue] = React.useState("khan@khan.org");
|
|
96
145
|
|
|
97
146
|
const validate = (value: string) => {
|
|
@@ -121,7 +170,44 @@ export const email: StoryComponentType = () => {
|
|
|
121
170
|
);
|
|
122
171
|
};
|
|
123
172
|
|
|
124
|
-
export const
|
|
173
|
+
export const EmailRequired: StoryComponentType = () => {
|
|
174
|
+
const [value, setValue] = React.useState("");
|
|
175
|
+
|
|
176
|
+
const validate = (value: string) => {
|
|
177
|
+
const emailRegex = /^[^@\s]+@[^@\s.]+\.[^@.\s]+$/;
|
|
178
|
+
if (!emailRegex.test(value)) {
|
|
179
|
+
return "Please enter a valid email";
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
|
184
|
+
if (event.key === "Enter") {
|
|
185
|
+
event.currentTarget.blur();
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
return (
|
|
190
|
+
<LabeledTextField
|
|
191
|
+
label="Email"
|
|
192
|
+
type="email"
|
|
193
|
+
onChange={(newValue) => setValue(newValue)}
|
|
194
|
+
description="Please provide your personal email"
|
|
195
|
+
value={value}
|
|
196
|
+
validate={validate}
|
|
197
|
+
onKeyDown={handleKeyDown}
|
|
198
|
+
required={true}
|
|
199
|
+
/>
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
EmailRequired.parameters = {
|
|
204
|
+
chromatic: {
|
|
205
|
+
// We have screenshots of other stories that cover this case.
|
|
206
|
+
disableSnapshot: true,
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export const Telephone: StoryComponentType = () => {
|
|
125
211
|
const [value, setValue] = React.useState("123-456-7890");
|
|
126
212
|
|
|
127
213
|
const validate = (value: string) => {
|
|
@@ -151,7 +237,7 @@ export const telephone: StoryComponentType = () => {
|
|
|
151
237
|
);
|
|
152
238
|
};
|
|
153
239
|
|
|
154
|
-
export const
|
|
240
|
+
export const Error: StoryComponentType = () => {
|
|
155
241
|
const [value, setValue] = React.useState("khan");
|
|
156
242
|
|
|
157
243
|
const validate = (value: string) => {
|
|
@@ -181,7 +267,7 @@ export const error: StoryComponentType = () => {
|
|
|
181
267
|
);
|
|
182
268
|
};
|
|
183
269
|
|
|
184
|
-
export const
|
|
270
|
+
export const Disabled: StoryComponentType = () => (
|
|
185
271
|
<LabeledTextField
|
|
186
272
|
label="Name"
|
|
187
273
|
description="Please enter your name"
|
|
@@ -192,7 +278,7 @@ export const disabled: StoryComponentType = () => (
|
|
|
192
278
|
/>
|
|
193
279
|
);
|
|
194
280
|
|
|
195
|
-
export const
|
|
281
|
+
export const Light: StoryComponentType = () => {
|
|
196
282
|
const [value, setValue] = React.useState("");
|
|
197
283
|
|
|
198
284
|
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
|
@@ -222,7 +308,7 @@ export const light: StoryComponentType = () => {
|
|
|
222
308
|
);
|
|
223
309
|
};
|
|
224
310
|
|
|
225
|
-
export const
|
|
311
|
+
export const CustomStyle: StoryComponentType = () => {
|
|
226
312
|
const [firstName, setFirstName] = React.useState("");
|
|
227
313
|
const [lastName, setLastName] = React.useState("");
|
|
228
314
|
|
|
@@ -257,7 +343,7 @@ export const customStyle: StoryComponentType = () => {
|
|
|
257
343
|
);
|
|
258
344
|
};
|
|
259
345
|
|
|
260
|
-
export const
|
|
346
|
+
export const Ref: StoryComponentType = () => {
|
|
261
347
|
const [value, setValue] = React.useState("Khan");
|
|
262
348
|
const inputRef = React.createRef();
|
|
263
349
|
|
|
@@ -292,7 +378,7 @@ export const ref: StoryComponentType = () => {
|
|
|
292
378
|
);
|
|
293
379
|
};
|
|
294
380
|
|
|
295
|
-
export const
|
|
381
|
+
export const ReadOnly: StoryComponentType = () => {
|
|
296
382
|
const [value, setValue] = React.useState("Khan");
|
|
297
383
|
|
|
298
384
|
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
|
@@ -314,7 +400,7 @@ export const readOnly: StoryComponentType = () => {
|
|
|
314
400
|
);
|
|
315
401
|
};
|
|
316
402
|
|
|
317
|
-
export const
|
|
403
|
+
export const AutoComplete: StoryComponentType = () => {
|
|
318
404
|
const [value, setValue] = React.useState("");
|
|
319
405
|
|
|
320
406
|
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
|
@@ -12,6 +12,8 @@ export type TextFieldType = "text" | "password" | "email" | "number" | "tel";
|
|
|
12
12
|
|
|
13
13
|
type WithForwardRef = {|forwardedRef: React.Ref<"input">|};
|
|
14
14
|
|
|
15
|
+
const defaultErrorMessage = "This field is required.";
|
|
16
|
+
|
|
15
17
|
type Props = {|
|
|
16
18
|
...AriaProps,
|
|
17
19
|
|
|
@@ -72,9 +74,28 @@ type Props = {|
|
|
|
72
74
|
placeholder?: string,
|
|
73
75
|
|
|
74
76
|
/**
|
|
75
|
-
* Whether this
|
|
77
|
+
* Whether this field is required to to continue, or the error message to
|
|
78
|
+
* render if this field is left blank.
|
|
79
|
+
*
|
|
80
|
+
* This can be a boolean or a string.
|
|
81
|
+
*
|
|
82
|
+
* String:
|
|
83
|
+
* Please pass in a translated string to use as the error message that will
|
|
84
|
+
* render if the user leaves this field blank. If this field is required,
|
|
85
|
+
* and a string is not passed in, a default untranslated string will render
|
|
86
|
+
* upon error.
|
|
87
|
+
* Note: The string will not be used if a `validate` prop is passed in.
|
|
88
|
+
*
|
|
89
|
+
* Example message: i18n._("A password is required to log in.")
|
|
90
|
+
*
|
|
91
|
+
* Boolean:
|
|
92
|
+
* True/false indicating whether this field is required. Please do not pass
|
|
93
|
+
* in `true` if possible - pass in the error string instead.
|
|
94
|
+
* If `true` is passed, and a `validate` prop is not passed, that means
|
|
95
|
+
* there is no corresponding message and the default untranlsated message
|
|
96
|
+
* will be used.
|
|
76
97
|
*/
|
|
77
|
-
required?: boolean,
|
|
98
|
+
required?: boolean | string,
|
|
78
99
|
|
|
79
100
|
/**
|
|
80
101
|
* Change the default focus ring color to fit a dark background.
|
|
@@ -138,7 +159,7 @@ class TextFieldInternal extends React.Component<PropsWithForwardRef, State> {
|
|
|
138
159
|
|
|
139
160
|
constructor(props: PropsWithForwardRef) {
|
|
140
161
|
super(props);
|
|
141
|
-
if (props.validate) {
|
|
162
|
+
if (props.validate && props.value !== "") {
|
|
142
163
|
// Ensures error is updated on unmounted server-side renders
|
|
143
164
|
this.state.error = props.validate(props.value) || null;
|
|
144
165
|
}
|
|
@@ -150,11 +171,14 @@ class TextFieldInternal extends React.Component<PropsWithForwardRef, State> {
|
|
|
150
171
|
};
|
|
151
172
|
|
|
152
173
|
componentDidMount() {
|
|
153
|
-
|
|
174
|
+
if (this.props.value !== "") {
|
|
175
|
+
this.maybeValidate(this.props.value);
|
|
176
|
+
}
|
|
154
177
|
}
|
|
155
178
|
|
|
156
179
|
maybeValidate: (newValue: string) => void = (newValue) => {
|
|
157
|
-
const {validate, onValidate} = this.props;
|
|
180
|
+
const {validate, onValidate, required} = this.props;
|
|
181
|
+
|
|
158
182
|
if (validate) {
|
|
159
183
|
const maybeError = validate(newValue) || null;
|
|
160
184
|
this.setState({error: maybeError}, () => {
|
|
@@ -162,6 +186,15 @@ class TextFieldInternal extends React.Component<PropsWithForwardRef, State> {
|
|
|
162
186
|
onValidate(maybeError);
|
|
163
187
|
}
|
|
164
188
|
});
|
|
189
|
+
} else if (required) {
|
|
190
|
+
const requiredString =
|
|
191
|
+
typeof required === "string" ? required : defaultErrorMessage;
|
|
192
|
+
const maybeError = newValue ? null : requiredString;
|
|
193
|
+
this.setState({error: maybeError}, () => {
|
|
194
|
+
if (onValidate) {
|
|
195
|
+
onValidate(maybeError);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
165
198
|
}
|
|
166
199
|
};
|
|
167
200
|
|
|
@@ -204,7 +237,6 @@ class TextFieldInternal extends React.Component<PropsWithForwardRef, State> {
|
|
|
204
237
|
disabled,
|
|
205
238
|
onKeyDown,
|
|
206
239
|
placeholder,
|
|
207
|
-
required,
|
|
208
240
|
light,
|
|
209
241
|
style,
|
|
210
242
|
testId,
|
|
@@ -219,6 +251,7 @@ class TextFieldInternal extends React.Component<PropsWithForwardRef, State> {
|
|
|
219
251
|
onValidate,
|
|
220
252
|
validate,
|
|
221
253
|
onChange,
|
|
254
|
+
required,
|
|
222
255
|
/* eslint-enable no-unused-vars */
|
|
223
256
|
// Should only include Aria related props
|
|
224
257
|
...otherProps
|
|
@@ -249,7 +282,6 @@ class TextFieldInternal extends React.Component<PropsWithForwardRef, State> {
|
|
|
249
282
|
onKeyDown={onKeyDown}
|
|
250
283
|
onFocus={this.handleFocus}
|
|
251
284
|
onBlur={this.handleBlur}
|
|
252
|
-
required={required}
|
|
253
285
|
data-test-id={testId}
|
|
254
286
|
readOnly={readOnly}
|
|
255
287
|
autoComplete={autoComplete}
|
|
@@ -316,11 +348,9 @@ type ExportProps = $Diff<
|
|
|
316
348
|
WithForwardRef,
|
|
317
349
|
>;
|
|
318
350
|
|
|
319
|
-
const TextField: React.AbstractComponent<
|
|
320
|
-
ExportProps,
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
<TextFieldInternal {...props} forwardedRef={ref} />
|
|
324
|
-
));
|
|
351
|
+
const TextField: React.AbstractComponent<ExportProps, HTMLInputElement> =
|
|
352
|
+
React.forwardRef<ExportProps, HTMLInputElement>((props, ref) => (
|
|
353
|
+
<TextFieldInternal {...props} forwardedRef={ref} />
|
|
354
|
+
));
|
|
325
355
|
|
|
326
356
|
export default TextField;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import {StyleSheet} from "aphrodite";
|
|
4
4
|
|
|
5
|
-
import {View, Text} from "@khanacademy/wonder-blocks-core";
|
|
5
|
+
import {View, Text as _Text} from "@khanacademy/wonder-blocks-core";
|
|
6
6
|
import Color from "@khanacademy/wonder-blocks-color";
|
|
7
7
|
import {Strut} from "@khanacademy/wonder-blocks-layout";
|
|
8
8
|
import Spacing from "@khanacademy/wonder-blocks-spacing";
|
|
@@ -15,7 +15,7 @@ export default {
|
|
|
15
15
|
title: "Form / TextField",
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
export const
|
|
18
|
+
export const Text: StoryComponentType = () => {
|
|
19
19
|
const [value, setValue] = React.useState("");
|
|
20
20
|
|
|
21
21
|
const handleChange = (newValue: string) => {
|
|
@@ -40,7 +40,32 @@ export const text: StoryComponentType = () => {
|
|
|
40
40
|
);
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
export const
|
|
43
|
+
export const Required: StoryComponentType = () => {
|
|
44
|
+
const [value, setValue] = React.useState("");
|
|
45
|
+
|
|
46
|
+
const handleChange = (newValue: string) => {
|
|
47
|
+
setValue(newValue);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
|
|
51
|
+
if (event.key === "Enter") {
|
|
52
|
+
event.currentTarget.blur();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<TextField
|
|
58
|
+
id="tf-1"
|
|
59
|
+
type="text"
|
|
60
|
+
value={value}
|
|
61
|
+
onChange={handleChange}
|
|
62
|
+
onKeyDown={handleKeyDown}
|
|
63
|
+
required={true}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const Number: StoryComponentType = () => {
|
|
44
69
|
const [value, setValue] = React.useState("12345");
|
|
45
70
|
|
|
46
71
|
const handleChange = (newValue: string) => {
|
|
@@ -65,7 +90,7 @@ export const number: StoryComponentType = () => {
|
|
|
65
90
|
);
|
|
66
91
|
};
|
|
67
92
|
|
|
68
|
-
export const
|
|
93
|
+
export const Password: StoryComponentType = () => {
|
|
69
94
|
const [value, setValue] = React.useState("Password123");
|
|
70
95
|
const [errorMessage, setErrorMessage] = React.useState();
|
|
71
96
|
const [focused, setFocused] = React.useState(false);
|
|
@@ -118,14 +143,14 @@ export const password: StoryComponentType = () => {
|
|
|
118
143
|
{!focused && errorMessage && (
|
|
119
144
|
<View>
|
|
120
145
|
<Strut size={Spacing.xSmall_8} />
|
|
121
|
-
<
|
|
146
|
+
<_Text style={styles.errorMessage}>{errorMessage}</_Text>
|
|
122
147
|
</View>
|
|
123
148
|
)}
|
|
124
149
|
</View>
|
|
125
150
|
);
|
|
126
151
|
};
|
|
127
152
|
|
|
128
|
-
export const
|
|
153
|
+
export const Email: StoryComponentType = () => {
|
|
129
154
|
const [value, setValue] = React.useState("khan@khanacademy.org");
|
|
130
155
|
const [errorMessage, setErrorMessage] = React.useState();
|
|
131
156
|
const [focused, setFocused] = React.useState(false);
|
|
@@ -176,14 +201,14 @@ export const email: StoryComponentType = () => {
|
|
|
176
201
|
{!focused && errorMessage && (
|
|
177
202
|
<View>
|
|
178
203
|
<Strut size={Spacing.xSmall_8} />
|
|
179
|
-
<
|
|
204
|
+
<_Text style={styles.errorMessage}>{errorMessage}</_Text>
|
|
180
205
|
</View>
|
|
181
206
|
)}
|
|
182
207
|
</View>
|
|
183
208
|
);
|
|
184
209
|
};
|
|
185
210
|
|
|
186
|
-
export const
|
|
211
|
+
export const Telephone: StoryComponentType = () => {
|
|
187
212
|
const [value, setValue] = React.useState("123-456-7890");
|
|
188
213
|
const [errorMessage, setErrorMessage] = React.useState();
|
|
189
214
|
const [focused, setFocused] = React.useState(false);
|
|
@@ -234,14 +259,14 @@ export const telephone: StoryComponentType = () => {
|
|
|
234
259
|
{!focused && errorMessage && (
|
|
235
260
|
<View>
|
|
236
261
|
<Strut size={Spacing.xSmall_8} />
|
|
237
|
-
<
|
|
262
|
+
<_Text style={styles.errorMessage}>{errorMessage}</_Text>
|
|
238
263
|
</View>
|
|
239
264
|
)}
|
|
240
265
|
</View>
|
|
241
266
|
);
|
|
242
267
|
};
|
|
243
268
|
|
|
244
|
-
export const
|
|
269
|
+
export const Error: StoryComponentType = () => {
|
|
245
270
|
const [value, setValue] = React.useState("khan");
|
|
246
271
|
const [errorMessage, setErrorMessage] = React.useState();
|
|
247
272
|
const [focused, setFocused] = React.useState(false);
|
|
@@ -292,14 +317,14 @@ export const error: StoryComponentType = () => {
|
|
|
292
317
|
{!focused && errorMessage && (
|
|
293
318
|
<View>
|
|
294
319
|
<Strut size={Spacing.xSmall_8} />
|
|
295
|
-
<
|
|
320
|
+
<_Text style={styles.errorMessage}>{errorMessage}</_Text>
|
|
296
321
|
</View>
|
|
297
322
|
)}
|
|
298
323
|
</View>
|
|
299
324
|
);
|
|
300
325
|
};
|
|
301
326
|
|
|
302
|
-
export const
|
|
327
|
+
export const Disabled: StoryComponentType = () => (
|
|
303
328
|
<TextField
|
|
304
329
|
id="tf-1"
|
|
305
330
|
value=""
|
|
@@ -309,7 +334,7 @@ export const disabled: StoryComponentType = () => (
|
|
|
309
334
|
/>
|
|
310
335
|
);
|
|
311
336
|
|
|
312
|
-
export const
|
|
337
|
+
export const Light: StoryComponentType = () => {
|
|
313
338
|
const [value, setValue] = React.useState("khan@khanacademy.org");
|
|
314
339
|
const [errorMessage, setErrorMessage] = React.useState();
|
|
315
340
|
const [focused, setFocused] = React.useState(false);
|
|
@@ -361,14 +386,16 @@ export const light: StoryComponentType = () => {
|
|
|
361
386
|
{!focused && errorMessage && (
|
|
362
387
|
<View>
|
|
363
388
|
<Strut size={Spacing.xSmall_8} />
|
|
364
|
-
<
|
|
389
|
+
<_Text style={styles.errorMessageLight}>
|
|
390
|
+
{errorMessage}
|
|
391
|
+
</_Text>
|
|
365
392
|
</View>
|
|
366
393
|
)}
|
|
367
394
|
</View>
|
|
368
395
|
);
|
|
369
396
|
};
|
|
370
397
|
|
|
371
|
-
export const
|
|
398
|
+
export const CustomStyle: StoryComponentType = () => {
|
|
372
399
|
const [value, setValue] = React.useState("");
|
|
373
400
|
|
|
374
401
|
const handleChange = (newValue: string) => {
|
|
@@ -394,7 +421,7 @@ export const customStyle: StoryComponentType = () => {
|
|
|
394
421
|
);
|
|
395
422
|
};
|
|
396
423
|
|
|
397
|
-
export const
|
|
424
|
+
export const Ref: StoryComponentType = () => {
|
|
398
425
|
const [value, setValue] = React.useState("");
|
|
399
426
|
const inputRef: RefObject<typeof HTMLInputElement> = React.createRef();
|
|
400
427
|
|
|
@@ -433,7 +460,7 @@ export const ref: StoryComponentType = () => {
|
|
|
433
460
|
);
|
|
434
461
|
};
|
|
435
462
|
|
|
436
|
-
export const
|
|
463
|
+
export const ReadOnly: StoryComponentType = () => {
|
|
437
464
|
const [value, setValue] = React.useState("Khan");
|
|
438
465
|
|
|
439
466
|
const handleChange = (newValue: string) => {
|
|
@@ -459,7 +486,7 @@ export const readOnly: StoryComponentType = () => {
|
|
|
459
486
|
);
|
|
460
487
|
};
|
|
461
488
|
|
|
462
|
-
export const
|
|
489
|
+
export const AutoComplete: StoryComponentType = () => {
|
|
463
490
|
const [value, setValue] = React.useState("");
|
|
464
491
|
|
|
465
492
|
const handleChange = (newValue: string) => {
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2018 Khan Academy
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|