@khanacademy/wonder-blocks-form 7.6.14 → 7.7.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/.turbo/turbo-build$colon$css.log +1 -1
- package/CHANGELOG.md +20 -0
- package/dist/components/text-area.d.ts +4 -4
- package/dist/components/text-field.d.ts +4 -4
- package/dist/es/index.js +2 -1
- package/dist/hooks/use-field-validation.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +3 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @khanacademy/wonder-blocks-form@7.
|
|
2
|
+
> @khanacademy/wonder-blocks-form@7.7.0 build:css /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-form
|
|
3
3
|
> pnpm exec wonder-blocks-tokens .
|
|
4
4
|
|
|
5
5
|
CSS variables generated successfully in: /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-form/dist/css
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-form
|
|
2
2
|
|
|
3
|
+
## 7.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9ec3189: The default required field error message in TextField and TextArea now reads a translated string from `WonderBlocksConfigProvider`. Passing a string to the `required` prop overrides the built-in translation.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [9ec3189]
|
|
12
|
+
- Updated dependencies [f070142]
|
|
13
|
+
- Updated dependencies [355f6e1]
|
|
14
|
+
- @khanacademy/wonder-blocks-config@0.4.0
|
|
15
|
+
|
|
16
|
+
## 7.6.15
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [66bae92]
|
|
21
|
+
- @khanacademy/wonder-blocks-clickable@8.3.1
|
|
22
|
+
|
|
3
23
|
## 7.6.14
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -170,8 +170,8 @@ declare const TextArea: React.ForwardRefExoticComponent<Readonly<import("@khanac
|
|
|
170
170
|
* String:
|
|
171
171
|
* Please pass in a translated string to use as the error message that will
|
|
172
172
|
* render if the user leaves this textarea blank. If this textarea is required,
|
|
173
|
-
* and a string is not passed in,
|
|
174
|
-
* upon error.
|
|
173
|
+
* and a string is not passed in, the default `requiredFieldMessage` string
|
|
174
|
+
* from `WonderBlocksConfigProvider` will render upon error.
|
|
175
175
|
* Note: The string will not be used if a `validate` prop is passed in.
|
|
176
176
|
*
|
|
177
177
|
* Example message: i18n._("A password is required to log in.")
|
|
@@ -180,8 +180,8 @@ declare const TextArea: React.ForwardRefExoticComponent<Readonly<import("@khanac
|
|
|
180
180
|
* True/false indicating whether this textarea is required. Please do not pass
|
|
181
181
|
* in `true` if possible - pass in the error string instead.
|
|
182
182
|
* If `true` is passed, and a `validate` prop is not passed, that means
|
|
183
|
-
* there is no corresponding message and the default
|
|
184
|
-
* will be used.
|
|
183
|
+
* there is no corresponding message and the default `requiredFieldMessage`
|
|
184
|
+
* string from `WonderBlocksConfigProvider` will be used.
|
|
185
185
|
*/
|
|
186
186
|
required?: boolean | string;
|
|
187
187
|
/**
|
|
@@ -91,8 +91,8 @@ type CommonProps = AriaProps & {
|
|
|
91
91
|
* String:
|
|
92
92
|
* Please pass in a translated string to use as the error message that will
|
|
93
93
|
* render if the user leaves this field blank. If this field is required,
|
|
94
|
-
* and a string is not passed in,
|
|
95
|
-
* upon error.
|
|
94
|
+
* and a string is not passed in, the default `requiredFieldMessage` string
|
|
95
|
+
* from `WonderBlocksConfigProvider` will render upon error.
|
|
96
96
|
* Note: The string will not be used if a `validate` prop is passed in.
|
|
97
97
|
*
|
|
98
98
|
* Example message: i18n._("A password is required to log in.")
|
|
@@ -101,8 +101,8 @@ type CommonProps = AriaProps & {
|
|
|
101
101
|
* True/false indicating whether this field is required. Please do not pass
|
|
102
102
|
* in `true` if possible - pass in the error string instead.
|
|
103
103
|
* If `true` is passed, and a `validate` prop is not passed, that means
|
|
104
|
-
* there is no corresponding message and the default
|
|
105
|
-
* will be used.
|
|
104
|
+
* there is no corresponding message and the default `requiredFieldMessage`
|
|
105
|
+
* string from `WonderBlocksConfigProvider` will be used.
|
|
106
106
|
*/
|
|
107
107
|
required?: boolean | string;
|
|
108
108
|
/**
|
package/dist/es/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
|
9
9
|
import checkIcon from '@phosphor-icons/core/bold/check-bold.svg';
|
|
10
10
|
import minusIcon from '@phosphor-icons/core/bold/minus-bold.svg';
|
|
11
11
|
import { focusStyles } from '@khanacademy/wonder-blocks-styles';
|
|
12
|
+
import { useWonderBlocksI18n } from '@khanacademy/wonder-blocks-config';
|
|
12
13
|
|
|
13
14
|
var themeDefault = {choice:{inputWrapper:{layout:{padding:sizing.size_0,margin:sizing.size_0}}},description:{color:{foreground:semanticColor.core.foreground.neutral.default}},field:{border:{radius:border.radius.radius_040,width:{error:border.width.thin,press:border.width.none}},sizing:{height:sizing.size_400},layout:{paddingBlock:sizing.size_100,paddingInline:sizing.size_160}}};
|
|
14
15
|
|
|
@@ -34,7 +35,7 @@ const StyledFieldset$1=addStyle("fieldset");const StyledLegend$1=addStyle("legen
|
|
|
34
35
|
|
|
35
36
|
const StyledFieldset=addStyle("fieldset");const StyledLegend=addStyle("legend");const RadioGroup=React.forwardRef(function RadioGroup(props,ref){const{children,label,description,errorMessage,groupName,onChange,selectedValue,style,testId}=props;const allChildren=React.Children.toArray(children).filter(Boolean);return jsxs(StyledFieldset,{"data-testid":testId,style:[styles$3.fieldset,style],ref:ref,children:[label&&jsx(StyledLegend,{style:styles$3.legend,children:jsx(BodyText,{tag:"span",children:label})}),description&&jsx(BodyText,{size:"small",style:styles$3.description,children:description}),errorMessage&&jsx(BodyText,{size:"small",style:styles$3.error,children:errorMessage}),allChildren.map((child,index)=>{const{style,value}=child.props;const checked=selectedValue===value;const hasMeta=!!(label||description||errorMessage);return React.cloneElement(child,{checked:checked,error:!!errorMessage,groupName:groupName,id:`${groupName}-${value}`,key:value,onChange:()=>onChange(value),style:[index===0&&hasMeta&&styles$3.firstChoiceMetaSpacing,index>0&&styles$3.choiceLineGap,style],variant:"radio"})})]})});
|
|
36
37
|
|
|
37
|
-
const
|
|
38
|
+
const useFieldValidation=({value,disabled=false,validate,onValidate,required=false,instantValidation=true})=>{const{strings}=useWonderBlocksI18n();const[errorMessage,setErrorMessage]=React.useState(()=>validate&&value!==""&&!disabled&&validate(value)||null);const onChangeValidation=newValue=>{if(instantValidation){handleValidation(newValue);}else {setErrorMessage(null);if(onValidate){onValidate(null);}}};const onBlurValidation=newValue=>{if(!instantValidation){if(newValue||required){handleValidation(newValue);}}};const handleValidation=newValue=>{if(disabled){return}if(validate){const error=validate(newValue)||null;setErrorMessage(error);if(onValidate){onValidate(error);}}else if(required){const requiredString=typeof required==="string"?required:strings.requiredFieldMessage;const error=newValue?null:requiredString;setErrorMessage(error);if(onValidate){onValidate(error);}}};useOnMountEffect(()=>{if(value!==""){handleValidation(value);}});return {errorMessage,onBlurValidation,onChangeValidation}};
|
|
38
39
|
|
|
39
40
|
const StyledInput=addStyle("input");const TextField=props=>{const{id,type="text",value,name,disabled=false,error,validate,onValidate,required,placeholder,style,testId,readOnly,autoFocus,autoComplete,forwardedRef,instantValidation=true,onKeyDown,onChange,onFocus,onBlur,onPaste,...otherProps}=props;const{errorMessage,onBlurValidation,onChangeValidation}=useFieldValidation({value,required,disabled,instantValidation,validate,onValidate});const hasError=error||!!errorMessage;const handleChange=event=>{if(type==="whole-number"){const newValue=event.target.value.replace(/[^0-9]/g,"");onChangeValidation(newValue);onChange(newValue);return}const newValue=event.target.value;onChangeValidation(newValue);onChange(newValue);};const handleFocus=event=>{if(onFocus){onFocus(event);}};const handleBlur=event=>{onBlurValidation(event.target.value);if(onBlur){onBlur(event);}};const handleKeyDown=event=>{if(type==="whole-number"){if(event.key==="."||event.key==="+"||event.key==="-"||event.key==="e"||event.key==="E"){event.preventDefault();}}onKeyDown?.(event);};return jsx(Id,{id:id,children:uniqueId=>jsx(StyledInput,{style:[styles$2.input,styles$7.BodyTextMediumMediumWeight,styles$2.default,disabled&&styles$2.disabled,hasError&&styles$2.error,readOnly&&styles$2.readOnly,style],id:uniqueId,type:type==="whole-number"?"number":type,placeholder:placeholder,value:value,name:name,"aria-disabled":disabled,"aria-required":!!required,onChange:handleChange,onKeyDown:disabled?undefined:handleKeyDown,onFocus:handleFocus,onBlur:handleBlur,onPaste:disabled?undefined:onPaste,"data-testid":testId,readOnly:readOnly||disabled,autoFocus:autoFocus,autoComplete:autoComplete,ref:forwardedRef,"aria-invalid":hasError,...otherProps})})};const ACTIVE_BOX_SHADOW$1=`0 0 0 ${theme.field.border.width.press} ${semanticColor.input.default.border}`;const styles$2=StyleSheet.create({input:{width:"100%",height:theme.field.sizing.height,borderRadius:theme.field.border.radius,boxSizing:"border-box",paddingInline:theme.field.layout.paddingInline,paddingBlock:theme.field.layout.paddingBlock,margin:sizing.size_0},readOnly:{background:semanticColor.input.readOnly.background,color:semanticColor.input.readOnly.text},default:{background:semanticColor.input.default.background,border:`${border.width.thin} solid ${semanticColor.input.default.border}`,color:semanticColor.input.default.foreground,"::placeholder":{color:semanticColor.input.default.placeholder},...focusStyles.focus,[":active:not([aria-disabled='true']):not([readonly])"]:{boxShadow:ACTIVE_BOX_SHADOW$1},[":focus-visible:active:not([aria-disabled='true']):not([readonly])"]:{boxShadow:`${ACTIVE_BOX_SHADOW$1}, ${focusStyles.focus[":focus-visible"].boxShadow}`}},error:{background:semanticColor.input.error.background,border:`${theme.field.border.width.error} solid ${semanticColor.input.error.border}`,color:semanticColor.input.error.foreground,"::placeholder":{color:semanticColor.input.default.placeholder},[":focus-visible:active:not([aria-disabled='true']):not([readonly])"]:{boxShadow:`${ACTIVE_BOX_SHADOW$1}, ${focusStyles.focus[":focus-visible"].boxShadow}`}},disabled:{background:semanticColor.input.disabled.background,border:`${border.width.thin} solid ${semanticColor.input.disabled.border}`,color:semanticColor.input.disabled.foreground,"::placeholder":{color:semanticColor.input.disabled.placeholder},cursor:"not-allowed"}});var TextField$1 = React.forwardRef((props,ref)=>jsx(TextField,{...props,forwardedRef:ref}));
|
|
40
41
|
|
|
@@ -17,7 +17,8 @@ type FieldValidationProps = {
|
|
|
17
17
|
* - `value` - The value of the field.
|
|
18
18
|
* - `disabled` - If the field is disabled.
|
|
19
19
|
* - `required` - Whether the field is required to continue, or the error
|
|
20
|
-
* message if it is left blank.
|
|
20
|
+
* message if it is left blank. If `true`, the error message is the
|
|
21
|
+
* `requiredFieldMessage` string provided by `WonderBlocksConfigProvider`.
|
|
21
22
|
* - `instantValidation` - If the field should be validated instantly.
|
|
22
23
|
* - `validate` - Validation for the field.
|
|
23
24
|
* - `onValidate` - Called after the `validate` prop is called.
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ var wonderBlocksIcon = require('@khanacademy/wonder-blocks-icon');
|
|
|
12
12
|
var checkIcon = require('@phosphor-icons/core/bold/check-bold.svg');
|
|
13
13
|
var minusIcon = require('@phosphor-icons/core/bold/minus-bold.svg');
|
|
14
14
|
var wonderBlocksStyles = require('@khanacademy/wonder-blocks-styles');
|
|
15
|
+
var wonderBlocksConfig = require('@khanacademy/wonder-blocks-config');
|
|
15
16
|
|
|
16
17
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
17
18
|
|
|
@@ -61,7 +62,7 @@ const StyledFieldset$1=wonderBlocksCore.addStyle("fieldset");const StyledLegend$
|
|
|
61
62
|
|
|
62
63
|
const StyledFieldset=wonderBlocksCore.addStyle("fieldset");const StyledLegend=wonderBlocksCore.addStyle("legend");const RadioGroup=React__namespace.forwardRef(function RadioGroup(props,ref){const{children,label,description,errorMessage,groupName,onChange,selectedValue,style,testId}=props;const allChildren=React__namespace.Children.toArray(children).filter(Boolean);return jsxRuntime.jsxs(StyledFieldset,{"data-testid":testId,style:[styles$3.fieldset,style],ref:ref,children:[label&&jsxRuntime.jsx(StyledLegend,{style:styles$3.legend,children:jsxRuntime.jsx(wonderBlocksTypography.BodyText,{tag:"span",children:label})}),description&&jsxRuntime.jsx(wonderBlocksTypography.BodyText,{size:"small",style:styles$3.description,children:description}),errorMessage&&jsxRuntime.jsx(wonderBlocksTypography.BodyText,{size:"small",style:styles$3.error,children:errorMessage}),allChildren.map((child,index)=>{const{style,value}=child.props;const checked=selectedValue===value;const hasMeta=!!(label||description||errorMessage);return React__namespace.cloneElement(child,{checked:checked,error:!!errorMessage,groupName:groupName,id:`${groupName}-${value}`,key:value,onChange:()=>onChange(value),style:[index===0&&hasMeta&&styles$3.firstChoiceMetaSpacing,index>0&&styles$3.choiceLineGap,style],variant:"radio"})})]})});
|
|
63
64
|
|
|
64
|
-
const
|
|
65
|
+
const useFieldValidation=({value,disabled=false,validate,onValidate,required=false,instantValidation=true})=>{const{strings}=wonderBlocksConfig.useWonderBlocksI18n();const[errorMessage,setErrorMessage]=React__namespace.useState(()=>validate&&value!==""&&!disabled&&validate(value)||null);const onChangeValidation=newValue=>{if(instantValidation){handleValidation(newValue);}else {setErrorMessage(null);if(onValidate){onValidate(null);}}};const onBlurValidation=newValue=>{if(!instantValidation){if(newValue||required){handleValidation(newValue);}}};const handleValidation=newValue=>{if(disabled){return}if(validate){const error=validate(newValue)||null;setErrorMessage(error);if(onValidate){onValidate(error);}}else if(required){const requiredString=typeof required==="string"?required:strings.requiredFieldMessage;const error=newValue?null:requiredString;setErrorMessage(error);if(onValidate){onValidate(error);}}};wonderBlocksCore.useOnMountEffect(()=>{if(value!==""){handleValidation(value);}});return {errorMessage,onBlurValidation,onChangeValidation}};
|
|
65
66
|
|
|
66
67
|
const StyledInput=wonderBlocksCore.addStyle("input");const TextField=props=>{const{id,type="text",value,name,disabled=false,error,validate,onValidate,required,placeholder,style,testId,readOnly,autoFocus,autoComplete,forwardedRef,instantValidation=true,onKeyDown,onChange,onFocus,onBlur,onPaste,...otherProps}=props;const{errorMessage,onBlurValidation,onChangeValidation}=useFieldValidation({value,required,disabled,instantValidation,validate,onValidate});const hasError=error||!!errorMessage;const handleChange=event=>{if(type==="whole-number"){const newValue=event.target.value.replace(/[^0-9]/g,"");onChangeValidation(newValue);onChange(newValue);return}const newValue=event.target.value;onChangeValidation(newValue);onChange(newValue);};const handleFocus=event=>{if(onFocus){onFocus(event);}};const handleBlur=event=>{onBlurValidation(event.target.value);if(onBlur){onBlur(event);}};const handleKeyDown=event=>{if(type==="whole-number"){if(event.key==="."||event.key==="+"||event.key==="-"||event.key==="e"||event.key==="E"){event.preventDefault();}}onKeyDown?.(event);};return jsxRuntime.jsx(wonderBlocksCore.Id,{id:id,children:uniqueId=>jsxRuntime.jsx(StyledInput,{style:[styles$2.input,wonderBlocksTypography.styles.BodyTextMediumMediumWeight,styles$2.default,disabled&&styles$2.disabled,hasError&&styles$2.error,readOnly&&styles$2.readOnly,style],id:uniqueId,type:type==="whole-number"?"number":type,placeholder:placeholder,value:value,name:name,"aria-disabled":disabled,"aria-required":!!required,onChange:handleChange,onKeyDown:disabled?undefined:handleKeyDown,onFocus:handleFocus,onBlur:handleBlur,onPaste:disabled?undefined:onPaste,"data-testid":testId,readOnly:readOnly||disabled,autoFocus:autoFocus,autoComplete:autoComplete,ref:forwardedRef,"aria-invalid":hasError,...otherProps})})};const ACTIVE_BOX_SHADOW$1=`0 0 0 ${theme.field.border.width.press} ${wonderBlocksTokens.semanticColor.input.default.border}`;const styles$2=aphrodite.StyleSheet.create({input:{width:"100%",height:theme.field.sizing.height,borderRadius:theme.field.border.radius,boxSizing:"border-box",paddingInline:theme.field.layout.paddingInline,paddingBlock:theme.field.layout.paddingBlock,margin:wonderBlocksTokens.sizing.size_0},readOnly:{background:wonderBlocksTokens.semanticColor.input.readOnly.background,color:wonderBlocksTokens.semanticColor.input.readOnly.text},default:{background:wonderBlocksTokens.semanticColor.input.default.background,border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.input.default.border}`,color:wonderBlocksTokens.semanticColor.input.default.foreground,"::placeholder":{color:wonderBlocksTokens.semanticColor.input.default.placeholder},...wonderBlocksStyles.focusStyles.focus,[":active:not([aria-disabled='true']):not([readonly])"]:{boxShadow:ACTIVE_BOX_SHADOW$1},[":focus-visible:active:not([aria-disabled='true']):not([readonly])"]:{boxShadow:`${ACTIVE_BOX_SHADOW$1}, ${wonderBlocksStyles.focusStyles.focus[":focus-visible"].boxShadow}`}},error:{background:wonderBlocksTokens.semanticColor.input.error.background,border:`${theme.field.border.width.error} solid ${wonderBlocksTokens.semanticColor.input.error.border}`,color:wonderBlocksTokens.semanticColor.input.error.foreground,"::placeholder":{color:wonderBlocksTokens.semanticColor.input.default.placeholder},[":focus-visible:active:not([aria-disabled='true']):not([readonly])"]:{boxShadow:`${ACTIVE_BOX_SHADOW$1}, ${wonderBlocksStyles.focusStyles.focus[":focus-visible"].boxShadow}`}},disabled:{background:wonderBlocksTokens.semanticColor.input.disabled.background,border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.input.disabled.border}`,color:wonderBlocksTokens.semanticColor.input.disabled.foreground,"::placeholder":{color:wonderBlocksTokens.semanticColor.input.disabled.placeholder},cursor:"not-allowed"}});var TextField$1 = React__namespace.forwardRef((props,ref)=>jsxRuntime.jsx(TextField,{...props,forwardedRef:ref}));
|
|
67
68
|
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Form components for Wonder Blocks.",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "7.
|
|
6
|
+
"version": "7.7.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"./styles.css": "./dist/css/vars.css"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@khanacademy/wonder-blocks-clickable": "8.3.
|
|
31
|
+
"@khanacademy/wonder-blocks-clickable": "8.3.1",
|
|
32
|
+
"@khanacademy/wonder-blocks-config": "0.4.0",
|
|
32
33
|
"@khanacademy/wonder-blocks-core": "12.5.0",
|
|
33
34
|
"@khanacademy/wonder-blocks-icon": "6.0.2",
|
|
34
35
|
"@khanacademy/wonder-blocks-layout": "3.1.62",
|