@genesislcap/foundation-ui 14.447.2 → 14.448.0-canary.wealth
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/custom-elements.json +1535 -963
- package/dist/dts/date-picker/date-picker.d.ts +63 -0
- package/dist/dts/date-picker/date-picker.d.ts.map +1 -1
- package/dist/dts/date-picker/date-picker.template.d.ts.map +1 -1
- package/dist/dts/date-picker/date-picker.util.d.ts +37 -0
- package/dist/dts/date-picker/date-picker.util.d.ts.map +1 -0
- package/dist/dts/date-picker/index.d.ts +1 -0
- package/dist/dts/date-picker/index.d.ts.map +1 -1
- package/dist/dts/react.d.ts +9 -20
- package/dist/dts/search-bar/search-bar-combobox.d.ts +5 -6
- package/dist/dts/search-bar/search-bar-combobox.d.ts.map +1 -1
- package/dist/dts/search-bar/search-bar-combobox.styles.d.ts.map +1 -1
- package/dist/dts/search-bar/search-bar.d.ts +31 -0
- package/dist/dts/search-bar/search-bar.d.ts.map +1 -1
- package/dist/dts/search-bar/search-bar.styles.d.ts.map +1 -1
- package/dist/dts/search-bar/search-bar.template.d.ts.map +1 -1
- package/dist/dts/search-bar/search-bar.types.d.ts +1 -1
- package/dist/dts/search-bar/search-bar.types.d.ts.map +1 -1
- package/dist/esm/date-picker/date-picker.js +264 -17
- package/dist/esm/date-picker/date-picker.template.js +9 -1
- package/dist/esm/date-picker/date-picker.util.js +92 -0
- package/dist/esm/date-picker/index.js +1 -0
- package/dist/esm/search-bar/search-bar-combobox.js +31 -1
- package/dist/esm/search-bar/search-bar-combobox.styles.js +15 -0
- package/dist/esm/search-bar/search-bar-combobox.template.js +1 -1
- package/dist/esm/search-bar/search-bar.js +81 -1
- package/dist/esm/search-bar/search-bar.styles.js +0 -17
- package/dist/esm/search-bar/search-bar.template.js +27 -26
- package/dist/react.cjs +6 -25
- package/dist/react.mjs +5 -23
- package/package.json +19 -19
|
@@ -6,9 +6,11 @@ import dayjs from 'dayjs';
|
|
|
6
6
|
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
7
7
|
import localeData from 'dayjs/plugin/localeData';
|
|
8
8
|
import LocalizedFormat from 'dayjs/plugin/localizedFormat';
|
|
9
|
+
import { wasClickOutsideElement } from '../utils';
|
|
9
10
|
import Calendar from './calendar';
|
|
10
11
|
import { foundationDatePickerStyles as styles } from './date-picker.styles';
|
|
11
12
|
import { foundationDatePickerTemplate as template } from './date-picker.template';
|
|
13
|
+
import { DATE_PICKER_VALUE_FORMAT, formatToPlaceholder, getBrowserLocale, getDisplayFormatForLang, hasDateValue, parseDatePickerValue, } from './date-picker.util';
|
|
12
14
|
import Day from './day';
|
|
13
15
|
import { getNextEnabledDay } from './day.util';
|
|
14
16
|
export const foundationDatePickerShadowOptions = undefined;
|
|
@@ -31,7 +33,7 @@ export class DatePicker extends FoundationElement {
|
|
|
31
33
|
* </rapid-date-picker>
|
|
32
34
|
* ```
|
|
33
35
|
*/
|
|
34
|
-
this.format =
|
|
36
|
+
this.format = DATE_PICKER_VALUE_FORMAT;
|
|
35
37
|
this.lang = 'en-US';
|
|
36
38
|
this.visible = false;
|
|
37
39
|
/**
|
|
@@ -56,53 +58,284 @@ export class DatePicker extends FoundationElement {
|
|
|
56
58
|
* ```
|
|
57
59
|
*/
|
|
58
60
|
this.disabledDaysOfWeek = [];
|
|
61
|
+
this.suppressValueChanged = false;
|
|
62
|
+
this.cachedFormat = DATE_PICKER_VALUE_FORMAT;
|
|
63
|
+
this.clickOutside = (e) => this.handleClickOutside(e);
|
|
64
|
+
this.keydownOutside = (e) => this.handleKeydownOutside(e);
|
|
59
65
|
}
|
|
60
66
|
formatChanged(oldValue, newValue) {
|
|
61
|
-
if (
|
|
67
|
+
if (!this.useLocaleFormat && newValue) {
|
|
68
|
+
this.cacheUserFormat(newValue);
|
|
69
|
+
}
|
|
70
|
+
if (newValue && this.calendar && hasDateValue(this.value)) {
|
|
62
71
|
this.formatDate = dayjs(this.currentDate.Date).format(newValue);
|
|
63
72
|
}
|
|
64
73
|
}
|
|
74
|
+
langChanged() {
|
|
75
|
+
this.applyEffectiveLangChange();
|
|
76
|
+
}
|
|
77
|
+
useLocaleFormatChanged(oldValue, newValue) {
|
|
78
|
+
// Pre-mount: format/useLocaleFormat may be set in any order; let connectedCallback do the
|
|
79
|
+
// initial cache so we don't snapshot the default format before the `format` attribute is parsed.
|
|
80
|
+
if (!this.calendar) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (newValue && !oldValue) {
|
|
84
|
+
this.cacheUserFormat(this.format);
|
|
85
|
+
}
|
|
86
|
+
else if (!newValue && oldValue) {
|
|
87
|
+
this.restoreUserFormat();
|
|
88
|
+
}
|
|
89
|
+
this.applyEffectiveLangChange();
|
|
90
|
+
}
|
|
65
91
|
inlineCalendarChanged() {
|
|
92
|
+
if (this.inlineCalendar) {
|
|
93
|
+
document.removeEventListener('mousedown', this.clickOutside);
|
|
94
|
+
document.removeEventListener('keydown', this.keydownOutside);
|
|
95
|
+
}
|
|
96
|
+
else if (this.visible) {
|
|
97
|
+
document.addEventListener('mousedown', this.clickOutside);
|
|
98
|
+
document.addEventListener('keydown', this.keydownOutside);
|
|
99
|
+
}
|
|
66
100
|
this.toggleVisibility();
|
|
67
101
|
}
|
|
68
102
|
hideWeekendsCalendarChanged() {
|
|
69
103
|
this.toggleVisibility();
|
|
70
104
|
}
|
|
71
105
|
valueChanged(oldValue, newValue) {
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
106
|
+
if (this.suppressValueChanged) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!this.calendar) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (!hasDateValue(newValue)) {
|
|
113
|
+
if (this.allowEmpty) {
|
|
114
|
+
this.clearToEmpty(false);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
this.resetToDefaultDate();
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
79
120
|
}
|
|
121
|
+
this.applyValue(newValue);
|
|
122
|
+
}
|
|
123
|
+
disconnectedCallback() {
|
|
124
|
+
document.removeEventListener('mousedown', this.clickOutside);
|
|
125
|
+
document.removeEventListener('keydown', this.keydownOutside);
|
|
126
|
+
super.disconnectedCallback();
|
|
80
127
|
}
|
|
81
128
|
connectedCallback() {
|
|
82
|
-
var _a;
|
|
83
129
|
super.connectedCallback();
|
|
84
130
|
dayjs.extend(customParseFormat);
|
|
85
131
|
dayjs.extend(LocalizedFormat);
|
|
86
132
|
dayjs.extend(localeData);
|
|
87
133
|
this.substringNumber = 3;
|
|
134
|
+
if (this.useLocaleFormat) {
|
|
135
|
+
this.cacheUserFormat(this.format);
|
|
136
|
+
this.applyLocaleFormat();
|
|
137
|
+
}
|
|
88
138
|
const dateString = this.value;
|
|
89
|
-
|
|
90
|
-
|
|
139
|
+
if (this.allowEmpty && !hasDateValue(dateString)) {
|
|
140
|
+
this.initializeEmpty();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (hasDateValue(dateString)) {
|
|
144
|
+
this.applyValue(dateString);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
this.initializeWithDefaultDate();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Clears the selected date (only when `allow-empty` is enabled).
|
|
151
|
+
* @public
|
|
152
|
+
*/
|
|
153
|
+
clear() {
|
|
154
|
+
if (!this.allowEmpty) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this.clearToEmpty(true);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* @internal
|
|
161
|
+
*/
|
|
162
|
+
get inputValue() {
|
|
163
|
+
return hasDateValue(this.value) ? this.formatDate : '';
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* @internal
|
|
167
|
+
*/
|
|
168
|
+
get inputPlaceholder() {
|
|
169
|
+
var _a;
|
|
170
|
+
if (!this.allowEmpty || hasDateValue(this.value)) {
|
|
171
|
+
return '';
|
|
172
|
+
}
|
|
173
|
+
return ((_a = this.placeholder) === null || _a === void 0 ? void 0 : _a.trim()) || formatToPlaceholder(this.format);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Locale for display format and calendar labels: explicit `lang`, or browser when using locale format.
|
|
177
|
+
* @internal
|
|
178
|
+
*/
|
|
179
|
+
get effectiveLang() {
|
|
180
|
+
if (this.useLocaleFormat && !this.hasAttribute('lang')) {
|
|
181
|
+
return getBrowserLocale();
|
|
182
|
+
}
|
|
183
|
+
return this.lang;
|
|
184
|
+
}
|
|
185
|
+
applyLocaleFormat() {
|
|
186
|
+
this.format = getDisplayFormatForLang(this.effectiveLang);
|
|
187
|
+
}
|
|
188
|
+
cacheUserFormat(format) {
|
|
189
|
+
const trimmed = format === null || format === void 0 ? void 0 : format.trim();
|
|
190
|
+
if (trimmed) {
|
|
191
|
+
this.cachedFormat = trimmed;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
restoreUserFormat() {
|
|
195
|
+
this.format = this.cachedFormat;
|
|
196
|
+
}
|
|
197
|
+
applyEffectiveLangChange() {
|
|
198
|
+
var _a, _b;
|
|
199
|
+
if (!this.calendar) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (this.useLocaleFormat) {
|
|
203
|
+
this.applyLocaleFormat();
|
|
204
|
+
}
|
|
205
|
+
const viewYear = this.calendar.year;
|
|
206
|
+
const viewMonth = this.calendar.month.number;
|
|
207
|
+
const selectedDate = (_b = (_a = this.currentDate) === null || _a === void 0 ? void 0 : _a.Date) !== null && _b !== void 0 ? _b : dayjs().toDate();
|
|
208
|
+
this.currentDate = new Day(selectedDate, this.effectiveLang);
|
|
209
|
+
this.calendar = new Calendar(viewYear, viewMonth, this.effectiveLang);
|
|
210
|
+
if (hasDateValue(this.value)) {
|
|
211
|
+
this.formatDate = dayjs(this.currentDate.Date).format(this.format);
|
|
212
|
+
}
|
|
213
|
+
this.updateHeaderText();
|
|
214
|
+
this.monthList = this.getMonthDaysGrid();
|
|
215
|
+
}
|
|
216
|
+
syncValueAttribute(value) {
|
|
217
|
+
this.suppressValueChanged = true;
|
|
218
|
+
this.value = value;
|
|
219
|
+
this.suppressValueChanged = false;
|
|
220
|
+
}
|
|
221
|
+
initializeEmpty() {
|
|
222
|
+
const viewDate = dayjs();
|
|
223
|
+
this.currentDate = new Day(viewDate.toDate(), this.effectiveLang);
|
|
224
|
+
this.calendar = new Calendar(this.currentDate.year, this.currentDate.monthNumber, this.effectiveLang);
|
|
225
|
+
this.formatDate = '';
|
|
226
|
+
this.syncValueAttribute('');
|
|
227
|
+
this.currentMonth = this.calendar.month.name;
|
|
228
|
+
this.currentYear = this.calendar.year;
|
|
229
|
+
this.monthList = this.getMonthDaysGrid();
|
|
230
|
+
}
|
|
231
|
+
initializeWithDefaultDate() {
|
|
232
|
+
this.resetToDefaultDate(true);
|
|
233
|
+
}
|
|
234
|
+
resetToDefaultDate(createCalendar = false) {
|
|
235
|
+
var _a;
|
|
236
|
+
let currentDate = new Day(dayjs().toDate(), this.effectiveLang);
|
|
91
237
|
if ((_a = this.disabledDaysOfWeek) === null || _a === void 0 ? void 0 : _a.length) {
|
|
92
|
-
currentDate = getNextEnabledDay(this.disabledDaysOfWeek, currentDate, this.
|
|
238
|
+
currentDate = getNextEnabledDay(this.disabledDaysOfWeek, currentDate, this.effectiveLang);
|
|
93
239
|
}
|
|
94
240
|
this.currentDate = currentDate;
|
|
95
|
-
|
|
96
|
-
|
|
241
|
+
if (createCalendar || !this.calendar) {
|
|
242
|
+
this.calendar = new Calendar(this.currentDate.year, this.currentDate.monthNumber, this.effectiveLang);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
this.calendar.goToDate(this.currentDate.monthNumber, this.currentDate.year);
|
|
246
|
+
}
|
|
247
|
+
this.formatDate = dayjs(this.currentDate.Date).format(this.format);
|
|
248
|
+
this.syncValueAttribute(dayjs(this.currentDate.Date).format(DATE_PICKER_VALUE_FORMAT));
|
|
97
249
|
this.currentMonth = this.calendar.month.name;
|
|
98
250
|
this.currentYear = this.calendar.year;
|
|
251
|
+
this.monthList = this.getMonthDaysGrid();
|
|
252
|
+
}
|
|
253
|
+
applyValue(dateString) {
|
|
254
|
+
const parsed = parseDatePickerValue(dateString, this.format);
|
|
255
|
+
if (!parsed) {
|
|
256
|
+
if (this.allowEmpty) {
|
|
257
|
+
this.clearToEmpty(false);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
this.resetToDefaultDate();
|
|
261
|
+
}
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
// Honor the host's value verbatim. Disabled-day roll-forward only applies to the
|
|
265
|
+
// default "today" fallback (see `resetToDefaultDate`); programmatic writes should not
|
|
266
|
+
// be silently shifted, and user clicks on disabled day cells are blocked in the template.
|
|
267
|
+
this.currentDate = new Day(parsed.toDate(), this.effectiveLang);
|
|
268
|
+
if (!this.calendar) {
|
|
269
|
+
this.calendar = new Calendar(this.currentDate.year, this.currentDate.monthNumber, this.effectiveLang);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
this.calendar.goToDate(this.currentDate.monthNumber, this.currentDate.year);
|
|
273
|
+
}
|
|
99
274
|
this.formatDate = dayjs(this.currentDate.Date).format(this.format);
|
|
275
|
+
this.syncValueAttribute(dayjs(this.currentDate.Date).format(DATE_PICKER_VALUE_FORMAT));
|
|
276
|
+
this.updateHeaderText();
|
|
100
277
|
this.monthList = this.getMonthDaysGrid();
|
|
101
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* Resets to the empty/cleared view.
|
|
281
|
+
* @param emitEvent - emit `value-changed` for user-driven clears (public `clear()`); skip for
|
|
282
|
+
* host-driven attribute writes since the host is the source of the change.
|
|
283
|
+
*/
|
|
284
|
+
clearToEmpty(emitEvent) {
|
|
285
|
+
const viewDate = dayjs();
|
|
286
|
+
this.currentDate = new Day(viewDate.toDate(), this.effectiveLang);
|
|
287
|
+
if (this.calendar) {
|
|
288
|
+
this.calendar.goToDate(this.currentDate.monthNumber, this.currentDate.year);
|
|
289
|
+
this.updateHeaderText();
|
|
290
|
+
this.monthList = this.getMonthDaysGrid();
|
|
291
|
+
}
|
|
292
|
+
this.formatDate = '';
|
|
293
|
+
this.syncValueAttribute('');
|
|
294
|
+
if (emitEvent) {
|
|
295
|
+
this.$emit('value-changed', undefined);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
102
298
|
updateHeaderText() {
|
|
103
299
|
this.currentMonth = this.calendar.month.name;
|
|
104
300
|
this.currentYear = this.calendar.year;
|
|
105
301
|
}
|
|
302
|
+
visibleChanged(_prev, next) {
|
|
303
|
+
if (this.inlineCalendar) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (next) {
|
|
307
|
+
document.addEventListener('mousedown', this.clickOutside);
|
|
308
|
+
document.addEventListener('keydown', this.keydownOutside);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
document.removeEventListener('mousedown', this.clickOutside);
|
|
312
|
+
document.removeEventListener('keydown', this.keydownOutside);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
handleKeydownOutside(event) {
|
|
316
|
+
if (this.inlineCalendar || !this.visible) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (event.key === 'Escape') {
|
|
320
|
+
event.preventDefault();
|
|
321
|
+
this.closeCalendar();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
handleClickOutside(event) {
|
|
325
|
+
if (this.inlineCalendar || !this.visible) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
if (wasClickOutsideElement(event, this)) {
|
|
329
|
+
this.closeCalendar();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
closeCalendar() {
|
|
333
|
+
if (!this.visible) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
this.visible = false;
|
|
337
|
+
this.toggleVisibility();
|
|
338
|
+
}
|
|
106
339
|
toggleCalendar() {
|
|
107
340
|
this.visible = !this.visible;
|
|
108
341
|
this.toggleVisibility();
|
|
@@ -115,6 +348,9 @@ export class DatePicker extends FoundationElement {
|
|
|
115
348
|
this.calendarDropdownClasses = classNames(['visible', this.visible], this.position, ['inline', this.inlineCalendar], ['hide-weekends', this.hideWeekends]);
|
|
116
349
|
}
|
|
117
350
|
isSelectedDate(date) {
|
|
351
|
+
if (this.allowEmpty && !hasDateValue(this.value)) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
118
354
|
return dayjs(date.Date).isSame(this.currentDate.Date, 'day');
|
|
119
355
|
}
|
|
120
356
|
isCurrentCalendarMonth() {
|
|
@@ -135,14 +371,16 @@ export class DatePicker extends FoundationElement {
|
|
|
135
371
|
this.monthList = this.getMonthDaysGrid();
|
|
136
372
|
}
|
|
137
373
|
selectDay(day) {
|
|
138
|
-
|
|
374
|
+
const sameDayAsCurrent = dayjs(day.Date).isSame(this.currentDate.Date, 'day');
|
|
375
|
+
if (sameDayAsCurrent && hasDateValue(this.value)) {
|
|
139
376
|
return;
|
|
377
|
+
}
|
|
140
378
|
this.currentDate = day;
|
|
141
379
|
if (day.monthNumber !== this.calendar.month.number) {
|
|
142
380
|
this.prevMonth();
|
|
143
381
|
}
|
|
144
382
|
this.formatDate = dayjs(this.currentDate.Date).format(this.format);
|
|
145
|
-
this.
|
|
383
|
+
this.syncValueAttribute(dayjs(day.Date).format(DATE_PICKER_VALUE_FORMAT));
|
|
146
384
|
this.$emit('value-changed', this.value);
|
|
147
385
|
this.toggleCalendar();
|
|
148
386
|
}
|
|
@@ -168,6 +406,9 @@ __decorate([
|
|
|
168
406
|
__decorate([
|
|
169
407
|
attr
|
|
170
408
|
], DatePicker.prototype, "lang", void 0);
|
|
409
|
+
__decorate([
|
|
410
|
+
attr({ attribute: 'use-locale-format', mode: 'boolean' })
|
|
411
|
+
], DatePicker.prototype, "useLocaleFormat", void 0);
|
|
171
412
|
__decorate([
|
|
172
413
|
attr
|
|
173
414
|
], DatePicker.prototype, "visible", void 0);
|
|
@@ -183,6 +424,12 @@ __decorate([
|
|
|
183
424
|
__decorate([
|
|
184
425
|
attr
|
|
185
426
|
], DatePicker.prototype, "label", void 0);
|
|
427
|
+
__decorate([
|
|
428
|
+
attr({ attribute: 'allow-empty', mode: 'boolean' })
|
|
429
|
+
], DatePicker.prototype, "allowEmpty", void 0);
|
|
430
|
+
__decorate([
|
|
431
|
+
attr
|
|
432
|
+
], DatePicker.prototype, "placeholder", void 0);
|
|
186
433
|
__decorate([
|
|
187
434
|
attr
|
|
188
435
|
], DatePicker.prototype, "value", void 0);
|
|
@@ -5,7 +5,15 @@ const SUNDAY_INDEX = 1;
|
|
|
5
5
|
const SATURDAY_INDEX = 7;
|
|
6
6
|
const WEEKEND_DAY_INDICES = [SUNDAY_INDEX, SATURDAY_INDEX];
|
|
7
7
|
export const getPrefixedDatePicker = (prefix) => html `
|
|
8
|
-
<${prefix}-text-field
|
|
8
|
+
<${prefix}-text-field
|
|
9
|
+
data-test-id="date-picker"
|
|
10
|
+
readonly
|
|
11
|
+
:value="${(x) => x.inputValue}"
|
|
12
|
+
placeholder="${(x) => x.inputPlaceholder}"
|
|
13
|
+
part="date-toggle"
|
|
14
|
+
class="date-toggle"
|
|
15
|
+
@click="${(x) => x.toggleCalendar()}"
|
|
16
|
+
>
|
|
9
17
|
${(x) => x.label}
|
|
10
18
|
<div class="input-icon-container" part="input-icon-container" slot="end"><${prefix}-icon variant="regular" name="calendar-alt" size="sm"></${prefix}-icon></div>
|
|
11
19
|
</${prefix}-text-field>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
3
|
+
import localeData from 'dayjs/plugin/localeData';
|
|
4
|
+
import LocalizedFormat from 'dayjs/plugin/localizedFormat';
|
|
5
|
+
import 'dayjs/locale/en-gb';
|
|
6
|
+
dayjs.extend(customParseFormat);
|
|
7
|
+
dayjs.extend(localeData);
|
|
8
|
+
dayjs.extend(LocalizedFormat);
|
|
9
|
+
/**
|
|
10
|
+
* Maps BCP-47 tags to dayjs locale ids (lowercase, e.g. `fr-FR` → `fr-fr`).
|
|
11
|
+
* English variants map to dayjs bundles: `en-US` → `en`, `en-GB` → `en-gb`.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export function resolveDayjsLocale(lang) {
|
|
15
|
+
const normalized = ((lang === null || lang === void 0 ? void 0 : lang.trim()) || 'en').toLowerCase().replace(/_/g, '-');
|
|
16
|
+
if (normalized === 'en-us' || normalized === 'en') {
|
|
17
|
+
return 'en';
|
|
18
|
+
}
|
|
19
|
+
if (normalized === 'en-gb') {
|
|
20
|
+
return 'en-gb';
|
|
21
|
+
}
|
|
22
|
+
return normalized;
|
|
23
|
+
}
|
|
24
|
+
function dayjsLocaleWasApplied(requested, applied) {
|
|
25
|
+
if (requested === applied) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
const language = requested.split('-')[0];
|
|
29
|
+
return applied === language;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Browser BCP-47 locale (e.g. `en-GB`), or `en` when unavailable (SSR/tests).
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
export function getBrowserLocale() {
|
|
36
|
+
if (typeof navigator !== 'undefined' && navigator.language) {
|
|
37
|
+
return navigator.language;
|
|
38
|
+
}
|
|
39
|
+
return 'en';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Display format from dayjs locale `L` (e.g. en / en-US → MM/DD/YYYY, en-gb → DD/MM/YYYY).
|
|
43
|
+
* Falls back to `en` when the locale is not loaded in dayjs (import the matching `dayjs/locale/*` bundle).
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export function getDisplayFormatForLang(lang = 'en') {
|
|
47
|
+
const locale = resolveDayjsLocale(lang);
|
|
48
|
+
const instance = dayjs().locale(locale);
|
|
49
|
+
const appliedLocale = instance.locale();
|
|
50
|
+
if (!dayjsLocaleWasApplied(locale, appliedLocale)) {
|
|
51
|
+
return dayjs().locale('en').localeData().longDateFormat('L') || 'MM/DD/YYYY';
|
|
52
|
+
}
|
|
53
|
+
return instance.localeData().longDateFormat('L') || 'MM/DD/YYYY';
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Maps a dayjs-style display format to a lowercase placeholder hint (e.g. DD/MM/YYYY → dd/mm/yyyy).
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
export function formatToPlaceholder(format) {
|
|
60
|
+
return format
|
|
61
|
+
.replace(/YYYY/g, 'yyyy')
|
|
62
|
+
.replace(/YY(?!Y)/g, 'yy')
|
|
63
|
+
.replace(/DD/g, 'dd')
|
|
64
|
+
.replace(/D(?!D)/g, 'd')
|
|
65
|
+
.replace(/MM/g, 'mm')
|
|
66
|
+
.replace(/M(?!M)/g, 'm');
|
|
67
|
+
}
|
|
68
|
+
export function hasDateValue(value) {
|
|
69
|
+
return value !== null && value !== undefined && String(value).trim() !== '';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Internal wire format for the date picker's `value` attribute.
|
|
73
|
+
* Display formatting is independent (see `format` / `getDisplayFormatForLang`).
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export const DATE_PICKER_VALUE_FORMAT = 'MM-DD-YYYY';
|
|
77
|
+
/**
|
|
78
|
+
* Strictly parses a date picker value (`displayFormat` or internal `DATE_PICKER_VALUE_FORMAT`). Returns null when invalid.
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
export function parseDatePickerValue(dateString, displayFormat) {
|
|
82
|
+
const trimmed = String(dateString).trim();
|
|
83
|
+
const display = dayjs(trimmed, displayFormat, true);
|
|
84
|
+
if (display.isValid()) {
|
|
85
|
+
return display;
|
|
86
|
+
}
|
|
87
|
+
const internal = dayjs(trimmed, DATE_PICKER_VALUE_FORMAT, true);
|
|
88
|
+
if (internal.isValid()) {
|
|
89
|
+
return internal;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
2
|
import { Combobox } from '@microsoft/fast-components';
|
|
3
|
-
import { attr } from '@microsoft/fast-element';
|
|
3
|
+
import { attr, observable } from '@microsoft/fast-element';
|
|
4
4
|
import { foundationSearchBarComboboxStyles } from './search-bar-combobox.styles';
|
|
5
5
|
import { foundationSearchBarComboboxTemplate } from './search-bar-combobox.template';
|
|
6
6
|
import { COMBO_INPUT_MIN_LENGTH } from './search-bar.types';
|
|
@@ -10,6 +10,18 @@ import { COMBO_INPUT_MIN_LENGTH } from './search-bar.types';
|
|
|
10
10
|
* @fires change - Fired when the combobox value changes
|
|
11
11
|
* @fires inputdeleted - Fired when the input is cleared by the user
|
|
12
12
|
*/
|
|
13
|
+
const INPUT_LOCK_ALLOWED_KEYS = new Set([
|
|
14
|
+
'Backspace',
|
|
15
|
+
'Delete',
|
|
16
|
+
'Tab',
|
|
17
|
+
'Escape',
|
|
18
|
+
'ArrowUp',
|
|
19
|
+
'ArrowDown',
|
|
20
|
+
'ArrowLeft',
|
|
21
|
+
'ArrowRight',
|
|
22
|
+
'Home',
|
|
23
|
+
'End',
|
|
24
|
+
]);
|
|
13
25
|
export class SearchBarCombobox extends Combobox {
|
|
14
26
|
constructor() {
|
|
15
27
|
super(...arguments);
|
|
@@ -70,6 +82,14 @@ export class SearchBarCombobox extends Combobox {
|
|
|
70
82
|
}
|
|
71
83
|
keydownHandler(e) {
|
|
72
84
|
const key = e.key;
|
|
85
|
+
if (this.inputLocked) {
|
|
86
|
+
const isModifier = e.ctrlKey || e.metaKey || e.altKey;
|
|
87
|
+
const isAllowed = INPUT_LOCK_ALLOWED_KEYS.has(key) || isModifier;
|
|
88
|
+
if (!isAllowed) {
|
|
89
|
+
e.preventDefault();
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
73
93
|
switch (key) {
|
|
74
94
|
case 'ArrowUp':
|
|
75
95
|
case 'ArrowDown': {
|
|
@@ -103,6 +123,13 @@ export class SearchBarCombobox extends Combobox {
|
|
|
103
123
|
}
|
|
104
124
|
}
|
|
105
125
|
inputHandler(e) {
|
|
126
|
+
if (this.inputLocked) {
|
|
127
|
+
this.control.value = '';
|
|
128
|
+
this.value = '';
|
|
129
|
+
this.open = false;
|
|
130
|
+
e.stopImmediatePropagation();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
106
133
|
if (this.control.value.length >= this.minlength) {
|
|
107
134
|
this.open = true;
|
|
108
135
|
}
|
|
@@ -128,6 +155,9 @@ export class SearchBarCombobox extends Combobox {
|
|
|
128
155
|
__decorate([
|
|
129
156
|
attr
|
|
130
157
|
], SearchBarCombobox.prototype, "minlength", void 0);
|
|
158
|
+
__decorate([
|
|
159
|
+
observable
|
|
160
|
+
], SearchBarCombobox.prototype, "inputLocked", void 0);
|
|
131
161
|
export const foundationSearchBarComboboxShadowOptions = {
|
|
132
162
|
delegatesFocus: true,
|
|
133
163
|
mode: 'open',
|
|
@@ -23,4 +23,19 @@ export const foundationSearchBarComboboxStyles = (context, definition) => css `
|
|
|
23
23
|
min-width: 150px;
|
|
24
24
|
max-width: 169px;
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
.input-locked .control,
|
|
28
|
+
:host(.input-locked) .control {
|
|
29
|
+
width: 0;
|
|
30
|
+
min-width: 0;
|
|
31
|
+
padding: 0;
|
|
32
|
+
margin: 0;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
flex: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.input-locked .selected-value,
|
|
38
|
+
:host(.input-locked) .selected-value {
|
|
39
|
+
display: none;
|
|
40
|
+
}
|
|
26
41
|
`;
|
|
@@ -4,7 +4,7 @@ export const foundationSearchBarComboboxTemplate = (context, definition) => html
|
|
|
4
4
|
<template
|
|
5
5
|
aria-disabled="${(x) => x.ariaDisabled}"
|
|
6
6
|
autocomplete="${(x) => x.autocomplete}"
|
|
7
|
-
class="${(x) => (x.open ? 'open' : '')} ${(x) => (x.disabled ? 'disabled' : '')} ${(x) => x.position} body"
|
|
7
|
+
class="${(x) => (x.open ? 'open' : '')} ${(x) => (x.disabled ? 'disabled' : '')} ${(x) => x.position} ${(x) => (x.inputLocked ? 'input-locked' : '')} body"
|
|
8
8
|
?open="${(x) => x.open}"
|
|
9
9
|
tabindex="${(x) => (!x.disabled ? '0' : null)}"
|
|
10
10
|
@click="${(x, c) => x.clickHandler(c.event)}"
|