@khanacademy/wonder-blocks-form
Advanced tools
Comparing version 2.4.2 to 2.4.3
# @khanacademy/wonder-blocks-form | ||
## 2.4.3 | ||
### Patch Changes | ||
- @khanacademy/wonder-blocks-clickable@2.2.6 | ||
- @khanacademy/wonder-blocks-core@4.3.1 | ||
- @khanacademy/wonder-blocks-icon@1.2.27 | ||
- @khanacademy/wonder-blocks-layout@1.4.9 | ||
- @khanacademy/wonder-blocks-typography@1.1.31 | ||
## 2.4.2 | ||
@@ -4,0 +14,0 @@ |
@@ -27,6 +27,2 @@ import _extends from '@babel/runtime/helpers/extends'; | ||
}; | ||
/** | ||
* The internal stateless ☑️ Checkbox | ||
*/ | ||
class CheckboxCore extends React.Component { | ||
@@ -37,3 +33,2 @@ constructor(...args) { | ||
this.handleChange = () => { | ||
// Empty because change is handled by ClickableBehavior | ||
return; | ||
@@ -64,3 +59,3 @@ }; | ||
}; | ||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledInput$1, _extends({}, sharedProps, { | ||
return React.createElement(React.Fragment, null, React.createElement(StyledInput$1, _extends({}, sharedProps, { | ||
type: "checkbox", | ||
@@ -71,8 +66,6 @@ "aria-invalid": error, | ||
id: id, | ||
name: groupName // Need to specify because this is a controlled React form | ||
// component, but we handle the click via ClickableBehavior | ||
, | ||
name: groupName, | ||
onChange: this.handleChange, | ||
style: defaultStyle | ||
}, props)), checked && /*#__PURE__*/React.createElement(Icon, { | ||
}, props)), checked && React.createElement(Icon, { | ||
color: disabled ? offBlack32$1 : white$1, | ||
@@ -88,3 +81,2 @@ icon: checkboxCheck, | ||
const sharedStyles$1 = StyleSheet.create({ | ||
// Reset the default styled input element | ||
inputReset: { | ||
@@ -137,3 +129,2 @@ appearance: "none", | ||
const _generateStyles$1 = (checked, error) => { | ||
// "hash" the parameters | ||
const styleKey = `${String(checked)}-${String(error)}`; | ||
@@ -196,6 +187,2 @@ | ||
const StyledInput = addStyle("input"); | ||
/** | ||
* The internal stateless 🔘 Radio button | ||
*/ | ||
class RadioCore extends React.Component { | ||
@@ -206,3 +193,2 @@ constructor(...args) { | ||
this.handleChange = () => { | ||
// Empty because change is handled by ClickableBehavior | ||
return; | ||
@@ -233,3 +219,3 @@ }; | ||
}; | ||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledInput, _extends({}, sharedProps, { | ||
return React.createElement(React.Fragment, null, React.createElement(StyledInput, _extends({}, sharedProps, { | ||
type: "radio", | ||
@@ -240,8 +226,6 @@ "aria-invalid": error, | ||
id: id, | ||
name: groupName // Need to specify because this is a controlled React form | ||
// component, but we handle the click via ClickableBehavior | ||
, | ||
name: groupName, | ||
onChange: this.handleChange, | ||
style: defaultStyle | ||
}, props)), disabled && checked && /*#__PURE__*/React.createElement("span", { | ||
}, props)), disabled && checked && React.createElement("span", { | ||
style: disabledChecked | ||
@@ -252,4 +236,3 @@ })); | ||
} | ||
const size = 16; // circle with a different color. Here, we add that center circle. // If the checkbox is disabled and selected, it has a border but also an inner | ||
const size = 16; | ||
const disabledChecked = { | ||
@@ -265,3 +248,2 @@ position: "absolute", | ||
const sharedStyles = StyleSheet.create({ | ||
// Reset the default styled input element | ||
inputReset: { | ||
@@ -310,3 +292,2 @@ appearance: "none", | ||
const _generateStyles = (checked, error) => { | ||
// "hash" the parameters | ||
const styleKey = `${String(checked)}-${String(error)}`; | ||
@@ -360,11 +341,2 @@ | ||
const _excluded$2 = ["label", "description", "onChange", "style", "className", "variant"]; | ||
/** | ||
* This is a potentially labeled 🔘 or ☑️ item. This is an internal component | ||
* that's wrapped by Checkbox and Radio. Choice is a wrapper for Checkbox and | ||
* Radio with many of its props auto-populated, to be used with CheckboxGroup | ||
* and RadioGroup. This design allows for more explicit prop typing. For | ||
* example, we can make onChange a required prop on Checkbox but not on Choice | ||
* (because for Choice, that prop would be auto-populated by CheckboxGroup). | ||
*/ | ||
class ChoiceInternal extends React.Component { | ||
@@ -375,4 +347,2 @@ constructor(...args) { | ||
this.handleLabelClick = event => { | ||
// Browsers automatically use the for attribute to select the input, | ||
// but we use ClickableBehavior to handle this. | ||
event.preventDefault(); | ||
@@ -386,3 +356,3 @@ }; | ||
variant | ||
} = this.props; // Radio buttons cannot be unchecked | ||
} = this.props; | ||
@@ -411,5 +381,5 @@ if (variant === "radio" && checked) { | ||
} = this.props; | ||
return /*#__PURE__*/React.createElement(LabelMedium, { | ||
return React.createElement(LabelMedium, { | ||
style: [styles$3.label, disabled && styles$3.disabledLabel] | ||
}, /*#__PURE__*/React.createElement("label", { | ||
}, React.createElement("label", { | ||
htmlFor: id, | ||
@@ -424,3 +394,3 @@ onClick: this.handleLabelClick | ||
} = this.props; | ||
return /*#__PURE__*/React.createElement(LabelSmall, { | ||
return React.createElement(LabelSmall, { | ||
style: styles$3.description, | ||
@@ -444,3 +414,3 @@ id: id | ||
const ClickableBehavior = getClickableBehavior(); | ||
return /*#__PURE__*/React.createElement(UniqueIDProvider, { | ||
return React.createElement(UniqueIDProvider, { | ||
mockOnFirstRender: true, | ||
@@ -450,6 +420,6 @@ scope: "choice" | ||
const descriptionId = description && ids.get("description"); | ||
return /*#__PURE__*/React.createElement(View, { | ||
return React.createElement(View, { | ||
style: style, | ||
className: className | ||
}, /*#__PURE__*/React.createElement(ClickableBehavior, { | ||
}, React.createElement(ClickableBehavior, { | ||
disabled: coreProps.disabled, | ||
@@ -459,12 +429,9 @@ onClick: this.handleClick, | ||
}, (state, childrenProps) => { | ||
return /*#__PURE__*/React.createElement(View, _extends({ | ||
return React.createElement(View, _extends({ | ||
style: styles$3.wrapper | ||
}, childrenProps, { | ||
// We are resetting the tabIndex=0 from handlers | ||
// because the ChoiceCore component will receive | ||
// focus on basis of it being an input element. | ||
tabIndex: -1 | ||
}), /*#__PURE__*/React.createElement(ChoiceCore, _extends({}, coreProps, state, { | ||
}), React.createElement(ChoiceCore, _extends({}, coreProps, state, { | ||
"aria-describedby": descriptionId | ||
})), /*#__PURE__*/React.createElement(Strut, { | ||
})), React.createElement(Strut, { | ||
size: Spacing.xSmall_8 | ||
@@ -490,6 +457,2 @@ }), label && this.getLabel()); | ||
userSelect: "none", | ||
// NOTE: The checkbox/radio button (height 16px) should be center | ||
// aligned with the first line of the label. However, LabelMedium has a | ||
// declared line height of 20px, so we need to adjust the top to get the | ||
// desired alignment. | ||
marginTop: -2 | ||
@@ -501,3 +464,2 @@ }, | ||
description: { | ||
// 16 for icon + 8 for spacing strut | ||
marginLeft: Spacing.medium_16 + Spacing.xSmall_8, | ||
@@ -509,12 +471,5 @@ marginTop: Spacing.xxxSmall_4, | ||
/** | ||
* ☑️ A nicely styled checkbox for all your checking needs. Can optionally take | ||
* label and description props. | ||
* | ||
* If you want a whole group of Checkbox[es] that are related, see the Choice | ||
* and CheckboxGroup components. | ||
*/ | ||
class Checkbox extends React.Component { | ||
render() { | ||
return /*#__PURE__*/React.createElement(ChoiceInternal, _extends({ | ||
return React.createElement(ChoiceInternal, _extends({ | ||
variant: "checkbox" | ||
@@ -530,12 +485,5 @@ }, this.props)); | ||
/** | ||
* 🔘 A nicely styled radio button for all your non-AMFM radio button needs. Can | ||
* optionally take label and description props. | ||
* | ||
* This component should not really be used by itself because radio buttons are | ||
* often grouped together. See RadioGroup. | ||
*/ | ||
class Radio extends React.Component { | ||
render() { | ||
return /*#__PURE__*/React.createElement(ChoiceInternal, _extends({ | ||
return React.createElement(ChoiceInternal, _extends({ | ||
variant: "radio" | ||
@@ -552,12 +500,2 @@ }, this.props)); | ||
const _excluded$1 = ["value", "variant"]; | ||
/** | ||
* This is a labeled 🔘 or ☑️ item. Choice is meant to be used as children of | ||
* CheckboxGroup and RadioGroup because many of its props are auto-populated | ||
* and not shown in the documentation here. See those components for usage | ||
* examples. | ||
* | ||
* If you wish to use just a single field, use Checkbox or Radio with the | ||
* optional label and description props. | ||
*/ | ||
class Choice extends React.Component { | ||
@@ -573,4 +511,2 @@ getChoiceComponent(variant) { | ||
render() { | ||
// we don't need this going into the ChoiceComponent | ||
// eslint-disable-next-line no-unused-vars | ||
const _this$props = this.props, | ||
@@ -583,3 +519,3 @@ { | ||
const ChoiceComponent = this.getChoiceComponent(variant); | ||
return /*#__PURE__*/React.createElement(ChoiceComponent, remainingProps); | ||
return React.createElement(ChoiceComponent, remainingProps); | ||
} | ||
@@ -618,9 +554,2 @@ | ||
const StyledLegend$1 = addStyle("legend"); | ||
/** | ||
* A checkbox group allows multiple selection. This component auto-populates | ||
* many props for its children Choice components. The Choice component is | ||
* exposed for the user to apply custom styles or to indicate which choices are | ||
* disabled. | ||
*/ | ||
class CheckboxGroup extends React.Component { | ||
@@ -653,14 +582,14 @@ handleChange(changedValue, originalCheckedState) { | ||
} = this.props; | ||
return /*#__PURE__*/React.createElement(StyledFieldset$1, { | ||
return React.createElement(StyledFieldset$1, { | ||
"data-test-id": testId, | ||
style: styles$2.fieldset | ||
}, /*#__PURE__*/React.createElement(View, { | ||
}, React.createElement(View, { | ||
style: style | ||
}, typeof label === "string" ? /*#__PURE__*/React.createElement(StyledLegend$1, { | ||
}, typeof label === "string" ? React.createElement(StyledLegend$1, { | ||
style: styles$2.legend | ||
}, /*#__PURE__*/React.createElement(LabelMedium, null, label)) : label && label, typeof description === "string" ? /*#__PURE__*/React.createElement(LabelSmall, { | ||
}, React.createElement(LabelMedium, null, label)) : label && label, typeof description === "string" ? React.createElement(LabelSmall, { | ||
style: styles$2.description | ||
}, description) : description && description, errorMessage && /*#__PURE__*/React.createElement(LabelSmall, { | ||
}, description) : description && description, errorMessage && React.createElement(LabelSmall, { | ||
style: styles$2.error | ||
}, errorMessage), (label || description || errorMessage) && /*#__PURE__*/React.createElement(Strut, { | ||
}, errorMessage), (label || description || errorMessage) && React.createElement(Strut, { | ||
size: Spacing.small_12 | ||
@@ -673,3 +602,3 @@ }), React.Children.map(children, (child, index) => { | ||
const checked = selectedValues.includes(value); | ||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.cloneElement(child, { | ||
return React.createElement(React.Fragment, null, React.cloneElement(child, { | ||
checked: checked, | ||
@@ -691,11 +620,2 @@ error: !!errorMessage, | ||
const StyledLegend = addStyle("legend"); | ||
/** | ||
* A radio group allows only single selection. Like CheckboxGroup, this | ||
* component auto-populates many props for its children Choice components. The | ||
* Choice component is exposed for the user to apply custom styles or to | ||
* indicate which choices are disabled. The use of the groupName prop is | ||
* important to maintain expected keyboard navigation behavior for | ||
* accessibility. | ||
*/ | ||
class RadioGroup extends React.Component { | ||
@@ -717,14 +637,14 @@ handleChange(changedValue) { | ||
} = this.props; | ||
return /*#__PURE__*/React.createElement(StyledFieldset, { | ||
return React.createElement(StyledFieldset, { | ||
"data-test-id": testId, | ||
style: styles$2.fieldset | ||
}, /*#__PURE__*/React.createElement(View, { | ||
}, React.createElement(View, { | ||
style: style | ||
}, label && /*#__PURE__*/React.createElement(StyledLegend, { | ||
}, label && React.createElement(StyledLegend, { | ||
style: styles$2.legend | ||
}, /*#__PURE__*/React.createElement(LabelMedium, null, label)), description && /*#__PURE__*/React.createElement(LabelSmall, { | ||
}, React.createElement(LabelMedium, null, label)), description && React.createElement(LabelSmall, { | ||
style: styles$2.description | ||
}, description), errorMessage && /*#__PURE__*/React.createElement(LabelSmall, { | ||
}, description), errorMessage && React.createElement(LabelSmall, { | ||
style: styles$2.error | ||
}, errorMessage), (label || description || errorMessage) && /*#__PURE__*/React.createElement(Strut, { | ||
}, errorMessage), (label || description || errorMessage) && React.createElement(Strut, { | ||
size: Spacing.small_12 | ||
@@ -737,3 +657,3 @@ }), React.Children.map(children, (child, index) => { | ||
const checked = selectedValue === value; | ||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.cloneElement(child, { | ||
return React.createElement(React.Fragment, null, React.cloneElement(child, { | ||
checked: checked, | ||
@@ -756,7 +676,2 @@ error: !!errorMessage, | ||
// 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. | ||
*/ | ||
class TextFieldInternal extends React.Component { | ||
@@ -835,3 +750,2 @@ constructor(props) { | ||
if (props.validate && props.value !== "") { | ||
// Ensures error is updated on unmounted server-side renders | ||
this.state.error = props.validate(props.value) || null; | ||
@@ -865,5 +779,4 @@ } | ||
return /*#__PURE__*/React.createElement("input", _extends({ | ||
className: css([styles$1.input, styles$6.LabelMedium, styles$1.default, // Prioritizes disabled, then focused, then error (if any) | ||
disabled ? styles$1.disabled : this.state.focused ? [styles$1.focused, light && styles$1.defaultLight] : this.state.error && [styles$1.error, light && styles$1.errorLight], style && style]), | ||
return React.createElement("input", _extends({ | ||
className: css([styles$1.input, styles$6.LabelMedium, styles$1.default, disabled ? styles$1.disabled : this.state.focused ? [styles$1.focused, light && styles$1.defaultLight] : this.state.error && [styles$1.error, light && styles$1.errorLight], style && style]), | ||
id: id, | ||
@@ -942,3 +855,3 @@ type: type, | ||
}); | ||
const TextField = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(TextFieldInternal, _extends({}, props, { | ||
const TextField = React.forwardRef((props, ref) => React.createElement(TextFieldInternal, _extends({}, props, { | ||
forwardedRef: ref | ||
@@ -948,7 +861,2 @@ }))); | ||
const StyledSpan = addStyle("span"); | ||
/** | ||
* A FieldHeading is an element that provides a label, description, and error element | ||
* to present better context and hints to any type of form field component. | ||
*/ | ||
class FieldHeading extends React.Component { | ||
@@ -962,7 +870,7 @@ renderLabel() { | ||
} = this.props; | ||
const requiredIcon = /*#__PURE__*/React.createElement(StyledSpan, { | ||
const requiredIcon = React.createElement(StyledSpan, { | ||
style: styles.required, | ||
"aria-hidden": true | ||
}, " ", "*"); | ||
return /*#__PURE__*/React.createElement(React.Fragment, null, typeof label === "string" ? /*#__PURE__*/React.createElement(LabelMedium, { | ||
return React.createElement(React.Fragment, null, typeof label === "string" ? React.createElement(LabelMedium, { | ||
style: styles.label, | ||
@@ -972,3 +880,3 @@ tag: "label", | ||
testId: testId && `${testId}-label` | ||
}, label, required && requiredIcon) : label, /*#__PURE__*/React.createElement(Strut, { | ||
}, label, required && requiredIcon) : label, React.createElement(Strut, { | ||
size: Spacing.xxxSmall_4 | ||
@@ -988,6 +896,6 @@ })); | ||
return /*#__PURE__*/React.createElement(React.Fragment, null, typeof description === "string" ? /*#__PURE__*/React.createElement(LabelSmall, { | ||
return React.createElement(React.Fragment, null, typeof description === "string" ? React.createElement(LabelSmall, { | ||
style: styles.description, | ||
testId: testId && `${testId}-description` | ||
}, description) : description, /*#__PURE__*/React.createElement(Strut, { | ||
}, description) : description, React.createElement(Strut, { | ||
size: Spacing.xxxSmall_4 | ||
@@ -1008,5 +916,5 @@ })); | ||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Strut, { | ||
return React.createElement(React.Fragment, null, React.createElement(Strut, { | ||
size: Spacing.small_12 | ||
}), typeof error === "string" ? /*#__PURE__*/React.createElement(LabelSmall, { | ||
}), typeof error === "string" ? React.createElement(LabelSmall, { | ||
style: styles.error, | ||
@@ -1024,5 +932,5 @@ role: "alert", | ||
} = this.props; | ||
return /*#__PURE__*/React.createElement(View, { | ||
return React.createElement(View, { | ||
style: style | ||
}, this.renderLabel(), this.maybeRenderDescription(), /*#__PURE__*/React.createElement(Strut, { | ||
}, this.renderLabel(), this.maybeRenderDescription(), React.createElement(Strut, { | ||
size: Spacing.xSmall_8 | ||
@@ -1048,8 +956,2 @@ }), field, this.maybeRenderError()); | ||
// 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 { | ||
@@ -1125,10 +1027,10 @@ constructor(props) { | ||
} = this.props; | ||
return /*#__PURE__*/React.createElement(IDProvider, { | ||
return React.createElement(IDProvider, { | ||
id: id, | ||
scope: "labeled-text-field" | ||
}, uniqueId => /*#__PURE__*/React.createElement(FieldHeading, { | ||
}, uniqueId => React.createElement(FieldHeading, { | ||
id: uniqueId, | ||
testId: testId, | ||
style: style, | ||
field: /*#__PURE__*/React.createElement(TextField, { | ||
field: React.createElement(TextField, { | ||
id: `${uniqueId}-field`, | ||
@@ -1169,3 +1071,3 @@ "aria-describedby": ariaDescribedby ? ariaDescribedby : `${uniqueId}-error`, | ||
}; | ||
const LabeledTextField = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(LabeledTextFieldInternal, _extends({}, props, { | ||
const LabeledTextField = React.forwardRef((props, ref) => React.createElement(LabeledTextFieldInternal, _extends({}, props, { | ||
forwardedRef: ref | ||
@@ -1172,0 +1074,0 @@ }))); |
{ | ||
"name": "@khanacademy/wonder-blocks-form", | ||
"version": "2.4.2", | ||
"version": "2.4.3", | ||
"design": "v1", | ||
@@ -19,9 +19,9 @@ "description": "Form components for Wonder Blocks.", | ||
"@babel/runtime": "^7.16.3", | ||
"@khanacademy/wonder-blocks-clickable": "^2.2.5", | ||
"@khanacademy/wonder-blocks-clickable": "^2.2.6", | ||
"@khanacademy/wonder-blocks-color": "^1.1.20", | ||
"@khanacademy/wonder-blocks-core": "^4.3.0", | ||
"@khanacademy/wonder-blocks-icon": "^1.2.26", | ||
"@khanacademy/wonder-blocks-layout": "^1.4.8", | ||
"@khanacademy/wonder-blocks-core": "^4.3.1", | ||
"@khanacademy/wonder-blocks-icon": "^1.2.27", | ||
"@khanacademy/wonder-blocks-layout": "^1.4.9", | ||
"@khanacademy/wonder-blocks-spacing": "^3.0.5", | ||
"@khanacademy/wonder-blocks-typography": "^1.1.30" | ||
"@khanacademy/wonder-blocks-typography": "^1.1.31" | ||
}, | ||
@@ -33,4 +33,4 @@ "peerDependencies": { | ||
"devDependencies": { | ||
"wb-dev-build-settings": "^0.3.0" | ||
"wb-dev-build-settings": "^0.4.0" | ||
} | ||
} |
492083
6873