@momentum-design/components 0.130.8 → 0.131.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/dist/browser/index.js +793 -488
- package/dist/browser/index.js.map +4 -4
- package/dist/components/timepicker/index.d.ts +13 -0
- package/dist/components/timepicker/index.js +10 -0
- package/dist/components/timepicker/timepicker.component.d.ts +328 -0
- package/dist/components/timepicker/timepicker.component.js +1016 -0
- package/dist/components/timepicker/timepicker.constants.d.ts +24 -0
- package/dist/components/timepicker/timepicker.constants.js +24 -0
- package/dist/components/timepicker/timepicker.styles.d.ts +2 -0
- package/dist/components/timepicker/timepicker.styles.js +179 -0
- package/dist/components/timepicker/timepicker.types.d.ts +21 -0
- package/dist/components/timepicker/timepicker.types.js +1 -0
- package/dist/custom-elements.json +1218 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +2 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/react/timepicker/index.d.ts +67 -0
- package/dist/react/timepicker/index.js +74 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1016 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { html, nothing } from 'lit';
|
|
11
|
+
import { property, query, state } from 'lit/decorators.js';
|
|
12
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
13
|
+
import { DataAriaLabelMixin } from '../../utils/mixins/DataAriaLabelMixin';
|
|
14
|
+
import { FormInternalsMixin } from '../../utils/mixins/FormInternalsMixin';
|
|
15
|
+
import { KEYS } from '../../utils/keys';
|
|
16
|
+
import FormfieldWrapper from '../formfieldwrapper/formfieldwrapper.component';
|
|
17
|
+
import { POPOVER_PLACEMENT, TRIGGER, DEFAULTS as POPOVER_DEFAULTS } from '../popover/popover.constants';
|
|
18
|
+
import { ARROW_ICON, DEFAULTS, TIME_FORMAT, TRIGGER_ID, LISTBOX_ID } from './timepicker.constants';
|
|
19
|
+
import styles from './timepicker.styles';
|
|
20
|
+
/**
|
|
21
|
+
* mdc-timepicker is a component that allows users to select a specific time
|
|
22
|
+
* or enter a time manually. It supports both 12-hour and 24-hour formats.
|
|
23
|
+
*
|
|
24
|
+
* The component consists of:
|
|
25
|
+
* - label - describes the time picker field
|
|
26
|
+
* - input field - made up of 2-3 spinbuttons (hours, minutes, optional AM/PM period)
|
|
27
|
+
* - dropdown arrow button - opens a flyout menu with predefined time intervals
|
|
28
|
+
* - helper text - displayed below the input field
|
|
29
|
+
*
|
|
30
|
+
* Users can input values by:
|
|
31
|
+
* - Manually entering numbers/characters in spinbuttons
|
|
32
|
+
* - Navigating using arrow keys to increment/decrement values
|
|
33
|
+
* - Selecting a predefined time from the dropdown menu
|
|
34
|
+
*
|
|
35
|
+
* @tagname mdc-timepicker
|
|
36
|
+
*
|
|
37
|
+
* @dependency mdc-button
|
|
38
|
+
* @dependency mdc-icon
|
|
39
|
+
* @dependency mdc-option
|
|
40
|
+
* @dependency mdc-popover
|
|
41
|
+
* @dependency mdc-text
|
|
42
|
+
* @dependency mdc-toggletip
|
|
43
|
+
*
|
|
44
|
+
* @event input - (React: onInput) This event is dispatched when the time value changes.
|
|
45
|
+
* @event change - (React: onChange) This event is dispatched when the time value is committed.
|
|
46
|
+
* @event focus - (React: onFocus) This event is dispatched when the timepicker receives focus.
|
|
47
|
+
* @event blur - (React: onBlur) This event is dispatched when the timepicker loses focus.
|
|
48
|
+
*
|
|
49
|
+
* @slot label - Slot for the label element.
|
|
50
|
+
* @slot toggletip - Slot for the toggletip info icon button.
|
|
51
|
+
* @slot help-icon - Slot for the helper/validation icon.
|
|
52
|
+
* @slot help-text - Slot for the helper/validation text.
|
|
53
|
+
*
|
|
54
|
+
* @cssproperty --mdc-timepicker-background-color - Background color of the timepicker input.
|
|
55
|
+
* @cssproperty --mdc-timepicker-border-color - Border color of the timepicker input.
|
|
56
|
+
* @cssproperty --mdc-timepicker-text-color - Text color of the timepicker input.
|
|
57
|
+
* @cssproperty --mdc-timepicker-width - Width of the timepicker component.
|
|
58
|
+
*
|
|
59
|
+
* @csspart label - The label element.
|
|
60
|
+
* @csspart label-text - The container for the label and required indicator elements.
|
|
61
|
+
* @csspart required-indicator - The required indicator element.
|
|
62
|
+
* @csspart info-icon-btn - The info icon button element.
|
|
63
|
+
* @csspart label-toggletip - The toggletip element.
|
|
64
|
+
* @csspart help-text - The helper/validation text element.
|
|
65
|
+
* @csspart helper-icon - The helper/validation icon element.
|
|
66
|
+
* @csspart help-text-container - The container for helper/validation elements.
|
|
67
|
+
* @csspart container - The outer container for the input and popover.
|
|
68
|
+
* @csspart base-container - The input container with border and background.
|
|
69
|
+
* @csspart spinbutton-group - The container for spinbutton elements.
|
|
70
|
+
* @csspart spinbutton - A spinbutton input element.
|
|
71
|
+
* @csspart separator - The colon separator between spinbuttons.
|
|
72
|
+
* @csspart period - The AM/PM period spinbutton.
|
|
73
|
+
* @csspart icon-container - The dropdown arrow button container.
|
|
74
|
+
* @csspart native-input - The hidden native input for form participation.
|
|
75
|
+
* @csspart listbox - The dropdown list container.
|
|
76
|
+
*/
|
|
77
|
+
class TimePicker extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
|
|
78
|
+
constructor() {
|
|
79
|
+
super(...arguments);
|
|
80
|
+
/**
|
|
81
|
+
* The time format to use for display.
|
|
82
|
+
* - `'12h'`: 12-hour format with AM/PM period
|
|
83
|
+
* - `'24h'`: 24-hour format without period
|
|
84
|
+
* @default '12h'
|
|
85
|
+
*/
|
|
86
|
+
this.timeFormat = DEFAULTS.TIME_FORMAT;
|
|
87
|
+
/**
|
|
88
|
+
* The interval in minutes between time options in the dropdown menu.
|
|
89
|
+
* @default 30
|
|
90
|
+
*/
|
|
91
|
+
this.interval = DEFAULTS.INTERVAL;
|
|
92
|
+
/**
|
|
93
|
+
* The placement of the popover dropdown.
|
|
94
|
+
* @default 'bottom-start'
|
|
95
|
+
*/
|
|
96
|
+
this.placement = POPOVER_PLACEMENT.BOTTOM_START;
|
|
97
|
+
/**
|
|
98
|
+
* The strategy for positioning the popover.
|
|
99
|
+
* @default 'absolute'
|
|
100
|
+
*/
|
|
101
|
+
this.strategy = POPOVER_DEFAULTS.STRATEGY;
|
|
102
|
+
/**
|
|
103
|
+
* Determines whether the dropdown should flip its position when it hits the boundary.
|
|
104
|
+
* @default false
|
|
105
|
+
*/
|
|
106
|
+
this.disableFlip = DEFAULTS.DISABLE_FLIP;
|
|
107
|
+
/**
|
|
108
|
+
* Accessible label for the hours spinbutton.
|
|
109
|
+
* Consumers must provide a translated string.
|
|
110
|
+
*/
|
|
111
|
+
this.localeHoursLabel = '';
|
|
112
|
+
/**
|
|
113
|
+
* Accessible label for the minutes spinbutton.
|
|
114
|
+
* Consumers must provide a translated string.
|
|
115
|
+
*/
|
|
116
|
+
this.localeMinutesLabel = '';
|
|
117
|
+
/**
|
|
118
|
+
* Accessible label for the period (AM/PM) spinbutton.
|
|
119
|
+
* Consumers must provide a translated string.
|
|
120
|
+
*/
|
|
121
|
+
this.localePeriodLabel = '';
|
|
122
|
+
/**
|
|
123
|
+
* Placeholder text for the hours spinbutton.
|
|
124
|
+
* Consumers must provide a translated string.
|
|
125
|
+
*/
|
|
126
|
+
this.localeHoursPlaceholder = '';
|
|
127
|
+
/**
|
|
128
|
+
* Placeholder text for the minutes spinbutton.
|
|
129
|
+
* Consumers must provide a translated string.
|
|
130
|
+
*/
|
|
131
|
+
this.localeMinutesPlaceholder = '';
|
|
132
|
+
/**
|
|
133
|
+
* Placeholder text for the period spinbutton.
|
|
134
|
+
* Consumers must provide a translated string.
|
|
135
|
+
*/
|
|
136
|
+
this.localePeriodPlaceholder = '';
|
|
137
|
+
/**
|
|
138
|
+
* Label for the AM period.
|
|
139
|
+
* Consumers must provide a translated string.
|
|
140
|
+
*/
|
|
141
|
+
this.localeAmLabel = '';
|
|
142
|
+
/**
|
|
143
|
+
* Label for the PM period.
|
|
144
|
+
* Consumers must provide a translated string.
|
|
145
|
+
*/
|
|
146
|
+
this.localePmLabel = '';
|
|
147
|
+
/**
|
|
148
|
+
* Accessible label for the dropdown toggle button.
|
|
149
|
+
* Consumers must provide a translated string.
|
|
150
|
+
*/
|
|
151
|
+
this.localeShowTimePickerLabel = '';
|
|
152
|
+
/**
|
|
153
|
+
* Accessible label for the time options listbox.
|
|
154
|
+
* Consumers must provide a translated string.
|
|
155
|
+
*/
|
|
156
|
+
this.localeTimeOptionsLabel = '';
|
|
157
|
+
/**
|
|
158
|
+
* Accessible description for spinbutton inputs (instruction text).
|
|
159
|
+
* Consumers must provide a translated string.
|
|
160
|
+
*/
|
|
161
|
+
this.localeSpinbuttonDescription = '';
|
|
162
|
+
/** @internal */
|
|
163
|
+
this.displayPopover = false;
|
|
164
|
+
/** @internal */
|
|
165
|
+
this.internalHours = '';
|
|
166
|
+
/** @internal */
|
|
167
|
+
this.internalMinutes = '';
|
|
168
|
+
/** @internal */
|
|
169
|
+
this.internalPeriod = 'AM';
|
|
170
|
+
/** @internal */
|
|
171
|
+
this.focusedOptionIndex = -1;
|
|
172
|
+
/** @internal */
|
|
173
|
+
this.pendingDigits = '';
|
|
174
|
+
}
|
|
175
|
+
connectedCallback() {
|
|
176
|
+
super.connectedCallback();
|
|
177
|
+
this.updateComplete
|
|
178
|
+
.then(() => {
|
|
179
|
+
this.parseValueToInternal();
|
|
180
|
+
this.syncFormValue();
|
|
181
|
+
})
|
|
182
|
+
.catch(error => {
|
|
183
|
+
if (this.onerror) {
|
|
184
|
+
this.onerror(error);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
disconnectedCallback() {
|
|
189
|
+
super.disconnectedCallback();
|
|
190
|
+
if (this.pendingDigitTimeout) {
|
|
191
|
+
clearTimeout(this.pendingDigitTimeout);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
willUpdate(changedProperties) {
|
|
195
|
+
super.willUpdate(changedProperties);
|
|
196
|
+
if (changedProperties.has('value') && !this.displayPopover) {
|
|
197
|
+
this.parseValueToInternal();
|
|
198
|
+
this.syncFormValue();
|
|
199
|
+
}
|
|
200
|
+
if (changedProperties.has('disabled') ||
|
|
201
|
+
changedProperties.has('softDisabled') ||
|
|
202
|
+
changedProperties.has('readonly')) {
|
|
203
|
+
if (this.disabled || this.softDisabled || this.readonly) {
|
|
204
|
+
this.displayPopover = false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
updated(changedProperties) {
|
|
209
|
+
super.updated(changedProperties);
|
|
210
|
+
if (changedProperties.has('displayPopover') && this.displayPopover) {
|
|
211
|
+
this.focusMenuItemOnOpen();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* When the menu opens, focus the selected item or the first item.
|
|
216
|
+
* @internal
|
|
217
|
+
*/
|
|
218
|
+
focusMenuItemOnOpen() {
|
|
219
|
+
const options = this.getTimeOptions();
|
|
220
|
+
const currentValue = this.internalToValue();
|
|
221
|
+
const selectedIndex = options.findIndex(opt => opt.value === currentValue);
|
|
222
|
+
this.focusedOptionIndex = selectedIndex >= 0 ? selectedIndex : 0;
|
|
223
|
+
this.updateComplete
|
|
224
|
+
.then(() => {
|
|
225
|
+
this.focusCurrentMenuItem();
|
|
226
|
+
})
|
|
227
|
+
.catch(() => { });
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Focuses the menu item at the current focusedOptionIndex.
|
|
231
|
+
* @internal
|
|
232
|
+
*/
|
|
233
|
+
focusCurrentMenuItem() {
|
|
234
|
+
var _a;
|
|
235
|
+
const listbox = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(`#${LISTBOX_ID}`);
|
|
236
|
+
if (!listbox)
|
|
237
|
+
return;
|
|
238
|
+
const items = listbox.querySelectorAll('mdc-option');
|
|
239
|
+
if (items[this.focusedOptionIndex]) {
|
|
240
|
+
items[this.focusedOptionIndex].focus();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/** @internal */
|
|
244
|
+
formResetCallback() {
|
|
245
|
+
this.value = '';
|
|
246
|
+
this.internalHours = '';
|
|
247
|
+
this.internalMinutes = '';
|
|
248
|
+
this.internalPeriod = 'AM';
|
|
249
|
+
this.syncFormValue();
|
|
250
|
+
this.requestUpdate();
|
|
251
|
+
}
|
|
252
|
+
/** @internal */
|
|
253
|
+
formStateRestoreCallback(state) {
|
|
254
|
+
this.value = state;
|
|
255
|
+
this.parseValueToInternal();
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Parses the value (24h HH:MM) into internal hours, minutes, and period.
|
|
259
|
+
* @internal
|
|
260
|
+
*/
|
|
261
|
+
parseValueToInternal() {
|
|
262
|
+
if (!this.value) {
|
|
263
|
+
this.internalHours = '';
|
|
264
|
+
this.internalMinutes = '';
|
|
265
|
+
this.internalPeriod = 'AM';
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const match = this.value.match(/^(\d{1,2}):(\d{2})$/);
|
|
269
|
+
if (!match)
|
|
270
|
+
return;
|
|
271
|
+
const hours = parseInt(match[1], 10);
|
|
272
|
+
const minutes = parseInt(match[2], 10);
|
|
273
|
+
if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59)
|
|
274
|
+
return;
|
|
275
|
+
this.internalMinutes = String(minutes).padStart(2, '0');
|
|
276
|
+
if (this.timeFormat === TIME_FORMAT.TWELVE_HOUR) {
|
|
277
|
+
if (hours === 0) {
|
|
278
|
+
this.internalPeriod = 'AM';
|
|
279
|
+
this.internalHours = '12';
|
|
280
|
+
}
|
|
281
|
+
else if (hours < 12) {
|
|
282
|
+
this.internalPeriod = 'AM';
|
|
283
|
+
this.internalHours = String(hours).padStart(2, '0');
|
|
284
|
+
}
|
|
285
|
+
else if (hours === 12) {
|
|
286
|
+
this.internalPeriod = 'PM';
|
|
287
|
+
this.internalHours = '12';
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
this.internalPeriod = 'PM';
|
|
291
|
+
this.internalHours = String(hours - 12).padStart(2, '0');
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
this.internalHours = String(hours).padStart(2, '0');
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Converts internal hours, minutes, and period to 24h HH:MM value.
|
|
300
|
+
* @internal
|
|
301
|
+
*/
|
|
302
|
+
internalToValue() {
|
|
303
|
+
if (!this.internalHours || !this.internalMinutes)
|
|
304
|
+
return '';
|
|
305
|
+
let hours = parseInt(this.internalHours, 10);
|
|
306
|
+
if (this.timeFormat === TIME_FORMAT.TWELVE_HOUR) {
|
|
307
|
+
if (this.internalPeriod === 'AM') {
|
|
308
|
+
hours = hours === 12 ? 0 : hours;
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
hours = hours === 12 ? 12 : hours + 12;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return `${String(hours).padStart(2, '0')}:${this.internalMinutes}`;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Syncs the form value with the current internal state.
|
|
318
|
+
* @internal
|
|
319
|
+
*/
|
|
320
|
+
syncFormValue() {
|
|
321
|
+
const val = this.internalToValue();
|
|
322
|
+
this.internals.setFormValue(val || this.value);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Updates the value from internal state and fires events.
|
|
326
|
+
* @internal
|
|
327
|
+
*/
|
|
328
|
+
commitValue() {
|
|
329
|
+
const newValue = this.internalToValue();
|
|
330
|
+
if (newValue && newValue !== this.value) {
|
|
331
|
+
this.value = newValue;
|
|
332
|
+
this.syncFormValue();
|
|
333
|
+
this.dispatchEvent(new CustomEvent('input', {
|
|
334
|
+
detail: { value: this.value },
|
|
335
|
+
composed: true,
|
|
336
|
+
bubbles: true,
|
|
337
|
+
}));
|
|
338
|
+
this.dispatchEvent(new CustomEvent('change', {
|
|
339
|
+
detail: { value: this.value },
|
|
340
|
+
composed: true,
|
|
341
|
+
bubbles: true,
|
|
342
|
+
}));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Generates time interval options for the dropdown.
|
|
347
|
+
* @internal
|
|
348
|
+
*/
|
|
349
|
+
getTimeOptions() {
|
|
350
|
+
const options = [];
|
|
351
|
+
const interval = Math.max(1, Math.min(this.interval, 60));
|
|
352
|
+
for (let totalMinutes = 0; totalMinutes < 24 * 60; totalMinutes += interval) {
|
|
353
|
+
const h = Math.floor(totalMinutes / 60);
|
|
354
|
+
const m = totalMinutes % 60;
|
|
355
|
+
const value24 = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
|
|
356
|
+
let label;
|
|
357
|
+
if (this.timeFormat === TIME_FORMAT.TWELVE_HOUR) {
|
|
358
|
+
const period = h < 12 ? this.localeAmLabel : this.localePmLabel;
|
|
359
|
+
let displayHour = h % 12;
|
|
360
|
+
if (displayHour === 0)
|
|
361
|
+
displayHour = 12;
|
|
362
|
+
const displayMin = m === 0 ? '00' : String(m);
|
|
363
|
+
label = `${displayHour}:${displayMin} ${period}`;
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
label = `${h}:${String(m).padStart(2, '0')}`;
|
|
367
|
+
}
|
|
368
|
+
// Filter by min/max if provided
|
|
369
|
+
const withinMin = !this.min || value24 >= this.min;
|
|
370
|
+
const withinMax = !this.max || value24 <= this.max;
|
|
371
|
+
if (withinMin && withinMax) {
|
|
372
|
+
options.push({ label, value: value24 });
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return options;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Handles clicking on a time option in the dropdown.
|
|
379
|
+
* @internal
|
|
380
|
+
*/
|
|
381
|
+
handleOptionClick(optionValue) {
|
|
382
|
+
var _a;
|
|
383
|
+
this.value = optionValue;
|
|
384
|
+
this.parseValueToInternal();
|
|
385
|
+
this.displayPopover = false;
|
|
386
|
+
this.syncFormValue();
|
|
387
|
+
this.dispatchEvent(new CustomEvent('input', {
|
|
388
|
+
detail: { value: this.value },
|
|
389
|
+
composed: true,
|
|
390
|
+
bubbles: true,
|
|
391
|
+
}));
|
|
392
|
+
this.dispatchEvent(new CustomEvent('change', {
|
|
393
|
+
detail: { value: this.value },
|
|
394
|
+
composed: true,
|
|
395
|
+
bubbles: true,
|
|
396
|
+
}));
|
|
397
|
+
// Return focus to the dropdown button
|
|
398
|
+
(_a = this.dropdownButton) === null || _a === void 0 ? void 0 : _a.focus();
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Handles clicking the dropdown arrow button.
|
|
402
|
+
* @internal
|
|
403
|
+
*/
|
|
404
|
+
handleDropdownClick(event) {
|
|
405
|
+
if (this.disabled || this.softDisabled || this.readonly)
|
|
406
|
+
return;
|
|
407
|
+
this.displayPopover = !this.displayPopover;
|
|
408
|
+
event.stopPropagation();
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Handles clicking on the spinbutton area (not the dropdown button).
|
|
412
|
+
* Focuses the nearest spinbutton.
|
|
413
|
+
* @internal
|
|
414
|
+
*/
|
|
415
|
+
handleSpinbuttonAreaClick(event) {
|
|
416
|
+
var _a, _b;
|
|
417
|
+
if (this.disabled || this.softDisabled || this.readonly)
|
|
418
|
+
return;
|
|
419
|
+
const target = event.target;
|
|
420
|
+
// If clicking on a spinbutton itself, let it handle focus
|
|
421
|
+
if (target.getAttribute('role') === 'spinbutton')
|
|
422
|
+
return;
|
|
423
|
+
// Otherwise focus the hours spinbutton
|
|
424
|
+
(_a = this.hoursInput) === null || _a === void 0 ? void 0 : _a.focus();
|
|
425
|
+
(_b = this.hoursInput) === null || _b === void 0 ? void 0 : _b.select();
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Handles keydown on the base container (when popover is closed).
|
|
429
|
+
* @internal
|
|
430
|
+
*/
|
|
431
|
+
handleBaseKeydown(event) {
|
|
432
|
+
var _a;
|
|
433
|
+
if (this.disabled || this.softDisabled || this.readonly)
|
|
434
|
+
return;
|
|
435
|
+
if (event.key === KEYS.ESCAPE && this.displayPopover) {
|
|
436
|
+
this.displayPopover = false;
|
|
437
|
+
(_a = this.dropdownButton) === null || _a === void 0 ? void 0 : _a.focus();
|
|
438
|
+
event.preventDefault();
|
|
439
|
+
event.stopPropagation();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Handles keydown on the popover/listbox (when open).
|
|
444
|
+
* Supports ArrowDown/ArrowUp to navigate, Enter to select, Escape to close.
|
|
445
|
+
* @internal
|
|
446
|
+
*/
|
|
447
|
+
handleListboxKeydown(event) {
|
|
448
|
+
var _a;
|
|
449
|
+
const options = this.getTimeOptions();
|
|
450
|
+
const optionCount = options.length;
|
|
451
|
+
if (optionCount === 0)
|
|
452
|
+
return;
|
|
453
|
+
switch (event.key) {
|
|
454
|
+
case KEYS.ARROW_DOWN: {
|
|
455
|
+
event.preventDefault();
|
|
456
|
+
event.stopPropagation();
|
|
457
|
+
this.focusedOptionIndex = (this.focusedOptionIndex + 1) % optionCount;
|
|
458
|
+
this.focusCurrentMenuItem();
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
case KEYS.ARROW_UP: {
|
|
462
|
+
event.preventDefault();
|
|
463
|
+
event.stopPropagation();
|
|
464
|
+
this.focusedOptionIndex = (this.focusedOptionIndex - 1 + optionCount) % optionCount;
|
|
465
|
+
this.focusCurrentMenuItem();
|
|
466
|
+
break;
|
|
467
|
+
}
|
|
468
|
+
case KEYS.ENTER: {
|
|
469
|
+
event.preventDefault();
|
|
470
|
+
event.stopPropagation();
|
|
471
|
+
if (this.focusedOptionIndex >= 0 && this.focusedOptionIndex < optionCount) {
|
|
472
|
+
this.handleOptionClick(options[this.focusedOptionIndex].value);
|
|
473
|
+
}
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
case KEYS.ESCAPE: {
|
|
477
|
+
event.preventDefault();
|
|
478
|
+
event.stopPropagation();
|
|
479
|
+
this.displayPopover = false;
|
|
480
|
+
(_a = this.dropdownButton) === null || _a === void 0 ? void 0 : _a.focus();
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
default:
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Handles keydown on the hours spinbutton.
|
|
489
|
+
* @internal
|
|
490
|
+
*/
|
|
491
|
+
handleHoursKeydown(event) {
|
|
492
|
+
this.handleSpinbuttonKeydown(event, 'hours');
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Handles keydown on the minutes spinbutton.
|
|
496
|
+
* @internal
|
|
497
|
+
*/
|
|
498
|
+
handleMinutesKeydown(event) {
|
|
499
|
+
this.handleSpinbuttonKeydown(event, 'minutes');
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Handles keydown on the period spinbutton.
|
|
503
|
+
* @internal
|
|
504
|
+
*/
|
|
505
|
+
handlePeriodKeydown(event) {
|
|
506
|
+
var _a, _b;
|
|
507
|
+
switch (event.key) {
|
|
508
|
+
case KEYS.ARROW_UP:
|
|
509
|
+
case KEYS.ARROW_DOWN:
|
|
510
|
+
event.preventDefault();
|
|
511
|
+
this.internalPeriod = this.internalPeriod === 'AM' ? 'PM' : 'AM';
|
|
512
|
+
this.commitValue();
|
|
513
|
+
this.requestUpdate();
|
|
514
|
+
break;
|
|
515
|
+
case KEYS.TAB:
|
|
516
|
+
// Allow default tab behavior
|
|
517
|
+
break;
|
|
518
|
+
case KEYS.ARROW_LEFT:
|
|
519
|
+
event.preventDefault();
|
|
520
|
+
(_a = this.minutesInput) === null || _a === void 0 ? void 0 : _a.focus();
|
|
521
|
+
(_b = this.minutesInput) === null || _b === void 0 ? void 0 : _b.select();
|
|
522
|
+
break;
|
|
523
|
+
default: {
|
|
524
|
+
event.preventDefault();
|
|
525
|
+
const amChar = this.localeAmLabel.charAt(0).toLowerCase();
|
|
526
|
+
const pmChar = this.localePmLabel.charAt(0).toLowerCase();
|
|
527
|
+
const pressed = event.key.toLowerCase();
|
|
528
|
+
if (pressed === amChar) {
|
|
529
|
+
this.internalPeriod = 'AM';
|
|
530
|
+
this.commitValue();
|
|
531
|
+
this.requestUpdate();
|
|
532
|
+
}
|
|
533
|
+
else if (pressed === pmChar) {
|
|
534
|
+
this.internalPeriod = 'PM';
|
|
535
|
+
this.commitValue();
|
|
536
|
+
this.requestUpdate();
|
|
537
|
+
}
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Generic spinbutton keydown handler for hours and minutes.
|
|
544
|
+
* @internal
|
|
545
|
+
*/
|
|
546
|
+
handleSpinbuttonKeydown(event, field) {
|
|
547
|
+
var _a, _b, _c, _d, _e, _f;
|
|
548
|
+
const is12h = this.timeFormat === TIME_FORMAT.TWELVE_HOUR;
|
|
549
|
+
let minVal;
|
|
550
|
+
let maxVal;
|
|
551
|
+
if (field === 'hours') {
|
|
552
|
+
minVal = is12h ? DEFAULTS.MIN_HOUR_12 : DEFAULTS.MIN_HOUR_24;
|
|
553
|
+
maxVal = is12h ? DEFAULTS.MAX_HOUR_12 : DEFAULTS.MAX_HOUR_24;
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
minVal = DEFAULTS.MIN_MINUTE;
|
|
557
|
+
maxVal = DEFAULTS.MAX_MINUTE;
|
|
558
|
+
}
|
|
559
|
+
const currentStr = field === 'hours' ? this.internalHours : this.internalMinutes;
|
|
560
|
+
let current = currentStr ? parseInt(currentStr, 10) : minVal;
|
|
561
|
+
switch (event.key) {
|
|
562
|
+
case KEYS.ARROW_UP: {
|
|
563
|
+
event.preventDefault();
|
|
564
|
+
current = current >= maxVal ? minVal : current + 1;
|
|
565
|
+
this.setSpinbuttonValue(field, current);
|
|
566
|
+
this.commitValue();
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
case KEYS.ARROW_DOWN: {
|
|
570
|
+
event.preventDefault();
|
|
571
|
+
current = current <= minVal ? maxVal : current - 1;
|
|
572
|
+
this.setSpinbuttonValue(field, current);
|
|
573
|
+
this.commitValue();
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
case KEYS.ARROW_RIGHT: {
|
|
577
|
+
event.preventDefault();
|
|
578
|
+
if (field === 'hours') {
|
|
579
|
+
(_a = this.minutesInput) === null || _a === void 0 ? void 0 : _a.focus();
|
|
580
|
+
(_b = this.minutesInput) === null || _b === void 0 ? void 0 : _b.select();
|
|
581
|
+
}
|
|
582
|
+
else if (is12h) {
|
|
583
|
+
(_c = this.periodInput) === null || _c === void 0 ? void 0 : _c.focus();
|
|
584
|
+
(_d = this.periodInput) === null || _d === void 0 ? void 0 : _d.select();
|
|
585
|
+
}
|
|
586
|
+
break;
|
|
587
|
+
}
|
|
588
|
+
case KEYS.ARROW_LEFT: {
|
|
589
|
+
event.preventDefault();
|
|
590
|
+
if (field === 'minutes') {
|
|
591
|
+
(_e = this.hoursInput) === null || _e === void 0 ? void 0 : _e.focus();
|
|
592
|
+
(_f = this.hoursInput) === null || _f === void 0 ? void 0 : _f.select();
|
|
593
|
+
}
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
case KEYS.TAB: {
|
|
597
|
+
// Allow default tab behavior for navigation
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
default: {
|
|
601
|
+
// Handle digit input
|
|
602
|
+
if (/^\d$/.test(event.key)) {
|
|
603
|
+
event.preventDefault();
|
|
604
|
+
this.handleDigitInput(event.key, field, minVal, maxVal);
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
event.preventDefault();
|
|
608
|
+
}
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Handles digit input for spinbuttons with auto-advance logic.
|
|
615
|
+
* @internal
|
|
616
|
+
*/
|
|
617
|
+
handleDigitInput(digit, field, minVal, maxVal) {
|
|
618
|
+
if (this.pendingDigitTimeout) {
|
|
619
|
+
clearTimeout(this.pendingDigitTimeout);
|
|
620
|
+
}
|
|
621
|
+
this.pendingDigits += digit;
|
|
622
|
+
if (this.pendingDigits.length >= 2) {
|
|
623
|
+
// Two digits entered - commit and advance
|
|
624
|
+
let val = parseInt(this.pendingDigits, 10);
|
|
625
|
+
if (val > maxVal)
|
|
626
|
+
val = maxVal;
|
|
627
|
+
if (val < minVal)
|
|
628
|
+
val = minVal;
|
|
629
|
+
this.setSpinbuttonValue(field, val);
|
|
630
|
+
this.pendingDigits = '';
|
|
631
|
+
this.commitValue();
|
|
632
|
+
this.advanceToNextField(field);
|
|
633
|
+
}
|
|
634
|
+
else {
|
|
635
|
+
// Single digit - check if we can determine the value needs a second digit
|
|
636
|
+
const firstDigit = parseInt(this.pendingDigits, 10);
|
|
637
|
+
const maxFirstDigit = Math.floor(maxVal / 10);
|
|
638
|
+
if (firstDigit > maxFirstDigit) {
|
|
639
|
+
// Single digit already exceeds max first digit - auto-pad and advance
|
|
640
|
+
let val = firstDigit;
|
|
641
|
+
if (val > maxVal)
|
|
642
|
+
val = maxVal;
|
|
643
|
+
if (val < minVal)
|
|
644
|
+
val = minVal;
|
|
645
|
+
this.setSpinbuttonValue(field, val);
|
|
646
|
+
this.pendingDigits = '';
|
|
647
|
+
this.commitValue();
|
|
648
|
+
this.advanceToNextField(field);
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
// Wait for second digit with timeout
|
|
652
|
+
this.setSpinbuttonValue(field, firstDigit);
|
|
653
|
+
this.pendingDigitTimeout = setTimeout(() => {
|
|
654
|
+
// Auto-pad with leading zero
|
|
655
|
+
let val = firstDigit;
|
|
656
|
+
if (val < minVal)
|
|
657
|
+
val = minVal;
|
|
658
|
+
this.setSpinbuttonValue(field, val);
|
|
659
|
+
this.pendingDigits = '';
|
|
660
|
+
this.commitValue();
|
|
661
|
+
this.advanceToNextField(field);
|
|
662
|
+
}, 1000);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Sets the value of a spinbutton field.
|
|
668
|
+
* @internal
|
|
669
|
+
*/
|
|
670
|
+
setSpinbuttonValue(field, val) {
|
|
671
|
+
const padded = String(val).padStart(2, '0');
|
|
672
|
+
if (field === 'hours') {
|
|
673
|
+
this.internalHours = padded;
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
this.internalMinutes = padded;
|
|
677
|
+
}
|
|
678
|
+
this.requestUpdate();
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Advances focus to the next spinbutton field.
|
|
682
|
+
* @internal
|
|
683
|
+
*/
|
|
684
|
+
advanceToNextField(currentField) {
|
|
685
|
+
if (currentField === 'hours') {
|
|
686
|
+
this.updateComplete
|
|
687
|
+
.then(() => {
|
|
688
|
+
var _a, _b;
|
|
689
|
+
(_a = this.minutesInput) === null || _a === void 0 ? void 0 : _a.focus();
|
|
690
|
+
(_b = this.minutesInput) === null || _b === void 0 ? void 0 : _b.select();
|
|
691
|
+
})
|
|
692
|
+
.catch(() => { });
|
|
693
|
+
}
|
|
694
|
+
else if (this.timeFormat === TIME_FORMAT.TWELVE_HOUR) {
|
|
695
|
+
this.updateComplete
|
|
696
|
+
.then(() => {
|
|
697
|
+
var _a, _b;
|
|
698
|
+
(_a = this.periodInput) === null || _a === void 0 ? void 0 : _a.focus();
|
|
699
|
+
(_b = this.periodInput) === null || _b === void 0 ? void 0 : _b.select();
|
|
700
|
+
})
|
|
701
|
+
.catch(() => { });
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Handles focus on a spinbutton - selects all text.
|
|
706
|
+
* @internal
|
|
707
|
+
*/
|
|
708
|
+
handleSpinbuttonFocus(event) {
|
|
709
|
+
const target = event.target;
|
|
710
|
+
target.select();
|
|
711
|
+
// Clear pending digits when switching fields
|
|
712
|
+
this.pendingDigits = '';
|
|
713
|
+
if (this.pendingDigitTimeout) {
|
|
714
|
+
clearTimeout(this.pendingDigitTimeout);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Gets the display text for the current period using locale labels.
|
|
719
|
+
* @internal
|
|
720
|
+
*/
|
|
721
|
+
get displayPeriod() {
|
|
722
|
+
return this.internalPeriod === 'AM' ? this.localeAmLabel : this.localePmLabel;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Gets the placeholder text for the hours spinbutton.
|
|
726
|
+
* @internal
|
|
727
|
+
*/
|
|
728
|
+
get hoursPlaceholder() {
|
|
729
|
+
return this.localeHoursPlaceholder;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Gets the placeholder text for the minutes spinbutton.
|
|
733
|
+
* @internal
|
|
734
|
+
*/
|
|
735
|
+
get minutesPlaceholder() {
|
|
736
|
+
return this.localeMinutesPlaceholder;
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Gets the placeholder text for the period spinbutton.
|
|
740
|
+
* @internal
|
|
741
|
+
*/
|
|
742
|
+
get periodPlaceholder() {
|
|
743
|
+
return this.localePeriodPlaceholder;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Renders the dropdown time options list using mdc-option components.
|
|
747
|
+
* @internal
|
|
748
|
+
*/
|
|
749
|
+
renderTimeOptions() {
|
|
750
|
+
const options = this.getTimeOptions();
|
|
751
|
+
const currentValue = this.internalToValue();
|
|
752
|
+
return options.map(option => html `
|
|
753
|
+
<mdc-option
|
|
754
|
+
label="${option.label}"
|
|
755
|
+
?selected="${option.value === currentValue}"
|
|
756
|
+
aria-selected="${option.value === currentValue ? 'true' : 'false'}"
|
|
757
|
+
@click="${() => this.handleOptionClick(option.value)}"
|
|
758
|
+
></mdc-option>
|
|
759
|
+
`);
|
|
760
|
+
}
|
|
761
|
+
render() {
|
|
762
|
+
const is12h = this.timeFormat === TIME_FORMAT.TWELVE_HOUR;
|
|
763
|
+
const hoursMin = is12h ? DEFAULTS.MIN_HOUR_12 : DEFAULTS.MIN_HOUR_24;
|
|
764
|
+
const hoursMax = is12h ? DEFAULTS.MAX_HOUR_12 : DEFAULTS.MAX_HOUR_24;
|
|
765
|
+
return html `
|
|
766
|
+
${this.renderLabel()}
|
|
767
|
+
<div part="container">
|
|
768
|
+
<div
|
|
769
|
+
id="${TRIGGER_ID}"
|
|
770
|
+
part="base-container"
|
|
771
|
+
class="mdc-focus-ring"
|
|
772
|
+
@click="${this.handleSpinbuttonAreaClick}"
|
|
773
|
+
@keydown="${this.handleBaseKeydown}"
|
|
774
|
+
>
|
|
775
|
+
<div part="spinbutton-group">
|
|
776
|
+
<input
|
|
777
|
+
id="hours-spinbutton"
|
|
778
|
+
part="spinbutton"
|
|
779
|
+
role="spinbutton"
|
|
780
|
+
aria-label="${this.localeHoursLabel}"
|
|
781
|
+
aria-valuemin="${hoursMin}"
|
|
782
|
+
aria-valuemax="${hoursMax}"
|
|
783
|
+
aria-valuenow="${this.internalHours ? parseInt(this.internalHours, 10) : ''}"
|
|
784
|
+
aria-description="${this.localeSpinbuttonDescription}"
|
|
785
|
+
.value="${this.internalHours}"
|
|
786
|
+
placeholder="${this.hoursPlaceholder}"
|
|
787
|
+
?disabled="${this.disabled}"
|
|
788
|
+
?readonly="${this.readonly}"
|
|
789
|
+
tabindex="${this.disabled ? '-1' : '0'}"
|
|
790
|
+
@keydown="${this.handleHoursKeydown}"
|
|
791
|
+
@focus="${this.handleSpinbuttonFocus}"
|
|
792
|
+
/>
|
|
793
|
+
<span part="separator">:</span>
|
|
794
|
+
<input
|
|
795
|
+
id="minutes-spinbutton"
|
|
796
|
+
part="spinbutton"
|
|
797
|
+
role="spinbutton"
|
|
798
|
+
aria-label="${this.localeMinutesLabel}"
|
|
799
|
+
aria-valuemin="${DEFAULTS.MIN_MINUTE}"
|
|
800
|
+
aria-valuemax="${DEFAULTS.MAX_MINUTE}"
|
|
801
|
+
aria-valuenow="${this.internalMinutes ? parseInt(this.internalMinutes, 10) : ''}"
|
|
802
|
+
aria-description="${this.localeSpinbuttonDescription}"
|
|
803
|
+
.value="${this.internalMinutes}"
|
|
804
|
+
placeholder="${this.minutesPlaceholder}"
|
|
805
|
+
?disabled="${this.disabled}"
|
|
806
|
+
?readonly="${this.readonly}"
|
|
807
|
+
tabindex="${this.disabled ? '-1' : '0'}"
|
|
808
|
+
@keydown="${this.handleMinutesKeydown}"
|
|
809
|
+
@focus="${this.handleSpinbuttonFocus}"
|
|
810
|
+
/>
|
|
811
|
+
${is12h
|
|
812
|
+
? html `
|
|
813
|
+
<input
|
|
814
|
+
id="period-spinbutton"
|
|
815
|
+
part="period"
|
|
816
|
+
role="spinbutton"
|
|
817
|
+
aria-label="${this.localePeriodLabel}"
|
|
818
|
+
aria-valuetext="${this.displayPeriod}"
|
|
819
|
+
aria-description="${this.localeSpinbuttonDescription}"
|
|
820
|
+
.value="${this.displayPeriod || ''}"
|
|
821
|
+
placeholder="${this.periodPlaceholder}"
|
|
822
|
+
?disabled="${this.disabled}"
|
|
823
|
+
?readonly="${this.readonly}"
|
|
824
|
+
tabindex="${this.disabled ? '-1' : '0'}"
|
|
825
|
+
@keydown="${this.handlePeriodKeydown}"
|
|
826
|
+
@focus="${this.handleSpinbuttonFocus}"
|
|
827
|
+
/>
|
|
828
|
+
`
|
|
829
|
+
: nothing}
|
|
830
|
+
</div>
|
|
831
|
+
<mdc-button
|
|
832
|
+
part="icon-container"
|
|
833
|
+
class="own-focus-ring"
|
|
834
|
+
variant="tertiary"
|
|
835
|
+
prefix-icon="${this.displayPopover ? ARROW_ICON.ARROW_UP : ARROW_ICON.ARROW_DOWN}"
|
|
836
|
+
aria-label="${this.localeShowTimePickerLabel}"
|
|
837
|
+
aria-expanded="${this.displayPopover ? 'true' : 'false'}"
|
|
838
|
+
aria-haspopup="true"
|
|
839
|
+
?disabled="${this.disabled}"
|
|
840
|
+
size="20"
|
|
841
|
+
@click="${this.handleDropdownClick}"
|
|
842
|
+
></mdc-button>
|
|
843
|
+
</div>
|
|
844
|
+
<input
|
|
845
|
+
id="${this.inputId}"
|
|
846
|
+
part="native-input"
|
|
847
|
+
name="${this.name}"
|
|
848
|
+
type="text"
|
|
849
|
+
?disabled="${this.disabled}"
|
|
850
|
+
?required="${this.required}"
|
|
851
|
+
?readonly="${this.readonly}"
|
|
852
|
+
tabindex="-1"
|
|
853
|
+
aria-hidden="true"
|
|
854
|
+
aria-disabled="${ifDefined(this.disabled || this.softDisabled)}"
|
|
855
|
+
/>
|
|
856
|
+
<mdc-popover
|
|
857
|
+
trigger="${TRIGGER.MANUAL}"
|
|
858
|
+
triggerid="${TRIGGER_ID}"
|
|
859
|
+
interactive
|
|
860
|
+
?visible="${this.displayPopover}"
|
|
861
|
+
role=""
|
|
862
|
+
backdrop
|
|
863
|
+
backdrop-append-to="${ifDefined(this.backdropAppendTo)}"
|
|
864
|
+
append-to="${ifDefined(this.appendTo)}"
|
|
865
|
+
hide-on-outside-click
|
|
866
|
+
hide-on-escape
|
|
867
|
+
focus-back-to-trigger
|
|
868
|
+
focus-trap
|
|
869
|
+
disable-aria-expanded
|
|
870
|
+
size
|
|
871
|
+
?disable-flip="${this.disableFlip}"
|
|
872
|
+
placement="${this.placement}"
|
|
873
|
+
strategy="${ifDefined(this.strategy)}"
|
|
874
|
+
@closebyescape="${(event) => {
|
|
875
|
+
if (event.target === event.currentTarget) {
|
|
876
|
+
this.displayPopover = false;
|
|
877
|
+
}
|
|
878
|
+
}}"
|
|
879
|
+
@closebyoutsideclick="${() => {
|
|
880
|
+
this.displayPopover = false;
|
|
881
|
+
}}"
|
|
882
|
+
exportparts="popover-content"
|
|
883
|
+
>
|
|
884
|
+
<div
|
|
885
|
+
id="${LISTBOX_ID}"
|
|
886
|
+
part="listbox"
|
|
887
|
+
role="listbox"
|
|
888
|
+
aria-label="${this.localeTimeOptionsLabel}"
|
|
889
|
+
@keydown="${this.handleListboxKeydown}"
|
|
890
|
+
>
|
|
891
|
+
${this.renderTimeOptions()}
|
|
892
|
+
</div>
|
|
893
|
+
</mdc-popover>
|
|
894
|
+
</div>
|
|
895
|
+
${this.helpText ? this.renderHelperText() : nothing}
|
|
896
|
+
`;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
TimePicker.styles = [...FormfieldWrapper.styles, ...styles];
|
|
900
|
+
__decorate([
|
|
901
|
+
property({ type: String, reflect: true, attribute: 'time-format' }),
|
|
902
|
+
__metadata("design:type", String)
|
|
903
|
+
], TimePicker.prototype, "timeFormat", void 0);
|
|
904
|
+
__decorate([
|
|
905
|
+
property({ type: Number, reflect: true }),
|
|
906
|
+
__metadata("design:type", Number)
|
|
907
|
+
], TimePicker.prototype, "interval", void 0);
|
|
908
|
+
__decorate([
|
|
909
|
+
property({ type: String, reflect: true }),
|
|
910
|
+
__metadata("design:type", String)
|
|
911
|
+
], TimePicker.prototype, "placement", void 0);
|
|
912
|
+
__decorate([
|
|
913
|
+
property({ type: String, reflect: true }),
|
|
914
|
+
__metadata("design:type", String)
|
|
915
|
+
], TimePicker.prototype, "strategy", void 0);
|
|
916
|
+
__decorate([
|
|
917
|
+
property({ type: Boolean, reflect: true, attribute: 'disable-flip' }),
|
|
918
|
+
__metadata("design:type", Boolean)
|
|
919
|
+
], TimePicker.prototype, "disableFlip", void 0);
|
|
920
|
+
__decorate([
|
|
921
|
+
property({ type: String, reflect: true, attribute: 'append-to' }),
|
|
922
|
+
__metadata("design:type", String)
|
|
923
|
+
], TimePicker.prototype, "appendTo", void 0);
|
|
924
|
+
__decorate([
|
|
925
|
+
property({ type: String, reflect: true, attribute: 'backdrop-append-to' }),
|
|
926
|
+
__metadata("design:type", String)
|
|
927
|
+
], TimePicker.prototype, "backdropAppendTo", void 0);
|
|
928
|
+
__decorate([
|
|
929
|
+
property({ type: String, reflect: true }),
|
|
930
|
+
__metadata("design:type", String)
|
|
931
|
+
], TimePicker.prototype, "min", void 0);
|
|
932
|
+
__decorate([
|
|
933
|
+
property({ type: String, reflect: true }),
|
|
934
|
+
__metadata("design:type", String)
|
|
935
|
+
], TimePicker.prototype, "max", void 0);
|
|
936
|
+
__decorate([
|
|
937
|
+
property({ type: String, attribute: 'locale-hours-label' }),
|
|
938
|
+
__metadata("design:type", Object)
|
|
939
|
+
], TimePicker.prototype, "localeHoursLabel", void 0);
|
|
940
|
+
__decorate([
|
|
941
|
+
property({ type: String, attribute: 'locale-minutes-label' }),
|
|
942
|
+
__metadata("design:type", Object)
|
|
943
|
+
], TimePicker.prototype, "localeMinutesLabel", void 0);
|
|
944
|
+
__decorate([
|
|
945
|
+
property({ type: String, attribute: 'locale-period-label' }),
|
|
946
|
+
__metadata("design:type", Object)
|
|
947
|
+
], TimePicker.prototype, "localePeriodLabel", void 0);
|
|
948
|
+
__decorate([
|
|
949
|
+
property({ type: String, attribute: 'locale-hours-placeholder' }),
|
|
950
|
+
__metadata("design:type", Object)
|
|
951
|
+
], TimePicker.prototype, "localeHoursPlaceholder", void 0);
|
|
952
|
+
__decorate([
|
|
953
|
+
property({ type: String, attribute: 'locale-minutes-placeholder' }),
|
|
954
|
+
__metadata("design:type", Object)
|
|
955
|
+
], TimePicker.prototype, "localeMinutesPlaceholder", void 0);
|
|
956
|
+
__decorate([
|
|
957
|
+
property({ type: String, attribute: 'locale-period-placeholder' }),
|
|
958
|
+
__metadata("design:type", Object)
|
|
959
|
+
], TimePicker.prototype, "localePeriodPlaceholder", void 0);
|
|
960
|
+
__decorate([
|
|
961
|
+
property({ type: String, attribute: 'locale-am-label' }),
|
|
962
|
+
__metadata("design:type", Object)
|
|
963
|
+
], TimePicker.prototype, "localeAmLabel", void 0);
|
|
964
|
+
__decorate([
|
|
965
|
+
property({ type: String, attribute: 'locale-pm-label' }),
|
|
966
|
+
__metadata("design:type", Object)
|
|
967
|
+
], TimePicker.prototype, "localePmLabel", void 0);
|
|
968
|
+
__decorate([
|
|
969
|
+
property({ type: String, attribute: 'locale-show-time-picker-label' }),
|
|
970
|
+
__metadata("design:type", Object)
|
|
971
|
+
], TimePicker.prototype, "localeShowTimePickerLabel", void 0);
|
|
972
|
+
__decorate([
|
|
973
|
+
property({ type: String, attribute: 'locale-time-options-label' }),
|
|
974
|
+
__metadata("design:type", Object)
|
|
975
|
+
], TimePicker.prototype, "localeTimeOptionsLabel", void 0);
|
|
976
|
+
__decorate([
|
|
977
|
+
property({ type: String, attribute: 'locale-spinbutton-description' }),
|
|
978
|
+
__metadata("design:type", Object)
|
|
979
|
+
], TimePicker.prototype, "localeSpinbuttonDescription", void 0);
|
|
980
|
+
__decorate([
|
|
981
|
+
query('mdc-button[part="icon-container"]'),
|
|
982
|
+
__metadata("design:type", HTMLElement)
|
|
983
|
+
], TimePicker.prototype, "dropdownButton", void 0);
|
|
984
|
+
__decorate([
|
|
985
|
+
query('#hours-spinbutton'),
|
|
986
|
+
__metadata("design:type", HTMLInputElement)
|
|
987
|
+
], TimePicker.prototype, "hoursInput", void 0);
|
|
988
|
+
__decorate([
|
|
989
|
+
query('#minutes-spinbutton'),
|
|
990
|
+
__metadata("design:type", HTMLInputElement)
|
|
991
|
+
], TimePicker.prototype, "minutesInput", void 0);
|
|
992
|
+
__decorate([
|
|
993
|
+
query('#period-spinbutton'),
|
|
994
|
+
__metadata("design:type", HTMLInputElement)
|
|
995
|
+
], TimePicker.prototype, "periodInput", void 0);
|
|
996
|
+
__decorate([
|
|
997
|
+
state(),
|
|
998
|
+
__metadata("design:type", Object)
|
|
999
|
+
], TimePicker.prototype, "displayPopover", void 0);
|
|
1000
|
+
__decorate([
|
|
1001
|
+
state(),
|
|
1002
|
+
__metadata("design:type", Object)
|
|
1003
|
+
], TimePicker.prototype, "internalHours", void 0);
|
|
1004
|
+
__decorate([
|
|
1005
|
+
state(),
|
|
1006
|
+
__metadata("design:type", Object)
|
|
1007
|
+
], TimePicker.prototype, "internalMinutes", void 0);
|
|
1008
|
+
__decorate([
|
|
1009
|
+
state(),
|
|
1010
|
+
__metadata("design:type", String)
|
|
1011
|
+
], TimePicker.prototype, "internalPeriod", void 0);
|
|
1012
|
+
__decorate([
|
|
1013
|
+
state(),
|
|
1014
|
+
__metadata("design:type", Object)
|
|
1015
|
+
], TimePicker.prototype, "focusedOptionIndex", void 0);
|
|
1016
|
+
export default TimePicker;
|