@instructure/ui-radio-input 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.
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-radio-input
@@ -1,4 +1,4 @@
1
- var _dec, _dec2, _class, _RadioInputGroup;
1
+ var _dec, _dec2, _dec3, _class, _RadioInputGroup;
2
2
  /*
3
3
  * The MIT License (MIT)
4
4
  *
@@ -23,18 +23,23 @@ var _dec, _dec2, _class, _RadioInputGroup;
23
23
  * SOFTWARE.
24
24
  */
25
25
 
26
+ /** @jsx jsx */
26
27
  import React, { Children, Component } from 'react';
27
28
  import { FormFieldGroup } from '@instructure/ui-form-field';
28
29
  import { testable } from '@instructure/ui-testable';
29
30
  import { matchComponentTypes, safeCloneElement, omitProps, pickProps, withDeterministicId } from '@instructure/ui-react-utils';
31
+ import { hasVisibleChildren } from '@instructure/ui-a11y-utils';
30
32
  import { RadioInput } from '../RadioInput';
33
+ import { jsx, withStyle } from '@instructure/emotion';
34
+ import generateStyle from './styles';
35
+ import generateComponentTheme from './theme';
31
36
  import { allowedProps, propTypes } from './props';
32
37
  /**
33
38
  ---
34
39
  category: components
35
40
  ---
36
41
  **/
37
- let RadioInputGroup = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class = _dec2(_class = (_RadioInputGroup = class RadioInputGroup extends Component {
42
+ let RadioInputGroup = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, generateComponentTheme), _dec3 = testable(), _dec(_class = _dec2(_class = _dec3(_class = (_RadioInputGroup = class RadioInputGroup extends Component {
38
43
  constructor(props) {
39
44
  super(props);
40
45
  this.ref = null;
@@ -67,6 +72,10 @@ let RadioInputGroup = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_c
67
72
  get hasMessages() {
68
73
  return !!this.props.messages && this.props.messages.length > 0;
69
74
  }
75
+ get invalid() {
76
+ var _this$props$messages;
77
+ return !!((_this$props$messages = this.props.messages) !== null && _this$props$messages !== void 0 && _this$props$messages.find(m => m.type === 'newError' || m.type === 'error'));
78
+ }
70
79
  get value() {
71
80
  return typeof this.props.value === 'undefined' ? this.state.value : this.props.value;
72
81
  }
@@ -110,11 +119,14 @@ let RadioInputGroup = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_c
110
119
  const _this$props2 = this.props,
111
120
  variant = _this$props2.variant,
112
121
  layout = _this$props2.layout,
113
- description = _this$props2.description;
114
- return /*#__PURE__*/React.createElement(FormFieldGroup, Object.assign({}, omitProps(this.props, RadioInputGroup.allowedProps), pickProps(this.props, FormFieldGroup.allowedProps), {
115
- description: description
116
- // TODO: split out toggle variant into its own component
117
- ,
122
+ description = _this$props2.description,
123
+ isRequired = _this$props2.isRequired,
124
+ styles = _this$props2.styles;
125
+ const descriptionWithRequired = hasVisibleChildren(description) ? jsx(React.Fragment, null, description, isRequired && description && jsx("span", {
126
+ css: this.invalid ? styles === null || styles === void 0 ? void 0 : styles.invalidAsterisk : {}
127
+ }, " *")) : description;
128
+ return jsx(FormFieldGroup, Object.assign({}, omitProps(this.props, RadioInputGroup.allowedProps), pickProps(this.props, FormFieldGroup.allowedProps), {
129
+ description: descriptionWithRequired,
118
130
  layout: layout === 'columns' && variant === 'toggle' ? 'stacked' : layout // toggles already display in cols
119
131
  ,
120
132
  vAlign: variant === 'toggle' ? 'middle' : 'top',
@@ -123,7 +135,8 @@ let RadioInputGroup = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_c
123
135
  ,
124
136
  startAt: variant === 'toggle' ? 'small' : void 0,
125
137
  messagesId: this._messagesId,
126
- elementRef: this.handleRef
138
+ elementRef: this.handleRef,
139
+ role: "radiogroup"
127
140
  }), this.renderChildren());
128
141
  }
129
142
  }, _RadioInputGroup.displayName = "RadioInputGroup", _RadioInputGroup.componentId = 'RadioInputGroup', _RadioInputGroup.allowedProps = allowedProps, _RadioInputGroup.propTypes = propTypes, _RadioInputGroup.defaultProps = {
@@ -132,6 +145,6 @@ let RadioInputGroup = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_c
132
145
  size: 'medium',
133
146
  layout: 'stacked',
134
147
  readOnly: false
135
- }, _RadioInputGroup)) || _class) || _class);
148
+ }, _RadioInputGroup)) || _class) || _class) || _class);
136
149
  export default RadioInputGroup;
137
150
  export { RadioInputGroup };
@@ -37,7 +37,8 @@ const propTypes = {
37
37
  children: PropTypes.node,
38
38
  variant: PropTypes.oneOf(['simple', 'toggle']),
39
39
  size: PropTypes.oneOf(['small', 'medium', 'large']),
40
- layout: PropTypes.oneOf(['stacked', 'columns', 'inline'])
40
+ layout: PropTypes.oneOf(['stacked', 'columns', 'inline']),
41
+ isRequired: PropTypes.bool
41
42
  };
42
43
  const allowedProps = ['name', 'description', 'defaultValue', 'value', 'onChange', 'disabled', 'readOnly', 'messages', 'children', 'variant', 'size', 'layout'];
43
44
  export { propTypes, allowedProps };
@@ -0,0 +1,41 @@
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
+ * ---
27
+ * private: true
28
+ * ---
29
+ * Generates the style object from the theme and provided additional information
30
+ * @param {Object} componentTheme The theme variable object.
31
+ * @return {Object} The final style object, which will be used in the component
32
+ */
33
+ const generateStyle = componentTheme => {
34
+ const invalidAsteriskColor = componentTheme.invalidAsteriskColor;
35
+ return {
36
+ invalidAsterisk: {
37
+ color: invalidAsteriskColor
38
+ }
39
+ };
40
+ };
41
+ export default generateStyle;
@@ -0,0 +1,39 @@
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
+ const componentVariables = {
33
+ invalidAsteriskColor: colors === null || colors === void 0 ? void 0 : colors.textDanger
34
+ };
35
+ return {
36
+ ...componentVariables
37
+ };
38
+ };
39
+ export default generateComponentTheme;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
5
  Object.defineProperty(exports, "__esModule", {
5
6
  value: true
6
7
  });
@@ -13,9 +14,13 @@ var _safeCloneElement = require("@instructure/ui-react-utils/lib/safeCloneElemen
13
14
  var _omitProps = require("@instructure/ui-react-utils/lib/omitProps.js");
14
15
  var _pickProps = require("@instructure/ui-react-utils/lib/pickProps.js");
15
16
  var _withDeterministicId = require("@instructure/ui-react-utils/lib/DeterministicIdContext/withDeterministicId.js");
17
+ var _hasVisibleChildren = require("@instructure/ui-a11y-utils/lib/hasVisibleChildren.js");
16
18
  var _RadioInput = require("../RadioInput");
19
+ var _emotion = require("@instructure/emotion");
20
+ var _styles = _interopRequireDefault(require("./styles"));
21
+ var _theme = _interopRequireDefault(require("./theme"));
17
22
  var _props = require("./props");
18
- var _dec, _dec2, _class, _RadioInputGroup;
23
+ var _dec, _dec2, _dec3, _class, _RadioInputGroup;
19
24
  /*
20
25
  * The MIT License (MIT)
21
26
  *
@@ -39,12 +44,13 @@ var _dec, _dec2, _class, _RadioInputGroup;
39
44
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40
45
  * SOFTWARE.
41
46
  */
47
+ /** @jsx jsx */
42
48
  /**
43
49
  ---
44
50
  category: components
45
51
  ---
46
52
  **/
47
- let RadioInputGroup = exports.RadioInputGroup = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 = (0, _testable.testable)(), _dec(_class = _dec2(_class = (_RadioInputGroup = class RadioInputGroup extends _react.Component {
53
+ let RadioInputGroup = exports.RadioInputGroup = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 = (0, _emotion.withStyle)(_styles.default, _theme.default), _dec3 = (0, _testable.testable)(), _dec(_class = _dec2(_class = _dec3(_class = (_RadioInputGroup = class RadioInputGroup extends _react.Component {
48
54
  constructor(props) {
49
55
  super(props);
50
56
  this.ref = null;
@@ -77,6 +83,10 @@ let RadioInputGroup = exports.RadioInputGroup = (_dec = (0, _withDeterministicId
77
83
  get hasMessages() {
78
84
  return !!this.props.messages && this.props.messages.length > 0;
79
85
  }
86
+ get invalid() {
87
+ var _this$props$messages;
88
+ return !!((_this$props$messages = this.props.messages) !== null && _this$props$messages !== void 0 && _this$props$messages.find(m => m.type === 'newError' || m.type === 'error'));
89
+ }
80
90
  get value() {
81
91
  return typeof this.props.value === 'undefined' ? this.state.value : this.props.value;
82
92
  }
@@ -120,11 +130,14 @@ let RadioInputGroup = exports.RadioInputGroup = (_dec = (0, _withDeterministicId
120
130
  const _this$props2 = this.props,
121
131
  variant = _this$props2.variant,
122
132
  layout = _this$props2.layout,
123
- description = _this$props2.description;
124
- return /*#__PURE__*/_react.default.createElement(_FormFieldGroup.FormFieldGroup, Object.assign({}, (0, _omitProps.omitProps)(this.props, RadioInputGroup.allowedProps), (0, _pickProps.pickProps)(this.props, _FormFieldGroup.FormFieldGroup.allowedProps), {
125
- description: description
126
- // TODO: split out toggle variant into its own component
127
- ,
133
+ description = _this$props2.description,
134
+ isRequired = _this$props2.isRequired,
135
+ styles = _this$props2.styles;
136
+ const descriptionWithRequired = (0, _hasVisibleChildren.hasVisibleChildren)(description) ? (0, _emotion.jsx)(_react.default.Fragment, null, description, isRequired && description && (0, _emotion.jsx)("span", {
137
+ css: this.invalid ? styles === null || styles === void 0 ? void 0 : styles.invalidAsterisk : {}
138
+ }, " *")) : description;
139
+ return (0, _emotion.jsx)(_FormFieldGroup.FormFieldGroup, Object.assign({}, (0, _omitProps.omitProps)(this.props, RadioInputGroup.allowedProps), (0, _pickProps.pickProps)(this.props, _FormFieldGroup.FormFieldGroup.allowedProps), {
140
+ description: descriptionWithRequired,
128
141
  layout: layout === 'columns' && variant === 'toggle' ? 'stacked' : layout // toggles already display in cols
129
142
  ,
130
143
  vAlign: variant === 'toggle' ? 'middle' : 'top',
@@ -133,7 +146,8 @@ let RadioInputGroup = exports.RadioInputGroup = (_dec = (0, _withDeterministicId
133
146
  ,
134
147
  startAt: variant === 'toggle' ? 'small' : void 0,
135
148
  messagesId: this._messagesId,
136
- elementRef: this.handleRef
149
+ elementRef: this.handleRef,
150
+ role: "radiogroup"
137
151
  }), this.renderChildren());
138
152
  }
139
153
  }, _RadioInputGroup.displayName = "RadioInputGroup", _RadioInputGroup.componentId = 'RadioInputGroup', _RadioInputGroup.allowedProps = _props.allowedProps, _RadioInputGroup.propTypes = _props.propTypes, _RadioInputGroup.defaultProps = {
@@ -142,5 +156,5 @@ let RadioInputGroup = exports.RadioInputGroup = (_dec = (0, _withDeterministicId
142
156
  size: 'medium',
143
157
  layout: 'stacked',
144
158
  readOnly: false
145
- }, _RadioInputGroup)) || _class) || _class);
159
+ }, _RadioInputGroup)) || _class) || _class) || _class);
146
160
  var _default = exports.default = RadioInputGroup;
@@ -44,6 +44,7 @@ const propTypes = exports.propTypes = {
44
44
  children: _propTypes.default.node,
45
45
  variant: _propTypes.default.oneOf(['simple', 'toggle']),
46
46
  size: _propTypes.default.oneOf(['small', 'medium', 'large']),
47
- layout: _propTypes.default.oneOf(['stacked', 'columns', 'inline'])
47
+ layout: _propTypes.default.oneOf(['stacked', 'columns', 'inline']),
48
+ isRequired: _propTypes.default.bool
48
49
  };
49
50
  const allowedProps = exports.allowedProps = ['name', 'description', 'defaultValue', 'value', 'onChange', 'disabled', 'readOnly', 'messages', 'children', 'variant', 'size', 'layout'];
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ /*
8
+ * The MIT License (MIT)
9
+ *
10
+ * Copyright (c) 2015 - present Instructure, Inc.
11
+ *
12
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ * of this software and associated documentation files (the "Software"), to deal
14
+ * in the Software without restriction, including without limitation the rights
15
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ * copies of the Software, and to permit persons to whom the Software is
17
+ * furnished to do so, subject to the following conditions:
18
+ *
19
+ * The above copyright notice and this permission notice shall be included in all
20
+ * copies or substantial portions of the Software.
21
+ *
22
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ * SOFTWARE.
29
+ */
30
+
31
+ /**
32
+ * ---
33
+ * private: true
34
+ * ---
35
+ * Generates the style object from the theme and provided additional information
36
+ * @param {Object} componentTheme The theme variable object.
37
+ * @return {Object} The final style object, which will be used in the component
38
+ */
39
+ const generateStyle = componentTheme => {
40
+ const invalidAsteriskColor = componentTheme.invalidAsteriskColor;
41
+ return {
42
+ invalidAsterisk: {
43
+ color: invalidAsteriskColor
44
+ }
45
+ };
46
+ };
47
+ var _default = exports.default = generateStyle;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ /*
8
+ * The MIT License (MIT)
9
+ *
10
+ * Copyright (c) 2015 - present Instructure, Inc.
11
+ *
12
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ * of this software and associated documentation files (the "Software"), to deal
14
+ * in the Software without restriction, including without limitation the rights
15
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ * copies of the Software, and to permit persons to whom the Software is
17
+ * furnished to do so, subject to the following conditions:
18
+ *
19
+ * The above copyright notice and this permission notice shall be included in all
20
+ * copies or substantial portions of the Software.
21
+ *
22
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ * SOFTWARE.
29
+ */
30
+
31
+ /**
32
+ * Generates the theme object for the component from the theme and provided additional information
33
+ * @param {Object} theme The actual theme object.
34
+ * @return {Object} The final theme object with the overrides and component variables
35
+ */
36
+ const generateComponentTheme = theme => {
37
+ const colors = theme.colors;
38
+ const componentVariables = {
39
+ invalidAsteriskColor: colors === null || colors === void 0 ? void 0 : colors.textDanger
40
+ };
41
+ return {
42
+ ...componentVariables
43
+ };
44
+ };
45
+ var _default = exports.default = generateComponentTheme;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/ui-radio-input",
3
- "version": "9.8.1",
3
+ "version": "9.9.0",
4
4
  "description": "A styled HTML input type='radio' element",
5
5
  "author": "Instructure, Inc. Engineering and Product Design",
6
6
  "module": "./es/index.js",
@@ -24,21 +24,22 @@
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
26
  "@babel/runtime": "^7.24.5",
27
- "@instructure/emotion": "9.8.1",
28
- "@instructure/shared-types": "9.8.1",
29
- "@instructure/ui-dom-utils": "9.8.1",
30
- "@instructure/ui-form-field": "9.8.1",
31
- "@instructure/ui-prop-types": "9.8.1",
32
- "@instructure/ui-react-utils": "9.8.1",
33
- "@instructure/ui-testable": "9.8.1",
27
+ "@instructure/emotion": "9.9.0",
28
+ "@instructure/shared-types": "9.9.0",
29
+ "@instructure/ui-a11y-utils": "9.9.0",
30
+ "@instructure/ui-dom-utils": "9.9.0",
31
+ "@instructure/ui-form-field": "9.9.0",
32
+ "@instructure/ui-prop-types": "9.9.0",
33
+ "@instructure/ui-react-utils": "9.9.0",
34
+ "@instructure/ui-testable": "9.9.0",
34
35
  "prop-types": "^15.8.1"
35
36
  },
36
37
  "devDependencies": {
37
- "@instructure/ui-babel-preset": "9.8.1",
38
- "@instructure/ui-color-utils": "9.8.1",
39
- "@instructure/ui-test-locator": "9.8.1",
40
- "@instructure/ui-test-utils": "9.8.1",
41
- "@instructure/ui-themes": "9.8.1"
38
+ "@instructure/ui-babel-preset": "9.9.0",
39
+ "@instructure/ui-color-utils": "9.9.0",
40
+ "@instructure/ui-test-locator": "9.9.0",
41
+ "@instructure/ui-test-utils": "9.9.0",
42
+ "@instructure/ui-themes": "9.9.0"
42
43
  },
43
44
  "peerDependencies": {
44
45
  "react": ">=16.8 <=18"
@@ -22,6 +22,7 @@
22
22
  * SOFTWARE.
23
23
  */
24
24
 
25
+ /** @jsx jsx */
25
26
  import React, { Children, Component } from 'react'
26
27
 
27
28
  import { FormFieldGroup } from '@instructure/ui-form-field'
@@ -33,10 +34,16 @@ import {
33
34
  pickProps,
34
35
  withDeterministicId
35
36
  } from '@instructure/ui-react-utils'
37
+ import { hasVisibleChildren } from '@instructure/ui-a11y-utils'
36
38
 
37
39
  import { RadioInput } from '../RadioInput'
38
40
  import type { RadioInputProps } from '../RadioInput/props'
39
41
 
42
+ import { jsx, withStyle } from '@instructure/emotion'
43
+
44
+ import generateStyle from './styles'
45
+ import generateComponentTheme from './theme'
46
+
40
47
  import type { RadioInputGroupProps, RadioInputGroupState } from './props'
41
48
  import { allowedProps, propTypes } from './props'
42
49
 
@@ -48,6 +55,7 @@ category: components
48
55
  ---
49
56
  **/
50
57
  @withDeterministicId()
58
+ @withStyle(generateStyle, generateComponentTheme)
51
59
  @testable()
52
60
  class RadioInputGroup extends Component<
53
61
  RadioInputGroupProps,
@@ -90,6 +98,12 @@ class RadioInputGroup extends Component<
90
98
  return !!this.props.messages && this.props.messages.length > 0
91
99
  }
92
100
 
101
+ get invalid() {
102
+ return !!this.props.messages?.find(
103
+ (m) => m.type === 'newError' || m.type === 'error'
104
+ )
105
+ }
106
+
93
107
  handleChange: RadioInputProps['onChange'] = (e) => {
94
108
  const value = e.target.value
95
109
 
@@ -145,14 +159,24 @@ class RadioInputGroup extends Component<
145
159
  }
146
160
 
147
161
  render() {
148
- const { variant, layout, description } = this.props
162
+ const { variant, layout, description, isRequired, styles } = this.props
163
+
164
+ const descriptionWithRequired = hasVisibleChildren(description) ? (
165
+ <React.Fragment>
166
+ {description}
167
+ {isRequired && description && (
168
+ <span css={this.invalid ? styles?.invalidAsterisk : {}}> *</span>
169
+ )}
170
+ </React.Fragment>
171
+ ) : (
172
+ description
173
+ )
149
174
 
150
175
  return (
151
176
  <FormFieldGroup
152
177
  {...omitProps(this.props, RadioInputGroup.allowedProps)}
153
178
  {...pickProps(this.props, FormFieldGroup.allowedProps)}
154
- description={description}
155
- // TODO: split out toggle variant into its own component
179
+ description={descriptionWithRequired}
156
180
  layout={
157
181
  layout === 'columns' && variant === 'toggle' ? 'stacked' : layout
158
182
  } // toggles already display in cols
@@ -162,6 +186,7 @@ class RadioInputGroup extends Component<
162
186
  startAt={variant === 'toggle' ? 'small' : undefined}
163
187
  messagesId={this._messagesId}
164
188
  elementRef={this.handleRef}
189
+ role="radiogroup"
165
190
  >
166
191
  {this.renderChildren()}
167
192
  </FormFieldGroup>
@@ -28,14 +28,23 @@ import PropTypes from 'prop-types'
28
28
  import { controllable } from '@instructure/ui-prop-types'
29
29
  import { FormPropTypes } from '@instructure/ui-form-field'
30
30
 
31
+ import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
31
32
  import type { FormMessage } from '@instructure/ui-form-field'
32
33
  import type {
33
34
  OtherHTMLAttributes,
34
- PropValidators
35
+ PropValidators,
36
+ RadioInputGroupTheme
35
37
  } from '@instructure/shared-types'
36
38
  import type { WithDeterministicIdProps } from '@instructure/ui-react-utils'
37
39
 
38
40
  type RadioInputGroupOwnProps = {
41
+ /**
42
+ * This prop sets the
43
+ * [same low level HTML attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio#defining_a_radio_group)
44
+ *
45
+ * **Must be unique across the DOM** otherwise groups will interfere with
46
+ * each other
47
+ */
39
48
  name: string
40
49
 
41
50
  description: React.ReactNode
@@ -48,7 +57,7 @@ type RadioInputGroupOwnProps = {
48
57
  /**
49
58
  * the selected value (must be accompanied by an `onChange` prop)
50
59
  */
51
- value?: string | number // TODO: controllable( PropTypes.oneOfType([PropTypes.string, PropTypes.number]) )
60
+ value?: string | number
52
61
 
53
62
  /**
54
63
  * when used with the `value` prop, the component will not control its own state
@@ -65,12 +74,12 @@ type RadioInputGroupOwnProps = {
65
74
  /**
66
75
  * Array of objects with shape: `{
67
76
  * text: ReactNode,
68
- * type: One of: ['error', 'hint', 'success', 'screenreader-only']
77
+ * type: One of: ['error', 'newError', 'hint', 'success', 'screenreader-only']
69
78
  * }`
70
79
  */
71
80
  messages?: FormMessage[]
72
81
 
73
- variant?: 'simple' | 'toggle' // TODO: split toggle out to its own component
82
+ variant?: 'simple' | 'toggle'
74
83
 
75
84
  size?: 'small' | 'medium' | 'large'
76
85
 
@@ -80,6 +89,11 @@ type RadioInputGroupOwnProps = {
80
89
  * any children (ones that aren't `RadioInput` are passed through)
81
90
  */
82
91
  children?: React.ReactNode
92
+
93
+ /**
94
+ * Setting this to `true` adds and asterisk after the description (group label). It does not cause any behavioural change.
95
+ */
96
+ isRequired?: boolean
83
97
  }
84
98
 
85
99
  type PropKeys = keyof RadioInputGroupOwnProps
@@ -87,12 +101,16 @@ type PropKeys = keyof RadioInputGroupOwnProps
87
101
  type AllowedPropKeys = Readonly<Array<PropKeys>>
88
102
 
89
103
  type RadioInputGroupProps = RadioInputGroupOwnProps &
90
- OtherHTMLAttributes<RadioInputGroupOwnProps> & WithDeterministicIdProps
104
+ WithStyleProps<RadioInputGroupTheme, RadioInputGroupStyle> &
105
+ OtherHTMLAttributes<RadioInputGroupOwnProps> &
106
+ WithDeterministicIdProps
91
107
 
92
108
  type RadioInputGroupState = {
93
109
  value?: string | number
94
110
  }
95
111
 
112
+ type RadioInputGroupStyle = ComponentStyle<'invalidAsterisk'>
113
+
96
114
  const propTypes: PropValidators<PropKeys> = {
97
115
  name: PropTypes.string.isRequired,
98
116
  description: PropTypes.node.isRequired,
@@ -107,7 +125,8 @@ const propTypes: PropValidators<PropKeys> = {
107
125
  children: PropTypes.node,
108
126
  variant: PropTypes.oneOf(['simple', 'toggle']),
109
127
  size: PropTypes.oneOf(['small', 'medium', 'large']),
110
- layout: PropTypes.oneOf(['stacked', 'columns', 'inline'])
128
+ layout: PropTypes.oneOf(['stacked', 'columns', 'inline']),
129
+ isRequired: PropTypes.bool
111
130
  }
112
131
 
113
132
  const allowedProps: AllowedPropKeys = [
@@ -125,5 +144,5 @@ const allowedProps: AllowedPropKeys = [
125
144
  'layout'
126
145
  ]
127
146
 
128
- export type { RadioInputGroupProps, RadioInputGroupState }
147
+ export type { RadioInputGroupProps, RadioInputGroupState, RadioInputGroupStyle }
129
148
  export { propTypes, allowedProps }
@@ -0,0 +1,48 @@
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
+ import type { RadioInputGroupTheme } from '@instructure/shared-types'
26
+ import type { RadioInputGroupStyle } from './props'
27
+
28
+ /**
29
+ * ---
30
+ * private: true
31
+ * ---
32
+ * Generates the style object from the theme and provided additional information
33
+ * @param {Object} componentTheme The theme variable object.
34
+ * @return {Object} The final style object, which will be used in the component
35
+ */
36
+ const generateStyle = (
37
+ componentTheme: RadioInputGroupTheme
38
+ ): RadioInputGroupStyle => {
39
+ const { invalidAsteriskColor } = componentTheme
40
+
41
+ return {
42
+ invalidAsterisk: {
43
+ color: invalidAsteriskColor
44
+ }
45
+ }
46
+ }
47
+
48
+ export default generateStyle