New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@khanacademy/wonder-blocks-form

Package Overview
Dependencies
Maintainers
1
Versions
612
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@khanacademy/wonder-blocks-form - npm Package Compare versions

Comparing version 1.5.0 to 1.6.0

66

dist/es/index.js

@@ -1,2 +0,2 @@

import { createElement, Fragment, Component, Children, cloneElement } from 'react';
import { createElement, Fragment, Component, Children, cloneElement, forwardRef } from 'react';
import { StyleSheet, css } from 'aphrodite';

@@ -1041,14 +1041,16 @@ import Color, { mix, fade } from '@khanacademy/wonder-blocks-color';

// TODO(WB-1081): Change class name back to TextField after Styleguidist is gone.
/**
* A TextField is an element used to accept a single line of text from the user.
*/
var TextField = /*#__PURE__*/function (_React$Component) {
_inherits(TextField, _React$Component);
var TextFieldInternal = /*#__PURE__*/function (_React$Component) {
_inherits(TextFieldInternal, _React$Component);
var _super = _createSuper(TextField);
var _super = _createSuper(TextFieldInternal);
function TextField(props) {
function TextFieldInternal(props) {
var _this;
_classCallCheck(this, TextField);
_classCallCheck(this, TextFieldInternal);

@@ -1121,3 +1123,3 @@ _this = _super.call(this, props);

_createClass(TextField, [{
_createClass(TextFieldInternal, [{
key: "componentDidMount",

@@ -1141,2 +1143,3 @@ value: function componentDidMount() {

testId = _this$props2.testId,
forwardedRef = _this$props2.forwardedRef,
onFocus = _this$props2.onFocus,

@@ -1147,3 +1150,3 @@ onBlur = _this$props2.onBlur,

onChange = _this$props2.onChange,
otherProps = _objectWithoutProperties(_this$props2, ["id", "type", "value", "disabled", "onKeyDown", "placeholder", "required", "light", "style", "testId", "onFocus", "onBlur", "onValidate", "validate", "onChange"]);
otherProps = _objectWithoutProperties(_this$props2, ["id", "type", "value", "disabled", "onKeyDown", "placeholder", "required", "light", "style", "testId", "forwardedRef", "onFocus", "onBlur", "onValidate", "validate", "onChange"]);

@@ -1163,3 +1166,4 @@ return /*#__PURE__*/createElement("input", _extends({

required: required,
"data-test-id": testId
"data-test-id": testId,
ref: forwardedRef
}, otherProps));

@@ -1169,6 +1173,6 @@ }

return TextField;
return TextFieldInternal;
}(Component);
_defineProperty(TextField, "defaultProps", {
_defineProperty(TextFieldInternal, "defaultProps", {
type: "text",

@@ -1178,2 +1182,3 @@ disabled: false,

});
var styles$4 = StyleSheet.create({

@@ -1229,2 +1234,7 @@ input: {

});
var TextField = forwardRef(function (props, ref) {
return /*#__PURE__*/createElement(TextFieldInternal, _extends({}, props, {
forwardedRef: ref
}));
});

@@ -1321,11 +1331,17 @@ var FieldHeading = /*#__PURE__*/function (_React$Component) {

var LabeledTextField = /*#__PURE__*/function (_React$Component) {
_inherits(LabeledTextField, _React$Component);
// TODO(WB-1081): Change class name back to LabeledTextField after Styleguidist is gone.
var _super = _createSuper(LabeledTextField);
/**
* A LabeledTextField is an element used to accept a single line of text
* from the user paired with a label, description, and error field elements.
*/
var LabeledTextFieldInternal = /*#__PURE__*/function (_React$Component) {
_inherits(LabeledTextFieldInternal, _React$Component);
function LabeledTextField(props) {
var _super = _createSuper(LabeledTextFieldInternal);
function LabeledTextFieldInternal(props) {
var _this;
_classCallCheck(this, LabeledTextField);
_classCallCheck(this, LabeledTextFieldInternal);

@@ -1390,3 +1406,3 @@ _this = _super.call(this, props);

_createClass(LabeledTextField, [{
_createClass(LabeledTextFieldInternal, [{
key: "render",

@@ -1407,3 +1423,4 @@ value: function render() {

style = _this$props.style,
testId = _this$props.testId;
testId = _this$props.testId,
forwardedRef = _this$props.forwardedRef;
return /*#__PURE__*/createElement(IDProvider, {

@@ -1432,3 +1449,4 @@ id: id,

light: light,
style: style
style: style,
ref: forwardedRef
}),

@@ -1443,6 +1461,6 @@ label: label,

return LabeledTextField;
return LabeledTextFieldInternal;
}(Component);
_defineProperty(LabeledTextField, "defaultProps", {
_defineProperty(LabeledTextFieldInternal, "defaultProps", {
type: "text",

@@ -1453,2 +1471,8 @@ disabled: false,

var LabeledTextField = forwardRef(function (props, ref) {
return /*#__PURE__*/createElement(LabeledTextFieldInternal, _extends({}, props, {
forwardedRef: ref
}));
});
export { Checkbox, CheckboxGroup, Choice, LabeledTextField, Radio, RadioGroup, TextField };
{
"name": "@khanacademy/wonder-blocks-form",
"version": "1.5.0",
"version": "1.6.0",
"design": "v1",

@@ -33,3 +33,3 @@ "description": "Form components for Wonder Blocks.",

},
"gitHead": "3614532cac2a6efa09dea648f728b04bc7f156b5"
"gitHead": "6529a7ca5f70d936fcf9388df73330e4024cad8d"
}

@@ -11,3 +11,3 @@ // This file is auto-generated by gen-snapshot-tests.js

jest.mock("react-dom");
import {View, Text} from "@khanacademy/wonder-blocks-core";
import {View} from "@khanacademy/wonder-blocks-core";
import {

@@ -19,4 +19,2 @@ Checkbox,

RadioGroup,
TextField,
LabeledTextField,
} from "@khanacademy/wonder-blocks-form";

@@ -31,4 +29,2 @@ import {StyleSheet} from "aphrodite";

import Color from "@khanacademy/wonder-blocks-color";
import {Strut} from "@khanacademy/wonder-blocks-layout";
import Spacing from "@khanacademy/wonder-blocks-spacing";

@@ -613,929 +609,2 @@ import CheckboxCore from "./../components/checkbox-core.js";

});
it("example 10", () => {
class TextFieldExample extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "",
};
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
}
handleChange(newValue) {
this.setState({
value: newValue,
});
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<TextField
id="tf-1"
type="text"
value={this.state.value}
placeholder="Text"
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
/>
);
}
}
const example = <TextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 11", () => {
class TextFieldExample extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "12345",
};
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
}
handleChange(newValue) {
this.setState({
value: newValue,
});
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<TextField
id="tf-1"
type="number"
value={this.state.value}
placeholder="Number"
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
/>
);
}
}
const example = <TextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 12", () => {
class TextFieldExample extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "Password123",
errorMessage: null,
focused: false,
};
this.validate = this.validate.bind(this);
this.handleValidate = this.handleValidate.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handleBlur = this.handleBlur.bind(this);
}
validate(value) {
if (value.length < 8) {
return "Password must be at least 8 characters long";
}
if (!/\d/.test(value)) {
return "Password must contain a numeric value";
}
}
handleValidate(errorMessage) {
this.setState({
errorMessage: errorMessage,
});
}
handleChange(newValue) {
this.setState({
value: newValue,
});
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
handleFocus() {
this.setState({
focused: true,
});
}
handleBlur() {
this.setState({
focused: false,
});
}
render() {
return (
<View>
<TextField
id="tf-1"
type="password"
value={this.state.value}
placeholder="Password"
validate={this.validate}
onValidate={this.handleValidate}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
{!this.state.focused && this.state.errorMessage && (
<View>
<Strut size={Spacing.xSmall_8} />
<Text style={styles.errorMessage}>
{this.state.errorMessage}
</Text>
</View>
)}
</View>
);
}
}
const styles = StyleSheet.create({
errorMessage: {
color: Color.red,
paddingLeft: Spacing.xxxSmall_4,
},
});
const example = <TextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 13", () => {
class TextFieldExample extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "khan@khanacademy.org",
errorMessage: null,
focused: false,
};
this.validate = this.validate.bind(this);
this.handleValidate = this.handleValidate.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handleBlur = this.handleBlur.bind(this);
}
validate(value) {
const emailRegex = /^[^@\s]+@[^@\s.]+\.[^@.\s]+$/;
if (!emailRegex.test(value)) {
return "Please enter a valid email";
}
}
handleValidate(errorMessage) {
this.setState({
errorMessage: errorMessage,
});
}
handleChange(newValue) {
this.setState({
value: newValue,
});
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
handleFocus() {
this.setState({
focused: true,
});
}
handleBlur() {
this.setState({
focused: false,
});
}
render() {
return (
<View>
<TextField
id="tf-1"
type="email"
value={this.state.value}
placeholder="Email"
validate={this.validate}
onValidate={this.handleValidate}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
{!this.state.focused && this.state.errorMessage && (
<View>
<Strut size={Spacing.xSmall_8} />
<Text style={styles.errorMessage}>
{this.state.errorMessage}
</Text>
</View>
)}
</View>
);
}
}
const styles = StyleSheet.create({
errorMessage: {
color: Color.red,
paddingLeft: Spacing.xxxSmall_4,
},
});
const example = <TextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 14", () => {
class TextFieldExample extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "123-456-7890",
errorMessage: null,
focused: false,
};
this.validate = this.validate.bind(this);
this.handleValidate = this.handleValidate.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handleBlur = this.handleBlur.bind(this);
}
validate(value) {
const telRegex = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
if (!telRegex.test(value)) {
return "Invalid US telephone number";
}
}
handleValidate(errorMessage) {
this.setState({
errorMessage: errorMessage,
});
}
handleChange(newValue) {
this.setState({
value: newValue,
});
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
handleFocus() {
this.setState({
focused: true,
});
}
handleBlur() {
this.setState({
focused: false,
});
}
render() {
return (
<View>
<TextField
id="tf-1"
type="email"
value={this.state.value}
placeholder="Telephone"
validate={this.validate}
onValidate={this.handleValidate}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
{!this.state.focused && this.state.errorMessage && (
<View>
<Strut size={Spacing.xSmall_8} />
<Text style={styles.errorMessage}>
{this.state.errorMessage}
</Text>
</View>
)}
</View>
);
}
}
const styles = StyleSheet.create({
errorMessage: {
color: Color.red,
paddingLeft: Spacing.xxxSmall_4,
},
});
const example = <TextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 15", () => {
class TextFieldExample extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "khan",
errorMessage: null,
focused: false,
};
this.validate = this.validate.bind(this);
this.handleValidate = this.handleValidate.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handleBlur = this.handleBlur.bind(this);
}
validate(value) {
const emailRegex = /^[^@\s]+@[^@\s.]+\.[^@.\s]+$/;
if (!emailRegex.test(value)) {
return "Please enter a valid email";
}
}
handleValidate(errorMessage) {
this.setState({
errorMessage: errorMessage,
});
}
handleChange(newValue) {
this.setState({
value: newValue,
});
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
handleFocus() {
this.setState({
focused: true,
});
}
handleBlur() {
this.setState({
focused: false,
});
}
render() {
return (
<View>
<TextField
id="tf-1"
type="email"
value={this.state.value}
placeholder="Email"
validate={this.validate}
onValidate={this.handleValidate}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
{!this.state.focused && this.state.errorMessage && (
<View>
<Strut size={Spacing.xSmall_8} />
<Text style={styles.errorMessage}>
{this.state.errorMessage}
</Text>
</View>
)}
</View>
);
}
}
const styles = StyleSheet.create({
errorMessage: {
color: Color.red,
paddingLeft: Spacing.xxxSmall_4,
},
});
const example = <TextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 16", () => {
const example = (
<TextField
id="tf-1"
value=""
placeholder="This field is disabled."
onChange={() => {}}
disabled={true}
/>
);
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 17", () => {
class TextFieldExample extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "khan@khanacademy.org",
errorMessage: null,
focused: false,
};
this.validate = this.validate.bind(this);
this.handleValidate = this.handleValidate.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handleBlur = this.handleBlur.bind(this);
}
validate(value) {
const emailRegex = /^[^@\s]+@[^@\s.]+\.[^@.\s]+$/;
if (!emailRegex.test(value)) {
return "Please enter a valid email";
}
}
handleValidate(errorMessage) {
this.setState({
errorMessage: errorMessage,
});
}
handleChange(newValue) {
this.setState({
value: newValue,
});
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
handleFocus() {
this.setState({
focused: true,
});
}
handleBlur() {
this.setState({
focused: false,
});
}
render() {
return (
<View style={styles.darkBackground}>
<TextField
id="tf-1"
type="email"
value={this.state.value}
light={true}
placeholder="Email"
validate={this.validate}
onValidate={this.handleValidate}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
{!this.state.focused && this.state.errorMessage && (
<View>
<Strut size={Spacing.xSmall_8} />
<Text style={styles.errorMessage}>
{this.state.errorMessage}
</Text>
</View>
)}
</View>
);
}
}
const styles = StyleSheet.create({
errorMessage: {
color: Color.white,
paddingLeft: Spacing.xxxSmall_4,
},
darkBackground: {
backgroundColor: Color.darkBlue,
padding: Spacing.medium_16,
},
});
const example = <TextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 18", () => {
class TextFieldExample extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "",
};
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
}
handleChange(newValue) {
this.setState({
value: newValue,
});
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<TextField
id="tf-1"
style={styles.customField}
type="text"
value={this.state.value}
placeholder="Text"
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
/>
);
}
}
const styles = StyleSheet.create({
customField: {
backgroundColor: Color.darkBlue,
color: Color.white,
border: "none",
maxWidth: 250,
"::placeholder": {
color: Color.white64,
},
},
});
const example = <TextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 19", () => {
class LabeledTextFieldExample extends React.Component {
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<LabeledTextField
label="Name"
description="Please enter your name"
initialValue="Khan"
placeholder="Name"
onKeyDown={this.handleKeyDown}
/>
);
}
}
const example = <LabeledTextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 20", () => {
class LabeledTextFieldExample extends React.Component {
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<LabeledTextField
label="Age"
type="number"
description="Please enter your age"
initialValue="18"
placeholder="Age"
onKeyDown={this.handleKeyDown}
/>
);
}
}
const example = <LabeledTextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 21", () => {
class LabeledTextFieldExample extends React.Component {
validate(value) {
if (value.length < 8) {
return "Password must be at least 8 characters long";
}
if (!/\d/.test(value)) {
return "Password must contain a numeric value";
}
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<LabeledTextField
label="Password"
type="password"
description="Please enter a secure password"
initialValue="Password123"
placeholder="Password"
validate={this.validate}
onKeyDown={this.handleKeyDown}
/>
);
}
}
const example = <LabeledTextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 22", () => {
class LabeledTextFieldExample extends React.Component {
validate(value) {
const emailRegex = /^[^@\s]+@[^@\s.]+\.[^@.\s]+$/;
if (!emailRegex.test(value)) {
return "Please enter a valid email";
}
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<LabeledTextField
label="Email"
type="email"
description="Please provide your personal email"
initialValue="khan@khan.org"
placeholder="Email"
validate={this.validate}
onKeyDown={this.handleKeyDown}
/>
);
}
}
const example = <LabeledTextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 23", () => {
class LabeledTextFieldExample extends React.Component {
validate(value) {
const telRegex = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
if (!telRegex.test(value)) {
return "Invalid US telephone number";
}
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<LabeledTextField
label="Telephone"
type="tel"
description="Please provide your personal phone number"
initialValue="123-456-7890"
placeholder="Telephone"
validate={this.validate}
onKeyDown={this.handleKeyDown}
/>
);
}
}
const example = <LabeledTextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 24", () => {
class LabeledTextFieldExample extends React.Component {
validate(value) {
const emailRegex = /^[^@\s]+@[^@\s.]+\.[^@.\s]+$/;
if (!emailRegex.test(value)) {
return "Please enter a valid email";
}
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<LabeledTextField
label="Email"
type="email"
description="Please enter your personal email"
initialValue="khan"
placeholder="Email"
validate={this.validate}
onKeyDown={this.handleKeyDown}
/>
);
}
}
const example = <LabeledTextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 25", () => {
const example = (
<LabeledTextField
label="Name"
description="Please enter your name"
placeholder="Name"
disabled={true}
/>
);
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 26", () => {
class LabeledTextFieldExample extends React.Component {
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<View style={styles.darkBackground}>
<LabeledTextField
label={
<LabelMedium style={styles.whiteColor}>
Name
</LabelMedium>
}
description={
<LabelSmall style={styles.offWhiteColor}>
Please enter your name
</LabelSmall>
}
placeholder="Name"
light={true}
onKeyDown={this.handleKeyDown}
/>
</View>
);
}
}
const styles = StyleSheet.create({
darkBackground: {
background: Color.darkBlue,
padding: `${Spacing.medium_16}px`,
},
whiteColor: {
color: Color.white,
},
offWhiteColor: {
color: Color.white64,
},
});
const example = <LabeledTextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 27", () => {
class LabeledTextFieldExample extends React.Component {
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
render() {
return (
<LabeledTextField
label="Name"
description="Please enter your name"
initialValue="Khan"
placeholder="Name"
style={styles.customField}
onKeyDown={this.handleKeyDown}
/>
);
}
}
const styles = StyleSheet.create({
customField: {
backgroundColor: Color.darkBlue,
color: Color.white,
border: "none",
maxWidth: 250,
"::placeholder": {
color: Color.white64,
},
},
});
const example = <LabeledTextFieldExample />;
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
});

@@ -18,3 +18,3 @@ //@flow

const wrapper = mount(<LabeledTextField label="Label" />);
const field = wrapper.find("TextField");
const field = wrapper.find("TextFieldInternal");

@@ -25,3 +25,6 @@ // Act

// Assert
expect(wrapper).toHaveState("focused", true);
expect(wrapper.find("LabeledTextFieldInternal")).toHaveState(
"focused",
true,
);
});

@@ -32,3 +35,3 @@

const wrapper = mount(<LabeledTextField label="Label" />);
const field = wrapper.find("TextField");
const field = wrapper.find("TextFieldInternal");

@@ -41,3 +44,6 @@ // Act

// Assert
expect(wrapper).toHaveState("focused", false);
expect(wrapper.find("LabeledTextFieldInternal")).toHaveState(
"focused",
false,
);
});

@@ -55,3 +61,6 @@

// Assert
expect(wrapper).toHaveState("value", newValue);
expect(wrapper.find("LabeledTextFieldInternal")).toHaveState(
"value",
newValue,
);
});

@@ -239,3 +248,3 @@

// Act
const field = wrapper.find("TextField");
const field = wrapper.find("TextFieldInternal");
field.simulate("focus");

@@ -255,3 +264,3 @@

// Act
const field = wrapper.find("TextField");
const field = wrapper.find("TextFieldInternal");
field.simulate("focus");

@@ -288,3 +297,3 @@ await wait(0);

// Assert
const textField = wrapper.find("TextField");
const textField = wrapper.find("TextFieldInternal");
expect(textField).toHaveProp("light", true);

@@ -308,3 +317,3 @@ });

// Assert
const textField = wrapper.find("TextField");
const textField = wrapper.find("TextFieldInternal");
expect(textField).toHaveStyle(styles.style1);

@@ -311,0 +320,0 @@ });

@@ -24,3 +24,3 @@ // @flow

// Assert
expect(wrapper).toHaveState("focused", true);
expect(wrapper.find("TextFieldInternal")).toHaveState("focused", true);
});

@@ -60,3 +60,3 @@

// Assert
expect(wrapper).toHaveState("focused", false);
expect(wrapper.find("TextFieldInternal")).toHaveState("focused", false);
});

@@ -63,0 +63,0 @@

@@ -10,2 +10,4 @@ // @flow

type WithForwardRef = {|forwardedRef: React.Ref<"input">|};
type Props = {|

@@ -95,6 +97,11 @@ /**

type PropsWithForwardRef = {|
...Props,
...WithForwardRef,
|};
type DefaultProps = {|
type: $PropertyType<Props, "type">,
disabled: $PropertyType<Props, "disabled">,
light: $PropertyType<Props, "light">,
type: $PropertyType<PropsWithForwardRef, "type">,
disabled: $PropertyType<PropsWithForwardRef, "disabled">,
light: $PropertyType<PropsWithForwardRef, "light">,
|};

@@ -119,3 +126,11 @@

export default class LabeledTextField extends React.Component<Props, State> {
// TODO(WB-1081): Change class name back to LabeledTextField after Styleguidist is gone.
/**
* A LabeledTextField is an element used to accept a single line of text
* from the user paired with a label, description, and error field elements.
*/
class LabeledTextFieldInternal extends React.Component<
PropsWithForwardRef,
State,
> {
static defaultProps: DefaultProps = {

@@ -127,3 +142,3 @@ type: "text",

constructor(props: Props) {
constructor(props: PropsWithForwardRef) {
super(props);

@@ -190,2 +205,3 @@ this.state = {

testId,
forwardedRef,
} = this.props;

@@ -219,2 +235,3 @@

style={style}
ref={forwardedRef}
/>

@@ -231,1 +248,15 @@ }

}
type ExportProps = $Diff<
React.ElementConfig<typeof LabeledTextFieldInternal>,
WithForwardRef,
>;
const LabeledTextField: React.AbstractComponent<
ExportProps,
HTMLInputElement,
> = React.forwardRef<ExportProps, HTMLInputElement>((props, ref) => (
<LabeledTextFieldInternal {...props} forwardedRef={ref} />
));
export default LabeledTextField;

@@ -318,2 +318,60 @@ LabeledTextField derives from TextField and allows the handling of single lines of text with convenient label, description, and error messages.

<LabeledTextFieldExample />
```
```
The field forwards its ref to the input
```js
import {View} from "@khanacademy/wonder-blocks-core";
import {LabeledTextField} from "@khanacademy/wonder-blocks-form";
import Button from "@khanacademy/wonder-blocks-button";
import {Strut} from "@khanacademy/wonder-blocks-layout";
import Spacing from "@khanacademy/wonder-blocks-spacing";
import {StyleSheet} from "aphrodite";
class LabeledTextFieldExample extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
this.handleSubmit = this.handleSubmit.bind(this);
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
handleSubmit() {
if (this.inputRef.current) {
this.inputRef.current.focus();
}
}
render() {
return (
<View>
<LabeledTextField
label="Name"
description="Please enter your name"
initialValue="Khan"
placeholder="Name"
onKeyDown={this.handleKeyDown}
ref={this.inputRef}
/>
<Strut size={Spacing.medium_16} />
<Button style={styles.button} onClick={this.handleSubmit}>
Focus Input
</Button>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
maxWidth: 150,
},
});
<LabeledTextFieldExample />
```

@@ -9,2 +9,4 @@ // @flow

import Spacing from "@khanacademy/wonder-blocks-spacing";
import {Strut} from "@khanacademy/wonder-blocks-layout";
import Button from "@khanacademy/wonder-blocks-button";
import {StyleSheet} from "aphrodite";

@@ -218,2 +220,35 @@

export const ref: StoryComponentType = () => {
const inputRef = React.createRef<HTMLInputElement>();
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter") {
event.currentTarget.blur();
}
};
const handleSubmit = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
return (
<View>
<LabeledTextField
label="Name"
description="Please enter your name"
initialValue="Khan"
placeholder="Name"
onKeyDown={handleKeyDown}
ref={inputRef}
/>
<Strut size={Spacing.medium_16} />
<Button style={styles.button} onClick={handleSubmit}>
Focus Input
</Button>
</View>
);
};
const styles = StyleSheet.create({

@@ -239,2 +274,5 @@ darkBackground: {

},
button: {
maxWidth: 150,
},
});

@@ -13,2 +13,4 @@ // @flow

type WithForwardRef = {|forwardedRef: React.Ref<"input">|};
type Props = {|

@@ -94,6 +96,11 @@ ...AriaProps,

type PropsWithForwardRef = {|
...Props,
...WithForwardRef,
|};
type DefaultProps = {|
type: $PropertyType<Props, "type">,
disabled: $PropertyType<Props, "disabled">,
light: $PropertyType<Props, "light">,
type: $PropertyType<PropsWithForwardRef, "type">,
disabled: $PropertyType<PropsWithForwardRef, "disabled">,
light: $PropertyType<PropsWithForwardRef, "light">,
|};

@@ -113,6 +120,7 @@

// TODO(WB-1081): Change class name back to TextField after Styleguidist is gone.
/**
* A TextField is an element used to accept a single line of text from the user.
*/
export default class TextField extends React.Component<Props, State> {
class TextFieldInternal extends React.Component<PropsWithForwardRef, State> {
static defaultProps: DefaultProps = {

@@ -124,3 +132,3 @@ type: "text",

constructor(props: Props) {
constructor(props: PropsWithForwardRef) {
super(props);

@@ -197,2 +205,3 @@ if (props.validate) {

testId,
forwardedRef,
// The following props are being included here to avoid

@@ -238,2 +247,3 @@ // passing them down to the otherProps spread

data-test-id={testId}
ref={forwardedRef}
{...otherProps}

@@ -295,1 +305,15 @@ />

});
type ExportProps = $Diff<
React.ElementConfig<typeof TextFieldInternal>,
WithForwardRef,
>;
const TextField: React.AbstractComponent<
ExportProps,
HTMLInputElement,
> = React.forwardRef<ExportProps, HTMLInputElement>((props, ref) => (
<TextFieldInternal {...props} forwardedRef={ref} />
));
export default TextField;

@@ -71,3 +71,3 @@ Text

<TextField
id="tf-1"
id="tf-2"
type="number"

@@ -147,3 +147,3 @@ value={this.state.value}

<TextField
id="tf-1"
id="tf-3"
type="password"

@@ -239,3 +239,3 @@ value={this.state.value}

<TextField
id="tf-1"
id="tf-4"
type="email"

@@ -331,3 +331,3 @@ value={this.state.value}

<TextField
id="tf-1"
id="tf-5"
type="email"

@@ -423,3 +423,3 @@ value={this.state.value}

<TextField
id="tf-1"
id="tf-6"
type="email"

@@ -462,3 +462,3 @@ value={this.state.value}

<TextField
id="tf-1" value=""
id="tf-7" value=""
placeholder="This field is disabled."

@@ -529,3 +529,3 @@ onChange={() => {}}

<TextField
id="tf-1"
id="tf-8"
type="email"

@@ -598,3 +598,3 @@ value={this.state.value}

<TextField
id="tf-1"
id="tf-9"
style={styles.customField}

@@ -625,1 +625,69 @@ type="text"

```
Using Ref
```js
import {View} from "@khanacademy/wonder-blocks-core";
import {TextField} from "@khanacademy/wonder-blocks-form";
import Button from "@khanacademy/wonder-blocks-button";
import {Strut} from "@khanacademy/wonder-blocks-layout";
import Spacing from "@khanacademy/wonder-blocks-spacing";
import {StyleSheet} from "aphrodite";
class TextFieldExample extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "",
};
this.inputRef = React.createRef();
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(newValue) {
this.setState({value: newValue});
}
handleKeyDown(event) {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}
handleSubmit() {
if (this.inputRef.current) {
this.inputRef.current.focus();
}
}
render() {
return (
<View>
<TextField
id="tf-10"
type="text"
value={this.state.value}
placeholder="Text"
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
ref={this.inputRef}
/>
<Strut size={Spacing.medium_16} />
<Button style={styles.button} onClick={this.handleSubmit}>
Focus Input
</Button>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
maxWidth: 150,
},
});
<TextFieldExample />
```

@@ -10,2 +10,3 @@ // @flow

import {TextField} from "@khanacademy/wonder-blocks-form";
import Button from "@khanacademy/wonder-blocks-button";

@@ -397,2 +398,41 @@ import type {StoryComponentType} from "@storybook/react";

export const ref: StoryComponentType = () => {
const [value, setValue] = React.useState("");
const inputRef: RefObject<typeof HTMLInputElement> = React.createRef();
const handleChange = (newValue: string) => {
setValue(newValue);
};
const handleKeyDown = (event: SyntheticKeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter") {
event.currentTarget.blur();
}
};
const handleSubmit = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
return (
<View>
<TextField
id="tf-1"
type="text"
value={value}
placeholder="Text"
onChange={handleChange}
onKeyDown={handleKeyDown}
ref={inputRef}
/>
<Strut size={Spacing.medium_16} />
<Button style={styles.button} onClick={handleSubmit}>
Focus Input
</Button>
</View>
);
};
const styles = StyleSheet.create({

@@ -420,2 +460,5 @@ errorMessage: {

},
button: {
maxWidth: 150,
},
});

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc