@aurodesignsystem/auro-formkit 3.0.1 → 3.1.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 (59) hide show
  1. package/CHANGELOG.md +18 -0
  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);
@@ -14834,6 +15277,7 @@ var helpTextVersion$1 = '1.0.0';
14834
15277
  * @csspart helpText - The helpText content container.
14835
15278
  * @event auroDropdown-triggerClick - Notifies that the trigger has been clicked.
14836
15279
  * @event auroDropdown-toggled - Notifies that the visibility of the dropdown bib has changed.
15280
+ * @event auroDropdown-idAdded - Notifies consumers that the unique ID for the dropdown bib has been generated.
14837
15281
  */
14838
15282
  class AuroDropdown extends r$2 {
14839
15283
  constructor() {
@@ -14879,7 +15323,9 @@ class AuroDropdown extends r$2 {
14879
15323
  this.rounded = false;
14880
15324
  this.tabIndex = 0;
14881
15325
  this.noToggle = false;
15326
+ this.a11yAutocomplete = 'none';
14882
15327
  this.labeled = true;
15328
+ this.a11yRole = 'combobox';
14883
15329
  this.onDark = false;
14884
15330
 
14885
15331
  // floaterConfig
@@ -15015,6 +15461,16 @@ class AuroDropdown extends r$2 {
15015
15461
  type: Number
15016
15462
  },
15017
15463
 
15464
+ /**
15465
+ * The unique ID for the dropdown bib element.
15466
+ * @private
15467
+ */
15468
+ dropdownId: {
15469
+ type: String,
15470
+ reflect: false,
15471
+ attribute: false
15472
+ },
15473
+
15018
15474
  /**
15019
15475
  * If declared in combination with `bordered` property or `helpText` slot content, will apply red color to both.
15020
15476
  */
@@ -15177,6 +15633,23 @@ class AuroDropdown extends r$2 {
15177
15633
  */
15178
15634
  tabIndex: {
15179
15635
  type: Number
15636
+ },
15637
+
15638
+ /**
15639
+ * The value for the role attribute of the trigger element.
15640
+ */
15641
+ a11yRole: {
15642
+ type: String || undefined,
15643
+ attribute: false,
15644
+ reflect: false
15645
+ },
15646
+
15647
+ /**
15648
+ * The value for the aria-autocomplete attribute of the trigger element.
15649
+ */
15650
+ a11yAutocomplete: {
15651
+ type: String,
15652
+ attribute: false,
15180
15653
  }
15181
15654
  };
15182
15655
  }
@@ -15227,7 +15700,22 @@ class AuroDropdown extends r$2 {
15227
15700
  }
15228
15701
 
15229
15702
  firstUpdated() {
15703
+
15704
+ // Configure the floater to, this will generate the ID for the bib
15230
15705
  this.floater.configure(this, 'auroDropdown');
15706
+
15707
+ /**
15708
+ * @description Let subscribers know that the dropdown ID ha been generated and added.
15709
+ * @event auroDropdown-idAdded
15710
+ * @type {Object<key: 'id', value: string>} - The ID of the dropdown bib element.
15711
+ */
15712
+ this.dispatchEvent(new CustomEvent('auroDropdown-idAdded', {detail: {id: this.floater.element.id}}));
15713
+
15714
+ // Set the bib ID locally if the user hasn't provided a focusable trigger
15715
+ if (!this.triggerContentFocusable) {
15716
+ this.dropdownId = this.floater.element.id;
15717
+ }
15718
+
15231
15719
  this.bibContent = this.floater.element.bib;
15232
15720
 
15233
15721
  // Add the tag name as an attribute if it is different than the component name
@@ -15379,6 +15867,30 @@ class AuroDropdown extends r$2 {
15379
15867
  });
15380
15868
  }
15381
15869
 
15870
+ /*
15871
+ * Sets aria attributes for the trigger element if a custom one is passed in.
15872
+ * @private
15873
+ * @method setTriggerAriaAttributes
15874
+ * @param { HTMLElement } triggerElement - The custom trigger element.
15875
+ */
15876
+ clearTriggerA11yAttributes(triggerElement) {
15877
+
15878
+ if (!triggerElement || !triggerElement.removeAttribute) {
15879
+ return;
15880
+ }
15881
+
15882
+ // Reset appropriate attributes for a11y
15883
+ triggerElement.removeAttribute('aria-labelledby');
15884
+ if (triggerElement.getAttribute('id') === `${this.id}-trigger-element`) {
15885
+ triggerElement.removeAttribute('id');
15886
+ }
15887
+ triggerElement.removeAttribute('role');
15888
+ triggerElement.removeAttribute('aria-expanded');
15889
+
15890
+ triggerElement.removeAttribute('aria-controls');
15891
+ triggerElement.removeAttribute('aria-autocomplete');
15892
+ }
15893
+
15382
15894
  /**
15383
15895
  * Handles changes to the trigger content slot and updates related properties.
15384
15896
  *
@@ -15392,32 +15904,41 @@ class AuroDropdown extends r$2 {
15392
15904
  * @returns {void}
15393
15905
  */
15394
15906
  handleTriggerContentSlotChange(event) {
15907
+
15395
15908
  this.floater.handleTriggerTabIndex();
15396
15909
 
15910
+ // Get the trigger
15911
+ const trigger = this.shadowRoot.querySelector('#trigger');
15912
+
15913
+ // Get the trigger slot
15397
15914
  const triggerSlot = this.shadowRoot.querySelector('.triggerContent slot');
15398
15915
 
15916
+ // If there's a trigger slot
15399
15917
  if (triggerSlot) {
15400
15918
 
15919
+ // Get the content nodes to see if there are any children
15401
15920
  const triggerContentNodes = triggerSlot.assignedNodes();
15402
15921
 
15922
+ // If there are children
15403
15923
  if (triggerContentNodes) {
15404
15924
 
15405
- triggerContentNodes.forEach((node) => {
15406
- if (!this.triggerContentFocusable) {
15407
- this.triggerContentFocusable = this.containsFocusableElement(node);
15408
- }
15409
- });
15410
- }
15411
- }
15925
+ // See if any of them are focusable elemeents
15926
+ this.triggerContentFocusable = triggerContentNodes.some((node) => this.containsFocusableElement(node));
15412
15927
 
15413
- const trigger = this.shadowRoot.querySelector('#trigger');
15928
+ // If any of them are focusable elements
15929
+ if (this.triggerContentFocusable) {
15414
15930
 
15415
- if (!this.triggerContentFocusable) {
15416
- trigger.setAttribute('tabindex', '0');
15417
- trigger.setAttribute('role', 'button');
15418
- } else {
15419
- trigger.removeAttribute('tabindex');
15420
- trigger.removeAttribute('role');
15931
+ // Assume the consumer will be providing their own a11y in whatever they passed in
15932
+ this.clearTriggerA11yAttributes(trigger);
15933
+
15934
+ // Remove the tabindex from the trigger so it doesn't interrupt focus flow
15935
+ trigger.removeAttribute('tabindex');
15936
+ } else {
15937
+
15938
+ // Add the tabindex to the trigger so that it's in the focus flow
15939
+ trigger.setAttribute('tabindex', '0');
15940
+ }
15941
+ }
15421
15942
  }
15422
15943
 
15423
15944
  if (event) {
@@ -15427,6 +15948,7 @@ class AuroDropdown extends r$2 {
15427
15948
 
15428
15949
  if (this.triggerContentSlot) {
15429
15950
  this.setupTriggerFocusEventBinding();
15951
+
15430
15952
  this.hasTriggerContent = this.triggerContentSlot.some((slot) => {
15431
15953
  if (slot.textContent.trim()) {
15432
15954
  return true;
@@ -15494,10 +16016,13 @@ class AuroDropdown extends r$2 {
15494
16016
  id="trigger"
15495
16017
  class="trigger"
15496
16018
  part="trigger"
15497
- aria-labelledby="triggerLabel"
15498
16019
  tabindex="${this.tabIndex}"
15499
16020
  ?showBorder="${this.showTriggerBorders}"
15500
- >
16021
+ role="${o(this.triggerContentFocusable ? undefined : this.a11yRole)}"
16022
+ aria-expanded="${o(this.triggerContentFocusable ? undefined : this.isPopoverVisible)}"
16023
+ aria-controls="${o(this.triggerContentFocusable ? undefined : this.dropdownId)}"
16024
+ aria-labelledby="${o(this.triggerContentFocusable ? undefined : 'triggerLabel')}"
16025
+ >
15501
16026
  <div class="triggerContentWrapper">
15502
16027
  <label class="label" id="triggerLabel" hasTrigger=${this.hasTriggerContent}>
15503
16028
  <slot name="label" @slotchange="${this.handleLabelSlotChange}"></slot>
@@ -15531,12 +16056,12 @@ class AuroDropdown extends r$2 {
15531
16056
  <div id="bibSizer" part="size"></div>
15532
16057
  <${this.dropdownBibTag}
15533
16058
  id="bib"
15534
- role="tooltip"
15535
16059
  ?data-show="${this.isPopoverVisible}"
15536
16060
  ?isfullscreen="${this.isBibFullscreen}"
15537
16061
  ?common="${this.common}"
15538
16062
  ?rounded="${this.common || this.rounded}"
15539
- ?inset="${this.common || this.inset}">
16063
+ ?inset="${this.common || this.inset}"
16064
+ >
15540
16065
  </${this.dropdownBibTag}>
15541
16066
  </div>
15542
16067
  `;
@@ -19527,6 +20052,414 @@ class AuroInputUtilities {
19527
20052
  }
19528
20053
  }
19529
20054
 
20055
+ class DateFormatter {
20056
+
20057
+ constructor() {
20058
+
20059
+ /**
20060
+ * @description Parses a date string into its components.
20061
+ * @param {string} dateStr - Date string to parse.
20062
+ * @param {string} format - Date format to parse.
20063
+ * @returns {Object<key["month" | "day" | "year"]: number>|undefined}
20064
+ */
20065
+ this.parseDate = (dateStr, format = 'mm/dd/yyyy') => {
20066
+
20067
+ // Guard Clause: Date string is defined
20068
+ if (!dateStr) {
20069
+ return undefined;
20070
+ }
20071
+
20072
+ // Assume the separator is a "/" a defined in our code base
20073
+ const separator = '/';
20074
+
20075
+ // Get the parts of the date and format
20076
+ const valueParts = dateStr.split(separator);
20077
+ const formatParts = format.split(separator);
20078
+
20079
+ // Check if the value and format have the correct number of parts
20080
+ if (valueParts.length !== formatParts.length) {
20081
+ throw new Error('AuroDatepickerUtilities | parseDate: Date string and format length do not match');
20082
+ }
20083
+
20084
+ // Holds the result to be returned
20085
+ const result = formatParts.reduce((acc, part, index) => {
20086
+ const value = valueParts[index];
20087
+
20088
+ if ((/m/iu).test(part)) {
20089
+ acc.month = value;
20090
+ } else if ((/d/iu).test(part)) {
20091
+ acc.day = value;
20092
+ } else if ((/y/iu).test(part)) {
20093
+ acc.year = value;
20094
+ }
20095
+
20096
+ return acc;
20097
+ }, {});
20098
+
20099
+ // If we found all the parts, return the result
20100
+ if (result.month && result.year) {
20101
+ return result;
20102
+ }
20103
+
20104
+ // Throw an error to let the dev know we were unable to parse the date string
20105
+ throw new Error('AuroDatepickerUtilities | parseDate: Unable to parse date string');
20106
+ };
20107
+
20108
+ /**
20109
+ * Convert a date object to string format.
20110
+ * @param {Object} date - Date to convert to string.
20111
+ * @returns {Object} Returns the date as a string.
20112
+ */
20113
+ this.getDateAsString = (date) => date.toLocaleDateString(undefined, {
20114
+ year: "numeric",
20115
+ month: "2-digit",
20116
+ day: "2-digit",
20117
+ });
20118
+
20119
+ /**
20120
+ * Converts a date string to a North American date format.
20121
+ * @param {String} dateStr - Date to validate.
20122
+ * @param {String} format - Date format to validate against.
20123
+ * @returns {Boolean}
20124
+ */
20125
+ this.toNorthAmericanFormat = (dateStr, format) => {
20126
+
20127
+ if (format === 'mm/dd/yyyy') {
20128
+ return dateStr;
20129
+ }
20130
+
20131
+ const parsedDate = this.parseDate(dateStr, format);
20132
+
20133
+ if (!parsedDate) {
20134
+ throw new Error('AuroDatepickerUtilities | toNorthAmericanFormat: Unable to parse date string');
20135
+ }
20136
+
20137
+ const { month, day, year } = parsedDate;
20138
+
20139
+ const dateParts = [];
20140
+ if (month) {
20141
+ dateParts.push(month);
20142
+ }
20143
+
20144
+ if (day) {
20145
+ dateParts.push(day);
20146
+ }
20147
+
20148
+ if (year) {
20149
+ dateParts.push(year);
20150
+ }
20151
+
20152
+ return dateParts.join('/');
20153
+ };
20154
+ }
20155
+ }
20156
+ const dateFormatter = new DateFormatter();
20157
+
20158
+ // filepath: dateConstraints.mjs
20159
+ const DATE_UTIL_CONSTRAINTS = {
20160
+ maxDay: 31,
20161
+ maxMonth: 12,
20162
+ maxYear: 2400,
20163
+ minDay: 1,
20164
+ minMonth: 1,
20165
+ minYear: 1900,
20166
+ };
20167
+
20168
+ class AuroDateUtilitiesBase {
20169
+
20170
+ /**
20171
+ * @description The maximum day value allowed by the various utilities in this class.
20172
+ * @readonly
20173
+ * @type {Number}
20174
+ */
20175
+ get maxDay() {
20176
+ return DATE_UTIL_CONSTRAINTS.maxDay;
20177
+ }
20178
+
20179
+ /**
20180
+ * @description The maximum month value allowed by the various utilities in this class.
20181
+ * @readonly
20182
+ * @type {Number}
20183
+ */
20184
+ get maxMonth() {
20185
+ return DATE_UTIL_CONSTRAINTS.maxMonth;
20186
+ }
20187
+
20188
+ /**
20189
+ * @description The maximum year value allowed by the various utilities in this class.
20190
+ * @readonly
20191
+ * @type {Number}
20192
+ */
20193
+ get maxYear() {
20194
+ return DATE_UTIL_CONSTRAINTS.maxYear;
20195
+ }
20196
+
20197
+ /**
20198
+ * @description The minimum day value allowed by the various utilities in this class.
20199
+ * @readonly
20200
+ * @type {Number}
20201
+ */
20202
+ get minDay() {
20203
+ return DATE_UTIL_CONSTRAINTS.minDay;
20204
+ }
20205
+
20206
+ /**
20207
+ * @description The minimum month value allowed by the various utilities in this class.
20208
+ * @readonly
20209
+ * @type {Number}
20210
+ */
20211
+ get minMonth() {
20212
+ return DATE_UTIL_CONSTRAINTS.minMonth;
20213
+ }
20214
+
20215
+ /**
20216
+ * @description The minimum year value allowed by the various utilities in this class.
20217
+ * @readonly
20218
+ * @type {Number}
20219
+ */
20220
+ get minYear() {
20221
+ return DATE_UTIL_CONSTRAINTS.minYear;
20222
+ }
20223
+ }
20224
+
20225
+ /* eslint-disable no-magic-numbers */
20226
+
20227
+ class AuroDateUtilities extends AuroDateUtilitiesBase {
20228
+
20229
+ /**
20230
+ * Returns the current century.
20231
+ * @returns {String} The current century.
20232
+ */
20233
+ getCentury () {
20234
+ return String(new Date().getFullYear()).slice(0, 2);
20235
+ }
20236
+
20237
+ /**
20238
+ * Returns a four digit year.
20239
+ * @param {String} year - The year to convert to four digits.
20240
+ * @returns {String} The four digit year.
20241
+ */
20242
+ getFourDigitYear (year) {
20243
+
20244
+ const strYear = String(year).trim();
20245
+ return strYear.length <= 2 ? this.getCentury() + strYear : strYear;
20246
+ }
20247
+
20248
+ constructor() {
20249
+
20250
+ super();
20251
+
20252
+ /**
20253
+ * Compares two dates to see if they match.
20254
+ * @param {Object} date1 - First date to compare.
20255
+ * @param {Object} date2 - Second date to compare.
20256
+ * @returns {Boolean} Returns true if the dates match.
20257
+ */
20258
+ this.datesMatch = (date1, date2) => new Date(date1).getTime() === new Date(date2).getTime();
20259
+
20260
+ /**
20261
+ * Returns true if value passed in is a valid date.
20262
+ * @param {String} date - Date to validate.
20263
+ * @param {String} format - Date format to validate against.
20264
+ * @returns {Boolean}
20265
+ */
20266
+ this.validDateStr = (date, format) => {
20267
+
20268
+ // The length we expect the date string to be
20269
+ const dateStrLength = format.length;
20270
+
20271
+ // Guard Clause: Date and format are defined
20272
+ if (typeof date === "undefined" || typeof format === "undefined") {
20273
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date and format are required');
20274
+ }
20275
+
20276
+ // Guard Clause: Date should be of type string
20277
+ if (typeof date !== "string") {
20278
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date must be a string');
20279
+ }
20280
+
20281
+ // Guard Clause: Format should be of type string
20282
+ if (typeof format !== "string") {
20283
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Format must be a string');
20284
+ }
20285
+
20286
+ // Guard Clause: Length is what we expect it to be
20287
+ if (date.length !== dateStrLength) {
20288
+ return false;
20289
+ }
20290
+ // Get a formatted date string and parse it
20291
+ const dateParts = dateFormatter.parseDate(date, format);
20292
+
20293
+ // Guard Clause: Date parse succeeded
20294
+ if (!dateParts) {
20295
+ return false;
20296
+ }
20297
+
20298
+ // Create the expected date string based on the date parts
20299
+ const expectedDateStr = `${dateParts.month}/${dateParts.day || "01"}/${this.getFourDigitYear(dateParts.year)}`;
20300
+
20301
+ // Generate a date object that we will extract a string date from to compare to the passed in date string
20302
+ const dateObj = new Date(this.getFourDigitYear(dateParts.year), dateParts.month - 1, dateParts.day || 1);
20303
+
20304
+ // Get the date string of the date object we created from the string date
20305
+ const actualDateStr = dateFormatter.getDateAsString(dateObj);
20306
+
20307
+ // Guard Clause: Generated date matches date string input
20308
+ if (expectedDateStr !== actualDateStr) {
20309
+ return false;
20310
+ }
20311
+
20312
+ // If we passed all other checks, we can assume the date is valid
20313
+ return true;
20314
+ };
20315
+
20316
+ /**
20317
+ * Determines if a string date value matches the format provided.
20318
+ * @param {string} value = The date string value.
20319
+ * @param { string} format = The date format to match against.
20320
+ * @returns {boolean}
20321
+ */
20322
+ this.dateAndFormatMatch = (value, format) => {
20323
+
20324
+ // Ensure we have both values we need to do the comparison
20325
+ if (!value || !format) {
20326
+ throw new Error('AuroFormValidation | dateFormatMatch: value and format are required');
20327
+ }
20328
+
20329
+ // If the lengths are different, they cannot match
20330
+ if (value.length !== format.length) {
20331
+ return false;
20332
+ }
20333
+
20334
+ // Get the parts of the date
20335
+ const dateParts = dateFormatter.parseDate(value, format);
20336
+
20337
+ // Validator for day
20338
+ const dayValueIsValid = (day) => {
20339
+
20340
+ // Guard clause: if there is no day in the dateParts, we can ignore this check.
20341
+ if (!dateParts.day) {
20342
+ return true;
20343
+ }
20344
+
20345
+ // Guard clause: ensure day exists.
20346
+ if (!day) {
20347
+ return false;
20348
+ }
20349
+
20350
+ // Convert day to number
20351
+ const numDay = Number.parseInt(day, 10);
20352
+
20353
+ // Guard clause: ensure day is a valid integer
20354
+ if (Number.isNaN(numDay)) {
20355
+ throw new Error('AuroDatepickerUtilities | dayValueIsValid: Unable to parse day value integer');
20356
+ }
20357
+
20358
+ // Guard clause: ensure day is within the valid range
20359
+ if (numDay < this.minDay || numDay > this.maxDay) {
20360
+ return false;
20361
+ }
20362
+
20363
+ // Default return
20364
+ return true;
20365
+ };
20366
+
20367
+ // Validator for month
20368
+ const monthValueIsValid = (month) => {
20369
+
20370
+ // Guard clause: ensure month exists.
20371
+ if (!month) {
20372
+ return false;
20373
+ }
20374
+
20375
+ // Convert month to number
20376
+ const numMonth = Number.parseInt(month, 10);
20377
+
20378
+ // Guard clause: ensure month is a valid integer
20379
+ if (Number.isNaN(numMonth)) {
20380
+ throw new Error('AuroDatepickerUtilities | monthValueIsValid: Unable to parse month value integer');
20381
+ }
20382
+
20383
+ // Guard clause: ensure month is within the valid range
20384
+ if (numMonth < this.minMonth || numMonth > this.maxMonth) {
20385
+ return false;
20386
+ }
20387
+
20388
+ // Default return
20389
+ return true;
20390
+ };
20391
+
20392
+ // Validator for year
20393
+ const yearIsValid = (_year) => {
20394
+
20395
+ // Guard clause: ensure year exists.
20396
+ if (!_year) {
20397
+ return false;
20398
+ }
20399
+
20400
+ // Get the full year
20401
+ const year = this.getFourDigitYear(_year);
20402
+
20403
+ // Convert year to number
20404
+ const numYear = Number.parseInt(year, 10);
20405
+
20406
+ // Guard clause: ensure year is a valid integer
20407
+ if (Number.isNaN(numYear)) {
20408
+ throw new Error('AuroDatepickerUtilities | yearValueIsValid: Unable to parse year value integer');
20409
+ }
20410
+
20411
+ // Guard clause: ensure year is within the valid range
20412
+ if (numYear < this.minYear || numYear > this.maxYear) {
20413
+ return false;
20414
+ }
20415
+
20416
+ // Default return
20417
+ return true;
20418
+ };
20419
+
20420
+ // Self-contained checks for month, day, and year
20421
+ const checks = [
20422
+ monthValueIsValid(dateParts.month),
20423
+ dayValueIsValid(dateParts.day),
20424
+ yearIsValid(dateParts.year)
20425
+ ];
20426
+
20427
+ // If any of the checks failed, the date format does not match and the result is invalid
20428
+ const isValid = checks.every((check) => check === true);
20429
+
20430
+ // If the check is invalid, return false
20431
+ if (!isValid) {
20432
+ return false;
20433
+ }
20434
+
20435
+ // Default case
20436
+ return true;
20437
+ };
20438
+ }
20439
+ }
20440
+
20441
+ // Export a class instance
20442
+ const dateUtilities = new AuroDateUtilities();
20443
+
20444
+ // Export the class instance methods individually
20445
+ const {
20446
+ datesMatch,
20447
+ validDateStr,
20448
+ dateAndFormatMatch,
20449
+ minDay,
20450
+ minMonth,
20451
+ minYear,
20452
+ maxDay,
20453
+ maxMonth,
20454
+ maxYear
20455
+ } = dateUtilities;
20456
+
20457
+ const {
20458
+ toNorthAmericanFormat,
20459
+ parseDate,
20460
+ getDateAsString
20461
+ } = dateFormatter;
20462
+
19530
20463
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
19531
20464
  // See LICENSE in the project root for license information.
19532
20465
 
@@ -19602,6 +20535,7 @@ let AuroLibraryRuntimeUtils$1 = class AuroLibraryRuntimeUtils {
19602
20535
 
19603
20536
 
19604
20537
  class AuroFormValidation {
20538
+
19605
20539
  constructor() {
19606
20540
  this.runtimeUtils = new AuroLibraryRuntimeUtils$1();
19607
20541
  }
@@ -19693,17 +20627,17 @@ class AuroFormValidation {
19693
20627
  ]
19694
20628
  }
19695
20629
  };
19696
-
20630
+
19697
20631
  let elementType;
19698
20632
  if (this.runtimeUtils.elementMatch(elem, 'auro-input')) {
19699
20633
  elementType = 'input';
19700
20634
  } else if (this.runtimeUtils.elementMatch(elem, 'auro-counter') || this.runtimeUtils.elementMatch(elem, 'auro-counter-group')) {
19701
20635
  elementType = 'counter';
19702
20636
  }
19703
-
20637
+
19704
20638
  if (elementType) {
19705
20639
  const rules = validationRules[elementType];
19706
-
20640
+
19707
20641
  if (rules) {
19708
20642
  Object.values(rules).flat().forEach(rule => {
19709
20643
  if (rule.check(elem)) {
@@ -19729,48 +20663,82 @@ class AuroFormValidation {
19729
20663
  if (!elem.value.match(emailRegex)) {
19730
20664
  elem.validity = 'patternMismatch';
19731
20665
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20666
+ return;
19732
20667
  }
19733
20668
  } else if (elem.type === 'credit-card') {
19734
20669
  if (elem.value.length > 0 && elem.value.length < elem.validationCCLength) {
19735
20670
  elem.validity = 'tooShort';
19736
20671
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20672
+ return;
19737
20673
  }
19738
20674
  } else if (elem.type === 'number') {
19739
20675
  if (elem.max !== undefined && Number(elem.max) < Number(elem.value)) {
19740
20676
  elem.validity = 'rangeOverflow';
19741
20677
  elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
20678
+ return;
19742
20679
  }
19743
20680
 
19744
20681
  if (elem.min !== undefined && elem.value?.length > 0 && Number(elem.min) > Number(elem.value)) {
19745
20682
  elem.validity = 'rangeUnderflow';
19746
20683
  elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
20684
+ return;
19747
20685
  }
19748
- } else if (elem.type === 'date') {
19749
- if (elem.value?.length > 0 && elem.value?.length < elem.lengthForType) {
20686
+ } else if (elem.type === 'date' && elem.value?.length > 0) {
20687
+
20688
+ // Guard Clause: if the value is too short
20689
+ if (elem.value.length < elem.lengthForType) {
20690
+
19750
20691
  elem.validity = 'tooShort';
19751
20692
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
19752
- } else if (elem.value?.length === elem.lengthForType && elem.util.toNorthAmericanFormat(elem.value, elem.format)) {
19753
- const formattedValue = elem.util.toNorthAmericanFormat(elem.value, elem.format);
19754
- const valueDate = new Date(formattedValue.dateForComparison);
20693
+ return;
20694
+ }
20695
+
20696
+ // Guard Clause: If the value is too long for the type
20697
+ if (elem.value?.length > elem.lengthForType) {
20698
+
20699
+ elem.validity = 'tooLong';
20700
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20701
+ return;
20702
+ }
20703
+
20704
+ // Validate that the date passed was the correct format
20705
+ if (!dateAndFormatMatch(elem.value, elem.format)) {
20706
+ elem.validity = 'patternMismatch';
20707
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || 'Invalid Date Format Entered';
20708
+ return;
20709
+ }
20710
+
20711
+ // Validate that the date passed was a valid date
20712
+ if (!validDateStr(elem.value, elem.format)) {
20713
+ elem.validity = 'invalidDate';
20714
+ elem.errorMessage = elem.setCustomValidityInvalidDate || elem.setCustomValidity || 'Invalid Date Entered';
20715
+ return;
20716
+ }
19755
20717
 
19756
- // validate max
19757
- if (elem.max?.length === elem.lengthForType) {
19758
- const maxDate = new Date(elem.util.toNorthAmericanFormat(elem.max, elem.format).dateForComparison);
20718
+ // Perform the rest of the validation
20719
+ const formattedValue = toNorthAmericanFormat(elem.value, elem.format);
20720
+ const valueDate = new Date(formattedValue);
19759
20721
 
19760
- if (valueDate > maxDate) {
19761
- elem.validity = 'rangeOverflow';
19762
- elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
19763
- }
20722
+ // // Validate max date
20723
+ if (elem.max?.length === elem.lengthForType) {
20724
+
20725
+ const maxDate = new Date(toNorthAmericanFormat(elem.max, elem.format));
20726
+
20727
+ if (valueDate > maxDate) {
20728
+ elem.validity = 'rangeOverflow';
20729
+ elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
20730
+ return;
19764
20731
  }
20732
+ }
19765
20733
 
19766
- // validate min
19767
- if (elem.min?.length === elem.lengthForType) {
19768
- const minDate = new Date(elem.util.toNorthAmericanFormat(elem.min, elem.format).dateForComparison);
20734
+ // Validate min date
20735
+ if (elem.min?.length === elem.lengthForType) {
20736
+ const minDate = new Date(toNorthAmericanFormat(elem.min, elem.format));
19769
20737
 
19770
- if (valueDate < minDate) {
19771
- elem.validity = 'rangeUnderflow';
19772
- elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
19773
- }
20738
+ if (valueDate < minDate) {
20739
+ elem.validity = 'rangeUnderflow';
20740
+ elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
20741
+ return;
19774
20742
  }
19775
20743
  }
19776
20744
  }
@@ -19889,7 +20857,7 @@ class AuroFormValidation {
19889
20857
  if (input.validationMessage.length > 0) {
19890
20858
  elem.errorMessage = input.validationMessage;
19891
20859
  }
19892
- } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
20860
+ } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
19893
20861
  const firstInput = this.inputElements[0];
19894
20862
 
19895
20863
  if (firstInput.validationMessage.length > 0) {
@@ -20011,6 +20979,33 @@ class BaseInput extends r$2 {
20011
20979
  static get properties() {
20012
20980
  return {
20013
20981
 
20982
+ /**
20983
+ * The value for the role attribute.
20984
+ */
20985
+ a11yRole: {
20986
+ type: String,
20987
+ attribute: true,
20988
+ reflect: true
20989
+ },
20990
+
20991
+ /**
20992
+ * The value for the aria-expanded attribute.
20993
+ */
20994
+ a11yExpanded: {
20995
+ type: Boolean,
20996
+ attribute: true,
20997
+ reflect: true
20998
+ },
20999
+
21000
+ /**
21001
+ * The value for the aria-controls attribute.
21002
+ */
21003
+ a11yControls: {
21004
+ type: String,
21005
+ attribute: true,
21006
+ reflect: true
21007
+ },
21008
+
20014
21009
  /**
20015
21010
  * If set, the label will remain fixed in the active position.
20016
21011
  */
@@ -20652,6 +21647,10 @@ class BaseInput extends r$2 {
20652
21647
  } else if (this.type === 'number') {
20653
21648
  this.inputMode = 'numeric';
20654
21649
  }
21650
+
21651
+ if (this.type === "date" && !this.format) {
21652
+ this.format = 'mm/dd/yyyy';
21653
+ }
20655
21654
  }
20656
21655
 
20657
21656
  /**
@@ -21895,6 +22894,7 @@ var helpTextVersion = '1.0.0';
21895
22894
 
21896
22895
  // build the component class
21897
22896
  class AuroInput extends BaseInput {
22897
+
21898
22898
  constructor() {
21899
22899
  super();
21900
22900
 
@@ -22007,7 +23007,7 @@ class AuroInput extends BaseInput {
22007
23007
  ?required="${this.required}"
22008
23008
  ?disabled="${this.disabled}"
22009
23009
  aria-describedby="${this.uniqueId}"
22010
- aria-invalid="${this.validity !== 'valid'}"
23010
+ ?aria-invalid="${this.validity !== 'valid'}"
22011
23011
  placeholder=${this.getPlaceholder()}
22012
23012
  lang="${o(this.lang)}"
22013
23013
  ?activeLabel="${this.activeLabel}"
@@ -22016,7 +23016,10 @@ class AuroInput extends BaseInput {
22016
23016
  autocapitalize="${o(this.autocapitalize ? this.autocapitalize : undefined)}"
22017
23017
  autocomplete="${o(this.autocomplete ? this.autocomplete : undefined)}"
22018
23018
  part="input"
22019
- />
23019
+ role="${o(this.a11yRole)}"
23020
+ aria-expanded="${o(this.a11yExpanded)}"
23021
+ aria-controls="${o(this.a11yControls)}"
23022
+ />
22020
23023
  </div>
22021
23024
  <div
22022
23025
  class="notificationIcons"