@tylertech/forge 3.9.1 → 3.10.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.
Files changed (93) hide show
  1. package/custom-elements.json +183 -25
  2. package/dist/badge/forge-badge.css +1 -1
  3. package/dist/forge.css +0 -1
  4. package/dist/lib.js +22 -22
  5. package/dist/lib.js.map +3 -3
  6. package/dist/table/forge-table.css +0 -1
  7. package/dist/vscode.html-custom-data.json +20 -0
  8. package/esm/autocomplete/autocomplete-core.js +9 -12
  9. package/esm/autocomplete/autocomplete-utils.js +3 -2
  10. package/esm/badge/badge.js +1 -1
  11. package/esm/button/base/base-button-adapter.js +6 -5
  12. package/esm/button/base/base-button-constants.d.ts +2 -2
  13. package/esm/button-area/button-area-adapter.d.ts +0 -2
  14. package/esm/button-area/button-area-adapter.js +5 -3
  15. package/esm/button-area/button-area-core.js +0 -1
  16. package/esm/button-area/button-area.js +1 -1
  17. package/esm/button-toggle/button-toggle-group/button-toggle-group-core.js +0 -1
  18. package/esm/calendar/calendar-core.js +6 -4
  19. package/esm/calendar/calendar-dropdown/calendar-dropdown.js +1 -1
  20. package/esm/calendar/calendar-utils.js +1 -3
  21. package/esm/calendar/calendar.js +1 -1
  22. package/esm/color-picker/color-picker-core.js +2 -2
  23. package/esm/core/configuration/global-configuration.js +0 -1
  24. package/esm/core/mask/date-input-mask.js +18 -1
  25. package/esm/core/mixins/form/with-form-associated.js +6 -2
  26. package/esm/core/utils/a11y-utils.d.ts +2 -2
  27. package/esm/core/utils/date-utils.d.ts +14 -5
  28. package/esm/core/utils/date-utils.js +229 -70
  29. package/esm/core/utils/dismissible-stack.js +0 -1
  30. package/esm/core/utils/feature-detection.js +2 -2
  31. package/esm/date-picker/base/base-date-picker-adapter.d.ts +2 -1
  32. package/esm/date-picker/base/base-date-picker-adapter.js +4 -0
  33. package/esm/date-picker/base/base-date-picker-constants.d.ts +19 -4
  34. package/esm/date-picker/base/base-date-picker-constants.js +20 -1
  35. package/esm/date-picker/base/base-date-picker-core.d.ts +11 -3
  36. package/esm/date-picker/base/base-date-picker-core.js +70 -17
  37. package/esm/date-picker/base/base-date-picker-utils.d.ts +2 -1
  38. package/esm/date-picker/base/base-date-picker.d.ts +10 -2
  39. package/esm/date-picker/base/base-date-picker.js +17 -1
  40. package/esm/date-picker/date-picker-adapter.js +1 -1
  41. package/esm/date-picker/date-picker-core.js +3 -2
  42. package/esm/date-range-picker/date-range-picker-adapter.d.ts +2 -1
  43. package/esm/date-range-picker/date-range-picker-adapter.js +1 -1
  44. package/esm/date-range-picker/date-range-picker-core.d.ts +1 -0
  45. package/esm/date-range-picker/date-range-picker-core.js +18 -9
  46. package/esm/deprecated/icon-button/deprecated-icon-button-component-delegate.js +2 -1
  47. package/esm/dialog/dialog.js +1 -1
  48. package/esm/expansion-panel/expansion-panel-core.d.ts +4 -0
  49. package/esm/expansion-panel/expansion-panel-core.js +19 -11
  50. package/esm/field/field-core.js +2 -1
  51. package/esm/field/field.js +1 -1
  52. package/esm/file-picker/file-picker-core.js +1 -3
  53. package/esm/floating-action-button/floating-action-button-adapter.d.ts +0 -4
  54. package/esm/floating-action-button/floating-action-button-adapter.js +3 -24
  55. package/esm/floating-action-button/floating-action-button-component-delegate.js +2 -1
  56. package/esm/floating-action-button/floating-action-button-core.d.ts +0 -1
  57. package/esm/floating-action-button/floating-action-button-core.js +0 -3
  58. package/esm/floating-action-button/floating-action-button.d.ts +0 -1
  59. package/esm/floating-action-button/floating-action-button.js +0 -3
  60. package/esm/icon/icon-core.js +1 -1
  61. package/esm/icon/icon-registry.js +1 -1
  62. package/esm/icon-button/icon-button-component-delegate.js +2 -1
  63. package/esm/label/label-aware.js +1 -3
  64. package/esm/list/list/list.js +1 -1
  65. package/esm/list/list-item/list-item.js +1 -1
  66. package/esm/list-dropdown/list-dropdown-core.js +4 -2
  67. package/esm/list-dropdown/list-dropdown-utils.js +5 -2
  68. package/esm/menu/menu-core.js +5 -6
  69. package/esm/overlay/overlay-constants.d.ts +1 -1
  70. package/esm/overlay/overlay-constants.js +1 -1
  71. package/esm/overlay/overlay.d.ts +2 -2
  72. package/esm/overlay/overlay.js +2 -2
  73. package/esm/select/core/base-select-adapter.js +0 -1
  74. package/esm/select/core/base-select-core.js +70 -74
  75. package/esm/select/core/select-utils.d.ts +1 -1
  76. package/esm/select/core/select-utils.js +2 -2
  77. package/esm/select/select-dropdown/select-dropdown-adapter.js +1 -3
  78. package/esm/split-view/split-view-panel/split-view-panel.js +1 -1
  79. package/esm/table/table-utils.js +10 -12
  80. package/esm/tabs/tab-bar/tab-bar-core.js +2 -1
  81. package/esm/text-field/text-field-adapter.js +1 -3
  82. package/esm/time-picker/time-picker-core.js +5 -5
  83. package/esm/toast/toast-adapter.js +1 -1
  84. package/esm/toast/toast-core.js +1 -1
  85. package/esm/toast/toast.js +2 -1
  86. package/esm/tooltip/tooltip.js +1 -1
  87. package/esm/view-switcher/view-switcher-core.js +2 -1
  88. package/package.json +1 -1
  89. package/sass/core/styles/tokens/badge/_tokens.scss +1 -1
  90. package/sass/list/list/list.scss +4 -2
  91. package/sass/list/list-item/list-item.scss +3 -1
  92. package/sass/table/forge-table.scss +0 -1
  93. package/sass/utils/_mixins.scss +7 -8
@@ -4,92 +4,251 @@
4
4
  * License: Apache-2.0
5
5
  */
6
6
  import { isValidDate } from '@tylertech/forge-core';
7
- export const ISO_8601_REGEX = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
7
+ export const ISO_8601_REGEX = /^([+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([.,]\d+(?!:))?)?(\17[0-5]\d([.,]\d+)?)?([zZ]|([+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
8
8
  export const ISO_TIMEZONE_REGEX = /a-z/i;
9
9
  const FUTURE_YEAR_COERCION = 10; // The number of years in the future to coerce two-digit years into current century
10
- /**
11
- * Parses a date string value to a `Date` object in local time.
12
- * @param str The date string value.
13
- */
14
- export function parseDateString(value) {
15
- value = value.replace(/_|\s/g, ''); // Remove potential extraneous characters
16
- // We first check if this is a valid date in ISO 8601 format and return it if so
17
- if (ISO_8601_REGEX.test(value)) {
18
- const iso8601Date = new Date(value);
19
- // This is an ISO string, but does it have a timezone? If not, we add current timezone offset
20
- if (!ISO_TIMEZONE_REGEX.test(value)) {
21
- iso8601Date.setMinutes(iso8601Date.getMinutes() + iso8601Date.getTimezoneOffset());
22
- }
23
- if (isValidDate(iso8601Date)) {
24
- return iso8601Date;
25
- }
10
+ const MONTH_ABBREVIATIONS = {
11
+ JAN: 1,
12
+ FEB: 2,
13
+ MAR: 3,
14
+ APR: 4,
15
+ MAY: 5,
16
+ JUN: 6,
17
+ JUL: 7,
18
+ AUG: 8,
19
+ SEP: 9,
20
+ OCT: 10,
21
+ NOV: 11,
22
+ DEC: 12
23
+ };
24
+ const MONTH_NAMES = {
25
+ 1: 'JAN',
26
+ 2: 'FEB',
27
+ 3: 'MAR',
28
+ 4: 'APR',
29
+ 5: 'MAY',
30
+ 6: 'JUN',
31
+ 7: 'JUL',
32
+ 8: 'AUG',
33
+ 9: 'SEP',
34
+ 10: 'OCT',
35
+ 11: 'NOV',
36
+ 12: 'DEC'
37
+ };
38
+ const DATE_PATTERNS = [
39
+ // YYYY-MM-DD (ISO-like numeric)
40
+ {
41
+ regex: /^(\d{4})-(\d{1,2})-(\d{1,2})$/,
42
+ parser: ([year, month, day]) => parseNumericDate(year, month, day, 'YMD')
43
+ },
44
+ // YYYY-MMM-DD
45
+ {
46
+ regex: /^(\d{4})-([A-Za-z]{3})-(\d{1,2})$/,
47
+ parser: ([year, monthAbbr, day]) => parseWithMonthAbbr(year, monthAbbr, day, 'YMD')
48
+ },
49
+ // MM/DD/YYYY or MM/DD/YY
50
+ {
51
+ regex: /^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/,
52
+ parser: ([month, day, year]) => parseNumericDate(month, day, year, 'MDY')
53
+ },
54
+ // MM-DD-YYYY or MM-DD-YY
55
+ {
56
+ regex: /^(\d{1,2})-(\d{1,2})-(\d{2,4})$/,
57
+ parser: ([month, day, year]) => parseNumericDate(month, day, year, 'MDY')
58
+ },
59
+ // DD/MMM/YYYY
60
+ {
61
+ regex: /^(\d{1,2})\/([A-Za-z]{3})\/(\d{2,4})$/,
62
+ parser: ([day, monthAbbr, year]) => parseWithMonthAbbr(day, monthAbbr, year, 'DMY')
63
+ },
64
+ // DD-MMM-YYYY
65
+ {
66
+ regex: /^(\d{1,2})-([A-Za-z]{3})-(\d{2,4})$/,
67
+ parser: ([day, monthAbbr, year]) => parseWithMonthAbbr(day, monthAbbr, year, 'DMY')
68
+ },
69
+ // Numeric without separators (MMDDYYYY or MMDDYY)
70
+ {
71
+ regex: /^(\d{2})(\d{2})(\d{2,4})$/,
72
+ parser: ([month, day, year]) => parseNumericDate(month, day, year, 'MDY')
73
+ },
74
+ // DD.MM.YYYY or DD.MM.YY
75
+ {
76
+ regex: /^(\d{1,2})\.(\d{1,2})\.(\d{2,4})$/,
77
+ parser: ([day, month, year]) => parseNumericDate(day, month, year, 'DMY')
26
78
  }
27
- let values = [];
28
- // We accept dates with a "/" or "-" separator and in the format of MM/DD/YYYY
29
- if (value.indexOf('/') !== -1) {
30
- values = value.split('/');
79
+ ];
80
+ const FORMAT_CONFIGS = {
81
+ 'MM/DD/YYYY': {
82
+ pattern: 'MM/DD/YYYY',
83
+ formatter: date => `${pad(date.getMonth() + 1)}/${pad(date.getDate())}/${date.getFullYear()}`
84
+ },
85
+ 'MM/DD/YY': {
86
+ pattern: 'MM/DD/YY',
87
+ formatter: date => `${pad(date.getMonth() + 1)}/${pad(date.getDate())}/${String(date.getFullYear()).slice(-2)}`
88
+ },
89
+ 'DD/MMM/YYYY': {
90
+ pattern: 'DD/MMM/YYYY',
91
+ formatter: date => `${pad(date.getDate())}/${MONTH_NAMES[(date.getMonth() + 1)]}/${date.getFullYear()}`
92
+ },
93
+ 'MM-DD-YYYY': {
94
+ pattern: 'MM-DD-YYYY',
95
+ formatter: date => `${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${date.getFullYear()}`
96
+ },
97
+ 'MM-DD-YY': {
98
+ pattern: 'MM-DD-YY',
99
+ formatter: date => `${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${String(date.getFullYear()).slice(-2)}`
100
+ },
101
+ 'DD-MMM-YYYY': {
102
+ pattern: 'DD-MMM-YYYY',
103
+ formatter: date => `${pad(date.getDate())}-${MONTH_NAMES[(date.getMonth() + 1)]}-${date.getFullYear()}`
104
+ },
105
+ 'YYYY-MM-DD': {
106
+ pattern: 'YYYY-MM-DD',
107
+ formatter: date => `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
108
+ },
109
+ 'YYYY-MMM-DD': {
110
+ pattern: 'YYYY-MMM-DD',
111
+ formatter: date => `${date.getFullYear()}-${MONTH_NAMES[(date.getMonth() + 1)]}-${pad(date.getDate())}`
112
+ },
113
+ 'DD.MM.YYYY': {
114
+ pattern: 'DD.MM.YYYY',
115
+ formatter: date => `${pad(date.getDate())}.${pad(date.getMonth() + 1)}.${date.getFullYear()}`
116
+ },
117
+ 'DD.MM.YY': {
118
+ pattern: 'DD.MM.YY',
119
+ formatter: date => `${pad(date.getDate())}.${pad(date.getMonth() + 1)}.${String(date.getFullYear()).slice(-2)}`
31
120
  }
32
- else if (value.indexOf('-') !== -1) {
33
- values = value.split('-');
121
+ };
122
+ function pad(num) {
123
+ return String(num).padStart(2, '0');
124
+ }
125
+ function normalizeYear(year) {
126
+ if (year.length === 3) {
127
+ year = year.padStart(4, '0');
34
128
  }
35
- else if ((value.length === 6 || value.length === 8) && !isNaN(+value)) {
36
- values = [value.substring(0, 2), value.substring(2, 4), value.substring(4)];
129
+ if (year.length === 2) {
130
+ const currentYear = new Date().getFullYear();
131
+ const minYear = currentYear - (100 - FUTURE_YEAR_COERCION);
132
+ const maxYear = currentYear + FUTURE_YEAR_COERCION;
133
+ const minCentury = String(minYear).slice(0, 2);
134
+ const maxCentury = String(maxYear).slice(0, 2);
135
+ const maxYearLastTwo = +String(maxYear).slice(2);
136
+ return +year <= maxYearLastTwo ? +`${maxCentury}${year}` : +`${minCentury}${year}`;
37
137
  }
38
- const hasMonthDayYear = values.length === 3;
39
- let [month, day, year] = values;
40
- // Ensure are month and year values are coerced from 0 to 1 in case of incomplete entry
41
- if (month === '0') {
42
- month = '1';
138
+ return +year;
139
+ }
140
+ function validateAndClampDate(month, day, year) {
141
+ const clampedMonth = Math.min(Math.max(month, 1), 12);
142
+ const maxDaysInMonth = new Date(year, clampedMonth, 0).getDate();
143
+ const clampedDay = Math.min(Math.max(day, 1), maxDaysInMonth);
144
+ return { month: clampedMonth, day: clampedDay, year };
145
+ }
146
+ function parseMonthAbbreviation(abbr) {
147
+ const upperAbbr = abbr.toUpperCase();
148
+ return MONTH_ABBREVIATIONS[upperAbbr] || null;
149
+ }
150
+ function parseNumericDate(part1, part2, part3, order) {
151
+ let monthStr;
152
+ let dayStr;
153
+ let yearStr;
154
+ if (order === 'MDY') {
155
+ [monthStr, dayStr, yearStr] = [part1, part2, part3];
43
156
  }
44
- if (day === '0') {
45
- day = '1';
157
+ else if (order === 'YMD') {
158
+ [yearStr, monthStr, dayStr] = [part1, part2, part3];
46
159
  }
47
- // Trap for the case where only 3 digit years are entered
48
- if (typeof year === 'string' && year.length === 3) {
49
- year = year.padStart(4, '0');
160
+ else {
161
+ // DMY
162
+ [dayStr, monthStr, yearStr] = [part1, part2, part3];
50
163
  }
51
- if (hasMonthDayYear) {
52
- const isValidMonthLength = month.length === 1 || month.length === 2;
53
- const isValidDayLength = day.length === 1 || day.length === 2;
54
- const isValidYearLength = year.length === 2 || year.length === 4;
55
- if (!isValidMonthLength || !isValidDayLength || !isValidYearLength) {
56
- return null;
57
- }
164
+ // Handle edge cases for incomplete input
165
+ if (monthStr === '0') {
166
+ monthStr = '1';
167
+ }
168
+ if (dayStr === '0') {
169
+ dayStr = '1';
170
+ }
171
+ const year = normalizeYear(yearStr);
172
+ const month = +monthStr;
173
+ const day = +dayStr;
174
+ const { month: validMonth, day: validDay, year: validYear } = validateAndClampDate(month, day, year);
175
+ const date = new Date(validYear, validMonth - 1, validDay, 0, 0, 0, 0);
176
+ return isValidDate(date) ? date : null;
177
+ }
178
+ function parseWithMonthAbbr(part1, monthAbbr, part3, order) {
179
+ const monthNum = parseMonthAbbreviation(monthAbbr);
180
+ if (!monthNum) {
181
+ return null;
182
+ }
183
+ let dayStr;
184
+ let yearStr;
185
+ if (order === 'DMY') {
186
+ [dayStr, yearStr] = [part1, part3];
58
187
  }
59
188
  else {
189
+ [yearStr, dayStr] = [part1, part3];
190
+ }
191
+ const year = normalizeYear(yearStr);
192
+ const day = +dayStr;
193
+ const { day: validDay, year: validYear } = validateAndClampDate(monthNum, day, year);
194
+ const date = new Date(validYear, monthNum - 1, validDay, 0, 0, 0, 0);
195
+ return isValidDate(date) ? date : null;
196
+ }
197
+ function parseISO8601(value) {
198
+ if (!ISO_8601_REGEX.test(value)) {
60
199
  return null;
61
200
  }
62
- // Check if we need to coerce two-digit years to the four-digit equivalent
63
- if (year.length === 2) {
64
- const minYear = new Date().getFullYear() - (100 - FUTURE_YEAR_COERCION);
65
- const maxYear = new Date().getFullYear() + FUTURE_YEAR_COERCION;
66
- const minYearCentury = String(minYear).slice(0, 2);
67
- const maxYearCentury = String(maxYear).slice(0, 2);
68
- const normalizedMaxYear = +String(maxYear).slice(2);
69
- year = +year <= normalizedMaxYear ? `${maxYearCentury}${year}` : `${minYearCentury}${year}`;
70
- }
71
- let numMonth = +month;
72
- let numDay = +day;
73
- const numYear = +year;
74
- if (numMonth > 12) {
75
- numMonth = 12;
76
- }
77
- const maxDaysInMonth = new Date(numYear, numMonth, 0).getDate();
78
- if (numDay > maxDaysInMonth) {
79
- numDay = maxDaysInMonth;
80
- }
81
- const parsedDate = new Date(numYear, numMonth - 1, numDay, 0, 0, 0, 0);
82
- return isValidDate(parsedDate) ? parsedDate : null;
201
+ const date = new Date(value);
202
+ // Handle timezone offset for ISO strings without explicit timezone
203
+ if (!ISO_TIMEZONE_REGEX.test(value)) {
204
+ date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
205
+ }
206
+ return isValidDate(date) ? date : null;
83
207
  }
84
208
  /**
85
- * Formats a `Date` to a specified format.
86
- * @param str The date string value.
209
+ * Parses a date string value to a `Date` object in local time.
210
+ * Supports multiple formats as defined in SupportedDateFormats.
211
+ *
212
+ * @param value The date string value to parse
213
+ * @param format Optional format hint for better parsing accuracy
214
+ * @returns Parsed Date object or null if parsing fails
87
215
  */
88
- export function formatDate(date) {
89
- const month = String(date.getMonth() + 1).padStart(2, '0');
90
- const day = String(date.getDate()).padStart(2, '0');
91
- const year = String(date.getFullYear()).padStart(4, '0');
92
- return [month, day, year].join('/');
216
+ export function parseDateString(value, format) {
217
+ const cleanValue = value.replace(/[_\s]/g, '');
218
+ // Try ISO 8601 first
219
+ const isoDate = parseISO8601(cleanValue);
220
+ if (isoDate) {
221
+ return isoDate;
222
+ }
223
+ // Try each pattern until one matches
224
+ for (const pattern of DATE_PATTERNS) {
225
+ const match = cleanValue.match(pattern.regex);
226
+ if (match) {
227
+ const result = pattern.parser(match.slice(1));
228
+ if (result) {
229
+ return result;
230
+ }
231
+ }
232
+ }
233
+ return null;
234
+ }
235
+ /**
236
+ * Formats a Date object to a specified string format.
237
+ *
238
+ * @param date The Date object to format
239
+ * @param format The desired output format (defaults to 'MM/DD/YYYY')
240
+ * @returns Formatted date string
241
+ * @throws Error if date is invalid or format is unsupported
242
+ */
243
+ export function formatDate(date, format = 'MM/DD/YYYY') {
244
+ if (!isValidDate(date)) {
245
+ throw new Error('Invalid date provided');
246
+ }
247
+ const config = FORMAT_CONFIGS[format];
248
+ if (!config) {
249
+ throw new Error(`Unsupported format: ${format}`);
250
+ }
251
+ return config.formatter(date);
93
252
  }
94
253
  /**
95
254
  * Determines if two date objects are equal.
@@ -18,7 +18,6 @@ export class DismissibleStack {
18
18
  get dismissing() {
19
19
  return this._deferredDismiss?.promise ?? Promise.resolve();
20
20
  }
21
- // eslint-disable-next-line @tylertech-eslint/require-private-modifier
22
21
  constructor() {
23
22
  /**
24
23
  * A set of all elements that are currently eligible for dismissal.
@@ -9,7 +9,7 @@ import { Platform } from '@tylertech/forge-core';
9
9
  * @returns {boolean}
10
10
  */
11
11
  export function supportsPopover() {
12
- return HTMLElement.prototype.hasOwnProperty('popover');
12
+ return Object.prototype.hasOwnProperty.call(HTMLElement.prototype, 'popover');
13
13
  }
14
14
  /**
15
15
  * Detects if the browser supports ARIA properties in Element Internals.
@@ -19,7 +19,7 @@ export function supportsPopover() {
19
19
  * @returns {boolean}
20
20
  */
21
21
  export function supportsElementInternalsAria() {
22
- return ElementInternals.prototype.hasOwnProperty('role');
22
+ return Object.prototype.hasOwnProperty.call(ElementInternals.prototype, 'role');
23
23
  }
24
24
  /**
25
25
  * Detects if the browser supports the hovering elements as the users primary input mechanism.
@@ -7,6 +7,7 @@ import { DateRange, DayOfWeek, ICalendarComponent } from '../../calendar';
7
7
  import { ICalendarDropdown, ICalendarDropdownPopupConfig } from '../../calendar/calendar-dropdown';
8
8
  import { BaseAdapter, IBaseAdapter, IDateInputMaskOptions } from '../../core';
9
9
  import { BaseComponent } from '../../core/base/base-component';
10
+ import { IIconButtonComponent } from '../../icon-button';
10
11
  import { IDatePickerCalendarDropdownText } from './base-date-picker-constants';
11
12
  export interface IBaseDatePickerAdapter extends IBaseAdapter {
12
13
  initialize(): void;
@@ -98,6 +99,6 @@ export declare abstract class BaseDatePickerAdapter<T extends BaseComponent> ext
98
99
  setCalendarText(text: IDatePickerCalendarDropdownText): void;
99
100
  propagateCalendarKey(evt: KeyboardEvent): void;
100
101
  tryCreateToggle(): void;
101
- protected _createToggleElement(): HTMLElement;
102
+ protected _createToggleElement(): IIconButtonComponent;
102
103
  protected _getDefaultTargetElement(): HTMLElement;
103
104
  }
@@ -173,6 +173,10 @@ export class BaseDatePickerAdapter extends BaseAdapter {
173
173
  return;
174
174
  }
175
175
  const iconButtonElement = this._createToggleElement();
176
+ // Inherit the density from the text field in certain cases
177
+ if (textField.density === 'extra-small') {
178
+ iconButtonElement.density = 'small';
179
+ }
176
180
  textField.appendChild(iconButtonElement);
177
181
  this._toggleElement = iconButtonElement;
178
182
  }
@@ -5,10 +5,19 @@
5
5
  */
6
6
  import { Masked, InputMask, type AppendFlags, type FactoryArg } from 'imask';
7
7
  import { DayOfWeek, ICalendarDateSelectEventData } from '../../calendar';
8
- export declare type DatePickerParseCallback = (value: string) => Date | null;
9
- export declare type DatePickerFormatCallback = (value: Date | null) => string;
10
- export declare type DatePickerPrepareMaskCallback = (value: string, masked: Masked<string>, flags: AppendFlags, maskInstance: InputMask<FactoryArg>) => string;
11
- export declare type DatePickerValueMode = 'object' | 'string' | 'iso-string';
8
+ import { type IDatePickerComponent } from '../date-picker';
9
+ import { SupportedDateFormats } from '../../core/utils/date-utils';
10
+ export type DatePickerParseCallback = (value: string) => Date | null;
11
+ export type DatePickerFormatCallback = (value: Date | null) => string | null;
12
+ export type DatePickerPrepareMaskCallback = (value: string, masked: Masked<string>, flags: AppendFlags, maskInstance: InputMask<FactoryArg>) => string;
13
+ export type DatePickerValueMode = 'object' | 'string' | 'iso-string';
14
+ export type DatePickerShortcuts = IDatePickerShortcuts | 'off' | undefined;
15
+ export type DatePickerDateFormat = SupportedDateFormats;
16
+ export interface IDatePickerShortcuts {
17
+ [key: string]: (context: {
18
+ instance: IDatePickerComponent;
19
+ }) => Date | null | undefined | void;
20
+ }
12
21
  export interface IDatePickerCalendarDropdownConfig<T> {
13
22
  value?: T | null;
14
23
  min?: Date | null;
@@ -45,7 +54,9 @@ export declare const BASE_DATE_PICKER_CONSTANTS: {
45
54
  MASKED: string;
46
55
  MASK_FORMAT: string;
47
56
  SHOW_MASK_FORMAT: string;
57
+ DATE_FORMAT: string;
48
58
  VALUE_MODE: string;
59
+ SHORTCUTS: string;
49
60
  ALLOW_INVALID_DATE: string;
50
61
  SHOW_TODAY: string;
51
62
  SHOW_CLEAR: string;
@@ -61,4 +72,8 @@ export declare const BASE_DATE_PICKER_CONSTANTS: {
61
72
  INPUT: string;
62
73
  TOGGLE: string;
63
74
  };
75
+ defaults: {
76
+ DATE_FORMAT: DatePickerDateFormat;
77
+ };
78
+ supportedDateFormats: SupportedDateFormats[];
64
79
  };
@@ -12,7 +12,9 @@ const observedAttributes = {
12
12
  MASKED: 'masked',
13
13
  MASK_FORMAT: 'mask-format',
14
14
  SHOW_MASK_FORMAT: 'show-mask-format',
15
+ DATE_FORMAT: 'date-format',
15
16
  VALUE_MODE: 'value-mode',
17
+ SHORTCUTS: 'shortcuts',
16
18
  ALLOW_INVALID_DATE: 'allow-invalid-date',
17
19
  SHOW_TODAY: 'show-today',
18
20
  SHOW_CLEAR: 'show-clear',
@@ -28,8 +30,25 @@ const selectors = {
28
30
  INPUT: 'input',
29
31
  TOGGLE: '[forge-date-picker-toggle],[data-forge-date-picker-toggle]'
30
32
  };
33
+ const defaults = {
34
+ DATE_FORMAT: 'MM/DD/YYYY'
35
+ };
36
+ const supportedDateFormats = [
37
+ 'MM/DD/YYYY',
38
+ 'MM/DD/YY',
39
+ 'DD/MMM/YYYY',
40
+ 'MM-DD-YYYY',
41
+ 'MM-DD-YY',
42
+ 'DD-MMM-YYYY',
43
+ 'YYYY-MM-DD',
44
+ 'YYYY-MMM-DD',
45
+ 'DD.MM.YYYY',
46
+ 'DD.MM.YY'
47
+ ];
31
48
  export const BASE_DATE_PICKER_CONSTANTS = {
32
49
  observedAttributes,
33
50
  attributes,
34
- selectors
51
+ selectors,
52
+ defaults,
53
+ supportedDateFormats
35
54
  };
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { CalendarMode, DayOfWeek, ICalendarDateSelectEventData } from '../../calendar/calendar-constants';
7
7
  import { IBaseDatePickerAdapter } from './base-date-picker-adapter';
8
- import { DatePickerFormatCallback, DatePickerParseCallback, DatePickerPrepareMaskCallback, DatePickerValueMode, IDatePickerCalendarDropdownText } from './base-date-picker-constants';
8
+ import { DatePickerFormatCallback, DatePickerParseCallback, DatePickerPrepareMaskCallback, IDatePickerShortcuts, DatePickerValueMode, IDatePickerCalendarDropdownText, DatePickerShortcuts, DatePickerDateFormat } from './base-date-picker-constants';
9
9
  export interface IBaseDatePickerCore<TValue> {
10
10
  value: TValue | null | undefined;
11
11
  min: Date | string | null | undefined;
@@ -20,6 +20,7 @@ export interface IBaseDatePickerCore<TValue> {
20
20
  masked: boolean;
21
21
  maskFormat: string;
22
22
  showMaskFormat: boolean;
23
+ dateFormat: DatePickerDateFormat;
23
24
  valueMode: DatePickerValueMode;
24
25
  notifyInputValueChanges: boolean;
25
26
  allowInvalidDate: boolean;
@@ -45,7 +46,9 @@ export declare abstract class BaseDatePickerCore<TAdapter extends IBaseDatePicke
45
46
  protected _masked: boolean;
46
47
  protected _maskFormat: string;
47
48
  protected _showMaskFormat: boolean;
49
+ protected _dateFormat: DatePickerDateFormat;
48
50
  protected _valueMode: DatePickerValueMode;
51
+ protected _shortcuts: IDatePickerShortcuts | undefined;
49
52
  protected _notifyInputValueChanges: boolean;
50
53
  protected _allowInvalidDate: boolean;
51
54
  protected _showToday: boolean;
@@ -95,6 +98,7 @@ export declare abstract class BaseDatePickerCore<TAdapter extends IBaseDatePicke
95
98
  protected _onInputBlur(evt: FocusEvent): void;
96
99
  protected _openCalendar(emitOpenEvent?: boolean): void;
97
100
  protected _closeCalendar(emitCloseEvent?: boolean): void;
101
+ private _getDefaultShortcuts;
98
102
  protected _onInputKeydown(evt: KeyboardEvent): void;
99
103
  protected _getSanitizedDateString(value: string): string;
100
104
  private _onToggleMousedown;
@@ -102,19 +106,21 @@ export declare abstract class BaseDatePickerCore<TAdapter extends IBaseDatePicke
102
106
  private _onMonthChanged;
103
107
  private _onActiveDescendantChanged;
104
108
  protected _formatInputValue(): void;
105
- protected _formatDate(date: Date | null | undefined): string;
109
+ protected _formatDate(date: Date | null | undefined): string | null;
106
110
  protected _parseDateString(value: string): Date | null;
107
111
  protected _coerceDateValue(value?: Date | string | null): Date | null | undefined;
108
112
  protected _getTypedValue(value: Date | null | undefined): Date | string | null | undefined;
109
113
  protected _isDateValueAcceptable(value?: Date | null): boolean;
110
114
  protected _initializeMask(): void;
111
- private _applyMask;
115
+ protected _applyMask(): void;
112
116
  protected _applyMin(): void;
113
117
  protected _applyMax(): void;
114
118
  private _applyDisableDayCallback;
115
119
  private _applyDisabled;
116
120
  get valueMode(): DatePickerValueMode;
117
121
  set valueMode(value: DatePickerValueMode);
122
+ get shortcuts(): DatePickerShortcuts;
123
+ set shortcuts(value: DatePickerShortcuts);
118
124
  get min(): Date | string | null | undefined;
119
125
  set min(value: Date | string | null | undefined);
120
126
  get max(): Date | string | null | undefined;
@@ -133,6 +139,8 @@ export declare abstract class BaseDatePickerCore<TAdapter extends IBaseDatePicke
133
139
  set maskFormat(value: string);
134
140
  get showMaskFormat(): boolean;
135
141
  set showMaskFormat(value: boolean);
142
+ get dateFormat(): DatePickerDateFormat;
143
+ set dateFormat(value: DatePickerDateFormat);
136
144
  get notifyInputValueChanges(): boolean;
137
145
  set notifyInputValueChanges(value: boolean);
138
146
  get allowInvalidDate(): boolean;