@khanacademy/wonder-blocks-labeled-field 4.1.11 → 4.3.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 +19 -0
- package/dist/components/labeled-field.d.ts +9 -2
- package/dist/es/index.js +2 -1
- package/dist/index.js +2 -1
- package/package.json +2 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @khanacademy/wonder-blocks-labeled-field@4.
|
|
2
|
+
> @khanacademy/wonder-blocks-labeled-field@4.3.0 build:css /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-labeled-field
|
|
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-labeled-field/dist/css
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-labeled-field
|
|
2
2
|
|
|
3
|
+
## 4.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- f070142: The default `aria-label` for the LabeledField error icon now reads a translated string from `WonderBlocksConfigProvider`. The `labels.errorIconAriaLabel` 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
|
+
## 4.2.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- bd6275f: LabeledField: use id and testId on the root element of the component
|
|
21
|
+
|
|
3
22
|
## 4.1.11
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -23,8 +23,9 @@ type Props = {
|
|
|
23
23
|
* set the `error` prop on the `field` component.
|
|
24
24
|
*
|
|
25
25
|
* Note: Since the error icon has an aria-label, screen readers will
|
|
26
|
-
* prefix the error message with
|
|
27
|
-
*
|
|
26
|
+
* prefix the error message with the `iconAltErrorMessagePrefix` string
|
|
27
|
+
* provided by `WonderBlocksConfigProvider` ("Error:" by default), or the
|
|
28
|
+
* value provided to the errorIconAriaLabel in the `labels` prop.
|
|
28
29
|
*
|
|
29
30
|
* If both `errorMessage` and `readOnlyMessage` are provided, the `readOnlyMessage`
|
|
30
31
|
* is displayed first.
|
|
@@ -60,6 +61,7 @@ type Props = {
|
|
|
60
61
|
/**
|
|
61
62
|
* A unique id to use as the base of the ids for the elements within the component.
|
|
62
63
|
* Here is how the id is used for the different elements in the component:
|
|
64
|
+
* - The root element will have an id formatted as `${id}`
|
|
63
65
|
* - The label will have an id formatted as `${id}-label`
|
|
64
66
|
* - The context label will have an id formatted as `${id}-context-label`
|
|
65
67
|
* - The description will have an id formatted as `${id}-description`
|
|
@@ -79,6 +81,7 @@ type Props = {
|
|
|
79
81
|
/**
|
|
80
82
|
* Optional test id for e2e testing. Here is how the test id is used for the
|
|
81
83
|
* different elements in the component:
|
|
84
|
+
* - The root element will have a testId formatted as `${testId}`
|
|
82
85
|
* - The label will have a testId formatted as `${testId}-label`
|
|
83
86
|
* - The context label will have a testId formatted as `${testId}-context-label`
|
|
84
87
|
* - The description will have a testId formatted as `${testId}-description`
|
|
@@ -96,6 +99,10 @@ type Props = {
|
|
|
96
99
|
labels?: LabeledFieldLabels;
|
|
97
100
|
};
|
|
98
101
|
export type LabeledFieldLabels = {
|
|
102
|
+
/**
|
|
103
|
+
* The `aria-label` for the error icon. This overrides the default label
|
|
104
|
+
* provided by `WonderBlocksConfigProvider`.
|
|
105
|
+
*/
|
|
99
106
|
errorIconAriaLabel?: string;
|
|
100
107
|
readOnlyIconAriaLabel?: string;
|
|
101
108
|
};
|
package/dist/es/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { StyleSheet } from 'aphrodite';
|
|
4
4
|
import WarningCircle from '@phosphor-icons/core/bold/warning-circle-bold.svg';
|
|
5
5
|
import LockIcon from '@phosphor-icons/core/bold/lock-bold.svg';
|
|
6
|
+
import { useWonderBlocksI18n } from '@khanacademy/wonder-blocks-config';
|
|
6
7
|
import { BodyText } from '@khanacademy/wonder-blocks-typography';
|
|
7
8
|
import { addStyle, View } from '@khanacademy/wonder-blocks-core';
|
|
8
9
|
import { sizing, semanticColor, font, mapValuesToCssVars } from '@khanacademy/wonder-blocks-tokens';
|
|
@@ -13,6 +14,6 @@ const theme$1={root:{layout:{paddingBlockEnd:{labelWithDescription:sizing.size_0
|
|
|
13
14
|
|
|
14
15
|
var theme = mapValuesToCssVars(theme$1,"--wb-c-labeled-field-");
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
function LabeledField(props){const{field,styles:stylesProp,label,id,testId,contextLabel,description,errorMessage,readOnlyMessage,additionalHelperMessage,labels}=props;const{strings}=useWonderBlocksI18n();const generatedUniqueId=React.useId();const uniqueId=id??`${generatedUniqueId}-labeled-field`;const labelId=`${uniqueId}-label`;const descriptionId=`${uniqueId}-description`;const fieldId=`${uniqueId}-field`;const errorId=`${uniqueId}-error`;const readOnlyMessageId=`${uniqueId}-read-only-message`;const additionalHelperMessageId=`${uniqueId}-additional-helper-message`;const contextLabelId=`${uniqueId}-context-label`;const hasError=!!errorMessage||!!field.props.error;const isDisabled=!!field.props.disabled;function renderLabelAndContextLabel(){return jsxs(View,{style:styles.labelContainer,children:[jsx(BodyText,{style:[styles.label,hasError?styles.labelWithError:undefined,description?styles.labelWithDescription:styles.labelWithNoDescription,isDisabled&&styles.disabledLabel,stylesProp?.label],tag:"label",htmlFor:fieldId,testId:testId&&`${testId}-label`,id:labelId,weight:"semi",children:label}),contextLabel&&jsx(BodyText,{tag:"div",id:contextLabelId,testId:testId&&`${testId}-context-label`,style:[styles.helperText,styles.contextLabel,isDisabled&&styles.disabledHelperText,hasError?styles.contextLabelWithError:undefined,stylesProp?.contextLabel],children:contextLabel})]})}function maybeRenderDescription(){if(!description){return null}return jsx(BodyText,{style:[styles.helperText,styles.spacingBelowHelperText,isDisabled&&styles.disabledHelperText,stylesProp?.description],testId:testId&&`${testId}-description`,id:descriptionId,children:description})}function maybeRenderError(){return jsx(View,{style:[styles.helperTextWithIcon,errorMessage?styles.spacingAboveHelperText:undefined,stylesProp?.error],id:errorId,testId:testId&&`${testId}-error`,"aria-live":"assertive","aria-atomic":"true",children:errorMessage&&jsxs(Fragment,{children:[jsx(PhosphorIcon,{icon:WarningCircle,style:[styles.errorIcon,styles.error],role:"img","aria-label":labels?.errorIconAriaLabel||strings.iconAltErrorMessagePrefix}),jsx(BodyText,{style:[styles.helperText,styles.errorMessage,styles.error],children:errorMessage})]})})}function renderField(){return React.cloneElement(field,{id:fieldId,"aria-describedby":[contextLabel&&contextLabelId,description&&descriptionId,additionalHelperMessage&&additionalHelperMessageId,readOnlyMessage&&readOnlyMessageId,errorMessage&&errorId].filter(Boolean).join(" "),error:hasError,testId:testId?`${testId}-field`:undefined,readOnly:!!readOnlyMessage||field.props.readOnly})}function maybeRenderReadOnlyMessage(){if(!readOnlyMessage){return null}return jsxs(View,{style:[styles.helperTextWithIcon,styles.spacingAboveHelperText,stylesProp?.readOnlyMessage],id:readOnlyMessageId,testId:testId&&`${testId}-read-only-message`,children:[jsx(PhosphorIcon,{icon:LockIcon,"aria-label":labels?.readOnlyIconAriaLabel,color:semanticColor.core.foreground.neutral.subtle}),jsx(BodyText,{style:styles.helperText,children:readOnlyMessage})]})}function maybeRenderAdditionalHelperMessage(){if(!additionalHelperMessage){return null}return jsx(BodyText,{id:additionalHelperMessageId,testId:testId&&`${testId}-additional-helper-message`,style:[styles.helperText,styles.spacingAboveHelperText,isDisabled&&styles.disabledHelperText,stylesProp?.additionalHelperMessage],tag:"div",children:additionalHelperMessage})}return jsxs(View,{style:stylesProp?.root,testId:testId,id:uniqueId,children:[renderLabelAndContextLabel(),maybeRenderDescription(),renderField(),maybeRenderAdditionalHelperMessage(),maybeRenderReadOnlyMessage(),maybeRenderError()]})}const styles=StyleSheet.create({labelContainer:{display:"flex",flexDirection:"row",justifyContent:"space-between",gap:theme.root.layout.spacingBetweenHelperText},label:{color:semanticColor.core.foreground.neutral.strong,overflowWrap:"break-word",minInlineSize:sizing.size_0},contextLabel:{lineHeight:font.body.lineHeight.medium,maxInlineSize:"30%",flexShrink:0},labelWithError:{color:theme.label.color.error.foreground,fontWeight:theme.error.font.weight},contextLabelWithError:{color:theme.contextLabel.color.error.foreground,fontWeight:theme.error.font.weight},disabledLabel:{color:theme.label.color.disabled.foreground},labelWithDescription:{paddingBlockEnd:theme.root.layout.paddingBlockEnd.labelWithDescription},labelWithNoDescription:{paddingBlockEnd:theme.root.layout.paddingBlockEnd.labelWithNoDescription},helperTextWithIcon:{flexDirection:"row",gap:theme.helperText.layout.gap},spacingAboveHelperText:{paddingBlockStart:theme.root.layout.spacingBetweenHelperText},spacingBelowHelperText:{paddingBlockEnd:theme.root.layout.spacingBetweenHelperText},helperText:{color:theme.helperText.color.default.foreground,fontSize:theme.helperText.font.size,lineHeight:theme.helperText.font.lineHeight,minInlineSize:sizing.size_0,overflowWrap:"break-word"},disabledHelperText:{color:theme.helperText.color.disabled.foreground},error:{color:semanticColor.core.foreground.critical.default},errorIcon:{marginBlockStart:sizing.size_010},errorMessage:{fontWeight:theme.error.font.weight,marginBlockStart:theme.error.layout.marginBlockStart}});
|
|
17
18
|
|
|
18
19
|
export { LabeledField };
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ var React = require('react');
|
|
|
7
7
|
var aphrodite = require('aphrodite');
|
|
8
8
|
var WarningCircle = require('@phosphor-icons/core/bold/warning-circle-bold.svg');
|
|
9
9
|
var LockIcon = require('@phosphor-icons/core/bold/lock-bold.svg');
|
|
10
|
+
var wonderBlocksConfig = require('@khanacademy/wonder-blocks-config');
|
|
10
11
|
var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
|
|
11
12
|
var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
|
|
12
13
|
var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
|
|
@@ -41,6 +42,6 @@ const theme$1={root:{layout:{paddingBlockEnd:{labelWithDescription:wonderBlocksT
|
|
|
41
42
|
|
|
42
43
|
var theme = wonderBlocksTokens.mapValuesToCssVars(theme$1,"--wb-c-labeled-field-");
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
function LabeledField(props){const{field,styles:stylesProp,label,id,testId,contextLabel,description,errorMessage,readOnlyMessage,additionalHelperMessage,labels}=props;const{strings}=wonderBlocksConfig.useWonderBlocksI18n();const generatedUniqueId=React__namespace.useId();const uniqueId=id??`${generatedUniqueId}-labeled-field`;const labelId=`${uniqueId}-label`;const descriptionId=`${uniqueId}-description`;const fieldId=`${uniqueId}-field`;const errorId=`${uniqueId}-error`;const readOnlyMessageId=`${uniqueId}-read-only-message`;const additionalHelperMessageId=`${uniqueId}-additional-helper-message`;const contextLabelId=`${uniqueId}-context-label`;const hasError=!!errorMessage||!!field.props.error;const isDisabled=!!field.props.disabled;function renderLabelAndContextLabel(){return jsxRuntime.jsxs(wonderBlocksCore.View,{style:styles.labelContainer,children:[jsxRuntime.jsx(wonderBlocksTypography.BodyText,{style:[styles.label,hasError?styles.labelWithError:undefined,description?styles.labelWithDescription:styles.labelWithNoDescription,isDisabled&&styles.disabledLabel,stylesProp?.label],tag:"label",htmlFor:fieldId,testId:testId&&`${testId}-label`,id:labelId,weight:"semi",children:label}),contextLabel&&jsxRuntime.jsx(wonderBlocksTypography.BodyText,{tag:"div",id:contextLabelId,testId:testId&&`${testId}-context-label`,style:[styles.helperText,styles.contextLabel,isDisabled&&styles.disabledHelperText,hasError?styles.contextLabelWithError:undefined,stylesProp?.contextLabel],children:contextLabel})]})}function maybeRenderDescription(){if(!description){return null}return jsxRuntime.jsx(wonderBlocksTypography.BodyText,{style:[styles.helperText,styles.spacingBelowHelperText,isDisabled&&styles.disabledHelperText,stylesProp?.description],testId:testId&&`${testId}-description`,id:descriptionId,children:description})}function maybeRenderError(){return jsxRuntime.jsx(wonderBlocksCore.View,{style:[styles.helperTextWithIcon,errorMessage?styles.spacingAboveHelperText:undefined,stylesProp?.error],id:errorId,testId:testId&&`${testId}-error`,"aria-live":"assertive","aria-atomic":"true",children:errorMessage&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(PhosphorIcon,{icon:WarningCircle__default["default"],style:[styles.errorIcon,styles.error],role:"img","aria-label":labels?.errorIconAriaLabel||strings.iconAltErrorMessagePrefix}),jsxRuntime.jsx(wonderBlocksTypography.BodyText,{style:[styles.helperText,styles.errorMessage,styles.error],children:errorMessage})]})})}function renderField(){return React__namespace.cloneElement(field,{id:fieldId,"aria-describedby":[contextLabel&&contextLabelId,description&&descriptionId,additionalHelperMessage&&additionalHelperMessageId,readOnlyMessage&&readOnlyMessageId,errorMessage&&errorId].filter(Boolean).join(" "),error:hasError,testId:testId?`${testId}-field`:undefined,readOnly:!!readOnlyMessage||field.props.readOnly})}function maybeRenderReadOnlyMessage(){if(!readOnlyMessage){return null}return jsxRuntime.jsxs(wonderBlocksCore.View,{style:[styles.helperTextWithIcon,styles.spacingAboveHelperText,stylesProp?.readOnlyMessage],id:readOnlyMessageId,testId:testId&&`${testId}-read-only-message`,children:[jsxRuntime.jsx(PhosphorIcon,{icon:LockIcon__default["default"],"aria-label":labels?.readOnlyIconAriaLabel,color:wonderBlocksTokens.semanticColor.core.foreground.neutral.subtle}),jsxRuntime.jsx(wonderBlocksTypography.BodyText,{style:styles.helperText,children:readOnlyMessage})]})}function maybeRenderAdditionalHelperMessage(){if(!additionalHelperMessage){return null}return jsxRuntime.jsx(wonderBlocksTypography.BodyText,{id:additionalHelperMessageId,testId:testId&&`${testId}-additional-helper-message`,style:[styles.helperText,styles.spacingAboveHelperText,isDisabled&&styles.disabledHelperText,stylesProp?.additionalHelperMessage],tag:"div",children:additionalHelperMessage})}return jsxRuntime.jsxs(wonderBlocksCore.View,{style:stylesProp?.root,testId:testId,id:uniqueId,children:[renderLabelAndContextLabel(),maybeRenderDescription(),renderField(),maybeRenderAdditionalHelperMessage(),maybeRenderReadOnlyMessage(),maybeRenderError()]})}const styles=aphrodite.StyleSheet.create({labelContainer:{display:"flex",flexDirection:"row",justifyContent:"space-between",gap:theme.root.layout.spacingBetweenHelperText},label:{color:wonderBlocksTokens.semanticColor.core.foreground.neutral.strong,overflowWrap:"break-word",minInlineSize:wonderBlocksTokens.sizing.size_0},contextLabel:{lineHeight:wonderBlocksTokens.font.body.lineHeight.medium,maxInlineSize:"30%",flexShrink:0},labelWithError:{color:theme.label.color.error.foreground,fontWeight:theme.error.font.weight},contextLabelWithError:{color:theme.contextLabel.color.error.foreground,fontWeight:theme.error.font.weight},disabledLabel:{color:theme.label.color.disabled.foreground},labelWithDescription:{paddingBlockEnd:theme.root.layout.paddingBlockEnd.labelWithDescription},labelWithNoDescription:{paddingBlockEnd:theme.root.layout.paddingBlockEnd.labelWithNoDescription},helperTextWithIcon:{flexDirection:"row",gap:theme.helperText.layout.gap},spacingAboveHelperText:{paddingBlockStart:theme.root.layout.spacingBetweenHelperText},spacingBelowHelperText:{paddingBlockEnd:theme.root.layout.spacingBetweenHelperText},helperText:{color:theme.helperText.color.default.foreground,fontSize:theme.helperText.font.size,lineHeight:theme.helperText.font.lineHeight,minInlineSize:wonderBlocksTokens.sizing.size_0,overflowWrap:"break-word"},disabledHelperText:{color:theme.helperText.color.disabled.foreground},error:{color:wonderBlocksTokens.semanticColor.core.foreground.critical.default},errorIcon:{marginBlockStart:wonderBlocksTokens.sizing.size_010},errorMessage:{fontWeight:theme.error.font.weight,marginBlockStart:theme.error.layout.marginBlockStart}});
|
|
45
46
|
|
|
46
47
|
exports.LabeledField = LabeledField;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "LabeledField handles accessibility and layout for associating labels with form components.",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "4.
|
|
6
|
+
"version": "4.3.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"./styles.css": "./dist/css/vars.css"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
+
"@khanacademy/wonder-blocks-config": "0.4.0",
|
|
31
32
|
"@khanacademy/wonder-blocks-core": "12.5.0",
|
|
32
33
|
"@khanacademy/wonder-blocks-layout": "3.1.62",
|
|
33
34
|
"@khanacademy/wonder-blocks-tokens": "18.0.0",
|