@instructure/ui-time-select 11.7.3-snapshot-7 → 11.7.3-snapshot-26
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 +5 -2
- package/es/TimeSelect/v1/index.js +260 -261
- package/es/TimeSelect/v2/index.js +260 -261
- package/lib/TimeSelect/v1/index.js +260 -262
- package/lib/TimeSelect/v2/index.js +260 -262
- package/package.json +11 -11
- package/tsconfig.build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,9 +3,12 @@
|
|
|
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
|
-
## [11.7.3-snapshot-
|
|
6
|
+
## [11.7.3-snapshot-26](https://github.com/instructure/instructure-ui/compare/v11.7.2...v11.7.3-snapshot-26) (2026-05-05)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **many:** update dependencies, remove lots of Babel plugins, remove Webpack 4 support ([f916fca](https://github.com/instructure/instructure-ui/commit/f916fcafdddcb2d7de401f93e8ff92cfdfa47bba))
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
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
|
-
var _dec, _class, _TimeSelect;
|
|
1
|
+
var _dec, _class;
|
|
4
2
|
/*
|
|
5
3
|
* The MIT License (MIT)
|
|
6
4
|
*
|
|
@@ -39,201 +37,29 @@ category: components
|
|
|
39
37
|
|
|
40
38
|
A component used to select a time value.
|
|
41
39
|
**/
|
|
42
|
-
let TimeSelect = (_dec = withDeterministicId(), _dec(_class =
|
|
40
|
+
let TimeSelect = (_dec = withDeterministicId(), _dec(_class = class TimeSelect extends Component {
|
|
41
|
+
static displayName = "TimeSelect";
|
|
42
|
+
static componentId = 'TimeSelect';
|
|
43
|
+
static allowedProps = allowedProps;
|
|
44
|
+
static defaultProps = {
|
|
45
|
+
defaultToFirstOption: false,
|
|
46
|
+
format: 'LT',
|
|
47
|
+
// see https://momentjs.com/docs/#/displaying/
|
|
48
|
+
step: 30,
|
|
49
|
+
isRequired: false,
|
|
50
|
+
isInline: false,
|
|
51
|
+
visibleOptionsCount: 8,
|
|
52
|
+
placement: 'bottom stretch',
|
|
53
|
+
constrain: 'window',
|
|
54
|
+
renderEmptyOption: '---',
|
|
55
|
+
allowNonStepInput: false,
|
|
56
|
+
allowClearingSelection: false
|
|
57
|
+
};
|
|
58
|
+
static contextType = ApplyLocaleContext;
|
|
59
|
+
ref = null;
|
|
60
|
+
_emptyOptionId = this.props.deterministicId('Select-EmptyOption');
|
|
43
61
|
constructor(props) {
|
|
44
62
|
super(props);
|
|
45
|
-
this.ref = null;
|
|
46
|
-
this._emptyOptionId = this.props.deterministicId('Select-EmptyOption');
|
|
47
|
-
this.getOption = (field, value, options = this.state.options) => {
|
|
48
|
-
return options.find(option => option[field] === value);
|
|
49
|
-
};
|
|
50
|
-
this.handleRef = node => {
|
|
51
|
-
this.ref = node;
|
|
52
|
-
};
|
|
53
|
-
this.handleBlur = event => {
|
|
54
|
-
var _this$props$onBlur, _this$props;
|
|
55
|
-
(_this$props$onBlur = (_this$props = this.props).onBlur) === null || _this$props$onBlur === void 0 ? void 0 : _this$props$onBlur.call(_this$props, event);
|
|
56
|
-
};
|
|
57
|
-
this.handleInputChange = event => {
|
|
58
|
-
var _this$props$onInputCh, _this$props3;
|
|
59
|
-
const value = event.target.value;
|
|
60
|
-
const newOptions = this.filterOptions(value);
|
|
61
|
-
if ((newOptions === null || newOptions === void 0 ? void 0 : newOptions.length) == 1) {
|
|
62
|
-
// if there is only 1 option, it will be automatically selected except
|
|
63
|
-
// if in controlled mode (it would commit this change)
|
|
64
|
-
if (!this.isControlled) {
|
|
65
|
-
this.setState({
|
|
66
|
-
selectedOptionId: newOptions[0].id
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
this.setState({
|
|
70
|
-
fireChangeOnBlur: newOptions[0]
|
|
71
|
-
});
|
|
72
|
-
} else {
|
|
73
|
-
this.setState({
|
|
74
|
-
fireChangeOnBlur: void 0,
|
|
75
|
-
isInputCleared: this.props.allowClearingSelection && value === ''
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
this.setState({
|
|
79
|
-
inputValue: value,
|
|
80
|
-
filteredOptions: newOptions,
|
|
81
|
-
highlightedOptionId: newOptions.length > 0 ? newOptions[0].id : void 0,
|
|
82
|
-
isShowingOptions: true
|
|
83
|
-
});
|
|
84
|
-
if (!this.state.isShowingOptions) {
|
|
85
|
-
var _this$props$onShowOpt, _this$props2;
|
|
86
|
-
(_this$props$onShowOpt = (_this$props2 = this.props).onShowOptions) === null || _this$props$onShowOpt === void 0 ? void 0 : _this$props$onShowOpt.call(_this$props2, event);
|
|
87
|
-
}
|
|
88
|
-
const inputAsDate = this.parseInputText(value);
|
|
89
|
-
(_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);
|
|
90
|
-
};
|
|
91
|
-
this.onKeyDown = event => {
|
|
92
|
-
var _this$props$onKeyDown, _this$props4;
|
|
93
|
-
const input = this.parseInputText(this.state.inputValue);
|
|
94
|
-
if (event.key === 'Enter' && this.props.allowNonStepInput && input.isValid()) {
|
|
95
|
-
this.setState(() => ({
|
|
96
|
-
isShowingOptions: false,
|
|
97
|
-
highlightedOptionId: void 0
|
|
98
|
-
}));
|
|
99
|
-
// others are set in handleBlurOrEsc
|
|
100
|
-
}
|
|
101
|
-
(_this$props$onKeyDown = (_this$props4 = this.props).onKeyDown) === null || _this$props$onKeyDown === void 0 ? void 0 : _this$props$onKeyDown.call(_this$props4, event);
|
|
102
|
-
};
|
|
103
|
-
this.handleShowOptions = event => {
|
|
104
|
-
var _this$props$onShowOpt2, _this$props5;
|
|
105
|
-
this.setState({
|
|
106
|
-
isShowingOptions: true,
|
|
107
|
-
highlightedOptionId: this.state.selectedOptionId
|
|
108
|
-
});
|
|
109
|
-
(_this$props$onShowOpt2 = (_this$props5 = this.props).onShowOptions) === null || _this$props$onShowOpt2 === void 0 ? void 0 : _this$props$onShowOpt2.call(_this$props5, event);
|
|
110
|
-
if (event.type.startsWith('key')) {
|
|
111
|
-
const keyboardEvent = event;
|
|
112
|
-
const children = this.state.filteredOptions;
|
|
113
|
-
if (!this.state.inputValue && children.length > 0 && !this.props.allowClearingSelection) {
|
|
114
|
-
const optionId = keyboardEvent.key === 'ArrowDown' ? children[0].id : keyboardEvent.key === 'ArrowUp' ? children[children.length - 1].id : void 0;
|
|
115
|
-
optionId && this.setState({
|
|
116
|
-
highlightedOptionId: optionId
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
// Called when the input is blurred (=when clicking outside, tabbing away),
|
|
122
|
-
// when pressing ESC. NOT called when an item is selected via Enter/click,
|
|
123
|
-
// (but in this case it will be called later when the input is blurred.)
|
|
124
|
-
this.handleBlurOrEsc = event => {
|
|
125
|
-
var _this$props$onHideOpt, _this$props8;
|
|
126
|
-
const _this$state = this.state,
|
|
127
|
-
selectedOptionId = _this$state.selectedOptionId,
|
|
128
|
-
inputValue = _this$state.inputValue,
|
|
129
|
-
isInputCleared = _this$state.isInputCleared;
|
|
130
|
-
let defaultValue = '';
|
|
131
|
-
if (this.props.defaultValue) {
|
|
132
|
-
const date = DateTime.parse(this.props.defaultValue, this.locale(), this.timezone());
|
|
133
|
-
defaultValue = this.props.format ? date.format(this.props.format) : date.toISOString();
|
|
134
|
-
}
|
|
135
|
-
const selectedOption = this.getOption('id', selectedOptionId);
|
|
136
|
-
let newInputValue = defaultValue;
|
|
137
|
-
// if input was completely cleared, ensure it stays clear
|
|
138
|
-
// e.g. defaultValue defined, but no selection yet made
|
|
139
|
-
if (inputValue === '' && this.props.allowClearingSelection) {
|
|
140
|
-
newInputValue = '';
|
|
141
|
-
} else if (selectedOption) {
|
|
142
|
-
// If there is a selected option use its value in the input field.
|
|
143
|
-
newInputValue = selectedOption.label;
|
|
144
|
-
} else if (this.props.value) {
|
|
145
|
-
// If controlled and input is cleared and blurred after the first render, it should revert to value
|
|
146
|
-
const date = DateTime.parse(this.props.value, this.locale(), this.timezone());
|
|
147
|
-
newInputValue = this.props.format ? date.format(this.props.format) : date.toISOString();
|
|
148
|
-
}
|
|
149
|
-
this.setState(() => ({
|
|
150
|
-
isShowingOptions: false,
|
|
151
|
-
highlightedOptionId: void 0,
|
|
152
|
-
inputValue: newInputValue,
|
|
153
|
-
filteredOptions: this.filterOptions('')
|
|
154
|
-
}));
|
|
155
|
-
if (this.state.fireChangeOnBlur && event.key !== 'Escape') {
|
|
156
|
-
var _this$props$onChange, _this$props6;
|
|
157
|
-
this.setState(() => ({
|
|
158
|
-
fireChangeOnBlur: void 0
|
|
159
|
-
}));
|
|
160
|
-
(_this$props$onChange = (_this$props6 = this.props).onChange) === null || _this$props$onChange === void 0 ? void 0 : _this$props$onChange.call(_this$props6, event, {
|
|
161
|
-
value: this.state.fireChangeOnBlur.value.toISOString(),
|
|
162
|
-
inputText: this.state.fireChangeOnBlur.label
|
|
163
|
-
});
|
|
164
|
-
} else if (isInputCleared && event.key !== 'Escape' && this.props.allowClearingSelection) {
|
|
165
|
-
var _this$props$onChange2, _this$props7;
|
|
166
|
-
this.setState(() => ({
|
|
167
|
-
isInputCleared: false
|
|
168
|
-
}));
|
|
169
|
-
(_this$props$onChange2 = (_this$props7 = this.props).onChange) === null || _this$props$onChange2 === void 0 ? void 0 : _this$props$onChange2.call(_this$props7, event, {
|
|
170
|
-
value: '',
|
|
171
|
-
inputText: ''
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
// TODO only fire this if handleSelectOption was not called before.
|
|
175
|
-
(_this$props$onHideOpt = (_this$props8 = this.props).onHideOptions) === null || _this$props$onHideOpt === void 0 ? void 0 : _this$props$onHideOpt.call(_this$props8, event);
|
|
176
|
-
};
|
|
177
|
-
// Called when an option is selected via mouse click or Enter.
|
|
178
|
-
this.handleSelectOption = (event, data) => {
|
|
179
|
-
var _this$props$onHideOpt2, _this$props0;
|
|
180
|
-
if (data.id === this._emptyOptionId) {
|
|
181
|
-
this.setState({
|
|
182
|
-
isShowingOptions: false
|
|
183
|
-
});
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
const selectedOption = this.getOption('id', data.id);
|
|
187
|
-
let newInputValue;
|
|
188
|
-
const currentSelectedOptionId = this.state.selectedOptionId;
|
|
189
|
-
|
|
190
|
-
// Focus needs to be reapplied to input
|
|
191
|
-
// after selecting an item to make sure VoiceOver behaves correctly on iOS
|
|
192
|
-
if (utils.isAndroidOrIOS()) {
|
|
193
|
-
this.blur();
|
|
194
|
-
this.focus();
|
|
195
|
-
}
|
|
196
|
-
if (this.isControlled) {
|
|
197
|
-
// in controlled mode we leave to the user to set the value of the
|
|
198
|
-
// component e.g. in the onChange event handler.
|
|
199
|
-
// This is accomplished by not setting a selectedOptionId
|
|
200
|
-
const prev = this.getOption('id', this.state.selectedOptionId);
|
|
201
|
-
newInputValue = prev ? prev.label : '';
|
|
202
|
-
this.setState({
|
|
203
|
-
isShowingOptions: false
|
|
204
|
-
});
|
|
205
|
-
} else {
|
|
206
|
-
newInputValue = selectedOption.label;
|
|
207
|
-
this.setState({
|
|
208
|
-
isShowingOptions: false,
|
|
209
|
-
selectedOptionId: data.id,
|
|
210
|
-
inputValue: newInputValue
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
if (data.id !== currentSelectedOptionId) {
|
|
214
|
-
var _this$props$onChange3, _this$props9;
|
|
215
|
-
(_this$props$onChange3 = (_this$props9 = this.props).onChange) === null || _this$props$onChange3 === void 0 ? void 0 : _this$props$onChange3.call(_this$props9, event, {
|
|
216
|
-
value: selectedOption.value.toISOString(),
|
|
217
|
-
inputText: newInputValue
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
(_this$props$onHideOpt2 = (_this$props0 = this.props).onHideOptions) === null || _this$props$onHideOpt2 === void 0 ? void 0 : _this$props$onHideOpt2.call(_this$props0, event);
|
|
221
|
-
};
|
|
222
|
-
this.handleHighlightOption = (_event, data) => {
|
|
223
|
-
if (data.id === this._emptyOptionId) return;
|
|
224
|
-
this.setState(state => ({
|
|
225
|
-
highlightedOptionId: data.id,
|
|
226
|
-
inputValue: state.inputValue
|
|
227
|
-
}));
|
|
228
|
-
};
|
|
229
|
-
this.parseInputText = inputValue => {
|
|
230
|
-
const input = DateTime.parse(inputValue, this.locale(), this.timezone(), [this.props.format], true);
|
|
231
|
-
const baseDate = this.getBaseDate();
|
|
232
|
-
input.year(baseDate.year());
|
|
233
|
-
input.month(baseDate.month());
|
|
234
|
-
input.date(baseDate.date());
|
|
235
|
-
return input;
|
|
236
|
-
};
|
|
237
63
|
this.state = this.getInitialState();
|
|
238
64
|
}
|
|
239
65
|
componentDidMount() {
|
|
@@ -242,8 +68,7 @@ let TimeSelect = (_dec = withDeterministicId(), _dec(_class = (_TimeSelect = cla
|
|
|
242
68
|
this.setState(this.getInitialState());
|
|
243
69
|
}
|
|
244
70
|
focus() {
|
|
245
|
-
|
|
246
|
-
(_this$ref = this.ref) === null || _this$ref === void 0 ? void 0 : _this$ref.focus();
|
|
71
|
+
this.ref?.focus();
|
|
247
72
|
}
|
|
248
73
|
blur() {
|
|
249
74
|
this.ref && this.ref.blur();
|
|
@@ -315,7 +140,7 @@ let TimeSelect = (_dec = withDeterministicId(), _dec(_class = (_TimeSelect = cla
|
|
|
315
140
|
}
|
|
316
141
|
this.setState({
|
|
317
142
|
inputValue: option ? option.label : label,
|
|
318
|
-
selectedOptionId: option ? option.id :
|
|
143
|
+
selectedOptionId: option ? option.id : undefined
|
|
319
144
|
});
|
|
320
145
|
}
|
|
321
146
|
}
|
|
@@ -333,17 +158,18 @@ let TimeSelect = (_dec = withDeterministicId(), _dec(_class = (_TimeSelect = cla
|
|
|
333
158
|
// 288 = 5 min step
|
|
334
159
|
filteredOptions: initialOptions.length > 288 ? initialOptions.filter(opt => opt.value.minute() % this.props.step === 0) : initialOptions,
|
|
335
160
|
isShowingOptions: false,
|
|
336
|
-
highlightedOptionId: initialSelection ? initialSelection.id :
|
|
337
|
-
selectedOptionId: initialSelection ? initialSelection.id :
|
|
161
|
+
highlightedOptionId: initialSelection ? initialSelection.id : undefined,
|
|
162
|
+
selectedOptionId: initialSelection ? initialSelection.id : undefined,
|
|
338
163
|
isInputCleared: false
|
|
339
164
|
};
|
|
340
165
|
}
|
|
341
166
|
getInitialOption(options) {
|
|
342
|
-
const
|
|
343
|
-
value
|
|
344
|
-
defaultValue
|
|
345
|
-
defaultToFirstOption
|
|
346
|
-
format
|
|
167
|
+
const {
|
|
168
|
+
value,
|
|
169
|
+
defaultValue,
|
|
170
|
+
defaultToFirstOption,
|
|
171
|
+
format
|
|
172
|
+
} = this.props;
|
|
347
173
|
const initialValue = value || defaultValue;
|
|
348
174
|
if (typeof initialValue === 'string') {
|
|
349
175
|
const date = DateTime.parse(initialValue, this.locale(), this.timezone());
|
|
@@ -364,8 +190,11 @@ let TimeSelect = (_dec = withDeterministicId(), _dec(_class = (_TimeSelect = cla
|
|
|
364
190
|
if (defaultToFirstOption) {
|
|
365
191
|
return options[0];
|
|
366
192
|
}
|
|
367
|
-
return
|
|
193
|
+
return undefined;
|
|
368
194
|
}
|
|
195
|
+
getOption = (field, value, options = this.state.options) => {
|
|
196
|
+
return options.find(option => option[field] === value);
|
|
197
|
+
};
|
|
369
198
|
getBaseDate() {
|
|
370
199
|
let baseDate;
|
|
371
200
|
const baseValue = this.props.value || this.props.defaultValue;
|
|
@@ -403,7 +232,6 @@ let TimeSelect = (_dec = withDeterministicId(), _dec(_class = (_TimeSelect = cla
|
|
|
403
232
|
return options;
|
|
404
233
|
}
|
|
405
234
|
filterOptions(inputValue) {
|
|
406
|
-
var _this$state3;
|
|
407
235
|
let inputNoSeconds = inputValue;
|
|
408
236
|
// if the input contains seconds disregard them (e.g. if format = LTS)
|
|
409
237
|
if (inputValue.length > 5) {
|
|
@@ -417,25 +245,199 @@ let TimeSelect = (_dec = withDeterministicId(), _dec(_class = (_TimeSelect = cla
|
|
|
417
245
|
}
|
|
418
246
|
}
|
|
419
247
|
if (this.props.allowNonStepInput && inputNoSeconds.length < 3) {
|
|
420
|
-
var _this$state2;
|
|
421
248
|
// could show too many results, show only step values
|
|
422
|
-
return
|
|
249
|
+
return this.state?.options.filter(option => {
|
|
423
250
|
return option.label.toLowerCase().startsWith(inputNoSeconds.toLowerCase()) && option.value.minute() % this.props.step == 0;
|
|
424
251
|
});
|
|
425
252
|
}
|
|
426
|
-
return
|
|
253
|
+
return this.state?.options.filter(option => option.label.toLowerCase().startsWith(inputNoSeconds.toLowerCase()));
|
|
427
254
|
}
|
|
255
|
+
handleRef = node => {
|
|
256
|
+
this.ref = node;
|
|
257
|
+
};
|
|
258
|
+
handleBlur = event => {
|
|
259
|
+
this.props.onBlur?.(event);
|
|
260
|
+
};
|
|
261
|
+
handleInputChange = event => {
|
|
262
|
+
const value = event.target.value;
|
|
263
|
+
const newOptions = this.filterOptions(value);
|
|
264
|
+
if (newOptions?.length == 1) {
|
|
265
|
+
// if there is only 1 option, it will be automatically selected except
|
|
266
|
+
// if in controlled mode (it would commit this change)
|
|
267
|
+
if (!this.isControlled) {
|
|
268
|
+
this.setState({
|
|
269
|
+
selectedOptionId: newOptions[0].id
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
this.setState({
|
|
273
|
+
fireChangeOnBlur: newOptions[0]
|
|
274
|
+
});
|
|
275
|
+
} else {
|
|
276
|
+
this.setState({
|
|
277
|
+
fireChangeOnBlur: undefined,
|
|
278
|
+
isInputCleared: this.props.allowClearingSelection && value === ''
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
this.setState({
|
|
282
|
+
inputValue: value,
|
|
283
|
+
filteredOptions: newOptions,
|
|
284
|
+
highlightedOptionId: newOptions.length > 0 ? newOptions[0].id : undefined,
|
|
285
|
+
isShowingOptions: true
|
|
286
|
+
});
|
|
287
|
+
if (!this.state.isShowingOptions) {
|
|
288
|
+
this.props.onShowOptions?.(event);
|
|
289
|
+
}
|
|
290
|
+
const inputAsDate = this.parseInputText(value);
|
|
291
|
+
this.props.onInputChange?.(event, value, inputAsDate.isValid() ? inputAsDate.toISOString() : undefined);
|
|
292
|
+
};
|
|
293
|
+
onKeyDown = event => {
|
|
294
|
+
const input = this.parseInputText(this.state.inputValue);
|
|
295
|
+
if (event.key === 'Enter' && this.props.allowNonStepInput && input.isValid()) {
|
|
296
|
+
this.setState(() => ({
|
|
297
|
+
isShowingOptions: false,
|
|
298
|
+
highlightedOptionId: undefined
|
|
299
|
+
}));
|
|
300
|
+
// others are set in handleBlurOrEsc
|
|
301
|
+
}
|
|
302
|
+
this.props.onKeyDown?.(event);
|
|
303
|
+
};
|
|
304
|
+
handleShowOptions = event => {
|
|
305
|
+
this.setState({
|
|
306
|
+
isShowingOptions: true,
|
|
307
|
+
highlightedOptionId: this.state.selectedOptionId
|
|
308
|
+
});
|
|
309
|
+
this.props.onShowOptions?.(event);
|
|
310
|
+
if (event.type.startsWith('key')) {
|
|
311
|
+
const keyboardEvent = event;
|
|
312
|
+
const children = this.state.filteredOptions;
|
|
313
|
+
if (!this.state.inputValue && children.length > 0 && !this.props.allowClearingSelection) {
|
|
314
|
+
const optionId = keyboardEvent.key === 'ArrowDown' ? children[0].id : keyboardEvent.key === 'ArrowUp' ? children[children.length - 1].id : undefined;
|
|
315
|
+
optionId && this.setState({
|
|
316
|
+
highlightedOptionId: optionId
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
// Called when the input is blurred (=when clicking outside, tabbing away),
|
|
323
|
+
// when pressing ESC. NOT called when an item is selected via Enter/click,
|
|
324
|
+
// (but in this case it will be called later when the input is blurred.)
|
|
325
|
+
handleBlurOrEsc = event => {
|
|
326
|
+
const {
|
|
327
|
+
selectedOptionId,
|
|
328
|
+
inputValue,
|
|
329
|
+
isInputCleared
|
|
330
|
+
} = this.state;
|
|
331
|
+
let defaultValue = '';
|
|
332
|
+
if (this.props.defaultValue) {
|
|
333
|
+
const date = DateTime.parse(this.props.defaultValue, this.locale(), this.timezone());
|
|
334
|
+
defaultValue = this.props.format ? date.format(this.props.format) : date.toISOString();
|
|
335
|
+
}
|
|
336
|
+
const selectedOption = this.getOption('id', selectedOptionId);
|
|
337
|
+
let newInputValue = defaultValue;
|
|
338
|
+
// if input was completely cleared, ensure it stays clear
|
|
339
|
+
// e.g. defaultValue defined, but no selection yet made
|
|
340
|
+
if (inputValue === '' && this.props.allowClearingSelection) {
|
|
341
|
+
newInputValue = '';
|
|
342
|
+
} else if (selectedOption) {
|
|
343
|
+
// If there is a selected option use its value in the input field.
|
|
344
|
+
newInputValue = selectedOption.label;
|
|
345
|
+
} else if (this.props.value) {
|
|
346
|
+
// If controlled and input is cleared and blurred after the first render, it should revert to value
|
|
347
|
+
const date = DateTime.parse(this.props.value, this.locale(), this.timezone());
|
|
348
|
+
newInputValue = this.props.format ? date.format(this.props.format) : date.toISOString();
|
|
349
|
+
}
|
|
350
|
+
this.setState(() => ({
|
|
351
|
+
isShowingOptions: false,
|
|
352
|
+
highlightedOptionId: undefined,
|
|
353
|
+
inputValue: newInputValue,
|
|
354
|
+
filteredOptions: this.filterOptions('')
|
|
355
|
+
}));
|
|
356
|
+
if (this.state.fireChangeOnBlur && event.key !== 'Escape') {
|
|
357
|
+
this.setState(() => ({
|
|
358
|
+
fireChangeOnBlur: undefined
|
|
359
|
+
}));
|
|
360
|
+
this.props.onChange?.(event, {
|
|
361
|
+
value: this.state.fireChangeOnBlur.value.toISOString(),
|
|
362
|
+
inputText: this.state.fireChangeOnBlur.label
|
|
363
|
+
});
|
|
364
|
+
} else if (isInputCleared && event.key !== 'Escape' && this.props.allowClearingSelection) {
|
|
365
|
+
this.setState(() => ({
|
|
366
|
+
isInputCleared: false
|
|
367
|
+
}));
|
|
368
|
+
this.props.onChange?.(event, {
|
|
369
|
+
value: '',
|
|
370
|
+
inputText: ''
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
// TODO only fire this if handleSelectOption was not called before.
|
|
374
|
+
this.props.onHideOptions?.(event);
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
// Called when an option is selected via mouse click or Enter.
|
|
378
|
+
handleSelectOption = (event, data) => {
|
|
379
|
+
if (data.id === this._emptyOptionId) {
|
|
380
|
+
this.setState({
|
|
381
|
+
isShowingOptions: false
|
|
382
|
+
});
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const selectedOption = this.getOption('id', data.id);
|
|
386
|
+
let newInputValue;
|
|
387
|
+
const currentSelectedOptionId = this.state.selectedOptionId;
|
|
388
|
+
|
|
389
|
+
// Focus needs to be reapplied to input
|
|
390
|
+
// after selecting an item to make sure VoiceOver behaves correctly on iOS
|
|
391
|
+
if (utils.isAndroidOrIOS()) {
|
|
392
|
+
this.blur();
|
|
393
|
+
this.focus();
|
|
394
|
+
}
|
|
395
|
+
if (this.isControlled) {
|
|
396
|
+
// in controlled mode we leave to the user to set the value of the
|
|
397
|
+
// component e.g. in the onChange event handler.
|
|
398
|
+
// This is accomplished by not setting a selectedOptionId
|
|
399
|
+
const prev = this.getOption('id', this.state.selectedOptionId);
|
|
400
|
+
newInputValue = prev ? prev.label : '';
|
|
401
|
+
this.setState({
|
|
402
|
+
isShowingOptions: false
|
|
403
|
+
});
|
|
404
|
+
} else {
|
|
405
|
+
newInputValue = selectedOption.label;
|
|
406
|
+
this.setState({
|
|
407
|
+
isShowingOptions: false,
|
|
408
|
+
selectedOptionId: data.id,
|
|
409
|
+
inputValue: newInputValue
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
if (data.id !== currentSelectedOptionId) {
|
|
413
|
+
this.props.onChange?.(event, {
|
|
414
|
+
value: selectedOption.value.toISOString(),
|
|
415
|
+
inputText: newInputValue
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
this.props.onHideOptions?.(event);
|
|
419
|
+
};
|
|
420
|
+
handleHighlightOption = (_event, data) => {
|
|
421
|
+
if (data.id === this._emptyOptionId) return;
|
|
422
|
+
this.setState(state => ({
|
|
423
|
+
highlightedOptionId: data.id,
|
|
424
|
+
inputValue: state.inputValue
|
|
425
|
+
}));
|
|
426
|
+
};
|
|
428
427
|
renderOptions() {
|
|
429
|
-
const
|
|
430
|
-
filteredOptions
|
|
431
|
-
highlightedOptionId
|
|
432
|
-
selectedOptionId
|
|
428
|
+
const {
|
|
429
|
+
filteredOptions,
|
|
430
|
+
highlightedOptionId,
|
|
431
|
+
selectedOptionId
|
|
432
|
+
} = this.state;
|
|
433
433
|
if (filteredOptions.length < 1) {
|
|
434
434
|
return this.renderEmptyOption();
|
|
435
435
|
}
|
|
436
436
|
return filteredOptions.map(option => {
|
|
437
|
-
const
|
|
438
|
-
|
|
437
|
+
const {
|
|
438
|
+
id,
|
|
439
|
+
label
|
|
440
|
+
} = option;
|
|
439
441
|
return _jsx(Select.Option, {
|
|
440
442
|
id: id,
|
|
441
443
|
isHighlighted: id === highlightedOptionId,
|
|
@@ -452,37 +454,47 @@ let TimeSelect = (_dec = withDeterministicId(), _dec(_class = (_TimeSelect = cla
|
|
|
452
454
|
children: callRenderProp(this.props.renderEmptyOption)
|
|
453
455
|
});
|
|
454
456
|
}
|
|
457
|
+
parseInputText = inputValue => {
|
|
458
|
+
const input = DateTime.parse(inputValue, this.locale(), this.timezone(), [this.props.format], true);
|
|
459
|
+
const baseDate = this.getBaseDate();
|
|
460
|
+
input.year(baseDate.year());
|
|
461
|
+
input.month(baseDate.month());
|
|
462
|
+
input.date(baseDate.date());
|
|
463
|
+
return input;
|
|
464
|
+
};
|
|
455
465
|
render() {
|
|
456
|
-
const
|
|
457
|
-
value
|
|
458
|
-
defaultValue
|
|
459
|
-
placeholder
|
|
460
|
-
renderLabel
|
|
461
|
-
inputRef
|
|
462
|
-
id
|
|
463
|
-
listRef
|
|
464
|
-
renderBeforeInput
|
|
465
|
-
renderAfterInput
|
|
466
|
-
isRequired
|
|
467
|
-
isInline
|
|
468
|
-
width
|
|
469
|
-
format
|
|
470
|
-
step
|
|
471
|
-
optionsMaxWidth
|
|
472
|
-
visibleOptionsCount
|
|
473
|
-
messages
|
|
474
|
-
placement
|
|
475
|
-
constrain
|
|
476
|
-
onFocus
|
|
477
|
-
onShowOptions
|
|
478
|
-
onHideOptions
|
|
479
|
-
onInputChange
|
|
480
|
-
onKeyDown
|
|
481
|
-
mountNode
|
|
482
|
-
rest
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
466
|
+
const {
|
|
467
|
+
value,
|
|
468
|
+
defaultValue,
|
|
469
|
+
placeholder,
|
|
470
|
+
renderLabel,
|
|
471
|
+
inputRef,
|
|
472
|
+
id,
|
|
473
|
+
listRef,
|
|
474
|
+
renderBeforeInput,
|
|
475
|
+
renderAfterInput,
|
|
476
|
+
isRequired,
|
|
477
|
+
isInline,
|
|
478
|
+
width,
|
|
479
|
+
format,
|
|
480
|
+
step,
|
|
481
|
+
optionsMaxWidth,
|
|
482
|
+
visibleOptionsCount,
|
|
483
|
+
messages,
|
|
484
|
+
placement,
|
|
485
|
+
constrain,
|
|
486
|
+
onFocus,
|
|
487
|
+
onShowOptions,
|
|
488
|
+
onHideOptions,
|
|
489
|
+
onInputChange,
|
|
490
|
+
onKeyDown,
|
|
491
|
+
mountNode,
|
|
492
|
+
...rest
|
|
493
|
+
} = this.props;
|
|
494
|
+
const {
|
|
495
|
+
inputValue,
|
|
496
|
+
isShowingOptions
|
|
497
|
+
} = this.state;
|
|
486
498
|
return _jsx(Select, {
|
|
487
499
|
mountNode: mountNode,
|
|
488
500
|
renderLabel: renderLabel,
|
|
@@ -517,19 +529,6 @@ let TimeSelect = (_dec = withDeterministicId(), _dec(_class = (_TimeSelect = cla
|
|
|
517
529
|
children: isShowingOptions && this.renderOptions()
|
|
518
530
|
});
|
|
519
531
|
}
|
|
520
|
-
}
|
|
521
|
-
defaultToFirstOption: false,
|
|
522
|
-
format: 'LT',
|
|
523
|
-
// see https://momentjs.com/docs/#/displaying/
|
|
524
|
-
step: 30,
|
|
525
|
-
isRequired: false,
|
|
526
|
-
isInline: false,
|
|
527
|
-
visibleOptionsCount: 8,
|
|
528
|
-
placement: 'bottom stretch',
|
|
529
|
-
constrain: 'window',
|
|
530
|
-
renderEmptyOption: '---',
|
|
531
|
-
allowNonStepInput: false,
|
|
532
|
-
allowClearingSelection: false
|
|
533
|
-
}, _TimeSelect.contextType = ApplyLocaleContext, _TimeSelect)) || _class);
|
|
532
|
+
}) || _class);
|
|
534
533
|
export { TimeSelect };
|
|
535
534
|
export default TimeSelect;
|