@instructure/ui-checkbox 9.8.1 → 9.9.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +1 -1
  3. package/es/Checkbox/CheckboxFacade/props.js +2 -1
  4. package/es/Checkbox/CheckboxFacade/styles.js +3 -2
  5. package/es/Checkbox/CheckboxFacade/theme.js +1 -0
  6. package/es/Checkbox/ToggleFacade/props.js +2 -1
  7. package/es/Checkbox/ToggleFacade/styles.js +3 -2
  8. package/es/Checkbox/ToggleFacade/theme.js +1 -0
  9. package/es/Checkbox/index.js +50 -28
  10. package/es/Checkbox/props.js +2 -1
  11. package/es/Checkbox/styles.js +14 -1
  12. package/es/Checkbox/theme.js +43 -0
  13. package/lib/Checkbox/CheckboxFacade/props.js +2 -1
  14. package/lib/Checkbox/CheckboxFacade/styles.js +3 -2
  15. package/lib/Checkbox/CheckboxFacade/theme.js +1 -0
  16. package/lib/Checkbox/ToggleFacade/props.js +2 -1
  17. package/lib/Checkbox/ToggleFacade/styles.js +3 -2
  18. package/lib/Checkbox/ToggleFacade/theme.js +1 -0
  19. package/lib/Checkbox/index.js +50 -28
  20. package/lib/Checkbox/props.js +2 -1
  21. package/lib/Checkbox/styles.js +14 -1
  22. package/lib/Checkbox/theme.js +49 -0
  23. package/package.json +19 -19
  24. package/src/Checkbox/CheckboxFacade/props.ts +6 -1
  25. package/src/Checkbox/CheckboxFacade/styles.ts +4 -2
  26. package/src/Checkbox/CheckboxFacade/theme.ts +1 -0
  27. package/src/Checkbox/README.md +11 -0
  28. package/src/Checkbox/ToggleFacade/props.ts +6 -1
  29. package/src/Checkbox/ToggleFacade/styles.ts +6 -3
  30. package/src/Checkbox/ToggleFacade/theme.ts +1 -0
  31. package/src/Checkbox/index.tsx +62 -30
  32. package/src/Checkbox/props.ts +14 -3
  33. package/src/Checkbox/styles.ts +14 -1
  34. package/src/Checkbox/theme.ts +46 -0
  35. package/tsconfig.build.tsbuildinfo +1 -1
  36. package/types/Checkbox/CheckboxFacade/index.d.ts +2 -0
  37. package/types/Checkbox/CheckboxFacade/index.d.ts.map +1 -1
  38. package/types/Checkbox/CheckboxFacade/props.d.ts +4 -0
  39. package/types/Checkbox/CheckboxFacade/props.d.ts.map +1 -1
  40. package/types/Checkbox/CheckboxFacade/styles.d.ts.map +1 -1
  41. package/types/Checkbox/CheckboxFacade/theme.d.ts.map +1 -1
  42. package/types/Checkbox/ToggleFacade/index.d.ts +2 -0
  43. package/types/Checkbox/ToggleFacade/index.d.ts.map +1 -1
  44. package/types/Checkbox/ToggleFacade/props.d.ts +4 -0
  45. package/types/Checkbox/ToggleFacade/props.d.ts.map +1 -1
  46. package/types/Checkbox/ToggleFacade/styles.d.ts.map +1 -1
  47. package/types/Checkbox/ToggleFacade/theme.d.ts.map +1 -1
  48. package/types/Checkbox/index.d.ts +4 -0
  49. package/types/Checkbox/index.d.ts.map +1 -1
  50. package/types/Checkbox/props.d.ts +2 -1
  51. package/types/Checkbox/props.d.ts.map +1 -1
  52. package/types/Checkbox/styles.d.ts +1 -1
  53. package/types/Checkbox/styles.d.ts.map +1 -1
  54. package/types/Checkbox/theme.d.ts +9 -0
  55. package/types/Checkbox/theme.d.ts.map +1 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [9.9.0](https://github.com/instructure/instructure-ui/compare/v9.8.1...v9.9.0) (2024-11-12)
7
+
8
+
9
+ ### Features
10
+
11
+ * **many:** backport new error messages from v10 ([9003d19](https://github.com/instructure/instructure-ui/commit/9003d19cc66022dfdeecc2e2c8c8d9d2a7300e3f))
12
+
13
+
14
+
15
+
16
+
6
17
  ## [9.8.1](https://github.com/instructure/instructure-ui/compare/v9.8.0...v9.8.1) (2024-10-28)
7
18
 
8
19
  **Note:** Version bump only for package @instructure/ui-checkbox
package/README.md CHANGED
@@ -37,6 +37,6 @@ const MyCheckbox = () => {
37
37
  [npm]: https://img.shields.io/npm/v/@instructure/ui-checkbox.svg
38
38
  [npm-url]: https://npmjs.com/package/@instructure/ui-checkbox
39
39
  [license-badge]: https://img.shields.io/npm/l/instructure-ui.svg?style=flat-square
40
- [license]: https://github.com/instructure/instructure-ui/blob/master/LICENSE
40
+ [license]: https://github.com/instructure/instructure-ui/blob/master/LICENSE.md
41
41
  [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
42
42
  [coc]: https://github.com/instructure/instructure-ui/blob/master/CODE_OF_CONDUCT.md
@@ -29,7 +29,8 @@ const propTypes = {
29
29
  focused: PropTypes.bool,
30
30
  hovered: PropTypes.bool,
31
31
  size: PropTypes.oneOf(['small', 'medium', 'large']),
32
- indeterminate: PropTypes.bool
32
+ indeterminate: PropTypes.bool,
33
+ invalid: PropTypes.bool
33
34
  };
34
35
  const allowedProps = ['children', 'checked', 'focused', 'hovered', 'size', 'indeterminate'];
35
36
  export { propTypes, allowedProps };
@@ -37,7 +37,8 @@ const generateStyle = (componentTheme, props) => {
37
37
  checked = props.checked,
38
38
  focused = props.focused,
39
39
  hovered = props.hovered,
40
- indeterminate = props.indeterminate;
40
+ indeterminate = props.indeterminate,
41
+ invalid = props.invalid;
41
42
  const isChecked = checked || indeterminate;
42
43
  const sizeVariants = {
43
44
  small: {
@@ -88,7 +89,7 @@ const generateStyle = (componentTheme, props) => {
88
89
  boxSizing: 'border-box',
89
90
  flexShrink: 0,
90
91
  transition: 'all 0.2s',
91
- border: `${componentTheme.borderWidth} solid ${componentTheme.borderColor}`,
92
+ border: `${componentTheme.borderWidth} solid ${invalid ? componentTheme.errorBorderColor : componentTheme.borderColor}`,
92
93
  borderRadius: componentTheme.borderRadius,
93
94
  marginInlineEnd: componentTheme.marginRight,
94
95
  marginInlineStart: '0',
@@ -54,6 +54,7 @@ const generateComponentTheme = theme => {
54
54
  checkedBackground: colors === null || colors === void 0 ? void 0 : colors.backgroundDarkest,
55
55
  checkedBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderDarkest,
56
56
  hoverBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderDarkest,
57
+ errorBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderDanger,
57
58
  focusBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderBrand,
58
59
  focusBorderWidth: borders === null || borders === void 0 ? void 0 : borders.widthMedium,
59
60
  focusBorderStyle: borders === null || borders === void 0 ? void 0 : borders.style,
@@ -30,7 +30,8 @@ const propTypes = {
30
30
  readOnly: PropTypes.bool,
31
31
  focused: PropTypes.bool,
32
32
  size: PropTypes.oneOf(['small', 'medium', 'large']),
33
- labelPlacement: PropTypes.oneOf(['top', 'start', 'end'])
33
+ labelPlacement: PropTypes.oneOf(['top', 'start', 'end']),
34
+ invalid: PropTypes.bool
34
35
  };
35
36
  const allowedProps = ['children', 'checked', 'disabled', 'readOnly', 'focused', 'size', 'labelPlacement'];
36
37
  export { propTypes, allowedProps };
@@ -36,7 +36,8 @@ const generateStyle = (componentTheme, props) => {
36
36
  const size = props.size,
37
37
  checked = props.checked,
38
38
  focused = props.focused,
39
- labelPlacement = props.labelPlacement;
39
+ labelPlacement = props.labelPlacement,
40
+ invalid = props.invalid;
40
41
  const labelPlacementVariants = {
41
42
  start: {
42
43
  facade: {
@@ -93,7 +94,7 @@ const generateStyle = (componentTheme, props) => {
93
94
  position: 'relative',
94
95
  borderRadius: '3rem',
95
96
  verticalAlign: 'middle',
96
- boxShadow: `inset 0 0 0 ${componentTheme.borderWidth} ${componentTheme.borderColor}`,
97
+ boxShadow: `inset 0 0 0 ${componentTheme.borderWidth} ${invalid && !checked ? componentTheme.errorBorderColor : componentTheme.borderColor}`,
97
98
  height: componentTheme.toggleSize,
98
99
  width: `calc(${componentTheme.toggleSize} * 1.5)`,
99
100
  ...labelPlacementVariants[labelPlacement].facade,
@@ -47,6 +47,7 @@ const generateComponentTheme = theme => {
47
47
  };
48
48
  const componentVariables = {
49
49
  color: colors === null || colors === void 0 ? void 0 : colors.textLightest,
50
+ errorBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderDanger,
50
51
  background: colors === null || colors === void 0 ? void 0 : colors.backgroundLight,
51
52
  borderColor: colors === null || colors === void 0 ? void 0 : colors.borderMedium,
52
53
  borderWidth: borders === null || borders === void 0 ? void 0 : borders.widthSmall,
@@ -37,6 +37,7 @@ import { withStyle, jsx } from '@instructure/emotion';
37
37
  import { CheckboxFacade } from './CheckboxFacade';
38
38
  import { ToggleFacade } from './ToggleFacade';
39
39
  import generateStyle from './styles';
40
+ import generateComponentTheme from './theme';
40
41
  import { propTypes, allowedProps } from './props';
41
42
  /**
42
43
  ---
@@ -44,7 +45,7 @@ category: components
44
45
  tags: toggle, switch
45
46
  ---
46
47
  **/
47
- let Checkbox = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, null), _dec3 = testable(), _dec(_class = _dec2(_class = _dec3(_class = (_Checkbox = class Checkbox extends Component {
48
+ let Checkbox = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, generateComponentTheme), _dec3 = testable(), _dec(_class = _dec2(_class = _dec3(_class = (_Checkbox = class Checkbox extends Component {
48
49
  constructor(props) {
49
50
  super(props);
50
51
  this._defaultId = void 0;
@@ -132,6 +133,14 @@ let Checkbox = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, n
132
133
  get focused() {
133
134
  return isActiveElement(this._input);
134
135
  }
136
+ get isNewError() {
137
+ var _this$props$messages;
138
+ return !!((_this$props$messages = this.props.messages) !== null && _this$props$messages !== void 0 && _this$props$messages.find(m => m.type === 'newError'));
139
+ }
140
+ get invalid() {
141
+ var _this$props$messages2;
142
+ return !!((_this$props$messages2 = this.props.messages) !== null && _this$props$messages2 !== void 0 && _this$props$messages2.find(m => m.type === 'newError' || m.type === 'error'));
143
+ }
135
144
  focus() {
136
145
  this._input && this._input.focus();
137
146
  }
@@ -144,7 +153,9 @@ let Checkbox = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, n
144
153
  readOnly = _this$props4.readOnly,
145
154
  indeterminate = _this$props4.indeterminate,
146
155
  labelPlacement = _this$props4.labelPlacement,
147
- themeOverride = _this$props4.themeOverride;
156
+ themeOverride = _this$props4.themeOverride,
157
+ isRequired = _this$props4.isRequired,
158
+ styles = _this$props4.styles;
148
159
  const _this$state = this.state,
149
160
  hovered = _this$state.hovered,
150
161
  focused = _this$state.focused;
@@ -157,8 +168,11 @@ let Checkbox = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, n
157
168
  checked: this.checked,
158
169
  readOnly: readOnly,
159
170
  labelPlacement: labelPlacement,
160
- themeOverride: themeOverride
161
- }, label);
171
+ themeOverride: themeOverride,
172
+ invalid: this.invalid
173
+ }, label, isRequired && jsx("span", {
174
+ css: this.invalid ? styles === null || styles === void 0 ? void 0 : styles.requiredInvalid : {}
175
+ }, " *"));
162
176
  } else {
163
177
  return jsx(CheckboxFacade, {
164
178
  size: size,
@@ -166,42 +180,51 @@ let Checkbox = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, n
166
180
  focused: focused,
167
181
  checked: this.checked,
168
182
  indeterminate: indeterminate,
169
- themeOverride: themeOverride
170
- }, label);
183
+ themeOverride: themeOverride,
184
+ invalid: this.invalid
185
+ }, label, isRequired && jsx("span", {
186
+ css: this.invalid ? styles === null || styles === void 0 ? void 0 : styles.requiredInvalid : {}
187
+ }, " *"));
171
188
  }
172
189
  }
173
190
  renderMessages() {
174
- const messages = this.props.messages;
191
+ const _this$props5 = this.props,
192
+ messages = _this$props5.messages,
193
+ styles = _this$props5.styles,
194
+ variant = _this$props5.variant;
175
195
  return messages && messages.length > 0 ? jsx(View, {
176
196
  display: "block",
177
- margin: "small 0 0"
197
+ margin: "small 0 0",
198
+ css: this.isNewError && (variant === 'toggle' ? styles === null || styles === void 0 ? void 0 : styles.indentedToggleError : styles === null || styles === void 0 ? void 0 : styles.indentedError)
178
199
  }, jsx(FormFieldMessages, {
179
200
  messages: messages
180
201
  })) : null;
181
202
  }
182
203
  render() {
183
- const _this$props5 = this.props,
184
- disabled = _this$props5.disabled,
185
- readOnly = _this$props5.readOnly,
186
- value = _this$props5.value,
187
- onKeyDown = _this$props5.onKeyDown,
188
- onFocus = _this$props5.onFocus,
189
- onBlur = _this$props5.onBlur,
190
- onMouseOver = _this$props5.onMouseOver,
191
- onMouseOut = _this$props5.onMouseOut,
192
- indeterminate = _this$props5.indeterminate,
193
- variant = _this$props5.variant,
194
- styles = _this$props5.styles;
204
+ const _this$props6 = this.props,
205
+ disabled = _this$props6.disabled,
206
+ readOnly = _this$props6.readOnly,
207
+ value = _this$props6.value,
208
+ onKeyDown = _this$props6.onKeyDown,
209
+ onFocus = _this$props6.onFocus,
210
+ onBlur = _this$props6.onBlur,
211
+ onMouseOver = _this$props6.onMouseOver,
212
+ onMouseOut = _this$props6.onMouseOut,
213
+ indeterminate = _this$props6.indeterminate,
214
+ variant = _this$props6.variant,
215
+ styles = _this$props6.styles,
216
+ isRequired = _this$props6.isRequired;
195
217
  const props = omitProps(this.props, Checkbox.allowedProps);
196
218
  error(!(variant === 'toggle' && indeterminate), `[Checkbox] The \`toggle\` variant does not support the \`indeterminate\` property. Use the \`simple\` variant instead.`);
197
-
198
- /* eslint-disable jsx-a11y/mouse-events-have-key-events */
199
-
200
219
  return jsx("div", {
201
- css: styles === null || styles === void 0 ? void 0 : styles.checkbox,
202
- onMouseOver: createChainedFunction(onMouseOver, this.handleMouseOver),
220
+ css: styles === null || styles === void 0 ? void 0 : styles.checkbox
221
+ /* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events */,
222
+ onMouseOver: createChainedFunction(onMouseOver, this.handleMouseOver)
223
+ /* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events */,
203
224
  onMouseOut: createChainedFunction(onMouseOut, this.handleMouseOut),
204
225
  ref: this.handleRef
226
+ }, jsx("div", {
227
+ css: styles === null || styles === void 0 ? void 0 : styles.container
205
228
  }, jsx("input", Object.assign({}, props, {
206
229
  id: this.id,
207
230
  value: value,
@@ -209,6 +232,7 @@ let Checkbox = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, n
209
232
  ref: c => {
210
233
  this._input = c;
211
234
  },
235
+ required: isRequired,
212
236
  disabled: disabled || readOnly,
213
237
  "aria-checked": indeterminate ? 'mixed' : void 0,
214
238
  css: styles === null || styles === void 0 ? void 0 : styles.input,
@@ -220,9 +244,7 @@ let Checkbox = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, n
220
244
  })), jsx("label", {
221
245
  htmlFor: this.id,
222
246
  css: styles === null || styles === void 0 ? void 0 : styles.control
223
- }, this.renderFacade(), this.renderMessages()));
224
-
225
- /* eslint-enable jsx-a11y/mouse-events-have-key-events */
247
+ }, this.renderFacade(), this.renderMessages())));
226
248
  }
227
249
  }, _Checkbox.displayName = "Checkbox", _Checkbox.componentId = 'Checkbox', _Checkbox.propTypes = propTypes, _Checkbox.allowedProps = allowedProps, _Checkbox.defaultProps = {
228
250
  size: 'medium',
@@ -44,7 +44,8 @@ const propTypes = {
44
44
  size: PropTypes.oneOf(['small', 'medium', 'large']),
45
45
  variant: PropTypes.oneOf(['simple', 'toggle']),
46
46
  inline: PropTypes.bool,
47
- labelPlacement: PropTypes.oneOf(['top', 'start', 'end'])
47
+ labelPlacement: PropTypes.oneOf(['top', 'start', 'end']),
48
+ isRequired: PropTypes.bool
48
49
  };
49
50
  const allowedProps = ['label', 'id', 'value', 'messages', 'defaultChecked', 'checked', 'onChange', 'onKeyDown', 'onFocus', 'onBlur', 'onMouseOver', 'onMouseOut', 'disabled', 'readOnly', 'indeterminate', 'size', 'variant', 'inline', 'labelPlacement'];
50
51
  export { propTypes, allowedProps };
@@ -32,10 +32,19 @@
32
32
  * @param {Object} state the state of the component, the style is applied to
33
33
  * @return {Object} The final style object, which will be used in the component
34
34
  */
35
- const generateStyle = (_componentTheme, props) => {
35
+ const generateStyle = (componentTheme, props) => {
36
36
  const inline = props.inline,
37
37
  disabled = props.disabled;
38
38
  return {
39
+ requiredInvalid: {
40
+ color: componentTheme.requiredInvalidColor
41
+ },
42
+ indentedError: {
43
+ paddingLeft: componentTheme.checkErrorInsetWidth
44
+ },
45
+ indentedToggleError: {
46
+ paddingLeft: componentTheme.toggleErrorInsetWidth
47
+ },
39
48
  checkbox: {
40
49
  label: 'checkbox',
41
50
  position: 'relative',
@@ -51,6 +60,10 @@ const generateStyle = (_componentTheme, props) => {
51
60
  width: 'auto'
52
61
  })
53
62
  },
63
+ // this container is added to reduce the clickable area of the checkbox to the actual checkbox and label
64
+ container: {
65
+ width: 'fit-content'
66
+ },
54
67
  input: {
55
68
  label: 'checkbox__input',
56
69
  padding: 0,
@@ -0,0 +1,43 @@
1
+ /*
2
+ * The MIT License (MIT)
3
+ *
4
+ * Copyright (c) 2015 - present Instructure, Inc.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in all
14
+ * copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ * SOFTWARE.
23
+ */
24
+
25
+ /**
26
+ * Generates the theme object for the component from the theme and provided additional information
27
+ * @param {Object} theme The actual theme object.
28
+ * @return {Object} The final theme object with the overrides and component variables
29
+ */
30
+ const generateComponentTheme = theme => {
31
+ const colors = theme.colors,
32
+ forms = theme.forms,
33
+ spacing = theme.spacing;
34
+ const componentVariables = {
35
+ requiredInvalidColor: colors === null || colors === void 0 ? void 0 : colors.textDanger,
36
+ toggleErrorInsetWidth: `calc(${forms === null || forms === void 0 ? void 0 : forms.inputHeightSmall}*1.5 + ${spacing === null || spacing === void 0 ? void 0 : spacing.small})`,
37
+ checkErrorInsetWidth: `calc(1.25em + ${spacing === null || spacing === void 0 ? void 0 : spacing.xSmall})`
38
+ };
39
+ return {
40
+ ...componentVariables
41
+ };
42
+ };
43
+ export default generateComponentTheme;
@@ -36,6 +36,7 @@ const propTypes = exports.propTypes = {
36
36
  focused: _propTypes.default.bool,
37
37
  hovered: _propTypes.default.bool,
38
38
  size: _propTypes.default.oneOf(['small', 'medium', 'large']),
39
- indeterminate: _propTypes.default.bool
39
+ indeterminate: _propTypes.default.bool,
40
+ invalid: _propTypes.default.bool
40
41
  };
41
42
  const allowedProps = exports.allowedProps = ['children', 'checked', 'focused', 'hovered', 'size', 'indeterminate'];
@@ -43,7 +43,8 @@ const generateStyle = (componentTheme, props) => {
43
43
  checked = props.checked,
44
44
  focused = props.focused,
45
45
  hovered = props.hovered,
46
- indeterminate = props.indeterminate;
46
+ indeterminate = props.indeterminate,
47
+ invalid = props.invalid;
47
48
  const isChecked = checked || indeterminate;
48
49
  const sizeVariants = {
49
50
  small: {
@@ -94,7 +95,7 @@ const generateStyle = (componentTheme, props) => {
94
95
  boxSizing: 'border-box',
95
96
  flexShrink: 0,
96
97
  transition: 'all 0.2s',
97
- border: `${componentTheme.borderWidth} solid ${componentTheme.borderColor}`,
98
+ border: `${componentTheme.borderWidth} solid ${invalid ? componentTheme.errorBorderColor : componentTheme.borderColor}`,
98
99
  borderRadius: componentTheme.borderRadius,
99
100
  marginInlineEnd: componentTheme.marginRight,
100
101
  marginInlineStart: '0',
@@ -60,6 +60,7 @@ const generateComponentTheme = theme => {
60
60
  checkedBackground: colors === null || colors === void 0 ? void 0 : colors.backgroundDarkest,
61
61
  checkedBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderDarkest,
62
62
  hoverBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderDarkest,
63
+ errorBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderDanger,
63
64
  focusBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderBrand,
64
65
  focusBorderWidth: borders === null || borders === void 0 ? void 0 : borders.widthMedium,
65
66
  focusBorderStyle: borders === null || borders === void 0 ? void 0 : borders.style,
@@ -37,6 +37,7 @@ const propTypes = exports.propTypes = {
37
37
  readOnly: _propTypes.default.bool,
38
38
  focused: _propTypes.default.bool,
39
39
  size: _propTypes.default.oneOf(['small', 'medium', 'large']),
40
- labelPlacement: _propTypes.default.oneOf(['top', 'start', 'end'])
40
+ labelPlacement: _propTypes.default.oneOf(['top', 'start', 'end']),
41
+ invalid: _propTypes.default.bool
41
42
  };
42
43
  const allowedProps = exports.allowedProps = ['children', 'checked', 'disabled', 'readOnly', 'focused', 'size', 'labelPlacement'];
@@ -42,7 +42,8 @@ const generateStyle = (componentTheme, props) => {
42
42
  const size = props.size,
43
43
  checked = props.checked,
44
44
  focused = props.focused,
45
- labelPlacement = props.labelPlacement;
45
+ labelPlacement = props.labelPlacement,
46
+ invalid = props.invalid;
46
47
  const labelPlacementVariants = {
47
48
  start: {
48
49
  facade: {
@@ -99,7 +100,7 @@ const generateStyle = (componentTheme, props) => {
99
100
  position: 'relative',
100
101
  borderRadius: '3rem',
101
102
  verticalAlign: 'middle',
102
- boxShadow: `inset 0 0 0 ${componentTheme.borderWidth} ${componentTheme.borderColor}`,
103
+ boxShadow: `inset 0 0 0 ${componentTheme.borderWidth} ${invalid && !checked ? componentTheme.errorBorderColor : componentTheme.borderColor}`,
103
104
  height: componentTheme.toggleSize,
104
105
  width: `calc(${componentTheme.toggleSize} * 1.5)`,
105
106
  ...labelPlacementVariants[labelPlacement].facade,
@@ -53,6 +53,7 @@ const generateComponentTheme = theme => {
53
53
  };
54
54
  const componentVariables = {
55
55
  color: colors === null || colors === void 0 ? void 0 : colors.textLightest,
56
+ errorBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderDanger,
56
57
  background: colors === null || colors === void 0 ? void 0 : colors.backgroundLight,
57
58
  borderColor: colors === null || colors === void 0 ? void 0 : colors.borderMedium,
58
59
  borderWidth: borders === null || borders === void 0 ? void 0 : borders.widthSmall,
@@ -33,6 +33,7 @@ var _emotion = require("@instructure/emotion");
33
33
  var _CheckboxFacade = require("./CheckboxFacade");
34
34
  var _ToggleFacade = require("./ToggleFacade");
35
35
  var _styles = _interopRequireDefault(require("./styles"));
36
+ var _theme = _interopRequireDefault(require("./theme"));
36
37
  var _props = require("./props");
37
38
  var _dec, _dec2, _dec3, _class, _Checkbox;
38
39
  /*
@@ -65,7 +66,7 @@ category: components
65
66
  tags: toggle, switch
66
67
  ---
67
68
  **/
68
- let Checkbox = exports.Checkbox = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 = (0, _emotion.withStyle)(_styles.default, null), _dec3 = (0, _testable.testable)(), _dec(_class = _dec2(_class = _dec3(_class = (_Checkbox = class Checkbox extends _react.Component {
69
+ let Checkbox = exports.Checkbox = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 = (0, _emotion.withStyle)(_styles.default, _theme.default), _dec3 = (0, _testable.testable)(), _dec(_class = _dec2(_class = _dec3(_class = (_Checkbox = class Checkbox extends _react.Component {
69
70
  constructor(props) {
70
71
  super(props);
71
72
  this._defaultId = void 0;
@@ -153,6 +154,14 @@ let Checkbox = exports.Checkbox = (_dec = (0, _withDeterministicId.withDetermini
153
154
  get focused() {
154
155
  return (0, _isActiveElement.isActiveElement)(this._input);
155
156
  }
157
+ get isNewError() {
158
+ var _this$props$messages;
159
+ return !!((_this$props$messages = this.props.messages) !== null && _this$props$messages !== void 0 && _this$props$messages.find(m => m.type === 'newError'));
160
+ }
161
+ get invalid() {
162
+ var _this$props$messages2;
163
+ return !!((_this$props$messages2 = this.props.messages) !== null && _this$props$messages2 !== void 0 && _this$props$messages2.find(m => m.type === 'newError' || m.type === 'error'));
164
+ }
156
165
  focus() {
157
166
  this._input && this._input.focus();
158
167
  }
@@ -165,7 +174,9 @@ let Checkbox = exports.Checkbox = (_dec = (0, _withDeterministicId.withDetermini
165
174
  readOnly = _this$props4.readOnly,
166
175
  indeterminate = _this$props4.indeterminate,
167
176
  labelPlacement = _this$props4.labelPlacement,
168
- themeOverride = _this$props4.themeOverride;
177
+ themeOverride = _this$props4.themeOverride,
178
+ isRequired = _this$props4.isRequired,
179
+ styles = _this$props4.styles;
169
180
  const _this$state = this.state,
170
181
  hovered = _this$state.hovered,
171
182
  focused = _this$state.focused;
@@ -178,8 +189,11 @@ let Checkbox = exports.Checkbox = (_dec = (0, _withDeterministicId.withDetermini
178
189
  checked: this.checked,
179
190
  readOnly: readOnly,
180
191
  labelPlacement: labelPlacement,
181
- themeOverride: themeOverride
182
- }, label);
192
+ themeOverride: themeOverride,
193
+ invalid: this.invalid
194
+ }, label, isRequired && (0, _emotion.jsx)("span", {
195
+ css: this.invalid ? styles === null || styles === void 0 ? void 0 : styles.requiredInvalid : {}
196
+ }, " *"));
183
197
  } else {
184
198
  return (0, _emotion.jsx)(_CheckboxFacade.CheckboxFacade, {
185
199
  size: size,
@@ -187,42 +201,51 @@ let Checkbox = exports.Checkbox = (_dec = (0, _withDeterministicId.withDetermini
187
201
  focused: focused,
188
202
  checked: this.checked,
189
203
  indeterminate: indeterminate,
190
- themeOverride: themeOverride
191
- }, label);
204
+ themeOverride: themeOverride,
205
+ invalid: this.invalid
206
+ }, label, isRequired && (0, _emotion.jsx)("span", {
207
+ css: this.invalid ? styles === null || styles === void 0 ? void 0 : styles.requiredInvalid : {}
208
+ }, " *"));
192
209
  }
193
210
  }
194
211
  renderMessages() {
195
- const messages = this.props.messages;
212
+ const _this$props5 = this.props,
213
+ messages = _this$props5.messages,
214
+ styles = _this$props5.styles,
215
+ variant = _this$props5.variant;
196
216
  return messages && messages.length > 0 ? (0, _emotion.jsx)(_View.View, {
197
217
  display: "block",
198
- margin: "small 0 0"
218
+ margin: "small 0 0",
219
+ css: this.isNewError && (variant === 'toggle' ? styles === null || styles === void 0 ? void 0 : styles.indentedToggleError : styles === null || styles === void 0 ? void 0 : styles.indentedError)
199
220
  }, (0, _emotion.jsx)(_FormFieldMessages.FormFieldMessages, {
200
221
  messages: messages
201
222
  })) : null;
202
223
  }
203
224
  render() {
204
- const _this$props5 = this.props,
205
- disabled = _this$props5.disabled,
206
- readOnly = _this$props5.readOnly,
207
- value = _this$props5.value,
208
- onKeyDown = _this$props5.onKeyDown,
209
- onFocus = _this$props5.onFocus,
210
- onBlur = _this$props5.onBlur,
211
- onMouseOver = _this$props5.onMouseOver,
212
- onMouseOut = _this$props5.onMouseOut,
213
- indeterminate = _this$props5.indeterminate,
214
- variant = _this$props5.variant,
215
- styles = _this$props5.styles;
225
+ const _this$props6 = this.props,
226
+ disabled = _this$props6.disabled,
227
+ readOnly = _this$props6.readOnly,
228
+ value = _this$props6.value,
229
+ onKeyDown = _this$props6.onKeyDown,
230
+ onFocus = _this$props6.onFocus,
231
+ onBlur = _this$props6.onBlur,
232
+ onMouseOver = _this$props6.onMouseOver,
233
+ onMouseOut = _this$props6.onMouseOut,
234
+ indeterminate = _this$props6.indeterminate,
235
+ variant = _this$props6.variant,
236
+ styles = _this$props6.styles,
237
+ isRequired = _this$props6.isRequired;
216
238
  const props = (0, _omitProps.omitProps)(this.props, Checkbox.allowedProps);
217
239
  (0, _console.logError)(!(variant === 'toggle' && indeterminate), `[Checkbox] The \`toggle\` variant does not support the \`indeterminate\` property. Use the \`simple\` variant instead.`);
218
-
219
- /* eslint-disable jsx-a11y/mouse-events-have-key-events */
220
-
221
240
  return (0, _emotion.jsx)("div", {
222
- css: styles === null || styles === void 0 ? void 0 : styles.checkbox,
223
- onMouseOver: (0, _createChainedFunction.createChainedFunction)(onMouseOver, this.handleMouseOver),
241
+ css: styles === null || styles === void 0 ? void 0 : styles.checkbox
242
+ /* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events */,
243
+ onMouseOver: (0, _createChainedFunction.createChainedFunction)(onMouseOver, this.handleMouseOver)
244
+ /* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events */,
224
245
  onMouseOut: (0, _createChainedFunction.createChainedFunction)(onMouseOut, this.handleMouseOut),
225
246
  ref: this.handleRef
247
+ }, (0, _emotion.jsx)("div", {
248
+ css: styles === null || styles === void 0 ? void 0 : styles.container
226
249
  }, (0, _emotion.jsx)("input", Object.assign({}, props, {
227
250
  id: this.id,
228
251
  value: value,
@@ -230,6 +253,7 @@ let Checkbox = exports.Checkbox = (_dec = (0, _withDeterministicId.withDetermini
230
253
  ref: c => {
231
254
  this._input = c;
232
255
  },
256
+ required: isRequired,
233
257
  disabled: disabled || readOnly,
234
258
  "aria-checked": indeterminate ? 'mixed' : void 0,
235
259
  css: styles === null || styles === void 0 ? void 0 : styles.input,
@@ -241,9 +265,7 @@ let Checkbox = exports.Checkbox = (_dec = (0, _withDeterministicId.withDetermini
241
265
  })), (0, _emotion.jsx)("label", {
242
266
  htmlFor: this.id,
243
267
  css: styles === null || styles === void 0 ? void 0 : styles.control
244
- }, this.renderFacade(), this.renderMessages()));
245
-
246
- /* eslint-enable jsx-a11y/mouse-events-have-key-events */
268
+ }, this.renderFacade(), this.renderMessages())));
247
269
  }
248
270
  }, _Checkbox.displayName = "Checkbox", _Checkbox.componentId = 'Checkbox', _Checkbox.propTypes = _props.propTypes, _Checkbox.allowedProps = _props.allowedProps, _Checkbox.defaultProps = {
249
271
  size: 'medium',
@@ -51,6 +51,7 @@ const propTypes = exports.propTypes = {
51
51
  size: _propTypes.default.oneOf(['small', 'medium', 'large']),
52
52
  variant: _propTypes.default.oneOf(['simple', 'toggle']),
53
53
  inline: _propTypes.default.bool,
54
- labelPlacement: _propTypes.default.oneOf(['top', 'start', 'end'])
54
+ labelPlacement: _propTypes.default.oneOf(['top', 'start', 'end']),
55
+ isRequired: _propTypes.default.bool
55
56
  };
56
57
  const allowedProps = exports.allowedProps = ['label', 'id', 'value', 'messages', 'defaultChecked', 'checked', 'onChange', 'onKeyDown', 'onFocus', 'onBlur', 'onMouseOver', 'onMouseOut', 'disabled', 'readOnly', 'indeterminate', 'size', 'variant', 'inline', 'labelPlacement'];
@@ -38,10 +38,19 @@ exports.default = void 0;
38
38
  * @param {Object} state the state of the component, the style is applied to
39
39
  * @return {Object} The final style object, which will be used in the component
40
40
  */
41
- const generateStyle = (_componentTheme, props) => {
41
+ const generateStyle = (componentTheme, props) => {
42
42
  const inline = props.inline,
43
43
  disabled = props.disabled;
44
44
  return {
45
+ requiredInvalid: {
46
+ color: componentTheme.requiredInvalidColor
47
+ },
48
+ indentedError: {
49
+ paddingLeft: componentTheme.checkErrorInsetWidth
50
+ },
51
+ indentedToggleError: {
52
+ paddingLeft: componentTheme.toggleErrorInsetWidth
53
+ },
45
54
  checkbox: {
46
55
  label: 'checkbox',
47
56
  position: 'relative',
@@ -57,6 +66,10 @@ const generateStyle = (_componentTheme, props) => {
57
66
  width: 'auto'
58
67
  })
59
68
  },
69
+ // this container is added to reduce the clickable area of the checkbox to the actual checkbox and label
70
+ container: {
71
+ width: 'fit-content'
72
+ },
60
73
  input: {
61
74
  label: 'checkbox__input',
62
75
  padding: 0,