@khanacademy/wonder-blocks-form 4.2.3 → 4.3.1

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 (33) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/components/checkbox-core.d.ts +13 -8
  3. package/dist/components/checkbox-core.js.flow +19 -10
  4. package/dist/components/checkbox-group.d.ts +2 -5
  5. package/dist/components/checkbox-group.js.flow +5 -6
  6. package/dist/components/checkbox.d.ts +33 -39
  7. package/dist/components/checkbox.js.flow +38 -41
  8. package/dist/components/choice-internal.d.ts +19 -31
  9. package/dist/components/choice-internal.js.flow +25 -32
  10. package/dist/components/choice.d.ts +50 -60
  11. package/dist/components/choice.js.flow +79 -84
  12. package/dist/components/radio-core.d.ts +13 -5
  13. package/dist/components/radio-core.js.flow +19 -7
  14. package/dist/components/radio-group.d.ts +2 -5
  15. package/dist/components/radio-group.js.flow +5 -6
  16. package/dist/components/radio.d.ts +18 -24
  17. package/dist/components/radio.js.flow +24 -27
  18. package/dist/es/index.js +262 -294
  19. package/dist/index.js +262 -294
  20. package/dist/util/types.d.ts +1 -1
  21. package/dist/util/types.js.flow +1 -1
  22. package/package.json +6 -6
  23. package/src/components/__tests__/{checkbox.test.js → checkbox.test.tsx} +55 -1
  24. package/src/components/checkbox-core.tsx +66 -71
  25. package/src/components/checkbox-group.tsx +62 -59
  26. package/src/components/checkbox.tsx +19 -16
  27. package/src/components/choice-internal.tsx +80 -77
  28. package/src/components/choice.tsx +34 -26
  29. package/src/components/radio-core.tsx +40 -44
  30. package/src/components/radio-group.tsx +57 -59
  31. package/src/components/radio.tsx +19 -16
  32. package/src/util/types.ts +1 -1
  33. package/tsconfig-build.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-form",
3
- "version": "4.2.3",
3
+ "version": "4.3.1",
4
4
  "design": "v1",
5
5
  "description": "Form components for Wonder Blocks.",
6
6
  "main": "dist/index.js",
@@ -16,13 +16,13 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@babel/runtime": "^7.18.6",
19
- "@khanacademy/wonder-blocks-clickable": "^3.1.0",
19
+ "@khanacademy/wonder-blocks-clickable": "^3.1.2",
20
20
  "@khanacademy/wonder-blocks-color": "^2.0.1",
21
- "@khanacademy/wonder-blocks-core": "^5.2.3",
22
- "@khanacademy/wonder-blocks-icon": "^2.0.13",
23
- "@khanacademy/wonder-blocks-layout": "^2.0.13",
21
+ "@khanacademy/wonder-blocks-core": "^5.3.1",
22
+ "@khanacademy/wonder-blocks-icon": "^2.0.15",
23
+ "@khanacademy/wonder-blocks-layout": "^2.0.15",
24
24
  "@khanacademy/wonder-blocks-spacing": "^4.0.1",
25
- "@khanacademy/wonder-blocks-typography": "^2.0.13"
25
+ "@khanacademy/wonder-blocks-typography": "^2.1.1"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "aphrodite": "^1.2.5",
@@ -1,4 +1,3 @@
1
- //@flow
2
1
  import * as React from "react";
3
2
  import {render, screen} from "@testing-library/react";
4
3
 
@@ -81,4 +80,59 @@ describe("Checkbox", () => {
81
80
  // Assert
82
81
  expect(onChangeSpy).toHaveBeenCalled();
83
82
  });
83
+
84
+ test.each`
85
+ indeterminateValue | checkedValue
86
+ ${true} | ${null}
87
+ ${false} | ${true}
88
+ ${false} | ${false}
89
+ `(
90
+ "sets the indeterminate property to $indeterminateValue when checked is $checkedValue (with ref)",
91
+ ({indeterminateValue, checkedValue}) => {
92
+ // Arrange
93
+ const ref = React.createRef<HTMLInputElement>();
94
+
95
+ // Act
96
+ render(
97
+ <Checkbox
98
+ label="Some label"
99
+ description="Some description"
100
+ checked={checkedValue}
101
+ onChange={() => {}}
102
+ ref={ref}
103
+ />,
104
+ );
105
+
106
+ // Assert
107
+ expect(ref?.current?.indeterminate).toBe(indeterminateValue);
108
+ },
109
+ );
110
+
111
+ test.each`
112
+ indeterminateValue | checkedValue
113
+ ${true} | ${null}
114
+ ${false} | ${true}
115
+ ${false} | ${false}
116
+ `(
117
+ "sets the indeterminate property to $indeterminateValue when checked is $checkedValue (innerRef)",
118
+ ({indeterminateValue, checkedValue}) => {
119
+ // Arrange
120
+ render(
121
+ <Checkbox
122
+ label="Some label"
123
+ description="Some description"
124
+ checked={checkedValue}
125
+ onChange={() => {}}
126
+ />,
127
+ );
128
+
129
+ // Act
130
+ const inputElement = screen.getByRole(
131
+ "checkbox",
132
+ ) as HTMLInputElement;
133
+
134
+ // Assert
135
+ expect(inputElement.indeterminate).toBe(indeterminateValue);
136
+ },
137
+ );
84
138
  });
@@ -39,84 +39,77 @@ const indeterminatePath: IconAsset = {
39
39
  /**
40
40
  * The internal stateless ☑️ Checkbox
41
41
  */
42
- export default class CheckboxCore extends React.Component<ChoiceCoreProps> {
43
- componentDidMount(): void {
44
- if (this.props.checked == null && this.inputRef.current != null) {
45
- this.inputRef.current.indeterminate = true;
42
+ const CheckboxCore = React.forwardRef(function CheckboxCore(
43
+ props: ChoiceCoreProps,
44
+ ref: React.ForwardedRef<HTMLInputElement>,
45
+ ) {
46
+ const {checked, disabled, error, groupName, id, testId, ...sharedProps} =
47
+ props;
48
+
49
+ const innerRef = React.useRef<HTMLInputElement>(null);
50
+
51
+ React.useEffect(() => {
52
+ // Keep the indeterminate state in sync with the checked prop
53
+ if (innerRef.current != null) {
54
+ innerRef.current.indeterminate = checked == null;
46
55
  }
47
- }
48
-
49
- componentDidUpdate(prevProps: Readonly<ChoiceCoreProps>): void {
50
- if (this.inputRef.current != null) {
51
- this.inputRef.current.indeterminate = this.props.checked == null;
52
- }
53
- }
54
-
55
- inputRef: React.RefObject<HTMLInputElement> = React.createRef();
56
+ }, [checked, innerRef]);
56
57
 
57
- handleChange: () => void = () => {
58
+ const handleChange: () => void = () => {
58
59
  // Empty because change is handled by ClickableBehavior
59
60
  return;
60
61
  };
61
62
 
62
- render(): React.ReactNode {
63
- const {
64
- checked,
65
- disabled,
66
- error,
67
- groupName,
68
- id,
69
- testId,
70
- ...sharedProps
71
- } = this.props;
72
-
73
- const stateStyles = _generateStyles(checked, error);
74
-
75
- const defaultStyle = [
76
- sharedStyles.inputReset,
77
- sharedStyles.default,
78
- !disabled && stateStyles.default,
79
- disabled && sharedStyles.disabled,
80
- ];
81
-
82
- const props = {
83
- "data-test-id": testId,
84
- } as const;
85
-
86
- const checkboxIcon = (
87
- <Icon
88
- color={disabled ? offBlack32 : white}
89
- icon={checked ? checkPath : indeterminatePath}
90
- size="small"
91
- style={sharedStyles.checkboxIcon}
63
+ const stateStyles = _generateStyles(checked, error);
64
+
65
+ const defaultStyle = [
66
+ sharedStyles.inputReset,
67
+ sharedStyles.default,
68
+ !disabled && stateStyles.default,
69
+ disabled && sharedStyles.disabled,
70
+ ];
71
+
72
+ const checkboxIcon = (
73
+ <Icon
74
+ color={disabled ? offBlack32 : white}
75
+ icon={checked ? checkPath : indeterminatePath}
76
+ size="small"
77
+ style={sharedStyles.checkboxIcon}
78
+ />
79
+ );
80
+
81
+ const ariaChecked = mapCheckedToAriaChecked(checked);
82
+
83
+ return (
84
+ <React.Fragment>
85
+ <StyledInput
86
+ {...sharedProps}
87
+ ref={(node) => {
88
+ // @ts-expect-error: current is not actually read-only
89
+ innerRef.current = node;
90
+ if (typeof ref === "function") {
91
+ ref(node);
92
+ } else if (ref != null) {
93
+ ref.current = node;
94
+ }
95
+ }}
96
+ type="checkbox"
97
+ aria-checked={ariaChecked}
98
+ aria-invalid={error}
99
+ checked={checked ?? undefined}
100
+ disabled={disabled}
101
+ id={id}
102
+ name={groupName}
103
+ // Need to specify because this is a controlled React form
104
+ // component, but we handle the click via ClickableBehavior
105
+ onChange={handleChange}
106
+ style={defaultStyle}
107
+ data-test-id={testId}
92
108
  />
93
- );
94
-
95
- const ariaChecked = mapCheckedToAriaChecked(checked);
96
-
97
- return (
98
- <React.Fragment>
99
- <StyledInput
100
- {...sharedProps}
101
- ref={this.inputRef}
102
- type="checkbox"
103
- aria-checked={ariaChecked}
104
- aria-invalid={error}
105
- checked={checked ?? undefined}
106
- disabled={disabled}
107
- id={id}
108
- name={groupName}
109
- // Need to specify because this is a controlled React form
110
- // component, but we handle the click via ClickableBehavior
111
- onChange={this.handleChange}
112
- style={defaultStyle}
113
- {...props}
114
- />
115
- {checked || checked == null ? checkboxIcon : <></>}
116
- </React.Fragment>
117
- );
118
- }
119
- }
109
+ {checked || checked == null ? checkboxIcon : <></>}
110
+ </React.Fragment>
111
+ );
112
+ });
120
113
 
121
114
  const size = 16;
122
115
 
@@ -237,3 +230,5 @@ const _generateStyles = (checked: Checked, error: boolean) => {
237
230
  styles[styleKey] = StyleSheet.create(newStyles);
238
231
  return styles[styleKey];
239
232
  };
233
+
234
+ export default CheckboxCore;
@@ -95,10 +95,26 @@ const StyledLegend = addStyle("legend");
95
95
  * </CheckboxGroup>
96
96
  * ```
97
97
  */
98
- export default class CheckboxGroup extends React.Component<CheckboxGroupProps> {
99
- handleChange(changedValue: string, originalCheckedState: boolean) {
100
- const {onChange, selectedValues} = this.props;
98
+ const CheckboxGroup = React.forwardRef(function CheckboxGroup(
99
+ props: CheckboxGroupProps,
100
+ ref: React.ForwardedRef<HTMLFieldSetElement>,
101
+ ) {
102
+ const {
103
+ children,
104
+ label,
105
+ description,
106
+ errorMessage,
107
+ groupName,
108
+ onChange,
109
+ selectedValues,
110
+ style,
111
+ testId,
112
+ } = props;
101
113
 
114
+ const handleChange = (
115
+ changedValue: string,
116
+ originalCheckedState: boolean,
117
+ ) => {
102
118
  if (originalCheckedState) {
103
119
  const index = selectedValues.indexOf(changedValue);
104
120
  const updatedSelection = [
@@ -109,63 +125,50 @@ export default class CheckboxGroup extends React.Component<CheckboxGroupProps> {
109
125
  } else {
110
126
  onChange([...selectedValues, changedValue]);
111
127
  }
112
- }
128
+ };
113
129
 
114
- render(): React.ReactNode {
115
- const {
116
- children,
117
- label,
118
- description,
119
- errorMessage,
120
- groupName,
121
- selectedValues,
122
- style,
123
- testId,
124
- } = this.props;
130
+ const allChildren = React.Children.toArray(children).filter(Boolean);
125
131
 
126
- const allChildren = React.Children.toArray(children).filter(Boolean);
132
+ return (
133
+ <StyledFieldset data-test-id={testId} style={styles.fieldset} ref={ref}>
134
+ {/* We have a View here because fieldset cannot be used with flexbox*/}
135
+ <View style={style}>
136
+ {label && (
137
+ <StyledLegend style={styles.legend}>
138
+ <LabelMedium>{label}</LabelMedium>
139
+ </StyledLegend>
140
+ )}
141
+ {description && (
142
+ <LabelSmall style={styles.description}>
143
+ {description}
144
+ </LabelSmall>
145
+ )}
146
+ {errorMessage && (
147
+ <LabelSmall style={styles.error}>{errorMessage}</LabelSmall>
148
+ )}
149
+ {(label || description || errorMessage) && (
150
+ <Strut size={Spacing.small_12} />
151
+ )}
127
152
 
128
- return (
129
- <StyledFieldset data-test-id={testId} style={styles.fieldset}>
130
- {/* We have a View here because fieldset cannot be used with flexbox*/}
131
- <View style={style}>
132
- {label && (
133
- <StyledLegend style={styles.legend}>
134
- <LabelMedium>{label}</LabelMedium>
135
- </StyledLegend>
136
- )}
137
- {description && (
138
- <LabelSmall style={styles.description}>
139
- {description}
140
- </LabelSmall>
141
- )}
142
- {errorMessage && (
143
- <LabelSmall style={styles.error}>
144
- {errorMessage}
145
- </LabelSmall>
146
- )}
147
- {(label || description || errorMessage) && (
148
- <Strut size={Spacing.small_12} />
149
- )}
153
+ {allChildren.map((child, index) => {
154
+ // @ts-expect-error [FEI-5019] - TS2339 - Property 'props' does not exist on type 'ReactChild | ReactFragment | ReactPortal'.
155
+ const {style, value} = child.props;
156
+ const checked = selectedValues.includes(value);
157
+ // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
158
+ return React.cloneElement(child, {
159
+ checked: checked,
160
+ error: !!errorMessage,
161
+ groupName: groupName,
162
+ id: `${groupName}-${value}`,
163
+ key: value,
164
+ onChange: () => handleChange(value, checked),
165
+ style: [index > 0 && styles.defaultLineGap, style],
166
+ variant: "checkbox",
167
+ });
168
+ })}
169
+ </View>
170
+ </StyledFieldset>
171
+ );
172
+ });
150
173
 
151
- {allChildren.map((child, index) => {
152
- // @ts-expect-error [FEI-5019] - TS2339 - Property 'props' does not exist on type 'ReactChild | ReactFragment | ReactPortal'.
153
- const {style, value} = child.props;
154
- const checked = selectedValues.includes(value);
155
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
156
- return React.cloneElement(child, {
157
- checked: checked,
158
- error: !!errorMessage,
159
- groupName: groupName,
160
- id: `${groupName}-${value}`,
161
- key: value,
162
- onChange: () => this.handleChange(value, checked),
163
- style: [index > 0 && styles.defaultLineGap, style],
164
- variant: "checkbox",
165
- });
166
- })}
167
- </View>
168
- </StyledFieldset>
169
- );
170
- }
171
- }
174
+ export default CheckboxGroup;
@@ -14,11 +14,11 @@ type ChoiceComponentProps = AriaProps & {
14
14
  /**
15
15
  * Whether this component is disabled
16
16
  */
17
- disabled: boolean;
17
+ disabled?: boolean;
18
18
  /**
19
19
  * Whether this component should show an error state
20
20
  */
21
- error: boolean;
21
+ error?: boolean;
22
22
  /**
23
23
  * Callback when this component is selected. The newCheckedState is the
24
24
  * new checked state of the component.
@@ -58,11 +58,6 @@ type ChoiceComponentProps = AriaProps & {
58
58
  groupName?: string;
59
59
  };
60
60
 
61
- type DefaultProps = {
62
- disabled: ChoiceComponentProps["disabled"];
63
- error: ChoiceComponentProps["error"];
64
- };
65
-
66
61
  /**
67
62
  * ☑️ A nicely styled checkbox for all your checking needs. Can optionally take
68
63
  * label and description props.
@@ -84,13 +79,21 @@ type DefaultProps = {
84
79
  * <Checkbox checked={checked} onChange={setChecked} />
85
80
  * ```
86
81
  */
87
- export default class Checkbox extends React.Component<ChoiceComponentProps> {
88
- static defaultProps: DefaultProps = {
89
- disabled: false,
90
- error: false,
91
- };
82
+ const Checkbox = React.forwardRef(function Checkbox(
83
+ props: ChoiceComponentProps,
84
+ ref: React.ForwardedRef<HTMLInputElement>,
85
+ ) {
86
+ const {disabled = false, error = false} = props;
87
+
88
+ return (
89
+ <ChoiceInternal
90
+ {...props}
91
+ variant="checkbox"
92
+ disabled={disabled}
93
+ error={error}
94
+ ref={ref}
95
+ />
96
+ );
97
+ });
92
98
 
93
- render(): React.ReactNode {
94
- return <ChoiceInternal variant="checkbox" {...this.props} />;
95
- }
96
- }
99
+ export default Checkbox;
@@ -14,9 +14,9 @@ type Props = AriaProps & {
14
14
  /** Whether this choice is checked. */
15
15
  checked: boolean | null | undefined;
16
16
  /** Whether this choice option is disabled. */
17
- disabled: boolean;
17
+ disabled?: boolean;
18
18
  /** Whether this choice is in error mode. */
19
- error: boolean;
19
+ error?: boolean;
20
20
  /** Returns the new checked state of the component. */
21
21
  onChange: (newCheckedState: boolean) => unknown;
22
22
  /**
@@ -48,11 +48,6 @@ type Props = AriaProps & {
48
48
  variant: "radio" | "checkbox";
49
49
  };
50
50
 
51
- type DefaultProps = {
52
- disabled: Props["disabled"];
53
- error: Props["error"];
54
- };
55
-
56
51
  /**
57
52
  * This is a potentially labeled 🔘 or ☑️ item. This is an internal component
58
53
  * that's wrapped by Checkbox and Radio. Choice is a wrapper for Checkbox and
@@ -60,14 +55,27 @@ type DefaultProps = {
60
55
  * and RadioGroup. This design allows for more explicit prop typing. For
61
56
  * example, we can make onChange a required prop on Checkbox but not on Choice
62
57
  * (because for Choice, that prop would be auto-populated by CheckboxGroup).
63
- */ export default class ChoiceInternal extends React.Component<Props> {
64
- static defaultProps: DefaultProps = {
65
- disabled: false,
66
- error: false,
67
- };
58
+ */ const ChoiceInternal = React.forwardRef(function ChoiceInternal(
59
+ props: Props,
60
+ ref: React.ForwardedRef<HTMLInputElement>,
61
+ ) {
62
+ const {
63
+ checked,
64
+ description,
65
+ disabled = false,
66
+ error = false,
67
+ id,
68
+ label,
69
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
70
+ onChange,
71
+ style,
72
+ className,
73
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
74
+ variant,
75
+ // ...coreProps
76
+ } = props;
68
77
 
69
- handleClick: () => void = () => {
70
- const {checked, onChange, variant} = this.props;
78
+ const handleClick: () => void = () => {
71
79
  // Radio buttons cannot be unchecked
72
80
  if (variant === "radio" && checked) {
73
81
  return;
@@ -75,15 +83,17 @@ type DefaultProps = {
75
83
  onChange(!checked);
76
84
  };
77
85
 
78
- getChoiceCoreComponent(): typeof RadioCore | typeof CheckboxCore {
79
- if (this.props.variant === "radio") {
86
+ const getChoiceCoreComponent = ():
87
+ | typeof RadioCore
88
+ | typeof CheckboxCore => {
89
+ if (variant === "radio") {
80
90
  return RadioCore;
81
91
  } else {
82
92
  return CheckboxCore;
83
93
  }
84
- }
85
- getLabel(id: string): React.ReactNode {
86
- const {disabled, label} = this.props;
94
+ };
95
+
96
+ const getLabel = (id: string): React.ReactNode => {
87
97
  return (
88
98
  <LabelMedium
89
99
  style={[styles.label, disabled && styles.disabledLabel]}
@@ -91,73 +101,64 @@ type DefaultProps = {
91
101
  <label htmlFor={id}>{label}</label>
92
102
  </LabelMedium>
93
103
  );
94
- }
95
- getDescription(id?: string): React.ReactNode {
96
- const {description} = this.props;
104
+ };
105
+
106
+ const getDescription = (id?: string): React.ReactNode => {
97
107
  return (
98
108
  <LabelSmall style={styles.description} id={id}>
99
109
  {description}
100
110
  </LabelSmall>
101
111
  );
102
- }
103
- render(): React.ReactNode {
104
- const {
105
- label,
106
- description,
107
- id,
108
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
109
- onChange,
110
- style,
111
- className,
112
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
113
- variant,
114
- ...coreProps
115
- } = this.props;
116
- const ChoiceCore = this.getChoiceCoreComponent();
112
+ };
117
113
 
118
- return (
119
- <UniqueIDProvider mockOnFirstRender={true} scope="choice">
120
- {(ids) => {
121
- // A choice element should always have a unique ID set
122
- // so that the label can always refer to this element.
123
- // This guarantees that clicking on the label will
124
- // always click on the choice as well. If an ID is
125
- // passed in as a prop, use that one. Otherwise,
126
- // create a unique ID using the provider.
127
- const uniqueId = id || ids.get("main");
114
+ const ChoiceCore = getChoiceCoreComponent();
128
115
 
129
- // Create a unique ID for the description section to be
130
- // used by this element's `aria-describedby`.
131
- const descriptionId = description
132
- ? ids.get("description")
133
- : undefined;
116
+ return (
117
+ <UniqueIDProvider mockOnFirstRender={true} scope="choice">
118
+ {(ids) => {
119
+ // A choice element should always have a unique ID set
120
+ // so that the label can always refer to this element.
121
+ // This guarantees that clicking on the label will
122
+ // always click on the choice as well. If an ID is
123
+ // passed in as a prop, use that one. Otherwise,
124
+ // create a unique ID using the provider.
125
+ const uniqueId = id || ids.get("main");
134
126
 
135
- return (
136
- <View style={style} className={className}>
137
- <View
138
- style={styles.wrapper}
139
- // We are resetting the tabIndex=0 from handlers
140
- // because the ChoiceCore component will receive
141
- // focus on basis of it being an input element.
142
- tabIndex={-1}
143
- >
144
- <ChoiceCore
145
- {...coreProps}
146
- id={uniqueId}
147
- aria-describedby={descriptionId}
148
- onClick={this.handleClick}
149
- />
150
- <Strut size={Spacing.xSmall_8} />
151
- {label && this.getLabel(uniqueId)}
152
- </View>
153
- {description && this.getDescription(descriptionId)}
127
+ // Create a unique ID for the description section to be
128
+ // used by this element's `aria-describedby`.
129
+ const descriptionId = description
130
+ ? ids.get("description")
131
+ : undefined;
132
+
133
+ return (
134
+ <View style={style} className={className}>
135
+ <View
136
+ style={styles.wrapper}
137
+ // We are resetting the tabIndex=0 from handlers
138
+ // because the ChoiceCore component will receive
139
+ // focus on basis of it being an input element.
140
+ tabIndex={-1}
141
+ >
142
+ <ChoiceCore
143
+ {...props}
144
+ id={uniqueId}
145
+ aria-describedby={descriptionId}
146
+ onClick={handleClick}
147
+ disabled={disabled}
148
+ error={error}
149
+ ref={ref}
150
+ />
151
+ <Strut size={Spacing.xSmall_8} />
152
+ {label && getLabel(uniqueId)}
154
153
  </View>
155
- );
156
- }}
157
- </UniqueIDProvider>
158
- );
159
- }
160
- }
154
+ {description && getDescription(descriptionId)}
155
+ </View>
156
+ );
157
+ }}
158
+ </UniqueIDProvider>
159
+ );
160
+ });
161
+
161
162
  const styles = StyleSheet.create({
162
163
  wrapper: {
163
164
  flexDirection: "row",
@@ -181,3 +182,5 @@ const styles = StyleSheet.create({
181
182
  color: Color.offBlack64,
182
183
  },
183
184
  });
185
+
186
+ export default ChoiceInternal;