@khanacademy/wonder-blocks-form 7.6.15 → 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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @khanacademy/wonder-blocks-form@7.6.15 build:css /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-form
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,18 @@
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
+
3
16
  ## 7.6.15
4
17
 
5
18
  ### 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, a default untranslated string will render
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 untranlsated message
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, a default untranslated string will render
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 untranlsated message
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 defaultErrorMessage="This field is required.";const useFieldValidation=({value,disabled=false,validate,onValidate,required=false,instantValidation=true})=>{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:defaultErrorMessage;const error=newValue?null:requiredString;setErrorMessage(error);if(onValidate){onValidate(error);}}};useOnMountEffect(()=>{if(value!==""){handleValidation(value);}});return {errorMessage,onBlurValidation,onChangeValidation}};
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 defaultErrorMessage="This field is required.";const useFieldValidation=({value,disabled=false,validate,onValidate,required=false,instantValidation=true})=>{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:defaultErrorMessage;const error=newValue?null:requiredString;setErrorMessage(error);if(onValidate){onValidate(error);}}};wonderBlocksCore.useOnMountEffect(()=>{if(value!==""){handleValidation(value);}});return {errorMessage,onBlurValidation,onChangeValidation}};
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.15",
6
+ "version": "7.7.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -29,10 +29,11 @@
29
29
  },
30
30
  "dependencies": {
31
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",
34
+ "@khanacademy/wonder-blocks-icon": "6.0.2",
33
35
  "@khanacademy/wonder-blocks-layout": "3.1.62",
34
36
  "@khanacademy/wonder-blocks-tokens": "18.0.0",
35
- "@khanacademy/wonder-blocks-icon": "6.0.2",
36
37
  "@khanacademy/wonder-blocks-typography": "5.0.5"
37
38
  },
38
39
  "peerDependencies": {