@khanacademy/wonder-blocks-form 7.1.26 → 7.2.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 +5 -0
- package/CHANGELOG.md +15 -0
- package/dist/css/vars.css +5 -0
- package/dist/es/index.js +16 -9
- package/dist/index.js +13 -6
- package/dist/theme/default.d.ts +11 -0
- package/dist/theme/index.d.ts +11 -0
- package/dist/theme/thunderblocks.d.ts +11 -0
- package/dist/util/styles.d.ts +89 -0
- package/package.json +15 -6
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
|
|
2
|
+
> @khanacademy/wonder-blocks-form@7.2.0 build:css /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-form
|
|
3
|
+
> pnpm exec wonder-blocks-tokens .
|
|
4
|
+
|
|
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,20 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-form
|
|
2
2
|
|
|
3
|
+
## 7.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- d8716ab: Add Thunderblocks theme to Checkbox and Radio components
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [d8716ab]
|
|
12
|
+
- @khanacademy/wonder-blocks-tokens@11.2.2
|
|
13
|
+
- @khanacademy/wonder-blocks-clickable@7.1.13
|
|
14
|
+
- @khanacademy/wonder-blocks-icon@5.2.7
|
|
15
|
+
- @khanacademy/wonder-blocks-layout@3.1.24
|
|
16
|
+
- @khanacademy/wonder-blocks-typography@4.2.9
|
|
17
|
+
|
|
3
18
|
## 7.1.26
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
:root {--wb-c-form-choice-inputWrapper-layout-padding: var(--wb-sizing-size_0);
|
|
2
|
+
--wb-c-form-choice-inputWrapper-layout-margin: var(--wb-sizing-size_0);}
|
|
3
|
+
|
|
4
|
+
[data-wb-theme='thunderblocks'] {--wb-c-form-choice-inputWrapper-layout-padding: var(--wb-sizing-size_040);
|
|
5
|
+
--wb-c-form-choice-inputWrapper-layout-margin: calc(var(--wb-sizing-size_040) * -1);}
|
package/dist/es/index.js
CHANGED
|
@@ -2,19 +2,26 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { useId } from 'react';
|
|
4
4
|
import { StyleSheet } from 'aphrodite';
|
|
5
|
-
import { addStyle,
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { LabelMedium, LabelSmall, styles as styles$7 } from '@khanacademy/wonder-blocks-typography';
|
|
5
|
+
import { addStyle, View, Id, useOnMountEffect } from '@khanacademy/wonder-blocks-core';
|
|
6
|
+
import { sizing, mapValuesToCssVars, semanticColor, border, spacing, font } from '@khanacademy/wonder-blocks-tokens';
|
|
7
|
+
import { BodyText, styles as styles$7, LabelMedium, LabelSmall } from '@khanacademy/wonder-blocks-typography';
|
|
9
8
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
10
9
|
import checkIcon from '@phosphor-icons/core/bold/check-bold.svg';
|
|
11
10
|
import minusIcon from '@phosphor-icons/core/bold/minus-bold.svg';
|
|
11
|
+
import { focusStyles } from '@khanacademy/wonder-blocks-styles';
|
|
12
|
+
import { Strut } from '@khanacademy/wonder-blocks-layout';
|
|
13
|
+
|
|
14
|
+
var themeDefault = {choice:{inputWrapper:{layout:{padding:sizing.size_0,margin:sizing.size_0}}}};
|
|
15
|
+
|
|
16
|
+
var theme = mapValuesToCssVars(themeDefault,"--wb-c-form-");
|
|
17
|
+
|
|
18
|
+
const baseStyles={choice:{sizing:{size:sizing.size_160},checked:{border:semanticColor.input.checked.border},disabled:{border:semanticColor.input.disabled.border,background:semanticColor.input.disabled.background},error:{border:semanticColor.input.error.border,background:semanticColor.input.error.background},unchecked:{rest:{border:semanticColor.input.default.border,background:semanticColor.input.default.background},hover:{border:semanticColor.action.secondary.progressive.hover.border,background:semanticColor.action.secondary.progressive.hover.background},press:{border:semanticColor.action.secondary.progressive.press.border,background:semanticColor.action.secondary.progressive.press.background}}},radio:{border:{radius:{default:border.radius.radius_full},width:{default:border.width.thin}}},checkbox:{border:{radius:{default:border.radius.radius_040},width:{default:border.width.thin}},sizing:{checkSize:sizing.size_120},disabledChecked:{border:semanticColor.core.transparent,background:semanticColor.core.background.disabled.strong}},icon:{default:{foreground:semanticColor.core.foreground.inverse.strong},disabled:{foreground:semanticColor.core.foreground.neutral.subtle}}};const colorStates={checkbox:{unchecked:{default:baseStyles.choice.unchecked,disabled:{rest:baseStyles.choice.disabled,hover:baseStyles.choice.disabled,press:baseStyles.choice.disabled},error:{rest:baseStyles.choice.error,hover:baseStyles.choice.error,press:{...baseStyles.choice.error,border:semanticColor.core.border.critical.strong}}},checked:{default:{rest:{border:semanticColor.core.transparent,background:semanticColor.input.checked.background},hover:{border:semanticColor.core.border.instructive.default},press:{border:semanticColor.input.checked.border,background:semanticColor.core.background.instructive.strong}},disabled:{rest:baseStyles.checkbox.disabledChecked,hover:baseStyles.checkbox.disabledChecked,press:baseStyles.checkbox.disabledChecked},error:{rest:{background:semanticColor.core.border.critical.default,border:semanticColor.core.border.critical.default},hover:{background:semanticColor.core.background.critical.default,border:semanticColor.core.border.critical.default},press:{background:semanticColor.core.background.critical.strong,border:semanticColor.core.border.critical.strong}}}},radio:{unchecked:{default:baseStyles.choice.unchecked,disabled:{rest:baseStyles.choice.disabled,hover:baseStyles.choice.disabled,press:baseStyles.choice.disabled},error:{rest:baseStyles.choice.error,hover:baseStyles.choice.error,press:{...baseStyles.choice.error,border:semanticColor.core.border.critical.strong}}},checked:{default:{rest:{border:semanticColor.input.checked.background,background:semanticColor.core.border.inverse.strong},hover:baseStyles.choice.checked,press:{border:semanticColor.core.background.instructive.strong,background:semanticColor.core.background.instructive.strong}},error:{rest:baseStyles.choice.error,hover:baseStyles.choice.error,press:{...baseStyles.choice.error,background:semanticColor.core.background.critical.strong,border:semanticColor.core.border.critical.strong}},disabled:{rest:{border:semanticColor.core.border.disabled.default,background:semanticColor.core.border.inverse.strong},hover:{border:semanticColor.core.border.disabled.strong,background:semanticColor.core.border.inverse.strong},press:{border:semanticColor.core.border.disabled.strong,background:semanticColor.core.border.inverse.strong}}}}};
|
|
12
19
|
|
|
13
|
-
function mapCheckedToAriaChecked(value){switch(value){case true:return "true";case false:return "false";default:return "mixed"}}const
|
|
20
|
+
function mapCheckedToAriaChecked(value){switch(value){case true:return "true";case false:return "false";default:return "mixed"}}const StyledInput$2=addStyle("input");const CheckboxCore=React.forwardRef(function CheckboxCore(props,ref){const{checked,disabled,error,groupName,id,testId,...sharedProps}=props;const innerRef=React.useRef(null);React.useEffect(()=>{if(innerRef.current!=null){innerRef.current.indeterminate=checked==null;}},[checked,innerRef]);const handleChange=()=>{return};const stateStyles=_generateStyles$1(checked,error,disabled);const defaultStyle=[sharedStyles$1.inputReset,sharedStyles$1.default,stateStyles.default];const wrapperStyle=[sharedStyles$1.inputWrapper,stateStyles.inputWrapper];const checkboxIcon=jsx(PhosphorIcon,{color:disabled?baseStyles.icon.disabled.foreground:baseStyles.icon.default.foreground,icon:checked?checkIcon:minusIcon,size:"small",style:[sharedStyles$1.checkboxIcon,{width:baseStyles.checkbox.sizing.checkSize,height:baseStyles.checkbox.sizing.checkSize}]});const ariaChecked=mapCheckedToAriaChecked(checked);const handleWrapperClick=e=>{if(!disabled&&e.target!==innerRef.current){innerRef.current?.click();}};return jsx(React.Fragment,{children:jsxs(View,{style:wrapperStyle,onClick:handleWrapperClick,testId:"wb-checkbox-wrapper",children:[jsx(StyledInput$2,{...sharedProps,ref:node=>{innerRef.current=node;if(typeof ref==="function"){ref(node);}else if(ref!=null){ref.current=node;}},type:"checkbox","aria-checked":ariaChecked,"aria-invalid":error,checked:checked??undefined,disabled:disabled,id:id,name:groupName,onChange:handleChange,style:defaultStyle,"data-testid":testId}),checked||checked==null?checkboxIcon:jsx(Fragment,{})]})})});const sharedStyles$1=StyleSheet.create({inputWrapper:{margin:theme.choice.inputWrapper.layout.margin,padding:theme.choice.inputWrapper.layout.padding,position:"relative"},inputReset:{appearance:"none",WebkitAppearance:"none",MozAppearance:"none"},default:{height:baseStyles.choice.sizing.size,width:baseStyles.choice.sizing.size,minHeight:baseStyles.choice.sizing.size,minWidth:baseStyles.choice.sizing.size,margin:0,outline:"none",boxSizing:"border-box",borderStyle:"solid",borderWidth:baseStyles.checkbox.border.width.default,borderRadius:baseStyles.checkbox.border.radius.default},checkboxIcon:{position:"absolute",pointerEvents:"none",margin:`calc((${baseStyles.choice.sizing.size} - ${baseStyles.checkbox.sizing.checkSize}) / 2)`}});const styles$6={};const _generateStyles$1=(checked,error,disabled)=>{const styleKey=`${String(checked)}-${String(error)}-${String(disabled)}`;if(styles$6[styleKey]){return styles$6[styleKey]}const isCheckedOrIndeterminate=checked||checked==null;let stateStyles={};const currentState=error?"error":disabled?"disabled":"default";if(isCheckedOrIndeterminate){const checkedStyles=colorStates.checkbox.checked[currentState];stateStyles={inputWrapper:{":hover input:not([disabled])":{outline:`${border.width.medium} solid ${checkedStyles.hover.border}`,outlineOffset:1}},default:{backgroundColor:checkedStyles.rest.background,borderColor:checkedStyles.rest.border,":focus-visible:not([disabled])":focusStyles.focus[":focus-visible"],":active:not([disabled])":{outline:`${border.width.medium} solid ${checkedStyles.press.border}`,outlineOffset:1,background:checkedStyles.press.background,borderColor:checkedStyles.press.background}}};}else {const uncheckedStyles=colorStates.checkbox.unchecked[currentState];stateStyles={inputWrapper:{":hover input:not([disabled])":{backgroundColor:uncheckedStyles.hover.background,outline:`${border.width.medium} solid ${uncheckedStyles.hover.border}`,outlineOffset:-1}},default:{backgroundColor:uncheckedStyles.rest.background,borderColor:uncheckedStyles.rest.border,":focus-visible:not([disabled])":{...focusStyles.focus},":active:not([disabled])":{backgroundColor:uncheckedStyles.press.background,outline:`${border.width.medium} solid ${uncheckedStyles.press.border}`,outlineOffset:-1}}};}styles$6[styleKey]=StyleSheet.create(stateStyles);return styles$6[styleKey]};
|
|
14
21
|
|
|
15
|
-
const StyledInput$1=addStyle("input");const RadioCore=React.forwardRef(function RadioCore(props,ref){const handleChange=()=>{return};const{checked,disabled,error,groupName,id,testId,...sharedProps}=props;const stateStyles=_generateStyles(checked,error);const defaultStyle=[sharedStyles.inputReset,sharedStyles.default
|
|
22
|
+
const StyledInput$1=addStyle("input");const RadioCore=React.forwardRef(function RadioCore(props,ref){const innerRef=React.useRef(null);const handleChange=()=>{return};const{checked,disabled,error,groupName,id,testId,...sharedProps}=props;const stateStyles=_generateStyles(checked,error,disabled);const defaultStyle=[sharedStyles.inputReset,sharedStyles.default,stateStyles.default];const wrapperStyle=[sharedStyles.inputWrapper,stateStyles.inputWrapper];const handleWrapperClick=e=>{if(!disabled&&e.target!==innerRef?.current){innerRef?.current?.click();}};return jsx(React.Fragment,{children:jsxs(View,{style:wrapperStyle,onClick:handleWrapperClick,children:[jsx(StyledInput$1,{...sharedProps,type:"radio","aria-invalid":error,checked:checked??undefined,disabled:disabled,id:id,name:groupName,onChange:handleChange,style:defaultStyle,"data-testid":testId,ref:node=>{innerRef.current=node;if(typeof ref==="function"){ref(node);}else if(ref!=null){ref.current=node;}}}),disabled&&checked&&jsx("span",{style:stateStyles.disabledChecked})]})})});const sharedStyles=StyleSheet.create({inputWrapper:{padding:theme.choice.inputWrapper.layout.padding,margin:theme.choice.inputWrapper.layout.margin,position:"relative"},inputReset:{appearance:"none",WebkitAppearance:"none",MozAppearance:"none"},default:{height:baseStyles.choice.sizing.size,width:baseStyles.choice.sizing.size,minHeight:baseStyles.choice.sizing.size,minWidth:baseStyles.choice.sizing.size,margin:0,outline:"none",boxSizing:"border-box",borderStyle:"solid",borderWidth:baseStyles.radio.border.width.default,borderRadius:baseStyles.radio.border.radius.default}});const styles$5={};const _generateStyles=(checked,error,disabled)=>{const styleKey=`${String(checked)}-${String(error)}-${String(disabled)}`;if(styles$5[styleKey]){return styles$5[styleKey]}let newStyles={};const currentState=error?"error":disabled?"disabled":"default";if(checked){const checkedStyles=colorStates.radio.checked[currentState];newStyles={inputWrapper:{":hover input:not([disabled])":{outline:`${border.width.medium} solid ${checkedStyles.hover.border}`,outlineOffset:1}},default:{backgroundColor:checkedStyles.rest.background,borderColor:checkedStyles.rest.border,borderWidth:`calc(${baseStyles.choice.sizing.size} / 4)`,":focus-visible:not([disabled])":focusStyles.focus[":focus-visible"],":active:not([disabled])":{outline:`${border.width.medium} solid ${checkedStyles.press.border}`,outlineOffset:1,borderColor:checkedStyles.press.border}},disabledChecked:{position:"absolute",top:`calc(${baseStyles.choice.sizing.size} * .25 + ${theme.choice.inputWrapper.layout.padding})`,left:`calc(${baseStyles.choice.sizing.size} * .25 + ${theme.choice.inputWrapper.layout.padding})`,height:`calc(${baseStyles.choice.sizing.size} / 2)`,width:`calc(${baseStyles.choice.sizing.size} / 2)`,borderRadius:baseStyles.radio.border.radius.default,backgroundColor:checkedStyles.rest.background}};}else {const uncheckedStyles=colorStates.radio.unchecked[currentState];newStyles={inputWrapper:{":hover input:not([disabled])":{backgroundColor:uncheckedStyles.hover.background,outline:`${border.width.medium} solid ${uncheckedStyles.hover.border}`,outlineOffset:-1}},default:{backgroundColor:uncheckedStyles.rest.background,borderColor:uncheckedStyles.rest.border,":focus-visible:not([disabled])":focusStyles.focus[":focus-visible"],":active:not([disabled])":{backgroundColor:uncheckedStyles.press.background,outline:`${border.width.medium} solid ${uncheckedStyles.press.border}`,outlineOffset:-1}}};}styles$5[styleKey]=StyleSheet.create(newStyles);return styles$5[styleKey]};
|
|
16
23
|
|
|
17
|
-
const ChoiceInternal=React.forwardRef(function ChoiceInternal(props,ref){const{checked,description,disabled=false,error=false,id,label,onChange,style,className,variant,...coreProps}=props;const handleClick=()=>{if(variant==="radio"&&checked){return}onChange(!checked);};const getChoiceCoreComponent=()=>{if(variant==="radio"){return RadioCore}else {return CheckboxCore}};const getLabel=id=>{return jsx(
|
|
24
|
+
const ChoiceInternal=React.forwardRef(function ChoiceInternal(props,ref){const{checked,description,disabled=false,error=false,id,label,onChange,style,className,variant,...coreProps}=props;const handleClick=()=>{if(variant==="radio"&&checked){return}onChange(!checked);};const getChoiceCoreComponent=()=>{if(variant==="radio"){return RadioCore}else {return CheckboxCore}};const getLabel=id=>{return jsx(BodyText,{tag:"div",weight:"semi",style:[styles$4.label,disabled&&styles$4.disabledLabel],children:jsx("label",{htmlFor:id,children:label})})};const getDescription=id=>{return jsx(BodyText,{size:"small",style:styles$4.description,id:id,children:description})};const ChoiceCore=getChoiceCoreComponent();return jsx(Id,{id:id,children:uniqueId=>{const descriptionId=description?`${uniqueId}-description`:undefined;return jsxs(View,{style:style,className:className,children:[jsxs(View,{style:styles$4.wrapper,tabIndex:-1,children:[jsx(View,{style:[styles$4.choiceWrapper],children:jsx(ChoiceCore,{...coreProps,id:uniqueId,checked:checked,"aria-describedby":descriptionId,onClick:handleClick,disabled:disabled,error:error,ref:ref})}),label&&getLabel(uniqueId)]}),description&&getDescription(descriptionId)]})}})});const styles$4=StyleSheet.create({wrapper:{gap:spacing.xSmall_8,lineHeight:font.body.lineHeight.small,flexDirection:"row",alignItems:"flex-start",outline:"none"},choiceWrapper:{display:"block",marginBlockStart:sizing.size_010},label:{color:semanticColor.core.foreground.neutral.strong,lineHeight:font.body.lineHeight.small},disabledLabel:{color:semanticColor.core.foreground.disabled.subtle},description:{marginLeft:spacing.medium_16+spacing.xSmall_8,marginTop:spacing.xxxSmall_4,color:semanticColor.text.secondary}});
|
|
18
25
|
|
|
19
26
|
const Checkbox=React.forwardRef(function Checkbox(props,ref){const{disabled=false,error=false}=props;return jsx(ChoiceInternal,{...props,variant:"checkbox",disabled:disabled,error:error,ref:ref})});
|
|
20
27
|
|
|
@@ -24,9 +31,9 @@ const Choice=React.forwardRef(function Choice(props,ref){const{checked=false,dis
|
|
|
24
31
|
|
|
25
32
|
const styles$3=StyleSheet.create({fieldset:{display:"flex",flexDirection:"column",border:"none",padding:0,margin:0},legend:{padding:0,width:"100%"},description:{marginTop:spacing.xxxSmall_4,color:semanticColor.text.secondary},error:{marginTop:spacing.xxxSmall_4,color:semanticColor.status.critical.foreground},defaultLineGap:{marginTop:spacing.xSmall_8}});
|
|
26
33
|
|
|
27
|
-
const StyledFieldset$1=addStyle("fieldset");const StyledLegend$1=addStyle("legend");const CheckboxGroup=React.forwardRef(function CheckboxGroup(props,ref){const{children,label,description,errorMessage,groupName,onChange,selectedValues,style,testId}=props;const handleChange=(changedValue,originalCheckedState)=>{if(originalCheckedState){const index=selectedValues.indexOf(changedValue);const updatedSelection=[...selectedValues.slice(0,index),...selectedValues.slice(index+1)];onChange(updatedSelection);}else {onChange([...selectedValues,changedValue]);}};const allChildren=React.Children.toArray(children).filter(Boolean);return jsxs(StyledFieldset$1,{"data-testid":testId,style:[styles$3.fieldset,style],ref:ref,children:[label&&jsx(StyledLegend$1,{style:styles$3.legend,children:jsx(
|
|
34
|
+
const StyledFieldset$1=addStyle("fieldset");const StyledLegend$1=addStyle("legend");const CheckboxGroup=React.forwardRef(function CheckboxGroup(props,ref){const{children,label,description,errorMessage,groupName,onChange,selectedValues,style,testId}=props;const handleChange=(changedValue,originalCheckedState)=>{if(originalCheckedState){const index=selectedValues.indexOf(changedValue);const updatedSelection=[...selectedValues.slice(0,index),...selectedValues.slice(index+1)];onChange(updatedSelection);}else {onChange([...selectedValues,changedValue]);}};const allChildren=React.Children.toArray(children).filter(Boolean);return jsxs(StyledFieldset$1,{"data-testid":testId,style:[styles$3.fieldset,style],ref:ref,children:[label&&jsx(StyledLegend$1,{style:styles$3.legend,children:jsx(BodyText,{tag:"span",children:label})}),description&&jsx(BodyText,{size:"small",tag:"span",style:styles$3.description,children:description}),errorMessage&&jsx(BodyText,{size:"small",tag:"span",style:styles$3.error,children:errorMessage}),(label||description||errorMessage)&&jsx(Strut,{size:spacing.small_12}),allChildren.map((child,index)=>{const{style,value}=child.props;const checked=selectedValues.includes(value);return React.cloneElement(child,{checked:checked,error:!!errorMessage,groupName:groupName,id:`${groupName}-${value}`,key:value,onChange:()=>handleChange(value,checked),style:[index>0&&styles$3.defaultLineGap,style],variant:"checkbox"})})]})});
|
|
28
35
|
|
|
29
|
-
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(
|
|
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}),(label||description||errorMessage)&&jsx(Strut,{size:spacing.small_12}),allChildren.map((child,index)=>{const{style,value}=child.props;const checked=selectedValue===value;return React.cloneElement(child,{checked:checked,error:!!errorMessage,groupName:groupName,id:`${groupName}-${value}`,key:value,onChange:()=>onChange(value),style:[index>0&&styles$3.defaultLineGap,style],variant:"radio"})})]})});
|
|
30
37
|
|
|
31
38
|
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}};
|
|
32
39
|
|
package/dist/index.js
CHANGED
|
@@ -6,12 +6,13 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
6
6
|
var React = require('react');
|
|
7
7
|
var aphrodite = require('aphrodite');
|
|
8
8
|
var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
|
|
9
|
-
var wonderBlocksLayout = require('@khanacademy/wonder-blocks-layout');
|
|
10
9
|
var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
|
|
11
10
|
var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
|
|
12
11
|
var wonderBlocksIcon = require('@khanacademy/wonder-blocks-icon');
|
|
13
12
|
var checkIcon = require('@phosphor-icons/core/bold/check-bold.svg');
|
|
14
13
|
var minusIcon = require('@phosphor-icons/core/bold/minus-bold.svg');
|
|
14
|
+
var wonderBlocksStyles = require('@khanacademy/wonder-blocks-styles');
|
|
15
|
+
var wonderBlocksLayout = require('@khanacademy/wonder-blocks-layout');
|
|
15
16
|
|
|
16
17
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
17
18
|
|
|
@@ -37,11 +38,17 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
|
37
38
|
var checkIcon__default = /*#__PURE__*/_interopDefaultLegacy(checkIcon);
|
|
38
39
|
var minusIcon__default = /*#__PURE__*/_interopDefaultLegacy(minusIcon);
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
var themeDefault = {choice:{inputWrapper:{layout:{padding:wonderBlocksTokens.sizing.size_0,margin:wonderBlocksTokens.sizing.size_0}}}};
|
|
42
|
+
|
|
43
|
+
var theme = wonderBlocksTokens.mapValuesToCssVars(themeDefault,"--wb-c-form-");
|
|
44
|
+
|
|
45
|
+
const baseStyles={choice:{sizing:{size:wonderBlocksTokens.sizing.size_160},checked:{border:wonderBlocksTokens.semanticColor.input.checked.border},disabled:{border:wonderBlocksTokens.semanticColor.input.disabled.border,background:wonderBlocksTokens.semanticColor.input.disabled.background},error:{border:wonderBlocksTokens.semanticColor.input.error.border,background:wonderBlocksTokens.semanticColor.input.error.background},unchecked:{rest:{border:wonderBlocksTokens.semanticColor.input.default.border,background:wonderBlocksTokens.semanticColor.input.default.background},hover:{border:wonderBlocksTokens.semanticColor.action.secondary.progressive.hover.border,background:wonderBlocksTokens.semanticColor.action.secondary.progressive.hover.background},press:{border:wonderBlocksTokens.semanticColor.action.secondary.progressive.press.border,background:wonderBlocksTokens.semanticColor.action.secondary.progressive.press.background}}},radio:{border:{radius:{default:wonderBlocksTokens.border.radius.radius_full},width:{default:wonderBlocksTokens.border.width.thin}}},checkbox:{border:{radius:{default:wonderBlocksTokens.border.radius.radius_040},width:{default:wonderBlocksTokens.border.width.thin}},sizing:{checkSize:wonderBlocksTokens.sizing.size_120},disabledChecked:{border:wonderBlocksTokens.semanticColor.core.transparent,background:wonderBlocksTokens.semanticColor.core.background.disabled.strong}},icon:{default:{foreground:wonderBlocksTokens.semanticColor.core.foreground.inverse.strong},disabled:{foreground:wonderBlocksTokens.semanticColor.core.foreground.neutral.subtle}}};const colorStates={checkbox:{unchecked:{default:baseStyles.choice.unchecked,disabled:{rest:baseStyles.choice.disabled,hover:baseStyles.choice.disabled,press:baseStyles.choice.disabled},error:{rest:baseStyles.choice.error,hover:baseStyles.choice.error,press:{...baseStyles.choice.error,border:wonderBlocksTokens.semanticColor.core.border.critical.strong}}},checked:{default:{rest:{border:wonderBlocksTokens.semanticColor.core.transparent,background:wonderBlocksTokens.semanticColor.input.checked.background},hover:{border:wonderBlocksTokens.semanticColor.core.border.instructive.default},press:{border:wonderBlocksTokens.semanticColor.input.checked.border,background:wonderBlocksTokens.semanticColor.core.background.instructive.strong}},disabled:{rest:baseStyles.checkbox.disabledChecked,hover:baseStyles.checkbox.disabledChecked,press:baseStyles.checkbox.disabledChecked},error:{rest:{background:wonderBlocksTokens.semanticColor.core.border.critical.default,border:wonderBlocksTokens.semanticColor.core.border.critical.default},hover:{background:wonderBlocksTokens.semanticColor.core.background.critical.default,border:wonderBlocksTokens.semanticColor.core.border.critical.default},press:{background:wonderBlocksTokens.semanticColor.core.background.critical.strong,border:wonderBlocksTokens.semanticColor.core.border.critical.strong}}}},radio:{unchecked:{default:baseStyles.choice.unchecked,disabled:{rest:baseStyles.choice.disabled,hover:baseStyles.choice.disabled,press:baseStyles.choice.disabled},error:{rest:baseStyles.choice.error,hover:baseStyles.choice.error,press:{...baseStyles.choice.error,border:wonderBlocksTokens.semanticColor.core.border.critical.strong}}},checked:{default:{rest:{border:wonderBlocksTokens.semanticColor.input.checked.background,background:wonderBlocksTokens.semanticColor.core.border.inverse.strong},hover:baseStyles.choice.checked,press:{border:wonderBlocksTokens.semanticColor.core.background.instructive.strong,background:wonderBlocksTokens.semanticColor.core.background.instructive.strong}},error:{rest:baseStyles.choice.error,hover:baseStyles.choice.error,press:{...baseStyles.choice.error,background:wonderBlocksTokens.semanticColor.core.background.critical.strong,border:wonderBlocksTokens.semanticColor.core.border.critical.strong}},disabled:{rest:{border:wonderBlocksTokens.semanticColor.core.border.disabled.default,background:wonderBlocksTokens.semanticColor.core.border.inverse.strong},hover:{border:wonderBlocksTokens.semanticColor.core.border.disabled.strong,background:wonderBlocksTokens.semanticColor.core.border.inverse.strong},press:{border:wonderBlocksTokens.semanticColor.core.border.disabled.strong,background:wonderBlocksTokens.semanticColor.core.border.inverse.strong}}}}};
|
|
46
|
+
|
|
47
|
+
function mapCheckedToAriaChecked(value){switch(value){case true:return "true";case false:return "false";default:return "mixed"}}const StyledInput$2=wonderBlocksCore.addStyle("input");const CheckboxCore=React__namespace.forwardRef(function CheckboxCore(props,ref){const{checked,disabled,error,groupName,id,testId,...sharedProps}=props;const innerRef=React__namespace.useRef(null);React__namespace.useEffect(()=>{if(innerRef.current!=null){innerRef.current.indeterminate=checked==null;}},[checked,innerRef]);const handleChange=()=>{return};const stateStyles=_generateStyles$1(checked,error,disabled);const defaultStyle=[sharedStyles$1.inputReset,sharedStyles$1.default,stateStyles.default];const wrapperStyle=[sharedStyles$1.inputWrapper,stateStyles.inputWrapper];const checkboxIcon=jsxRuntime.jsx(wonderBlocksIcon.PhosphorIcon,{color:disabled?baseStyles.icon.disabled.foreground:baseStyles.icon.default.foreground,icon:checked?checkIcon__default["default"]:minusIcon__default["default"],size:"small",style:[sharedStyles$1.checkboxIcon,{width:baseStyles.checkbox.sizing.checkSize,height:baseStyles.checkbox.sizing.checkSize}]});const ariaChecked=mapCheckedToAriaChecked(checked);const handleWrapperClick=e=>{if(!disabled&&e.target!==innerRef.current){innerRef.current?.click();}};return jsxRuntime.jsx(React__namespace.Fragment,{children:jsxRuntime.jsxs(wonderBlocksCore.View,{style:wrapperStyle,onClick:handleWrapperClick,testId:"wb-checkbox-wrapper",children:[jsxRuntime.jsx(StyledInput$2,{...sharedProps,ref:node=>{innerRef.current=node;if(typeof ref==="function"){ref(node);}else if(ref!=null){ref.current=node;}},type:"checkbox","aria-checked":ariaChecked,"aria-invalid":error,checked:checked??undefined,disabled:disabled,id:id,name:groupName,onChange:handleChange,style:defaultStyle,"data-testid":testId}),checked||checked==null?checkboxIcon:jsxRuntime.jsx(jsxRuntime.Fragment,{})]})})});const sharedStyles$1=aphrodite.StyleSheet.create({inputWrapper:{margin:theme.choice.inputWrapper.layout.margin,padding:theme.choice.inputWrapper.layout.padding,position:"relative"},inputReset:{appearance:"none",WebkitAppearance:"none",MozAppearance:"none"},default:{height:baseStyles.choice.sizing.size,width:baseStyles.choice.sizing.size,minHeight:baseStyles.choice.sizing.size,minWidth:baseStyles.choice.sizing.size,margin:0,outline:"none",boxSizing:"border-box",borderStyle:"solid",borderWidth:baseStyles.checkbox.border.width.default,borderRadius:baseStyles.checkbox.border.radius.default},checkboxIcon:{position:"absolute",pointerEvents:"none",margin:`calc((${baseStyles.choice.sizing.size} - ${baseStyles.checkbox.sizing.checkSize}) / 2)`}});const styles$6={};const _generateStyles$1=(checked,error,disabled)=>{const styleKey=`${String(checked)}-${String(error)}-${String(disabled)}`;if(styles$6[styleKey]){return styles$6[styleKey]}const isCheckedOrIndeterminate=checked||checked==null;let stateStyles={};const currentState=error?"error":disabled?"disabled":"default";if(isCheckedOrIndeterminate){const checkedStyles=colorStates.checkbox.checked[currentState];stateStyles={inputWrapper:{":hover input:not([disabled])":{outline:`${wonderBlocksTokens.border.width.medium} solid ${checkedStyles.hover.border}`,outlineOffset:1}},default:{backgroundColor:checkedStyles.rest.background,borderColor:checkedStyles.rest.border,":focus-visible:not([disabled])":wonderBlocksStyles.focusStyles.focus[":focus-visible"],":active:not([disabled])":{outline:`${wonderBlocksTokens.border.width.medium} solid ${checkedStyles.press.border}`,outlineOffset:1,background:checkedStyles.press.background,borderColor:checkedStyles.press.background}}};}else {const uncheckedStyles=colorStates.checkbox.unchecked[currentState];stateStyles={inputWrapper:{":hover input:not([disabled])":{backgroundColor:uncheckedStyles.hover.background,outline:`${wonderBlocksTokens.border.width.medium} solid ${uncheckedStyles.hover.border}`,outlineOffset:-1}},default:{backgroundColor:uncheckedStyles.rest.background,borderColor:uncheckedStyles.rest.border,":focus-visible:not([disabled])":{...wonderBlocksStyles.focusStyles.focus},":active:not([disabled])":{backgroundColor:uncheckedStyles.press.background,outline:`${wonderBlocksTokens.border.width.medium} solid ${uncheckedStyles.press.border}`,outlineOffset:-1}}};}styles$6[styleKey]=aphrodite.StyleSheet.create(stateStyles);return styles$6[styleKey]};
|
|
41
48
|
|
|
42
|
-
const StyledInput$1=wonderBlocksCore.addStyle("input");const RadioCore=React__namespace.forwardRef(function RadioCore(props,ref){const handleChange=()=>{return};const{checked,disabled,error,groupName,id,testId,...sharedProps}=props;const stateStyles=_generateStyles(checked,error);const defaultStyle=[sharedStyles.inputReset,sharedStyles.default
|
|
49
|
+
const StyledInput$1=wonderBlocksCore.addStyle("input");const RadioCore=React__namespace.forwardRef(function RadioCore(props,ref){const innerRef=React__namespace.useRef(null);const handleChange=()=>{return};const{checked,disabled,error,groupName,id,testId,...sharedProps}=props;const stateStyles=_generateStyles(checked,error,disabled);const defaultStyle=[sharedStyles.inputReset,sharedStyles.default,stateStyles.default];const wrapperStyle=[sharedStyles.inputWrapper,stateStyles.inputWrapper];const handleWrapperClick=e=>{if(!disabled&&e.target!==innerRef?.current){innerRef?.current?.click();}};return jsxRuntime.jsx(React__namespace.Fragment,{children:jsxRuntime.jsxs(wonderBlocksCore.View,{style:wrapperStyle,onClick:handleWrapperClick,children:[jsxRuntime.jsx(StyledInput$1,{...sharedProps,type:"radio","aria-invalid":error,checked:checked??undefined,disabled:disabled,id:id,name:groupName,onChange:handleChange,style:defaultStyle,"data-testid":testId,ref:node=>{innerRef.current=node;if(typeof ref==="function"){ref(node);}else if(ref!=null){ref.current=node;}}}),disabled&&checked&&jsxRuntime.jsx("span",{style:stateStyles.disabledChecked})]})})});const sharedStyles=aphrodite.StyleSheet.create({inputWrapper:{padding:theme.choice.inputWrapper.layout.padding,margin:theme.choice.inputWrapper.layout.margin,position:"relative"},inputReset:{appearance:"none",WebkitAppearance:"none",MozAppearance:"none"},default:{height:baseStyles.choice.sizing.size,width:baseStyles.choice.sizing.size,minHeight:baseStyles.choice.sizing.size,minWidth:baseStyles.choice.sizing.size,margin:0,outline:"none",boxSizing:"border-box",borderStyle:"solid",borderWidth:baseStyles.radio.border.width.default,borderRadius:baseStyles.radio.border.radius.default}});const styles$5={};const _generateStyles=(checked,error,disabled)=>{const styleKey=`${String(checked)}-${String(error)}-${String(disabled)}`;if(styles$5[styleKey]){return styles$5[styleKey]}let newStyles={};const currentState=error?"error":disabled?"disabled":"default";if(checked){const checkedStyles=colorStates.radio.checked[currentState];newStyles={inputWrapper:{":hover input:not([disabled])":{outline:`${wonderBlocksTokens.border.width.medium} solid ${checkedStyles.hover.border}`,outlineOffset:1}},default:{backgroundColor:checkedStyles.rest.background,borderColor:checkedStyles.rest.border,borderWidth:`calc(${baseStyles.choice.sizing.size} / 4)`,":focus-visible:not([disabled])":wonderBlocksStyles.focusStyles.focus[":focus-visible"],":active:not([disabled])":{outline:`${wonderBlocksTokens.border.width.medium} solid ${checkedStyles.press.border}`,outlineOffset:1,borderColor:checkedStyles.press.border}},disabledChecked:{position:"absolute",top:`calc(${baseStyles.choice.sizing.size} * .25 + ${theme.choice.inputWrapper.layout.padding})`,left:`calc(${baseStyles.choice.sizing.size} * .25 + ${theme.choice.inputWrapper.layout.padding})`,height:`calc(${baseStyles.choice.sizing.size} / 2)`,width:`calc(${baseStyles.choice.sizing.size} / 2)`,borderRadius:baseStyles.radio.border.radius.default,backgroundColor:checkedStyles.rest.background}};}else {const uncheckedStyles=colorStates.radio.unchecked[currentState];newStyles={inputWrapper:{":hover input:not([disabled])":{backgroundColor:uncheckedStyles.hover.background,outline:`${wonderBlocksTokens.border.width.medium} solid ${uncheckedStyles.hover.border}`,outlineOffset:-1}},default:{backgroundColor:uncheckedStyles.rest.background,borderColor:uncheckedStyles.rest.border,":focus-visible:not([disabled])":wonderBlocksStyles.focusStyles.focus[":focus-visible"],":active:not([disabled])":{backgroundColor:uncheckedStyles.press.background,outline:`${wonderBlocksTokens.border.width.medium} solid ${uncheckedStyles.press.border}`,outlineOffset:-1}}};}styles$5[styleKey]=aphrodite.StyleSheet.create(newStyles);return styles$5[styleKey]};
|
|
43
50
|
|
|
44
|
-
const ChoiceInternal=React__namespace.forwardRef(function ChoiceInternal(props,ref){const{checked,description,disabled=false,error=false,id,label,onChange,style,className,variant,...coreProps}=props;const handleClick=()=>{if(variant==="radio"&&checked){return}onChange(!checked);};const getChoiceCoreComponent=()=>{if(variant==="radio"){return RadioCore}else {return CheckboxCore}};const getLabel=id=>{return jsxRuntime.jsx(wonderBlocksTypography.
|
|
51
|
+
const ChoiceInternal=React__namespace.forwardRef(function ChoiceInternal(props,ref){const{checked,description,disabled=false,error=false,id,label,onChange,style,className,variant,...coreProps}=props;const handleClick=()=>{if(variant==="radio"&&checked){return}onChange(!checked);};const getChoiceCoreComponent=()=>{if(variant==="radio"){return RadioCore}else {return CheckboxCore}};const getLabel=id=>{return jsxRuntime.jsx(wonderBlocksTypography.BodyText,{tag:"div",weight:"semi",style:[styles$4.label,disabled&&styles$4.disabledLabel],children:jsxRuntime.jsx("label",{htmlFor:id,children:label})})};const getDescription=id=>{return jsxRuntime.jsx(wonderBlocksTypography.BodyText,{size:"small",style:styles$4.description,id:id,children:description})};const ChoiceCore=getChoiceCoreComponent();return jsxRuntime.jsx(wonderBlocksCore.Id,{id:id,children:uniqueId=>{const descriptionId=description?`${uniqueId}-description`:undefined;return jsxRuntime.jsxs(wonderBlocksCore.View,{style:style,className:className,children:[jsxRuntime.jsxs(wonderBlocksCore.View,{style:styles$4.wrapper,tabIndex:-1,children:[jsxRuntime.jsx(wonderBlocksCore.View,{style:[styles$4.choiceWrapper],children:jsxRuntime.jsx(ChoiceCore,{...coreProps,id:uniqueId,checked:checked,"aria-describedby":descriptionId,onClick:handleClick,disabled:disabled,error:error,ref:ref})}),label&&getLabel(uniqueId)]}),description&&getDescription(descriptionId)]})}})});const styles$4=aphrodite.StyleSheet.create({wrapper:{gap:wonderBlocksTokens.spacing.xSmall_8,lineHeight:wonderBlocksTokens.font.body.lineHeight.small,flexDirection:"row",alignItems:"flex-start",outline:"none"},choiceWrapper:{display:"block",marginBlockStart:wonderBlocksTokens.sizing.size_010},label:{color:wonderBlocksTokens.semanticColor.core.foreground.neutral.strong,lineHeight:wonderBlocksTokens.font.body.lineHeight.small},disabledLabel:{color:wonderBlocksTokens.semanticColor.core.foreground.disabled.subtle},description:{marginLeft:wonderBlocksTokens.spacing.medium_16+wonderBlocksTokens.spacing.xSmall_8,marginTop:wonderBlocksTokens.spacing.xxxSmall_4,color:wonderBlocksTokens.semanticColor.text.secondary}});
|
|
45
52
|
|
|
46
53
|
const Checkbox=React__namespace.forwardRef(function Checkbox(props,ref){const{disabled=false,error=false}=props;return jsxRuntime.jsx(ChoiceInternal,{...props,variant:"checkbox",disabled:disabled,error:error,ref:ref})});
|
|
47
54
|
|
|
@@ -51,9 +58,9 @@ const Choice=React__namespace.forwardRef(function Choice(props,ref){const{checke
|
|
|
51
58
|
|
|
52
59
|
const styles$3=aphrodite.StyleSheet.create({fieldset:{display:"flex",flexDirection:"column",border:"none",padding:0,margin:0},legend:{padding:0,width:"100%"},description:{marginTop:wonderBlocksTokens.spacing.xxxSmall_4,color:wonderBlocksTokens.semanticColor.text.secondary},error:{marginTop:wonderBlocksTokens.spacing.xxxSmall_4,color:wonderBlocksTokens.semanticColor.status.critical.foreground},defaultLineGap:{marginTop:wonderBlocksTokens.spacing.xSmall_8}});
|
|
53
60
|
|
|
54
|
-
const StyledFieldset$1=wonderBlocksCore.addStyle("fieldset");const StyledLegend$1=wonderBlocksCore.addStyle("legend");const CheckboxGroup=React__namespace.forwardRef(function CheckboxGroup(props,ref){const{children,label,description,errorMessage,groupName,onChange,selectedValues,style,testId}=props;const handleChange=(changedValue,originalCheckedState)=>{if(originalCheckedState){const index=selectedValues.indexOf(changedValue);const updatedSelection=[...selectedValues.slice(0,index),...selectedValues.slice(index+1)];onChange(updatedSelection);}else {onChange([...selectedValues,changedValue]);}};const allChildren=React__namespace.Children.toArray(children).filter(Boolean);return jsxRuntime.jsxs(StyledFieldset$1,{"data-testid":testId,style:[styles$3.fieldset,style],ref:ref,children:[label&&jsxRuntime.jsx(StyledLegend$1,{style:styles$3.legend,children:jsxRuntime.jsx(wonderBlocksTypography.
|
|
61
|
+
const StyledFieldset$1=wonderBlocksCore.addStyle("fieldset");const StyledLegend$1=wonderBlocksCore.addStyle("legend");const CheckboxGroup=React__namespace.forwardRef(function CheckboxGroup(props,ref){const{children,label,description,errorMessage,groupName,onChange,selectedValues,style,testId}=props;const handleChange=(changedValue,originalCheckedState)=>{if(originalCheckedState){const index=selectedValues.indexOf(changedValue);const updatedSelection=[...selectedValues.slice(0,index),...selectedValues.slice(index+1)];onChange(updatedSelection);}else {onChange([...selectedValues,changedValue]);}};const allChildren=React__namespace.Children.toArray(children).filter(Boolean);return jsxRuntime.jsxs(StyledFieldset$1,{"data-testid":testId,style:[styles$3.fieldset,style],ref:ref,children:[label&&jsxRuntime.jsx(StyledLegend$1,{style:styles$3.legend,children:jsxRuntime.jsx(wonderBlocksTypography.BodyText,{tag:"span",children:label})}),description&&jsxRuntime.jsx(wonderBlocksTypography.BodyText,{size:"small",tag:"span",style:styles$3.description,children:description}),errorMessage&&jsxRuntime.jsx(wonderBlocksTypography.BodyText,{size:"small",tag:"span",style:styles$3.error,children:errorMessage}),(label||description||errorMessage)&&jsxRuntime.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),allChildren.map((child,index)=>{const{style,value}=child.props;const checked=selectedValues.includes(value);return React__namespace.cloneElement(child,{checked:checked,error:!!errorMessage,groupName:groupName,id:`${groupName}-${value}`,key:value,onChange:()=>handleChange(value,checked),style:[index>0&&styles$3.defaultLineGap,style],variant:"checkbox"})})]})});
|
|
55
62
|
|
|
56
|
-
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.
|
|
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}),(label||description||errorMessage)&&jsxRuntime.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),allChildren.map((child,index)=>{const{style,value}=child.props;const checked=selectedValue===value;return React__namespace.cloneElement(child,{checked:checked,error:!!errorMessage,groupName:groupName,id:`${groupName}-${value}`,key:value,onChange:()=>onChange(value),style:[index>0&&styles$3.defaultLineGap,style],variant:"radio"})})]})});
|
|
57
64
|
|
|
58
65
|
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}};
|
|
59
66
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
type InteractionState = {
|
|
2
|
+
background?: string;
|
|
3
|
+
border?: string;
|
|
4
|
+
};
|
|
5
|
+
type ComponentState = {
|
|
6
|
+
rest: InteractionState;
|
|
7
|
+
hover: InteractionState;
|
|
8
|
+
press: InteractionState;
|
|
9
|
+
};
|
|
10
|
+
type ComponentStates = {
|
|
11
|
+
default: ComponentState;
|
|
12
|
+
disabled: ComponentState;
|
|
13
|
+
error: ComponentState;
|
|
14
|
+
};
|
|
15
|
+
export interface StyleMap {
|
|
16
|
+
[key: string]: {
|
|
17
|
+
unchecked: ComponentStates;
|
|
18
|
+
checked: ComponentStates;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export declare const baseStyles: {
|
|
22
|
+
choice: {
|
|
23
|
+
sizing: {
|
|
24
|
+
size: string;
|
|
25
|
+
};
|
|
26
|
+
checked: {
|
|
27
|
+
border: string;
|
|
28
|
+
};
|
|
29
|
+
disabled: {
|
|
30
|
+
border: string;
|
|
31
|
+
background: string;
|
|
32
|
+
};
|
|
33
|
+
error: {
|
|
34
|
+
border: string;
|
|
35
|
+
background: string;
|
|
36
|
+
};
|
|
37
|
+
unchecked: {
|
|
38
|
+
rest: {
|
|
39
|
+
border: string;
|
|
40
|
+
background: string;
|
|
41
|
+
};
|
|
42
|
+
hover: {
|
|
43
|
+
border: string;
|
|
44
|
+
background: string;
|
|
45
|
+
};
|
|
46
|
+
press: {
|
|
47
|
+
border: string;
|
|
48
|
+
background: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
radio: {
|
|
53
|
+
border: {
|
|
54
|
+
radius: {
|
|
55
|
+
default: string;
|
|
56
|
+
};
|
|
57
|
+
width: {
|
|
58
|
+
default: string;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
checkbox: {
|
|
63
|
+
border: {
|
|
64
|
+
radius: {
|
|
65
|
+
default: string;
|
|
66
|
+
};
|
|
67
|
+
width: {
|
|
68
|
+
default: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
sizing: {
|
|
72
|
+
checkSize: string;
|
|
73
|
+
};
|
|
74
|
+
disabledChecked: {
|
|
75
|
+
border: string;
|
|
76
|
+
background: string;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
icon: {
|
|
80
|
+
default: {
|
|
81
|
+
foreground: string;
|
|
82
|
+
};
|
|
83
|
+
disabled: {
|
|
84
|
+
foreground: string;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
export declare const colorStates: StyleMap;
|
|
89
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-form",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.0",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"description": "Form components for Wonder Blocks.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/es/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/es/index.js",
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"./styles.css": "./dist/css/vars.css"
|
|
16
|
+
},
|
|
9
17
|
"author": "",
|
|
10
18
|
"license": "MIT",
|
|
11
19
|
"publishConfig": {
|
|
12
20
|
"access": "public"
|
|
13
21
|
},
|
|
14
22
|
"dependencies": {
|
|
15
|
-
"@khanacademy/wonder-blocks-clickable": "7.1.
|
|
23
|
+
"@khanacademy/wonder-blocks-clickable": "7.1.13",
|
|
16
24
|
"@khanacademy/wonder-blocks-core": "12.3.0",
|
|
17
|
-
"@khanacademy/wonder-blocks-icon": "5.2.
|
|
18
|
-
"@khanacademy/wonder-blocks-layout": "3.1.
|
|
19
|
-
"@khanacademy/wonder-blocks-tokens": "11.2.
|
|
20
|
-
"@khanacademy/wonder-blocks-typography": "4.2.
|
|
25
|
+
"@khanacademy/wonder-blocks-icon": "5.2.7",
|
|
26
|
+
"@khanacademy/wonder-blocks-layout": "3.1.24",
|
|
27
|
+
"@khanacademy/wonder-blocks-tokens": "11.2.2",
|
|
28
|
+
"@khanacademy/wonder-blocks-typography": "4.2.9"
|
|
21
29
|
},
|
|
22
30
|
"peerDependencies": {
|
|
23
31
|
"@phosphor-icons/core": "^2.0.2",
|
|
@@ -28,6 +36,7 @@
|
|
|
28
36
|
"@khanacademy/wb-dev-build-settings": "3.2.0"
|
|
29
37
|
},
|
|
30
38
|
"scripts": {
|
|
39
|
+
"build:css": "pnpm exec wonder-blocks-tokens .",
|
|
31
40
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
32
41
|
}
|
|
33
42
|
}
|