@instructure/ui-time-select 8.34.1-snapshot-1 → 8.35.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 +3 -5
- package/es/TimeSelect/index.js +105 -53
- package/es/TimeSelect/props.js +4 -2
- package/lib/TimeSelect/index.js +105 -53
- package/lib/TimeSelect/props.js +4 -2
- package/package.json +13 -12
- package/src/TimeSelect/README.md +27 -1
- package/src/TimeSelect/index.tsx +90 -29
- package/src/TimeSelect/props.ts +42 -2
- package/tsconfig.build.json +1 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/TimeSelect/index.d.ts +9 -2
- package/types/TimeSelect/index.d.ts.map +1 -1
- package/types/TimeSelect/props.d.ts +35 -0
- package/types/TimeSelect/props.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,13 +3,11 @@
|
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
**Note:** Version bump only for package @instructure/ui-time-select
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
# [8.35.0](https://github.com/instructure/instructure-ui/compare/v8.34.0...v8.35.0) (2023-02-17)
|
|
11
7
|
|
|
8
|
+
### Features
|
|
12
9
|
|
|
10
|
+
- **ui-time-select:** allow non-step values with allowNonStepInput ([6dace32](https://github.com/instructure/instructure-ui/commit/6dace32d7fbb4d13227ac988b83f521308541204))
|
|
13
11
|
|
|
14
12
|
# [8.34.0](https://github.com/instructure/instructure-ui/compare/v8.33.2...v8.34.0) (2023-02-10)
|
|
15
13
|
|
package/es/TimeSelect/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
|
|
2
|
-
const _excluded = ["value", "defaultValue", "placeholder", "renderLabel", "inputRef", "id", "listRef", "renderBeforeInput", "renderAfterInput", "isRequired", "isInline", "width", "format", "step", "optionsMaxWidth", "visibleOptionsCount", "messages", "placement", "constrain", "onFocus", "onShowOptions", "onHideOptions", "mountNode"];
|
|
2
|
+
const _excluded = ["value", "defaultValue", "placeholder", "renderLabel", "inputRef", "id", "listRef", "renderBeforeInput", "renderAfterInput", "isRequired", "isInline", "width", "format", "step", "optionsMaxWidth", "visibleOptionsCount", "messages", "placement", "constrain", "onFocus", "onShowOptions", "onHideOptions", "onInputChange", "onKeyDown", "mountNode"];
|
|
3
3
|
var _dec, _dec2, _class, _class2;
|
|
4
4
|
/*
|
|
5
5
|
* The MIT License (MIT)
|
|
@@ -61,6 +61,7 @@ let TimeSelect = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class
|
|
|
61
61
|
(_this$props$onBlur = (_this$props = this.props).onBlur) === null || _this$props$onBlur === void 0 ? void 0 : _this$props$onBlur.call(_this$props, event);
|
|
62
62
|
};
|
|
63
63
|
this.handleInputChange = event => {
|
|
64
|
+
var _this$props$onInputCh, _this$props3;
|
|
64
65
|
const value = event.target.value;
|
|
65
66
|
const newOptions = this.filterOptions(value);
|
|
66
67
|
this.setState({
|
|
@@ -73,32 +74,44 @@ let TimeSelect = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class
|
|
|
73
74
|
var _this$props$onShowOpt, _this$props2;
|
|
74
75
|
(_this$props$onShowOpt = (_this$props2 = this.props).onShowOptions) === null || _this$props$onShowOpt === void 0 ? void 0 : _this$props$onShowOpt.call(_this$props2, event);
|
|
75
76
|
}
|
|
77
|
+
const inputAsDate = this.parseInputText(value);
|
|
78
|
+
(_this$props$onInputCh = (_this$props3 = this.props).onInputChange) === null || _this$props$onInputCh === void 0 ? void 0 : _this$props$onInputCh.call(_this$props3, event, value, inputAsDate.isValid() ? inputAsDate.toISOString() : void 0);
|
|
76
79
|
};
|
|
77
80
|
this.handleShowOptions = event => {
|
|
78
|
-
var _this$props$onShowOpt2, _this$
|
|
81
|
+
var _this$props$onShowOpt2, _this$props4;
|
|
79
82
|
this.setState({
|
|
80
83
|
isShowingOptions: true,
|
|
81
84
|
highlightedOptionId: this.state.selectedOptionId
|
|
82
85
|
});
|
|
83
|
-
(_this$props$onShowOpt2 = (_this$
|
|
86
|
+
(_this$props$onShowOpt2 = (_this$props4 = this.props).onShowOptions) === null || _this$props$onShowOpt2 === void 0 ? void 0 : _this$props$onShowOpt2.call(_this$props4, event);
|
|
84
87
|
};
|
|
85
88
|
this.handleHideOptions = event => {
|
|
86
|
-
var _this$props$onHideOpt, _this$
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
let prevValue = '';
|
|
89
|
+
var _this$props$onHideOpt, _this$props5;
|
|
90
|
+
const input = this.parseInputText(this.state.inputValue);
|
|
91
|
+
let defaultValue = '';
|
|
90
92
|
if (this.props.defaultValue) {
|
|
91
93
|
const date = DateTime.parse(this.props.defaultValue, this.locale(), this.timezone());
|
|
92
|
-
|
|
94
|
+
defaultValue = this.props.format ? date.format(this.props.format) : date.toISOString();
|
|
93
95
|
}
|
|
94
|
-
this.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
if (!this.props.allowNonStepInput || this.props.allowNonStepInput && input.isValid() && input.minute() % this.props.step === 0) {
|
|
97
|
+
const selectedOptionId = this.state.selectedOptionId;
|
|
98
|
+
const option = this.getOption('id', selectedOptionId);
|
|
99
|
+
this.setState(() => ({
|
|
100
|
+
isShowingOptions: false,
|
|
101
|
+
highlightedOptionId: void 0,
|
|
102
|
+
inputValue: selectedOptionId ? option.label : defaultValue,
|
|
103
|
+
filteredOptions: this.filterOptions(''),
|
|
104
|
+
...this.matchValue()
|
|
105
|
+
}));
|
|
106
|
+
} else {
|
|
107
|
+
this.setState(() => ({
|
|
108
|
+
isShowingOptions: false,
|
|
109
|
+
highlightedOptionId: void 0,
|
|
110
|
+
inputValue: this.state.lastValidInput || defaultValue || '',
|
|
111
|
+
filteredOptions: this.filterOptions('')
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
(_this$props$onHideOpt = (_this$props5 = this.props).onHideOptions) === null || _this$props$onHideOpt === void 0 ? void 0 : _this$props$onHideOpt.call(_this$props5, event);
|
|
102
115
|
};
|
|
103
116
|
this.handleHighlightOption = (event, _ref) => {
|
|
104
117
|
let id = _ref.id;
|
|
@@ -111,7 +124,7 @@ let TimeSelect = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class
|
|
|
111
124
|
}));
|
|
112
125
|
};
|
|
113
126
|
this.handleSelectOption = (event, _ref2) => {
|
|
114
|
-
var _this$props$onHideOpt2, _this$
|
|
127
|
+
var _this$props$onHideOpt2, _this$props7;
|
|
115
128
|
let id = _ref2.id;
|
|
116
129
|
if (id === this._emptyOptionId) {
|
|
117
130
|
this.setState({
|
|
@@ -139,13 +152,45 @@ let TimeSelect = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class
|
|
|
139
152
|
});
|
|
140
153
|
}
|
|
141
154
|
if (id !== this.state.selectedOptionId) {
|
|
142
|
-
var _this$props$onChange, _this$
|
|
143
|
-
|
|
155
|
+
var _this$props$onChange, _this$props6;
|
|
156
|
+
this.setState({
|
|
157
|
+
lastValidInput: newInputValue
|
|
158
|
+
});
|
|
159
|
+
(_this$props$onChange = (_this$props6 = this.props).onChange) === null || _this$props$onChange === void 0 ? void 0 : _this$props$onChange.call(_this$props6, event, {
|
|
144
160
|
value: option.value,
|
|
145
161
|
inputText: newInputValue
|
|
146
162
|
});
|
|
147
163
|
}
|
|
148
|
-
(_this$props$onHideOpt2 = (_this$
|
|
164
|
+
(_this$props$onHideOpt2 = (_this$props7 = this.props).onHideOptions) === null || _this$props$onHideOpt2 === void 0 ? void 0 : _this$props$onHideOpt2.call(_this$props7, event);
|
|
165
|
+
};
|
|
166
|
+
this.onKeyDown = event => {
|
|
167
|
+
var _this$props$onKeyDown, _this$props9;
|
|
168
|
+
const input = this.parseInputText(this.state.inputValue);
|
|
169
|
+
// validate input and if OK close dropdown
|
|
170
|
+
if (event.key === 'Enter' && this.props.allowNonStepInput && input.isValid() && input.minute() % this.props.step !== 0 && this.state.lastValidInput != this.state.inputValue) {
|
|
171
|
+
var _this$props$onChange2, _this$props8;
|
|
172
|
+
this.setState(() => ({
|
|
173
|
+
isShowingOptions: false,
|
|
174
|
+
highlightedOptionId: void 0,
|
|
175
|
+
filteredOptions: this.filterOptions(''),
|
|
176
|
+
lastValidInput: this.state.inputValue
|
|
177
|
+
}));
|
|
178
|
+
(_this$props$onChange2 = (_this$props8 = this.props).onChange) === null || _this$props$onChange2 === void 0 ? void 0 : _this$props$onChange2.call(_this$props8, event, {
|
|
179
|
+
value: input.toISOString(),
|
|
180
|
+
inputText: this.state.inputValue
|
|
181
|
+
});
|
|
182
|
+
// others are set in OnHideOptions
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
(_this$props$onKeyDown = (_this$props9 = this.props).onKeyDown) === null || _this$props$onKeyDown === void 0 ? void 0 : _this$props$onKeyDown.call(_this$props9, event);
|
|
186
|
+
};
|
|
187
|
+
this.parseInputText = inputValue => {
|
|
188
|
+
const input = DateTime.parse(inputValue, this.locale(), this.timezone(), [this.props.format], true);
|
|
189
|
+
const baseDate = this.getBaseDate();
|
|
190
|
+
input.year(baseDate.year());
|
|
191
|
+
input.month(baseDate.month());
|
|
192
|
+
input.date(baseDate.date());
|
|
193
|
+
return input;
|
|
149
194
|
};
|
|
150
195
|
this.state = this.getInitialState();
|
|
151
196
|
}
|
|
@@ -212,7 +257,10 @@ let TimeSelect = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class
|
|
|
212
257
|
const outsideVal = this.props.value ? this.props.value : '';
|
|
213
258
|
// value does not match an existing option
|
|
214
259
|
const date = DateTime.parse(outsideVal, this.locale(), this.timezone());
|
|
215
|
-
|
|
260
|
+
let label = '';
|
|
261
|
+
if (date.isValid()) {
|
|
262
|
+
label = this.props.format ? date.format(this.props.format) : date.toISOString();
|
|
263
|
+
}
|
|
216
264
|
this.setState({
|
|
217
265
|
inputValue: option ? option.label : label,
|
|
218
266
|
selectedOptionId: option ? option.id : void 0
|
|
@@ -241,11 +289,11 @@ let TimeSelect = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class
|
|
|
241
289
|
};
|
|
242
290
|
}
|
|
243
291
|
getInitialOption(options) {
|
|
244
|
-
const _this$
|
|
245
|
-
value = _this$
|
|
246
|
-
defaultValue = _this$
|
|
247
|
-
defaultToFirstOption = _this$
|
|
248
|
-
format = _this$
|
|
292
|
+
const _this$props10 = this.props,
|
|
293
|
+
value = _this$props10.value,
|
|
294
|
+
defaultValue = _this$props10.defaultValue,
|
|
295
|
+
defaultToFirstOption = _this$props10.defaultToFirstOption,
|
|
296
|
+
format = _this$props10.format;
|
|
249
297
|
const initialValue = value || defaultValue;
|
|
250
298
|
if (typeof initialValue === 'string') {
|
|
251
299
|
// get option based on value or defaultValue, if provided
|
|
@@ -380,31 +428,33 @@ let TimeSelect = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class
|
|
|
380
428
|
}, callRenderProp(this.props.renderEmptyOption));
|
|
381
429
|
}
|
|
382
430
|
render() {
|
|
383
|
-
const _this$
|
|
384
|
-
value = _this$
|
|
385
|
-
defaultValue = _this$
|
|
386
|
-
placeholder = _this$
|
|
387
|
-
renderLabel = _this$
|
|
388
|
-
inputRef = _this$
|
|
389
|
-
id = _this$
|
|
390
|
-
listRef = _this$
|
|
391
|
-
renderBeforeInput = _this$
|
|
392
|
-
renderAfterInput = _this$
|
|
393
|
-
isRequired = _this$
|
|
394
|
-
isInline = _this$
|
|
395
|
-
width = _this$
|
|
396
|
-
format = _this$
|
|
397
|
-
step = _this$
|
|
398
|
-
optionsMaxWidth = _this$
|
|
399
|
-
visibleOptionsCount = _this$
|
|
400
|
-
messages = _this$
|
|
401
|
-
placement = _this$
|
|
402
|
-
constrain = _this$
|
|
403
|
-
onFocus = _this$
|
|
404
|
-
onShowOptions = _this$
|
|
405
|
-
onHideOptions = _this$
|
|
406
|
-
|
|
407
|
-
|
|
431
|
+
const _this$props11 = this.props,
|
|
432
|
+
value = _this$props11.value,
|
|
433
|
+
defaultValue = _this$props11.defaultValue,
|
|
434
|
+
placeholder = _this$props11.placeholder,
|
|
435
|
+
renderLabel = _this$props11.renderLabel,
|
|
436
|
+
inputRef = _this$props11.inputRef,
|
|
437
|
+
id = _this$props11.id,
|
|
438
|
+
listRef = _this$props11.listRef,
|
|
439
|
+
renderBeforeInput = _this$props11.renderBeforeInput,
|
|
440
|
+
renderAfterInput = _this$props11.renderAfterInput,
|
|
441
|
+
isRequired = _this$props11.isRequired,
|
|
442
|
+
isInline = _this$props11.isInline,
|
|
443
|
+
width = _this$props11.width,
|
|
444
|
+
format = _this$props11.format,
|
|
445
|
+
step = _this$props11.step,
|
|
446
|
+
optionsMaxWidth = _this$props11.optionsMaxWidth,
|
|
447
|
+
visibleOptionsCount = _this$props11.visibleOptionsCount,
|
|
448
|
+
messages = _this$props11.messages,
|
|
449
|
+
placement = _this$props11.placement,
|
|
450
|
+
constrain = _this$props11.constrain,
|
|
451
|
+
onFocus = _this$props11.onFocus,
|
|
452
|
+
onShowOptions = _this$props11.onShowOptions,
|
|
453
|
+
onHideOptions = _this$props11.onHideOptions,
|
|
454
|
+
onInputChange = _this$props11.onInputChange,
|
|
455
|
+
onKeyDown = _this$props11.onKeyDown,
|
|
456
|
+
mountNode = _this$props11.mountNode,
|
|
457
|
+
rest = _objectWithoutProperties(_this$props11, _excluded);
|
|
408
458
|
const _this$state4 = this.state,
|
|
409
459
|
inputValue = _this$state4.inputValue,
|
|
410
460
|
isShowingOptions = _this$state4.isShowingOptions;
|
|
@@ -435,7 +485,8 @@ let TimeSelect = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class
|
|
|
435
485
|
onRequestHideOptions: this.handleHideOptions,
|
|
436
486
|
onRequestHighlightOption: this.handleHighlightOption,
|
|
437
487
|
onRequestSelectOption: this.handleSelectOption,
|
|
438
|
-
onInputChange: this.handleInputChange
|
|
488
|
+
onInputChange: this.handleInputChange,
|
|
489
|
+
onKeyDown: this.onKeyDown
|
|
439
490
|
}, passthroughProps(rest)), isShowingOptions && this.renderOptions());
|
|
440
491
|
}
|
|
441
492
|
}, _class2.displayName = "TimeSelect", _class2.componentId = 'TimeSelect', _class2.allowedProps = allowedProps, _class2.propTypes = propTypes, _class2.defaultProps = {
|
|
@@ -448,7 +499,8 @@ let TimeSelect = (_dec = withDeterministicId(), _dec2 = testable(), _dec(_class
|
|
|
448
499
|
visibleOptionsCount: 8,
|
|
449
500
|
placement: 'bottom stretch',
|
|
450
501
|
constrain: 'window',
|
|
451
|
-
renderEmptyOption: '---'
|
|
502
|
+
renderEmptyOption: '---',
|
|
503
|
+
allowNonStepInput: false
|
|
452
504
|
}, _class2.contextType = ApplyLocaleContext, _class2)) || _class) || _class);
|
|
453
505
|
export { TimeSelect };
|
|
454
506
|
export default TimeSelect;
|
package/es/TimeSelect/props.js
CHANGED
|
@@ -57,7 +57,9 @@ const propTypes = {
|
|
|
57
57
|
renderBeforeInput: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
58
58
|
renderAfterInput: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
59
59
|
locale: PropTypes.string,
|
|
60
|
-
timezone: PropTypes.string
|
|
60
|
+
timezone: PropTypes.string,
|
|
61
|
+
allowNonStepInput: PropTypes.bool,
|
|
62
|
+
onInputChange: PropTypes.func
|
|
61
63
|
};
|
|
62
|
-
const allowedProps = ['renderLabel', 'defaultToFirstOption', 'value', 'defaultValue', 'id', 'format', 'step', 'interaction', 'placeholder', 'isRequired', 'isInline', 'width', 'optionsMaxWidth', 'mountNode', 'visibleOptionsCount', 'messages', 'placement', 'constrain', 'onChange', 'onFocus', 'onBlur', 'onShowOptions', 'onHideOptions', 'inputRef', 'listRef', 'renderEmptyOption', 'renderBeforeInput', 'renderAfterInput', 'locale', 'timezone'];
|
|
64
|
+
const allowedProps = ['renderLabel', 'defaultToFirstOption', 'value', 'defaultValue', 'id', 'format', 'step', 'interaction', 'placeholder', 'isRequired', 'isInline', 'width', 'optionsMaxWidth', 'mountNode', 'visibleOptionsCount', 'messages', 'placement', 'constrain', 'onChange', 'onFocus', 'onBlur', 'onShowOptions', 'onHideOptions', 'inputRef', 'listRef', 'renderEmptyOption', 'renderBeforeInput', 'renderAfterInput', 'locale', 'timezone', 'allowNonStepInput', 'onInputChange'];
|
|
63
65
|
export { propTypes, allowedProps };
|
package/lib/TimeSelect/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var _withDeterministicId = require("@instructure/ui-react-utils/lib/Deterministi
|
|
|
18
18
|
var _testable = require("@instructure/ui-testable/lib/testable.js");
|
|
19
19
|
var _Select = require("@instructure/ui-select/lib/Select");
|
|
20
20
|
var _props = require("./props");
|
|
21
|
-
const _excluded = ["value", "defaultValue", "placeholder", "renderLabel", "inputRef", "id", "listRef", "renderBeforeInput", "renderAfterInput", "isRequired", "isInline", "width", "format", "step", "optionsMaxWidth", "visibleOptionsCount", "messages", "placement", "constrain", "onFocus", "onShowOptions", "onHideOptions", "mountNode"];
|
|
21
|
+
const _excluded = ["value", "defaultValue", "placeholder", "renderLabel", "inputRef", "id", "listRef", "renderBeforeInput", "renderAfterInput", "isRequired", "isInline", "width", "format", "step", "optionsMaxWidth", "visibleOptionsCount", "messages", "placement", "constrain", "onFocus", "onShowOptions", "onHideOptions", "onInputChange", "onKeyDown", "mountNode"];
|
|
22
22
|
var _dec, _dec2, _class, _class2;
|
|
23
23
|
/**
|
|
24
24
|
---
|
|
@@ -50,6 +50,7 @@ let TimeSelect = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2
|
|
|
50
50
|
(_this$props$onBlur = (_this$props = this.props).onBlur) === null || _this$props$onBlur === void 0 ? void 0 : _this$props$onBlur.call(_this$props, event);
|
|
51
51
|
};
|
|
52
52
|
this.handleInputChange = event => {
|
|
53
|
+
var _this$props$onInputCh, _this$props3;
|
|
53
54
|
const value = event.target.value;
|
|
54
55
|
const newOptions = this.filterOptions(value);
|
|
55
56
|
this.setState({
|
|
@@ -62,32 +63,44 @@ let TimeSelect = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2
|
|
|
62
63
|
var _this$props$onShowOpt, _this$props2;
|
|
63
64
|
(_this$props$onShowOpt = (_this$props2 = this.props).onShowOptions) === null || _this$props$onShowOpt === void 0 ? void 0 : _this$props$onShowOpt.call(_this$props2, event);
|
|
64
65
|
}
|
|
66
|
+
const inputAsDate = this.parseInputText(value);
|
|
67
|
+
(_this$props$onInputCh = (_this$props3 = this.props).onInputChange) === null || _this$props$onInputCh === void 0 ? void 0 : _this$props$onInputCh.call(_this$props3, event, value, inputAsDate.isValid() ? inputAsDate.toISOString() : void 0);
|
|
65
68
|
};
|
|
66
69
|
this.handleShowOptions = event => {
|
|
67
|
-
var _this$props$onShowOpt2, _this$
|
|
70
|
+
var _this$props$onShowOpt2, _this$props4;
|
|
68
71
|
this.setState({
|
|
69
72
|
isShowingOptions: true,
|
|
70
73
|
highlightedOptionId: this.state.selectedOptionId
|
|
71
74
|
});
|
|
72
|
-
(_this$props$onShowOpt2 = (_this$
|
|
75
|
+
(_this$props$onShowOpt2 = (_this$props4 = this.props).onShowOptions) === null || _this$props$onShowOpt2 === void 0 ? void 0 : _this$props$onShowOpt2.call(_this$props4, event);
|
|
73
76
|
};
|
|
74
77
|
this.handleHideOptions = event => {
|
|
75
|
-
var _this$props$onHideOpt, _this$
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
let prevValue = '';
|
|
78
|
+
var _this$props$onHideOpt, _this$props5;
|
|
79
|
+
const input = this.parseInputText(this.state.inputValue);
|
|
80
|
+
let defaultValue = '';
|
|
79
81
|
if (this.props.defaultValue) {
|
|
80
82
|
const date = _DateTime.DateTime.parse(this.props.defaultValue, this.locale(), this.timezone());
|
|
81
|
-
|
|
83
|
+
defaultValue = this.props.format ? date.format(this.props.format) : date.toISOString();
|
|
82
84
|
}
|
|
83
|
-
this.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
if (!this.props.allowNonStepInput || this.props.allowNonStepInput && input.isValid() && input.minute() % this.props.step === 0) {
|
|
86
|
+
const selectedOptionId = this.state.selectedOptionId;
|
|
87
|
+
const option = this.getOption('id', selectedOptionId);
|
|
88
|
+
this.setState(() => ({
|
|
89
|
+
isShowingOptions: false,
|
|
90
|
+
highlightedOptionId: void 0,
|
|
91
|
+
inputValue: selectedOptionId ? option.label : defaultValue,
|
|
92
|
+
filteredOptions: this.filterOptions(''),
|
|
93
|
+
...this.matchValue()
|
|
94
|
+
}));
|
|
95
|
+
} else {
|
|
96
|
+
this.setState(() => ({
|
|
97
|
+
isShowingOptions: false,
|
|
98
|
+
highlightedOptionId: void 0,
|
|
99
|
+
inputValue: this.state.lastValidInput || defaultValue || '',
|
|
100
|
+
filteredOptions: this.filterOptions('')
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
(_this$props$onHideOpt = (_this$props5 = this.props).onHideOptions) === null || _this$props$onHideOpt === void 0 ? void 0 : _this$props$onHideOpt.call(_this$props5, event);
|
|
91
104
|
};
|
|
92
105
|
this.handleHighlightOption = (event, _ref) => {
|
|
93
106
|
let id = _ref.id;
|
|
@@ -100,7 +113,7 @@ let TimeSelect = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2
|
|
|
100
113
|
}));
|
|
101
114
|
};
|
|
102
115
|
this.handleSelectOption = (event, _ref2) => {
|
|
103
|
-
var _this$props$onHideOpt2, _this$
|
|
116
|
+
var _this$props$onHideOpt2, _this$props7;
|
|
104
117
|
let id = _ref2.id;
|
|
105
118
|
if (id === this._emptyOptionId) {
|
|
106
119
|
this.setState({
|
|
@@ -128,13 +141,45 @@ let TimeSelect = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2
|
|
|
128
141
|
});
|
|
129
142
|
}
|
|
130
143
|
if (id !== this.state.selectedOptionId) {
|
|
131
|
-
var _this$props$onChange, _this$
|
|
132
|
-
|
|
144
|
+
var _this$props$onChange, _this$props6;
|
|
145
|
+
this.setState({
|
|
146
|
+
lastValidInput: newInputValue
|
|
147
|
+
});
|
|
148
|
+
(_this$props$onChange = (_this$props6 = this.props).onChange) === null || _this$props$onChange === void 0 ? void 0 : _this$props$onChange.call(_this$props6, event, {
|
|
133
149
|
value: option.value,
|
|
134
150
|
inputText: newInputValue
|
|
135
151
|
});
|
|
136
152
|
}
|
|
137
|
-
(_this$props$onHideOpt2 = (_this$
|
|
153
|
+
(_this$props$onHideOpt2 = (_this$props7 = this.props).onHideOptions) === null || _this$props$onHideOpt2 === void 0 ? void 0 : _this$props$onHideOpt2.call(_this$props7, event);
|
|
154
|
+
};
|
|
155
|
+
this.onKeyDown = event => {
|
|
156
|
+
var _this$props$onKeyDown, _this$props9;
|
|
157
|
+
const input = this.parseInputText(this.state.inputValue);
|
|
158
|
+
// validate input and if OK close dropdown
|
|
159
|
+
if (event.key === 'Enter' && this.props.allowNonStepInput && input.isValid() && input.minute() % this.props.step !== 0 && this.state.lastValidInput != this.state.inputValue) {
|
|
160
|
+
var _this$props$onChange2, _this$props8;
|
|
161
|
+
this.setState(() => ({
|
|
162
|
+
isShowingOptions: false,
|
|
163
|
+
highlightedOptionId: void 0,
|
|
164
|
+
filteredOptions: this.filterOptions(''),
|
|
165
|
+
lastValidInput: this.state.inputValue
|
|
166
|
+
}));
|
|
167
|
+
(_this$props$onChange2 = (_this$props8 = this.props).onChange) === null || _this$props$onChange2 === void 0 ? void 0 : _this$props$onChange2.call(_this$props8, event, {
|
|
168
|
+
value: input.toISOString(),
|
|
169
|
+
inputText: this.state.inputValue
|
|
170
|
+
});
|
|
171
|
+
// others are set in OnHideOptions
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
(_this$props$onKeyDown = (_this$props9 = this.props).onKeyDown) === null || _this$props$onKeyDown === void 0 ? void 0 : _this$props$onKeyDown.call(_this$props9, event);
|
|
175
|
+
};
|
|
176
|
+
this.parseInputText = inputValue => {
|
|
177
|
+
const input = _DateTime.DateTime.parse(inputValue, this.locale(), this.timezone(), [this.props.format], true);
|
|
178
|
+
const baseDate = this.getBaseDate();
|
|
179
|
+
input.year(baseDate.year());
|
|
180
|
+
input.month(baseDate.month());
|
|
181
|
+
input.date(baseDate.date());
|
|
182
|
+
return input;
|
|
138
183
|
};
|
|
139
184
|
this.state = this.getInitialState();
|
|
140
185
|
}
|
|
@@ -201,7 +246,10 @@ let TimeSelect = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2
|
|
|
201
246
|
const outsideVal = this.props.value ? this.props.value : '';
|
|
202
247
|
// value does not match an existing option
|
|
203
248
|
const date = _DateTime.DateTime.parse(outsideVal, this.locale(), this.timezone());
|
|
204
|
-
|
|
249
|
+
let label = '';
|
|
250
|
+
if (date.isValid()) {
|
|
251
|
+
label = this.props.format ? date.format(this.props.format) : date.toISOString();
|
|
252
|
+
}
|
|
205
253
|
this.setState({
|
|
206
254
|
inputValue: option ? option.label : label,
|
|
207
255
|
selectedOptionId: option ? option.id : void 0
|
|
@@ -230,11 +278,11 @@ let TimeSelect = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2
|
|
|
230
278
|
};
|
|
231
279
|
}
|
|
232
280
|
getInitialOption(options) {
|
|
233
|
-
const _this$
|
|
234
|
-
value = _this$
|
|
235
|
-
defaultValue = _this$
|
|
236
|
-
defaultToFirstOption = _this$
|
|
237
|
-
format = _this$
|
|
281
|
+
const _this$props10 = this.props,
|
|
282
|
+
value = _this$props10.value,
|
|
283
|
+
defaultValue = _this$props10.defaultValue,
|
|
284
|
+
defaultToFirstOption = _this$props10.defaultToFirstOption,
|
|
285
|
+
format = _this$props10.format;
|
|
238
286
|
const initialValue = value || defaultValue;
|
|
239
287
|
if (typeof initialValue === 'string') {
|
|
240
288
|
// get option based on value or defaultValue, if provided
|
|
@@ -369,31 +417,33 @@ let TimeSelect = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2
|
|
|
369
417
|
}, (0, _callRenderProp.callRenderProp)(this.props.renderEmptyOption));
|
|
370
418
|
}
|
|
371
419
|
render() {
|
|
372
|
-
const _this$
|
|
373
|
-
value = _this$
|
|
374
|
-
defaultValue = _this$
|
|
375
|
-
placeholder = _this$
|
|
376
|
-
renderLabel = _this$
|
|
377
|
-
inputRef = _this$
|
|
378
|
-
id = _this$
|
|
379
|
-
listRef = _this$
|
|
380
|
-
renderBeforeInput = _this$
|
|
381
|
-
renderAfterInput = _this$
|
|
382
|
-
isRequired = _this$
|
|
383
|
-
isInline = _this$
|
|
384
|
-
width = _this$
|
|
385
|
-
format = _this$
|
|
386
|
-
step = _this$
|
|
387
|
-
optionsMaxWidth = _this$
|
|
388
|
-
visibleOptionsCount = _this$
|
|
389
|
-
messages = _this$
|
|
390
|
-
placement = _this$
|
|
391
|
-
constrain = _this$
|
|
392
|
-
onFocus = _this$
|
|
393
|
-
onShowOptions = _this$
|
|
394
|
-
onHideOptions = _this$
|
|
395
|
-
|
|
396
|
-
|
|
420
|
+
const _this$props11 = this.props,
|
|
421
|
+
value = _this$props11.value,
|
|
422
|
+
defaultValue = _this$props11.defaultValue,
|
|
423
|
+
placeholder = _this$props11.placeholder,
|
|
424
|
+
renderLabel = _this$props11.renderLabel,
|
|
425
|
+
inputRef = _this$props11.inputRef,
|
|
426
|
+
id = _this$props11.id,
|
|
427
|
+
listRef = _this$props11.listRef,
|
|
428
|
+
renderBeforeInput = _this$props11.renderBeforeInput,
|
|
429
|
+
renderAfterInput = _this$props11.renderAfterInput,
|
|
430
|
+
isRequired = _this$props11.isRequired,
|
|
431
|
+
isInline = _this$props11.isInline,
|
|
432
|
+
width = _this$props11.width,
|
|
433
|
+
format = _this$props11.format,
|
|
434
|
+
step = _this$props11.step,
|
|
435
|
+
optionsMaxWidth = _this$props11.optionsMaxWidth,
|
|
436
|
+
visibleOptionsCount = _this$props11.visibleOptionsCount,
|
|
437
|
+
messages = _this$props11.messages,
|
|
438
|
+
placement = _this$props11.placement,
|
|
439
|
+
constrain = _this$props11.constrain,
|
|
440
|
+
onFocus = _this$props11.onFocus,
|
|
441
|
+
onShowOptions = _this$props11.onShowOptions,
|
|
442
|
+
onHideOptions = _this$props11.onHideOptions,
|
|
443
|
+
onInputChange = _this$props11.onInputChange,
|
|
444
|
+
onKeyDown = _this$props11.onKeyDown,
|
|
445
|
+
mountNode = _this$props11.mountNode,
|
|
446
|
+
rest = (0, _objectWithoutProperties2.default)(_this$props11, _excluded);
|
|
397
447
|
const _this$state4 = this.state,
|
|
398
448
|
inputValue = _this$state4.inputValue,
|
|
399
449
|
isShowingOptions = _this$state4.isShowingOptions;
|
|
@@ -424,7 +474,8 @@ let TimeSelect = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2
|
|
|
424
474
|
onRequestHideOptions: this.handleHideOptions,
|
|
425
475
|
onRequestHighlightOption: this.handleHighlightOption,
|
|
426
476
|
onRequestSelectOption: this.handleSelectOption,
|
|
427
|
-
onInputChange: this.handleInputChange
|
|
477
|
+
onInputChange: this.handleInputChange,
|
|
478
|
+
onKeyDown: this.onKeyDown
|
|
428
479
|
}, (0, _passthroughProps.passthroughProps)(rest)), isShowingOptions && this.renderOptions());
|
|
429
480
|
}
|
|
430
481
|
}, _class2.displayName = "TimeSelect", _class2.componentId = 'TimeSelect', _class2.allowedProps = _props.allowedProps, _class2.propTypes = _props.propTypes, _class2.defaultProps = {
|
|
@@ -437,7 +488,8 @@ let TimeSelect = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2
|
|
|
437
488
|
visibleOptionsCount: 8,
|
|
438
489
|
placement: 'bottom stretch',
|
|
439
490
|
constrain: 'window',
|
|
440
|
-
renderEmptyOption: '---'
|
|
491
|
+
renderEmptyOption: '---',
|
|
492
|
+
allowNonStepInput: false
|
|
441
493
|
}, _class2.contextType = _ApplyLocaleContext.ApplyLocaleContext, _class2)) || _class) || _class);
|
|
442
494
|
exports.TimeSelect = TimeSelect;
|
|
443
495
|
var _default = TimeSelect;
|
package/lib/TimeSelect/props.js
CHANGED
|
@@ -64,8 +64,10 @@ const propTypes = {
|
|
|
64
64
|
renderBeforeInput: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.func]),
|
|
65
65
|
renderAfterInput: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.func]),
|
|
66
66
|
locale: _propTypes.default.string,
|
|
67
|
-
timezone: _propTypes.default.string
|
|
67
|
+
timezone: _propTypes.default.string,
|
|
68
|
+
allowNonStepInput: _propTypes.default.bool,
|
|
69
|
+
onInputChange: _propTypes.default.func
|
|
68
70
|
};
|
|
69
71
|
exports.propTypes = propTypes;
|
|
70
|
-
const allowedProps = ['renderLabel', 'defaultToFirstOption', 'value', 'defaultValue', 'id', 'format', 'step', 'interaction', 'placeholder', 'isRequired', 'isInline', 'width', 'optionsMaxWidth', 'mountNode', 'visibleOptionsCount', 'messages', 'placement', 'constrain', 'onChange', 'onFocus', 'onBlur', 'onShowOptions', 'onHideOptions', 'inputRef', 'listRef', 'renderEmptyOption', 'renderBeforeInput', 'renderAfterInput', 'locale', 'timezone'];
|
|
72
|
+
const allowedProps = ['renderLabel', 'defaultToFirstOption', 'value', 'defaultValue', 'id', 'format', 'step', 'interaction', 'placeholder', 'isRequired', 'isInline', 'width', 'optionsMaxWidth', 'mountNode', 'visibleOptionsCount', 'messages', 'placement', 'constrain', 'onChange', 'onFocus', 'onBlur', 'onShowOptions', 'onHideOptions', 'inputRef', 'listRef', 'renderEmptyOption', 'renderBeforeInput', 'renderAfterInput', 'locale', 'timezone', 'allowNonStepInput', 'onInputChange'];
|
|
71
73
|
exports.allowedProps = allowedProps;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/ui-time-select",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.35.0",
|
|
4
4
|
"description": "A component for selecting time values.",
|
|
5
5
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
6
6
|
"module": "./es/index.js",
|
|
@@ -24,20 +24,21 @@
|
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@babel/runtime": "^7.20.13",
|
|
27
|
-
"@instructure/shared-types": "8.
|
|
28
|
-
"@instructure/ui-form-field": "8.
|
|
29
|
-
"@instructure/ui-i18n": "8.
|
|
30
|
-
"@instructure/ui-position": "8.
|
|
31
|
-
"@instructure/ui-prop-types": "8.
|
|
32
|
-
"@instructure/ui-react-utils": "8.
|
|
33
|
-
"@instructure/ui-select": "8.
|
|
34
|
-
"@instructure/ui-test-locator": "8.
|
|
35
|
-
"@instructure/ui-testable": "8.
|
|
27
|
+
"@instructure/shared-types": "8.35.0",
|
|
28
|
+
"@instructure/ui-form-field": "8.35.0",
|
|
29
|
+
"@instructure/ui-i18n": "8.35.0",
|
|
30
|
+
"@instructure/ui-position": "8.35.0",
|
|
31
|
+
"@instructure/ui-prop-types": "8.35.0",
|
|
32
|
+
"@instructure/ui-react-utils": "8.35.0",
|
|
33
|
+
"@instructure/ui-select": "8.35.0",
|
|
34
|
+
"@instructure/ui-test-locator": "8.35.0",
|
|
35
|
+
"@instructure/ui-testable": "8.35.0",
|
|
36
|
+
"@instructure/ui-utils": "8.35.0",
|
|
36
37
|
"prop-types": "^15.8.1"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@instructure/ui-babel-preset": "8.
|
|
40
|
-
"@instructure/ui-test-utils": "8.
|
|
40
|
+
"@instructure/ui-babel-preset": "8.35.0",
|
|
41
|
+
"@instructure/ui-test-utils": "8.35.0",
|
|
41
42
|
"moment-timezone": "^0.5.40"
|
|
42
43
|
},
|
|
43
44
|
"peerDependencies": {
|
package/src/TimeSelect/README.md
CHANGED
|
@@ -5,6 +5,7 @@ describes: TimeSelect
|
|
|
5
5
|
`TimeSelect` component is a higher level abstraction of [Select](#Select) specifically for selecting time values. The list of possible values can be configured via the component's props. If you need to select times and dates, be sure to check out the documentation around [Time and Date patterns](#TimeDate).
|
|
6
6
|
|
|
7
7
|
### Uncontrolled
|
|
8
|
+
|
|
8
9
|
For the most basic implementations, `TimeSelect` can be uncontrolled. If desired, the `defaultValue` prop can be used to set the initial selection.
|
|
9
10
|
|
|
10
11
|
```javascript
|
|
@@ -15,11 +16,13 @@ render: true
|
|
|
15
16
|
<TimeSelect
|
|
16
17
|
renderLabel="Choose a time"
|
|
17
18
|
onChange={(e, { value }) => console.log(value)}
|
|
19
|
+
onHideOptions={(e)=> console.log("hide opts")}
|
|
18
20
|
// defaultValue={new Date().toISOString()}
|
|
19
21
|
/>
|
|
20
22
|
```
|
|
21
23
|
|
|
22
24
|
### Controlled
|
|
25
|
+
|
|
23
26
|
To use `TimeSelect` controlled, simply provide the `value` prop an ISO string. The `onChange` callback provides the ISO value of the corresponding option that was selected. Use this value to update the state.
|
|
24
27
|
|
|
25
28
|
```javascript
|
|
@@ -54,7 +57,29 @@ render(
|
|
|
54
57
|
)
|
|
55
58
|
```
|
|
56
59
|
|
|
60
|
+
### Freeform input
|
|
61
|
+
|
|
62
|
+
By default, the user can only set a value that is divisible by `step` (although the component allows to set any valid time value programmatically). You can allow the user to set any valid value with typing in by setting `allowNonStepInput` to `true`. You can use the `onInputChange` event to see whether the current input is valid and its current value.
|
|
63
|
+
Note that the exact value needed to be typed by the user depends on their `locale`:
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
---
|
|
67
|
+
example: true
|
|
68
|
+
render: true
|
|
69
|
+
---
|
|
70
|
+
<TimeSelect
|
|
71
|
+
renderLabel="Choose a time"
|
|
72
|
+
onChange={(e, { value }) => console.log("change",value)}
|
|
73
|
+
onInputChange={(e, value, isoValue)=> console.log("inputChange", value, isoValue)}
|
|
74
|
+
defaultValue="2022-05-12T05:30:00.000Z"
|
|
75
|
+
locale="en_AU"
|
|
76
|
+
timezone='US/Eastern'
|
|
77
|
+
allowNonStepInput
|
|
78
|
+
/>
|
|
79
|
+
```
|
|
80
|
+
|
|
57
81
|
### Guidelines
|
|
82
|
+
|
|
58
83
|
```js
|
|
59
84
|
---
|
|
60
85
|
guidelines: true
|
|
@@ -62,6 +87,7 @@ guidelines: true
|
|
|
62
87
|
<Guidelines>
|
|
63
88
|
<Figure recommendation="yes" title="Do">
|
|
64
89
|
<Figure.Item>Use a default value of 11:59 pm for implementations that have to do with due dates</Figure.Item>
|
|
90
|
+
<Figure.Item>Respect the user's `locale` and `timezone` browser settings (the component does this by itself when not setting `locale` or `timezone`).</Figure.Item>
|
|
65
91
|
</Figure>
|
|
66
92
|
</Guidelines>
|
|
67
|
-
```
|
|
93
|
+
```
|