@khanacademy/wonder-blocks-form 4.0.9 → 4.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @khanacademy/wonder-blocks-form
2
2
 
3
+ ## 4.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ffe3758d: Add indeterminate state to checkbox
8
+
3
9
  ## 4.0.9
4
10
 
5
11
  ### Patch Changes
@@ -4,6 +4,9 @@ import type { ChoiceCoreProps } from "../util/types";
4
4
  * The internal stateless ☑️ Checkbox
5
5
  */
6
6
  export default class CheckboxCore extends React.Component<ChoiceCoreProps> {
7
+ componentDidMount(): void;
8
+ componentDidUpdate(prevProps: Readonly<ChoiceCoreProps>): void;
9
+ inputRef: React.RefObject<HTMLInputElement>;
7
10
  handleChange: () => void;
8
11
  render(): React.ReactNode;
9
12
  }
@@ -13,6 +13,9 @@ import type { ChoiceCoreProps } from "../util/types";
13
13
  declare export default class CheckboxCore
14
14
  extends React.Component<ChoiceCoreProps>
15
15
  {
16
+ componentDidMount(): void;
17
+ componentDidUpdate(prevProps: $ReadOnly<ChoiceCoreProps>): void;
18
+ inputRef: React.RefObject<HTMLInputElement>;
16
19
  handleChange: () => void;
17
20
  render(): React.Node;
18
21
  }
@@ -1,10 +1,11 @@
1
1
  import * as React from "react";
2
2
  import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
3
+ import type { Checked } from "../util/types";
3
4
  type ChoiceComponentProps = AriaProps & {
4
5
  /**
5
- * Whether this component is checked
6
+ * Whether this component is checked or indeterminate
6
7
  */
7
- checked: boolean;
8
+ checked: Checked;
8
9
  /**
9
10
  * Whether this component is disabled
10
11
  */
@@ -6,13 +6,14 @@
6
6
  */
7
7
  import * as React from "react";
8
8
  import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
9
+ import type { Checked } from "../util/types";
9
10
  declare type ChoiceComponentProps = {|
10
11
  ...AriaProps,
11
12
  ...{|
12
13
  /**
13
- * Whether this component is checked
14
+ * Whether this component is checked or indeterminate
14
15
  */
15
- checked: boolean,
16
+ checked: Checked,
16
17
 
17
18
  /**
18
19
  * Whether this component is disabled
@@ -4,7 +4,7 @@ import CheckboxCore from "./checkbox-core";
4
4
  import RadioCore from "./radio-core";
5
5
  type Props = AriaProps & {
6
6
  /** Whether this choice is checked. */
7
- checked: boolean;
7
+ checked: boolean | null | undefined;
8
8
  /** Whether this choice option is disabled. */
9
9
  disabled: boolean;
10
10
  /** Whether this choice is in error mode. */
@@ -40,7 +40,6 @@ type Props = AriaProps & {
40
40
  variant: "radio" | "checkbox";
41
41
  };
42
42
  type DefaultProps = {
43
- checked: Props["checked"];
44
43
  disabled: Props["disabled"];
45
44
  error: Props["error"];
46
45
  };
@@ -14,7 +14,7 @@ declare type Props = {|
14
14
  /**
15
15
  * Whether this choice is checked.
16
16
  */
17
- checked: boolean,
17
+ checked: boolean | null | void,
18
18
 
19
19
  /**
20
20
  * Whether this choice option is disabled.
@@ -74,7 +74,6 @@ declare type Props = {|
74
74
  |},
75
75
  |};
76
76
  declare type DefaultProps = {|
77
- checked: $PropertyType<Props, "checked">,
78
77
  disabled: $PropertyType<Props, "disabled">,
79
78
  error: $PropertyType<Props, "error">,
80
79
  |};
package/dist/es/index.js CHANGED
@@ -36,6 +36,16 @@ function _objectWithoutPropertiesLoose(source, excluded) {
36
36
  }
37
37
 
38
38
  const _excluded$4 = ["checked", "disabled", "error", "groupName", "id", "testId"];
39
+ function mapCheckedToAriaChecked(value) {
40
+ switch (value) {
41
+ case true:
42
+ return "true";
43
+ case false:
44
+ return "false";
45
+ default:
46
+ return "mixed";
47
+ }
48
+ }
39
49
  const {
40
50
  blue: blue$1,
41
51
  red: red$1,
@@ -46,16 +56,30 @@ const {
46
56
  offBlack50: offBlack50$1
47
57
  } = Color;
48
58
  const StyledInput$2 = addStyle("input");
49
- const checkboxCheck = {
59
+ const checkPath = {
50
60
  small: "M11.263 4.324a1 1 0 1 1 1.474 1.352l-5.5 6a1 1 0 0 1-1.505-.036l-2.5-3a1 1 0 1 1 1.536-1.28L6.536 9.48l4.727-5.157z"
51
61
  };
62
+ const indeterminatePath = {
63
+ small: "M3 8C3 7.44772 3.44772 7 4 7H12C12.5523 7 13 7.44772 13 8C13 8.55228 12.5523 9 12 9H4C3.44772 9 3 8.55228 3 8Z"
64
+ };
52
65
  class CheckboxCore extends React.Component {
53
66
  constructor(...args) {
54
67
  super(...args);
68
+ this.inputRef = React.createRef();
55
69
  this.handleChange = () => {
56
70
  return;
57
71
  };
58
72
  }
73
+ componentDidMount() {
74
+ if (this.props.checked == null && this.inputRef.current != null) {
75
+ this.inputRef.current.indeterminate = true;
76
+ }
77
+ }
78
+ componentDidUpdate(prevProps) {
79
+ if (this.inputRef.current != null) {
80
+ this.inputRef.current.indeterminate = this.props.checked == null;
81
+ }
82
+ }
59
83
  render() {
60
84
  const _this$props = this.props,
61
85
  {
@@ -72,21 +96,25 @@ class CheckboxCore extends React.Component {
72
96
  const props = {
73
97
  "data-test-id": testId
74
98
  };
99
+ const checkboxIcon = React.createElement(Icon, {
100
+ color: disabled ? offBlack32$1 : white$1,
101
+ icon: checked ? checkPath : indeterminatePath,
102
+ size: "small",
103
+ style: sharedStyles$1.checkboxIcon
104
+ });
105
+ const ariaChecked = mapCheckedToAriaChecked(checked);
75
106
  return React.createElement(React.Fragment, null, React.createElement(StyledInput$2, _extends({}, sharedProps, {
107
+ ref: this.inputRef,
76
108
  type: "checkbox",
109
+ "aria-checked": ariaChecked,
77
110
  "aria-invalid": error,
78
- checked: checked,
111
+ checked: checked != null ? checked : undefined,
79
112
  disabled: disabled,
80
113
  id: id,
81
114
  name: groupName,
82
115
  onChange: this.handleChange,
83
116
  style: defaultStyle
84
- }, props)), checked && React.createElement(Icon, {
85
- color: disabled ? offBlack32$1 : white$1,
86
- icon: checkboxCheck,
87
- size: "small",
88
- style: sharedStyles$1.checkIcon
89
- }));
117
+ }, props)), checked || checked == null ? checkboxIcon : React.createElement(React.Fragment, null));
90
118
  }
91
119
  }
92
120
  const size$1 = 16;
@@ -114,7 +142,7 @@ const sharedStyles$1 = StyleSheet.create({
114
142
  borderColor: offBlack16$1,
115
143
  borderWidth: 1
116
144
  },
117
- checkIcon: {
145
+ checkboxIcon: {
118
146
  position: "absolute",
119
147
  pointerEvents: "none"
120
148
  }
@@ -143,7 +171,7 @@ const _generateStyles$1 = (checked, error) => {
143
171
  }
144
172
  const palette = error ? colors$1.error : colors$1.default;
145
173
  let newStyles = {};
146
- if (checked) {
174
+ if (checked || checked == null) {
147
175
  newStyles = {
148
176
  default: {
149
177
  backgroundColor: palette.base,
@@ -224,7 +252,7 @@ class RadioCore extends React.Component {
224
252
  return React.createElement(React.Fragment, null, React.createElement(StyledInput$1, _extends({}, sharedProps, {
225
253
  type: "radio",
226
254
  "aria-invalid": error,
227
- checked: checked,
255
+ checked: checked != null ? checked : undefined,
228
256
  disabled: disabled,
229
257
  id: id,
230
258
  name: groupName,
@@ -416,7 +444,6 @@ class ChoiceInternal extends React.Component {
416
444
  }
417
445
  }
418
446
  ChoiceInternal.defaultProps = {
419
- checked: false,
420
447
  disabled: false,
421
448
  error: false
422
449
  };
package/dist/index.js CHANGED
@@ -65,6 +65,16 @@ function _objectWithoutPropertiesLoose(source, excluded) {
65
65
  }
66
66
 
67
67
  const _excluded$4 = ["checked", "disabled", "error", "groupName", "id", "testId"];
68
+ function mapCheckedToAriaChecked(value) {
69
+ switch (value) {
70
+ case true:
71
+ return "true";
72
+ case false:
73
+ return "false";
74
+ default:
75
+ return "mixed";
76
+ }
77
+ }
68
78
  const {
69
79
  blue: blue$1,
70
80
  red: red$1,
@@ -75,16 +85,30 @@ const {
75
85
  offBlack50: offBlack50$1
76
86
  } = Color__default["default"];
77
87
  const StyledInput$2 = wonderBlocksCore.addStyle("input");
78
- const checkboxCheck = {
88
+ const checkPath = {
79
89
  small: "M11.263 4.324a1 1 0 1 1 1.474 1.352l-5.5 6a1 1 0 0 1-1.505-.036l-2.5-3a1 1 0 1 1 1.536-1.28L6.536 9.48l4.727-5.157z"
80
90
  };
91
+ const indeterminatePath = {
92
+ small: "M3 8C3 7.44772 3.44772 7 4 7H12C12.5523 7 13 7.44772 13 8C13 8.55228 12.5523 9 12 9H4C3.44772 9 3 8.55228 3 8Z"
93
+ };
81
94
  class CheckboxCore extends React__namespace.Component {
82
95
  constructor(...args) {
83
96
  super(...args);
97
+ this.inputRef = React__namespace.createRef();
84
98
  this.handleChange = () => {
85
99
  return;
86
100
  };
87
101
  }
102
+ componentDidMount() {
103
+ if (this.props.checked == null && this.inputRef.current != null) {
104
+ this.inputRef.current.indeterminate = true;
105
+ }
106
+ }
107
+ componentDidUpdate(prevProps) {
108
+ if (this.inputRef.current != null) {
109
+ this.inputRef.current.indeterminate = this.props.checked == null;
110
+ }
111
+ }
88
112
  render() {
89
113
  const _this$props = this.props,
90
114
  {
@@ -101,21 +125,25 @@ class CheckboxCore extends React__namespace.Component {
101
125
  const props = {
102
126
  "data-test-id": testId
103
127
  };
128
+ const checkboxIcon = React__namespace.createElement(Icon__default["default"], {
129
+ color: disabled ? offBlack32$1 : white$1,
130
+ icon: checked ? checkPath : indeterminatePath,
131
+ size: "small",
132
+ style: sharedStyles$1.checkboxIcon
133
+ });
134
+ const ariaChecked = mapCheckedToAriaChecked(checked);
104
135
  return React__namespace.createElement(React__namespace.Fragment, null, React__namespace.createElement(StyledInput$2, _extends({}, sharedProps, {
136
+ ref: this.inputRef,
105
137
  type: "checkbox",
138
+ "aria-checked": ariaChecked,
106
139
  "aria-invalid": error,
107
- checked: checked,
140
+ checked: checked != null ? checked : undefined,
108
141
  disabled: disabled,
109
142
  id: id,
110
143
  name: groupName,
111
144
  onChange: this.handleChange,
112
145
  style: defaultStyle
113
- }, props)), checked && React__namespace.createElement(Icon__default["default"], {
114
- color: disabled ? offBlack32$1 : white$1,
115
- icon: checkboxCheck,
116
- size: "small",
117
- style: sharedStyles$1.checkIcon
118
- }));
146
+ }, props)), checked || checked == null ? checkboxIcon : React__namespace.createElement(React__namespace.Fragment, null));
119
147
  }
120
148
  }
121
149
  const size$1 = 16;
@@ -143,7 +171,7 @@ const sharedStyles$1 = aphrodite.StyleSheet.create({
143
171
  borderColor: offBlack16$1,
144
172
  borderWidth: 1
145
173
  },
146
- checkIcon: {
174
+ checkboxIcon: {
147
175
  position: "absolute",
148
176
  pointerEvents: "none"
149
177
  }
@@ -172,7 +200,7 @@ const _generateStyles$1 = (checked, error) => {
172
200
  }
173
201
  const palette = error ? colors$1.error : colors$1.default;
174
202
  let newStyles = {};
175
- if (checked) {
203
+ if (checked || checked == null) {
176
204
  newStyles = {
177
205
  default: {
178
206
  backgroundColor: palette.base,
@@ -253,7 +281,7 @@ class RadioCore extends React__namespace.Component {
253
281
  return React__namespace.createElement(React__namespace.Fragment, null, React__namespace.createElement(StyledInput$1, _extends({}, sharedProps, {
254
282
  type: "radio",
255
283
  "aria-invalid": error,
256
- checked: checked,
284
+ checked: checked != null ? checked : undefined,
257
285
  disabled: disabled,
258
286
  id: id,
259
287
  name: groupName,
@@ -445,7 +473,6 @@ class ChoiceInternal extends React__namespace.Component {
445
473
  }
446
474
  }
447
475
  ChoiceInternal.defaultProps = {
448
- checked: false,
449
476
  disabled: false,
450
477
  error: false
451
478
  };
@@ -1,8 +1,9 @@
1
1
  import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
2
2
  import Choice from "../components/choice";
3
+ export type Checked = boolean | null | undefined;
3
4
  export type ChoiceCoreProps = AriaProps & {
4
5
  /** Whether this component is checked */
5
- checked: boolean;
6
+ checked: Checked;
6
7
  /** Whether this component is disabled */
7
8
  disabled: boolean;
8
9
  /** Whether this component should show an error state */
@@ -6,13 +6,14 @@
6
6
  */
7
7
  import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
8
8
  import Choice from "../components/choice";
9
+ export type Checked = boolean | null | void;
9
10
  export type ChoiceCoreProps = {|
10
11
  ...AriaProps,
11
12
  ...{|
12
13
  /**
13
14
  * Whether this component is checked
14
15
  */
15
- checked: boolean,
16
+ checked: Checked,
16
17
 
17
18
  /**
18
19
  * Whether this component is disabled
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-form",
3
- "version": "4.0.9",
3
+ "version": "4.1.0",
4
4
  "design": "v1",
5
5
  "description": "Form components for Wonder Blocks.",
6
6
  "main": "dist/index.js",