@khanacademy/wonder-blocks-form 4.9.2 → 4.9.3

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/components/checkbox-core.d.ts +2 -2
  3. package/dist/components/checkbox.d.ts +2 -2
  4. package/dist/components/choice-internal.d.ts +2 -2
  5. package/dist/components/choice.d.ts +2 -2
  6. package/dist/components/radio-core.d.ts +2 -2
  7. package/dist/components/radio.d.ts +2 -2
  8. package/dist/components/text-area.d.ts +2 -2
  9. package/package.json +7 -7
  10. package/src/__tests__/__snapshots__/custom-snapshot.test.tsx.snap +0 -247
  11. package/src/__tests__/custom-snapshot.test.tsx +0 -48
  12. package/src/components/__tests__/checkbox-group.test.tsx +0 -162
  13. package/src/components/__tests__/checkbox.test.tsx +0 -138
  14. package/src/components/__tests__/field-heading.test.tsx +0 -225
  15. package/src/components/__tests__/labeled-text-field.test.tsx +0 -750
  16. package/src/components/__tests__/radio-group.test.tsx +0 -182
  17. package/src/components/__tests__/text-area.test.tsx +0 -1286
  18. package/src/components/__tests__/text-field.test.tsx +0 -562
  19. package/src/components/checkbox-core.tsx +0 -239
  20. package/src/components/checkbox-group.tsx +0 -174
  21. package/src/components/checkbox.tsx +0 -99
  22. package/src/components/choice-internal.tsx +0 -184
  23. package/src/components/choice.tsx +0 -157
  24. package/src/components/field-heading.tsx +0 -169
  25. package/src/components/group-styles.ts +0 -33
  26. package/src/components/labeled-text-field.tsx +0 -317
  27. package/src/components/radio-core.tsx +0 -171
  28. package/src/components/radio-group.tsx +0 -159
  29. package/src/components/radio.tsx +0 -82
  30. package/src/components/text-area.tsx +0 -430
  31. package/src/components/text-field.tsx +0 -399
  32. package/src/index.ts +0 -17
  33. package/src/util/types.ts +0 -85
  34. package/tsconfig-build.json +0 -19
  35. package/tsconfig-build.tsbuildinfo +0 -1
@@ -1,171 +0,0 @@
1
- import * as React from "react";
2
- import {StyleSheet} from "aphrodite";
3
-
4
- import {mix, color} from "@khanacademy/wonder-blocks-tokens";
5
- import {addStyle} from "@khanacademy/wonder-blocks-core";
6
-
7
- import type {ChoiceCoreProps, Checked} from "../util/types";
8
-
9
- const {blue, red, white, offWhite, offBlack16, offBlack32, offBlack50} = color;
10
-
11
- const StyledInput = addStyle("input");
12
-
13
- /**
14
- * The internal stateless 🔘 Radio button
15
- */ const RadioCore = React.forwardRef(function RadioCore(
16
- props: ChoiceCoreProps,
17
- ref: React.ForwardedRef<HTMLInputElement>,
18
- ) {
19
- const handleChange = () => {
20
- // Empty because change is handled by ClickableBehavior
21
- return;
22
- };
23
-
24
- const {checked, disabled, error, groupName, id, testId, ...sharedProps} =
25
- props;
26
-
27
- const stateStyles = _generateStyles(checked, error);
28
- const defaultStyle = [
29
- sharedStyles.inputReset,
30
- sharedStyles.default,
31
- !disabled && stateStyles.default,
32
- disabled && sharedStyles.disabled,
33
- ];
34
-
35
- return (
36
- <React.Fragment>
37
- <StyledInput
38
- {...sharedProps}
39
- type="radio"
40
- aria-invalid={error}
41
- checked={checked ?? undefined}
42
- disabled={disabled}
43
- id={id}
44
- name={groupName}
45
- // Need to specify because this is a controlled React form
46
- // component, but we handle the click via ClickableBehavior
47
- onChange={handleChange}
48
- style={defaultStyle}
49
- data-testid={testId}
50
- ref={ref}
51
- />
52
- {disabled && checked && <span style={disabledChecked} />}
53
- </React.Fragment>
54
- );
55
- });
56
-
57
- const size = 16; // circle with a different color. Here, we add that center circle. // If the checkbox is disabled and selected, it has a border but also an inner
58
- const disabledChecked = {
59
- position: "absolute",
60
- top: size / 4,
61
- left: size / 4,
62
- height: size / 2,
63
- width: size / 2,
64
- borderRadius: "50%",
65
- backgroundColor: offBlack32,
66
- } as const;
67
- const sharedStyles = StyleSheet.create({
68
- // Reset the default styled input element
69
- inputReset: {
70
- appearance: "none",
71
- WebkitAppearance: "none",
72
- MozAppearance: "none",
73
- },
74
- default: {
75
- height: size,
76
- width: size,
77
- minHeight: size,
78
- minWidth: size,
79
- margin: 0,
80
- outline: "none",
81
- boxSizing: "border-box",
82
- borderStyle: "solid",
83
- borderWidth: 1,
84
- borderRadius: "50%",
85
- },
86
- disabled: {
87
- cursor: "auto",
88
- backgroundColor: offWhite,
89
- borderColor: offBlack16,
90
- borderWidth: 1,
91
- },
92
- });
93
- const fadedBlue = mix(color.fadedBlue16, white);
94
- const fadedRed = mix(color.fadedRed8, white);
95
- const colors = {
96
- default: {
97
- faded: fadedBlue,
98
- base: blue,
99
- active: color.activeBlue,
100
- },
101
- error: {
102
- faded: fadedRed,
103
- base: red,
104
- active: color.activeRed,
105
- },
106
- } as const;
107
- const styles: Record<string, any> = {};
108
- const _generateStyles = (checked: Checked, error: boolean) => {
109
- // "hash" the parameters
110
- const styleKey = `${String(checked)}-${String(error)}`;
111
- if (styles[styleKey]) {
112
- return styles[styleKey];
113
- }
114
- const palette = error ? colors.error : colors.default;
115
- let newStyles: Record<string, any> = {};
116
- if (checked) {
117
- newStyles = {
118
- default: {
119
- backgroundColor: white,
120
- borderColor: palette.base,
121
- borderWidth: size / 4,
122
-
123
- // Focus and hover have the same style. Focus style only shows
124
- // up with keyboard navigation.
125
- ":focus-visible": {
126
- boxShadow: `0 0 0 1px ${white}, 0 0 0 3px ${palette.base}`,
127
- },
128
-
129
- ":hover": {
130
- boxShadow: `0 0 0 1px ${white}, 0 0 0 3px ${palette.base}`,
131
- },
132
-
133
- ":active": {
134
- boxShadow: `0 0 0 1px ${white}, 0 0 0 3px ${palette.active}`,
135
- borderColor: palette.active,
136
- },
137
- },
138
- };
139
- } else {
140
- newStyles = {
141
- default: {
142
- backgroundColor: error ? fadedRed : white,
143
- borderColor: error ? red : offBlack50,
144
-
145
- // Focus and hover have the same style. Focus style only shows
146
- // up with keyboard navigation.
147
- ":focus-visible": {
148
- backgroundColor: error ? fadedRed : white,
149
- borderColor: palette.base,
150
- borderWidth: 2,
151
- },
152
-
153
- ":hover": {
154
- backgroundColor: error ? fadedRed : white,
155
- borderColor: palette.base,
156
- borderWidth: 2,
157
- },
158
-
159
- ":active": {
160
- backgroundColor: palette.faded,
161
- borderColor: error ? color.activeRed : blue,
162
- borderWidth: 2,
163
- },
164
- },
165
- };
166
- }
167
- styles[styleKey] = StyleSheet.create(newStyles);
168
- return styles[styleKey];
169
- };
170
-
171
- export default RadioCore;
@@ -1,159 +0,0 @@
1
- import * as React from "react";
2
-
3
- import {View, addStyle} from "@khanacademy/wonder-blocks-core";
4
- import {Strut} from "@khanacademy/wonder-blocks-layout";
5
- import {spacing} from "@khanacademy/wonder-blocks-tokens";
6
- import {LabelMedium, LabelSmall} from "@khanacademy/wonder-blocks-typography";
7
- import type {StyleType} from "@khanacademy/wonder-blocks-core";
8
-
9
- import styles from "./group-styles";
10
- import Choice from "./choice";
11
-
12
- // Keep synced with RadioGroupProps in ../util/types.js
13
- type RadioGroupProps = {
14
- /**
15
- * Children should be Choice components.
16
- */
17
- children: Array<
18
- | React.ReactElement<React.ComponentProps<typeof Choice>>
19
- | false
20
- | null
21
- | undefined
22
- >;
23
- /**
24
- * Group name for this checkbox or radio group. Should be unique for all
25
- * such groups displayed on a page.
26
- */
27
- groupName: string;
28
- /**
29
- * Optional label for the group. This label is optional to allow for
30
- * greater flexibility in implementing checkbox and radio groups.
31
- */
32
- label?: React.ReactNode;
33
- /**
34
- * Optional description for the group.
35
- */
36
- description?: React.ReactNode;
37
- /**
38
- * Optional error message. If supplied, the group will be displayed in an
39
- * error state, along with this error message. If no error state is desired,
40
- * simply do not supply this prop, or pass along null.
41
- */
42
- errorMessage?: string;
43
- /**
44
- * Custom styling for this group of checkboxes.
45
- */
46
- style?: StyleType;
47
- /**
48
- * Callback for when the selected value of the radio group has changed.
49
- */
50
- onChange: (selectedValue: string) => unknown;
51
- /**
52
- * Value of the selected radio item.
53
- */
54
- selectedValue: string;
55
- /**
56
- * Test ID used for e2e testing.
57
- */
58
- testId?: string;
59
- };
60
-
61
- const StyledFieldset = addStyle("fieldset");
62
- const StyledLegend = addStyle("legend");
63
-
64
- /**
65
- * A radio group allows only single selection. Like CheckboxGroup, this
66
- * component auto-populates many props for its children Choice components. The
67
- * Choice component is exposed for the user to apply custom styles or to
68
- * indicate which choices are disabled. The use of the groupName prop is
69
- * important to maintain expected keyboard navigation behavior for
70
- * accessibility.
71
- *
72
- * ### Usage
73
- *
74
- * ```jsx
75
- * import {Choice, RadioGroup} from "@khanacademy/wonder-blocks-form";
76
- *
77
- * const [selectedValue, setSelectedValue] = React.useState("");
78
- *
79
- * <RadioGroup
80
- * label="some-label"
81
- * description="some-description"
82
- * groupName="some-group-name"
83
- * onChange={setSelectedValue}
84
- * selectedValue={selectedValue}
85
- * >
86
- * // Add as many choices as necessary
87
- * <Choice
88
- * label="Choice 1"
89
- * value="some-choice-value"
90
- * />
91
- * <Choice
92
- * label="Choice 2"
93
- * value="some-choice-value-2"
94
- * description="Some choice description."
95
- * />
96
- * </RadioGroup>
97
- * ```
98
- */
99
- const RadioGroup = React.forwardRef(function RadioGroup(
100
- props: RadioGroupProps,
101
- ref: React.ForwardedRef<HTMLFieldSetElement>,
102
- ) {
103
- const {
104
- children,
105
- label,
106
- description,
107
- errorMessage,
108
- groupName,
109
- onChange,
110
- selectedValue,
111
- style,
112
- testId,
113
- } = props;
114
-
115
- const allChildren = React.Children.toArray(children).filter(Boolean);
116
-
117
- return (
118
- <StyledFieldset data-testid={testId} style={styles.fieldset} ref={ref}>
119
- {/* We have a View here because fieldset cannot be used with flexbox*/}
120
- <View style={style}>
121
- {label && (
122
- <StyledLegend style={styles.legend}>
123
- <LabelMedium>{label}</LabelMedium>
124
- </StyledLegend>
125
- )}
126
- {description && (
127
- <LabelSmall style={styles.description}>
128
- {description}
129
- </LabelSmall>
130
- )}
131
- {errorMessage && (
132
- <LabelSmall style={styles.error}>{errorMessage}</LabelSmall>
133
- )}
134
- {(label || description || errorMessage) && (
135
- <Strut size={spacing.small_12} />
136
- )}
137
-
138
- {allChildren.map((child, index) => {
139
- // @ts-expect-error [FEI-5019] - TS2339 - Property 'props' does not exist on type 'ReactChild | ReactFragment | ReactPortal'.
140
- const {style, value} = child.props;
141
- const checked = selectedValue === value;
142
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
143
- return React.cloneElement(child, {
144
- checked: checked,
145
- error: !!errorMessage,
146
- groupName: groupName,
147
- id: `${groupName}-${value}`,
148
- key: value,
149
- onChange: () => onChange(value),
150
- style: [index > 0 && styles.defaultLineGap, style],
151
- variant: "radio",
152
- });
153
- })}
154
- </View>
155
- </StyledFieldset>
156
- );
157
- });
158
-
159
- export default RadioGroup;
@@ -1,82 +0,0 @@
1
- import * as React from "react";
2
-
3
- import type {AriaProps, StyleType} from "@khanacademy/wonder-blocks-core";
4
- import ChoiceInternal from "./choice-internal";
5
-
6
- // Keep synced with ChoiceComponentProps in ../util/types.js
7
- type ChoiceComponentProps = AriaProps & {
8
- /**
9
- * Whether this component is checked
10
- */
11
- checked: boolean;
12
- /**
13
- * Whether this component is disabled
14
- */
15
- disabled?: boolean;
16
- /**
17
- * Whether this component should show an error state
18
- */
19
- error?: boolean;
20
- /**
21
- * Callback when this component is selected. The newCheckedState is the
22
- * new checked state of the component.
23
- */
24
- onChange: (newCheckedState: boolean) => unknown;
25
- /**
26
- * Optional label for the field.
27
- */
28
- label?: React.ReactNode;
29
- /**
30
- * Optional description for the field.
31
- */
32
- description?: React.ReactNode;
33
- /**
34
- * Unique identifier attached to the HTML input element. If used, need to
35
- * guarantee that the ID is unique within everything rendered on a page.
36
- * Used to match `<label>` with `<input>` elements for screenreaders.
37
- */
38
- id?: string;
39
- /**
40
- * Optional styling for the container. Does not style the component.
41
- */
42
- style?: StyleType;
43
- /**
44
- * Adds CSS classes to the Checkbox.
45
- */
46
- className?: string;
47
- /**
48
- * Optional test ID for e2e testing
49
- */
50
- testId?: string;
51
- /**
52
- * Name for the checkbox or radio button group. Only applicable for group
53
- * contexts, auto-populated by group components via Choice.
54
- * @ignore
55
- */
56
- groupName?: string;
57
- };
58
-
59
- /**
60
- * 🔘 A nicely styled radio button for all your non-AMFM radio button needs. Can
61
- * optionally take label and description props.
62
- *
63
- * This component should not really be used by itself because radio buttons are
64
- * often grouped together. See RadioGroup.
65
- */ const Radio = React.forwardRef(function Radio(
66
- props: ChoiceComponentProps,
67
- ref: React.ForwardedRef<HTMLInputElement>,
68
- ) {
69
- const {disabled = false, error = false, ...otherProps} = props;
70
-
71
- return (
72
- <ChoiceInternal
73
- {...otherProps}
74
- variant="radio"
75
- disabled={disabled}
76
- error={error}
77
- ref={ref}
78
- />
79
- );
80
- });
81
-
82
- export default Radio;