@aurodesignsystem/auro-formkit 3.1.0-beta.1 → 3.2.0-beta.1

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 (59) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/components/checkbox/README.md +1 -1
  3. package/components/checkbox/demo/api.min.js +468 -25
  4. package/components/checkbox/demo/index.min.js +468 -25
  5. package/components/checkbox/demo/readme.md +1 -1
  6. package/components/checkbox/dist/index.js +468 -25
  7. package/components/checkbox/dist/registered.js +468 -25
  8. package/components/combobox/README.md +1 -1
  9. package/components/combobox/demo/api.min.js +1125 -74
  10. package/components/combobox/demo/index.min.js +1125 -74
  11. package/components/combobox/demo/readme.md +1 -1
  12. package/components/combobox/dist/auro-combobox.d.ts +30 -0
  13. package/components/combobox/dist/index.js +1125 -74
  14. package/components/combobox/dist/registered.js +1125 -74
  15. package/components/counter/README.md +1 -1
  16. package/components/counter/demo/api.min.js +570 -45
  17. package/components/counter/demo/index.min.js +570 -45
  18. package/components/counter/demo/readme.md +1 -1
  19. package/components/counter/dist/index.js +570 -45
  20. package/components/counter/dist/registered.js +570 -45
  21. package/components/datepicker/README.md +1 -1
  22. package/components/datepicker/demo/api.min.js +1073 -70
  23. package/components/datepicker/demo/index.min.js +1073 -70
  24. package/components/datepicker/demo/readme.md +1 -1
  25. package/components/datepicker/dist/index.js +1073 -70
  26. package/components/datepicker/dist/registered.js +1073 -70
  27. package/components/dropdown/README.md +1 -1
  28. package/components/dropdown/demo/api.md +8 -5
  29. package/components/dropdown/demo/api.min.js +104 -22
  30. package/components/dropdown/demo/index.min.js +104 -22
  31. package/components/dropdown/demo/readme.md +1 -1
  32. package/components/dropdown/dist/auro-dropdown.d.ts +29 -0
  33. package/components/dropdown/dist/index.js +104 -22
  34. package/components/dropdown/dist/registered.js +104 -22
  35. package/components/form/README.md +1 -1
  36. package/components/form/demo/readme.md +1 -1
  37. package/components/input/README.md +1 -1
  38. package/components/input/demo/api.md +4 -1
  39. package/components/input/demo/api.min.js +503 -25
  40. package/components/input/demo/index.min.js +503 -25
  41. package/components/input/demo/readme.md +1 -1
  42. package/components/input/dist/base-input.d.ts +24 -0
  43. package/components/input/dist/index.js +503 -25
  44. package/components/input/dist/registered.js +503 -25
  45. package/components/menu/README.md +1 -1
  46. package/components/menu/demo/readme.md +1 -1
  47. package/components/radio/README.md +1 -1
  48. package/components/radio/demo/api.min.js +468 -25
  49. package/components/radio/demo/index.min.js +468 -25
  50. package/components/radio/demo/readme.md +1 -1
  51. package/components/radio/dist/index.js +468 -25
  52. package/components/radio/dist/registered.js +468 -25
  53. package/components/select/README.md +1 -1
  54. package/components/select/demo/api.min.js +570 -45
  55. package/components/select/demo/index.min.js +570 -45
  56. package/components/select/demo/readme.md +1 -1
  57. package/components/select/dist/index.js +570 -45
  58. package/components/select/dist/registered.js +570 -45
  59. package/package.json +2 -2
@@ -31,6 +31,414 @@ const t$2=globalThis,i$3=t$2.trustedTypes,s$2=i$3?i$3.createPolicy("lit-html",{c
31
31
  */
32
32
  const a=Symbol.for(""),o$2=t=>{if(t?.r===a)return t?._$litStatic$},s$1=t=>({_$litStatic$:t,r:a}),i$1=(t,...r)=>({_$litStatic$:r.reduce(((r,e,a)=>r+(t=>{if(void 0!==t._$litStatic$)return t._$litStatic$;throw Error(`Value passed to 'literal' function must be a 'literal' result: ${t}. Use 'unsafeStatic' to pass non-literal values, but\n take care to ensure page security.`)})(e)+t[a+1]),t[0]),r:a}),l=new Map,n$1=t=>(r,...e)=>{const a=e.length;let s,i;const n=[],u=[];let c,$=0,f=false;for(;$<a;){for(c=r[$];$<a&&void 0!==(i=e[$],s=o$2(i));)c+=s+r[++$],f=true;$!==a&&u.push(i),n.push(c),$++;}if($===a&&n.push(r[a]),f){const t=n.join("$$lit$$");void 0===(r=l.get(t))&&(n.raw=n,l.set(t,r=n)),e=u;}return t(r,...e)},u$2=n$1(x);
33
33
 
34
+ let DateFormatter$1 = class DateFormatter {
35
+
36
+ constructor() {
37
+
38
+ /**
39
+ * @description Parses a date string into its components.
40
+ * @param {string} dateStr - Date string to parse.
41
+ * @param {string} format - Date format to parse.
42
+ * @returns {Object<key["month" | "day" | "year"]: number>|undefined}
43
+ */
44
+ this.parseDate = (dateStr, format = 'mm/dd/yyyy') => {
45
+
46
+ // Guard Clause: Date string is defined
47
+ if (!dateStr) {
48
+ return undefined;
49
+ }
50
+
51
+ // Assume the separator is a "/" a defined in our code base
52
+ const separator = '/';
53
+
54
+ // Get the parts of the date and format
55
+ const valueParts = dateStr.split(separator);
56
+ const formatParts = format.split(separator);
57
+
58
+ // Check if the value and format have the correct number of parts
59
+ if (valueParts.length !== formatParts.length) {
60
+ throw new Error('AuroDatepickerUtilities | parseDate: Date string and format length do not match');
61
+ }
62
+
63
+ // Holds the result to be returned
64
+ const result = formatParts.reduce((acc, part, index) => {
65
+ const value = valueParts[index];
66
+
67
+ if ((/m/iu).test(part)) {
68
+ acc.month = value;
69
+ } else if ((/d/iu).test(part)) {
70
+ acc.day = value;
71
+ } else if ((/y/iu).test(part)) {
72
+ acc.year = value;
73
+ }
74
+
75
+ return acc;
76
+ }, {});
77
+
78
+ // If we found all the parts, return the result
79
+ if (result.month && result.year) {
80
+ return result;
81
+ }
82
+
83
+ // Throw an error to let the dev know we were unable to parse the date string
84
+ throw new Error('AuroDatepickerUtilities | parseDate: Unable to parse date string');
85
+ };
86
+
87
+ /**
88
+ * Convert a date object to string format.
89
+ * @param {Object} date - Date to convert to string.
90
+ * @returns {Object} Returns the date as a string.
91
+ */
92
+ this.getDateAsString = (date) => date.toLocaleDateString(undefined, {
93
+ year: "numeric",
94
+ month: "2-digit",
95
+ day: "2-digit",
96
+ });
97
+
98
+ /**
99
+ * Converts a date string to a North American date format.
100
+ * @param {String} dateStr - Date to validate.
101
+ * @param {String} format - Date format to validate against.
102
+ * @returns {Boolean}
103
+ */
104
+ this.toNorthAmericanFormat = (dateStr, format) => {
105
+
106
+ if (format === 'mm/dd/yyyy') {
107
+ return dateStr;
108
+ }
109
+
110
+ const parsedDate = this.parseDate(dateStr, format);
111
+
112
+ if (!parsedDate) {
113
+ throw new Error('AuroDatepickerUtilities | toNorthAmericanFormat: Unable to parse date string');
114
+ }
115
+
116
+ const { month, day, year } = parsedDate;
117
+
118
+ const dateParts = [];
119
+ if (month) {
120
+ dateParts.push(month);
121
+ }
122
+
123
+ if (day) {
124
+ dateParts.push(day);
125
+ }
126
+
127
+ if (year) {
128
+ dateParts.push(year);
129
+ }
130
+
131
+ return dateParts.join('/');
132
+ };
133
+ }
134
+ };
135
+ const dateFormatter$1 = new DateFormatter$1();
136
+
137
+ // filepath: dateConstraints.mjs
138
+ const DATE_UTIL_CONSTRAINTS$1 = {
139
+ maxDay: 31,
140
+ maxMonth: 12,
141
+ maxYear: 2400,
142
+ minDay: 1,
143
+ minMonth: 1,
144
+ minYear: 1900,
145
+ };
146
+
147
+ let AuroDateUtilitiesBase$1 = class AuroDateUtilitiesBase {
148
+
149
+ /**
150
+ * @description The maximum day value allowed by the various utilities in this class.
151
+ * @readonly
152
+ * @type {Number}
153
+ */
154
+ get maxDay() {
155
+ return DATE_UTIL_CONSTRAINTS$1.maxDay;
156
+ }
157
+
158
+ /**
159
+ * @description The maximum month value allowed by the various utilities in this class.
160
+ * @readonly
161
+ * @type {Number}
162
+ */
163
+ get maxMonth() {
164
+ return DATE_UTIL_CONSTRAINTS$1.maxMonth;
165
+ }
166
+
167
+ /**
168
+ * @description The maximum year value allowed by the various utilities in this class.
169
+ * @readonly
170
+ * @type {Number}
171
+ */
172
+ get maxYear() {
173
+ return DATE_UTIL_CONSTRAINTS$1.maxYear;
174
+ }
175
+
176
+ /**
177
+ * @description The minimum day value allowed by the various utilities in this class.
178
+ * @readonly
179
+ * @type {Number}
180
+ */
181
+ get minDay() {
182
+ return DATE_UTIL_CONSTRAINTS$1.minDay;
183
+ }
184
+
185
+ /**
186
+ * @description The minimum month value allowed by the various utilities in this class.
187
+ * @readonly
188
+ * @type {Number}
189
+ */
190
+ get minMonth() {
191
+ return DATE_UTIL_CONSTRAINTS$1.minMonth;
192
+ }
193
+
194
+ /**
195
+ * @description The minimum year value allowed by the various utilities in this class.
196
+ * @readonly
197
+ * @type {Number}
198
+ */
199
+ get minYear() {
200
+ return DATE_UTIL_CONSTRAINTS$1.minYear;
201
+ }
202
+ };
203
+
204
+ /* eslint-disable no-magic-numbers */
205
+
206
+ let AuroDateUtilities$1 = class AuroDateUtilities extends AuroDateUtilitiesBase$1 {
207
+
208
+ /**
209
+ * Returns the current century.
210
+ * @returns {String} The current century.
211
+ */
212
+ getCentury () {
213
+ return String(new Date().getFullYear()).slice(0, 2);
214
+ }
215
+
216
+ /**
217
+ * Returns a four digit year.
218
+ * @param {String} year - The year to convert to four digits.
219
+ * @returns {String} The four digit year.
220
+ */
221
+ getFourDigitYear (year) {
222
+
223
+ const strYear = String(year).trim();
224
+ return strYear.length <= 2 ? this.getCentury() + strYear : strYear;
225
+ }
226
+
227
+ constructor() {
228
+
229
+ super();
230
+
231
+ /**
232
+ * Compares two dates to see if they match.
233
+ * @param {Object} date1 - First date to compare.
234
+ * @param {Object} date2 - Second date to compare.
235
+ * @returns {Boolean} Returns true if the dates match.
236
+ */
237
+ this.datesMatch = (date1, date2) => new Date(date1).getTime() === new Date(date2).getTime();
238
+
239
+ /**
240
+ * Returns true if value passed in is a valid date.
241
+ * @param {String} date - Date to validate.
242
+ * @param {String} format - Date format to validate against.
243
+ * @returns {Boolean}
244
+ */
245
+ this.validDateStr = (date, format) => {
246
+
247
+ // The length we expect the date string to be
248
+ const dateStrLength = format.length;
249
+
250
+ // Guard Clause: Date and format are defined
251
+ if (typeof date === "undefined" || typeof format === "undefined") {
252
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date and format are required');
253
+ }
254
+
255
+ // Guard Clause: Date should be of type string
256
+ if (typeof date !== "string") {
257
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date must be a string');
258
+ }
259
+
260
+ // Guard Clause: Format should be of type string
261
+ if (typeof format !== "string") {
262
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Format must be a string');
263
+ }
264
+
265
+ // Guard Clause: Length is what we expect it to be
266
+ if (date.length !== dateStrLength) {
267
+ return false;
268
+ }
269
+ // Get a formatted date string and parse it
270
+ const dateParts = dateFormatter$1.parseDate(date, format);
271
+
272
+ // Guard Clause: Date parse succeeded
273
+ if (!dateParts) {
274
+ return false;
275
+ }
276
+
277
+ // Create the expected date string based on the date parts
278
+ const expectedDateStr = `${dateParts.month}/${dateParts.day || "01"}/${this.getFourDigitYear(dateParts.year)}`;
279
+
280
+ // Generate a date object that we will extract a string date from to compare to the passed in date string
281
+ const dateObj = new Date(this.getFourDigitYear(dateParts.year), dateParts.month - 1, dateParts.day || 1);
282
+
283
+ // Get the date string of the date object we created from the string date
284
+ const actualDateStr = dateFormatter$1.getDateAsString(dateObj);
285
+
286
+ // Guard Clause: Generated date matches date string input
287
+ if (expectedDateStr !== actualDateStr) {
288
+ return false;
289
+ }
290
+
291
+ // If we passed all other checks, we can assume the date is valid
292
+ return true;
293
+ };
294
+
295
+ /**
296
+ * Determines if a string date value matches the format provided.
297
+ * @param {string} value = The date string value.
298
+ * @param { string} format = The date format to match against.
299
+ * @returns {boolean}
300
+ */
301
+ this.dateAndFormatMatch = (value, format) => {
302
+
303
+ // Ensure we have both values we need to do the comparison
304
+ if (!value || !format) {
305
+ throw new Error('AuroFormValidation | dateFormatMatch: value and format are required');
306
+ }
307
+
308
+ // If the lengths are different, they cannot match
309
+ if (value.length !== format.length) {
310
+ return false;
311
+ }
312
+
313
+ // Get the parts of the date
314
+ const dateParts = dateFormatter$1.parseDate(value, format);
315
+
316
+ // Validator for day
317
+ const dayValueIsValid = (day) => {
318
+
319
+ // Guard clause: if there is no day in the dateParts, we can ignore this check.
320
+ if (!dateParts.day) {
321
+ return true;
322
+ }
323
+
324
+ // Guard clause: ensure day exists.
325
+ if (!day) {
326
+ return false;
327
+ }
328
+
329
+ // Convert day to number
330
+ const numDay = Number.parseInt(day, 10);
331
+
332
+ // Guard clause: ensure day is a valid integer
333
+ if (Number.isNaN(numDay)) {
334
+ throw new Error('AuroDatepickerUtilities | dayValueIsValid: Unable to parse day value integer');
335
+ }
336
+
337
+ // Guard clause: ensure day is within the valid range
338
+ if (numDay < this.minDay || numDay > this.maxDay) {
339
+ return false;
340
+ }
341
+
342
+ // Default return
343
+ return true;
344
+ };
345
+
346
+ // Validator for month
347
+ const monthValueIsValid = (month) => {
348
+
349
+ // Guard clause: ensure month exists.
350
+ if (!month) {
351
+ return false;
352
+ }
353
+
354
+ // Convert month to number
355
+ const numMonth = Number.parseInt(month, 10);
356
+
357
+ // Guard clause: ensure month is a valid integer
358
+ if (Number.isNaN(numMonth)) {
359
+ throw new Error('AuroDatepickerUtilities | monthValueIsValid: Unable to parse month value integer');
360
+ }
361
+
362
+ // Guard clause: ensure month is within the valid range
363
+ if (numMonth < this.minMonth || numMonth > this.maxMonth) {
364
+ return false;
365
+ }
366
+
367
+ // Default return
368
+ return true;
369
+ };
370
+
371
+ // Validator for year
372
+ const yearIsValid = (_year) => {
373
+
374
+ // Guard clause: ensure year exists.
375
+ if (!_year) {
376
+ return false;
377
+ }
378
+
379
+ // Get the full year
380
+ const year = this.getFourDigitYear(_year);
381
+
382
+ // Convert year to number
383
+ const numYear = Number.parseInt(year, 10);
384
+
385
+ // Guard clause: ensure year is a valid integer
386
+ if (Number.isNaN(numYear)) {
387
+ throw new Error('AuroDatepickerUtilities | yearValueIsValid: Unable to parse year value integer');
388
+ }
389
+
390
+ // Guard clause: ensure year is within the valid range
391
+ if (numYear < this.minYear || numYear > this.maxYear) {
392
+ return false;
393
+ }
394
+
395
+ // Default return
396
+ return true;
397
+ };
398
+
399
+ // Self-contained checks for month, day, and year
400
+ const checks = [
401
+ monthValueIsValid(dateParts.month),
402
+ dayValueIsValid(dateParts.day),
403
+ yearIsValid(dateParts.year)
404
+ ];
405
+
406
+ // If any of the checks failed, the date format does not match and the result is invalid
407
+ const isValid = checks.every((check) => check === true);
408
+
409
+ // If the check is invalid, return false
410
+ if (!isValid) {
411
+ return false;
412
+ }
413
+
414
+ // Default case
415
+ return true;
416
+ };
417
+ }
418
+ };
419
+
420
+ // Export a class instance
421
+ const dateUtilities$1 = new AuroDateUtilities$1();
422
+
423
+ // Export the class instance methods individually
424
+ const {
425
+ datesMatch: datesMatch$1,
426
+ validDateStr: validDateStr$1,
427
+ dateAndFormatMatch: dateAndFormatMatch$1,
428
+ minDay: minDay$1,
429
+ minMonth: minMonth$1,
430
+ minYear: minYear$1,
431
+ maxDay: maxDay$1,
432
+ maxMonth: maxMonth$1,
433
+ maxYear: maxYear$1
434
+ } = dateUtilities$1;
435
+
436
+ const {
437
+ toNorthAmericanFormat: toNorthAmericanFormat$1,
438
+ parseDate: parseDate$1,
439
+ getDateAsString: getDateAsString$1
440
+ } = dateFormatter$1;
441
+
34
442
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
35
443
  // See LICENSE in the project root for license information.
36
444
 
@@ -106,6 +514,7 @@ let AuroLibraryRuntimeUtils$4 = class AuroLibraryRuntimeUtils {
106
514
 
107
515
 
108
516
  let AuroFormValidation$1 = class AuroFormValidation {
517
+
109
518
  constructor() {
110
519
  this.runtimeUtils = new AuroLibraryRuntimeUtils$4();
111
520
  }
@@ -197,17 +606,17 @@ let AuroFormValidation$1 = class AuroFormValidation {
197
606
  ]
198
607
  }
199
608
  };
200
-
609
+
201
610
  let elementType;
202
611
  if (this.runtimeUtils.elementMatch(elem, 'auro-input')) {
203
612
  elementType = 'input';
204
613
  } else if (this.runtimeUtils.elementMatch(elem, 'auro-counter') || this.runtimeUtils.elementMatch(elem, 'auro-counter-group')) {
205
614
  elementType = 'counter';
206
615
  }
207
-
616
+
208
617
  if (elementType) {
209
618
  const rules = validationRules[elementType];
210
-
619
+
211
620
  if (rules) {
212
621
  Object.values(rules).flat().forEach(rule => {
213
622
  if (rule.check(elem)) {
@@ -233,48 +642,82 @@ let AuroFormValidation$1 = class AuroFormValidation {
233
642
  if (!elem.value.match(emailRegex)) {
234
643
  elem.validity = 'patternMismatch';
235
644
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
645
+ return;
236
646
  }
237
647
  } else if (elem.type === 'credit-card') {
238
648
  if (elem.value.length > 0 && elem.value.length < elem.validationCCLength) {
239
649
  elem.validity = 'tooShort';
240
650
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
651
+ return;
241
652
  }
242
653
  } else if (elem.type === 'number') {
243
654
  if (elem.max !== undefined && Number(elem.max) < Number(elem.value)) {
244
655
  elem.validity = 'rangeOverflow';
245
656
  elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
657
+ return;
246
658
  }
247
659
 
248
660
  if (elem.min !== undefined && elem.value?.length > 0 && Number(elem.min) > Number(elem.value)) {
249
661
  elem.validity = 'rangeUnderflow';
250
662
  elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
663
+ return;
251
664
  }
252
- } else if (elem.type === 'date') {
253
- if (elem.value?.length > 0 && elem.value?.length < elem.lengthForType) {
665
+ } else if (elem.type === 'date' && elem.value?.length > 0) {
666
+
667
+ // Guard Clause: if the value is too short
668
+ if (elem.value.length < elem.lengthForType) {
669
+
254
670
  elem.validity = 'tooShort';
255
671
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
256
- } else if (elem.value?.length === elem.lengthForType && elem.util.toNorthAmericanFormat(elem.value, elem.format)) {
257
- const formattedValue = elem.util.toNorthAmericanFormat(elem.value, elem.format);
258
- const valueDate = new Date(formattedValue.dateForComparison);
672
+ return;
673
+ }
674
+
675
+ // Guard Clause: If the value is too long for the type
676
+ if (elem.value?.length > elem.lengthForType) {
259
677
 
260
- // validate max
261
- if (elem.max?.length === elem.lengthForType) {
262
- const maxDate = new Date(elem.util.toNorthAmericanFormat(elem.max, elem.format).dateForComparison);
678
+ elem.validity = 'tooLong';
679
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
680
+ return;
681
+ }
682
+
683
+ // Validate that the date passed was the correct format
684
+ if (!dateAndFormatMatch$1(elem.value, elem.format)) {
685
+ elem.validity = 'patternMismatch';
686
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || 'Invalid Date Format Entered';
687
+ return;
688
+ }
689
+
690
+ // Validate that the date passed was a valid date
691
+ if (!validDateStr$1(elem.value, elem.format)) {
692
+ elem.validity = 'invalidDate';
693
+ elem.errorMessage = elem.setCustomValidityInvalidDate || elem.setCustomValidity || 'Invalid Date Entered';
694
+ return;
695
+ }
263
696
 
264
- if (valueDate > maxDate) {
265
- elem.validity = 'rangeOverflow';
266
- elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
267
- }
697
+ // Perform the rest of the validation
698
+ const formattedValue = toNorthAmericanFormat$1(elem.value, elem.format);
699
+ const valueDate = new Date(formattedValue);
700
+
701
+ // // Validate max date
702
+ if (elem.max?.length === elem.lengthForType) {
703
+
704
+ const maxDate = new Date(toNorthAmericanFormat$1(elem.max, elem.format));
705
+
706
+ if (valueDate > maxDate) {
707
+ elem.validity = 'rangeOverflow';
708
+ elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
709
+ return;
268
710
  }
711
+ }
269
712
 
270
- // validate min
271
- if (elem.min?.length === elem.lengthForType) {
272
- const minDate = new Date(elem.util.toNorthAmericanFormat(elem.min, elem.format).dateForComparison);
713
+ // Validate min date
714
+ if (elem.min?.length === elem.lengthForType) {
715
+ const minDate = new Date(toNorthAmericanFormat$1(elem.min, elem.format));
273
716
 
274
- if (valueDate < minDate) {
275
- elem.validity = 'rangeUnderflow';
276
- elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
277
- }
717
+ if (valueDate < minDate) {
718
+ elem.validity = 'rangeUnderflow';
719
+ elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
720
+ return;
278
721
  }
279
722
  }
280
723
  }
@@ -393,7 +836,7 @@ let AuroFormValidation$1 = class AuroFormValidation {
393
836
  if (input.validationMessage.length > 0) {
394
837
  elem.errorMessage = input.validationMessage;
395
838
  }
396
- } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
839
+ } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
397
840
  const firstInput = this.inputElements[0];
398
841
 
399
842
  if (firstInput.validationMessage.length > 0) {
@@ -13760,7 +14203,7 @@ class AuroFloatingUI {
13760
14203
  /**
13761
14204
  * @private
13762
14205
  * getting called on 'blur' in trigger or `focusin` in document
13763
- *
14206
+ *
13764
14207
  * Hides the bib if focus moves outside of the trigger or bib, unless a 'noHideOnThisFocusLoss' flag is set.
13765
14208
  * This method checks if the currently active element is still within the trigger or bib.
13766
14209
  * If not, and if the bib isn't in fullscreen mode with focus lost, it hides the bib.
@@ -13876,7 +14319,7 @@ class AuroFloatingUI {
13876
14319
  // Close any other dropdown that is already open
13877
14320
  const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
13878
14321
  if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this &&
13879
- existedVisibleFloatingUI.isPopoverVisible &&
14322
+ existedVisibleFloatingUI.element.isPopoverVisible &&
13880
14323
  document.expandedAuroFloater.eventPrefix === this.eventPrefix) {
13881
14324
  document.expandedAuroFloater.hideBib();
13882
14325
  }
@@ -14052,7 +14495,7 @@ class AuroFloatingUI {
14052
14495
  this.id = window.crypto.randomUUID();
14053
14496
  this.element.setAttribute('id', this.id);
14054
14497
  }
14055
-
14498
+
14056
14499
  this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
14057
14500
  }
14058
14501
 
@@ -14105,7 +14548,7 @@ class AuroFloatingUI {
14105
14548
  if (this.element.bib) {
14106
14549
  this.element.shadowRoot.append(this.element.bib);
14107
14550
  }
14108
-
14551
+
14109
14552
  // Remove event & keyboard listeners
14110
14553
  if (this.element?.trigger) {
14111
14554
  this.element.trigger.removeEventListener('keydown', this.handleEvent);
@@ -14836,6 +15279,7 @@ var helpTextVersion$1 = '1.0.0';
14836
15279
  * @csspart helpText - The helpText content container.
14837
15280
  * @event auroDropdown-triggerClick - Notifies that the trigger has been clicked.
14838
15281
  * @event auroDropdown-toggled - Notifies that the visibility of the dropdown bib has changed.
15282
+ * @event auroDropdown-idAdded - Notifies consumers that the unique ID for the dropdown bib has been generated.
14839
15283
  */
14840
15284
  class AuroDropdown extends r$2 {
14841
15285
  constructor() {
@@ -14881,7 +15325,9 @@ class AuroDropdown extends r$2 {
14881
15325
  this.rounded = false;
14882
15326
  this.tabIndex = 0;
14883
15327
  this.noToggle = false;
15328
+ this.a11yAutocomplete = 'none';
14884
15329
  this.labeled = true;
15330
+ this.a11yRole = 'combobox';
14885
15331
  this.onDark = false;
14886
15332
 
14887
15333
  // floaterConfig
@@ -15017,6 +15463,16 @@ class AuroDropdown extends r$2 {
15017
15463
  type: Number
15018
15464
  },
15019
15465
 
15466
+ /**
15467
+ * The unique ID for the dropdown bib element.
15468
+ * @private
15469
+ */
15470
+ dropdownId: {
15471
+ type: String,
15472
+ reflect: false,
15473
+ attribute: false
15474
+ },
15475
+
15020
15476
  /**
15021
15477
  * If declared in combination with `bordered` property or `helpText` slot content, will apply red color to both.
15022
15478
  */
@@ -15184,6 +15640,23 @@ class AuroDropdown extends r$2 {
15184
15640
  */
15185
15641
  tabIndex: {
15186
15642
  type: Number
15643
+ },
15644
+
15645
+ /**
15646
+ * The value for the role attribute of the trigger element.
15647
+ */
15648
+ a11yRole: {
15649
+ type: String || undefined,
15650
+ attribute: false,
15651
+ reflect: false
15652
+ },
15653
+
15654
+ /**
15655
+ * The value for the aria-autocomplete attribute of the trigger element.
15656
+ */
15657
+ a11yAutocomplete: {
15658
+ type: String,
15659
+ attribute: false,
15187
15660
  }
15188
15661
  };
15189
15662
  }
@@ -15245,7 +15718,22 @@ class AuroDropdown extends r$2 {
15245
15718
  }
15246
15719
 
15247
15720
  firstUpdated() {
15721
+
15722
+ // Configure the floater to, this will generate the ID for the bib
15248
15723
  this.floater.configure(this, 'auroDropdown');
15724
+
15725
+ /**
15726
+ * @description Let subscribers know that the dropdown ID ha been generated and added.
15727
+ * @event auroDropdown-idAdded
15728
+ * @type {Object<key: 'id', value: string>} - The ID of the dropdown bib element.
15729
+ */
15730
+ this.dispatchEvent(new CustomEvent('auroDropdown-idAdded', {detail: {id: this.floater.element.id}}));
15731
+
15732
+ // Set the bib ID locally if the user hasn't provided a focusable trigger
15733
+ if (!this.triggerContentFocusable) {
15734
+ this.dropdownId = this.floater.element.id;
15735
+ }
15736
+
15249
15737
  this.bibContent = this.floater.element.bib;
15250
15738
 
15251
15739
  // Add the tag name as an attribute if it is different than the component name
@@ -15397,6 +15885,30 @@ class AuroDropdown extends r$2 {
15397
15885
  });
15398
15886
  }
15399
15887
 
15888
+ /*
15889
+ * Sets aria attributes for the trigger element if a custom one is passed in.
15890
+ * @private
15891
+ * @method setTriggerAriaAttributes
15892
+ * @param { HTMLElement } triggerElement - The custom trigger element.
15893
+ */
15894
+ clearTriggerA11yAttributes(triggerElement) {
15895
+
15896
+ if (!triggerElement || !triggerElement.removeAttribute) {
15897
+ return;
15898
+ }
15899
+
15900
+ // Reset appropriate attributes for a11y
15901
+ triggerElement.removeAttribute('aria-labelledby');
15902
+ if (triggerElement.getAttribute('id') === `${this.id}-trigger-element`) {
15903
+ triggerElement.removeAttribute('id');
15904
+ }
15905
+ triggerElement.removeAttribute('role');
15906
+ triggerElement.removeAttribute('aria-expanded');
15907
+
15908
+ triggerElement.removeAttribute('aria-controls');
15909
+ triggerElement.removeAttribute('aria-autocomplete');
15910
+ }
15911
+
15400
15912
  /**
15401
15913
  * Handles changes to the trigger content slot and updates related properties.
15402
15914
  *
@@ -15410,32 +15922,41 @@ class AuroDropdown extends r$2 {
15410
15922
  * @returns {void}
15411
15923
  */
15412
15924
  handleTriggerContentSlotChange(event) {
15925
+
15413
15926
  this.floater.handleTriggerTabIndex();
15414
15927
 
15928
+ // Get the trigger
15929
+ const trigger = this.shadowRoot.querySelector('#trigger');
15930
+
15931
+ // Get the trigger slot
15415
15932
  const triggerSlot = this.shadowRoot.querySelector('.triggerContent slot');
15416
15933
 
15934
+ // If there's a trigger slot
15417
15935
  if (triggerSlot) {
15418
15936
 
15937
+ // Get the content nodes to see if there are any children
15419
15938
  const triggerContentNodes = triggerSlot.assignedNodes();
15420
15939
 
15940
+ // If there are children
15421
15941
  if (triggerContentNodes) {
15422
15942
 
15423
- triggerContentNodes.forEach((node) => {
15424
- if (!this.triggerContentFocusable) {
15425
- this.triggerContentFocusable = this.containsFocusableElement(node);
15426
- }
15427
- });
15428
- }
15429
- }
15943
+ // See if any of them are focusable elemeents
15944
+ this.triggerContentFocusable = triggerContentNodes.some((node) => this.containsFocusableElement(node));
15430
15945
 
15431
- const trigger = this.shadowRoot.querySelector('#trigger');
15946
+ // If any of them are focusable elements
15947
+ if (this.triggerContentFocusable) {
15432
15948
 
15433
- if (!this.triggerContentFocusable) {
15434
- trigger.setAttribute('tabindex', '0');
15435
- trigger.setAttribute('role', 'button');
15436
- } else {
15437
- trigger.removeAttribute('tabindex');
15438
- trigger.removeAttribute('role');
15949
+ // Assume the consumer will be providing their own a11y in whatever they passed in
15950
+ this.clearTriggerA11yAttributes(trigger);
15951
+
15952
+ // Remove the tabindex from the trigger so it doesn't interrupt focus flow
15953
+ trigger.removeAttribute('tabindex');
15954
+ } else {
15955
+
15956
+ // Add the tabindex to the trigger so that it's in the focus flow
15957
+ trigger.setAttribute('tabindex', '0');
15958
+ }
15959
+ }
15439
15960
  }
15440
15961
 
15441
15962
  if (event) {
@@ -15445,6 +15966,7 @@ class AuroDropdown extends r$2 {
15445
15966
 
15446
15967
  if (this.triggerContentSlot) {
15447
15968
  this.setupTriggerFocusEventBinding();
15969
+
15448
15970
  this.hasTriggerContent = this.triggerContentSlot.some((slot) => {
15449
15971
  if (slot.textContent.trim()) {
15450
15972
  return true;
@@ -15512,10 +16034,13 @@ class AuroDropdown extends r$2 {
15512
16034
  id="trigger"
15513
16035
  class="trigger"
15514
16036
  part="trigger"
15515
- aria-labelledby="triggerLabel"
15516
16037
  tabindex="${this.tabIndex}"
15517
16038
  ?showBorder="${this.showTriggerBorders}"
15518
- >
16039
+ role="${o(this.triggerContentFocusable ? undefined : this.a11yRole)}"
16040
+ aria-expanded="${o(this.triggerContentFocusable ? undefined : this.isPopoverVisible)}"
16041
+ aria-controls="${o(this.triggerContentFocusable ? undefined : this.dropdownId)}"
16042
+ aria-labelledby="${o(this.triggerContentFocusable ? undefined : 'triggerLabel')}"
16043
+ >
15519
16044
  <div class="triggerContentWrapper">
15520
16045
  <label class="label" id="triggerLabel" hasTrigger=${this.hasTriggerContent}>
15521
16046
  <slot name="label" @slotchange="${this.handleLabelSlotChange}"></slot>
@@ -15549,12 +16074,12 @@ class AuroDropdown extends r$2 {
15549
16074
  <div id="bibSizer" part="size"></div>
15550
16075
  <${this.dropdownBibTag}
15551
16076
  id="bib"
15552
- role="tooltip"
15553
16077
  ?data-show="${this.isPopoverVisible}"
15554
16078
  ?isfullscreen="${this.isBibFullscreen}"
15555
16079
  ?common="${this.common}"
15556
16080
  ?rounded="${this.common || this.rounded}"
15557
- ?inset="${this.common || this.inset}">
16081
+ ?inset="${this.common || this.inset}"
16082
+ >
15558
16083
  </${this.dropdownBibTag}>
15559
16084
  </div>
15560
16085
  `;
@@ -19545,6 +20070,414 @@ class AuroInputUtilities {
19545
20070
  }
19546
20071
  }
19547
20072
 
20073
+ class DateFormatter {
20074
+
20075
+ constructor() {
20076
+
20077
+ /**
20078
+ * @description Parses a date string into its components.
20079
+ * @param {string} dateStr - Date string to parse.
20080
+ * @param {string} format - Date format to parse.
20081
+ * @returns {Object<key["month" | "day" | "year"]: number>|undefined}
20082
+ */
20083
+ this.parseDate = (dateStr, format = 'mm/dd/yyyy') => {
20084
+
20085
+ // Guard Clause: Date string is defined
20086
+ if (!dateStr) {
20087
+ return undefined;
20088
+ }
20089
+
20090
+ // Assume the separator is a "/" a defined in our code base
20091
+ const separator = '/';
20092
+
20093
+ // Get the parts of the date and format
20094
+ const valueParts = dateStr.split(separator);
20095
+ const formatParts = format.split(separator);
20096
+
20097
+ // Check if the value and format have the correct number of parts
20098
+ if (valueParts.length !== formatParts.length) {
20099
+ throw new Error('AuroDatepickerUtilities | parseDate: Date string and format length do not match');
20100
+ }
20101
+
20102
+ // Holds the result to be returned
20103
+ const result = formatParts.reduce((acc, part, index) => {
20104
+ const value = valueParts[index];
20105
+
20106
+ if ((/m/iu).test(part)) {
20107
+ acc.month = value;
20108
+ } else if ((/d/iu).test(part)) {
20109
+ acc.day = value;
20110
+ } else if ((/y/iu).test(part)) {
20111
+ acc.year = value;
20112
+ }
20113
+
20114
+ return acc;
20115
+ }, {});
20116
+
20117
+ // If we found all the parts, return the result
20118
+ if (result.month && result.year) {
20119
+ return result;
20120
+ }
20121
+
20122
+ // Throw an error to let the dev know we were unable to parse the date string
20123
+ throw new Error('AuroDatepickerUtilities | parseDate: Unable to parse date string');
20124
+ };
20125
+
20126
+ /**
20127
+ * Convert a date object to string format.
20128
+ * @param {Object} date - Date to convert to string.
20129
+ * @returns {Object} Returns the date as a string.
20130
+ */
20131
+ this.getDateAsString = (date) => date.toLocaleDateString(undefined, {
20132
+ year: "numeric",
20133
+ month: "2-digit",
20134
+ day: "2-digit",
20135
+ });
20136
+
20137
+ /**
20138
+ * Converts a date string to a North American date format.
20139
+ * @param {String} dateStr - Date to validate.
20140
+ * @param {String} format - Date format to validate against.
20141
+ * @returns {Boolean}
20142
+ */
20143
+ this.toNorthAmericanFormat = (dateStr, format) => {
20144
+
20145
+ if (format === 'mm/dd/yyyy') {
20146
+ return dateStr;
20147
+ }
20148
+
20149
+ const parsedDate = this.parseDate(dateStr, format);
20150
+
20151
+ if (!parsedDate) {
20152
+ throw new Error('AuroDatepickerUtilities | toNorthAmericanFormat: Unable to parse date string');
20153
+ }
20154
+
20155
+ const { month, day, year } = parsedDate;
20156
+
20157
+ const dateParts = [];
20158
+ if (month) {
20159
+ dateParts.push(month);
20160
+ }
20161
+
20162
+ if (day) {
20163
+ dateParts.push(day);
20164
+ }
20165
+
20166
+ if (year) {
20167
+ dateParts.push(year);
20168
+ }
20169
+
20170
+ return dateParts.join('/');
20171
+ };
20172
+ }
20173
+ }
20174
+ const dateFormatter = new DateFormatter();
20175
+
20176
+ // filepath: dateConstraints.mjs
20177
+ const DATE_UTIL_CONSTRAINTS = {
20178
+ maxDay: 31,
20179
+ maxMonth: 12,
20180
+ maxYear: 2400,
20181
+ minDay: 1,
20182
+ minMonth: 1,
20183
+ minYear: 1900,
20184
+ };
20185
+
20186
+ class AuroDateUtilitiesBase {
20187
+
20188
+ /**
20189
+ * @description The maximum day value allowed by the various utilities in this class.
20190
+ * @readonly
20191
+ * @type {Number}
20192
+ */
20193
+ get maxDay() {
20194
+ return DATE_UTIL_CONSTRAINTS.maxDay;
20195
+ }
20196
+
20197
+ /**
20198
+ * @description The maximum month value allowed by the various utilities in this class.
20199
+ * @readonly
20200
+ * @type {Number}
20201
+ */
20202
+ get maxMonth() {
20203
+ return DATE_UTIL_CONSTRAINTS.maxMonth;
20204
+ }
20205
+
20206
+ /**
20207
+ * @description The maximum year value allowed by the various utilities in this class.
20208
+ * @readonly
20209
+ * @type {Number}
20210
+ */
20211
+ get maxYear() {
20212
+ return DATE_UTIL_CONSTRAINTS.maxYear;
20213
+ }
20214
+
20215
+ /**
20216
+ * @description The minimum day value allowed by the various utilities in this class.
20217
+ * @readonly
20218
+ * @type {Number}
20219
+ */
20220
+ get minDay() {
20221
+ return DATE_UTIL_CONSTRAINTS.minDay;
20222
+ }
20223
+
20224
+ /**
20225
+ * @description The minimum month value allowed by the various utilities in this class.
20226
+ * @readonly
20227
+ * @type {Number}
20228
+ */
20229
+ get minMonth() {
20230
+ return DATE_UTIL_CONSTRAINTS.minMonth;
20231
+ }
20232
+
20233
+ /**
20234
+ * @description The minimum year value allowed by the various utilities in this class.
20235
+ * @readonly
20236
+ * @type {Number}
20237
+ */
20238
+ get minYear() {
20239
+ return DATE_UTIL_CONSTRAINTS.minYear;
20240
+ }
20241
+ }
20242
+
20243
+ /* eslint-disable no-magic-numbers */
20244
+
20245
+ class AuroDateUtilities extends AuroDateUtilitiesBase {
20246
+
20247
+ /**
20248
+ * Returns the current century.
20249
+ * @returns {String} The current century.
20250
+ */
20251
+ getCentury () {
20252
+ return String(new Date().getFullYear()).slice(0, 2);
20253
+ }
20254
+
20255
+ /**
20256
+ * Returns a four digit year.
20257
+ * @param {String} year - The year to convert to four digits.
20258
+ * @returns {String} The four digit year.
20259
+ */
20260
+ getFourDigitYear (year) {
20261
+
20262
+ const strYear = String(year).trim();
20263
+ return strYear.length <= 2 ? this.getCentury() + strYear : strYear;
20264
+ }
20265
+
20266
+ constructor() {
20267
+
20268
+ super();
20269
+
20270
+ /**
20271
+ * Compares two dates to see if they match.
20272
+ * @param {Object} date1 - First date to compare.
20273
+ * @param {Object} date2 - Second date to compare.
20274
+ * @returns {Boolean} Returns true if the dates match.
20275
+ */
20276
+ this.datesMatch = (date1, date2) => new Date(date1).getTime() === new Date(date2).getTime();
20277
+
20278
+ /**
20279
+ * Returns true if value passed in is a valid date.
20280
+ * @param {String} date - Date to validate.
20281
+ * @param {String} format - Date format to validate against.
20282
+ * @returns {Boolean}
20283
+ */
20284
+ this.validDateStr = (date, format) => {
20285
+
20286
+ // The length we expect the date string to be
20287
+ const dateStrLength = format.length;
20288
+
20289
+ // Guard Clause: Date and format are defined
20290
+ if (typeof date === "undefined" || typeof format === "undefined") {
20291
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date and format are required');
20292
+ }
20293
+
20294
+ // Guard Clause: Date should be of type string
20295
+ if (typeof date !== "string") {
20296
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date must be a string');
20297
+ }
20298
+
20299
+ // Guard Clause: Format should be of type string
20300
+ if (typeof format !== "string") {
20301
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Format must be a string');
20302
+ }
20303
+
20304
+ // Guard Clause: Length is what we expect it to be
20305
+ if (date.length !== dateStrLength) {
20306
+ return false;
20307
+ }
20308
+ // Get a formatted date string and parse it
20309
+ const dateParts = dateFormatter.parseDate(date, format);
20310
+
20311
+ // Guard Clause: Date parse succeeded
20312
+ if (!dateParts) {
20313
+ return false;
20314
+ }
20315
+
20316
+ // Create the expected date string based on the date parts
20317
+ const expectedDateStr = `${dateParts.month}/${dateParts.day || "01"}/${this.getFourDigitYear(dateParts.year)}`;
20318
+
20319
+ // Generate a date object that we will extract a string date from to compare to the passed in date string
20320
+ const dateObj = new Date(this.getFourDigitYear(dateParts.year), dateParts.month - 1, dateParts.day || 1);
20321
+
20322
+ // Get the date string of the date object we created from the string date
20323
+ const actualDateStr = dateFormatter.getDateAsString(dateObj);
20324
+
20325
+ // Guard Clause: Generated date matches date string input
20326
+ if (expectedDateStr !== actualDateStr) {
20327
+ return false;
20328
+ }
20329
+
20330
+ // If we passed all other checks, we can assume the date is valid
20331
+ return true;
20332
+ };
20333
+
20334
+ /**
20335
+ * Determines if a string date value matches the format provided.
20336
+ * @param {string} value = The date string value.
20337
+ * @param { string} format = The date format to match against.
20338
+ * @returns {boolean}
20339
+ */
20340
+ this.dateAndFormatMatch = (value, format) => {
20341
+
20342
+ // Ensure we have both values we need to do the comparison
20343
+ if (!value || !format) {
20344
+ throw new Error('AuroFormValidation | dateFormatMatch: value and format are required');
20345
+ }
20346
+
20347
+ // If the lengths are different, they cannot match
20348
+ if (value.length !== format.length) {
20349
+ return false;
20350
+ }
20351
+
20352
+ // Get the parts of the date
20353
+ const dateParts = dateFormatter.parseDate(value, format);
20354
+
20355
+ // Validator for day
20356
+ const dayValueIsValid = (day) => {
20357
+
20358
+ // Guard clause: if there is no day in the dateParts, we can ignore this check.
20359
+ if (!dateParts.day) {
20360
+ return true;
20361
+ }
20362
+
20363
+ // Guard clause: ensure day exists.
20364
+ if (!day) {
20365
+ return false;
20366
+ }
20367
+
20368
+ // Convert day to number
20369
+ const numDay = Number.parseInt(day, 10);
20370
+
20371
+ // Guard clause: ensure day is a valid integer
20372
+ if (Number.isNaN(numDay)) {
20373
+ throw new Error('AuroDatepickerUtilities | dayValueIsValid: Unable to parse day value integer');
20374
+ }
20375
+
20376
+ // Guard clause: ensure day is within the valid range
20377
+ if (numDay < this.minDay || numDay > this.maxDay) {
20378
+ return false;
20379
+ }
20380
+
20381
+ // Default return
20382
+ return true;
20383
+ };
20384
+
20385
+ // Validator for month
20386
+ const monthValueIsValid = (month) => {
20387
+
20388
+ // Guard clause: ensure month exists.
20389
+ if (!month) {
20390
+ return false;
20391
+ }
20392
+
20393
+ // Convert month to number
20394
+ const numMonth = Number.parseInt(month, 10);
20395
+
20396
+ // Guard clause: ensure month is a valid integer
20397
+ if (Number.isNaN(numMonth)) {
20398
+ throw new Error('AuroDatepickerUtilities | monthValueIsValid: Unable to parse month value integer');
20399
+ }
20400
+
20401
+ // Guard clause: ensure month is within the valid range
20402
+ if (numMonth < this.minMonth || numMonth > this.maxMonth) {
20403
+ return false;
20404
+ }
20405
+
20406
+ // Default return
20407
+ return true;
20408
+ };
20409
+
20410
+ // Validator for year
20411
+ const yearIsValid = (_year) => {
20412
+
20413
+ // Guard clause: ensure year exists.
20414
+ if (!_year) {
20415
+ return false;
20416
+ }
20417
+
20418
+ // Get the full year
20419
+ const year = this.getFourDigitYear(_year);
20420
+
20421
+ // Convert year to number
20422
+ const numYear = Number.parseInt(year, 10);
20423
+
20424
+ // Guard clause: ensure year is a valid integer
20425
+ if (Number.isNaN(numYear)) {
20426
+ throw new Error('AuroDatepickerUtilities | yearValueIsValid: Unable to parse year value integer');
20427
+ }
20428
+
20429
+ // Guard clause: ensure year is within the valid range
20430
+ if (numYear < this.minYear || numYear > this.maxYear) {
20431
+ return false;
20432
+ }
20433
+
20434
+ // Default return
20435
+ return true;
20436
+ };
20437
+
20438
+ // Self-contained checks for month, day, and year
20439
+ const checks = [
20440
+ monthValueIsValid(dateParts.month),
20441
+ dayValueIsValid(dateParts.day),
20442
+ yearIsValid(dateParts.year)
20443
+ ];
20444
+
20445
+ // If any of the checks failed, the date format does not match and the result is invalid
20446
+ const isValid = checks.every((check) => check === true);
20447
+
20448
+ // If the check is invalid, return false
20449
+ if (!isValid) {
20450
+ return false;
20451
+ }
20452
+
20453
+ // Default case
20454
+ return true;
20455
+ };
20456
+ }
20457
+ }
20458
+
20459
+ // Export a class instance
20460
+ const dateUtilities = new AuroDateUtilities();
20461
+
20462
+ // Export the class instance methods individually
20463
+ const {
20464
+ datesMatch,
20465
+ validDateStr,
20466
+ dateAndFormatMatch,
20467
+ minDay,
20468
+ minMonth,
20469
+ minYear,
20470
+ maxDay,
20471
+ maxMonth,
20472
+ maxYear
20473
+ } = dateUtilities;
20474
+
20475
+ const {
20476
+ toNorthAmericanFormat,
20477
+ parseDate,
20478
+ getDateAsString
20479
+ } = dateFormatter;
20480
+
19548
20481
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
19549
20482
  // See LICENSE in the project root for license information.
19550
20483
 
@@ -19620,6 +20553,7 @@ let AuroLibraryRuntimeUtils$1 = class AuroLibraryRuntimeUtils {
19620
20553
 
19621
20554
 
19622
20555
  class AuroFormValidation {
20556
+
19623
20557
  constructor() {
19624
20558
  this.runtimeUtils = new AuroLibraryRuntimeUtils$1();
19625
20559
  }
@@ -19711,17 +20645,17 @@ class AuroFormValidation {
19711
20645
  ]
19712
20646
  }
19713
20647
  };
19714
-
20648
+
19715
20649
  let elementType;
19716
20650
  if (this.runtimeUtils.elementMatch(elem, 'auro-input')) {
19717
20651
  elementType = 'input';
19718
20652
  } else if (this.runtimeUtils.elementMatch(elem, 'auro-counter') || this.runtimeUtils.elementMatch(elem, 'auro-counter-group')) {
19719
20653
  elementType = 'counter';
19720
20654
  }
19721
-
20655
+
19722
20656
  if (elementType) {
19723
20657
  const rules = validationRules[elementType];
19724
-
20658
+
19725
20659
  if (rules) {
19726
20660
  Object.values(rules).flat().forEach(rule => {
19727
20661
  if (rule.check(elem)) {
@@ -19747,48 +20681,82 @@ class AuroFormValidation {
19747
20681
  if (!elem.value.match(emailRegex)) {
19748
20682
  elem.validity = 'patternMismatch';
19749
20683
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20684
+ return;
19750
20685
  }
19751
20686
  } else if (elem.type === 'credit-card') {
19752
20687
  if (elem.value.length > 0 && elem.value.length < elem.validationCCLength) {
19753
20688
  elem.validity = 'tooShort';
19754
20689
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20690
+ return;
19755
20691
  }
19756
20692
  } else if (elem.type === 'number') {
19757
20693
  if (elem.max !== undefined && Number(elem.max) < Number(elem.value)) {
19758
20694
  elem.validity = 'rangeOverflow';
19759
20695
  elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
20696
+ return;
19760
20697
  }
19761
20698
 
19762
20699
  if (elem.min !== undefined && elem.value?.length > 0 && Number(elem.min) > Number(elem.value)) {
19763
20700
  elem.validity = 'rangeUnderflow';
19764
20701
  elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
20702
+ return;
19765
20703
  }
19766
- } else if (elem.type === 'date') {
19767
- if (elem.value?.length > 0 && elem.value?.length < elem.lengthForType) {
20704
+ } else if (elem.type === 'date' && elem.value?.length > 0) {
20705
+
20706
+ // Guard Clause: if the value is too short
20707
+ if (elem.value.length < elem.lengthForType) {
20708
+
19768
20709
  elem.validity = 'tooShort';
19769
20710
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
19770
- } else if (elem.value?.length === elem.lengthForType && elem.util.toNorthAmericanFormat(elem.value, elem.format)) {
19771
- const formattedValue = elem.util.toNorthAmericanFormat(elem.value, elem.format);
19772
- const valueDate = new Date(formattedValue.dateForComparison);
20711
+ return;
20712
+ }
20713
+
20714
+ // Guard Clause: If the value is too long for the type
20715
+ if (elem.value?.length > elem.lengthForType) {
20716
+
20717
+ elem.validity = 'tooLong';
20718
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20719
+ return;
20720
+ }
20721
+
20722
+ // Validate that the date passed was the correct format
20723
+ if (!dateAndFormatMatch(elem.value, elem.format)) {
20724
+ elem.validity = 'patternMismatch';
20725
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || 'Invalid Date Format Entered';
20726
+ return;
20727
+ }
20728
+
20729
+ // Validate that the date passed was a valid date
20730
+ if (!validDateStr(elem.value, elem.format)) {
20731
+ elem.validity = 'invalidDate';
20732
+ elem.errorMessage = elem.setCustomValidityInvalidDate || elem.setCustomValidity || 'Invalid Date Entered';
20733
+ return;
20734
+ }
19773
20735
 
19774
- // validate max
19775
- if (elem.max?.length === elem.lengthForType) {
19776
- const maxDate = new Date(elem.util.toNorthAmericanFormat(elem.max, elem.format).dateForComparison);
20736
+ // Perform the rest of the validation
20737
+ const formattedValue = toNorthAmericanFormat(elem.value, elem.format);
20738
+ const valueDate = new Date(formattedValue);
19777
20739
 
19778
- if (valueDate > maxDate) {
19779
- elem.validity = 'rangeOverflow';
19780
- elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
19781
- }
20740
+ // // Validate max date
20741
+ if (elem.max?.length === elem.lengthForType) {
20742
+
20743
+ const maxDate = new Date(toNorthAmericanFormat(elem.max, elem.format));
20744
+
20745
+ if (valueDate > maxDate) {
20746
+ elem.validity = 'rangeOverflow';
20747
+ elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
20748
+ return;
19782
20749
  }
20750
+ }
19783
20751
 
19784
- // validate min
19785
- if (elem.min?.length === elem.lengthForType) {
19786
- const minDate = new Date(elem.util.toNorthAmericanFormat(elem.min, elem.format).dateForComparison);
20752
+ // Validate min date
20753
+ if (elem.min?.length === elem.lengthForType) {
20754
+ const minDate = new Date(toNorthAmericanFormat(elem.min, elem.format));
19787
20755
 
19788
- if (valueDate < minDate) {
19789
- elem.validity = 'rangeUnderflow';
19790
- elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
19791
- }
20756
+ if (valueDate < minDate) {
20757
+ elem.validity = 'rangeUnderflow';
20758
+ elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
20759
+ return;
19792
20760
  }
19793
20761
  }
19794
20762
  }
@@ -19907,7 +20875,7 @@ class AuroFormValidation {
19907
20875
  if (input.validationMessage.length > 0) {
19908
20876
  elem.errorMessage = input.validationMessage;
19909
20877
  }
19910
- } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
20878
+ } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
19911
20879
  const firstInput = this.inputElements[0];
19912
20880
 
19913
20881
  if (firstInput.validationMessage.length > 0) {
@@ -20029,6 +20997,33 @@ class BaseInput extends r$2 {
20029
20997
  static get properties() {
20030
20998
  return {
20031
20999
 
21000
+ /**
21001
+ * The value for the role attribute.
21002
+ */
21003
+ a11yRole: {
21004
+ type: String,
21005
+ attribute: true,
21006
+ reflect: true
21007
+ },
21008
+
21009
+ /**
21010
+ * The value for the aria-expanded attribute.
21011
+ */
21012
+ a11yExpanded: {
21013
+ type: Boolean,
21014
+ attribute: true,
21015
+ reflect: true
21016
+ },
21017
+
21018
+ /**
21019
+ * The value for the aria-controls attribute.
21020
+ */
21021
+ a11yControls: {
21022
+ type: String,
21023
+ attribute: true,
21024
+ reflect: true
21025
+ },
21026
+
20032
21027
  /**
20033
21028
  * If set, the label will remain fixed in the active position.
20034
21029
  */
@@ -20670,6 +21665,10 @@ class BaseInput extends r$2 {
20670
21665
  } else if (this.type === 'number') {
20671
21666
  this.inputMode = 'numeric';
20672
21667
  }
21668
+
21669
+ if (this.type === "date" && !this.format) {
21670
+ this.format = 'mm/dd/yyyy';
21671
+ }
20673
21672
  }
20674
21673
 
20675
21674
  /**
@@ -21913,6 +22912,7 @@ var helpTextVersion = '1.0.0';
21913
22912
 
21914
22913
  // build the component class
21915
22914
  class AuroInput extends BaseInput {
22915
+
21916
22916
  constructor() {
21917
22917
  super();
21918
22918
 
@@ -22025,7 +23025,7 @@ class AuroInput extends BaseInput {
22025
23025
  ?required="${this.required}"
22026
23026
  ?disabled="${this.disabled}"
22027
23027
  aria-describedby="${this.uniqueId}"
22028
- aria-invalid="${this.validity !== 'valid'}"
23028
+ ?aria-invalid="${this.validity !== 'valid'}"
22029
23029
  placeholder=${this.getPlaceholder()}
22030
23030
  lang="${o(this.lang)}"
22031
23031
  ?activeLabel="${this.activeLabel}"
@@ -22034,7 +23034,10 @@ class AuroInput extends BaseInput {
22034
23034
  autocapitalize="${o(this.autocapitalize ? this.autocapitalize : undefined)}"
22035
23035
  autocomplete="${o(this.autocomplete ? this.autocomplete : undefined)}"
22036
23036
  part="input"
22037
- />
23037
+ role="${o(this.a11yRole)}"
23038
+ aria-expanded="${o(this.a11yExpanded)}"
23039
+ aria-controls="${o(this.a11yControls)}"
23040
+ />
22038
23041
  </div>
22039
23042
  <div
22040
23043
  class="notificationIcons"