@instructure/ui-number-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
 
@@ -30,6 +30,7 @@ import { FormField } from '@instructure/ui-form-field';
30
30
  import { IconArrowOpenDownLine, IconArrowOpenUpLine } from '@instructure/ui-icons';
31
31
  import { testable } from '@instructure/ui-testable';
32
32
  import { omitProps, pickProps, callRenderProp, getInteraction, withDeterministicId } from '@instructure/ui-react-utils';
33
+ import { hasVisibleChildren } from '@instructure/ui-a11y-utils';
33
34
  import { withStyle, jsx } from '@instructure/emotion';
34
35
  import generateStyle from './styles';
35
36
  import generateComponentTheme from './theme';
@@ -116,7 +117,7 @@ let NumberInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle
116
117
  return this._id;
117
118
  }
118
119
  get invalid() {
119
- return !!this.props.messages && this.props.messages.some(message => message.type === 'error');
120
+ return !!this.props.messages && this.props.messages.some(message => message.type === 'error' || message.type === 'newError');
120
121
  }
121
122
  get interaction() {
122
123
  return getInteraction({
@@ -177,10 +178,14 @@ let NumberInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle
177
178
  showArrows = _this$props4.showArrows,
178
179
  value = _this$props4.value,
179
180
  width = _this$props4.width,
180
- allowStringValue = _this$props4.allowStringValue;
181
+ styles = _this$props4.styles;
181
182
  const interaction = this.interaction;
183
+ const rawLabel = callRenderProp(renderLabel);
184
+ const label = hasVisibleChildren(rawLabel) ? jsx(React.Fragment, null, rawLabel, isRequired && jsx("span", {
185
+ css: this.invalid ? styles === null || styles === void 0 ? void 0 : styles.requiredInvalid : {}
186
+ }, " *")) : rawLabel;
182
187
  return jsx(FormField, Object.assign({}, pickProps(this.props, FormField.allowedProps), {
183
- label: callRenderProp(renderLabel),
188
+ label: label,
184
189
  inline: display === 'inline-block',
185
190
  id: this.id,
186
191
  elementRef: this.handleRef
@@ -195,7 +200,7 @@ let NumberInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle
195
200
  css: (_this$props$styles6 = this.props.styles) === null || _this$props$styles6 === void 0 ? void 0 : _this$props$styles6.input,
196
201
  "aria-invalid": this.invalid ? 'true' : void 0,
197
202
  id: this.id,
198
- type: allowStringValue ? 'text' : 'number',
203
+ type: "number",
199
204
  inputMode: this.props.inputMode,
200
205
  placeholder: placeholder,
201
206
  ref: this.handleInputRef,
@@ -218,8 +223,7 @@ let NumberInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle
218
223
  size: 'medium',
219
224
  display: 'block',
220
225
  textAlign: 'start',
221
- inputMode: 'numeric',
222
- allowStringValue: false
226
+ inputMode: 'numeric'
223
227
  }, _NumberInput)) || _class) || _class) || _class);
224
228
  export default NumberInput;
225
229
  export { NumberInput };
@@ -44,8 +44,7 @@ const propTypes = {
44
44
  onIncrement: PropTypes.func,
45
45
  onKeyDown: PropTypes.func,
46
46
  inputMode: PropTypes.oneOf(['numeric', 'decimal', 'tel']),
47
- textAlign: PropTypes.oneOf(['start', 'center']),
48
- allowStringValue: PropTypes.bool
47
+ textAlign: PropTypes.oneOf(['start', 'center'])
49
48
  };
50
- const allowedProps = ['renderLabel', 'id', 'interaction', 'messages', 'placeholder', 'isRequired', 'showArrows', 'size', 'value', 'width', 'display', 'inputRef', 'onFocus', 'onBlur', 'onChange', 'onDecrement', 'onIncrement', 'onKeyDown', 'inputMode', 'textAlign', 'allowStringValue'];
49
+ const allowedProps = ['renderLabel', 'id', 'interaction', 'messages', 'placeholder', 'isRequired', 'showArrows', 'size', 'value', 'width', 'display', 'inputRef', 'onFocus', 'onBlur', 'onChange', 'onDecrement', 'onIncrement', 'onKeyDown', 'inputMode', 'textAlign'];
51
50
  export { propTypes, allowedProps };
@@ -77,6 +77,9 @@ const generateStyle = (componentTheme, props, state) => {
77
77
  }
78
78
  };
79
79
  return {
80
+ requiredInvalid: {
81
+ color: componentTheme.requiredInvalidColor
82
+ },
80
83
  numberInput: {
81
84
  label: 'numberInput'
82
85
  },
@@ -50,6 +50,7 @@ const generateComponentTheme = theme => {
50
50
  borderRadius: borders === null || borders === void 0 ? void 0 : borders.radiusMedium,
51
51
  color: colors === null || colors === void 0 ? void 0 : colors.textDarkest,
52
52
  background: colors === null || colors === void 0 ? void 0 : colors.backgroundLightest,
53
+ requiredInvalidColor: colors === null || colors === void 0 ? void 0 : colors.textDanger,
53
54
  padding: `0 ${spacing === null || spacing === void 0 ? void 0 : spacing.small}`,
54
55
  arrowsContainerWidth: '2rem',
55
56
  arrowsColor: colors === null || colors === void 0 ? void 0 : colors.textDarkest,
@@ -17,6 +17,7 @@ var _pickProps = require("@instructure/ui-react-utils/lib/pickProps.js");
17
17
  var _callRenderProp = require("@instructure/ui-react-utils/lib/callRenderProp.js");
18
18
  var _getInteraction = require("@instructure/ui-react-utils/lib/getInteraction.js");
19
19
  var _withDeterministicId = require("@instructure/ui-react-utils/lib/DeterministicIdContext/withDeterministicId.js");
20
+ var _hasVisibleChildren = require("@instructure/ui-a11y-utils/lib/hasVisibleChildren.js");
20
21
  var _emotion = require("@instructure/emotion");
21
22
  var _styles = _interopRequireDefault(require("./styles"));
22
23
  var _theme = _interopRequireDefault(require("./theme"));
@@ -128,7 +129,7 @@ let NumberInput = exports.NumberInput = (_dec = (0, _withDeterministicId.withDet
128
129
  return this._id;
129
130
  }
130
131
  get invalid() {
131
- return !!this.props.messages && this.props.messages.some(message => message.type === 'error');
132
+ return !!this.props.messages && this.props.messages.some(message => message.type === 'error' || message.type === 'newError');
132
133
  }
133
134
  get interaction() {
134
135
  return (0, _getInteraction.getInteraction)({
@@ -189,10 +190,14 @@ let NumberInput = exports.NumberInput = (_dec = (0, _withDeterministicId.withDet
189
190
  showArrows = _this$props4.showArrows,
190
191
  value = _this$props4.value,
191
192
  width = _this$props4.width,
192
- allowStringValue = _this$props4.allowStringValue;
193
+ styles = _this$props4.styles;
193
194
  const interaction = this.interaction;
195
+ const rawLabel = (0, _callRenderProp.callRenderProp)(renderLabel);
196
+ const label = (0, _hasVisibleChildren.hasVisibleChildren)(rawLabel) ? (0, _emotion.jsx)(_react.default.Fragment, null, rawLabel, isRequired && (0, _emotion.jsx)("span", {
197
+ css: this.invalid ? styles === null || styles === void 0 ? void 0 : styles.requiredInvalid : {}
198
+ }, " *")) : rawLabel;
194
199
  return (0, _emotion.jsx)(_FormField.FormField, Object.assign({}, (0, _pickProps.pickProps)(this.props, _FormField.FormField.allowedProps), {
195
- label: (0, _callRenderProp.callRenderProp)(renderLabel),
200
+ label: label,
196
201
  inline: display === 'inline-block',
197
202
  id: this.id,
198
203
  elementRef: this.handleRef
@@ -207,7 +212,7 @@ let NumberInput = exports.NumberInput = (_dec = (0, _withDeterministicId.withDet
207
212
  css: (_this$props$styles6 = this.props.styles) === null || _this$props$styles6 === void 0 ? void 0 : _this$props$styles6.input,
208
213
  "aria-invalid": this.invalid ? 'true' : void 0,
209
214
  id: this.id,
210
- type: allowStringValue ? 'text' : 'number',
215
+ type: "number",
211
216
  inputMode: this.props.inputMode,
212
217
  placeholder: placeholder,
213
218
  ref: this.handleInputRef,
@@ -230,7 +235,6 @@ let NumberInput = exports.NumberInput = (_dec = (0, _withDeterministicId.withDet
230
235
  size: 'medium',
231
236
  display: 'block',
232
237
  textAlign: 'start',
233
- inputMode: 'numeric',
234
- allowStringValue: false
238
+ inputMode: 'numeric'
235
239
  }, _NumberInput)) || _class) || _class) || _class);
236
240
  var _default = exports.default = NumberInput;
@@ -51,7 +51,6 @@ const propTypes = exports.propTypes = {
51
51
  onIncrement: _propTypes.default.func,
52
52
  onKeyDown: _propTypes.default.func,
53
53
  inputMode: _propTypes.default.oneOf(['numeric', 'decimal', 'tel']),
54
- textAlign: _propTypes.default.oneOf(['start', 'center']),
55
- allowStringValue: _propTypes.default.bool
54
+ textAlign: _propTypes.default.oneOf(['start', 'center'])
56
55
  };
57
- const allowedProps = exports.allowedProps = ['renderLabel', 'id', 'interaction', 'messages', 'placeholder', 'isRequired', 'showArrows', 'size', 'value', 'width', 'display', 'inputRef', 'onFocus', 'onBlur', 'onChange', 'onDecrement', 'onIncrement', 'onKeyDown', 'inputMode', 'textAlign', 'allowStringValue'];
56
+ const allowedProps = exports.allowedProps = ['renderLabel', 'id', 'interaction', 'messages', 'placeholder', 'isRequired', 'showArrows', 'size', 'value', 'width', 'display', 'inputRef', 'onFocus', 'onBlur', 'onChange', 'onDecrement', 'onIncrement', 'onKeyDown', 'inputMode', 'textAlign'];
@@ -83,6 +83,9 @@ const generateStyle = (componentTheme, props, state) => {
83
83
  }
84
84
  };
85
85
  return {
86
+ requiredInvalid: {
87
+ color: componentTheme.requiredInvalidColor
88
+ },
86
89
  numberInput: {
87
90
  label: 'numberInput'
88
91
  },
@@ -56,6 +56,7 @@ const generateComponentTheme = theme => {
56
56
  borderRadius: borders === null || borders === void 0 ? void 0 : borders.radiusMedium,
57
57
  color: colors === null || colors === void 0 ? void 0 : colors.textDarkest,
58
58
  background: colors === null || colors === void 0 ? void 0 : colors.backgroundLightest,
59
+ requiredInvalidColor: colors === null || colors === void 0 ? void 0 : colors.textDanger,
59
60
  padding: `0 ${spacing === null || spacing === void 0 ? void 0 : spacing.small}`,
60
61
  arrowsContainerWidth: '2rem',
61
62
  arrowsColor: colors === null || colors === void 0 ? void 0 : colors.textDarkest,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/ui-number-input",
3
- "version": "9.8.1",
3
+ "version": "9.9.0",
4
4
  "description": "A UI component library made by Instructure Inc.",
5
5
  "author": "Instructure, Inc. Engineering and Product Design",
6
6
  "homepage": "https://instructure.github.io/instructure-ui/",
@@ -23,25 +23,26 @@
23
23
  "ts:check": "tsc -p tsconfig.build.json --noEmit --emitDeclarationOnly false"
24
24
  },
25
25
  "devDependencies": {
26
- "@instructure/ui-axe-check": "9.8.1",
27
- "@instructure/ui-babel-preset": "9.8.1",
28
- "@instructure/ui-scripts": "9.8.1",
29
- "@instructure/ui-test-locator": "9.8.1",
30
- "@instructure/ui-test-utils": "9.8.1",
31
- "@instructure/ui-themes": "9.8.1",
26
+ "@instructure/ui-axe-check": "9.9.0",
27
+ "@instructure/ui-babel-preset": "9.9.0",
28
+ "@instructure/ui-scripts": "9.9.0",
29
+ "@instructure/ui-test-locator": "9.9.0",
30
+ "@instructure/ui-test-utils": "9.9.0",
31
+ "@instructure/ui-themes": "9.9.0",
32
32
  "@testing-library/react": "^15.0.7",
33
33
  "vitest": "^2.0.2"
34
34
  },
35
35
  "dependencies": {
36
36
  "@babel/runtime": "^7.24.5",
37
- "@instructure/emotion": "9.8.1",
38
- "@instructure/shared-types": "9.8.1",
39
- "@instructure/ui-form-field": "9.8.1",
40
- "@instructure/ui-icons": "9.8.1",
41
- "@instructure/ui-react-utils": "9.8.1",
42
- "@instructure/ui-testable": "9.8.1",
43
- "@instructure/ui-utils": "9.8.1",
44
- "@instructure/uid": "9.8.1",
37
+ "@instructure/emotion": "9.9.0",
38
+ "@instructure/shared-types": "9.9.0",
39
+ "@instructure/ui-a11y-utils": "9.9.0",
40
+ "@instructure/ui-form-field": "9.9.0",
41
+ "@instructure/ui-icons": "9.9.0",
42
+ "@instructure/ui-react-utils": "9.9.0",
43
+ "@instructure/ui-testable": "9.9.0",
44
+ "@instructure/ui-utils": "9.9.0",
45
+ "@instructure/uid": "9.9.0",
45
46
  "keycode": "^2",
46
47
  "prop-types": "^15.8.1"
47
48
  },
@@ -39,6 +39,7 @@ import {
39
39
  getInteraction,
40
40
  withDeterministicId
41
41
  } from '@instructure/ui-react-utils'
42
+ import { hasVisibleChildren } from '@instructure/ui-a11y-utils'
42
43
 
43
44
  import { withStyle, jsx } from '@instructure/emotion'
44
45
 
@@ -74,8 +75,7 @@ class NumberInput extends Component<NumberInputProps, NumberInputState> {
74
75
  size: 'medium',
75
76
  display: 'block',
76
77
  textAlign: 'start',
77
- inputMode: 'numeric',
78
- allowStringValue: false
78
+ inputMode: 'numeric'
79
79
  }
80
80
 
81
81
  state: NumberInputState = { hasFocus: false }
@@ -102,7 +102,9 @@ class NumberInput extends Component<NumberInputProps, NumberInputState> {
102
102
  get invalid() {
103
103
  return (
104
104
  !!this.props.messages &&
105
- this.props.messages.some((message) => message.type === 'error')
105
+ this.props.messages.some(
106
+ (message) => message.type === 'error' || message.type === 'newError'
107
+ )
106
108
  )
107
109
  }
108
110
 
@@ -234,15 +236,27 @@ class NumberInput extends Component<NumberInputProps, NumberInputState> {
234
236
  showArrows,
235
237
  value,
236
238
  width,
237
- allowStringValue
239
+ styles
238
240
  } = this.props
239
241
 
240
242
  const { interaction } = this
241
243
 
244
+ const rawLabel = callRenderProp(renderLabel)
245
+ const label = hasVisibleChildren(rawLabel) ? (
246
+ <React.Fragment>
247
+ {rawLabel}
248
+ {isRequired && (
249
+ <span css={this.invalid ? styles?.requiredInvalid : {}}> *</span>
250
+ )}
251
+ </React.Fragment>
252
+ ) : (
253
+ rawLabel
254
+ )
255
+
242
256
  return (
243
257
  <FormField
244
258
  {...pickProps(this.props, FormField.allowedProps)}
245
- label={callRenderProp(renderLabel)}
259
+ label={label}
246
260
  inline={display === 'inline-block'}
247
261
  id={this.id}
248
262
  elementRef={this.handleRef}
@@ -260,7 +274,7 @@ class NumberInput extends Component<NumberInputProps, NumberInputState> {
260
274
  css={this.props.styles?.input}
261
275
  aria-invalid={this.invalid ? 'true' : undefined}
262
276
  id={this.id}
263
- type={allowStringValue ? 'text' : 'number'}
277
+ type="number"
264
278
  inputMode={this.props.inputMode}
265
279
  placeholder={placeholder}
266
280
  ref={this.handleInputRef}
@@ -64,7 +64,7 @@ type NumberInputOwnProps = {
64
64
  /**
65
65
  * Array of objects with shape: `{
66
66
  * text: ReactNode,
67
- * type: One of: ['error', 'hint', 'success', 'screenreader-only']
67
+ * type: One of: ['newError', 'error', 'hint', 'success', 'screenreader-only']
68
68
  * }`
69
69
  */
70
70
  messages?: FormMessage[]
@@ -161,11 +161,6 @@ type NumberInputOwnProps = {
161
161
  * The text alignment of the input.
162
162
  */
163
163
  textAlign?: 'start' | 'center'
164
-
165
- /**
166
- * sets the input type to string and allows string as value
167
- */
168
- allowStringValue?: boolean
169
164
  }
170
165
 
171
166
  type NumberInputState = {
@@ -202,6 +197,7 @@ type NumberInputStyle = ComponentStyle<
202
197
  | 'inputWidth'
203
198
  | 'inputContainer'
204
199
  | 'input'
200
+ | 'requiredInvalid'
205
201
  >
206
202
 
207
203
  const propTypes: PropValidators<PropKeys> = {
@@ -224,8 +220,7 @@ const propTypes: PropValidators<PropKeys> = {
224
220
  onIncrement: PropTypes.func,
225
221
  onKeyDown: PropTypes.func,
226
222
  inputMode: PropTypes.oneOf(['numeric', 'decimal', 'tel']),
227
- textAlign: PropTypes.oneOf(['start', 'center']),
228
- allowStringValue: PropTypes.bool
223
+ textAlign: PropTypes.oneOf(['start', 'center'])
229
224
  }
230
225
 
231
226
  const allowedProps: AllowedPropKeys = [
@@ -248,8 +243,7 @@ const allowedProps: AllowedPropKeys = [
248
243
  'onIncrement',
249
244
  'onKeyDown',
250
245
  'inputMode',
251
- 'textAlign',
252
- 'allowStringValue'
246
+ 'textAlign'
253
247
  ]
254
248
 
255
249
  export type {
@@ -98,6 +98,9 @@ const generateStyle = (
98
98
  }
99
99
 
100
100
  return {
101
+ requiredInvalid: {
102
+ color: componentTheme.requiredInvalidColor
103
+ },
101
104
  numberInput: {
102
105
  label: 'numberInput'
103
106
  },
@@ -53,6 +53,8 @@ const generateComponentTheme = (theme: Theme): NumberInputTheme => {
53
53
  color: colors?.textDarkest,
54
54
  background: colors?.backgroundLightest,
55
55
 
56
+ requiredInvalidColor: colors?.textDanger,
57
+
56
58
  padding: `0 ${spacing?.small}`,
57
59
 
58
60
  arrowsContainerWidth: '2rem',
@@ -18,6 +18,7 @@
18
18
  { "path": "../ui-form-field/tsconfig.build.json" },
19
19
  { "path": "../ui-icons/tsconfig.build.json" },
20
20
  { "path": "../ui-react-utils/tsconfig.build.json" },
21
+ { "path": "../ui-a11y-utils/tsconfig.build.json" },
21
22
  { "path": "../ui-testable/tsconfig.build.json" },
22
23
  { "path": "../ui-utils/tsconfig.build.json" },
23
24
  { "path": "../uid/tsconfig.build.json" }