@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
@@ -290,6 +290,414 @@ const t$2=globalThis,i$3=t$2.trustedTypes,s$2=i$3?i$3.createPolicy("lit-html",{c
290
290
  */
291
291
  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);
292
292
 
293
+ let DateFormatter$1 = class DateFormatter {
294
+
295
+ constructor() {
296
+
297
+ /**
298
+ * @description Parses a date string into its components.
299
+ * @param {string} dateStr - Date string to parse.
300
+ * @param {string} format - Date format to parse.
301
+ * @returns {Object<key["month" | "day" | "year"]: number>|undefined}
302
+ */
303
+ this.parseDate = (dateStr, format = 'mm/dd/yyyy') => {
304
+
305
+ // Guard Clause: Date string is defined
306
+ if (!dateStr) {
307
+ return undefined;
308
+ }
309
+
310
+ // Assume the separator is a "/" a defined in our code base
311
+ const separator = '/';
312
+
313
+ // Get the parts of the date and format
314
+ const valueParts = dateStr.split(separator);
315
+ const formatParts = format.split(separator);
316
+
317
+ // Check if the value and format have the correct number of parts
318
+ if (valueParts.length !== formatParts.length) {
319
+ throw new Error('AuroDatepickerUtilities | parseDate: Date string and format length do not match');
320
+ }
321
+
322
+ // Holds the result to be returned
323
+ const result = formatParts.reduce((acc, part, index) => {
324
+ const value = valueParts[index];
325
+
326
+ if ((/m/iu).test(part)) {
327
+ acc.month = value;
328
+ } else if ((/d/iu).test(part)) {
329
+ acc.day = value;
330
+ } else if ((/y/iu).test(part)) {
331
+ acc.year = value;
332
+ }
333
+
334
+ return acc;
335
+ }, {});
336
+
337
+ // If we found all the parts, return the result
338
+ if (result.month && result.year) {
339
+ return result;
340
+ }
341
+
342
+ // Throw an error to let the dev know we were unable to parse the date string
343
+ throw new Error('AuroDatepickerUtilities | parseDate: Unable to parse date string');
344
+ };
345
+
346
+ /**
347
+ * Convert a date object to string format.
348
+ * @param {Object} date - Date to convert to string.
349
+ * @returns {Object} Returns the date as a string.
350
+ */
351
+ this.getDateAsString = (date) => date.toLocaleDateString(undefined, {
352
+ year: "numeric",
353
+ month: "2-digit",
354
+ day: "2-digit",
355
+ });
356
+
357
+ /**
358
+ * Converts a date string to a North American date format.
359
+ * @param {String} dateStr - Date to validate.
360
+ * @param {String} format - Date format to validate against.
361
+ * @returns {Boolean}
362
+ */
363
+ this.toNorthAmericanFormat = (dateStr, format) => {
364
+
365
+ if (format === 'mm/dd/yyyy') {
366
+ return dateStr;
367
+ }
368
+
369
+ const parsedDate = this.parseDate(dateStr, format);
370
+
371
+ if (!parsedDate) {
372
+ throw new Error('AuroDatepickerUtilities | toNorthAmericanFormat: Unable to parse date string');
373
+ }
374
+
375
+ const { month, day, year } = parsedDate;
376
+
377
+ const dateParts = [];
378
+ if (month) {
379
+ dateParts.push(month);
380
+ }
381
+
382
+ if (day) {
383
+ dateParts.push(day);
384
+ }
385
+
386
+ if (year) {
387
+ dateParts.push(year);
388
+ }
389
+
390
+ return dateParts.join('/');
391
+ };
392
+ }
393
+ };
394
+ const dateFormatter$1 = new DateFormatter$1();
395
+
396
+ // filepath: dateConstraints.mjs
397
+ const DATE_UTIL_CONSTRAINTS$1 = {
398
+ maxDay: 31,
399
+ maxMonth: 12,
400
+ maxYear: 2400,
401
+ minDay: 1,
402
+ minMonth: 1,
403
+ minYear: 1900,
404
+ };
405
+
406
+ let AuroDateUtilitiesBase$1 = class AuroDateUtilitiesBase {
407
+
408
+ /**
409
+ * @description The maximum day value allowed by the various utilities in this class.
410
+ * @readonly
411
+ * @type {Number}
412
+ */
413
+ get maxDay() {
414
+ return DATE_UTIL_CONSTRAINTS$1.maxDay;
415
+ }
416
+
417
+ /**
418
+ * @description The maximum month value allowed by the various utilities in this class.
419
+ * @readonly
420
+ * @type {Number}
421
+ */
422
+ get maxMonth() {
423
+ return DATE_UTIL_CONSTRAINTS$1.maxMonth;
424
+ }
425
+
426
+ /**
427
+ * @description The maximum year value allowed by the various utilities in this class.
428
+ * @readonly
429
+ * @type {Number}
430
+ */
431
+ get maxYear() {
432
+ return DATE_UTIL_CONSTRAINTS$1.maxYear;
433
+ }
434
+
435
+ /**
436
+ * @description The minimum day value allowed by the various utilities in this class.
437
+ * @readonly
438
+ * @type {Number}
439
+ */
440
+ get minDay() {
441
+ return DATE_UTIL_CONSTRAINTS$1.minDay;
442
+ }
443
+
444
+ /**
445
+ * @description The minimum month value allowed by the various utilities in this class.
446
+ * @readonly
447
+ * @type {Number}
448
+ */
449
+ get minMonth() {
450
+ return DATE_UTIL_CONSTRAINTS$1.minMonth;
451
+ }
452
+
453
+ /**
454
+ * @description The minimum year value allowed by the various utilities in this class.
455
+ * @readonly
456
+ * @type {Number}
457
+ */
458
+ get minYear() {
459
+ return DATE_UTIL_CONSTRAINTS$1.minYear;
460
+ }
461
+ };
462
+
463
+ /* eslint-disable no-magic-numbers */
464
+
465
+ let AuroDateUtilities$1 = class AuroDateUtilities extends AuroDateUtilitiesBase$1 {
466
+
467
+ /**
468
+ * Returns the current century.
469
+ * @returns {String} The current century.
470
+ */
471
+ getCentury () {
472
+ return String(new Date().getFullYear()).slice(0, 2);
473
+ }
474
+
475
+ /**
476
+ * Returns a four digit year.
477
+ * @param {String} year - The year to convert to four digits.
478
+ * @returns {String} The four digit year.
479
+ */
480
+ getFourDigitYear (year) {
481
+
482
+ const strYear = String(year).trim();
483
+ return strYear.length <= 2 ? this.getCentury() + strYear : strYear;
484
+ }
485
+
486
+ constructor() {
487
+
488
+ super();
489
+
490
+ /**
491
+ * Compares two dates to see if they match.
492
+ * @param {Object} date1 - First date to compare.
493
+ * @param {Object} date2 - Second date to compare.
494
+ * @returns {Boolean} Returns true if the dates match.
495
+ */
496
+ this.datesMatch = (date1, date2) => new Date(date1).getTime() === new Date(date2).getTime();
497
+
498
+ /**
499
+ * Returns true if value passed in is a valid date.
500
+ * @param {String} date - Date to validate.
501
+ * @param {String} format - Date format to validate against.
502
+ * @returns {Boolean}
503
+ */
504
+ this.validDateStr = (date, format) => {
505
+
506
+ // The length we expect the date string to be
507
+ const dateStrLength = format.length;
508
+
509
+ // Guard Clause: Date and format are defined
510
+ if (typeof date === "undefined" || typeof format === "undefined") {
511
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date and format are required');
512
+ }
513
+
514
+ // Guard Clause: Date should be of type string
515
+ if (typeof date !== "string") {
516
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date must be a string');
517
+ }
518
+
519
+ // Guard Clause: Format should be of type string
520
+ if (typeof format !== "string") {
521
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Format must be a string');
522
+ }
523
+
524
+ // Guard Clause: Length is what we expect it to be
525
+ if (date.length !== dateStrLength) {
526
+ return false;
527
+ }
528
+ // Get a formatted date string and parse it
529
+ const dateParts = dateFormatter$1.parseDate(date, format);
530
+
531
+ // Guard Clause: Date parse succeeded
532
+ if (!dateParts) {
533
+ return false;
534
+ }
535
+
536
+ // Create the expected date string based on the date parts
537
+ const expectedDateStr = `${dateParts.month}/${dateParts.day || "01"}/${this.getFourDigitYear(dateParts.year)}`;
538
+
539
+ // Generate a date object that we will extract a string date from to compare to the passed in date string
540
+ const dateObj = new Date(this.getFourDigitYear(dateParts.year), dateParts.month - 1, dateParts.day || 1);
541
+
542
+ // Get the date string of the date object we created from the string date
543
+ const actualDateStr = dateFormatter$1.getDateAsString(dateObj);
544
+
545
+ // Guard Clause: Generated date matches date string input
546
+ if (expectedDateStr !== actualDateStr) {
547
+ return false;
548
+ }
549
+
550
+ // If we passed all other checks, we can assume the date is valid
551
+ return true;
552
+ };
553
+
554
+ /**
555
+ * Determines if a string date value matches the format provided.
556
+ * @param {string} value = The date string value.
557
+ * @param { string} format = The date format to match against.
558
+ * @returns {boolean}
559
+ */
560
+ this.dateAndFormatMatch = (value, format) => {
561
+
562
+ // Ensure we have both values we need to do the comparison
563
+ if (!value || !format) {
564
+ throw new Error('AuroFormValidation | dateFormatMatch: value and format are required');
565
+ }
566
+
567
+ // If the lengths are different, they cannot match
568
+ if (value.length !== format.length) {
569
+ return false;
570
+ }
571
+
572
+ // Get the parts of the date
573
+ const dateParts = dateFormatter$1.parseDate(value, format);
574
+
575
+ // Validator for day
576
+ const dayValueIsValid = (day) => {
577
+
578
+ // Guard clause: if there is no day in the dateParts, we can ignore this check.
579
+ if (!dateParts.day) {
580
+ return true;
581
+ }
582
+
583
+ // Guard clause: ensure day exists.
584
+ if (!day) {
585
+ return false;
586
+ }
587
+
588
+ // Convert day to number
589
+ const numDay = Number.parseInt(day, 10);
590
+
591
+ // Guard clause: ensure day is a valid integer
592
+ if (Number.isNaN(numDay)) {
593
+ throw new Error('AuroDatepickerUtilities | dayValueIsValid: Unable to parse day value integer');
594
+ }
595
+
596
+ // Guard clause: ensure day is within the valid range
597
+ if (numDay < this.minDay || numDay > this.maxDay) {
598
+ return false;
599
+ }
600
+
601
+ // Default return
602
+ return true;
603
+ };
604
+
605
+ // Validator for month
606
+ const monthValueIsValid = (month) => {
607
+
608
+ // Guard clause: ensure month exists.
609
+ if (!month) {
610
+ return false;
611
+ }
612
+
613
+ // Convert month to number
614
+ const numMonth = Number.parseInt(month, 10);
615
+
616
+ // Guard clause: ensure month is a valid integer
617
+ if (Number.isNaN(numMonth)) {
618
+ throw new Error('AuroDatepickerUtilities | monthValueIsValid: Unable to parse month value integer');
619
+ }
620
+
621
+ // Guard clause: ensure month is within the valid range
622
+ if (numMonth < this.minMonth || numMonth > this.maxMonth) {
623
+ return false;
624
+ }
625
+
626
+ // Default return
627
+ return true;
628
+ };
629
+
630
+ // Validator for year
631
+ const yearIsValid = (_year) => {
632
+
633
+ // Guard clause: ensure year exists.
634
+ if (!_year) {
635
+ return false;
636
+ }
637
+
638
+ // Get the full year
639
+ const year = this.getFourDigitYear(_year);
640
+
641
+ // Convert year to number
642
+ const numYear = Number.parseInt(year, 10);
643
+
644
+ // Guard clause: ensure year is a valid integer
645
+ if (Number.isNaN(numYear)) {
646
+ throw new Error('AuroDatepickerUtilities | yearValueIsValid: Unable to parse year value integer');
647
+ }
648
+
649
+ // Guard clause: ensure year is within the valid range
650
+ if (numYear < this.minYear || numYear > this.maxYear) {
651
+ return false;
652
+ }
653
+
654
+ // Default return
655
+ return true;
656
+ };
657
+
658
+ // Self-contained checks for month, day, and year
659
+ const checks = [
660
+ monthValueIsValid(dateParts.month),
661
+ dayValueIsValid(dateParts.day),
662
+ yearIsValid(dateParts.year)
663
+ ];
664
+
665
+ // If any of the checks failed, the date format does not match and the result is invalid
666
+ const isValid = checks.every((check) => check === true);
667
+
668
+ // If the check is invalid, return false
669
+ if (!isValid) {
670
+ return false;
671
+ }
672
+
673
+ // Default case
674
+ return true;
675
+ };
676
+ }
677
+ };
678
+
679
+ // Export a class instance
680
+ const dateUtilities$1 = new AuroDateUtilities$1();
681
+
682
+ // Export the class instance methods individually
683
+ const {
684
+ datesMatch: datesMatch$1,
685
+ validDateStr: validDateStr$1,
686
+ dateAndFormatMatch: dateAndFormatMatch$1,
687
+ minDay: minDay$1,
688
+ minMonth: minMonth$1,
689
+ minYear: minYear$1,
690
+ maxDay: maxDay$1,
691
+ maxMonth: maxMonth$1,
692
+ maxYear: maxYear$1
693
+ } = dateUtilities$1;
694
+
695
+ const {
696
+ toNorthAmericanFormat: toNorthAmericanFormat$1,
697
+ parseDate: parseDate$1,
698
+ getDateAsString: getDateAsString$1
699
+ } = dateFormatter$1;
700
+
293
701
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
294
702
  // See LICENSE in the project root for license information.
295
703
 
@@ -365,6 +773,7 @@ let AuroLibraryRuntimeUtils$4 = class AuroLibraryRuntimeUtils {
365
773
 
366
774
 
367
775
  let AuroFormValidation$1 = class AuroFormValidation {
776
+
368
777
  constructor() {
369
778
  this.runtimeUtils = new AuroLibraryRuntimeUtils$4();
370
779
  }
@@ -456,17 +865,17 @@ let AuroFormValidation$1 = class AuroFormValidation {
456
865
  ]
457
866
  }
458
867
  };
459
-
868
+
460
869
  let elementType;
461
870
  if (this.runtimeUtils.elementMatch(elem, 'auro-input')) {
462
871
  elementType = 'input';
463
872
  } else if (this.runtimeUtils.elementMatch(elem, 'auro-counter') || this.runtimeUtils.elementMatch(elem, 'auro-counter-group')) {
464
873
  elementType = 'counter';
465
874
  }
466
-
875
+
467
876
  if (elementType) {
468
877
  const rules = validationRules[elementType];
469
-
878
+
470
879
  if (rules) {
471
880
  Object.values(rules).flat().forEach(rule => {
472
881
  if (rule.check(elem)) {
@@ -492,48 +901,82 @@ let AuroFormValidation$1 = class AuroFormValidation {
492
901
  if (!elem.value.match(emailRegex)) {
493
902
  elem.validity = 'patternMismatch';
494
903
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
904
+ return;
495
905
  }
496
906
  } else if (elem.type === 'credit-card') {
497
907
  if (elem.value.length > 0 && elem.value.length < elem.validationCCLength) {
498
908
  elem.validity = 'tooShort';
499
909
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
910
+ return;
500
911
  }
501
912
  } else if (elem.type === 'number') {
502
913
  if (elem.max !== undefined && Number(elem.max) < Number(elem.value)) {
503
914
  elem.validity = 'rangeOverflow';
504
915
  elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
916
+ return;
505
917
  }
506
918
 
507
919
  if (elem.min !== undefined && elem.value?.length > 0 && Number(elem.min) > Number(elem.value)) {
508
920
  elem.validity = 'rangeUnderflow';
509
921
  elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
922
+ return;
510
923
  }
511
- } else if (elem.type === 'date') {
512
- if (elem.value?.length > 0 && elem.value?.length < elem.lengthForType) {
924
+ } else if (elem.type === 'date' && elem.value?.length > 0) {
925
+
926
+ // Guard Clause: if the value is too short
927
+ if (elem.value.length < elem.lengthForType) {
928
+
513
929
  elem.validity = 'tooShort';
514
930
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
515
- } else if (elem.value?.length === elem.lengthForType && elem.util.toNorthAmericanFormat(elem.value, elem.format)) {
516
- const formattedValue = elem.util.toNorthAmericanFormat(elem.value, elem.format);
517
- const valueDate = new Date(formattedValue.dateForComparison);
931
+ return;
932
+ }
933
+
934
+ // Guard Clause: If the value is too long for the type
935
+ if (elem.value?.length > elem.lengthForType) {
518
936
 
519
- // validate max
520
- if (elem.max?.length === elem.lengthForType) {
521
- const maxDate = new Date(elem.util.toNorthAmericanFormat(elem.max, elem.format).dateForComparison);
937
+ elem.validity = 'tooLong';
938
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
939
+ return;
940
+ }
941
+
942
+ // Validate that the date passed was the correct format
943
+ if (!dateAndFormatMatch$1(elem.value, elem.format)) {
944
+ elem.validity = 'patternMismatch';
945
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || 'Invalid Date Format Entered';
946
+ return;
947
+ }
948
+
949
+ // Validate that the date passed was a valid date
950
+ if (!validDateStr$1(elem.value, elem.format)) {
951
+ elem.validity = 'invalidDate';
952
+ elem.errorMessage = elem.setCustomValidityInvalidDate || elem.setCustomValidity || 'Invalid Date Entered';
953
+ return;
954
+ }
522
955
 
523
- if (valueDate > maxDate) {
524
- elem.validity = 'rangeOverflow';
525
- elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
526
- }
956
+ // Perform the rest of the validation
957
+ const formattedValue = toNorthAmericanFormat$1(elem.value, elem.format);
958
+ const valueDate = new Date(formattedValue);
959
+
960
+ // // Validate max date
961
+ if (elem.max?.length === elem.lengthForType) {
962
+
963
+ const maxDate = new Date(toNorthAmericanFormat$1(elem.max, elem.format));
964
+
965
+ if (valueDate > maxDate) {
966
+ elem.validity = 'rangeOverflow';
967
+ elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
968
+ return;
527
969
  }
970
+ }
528
971
 
529
- // validate min
530
- if (elem.min?.length === elem.lengthForType) {
531
- const minDate = new Date(elem.util.toNorthAmericanFormat(elem.min, elem.format).dateForComparison);
972
+ // Validate min date
973
+ if (elem.min?.length === elem.lengthForType) {
974
+ const minDate = new Date(toNorthAmericanFormat$1(elem.min, elem.format));
532
975
 
533
- if (valueDate < minDate) {
534
- elem.validity = 'rangeUnderflow';
535
- elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
536
- }
976
+ if (valueDate < minDate) {
977
+ elem.validity = 'rangeUnderflow';
978
+ elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
979
+ return;
537
980
  }
538
981
  }
539
982
  }
@@ -652,7 +1095,7 @@ let AuroFormValidation$1 = class AuroFormValidation {
652
1095
  if (input.validationMessage.length > 0) {
653
1096
  elem.errorMessage = input.validationMessage;
654
1097
  }
655
- } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
1098
+ } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
656
1099
  const firstInput = this.inputElements[0];
657
1100
 
658
1101
  if (firstInput.validationMessage.length > 0) {
@@ -14019,7 +14462,7 @@ class AuroFloatingUI {
14019
14462
  /**
14020
14463
  * @private
14021
14464
  * getting called on 'blur' in trigger or `focusin` in document
14022
- *
14465
+ *
14023
14466
  * Hides the bib if focus moves outside of the trigger or bib, unless a 'noHideOnThisFocusLoss' flag is set.
14024
14467
  * This method checks if the currently active element is still within the trigger or bib.
14025
14468
  * If not, and if the bib isn't in fullscreen mode with focus lost, it hides the bib.
@@ -14135,7 +14578,7 @@ class AuroFloatingUI {
14135
14578
  // Close any other dropdown that is already open
14136
14579
  const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
14137
14580
  if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this &&
14138
- existedVisibleFloatingUI.isPopoverVisible &&
14581
+ existedVisibleFloatingUI.element.isPopoverVisible &&
14139
14582
  document.expandedAuroFloater.eventPrefix === this.eventPrefix) {
14140
14583
  document.expandedAuroFloater.hideBib();
14141
14584
  }
@@ -14311,7 +14754,7 @@ class AuroFloatingUI {
14311
14754
  this.id = window.crypto.randomUUID();
14312
14755
  this.element.setAttribute('id', this.id);
14313
14756
  }
14314
-
14757
+
14315
14758
  this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
14316
14759
  }
14317
14760
 
@@ -14364,7 +14807,7 @@ class AuroFloatingUI {
14364
14807
  if (this.element.bib) {
14365
14808
  this.element.shadowRoot.append(this.element.bib);
14366
14809
  }
14367
-
14810
+
14368
14811
  // Remove event & keyboard listeners
14369
14812
  if (this.element?.trigger) {
14370
14813
  this.element.trigger.removeEventListener('keydown', this.handleEvent);
@@ -15095,6 +15538,7 @@ var helpTextVersion$1 = '1.0.0';
15095
15538
  * @csspart helpText - The helpText content container.
15096
15539
  * @event auroDropdown-triggerClick - Notifies that the trigger has been clicked.
15097
15540
  * @event auroDropdown-toggled - Notifies that the visibility of the dropdown bib has changed.
15541
+ * @event auroDropdown-idAdded - Notifies consumers that the unique ID for the dropdown bib has been generated.
15098
15542
  */
15099
15543
  class AuroDropdown extends r$2 {
15100
15544
  constructor() {
@@ -15140,7 +15584,9 @@ class AuroDropdown extends r$2 {
15140
15584
  this.rounded = false;
15141
15585
  this.tabIndex = 0;
15142
15586
  this.noToggle = false;
15587
+ this.a11yAutocomplete = 'none';
15143
15588
  this.labeled = true;
15589
+ this.a11yRole = 'combobox';
15144
15590
  this.onDark = false;
15145
15591
 
15146
15592
  // floaterConfig
@@ -15276,6 +15722,16 @@ class AuroDropdown extends r$2 {
15276
15722
  type: Number
15277
15723
  },
15278
15724
 
15725
+ /**
15726
+ * The unique ID for the dropdown bib element.
15727
+ * @private
15728
+ */
15729
+ dropdownId: {
15730
+ type: String,
15731
+ reflect: false,
15732
+ attribute: false
15733
+ },
15734
+
15279
15735
  /**
15280
15736
  * If declared in combination with `bordered` property or `helpText` slot content, will apply red color to both.
15281
15737
  */
@@ -15443,6 +15899,23 @@ class AuroDropdown extends r$2 {
15443
15899
  */
15444
15900
  tabIndex: {
15445
15901
  type: Number
15902
+ },
15903
+
15904
+ /**
15905
+ * The value for the role attribute of the trigger element.
15906
+ */
15907
+ a11yRole: {
15908
+ type: String || undefined,
15909
+ attribute: false,
15910
+ reflect: false
15911
+ },
15912
+
15913
+ /**
15914
+ * The value for the aria-autocomplete attribute of the trigger element.
15915
+ */
15916
+ a11yAutocomplete: {
15917
+ type: String,
15918
+ attribute: false,
15446
15919
  }
15447
15920
  };
15448
15921
  }
@@ -15504,7 +15977,22 @@ class AuroDropdown extends r$2 {
15504
15977
  }
15505
15978
 
15506
15979
  firstUpdated() {
15980
+
15981
+ // Configure the floater to, this will generate the ID for the bib
15507
15982
  this.floater.configure(this, 'auroDropdown');
15983
+
15984
+ /**
15985
+ * @description Let subscribers know that the dropdown ID ha been generated and added.
15986
+ * @event auroDropdown-idAdded
15987
+ * @type {Object<key: 'id', value: string>} - The ID of the dropdown bib element.
15988
+ */
15989
+ this.dispatchEvent(new CustomEvent('auroDropdown-idAdded', {detail: {id: this.floater.element.id}}));
15990
+
15991
+ // Set the bib ID locally if the user hasn't provided a focusable trigger
15992
+ if (!this.triggerContentFocusable) {
15993
+ this.dropdownId = this.floater.element.id;
15994
+ }
15995
+
15508
15996
  this.bibContent = this.floater.element.bib;
15509
15997
 
15510
15998
  // Add the tag name as an attribute if it is different than the component name
@@ -15656,6 +16144,30 @@ class AuroDropdown extends r$2 {
15656
16144
  });
15657
16145
  }
15658
16146
 
16147
+ /*
16148
+ * Sets aria attributes for the trigger element if a custom one is passed in.
16149
+ * @private
16150
+ * @method setTriggerAriaAttributes
16151
+ * @param { HTMLElement } triggerElement - The custom trigger element.
16152
+ */
16153
+ clearTriggerA11yAttributes(triggerElement) {
16154
+
16155
+ if (!triggerElement || !triggerElement.removeAttribute) {
16156
+ return;
16157
+ }
16158
+
16159
+ // Reset appropriate attributes for a11y
16160
+ triggerElement.removeAttribute('aria-labelledby');
16161
+ if (triggerElement.getAttribute('id') === `${this.id}-trigger-element`) {
16162
+ triggerElement.removeAttribute('id');
16163
+ }
16164
+ triggerElement.removeAttribute('role');
16165
+ triggerElement.removeAttribute('aria-expanded');
16166
+
16167
+ triggerElement.removeAttribute('aria-controls');
16168
+ triggerElement.removeAttribute('aria-autocomplete');
16169
+ }
16170
+
15659
16171
  /**
15660
16172
  * Handles changes to the trigger content slot and updates related properties.
15661
16173
  *
@@ -15669,32 +16181,41 @@ class AuroDropdown extends r$2 {
15669
16181
  * @returns {void}
15670
16182
  */
15671
16183
  handleTriggerContentSlotChange(event) {
16184
+
15672
16185
  this.floater.handleTriggerTabIndex();
15673
16186
 
16187
+ // Get the trigger
16188
+ const trigger = this.shadowRoot.querySelector('#trigger');
16189
+
16190
+ // Get the trigger slot
15674
16191
  const triggerSlot = this.shadowRoot.querySelector('.triggerContent slot');
15675
16192
 
16193
+ // If there's a trigger slot
15676
16194
  if (triggerSlot) {
15677
16195
 
16196
+ // Get the content nodes to see if there are any children
15678
16197
  const triggerContentNodes = triggerSlot.assignedNodes();
15679
16198
 
16199
+ // If there are children
15680
16200
  if (triggerContentNodes) {
15681
16201
 
15682
- triggerContentNodes.forEach((node) => {
15683
- if (!this.triggerContentFocusable) {
15684
- this.triggerContentFocusable = this.containsFocusableElement(node);
15685
- }
15686
- });
15687
- }
15688
- }
16202
+ // See if any of them are focusable elemeents
16203
+ this.triggerContentFocusable = triggerContentNodes.some((node) => this.containsFocusableElement(node));
15689
16204
 
15690
- const trigger = this.shadowRoot.querySelector('#trigger');
16205
+ // If any of them are focusable elements
16206
+ if (this.triggerContentFocusable) {
15691
16207
 
15692
- if (!this.triggerContentFocusable) {
15693
- trigger.setAttribute('tabindex', '0');
15694
- trigger.setAttribute('role', 'button');
15695
- } else {
15696
- trigger.removeAttribute('tabindex');
15697
- trigger.removeAttribute('role');
16208
+ // Assume the consumer will be providing their own a11y in whatever they passed in
16209
+ this.clearTriggerA11yAttributes(trigger);
16210
+
16211
+ // Remove the tabindex from the trigger so it doesn't interrupt focus flow
16212
+ trigger.removeAttribute('tabindex');
16213
+ } else {
16214
+
16215
+ // Add the tabindex to the trigger so that it's in the focus flow
16216
+ trigger.setAttribute('tabindex', '0');
16217
+ }
16218
+ }
15698
16219
  }
15699
16220
 
15700
16221
  if (event) {
@@ -15704,6 +16225,7 @@ class AuroDropdown extends r$2 {
15704
16225
 
15705
16226
  if (this.triggerContentSlot) {
15706
16227
  this.setupTriggerFocusEventBinding();
16228
+
15707
16229
  this.hasTriggerContent = this.triggerContentSlot.some((slot) => {
15708
16230
  if (slot.textContent.trim()) {
15709
16231
  return true;
@@ -15771,10 +16293,13 @@ class AuroDropdown extends r$2 {
15771
16293
  id="trigger"
15772
16294
  class="trigger"
15773
16295
  part="trigger"
15774
- aria-labelledby="triggerLabel"
15775
16296
  tabindex="${this.tabIndex}"
15776
16297
  ?showBorder="${this.showTriggerBorders}"
15777
- >
16298
+ role="${o(this.triggerContentFocusable ? undefined : this.a11yRole)}"
16299
+ aria-expanded="${o(this.triggerContentFocusable ? undefined : this.isPopoverVisible)}"
16300
+ aria-controls="${o(this.triggerContentFocusable ? undefined : this.dropdownId)}"
16301
+ aria-labelledby="${o(this.triggerContentFocusable ? undefined : 'triggerLabel')}"
16302
+ >
15778
16303
  <div class="triggerContentWrapper">
15779
16304
  <label class="label" id="triggerLabel" hasTrigger=${this.hasTriggerContent}>
15780
16305
  <slot name="label" @slotchange="${this.handleLabelSlotChange}"></slot>
@@ -15808,12 +16333,12 @@ class AuroDropdown extends r$2 {
15808
16333
  <div id="bibSizer" part="size"></div>
15809
16334
  <${this.dropdownBibTag}
15810
16335
  id="bib"
15811
- role="tooltip"
15812
16336
  ?data-show="${this.isPopoverVisible}"
15813
16337
  ?isfullscreen="${this.isBibFullscreen}"
15814
16338
  ?common="${this.common}"
15815
16339
  ?rounded="${this.common || this.rounded}"
15816
- ?inset="${this.common || this.inset}">
16340
+ ?inset="${this.common || this.inset}"
16341
+ >
15817
16342
  </${this.dropdownBibTag}>
15818
16343
  </div>
15819
16344
  `;
@@ -19804,6 +20329,414 @@ class AuroInputUtilities {
19804
20329
  }
19805
20330
  }
19806
20331
 
20332
+ class DateFormatter {
20333
+
20334
+ constructor() {
20335
+
20336
+ /**
20337
+ * @description Parses a date string into its components.
20338
+ * @param {string} dateStr - Date string to parse.
20339
+ * @param {string} format - Date format to parse.
20340
+ * @returns {Object<key["month" | "day" | "year"]: number>|undefined}
20341
+ */
20342
+ this.parseDate = (dateStr, format = 'mm/dd/yyyy') => {
20343
+
20344
+ // Guard Clause: Date string is defined
20345
+ if (!dateStr) {
20346
+ return undefined;
20347
+ }
20348
+
20349
+ // Assume the separator is a "/" a defined in our code base
20350
+ const separator = '/';
20351
+
20352
+ // Get the parts of the date and format
20353
+ const valueParts = dateStr.split(separator);
20354
+ const formatParts = format.split(separator);
20355
+
20356
+ // Check if the value and format have the correct number of parts
20357
+ if (valueParts.length !== formatParts.length) {
20358
+ throw new Error('AuroDatepickerUtilities | parseDate: Date string and format length do not match');
20359
+ }
20360
+
20361
+ // Holds the result to be returned
20362
+ const result = formatParts.reduce((acc, part, index) => {
20363
+ const value = valueParts[index];
20364
+
20365
+ if ((/m/iu).test(part)) {
20366
+ acc.month = value;
20367
+ } else if ((/d/iu).test(part)) {
20368
+ acc.day = value;
20369
+ } else if ((/y/iu).test(part)) {
20370
+ acc.year = value;
20371
+ }
20372
+
20373
+ return acc;
20374
+ }, {});
20375
+
20376
+ // If we found all the parts, return the result
20377
+ if (result.month && result.year) {
20378
+ return result;
20379
+ }
20380
+
20381
+ // Throw an error to let the dev know we were unable to parse the date string
20382
+ throw new Error('AuroDatepickerUtilities | parseDate: Unable to parse date string');
20383
+ };
20384
+
20385
+ /**
20386
+ * Convert a date object to string format.
20387
+ * @param {Object} date - Date to convert to string.
20388
+ * @returns {Object} Returns the date as a string.
20389
+ */
20390
+ this.getDateAsString = (date) => date.toLocaleDateString(undefined, {
20391
+ year: "numeric",
20392
+ month: "2-digit",
20393
+ day: "2-digit",
20394
+ });
20395
+
20396
+ /**
20397
+ * Converts a date string to a North American date format.
20398
+ * @param {String} dateStr - Date to validate.
20399
+ * @param {String} format - Date format to validate against.
20400
+ * @returns {Boolean}
20401
+ */
20402
+ this.toNorthAmericanFormat = (dateStr, format) => {
20403
+
20404
+ if (format === 'mm/dd/yyyy') {
20405
+ return dateStr;
20406
+ }
20407
+
20408
+ const parsedDate = this.parseDate(dateStr, format);
20409
+
20410
+ if (!parsedDate) {
20411
+ throw new Error('AuroDatepickerUtilities | toNorthAmericanFormat: Unable to parse date string');
20412
+ }
20413
+
20414
+ const { month, day, year } = parsedDate;
20415
+
20416
+ const dateParts = [];
20417
+ if (month) {
20418
+ dateParts.push(month);
20419
+ }
20420
+
20421
+ if (day) {
20422
+ dateParts.push(day);
20423
+ }
20424
+
20425
+ if (year) {
20426
+ dateParts.push(year);
20427
+ }
20428
+
20429
+ return dateParts.join('/');
20430
+ };
20431
+ }
20432
+ }
20433
+ const dateFormatter = new DateFormatter();
20434
+
20435
+ // filepath: dateConstraints.mjs
20436
+ const DATE_UTIL_CONSTRAINTS = {
20437
+ maxDay: 31,
20438
+ maxMonth: 12,
20439
+ maxYear: 2400,
20440
+ minDay: 1,
20441
+ minMonth: 1,
20442
+ minYear: 1900,
20443
+ };
20444
+
20445
+ class AuroDateUtilitiesBase {
20446
+
20447
+ /**
20448
+ * @description The maximum day value allowed by the various utilities in this class.
20449
+ * @readonly
20450
+ * @type {Number}
20451
+ */
20452
+ get maxDay() {
20453
+ return DATE_UTIL_CONSTRAINTS.maxDay;
20454
+ }
20455
+
20456
+ /**
20457
+ * @description The maximum month value allowed by the various utilities in this class.
20458
+ * @readonly
20459
+ * @type {Number}
20460
+ */
20461
+ get maxMonth() {
20462
+ return DATE_UTIL_CONSTRAINTS.maxMonth;
20463
+ }
20464
+
20465
+ /**
20466
+ * @description The maximum year value allowed by the various utilities in this class.
20467
+ * @readonly
20468
+ * @type {Number}
20469
+ */
20470
+ get maxYear() {
20471
+ return DATE_UTIL_CONSTRAINTS.maxYear;
20472
+ }
20473
+
20474
+ /**
20475
+ * @description The minimum day value allowed by the various utilities in this class.
20476
+ * @readonly
20477
+ * @type {Number}
20478
+ */
20479
+ get minDay() {
20480
+ return DATE_UTIL_CONSTRAINTS.minDay;
20481
+ }
20482
+
20483
+ /**
20484
+ * @description The minimum month value allowed by the various utilities in this class.
20485
+ * @readonly
20486
+ * @type {Number}
20487
+ */
20488
+ get minMonth() {
20489
+ return DATE_UTIL_CONSTRAINTS.minMonth;
20490
+ }
20491
+
20492
+ /**
20493
+ * @description The minimum year value allowed by the various utilities in this class.
20494
+ * @readonly
20495
+ * @type {Number}
20496
+ */
20497
+ get minYear() {
20498
+ return DATE_UTIL_CONSTRAINTS.minYear;
20499
+ }
20500
+ }
20501
+
20502
+ /* eslint-disable no-magic-numbers */
20503
+
20504
+ class AuroDateUtilities extends AuroDateUtilitiesBase {
20505
+
20506
+ /**
20507
+ * Returns the current century.
20508
+ * @returns {String} The current century.
20509
+ */
20510
+ getCentury () {
20511
+ return String(new Date().getFullYear()).slice(0, 2);
20512
+ }
20513
+
20514
+ /**
20515
+ * Returns a four digit year.
20516
+ * @param {String} year - The year to convert to four digits.
20517
+ * @returns {String} The four digit year.
20518
+ */
20519
+ getFourDigitYear (year) {
20520
+
20521
+ const strYear = String(year).trim();
20522
+ return strYear.length <= 2 ? this.getCentury() + strYear : strYear;
20523
+ }
20524
+
20525
+ constructor() {
20526
+
20527
+ super();
20528
+
20529
+ /**
20530
+ * Compares two dates to see if they match.
20531
+ * @param {Object} date1 - First date to compare.
20532
+ * @param {Object} date2 - Second date to compare.
20533
+ * @returns {Boolean} Returns true if the dates match.
20534
+ */
20535
+ this.datesMatch = (date1, date2) => new Date(date1).getTime() === new Date(date2).getTime();
20536
+
20537
+ /**
20538
+ * Returns true if value passed in is a valid date.
20539
+ * @param {String} date - Date to validate.
20540
+ * @param {String} format - Date format to validate against.
20541
+ * @returns {Boolean}
20542
+ */
20543
+ this.validDateStr = (date, format) => {
20544
+
20545
+ // The length we expect the date string to be
20546
+ const dateStrLength = format.length;
20547
+
20548
+ // Guard Clause: Date and format are defined
20549
+ if (typeof date === "undefined" || typeof format === "undefined") {
20550
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date and format are required');
20551
+ }
20552
+
20553
+ // Guard Clause: Date should be of type string
20554
+ if (typeof date !== "string") {
20555
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Date must be a string');
20556
+ }
20557
+
20558
+ // Guard Clause: Format should be of type string
20559
+ if (typeof format !== "string") {
20560
+ throw new Error('AuroDatepickerUtilities | validateDateStr: Format must be a string');
20561
+ }
20562
+
20563
+ // Guard Clause: Length is what we expect it to be
20564
+ if (date.length !== dateStrLength) {
20565
+ return false;
20566
+ }
20567
+ // Get a formatted date string and parse it
20568
+ const dateParts = dateFormatter.parseDate(date, format);
20569
+
20570
+ // Guard Clause: Date parse succeeded
20571
+ if (!dateParts) {
20572
+ return false;
20573
+ }
20574
+
20575
+ // Create the expected date string based on the date parts
20576
+ const expectedDateStr = `${dateParts.month}/${dateParts.day || "01"}/${this.getFourDigitYear(dateParts.year)}`;
20577
+
20578
+ // Generate a date object that we will extract a string date from to compare to the passed in date string
20579
+ const dateObj = new Date(this.getFourDigitYear(dateParts.year), dateParts.month - 1, dateParts.day || 1);
20580
+
20581
+ // Get the date string of the date object we created from the string date
20582
+ const actualDateStr = dateFormatter.getDateAsString(dateObj);
20583
+
20584
+ // Guard Clause: Generated date matches date string input
20585
+ if (expectedDateStr !== actualDateStr) {
20586
+ return false;
20587
+ }
20588
+
20589
+ // If we passed all other checks, we can assume the date is valid
20590
+ return true;
20591
+ };
20592
+
20593
+ /**
20594
+ * Determines if a string date value matches the format provided.
20595
+ * @param {string} value = The date string value.
20596
+ * @param { string} format = The date format to match against.
20597
+ * @returns {boolean}
20598
+ */
20599
+ this.dateAndFormatMatch = (value, format) => {
20600
+
20601
+ // Ensure we have both values we need to do the comparison
20602
+ if (!value || !format) {
20603
+ throw new Error('AuroFormValidation | dateFormatMatch: value and format are required');
20604
+ }
20605
+
20606
+ // If the lengths are different, they cannot match
20607
+ if (value.length !== format.length) {
20608
+ return false;
20609
+ }
20610
+
20611
+ // Get the parts of the date
20612
+ const dateParts = dateFormatter.parseDate(value, format);
20613
+
20614
+ // Validator for day
20615
+ const dayValueIsValid = (day) => {
20616
+
20617
+ // Guard clause: if there is no day in the dateParts, we can ignore this check.
20618
+ if (!dateParts.day) {
20619
+ return true;
20620
+ }
20621
+
20622
+ // Guard clause: ensure day exists.
20623
+ if (!day) {
20624
+ return false;
20625
+ }
20626
+
20627
+ // Convert day to number
20628
+ const numDay = Number.parseInt(day, 10);
20629
+
20630
+ // Guard clause: ensure day is a valid integer
20631
+ if (Number.isNaN(numDay)) {
20632
+ throw new Error('AuroDatepickerUtilities | dayValueIsValid: Unable to parse day value integer');
20633
+ }
20634
+
20635
+ // Guard clause: ensure day is within the valid range
20636
+ if (numDay < this.minDay || numDay > this.maxDay) {
20637
+ return false;
20638
+ }
20639
+
20640
+ // Default return
20641
+ return true;
20642
+ };
20643
+
20644
+ // Validator for month
20645
+ const monthValueIsValid = (month) => {
20646
+
20647
+ // Guard clause: ensure month exists.
20648
+ if (!month) {
20649
+ return false;
20650
+ }
20651
+
20652
+ // Convert month to number
20653
+ const numMonth = Number.parseInt(month, 10);
20654
+
20655
+ // Guard clause: ensure month is a valid integer
20656
+ if (Number.isNaN(numMonth)) {
20657
+ throw new Error('AuroDatepickerUtilities | monthValueIsValid: Unable to parse month value integer');
20658
+ }
20659
+
20660
+ // Guard clause: ensure month is within the valid range
20661
+ if (numMonth < this.minMonth || numMonth > this.maxMonth) {
20662
+ return false;
20663
+ }
20664
+
20665
+ // Default return
20666
+ return true;
20667
+ };
20668
+
20669
+ // Validator for year
20670
+ const yearIsValid = (_year) => {
20671
+
20672
+ // Guard clause: ensure year exists.
20673
+ if (!_year) {
20674
+ return false;
20675
+ }
20676
+
20677
+ // Get the full year
20678
+ const year = this.getFourDigitYear(_year);
20679
+
20680
+ // Convert year to number
20681
+ const numYear = Number.parseInt(year, 10);
20682
+
20683
+ // Guard clause: ensure year is a valid integer
20684
+ if (Number.isNaN(numYear)) {
20685
+ throw new Error('AuroDatepickerUtilities | yearValueIsValid: Unable to parse year value integer');
20686
+ }
20687
+
20688
+ // Guard clause: ensure year is within the valid range
20689
+ if (numYear < this.minYear || numYear > this.maxYear) {
20690
+ return false;
20691
+ }
20692
+
20693
+ // Default return
20694
+ return true;
20695
+ };
20696
+
20697
+ // Self-contained checks for month, day, and year
20698
+ const checks = [
20699
+ monthValueIsValid(dateParts.month),
20700
+ dayValueIsValid(dateParts.day),
20701
+ yearIsValid(dateParts.year)
20702
+ ];
20703
+
20704
+ // If any of the checks failed, the date format does not match and the result is invalid
20705
+ const isValid = checks.every((check) => check === true);
20706
+
20707
+ // If the check is invalid, return false
20708
+ if (!isValid) {
20709
+ return false;
20710
+ }
20711
+
20712
+ // Default case
20713
+ return true;
20714
+ };
20715
+ }
20716
+ }
20717
+
20718
+ // Export a class instance
20719
+ const dateUtilities = new AuroDateUtilities();
20720
+
20721
+ // Export the class instance methods individually
20722
+ const {
20723
+ datesMatch,
20724
+ validDateStr,
20725
+ dateAndFormatMatch,
20726
+ minDay,
20727
+ minMonth,
20728
+ minYear,
20729
+ maxDay,
20730
+ maxMonth,
20731
+ maxYear
20732
+ } = dateUtilities;
20733
+
20734
+ const {
20735
+ toNorthAmericanFormat,
20736
+ parseDate,
20737
+ getDateAsString
20738
+ } = dateFormatter;
20739
+
19807
20740
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
19808
20741
  // See LICENSE in the project root for license information.
19809
20742
 
@@ -19879,6 +20812,7 @@ let AuroLibraryRuntimeUtils$1 = class AuroLibraryRuntimeUtils {
19879
20812
 
19880
20813
 
19881
20814
  class AuroFormValidation {
20815
+
19882
20816
  constructor() {
19883
20817
  this.runtimeUtils = new AuroLibraryRuntimeUtils$1();
19884
20818
  }
@@ -19970,17 +20904,17 @@ class AuroFormValidation {
19970
20904
  ]
19971
20905
  }
19972
20906
  };
19973
-
20907
+
19974
20908
  let elementType;
19975
20909
  if (this.runtimeUtils.elementMatch(elem, 'auro-input')) {
19976
20910
  elementType = 'input';
19977
20911
  } else if (this.runtimeUtils.elementMatch(elem, 'auro-counter') || this.runtimeUtils.elementMatch(elem, 'auro-counter-group')) {
19978
20912
  elementType = 'counter';
19979
20913
  }
19980
-
20914
+
19981
20915
  if (elementType) {
19982
20916
  const rules = validationRules[elementType];
19983
-
20917
+
19984
20918
  if (rules) {
19985
20919
  Object.values(rules).flat().forEach(rule => {
19986
20920
  if (rule.check(elem)) {
@@ -20006,48 +20940,82 @@ class AuroFormValidation {
20006
20940
  if (!elem.value.match(emailRegex)) {
20007
20941
  elem.validity = 'patternMismatch';
20008
20942
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20943
+ return;
20009
20944
  }
20010
20945
  } else if (elem.type === 'credit-card') {
20011
20946
  if (elem.value.length > 0 && elem.value.length < elem.validationCCLength) {
20012
20947
  elem.validity = 'tooShort';
20013
20948
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20949
+ return;
20014
20950
  }
20015
20951
  } else if (elem.type === 'number') {
20016
20952
  if (elem.max !== undefined && Number(elem.max) < Number(elem.value)) {
20017
20953
  elem.validity = 'rangeOverflow';
20018
20954
  elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
20955
+ return;
20019
20956
  }
20020
20957
 
20021
20958
  if (elem.min !== undefined && elem.value?.length > 0 && Number(elem.min) > Number(elem.value)) {
20022
20959
  elem.validity = 'rangeUnderflow';
20023
20960
  elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
20961
+ return;
20024
20962
  }
20025
- } else if (elem.type === 'date') {
20026
- if (elem.value?.length > 0 && elem.value?.length < elem.lengthForType) {
20963
+ } else if (elem.type === 'date' && elem.value?.length > 0) {
20964
+
20965
+ // Guard Clause: if the value is too short
20966
+ if (elem.value.length < elem.lengthForType) {
20967
+
20027
20968
  elem.validity = 'tooShort';
20028
20969
  elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20029
- } else if (elem.value?.length === elem.lengthForType && elem.util.toNorthAmericanFormat(elem.value, elem.format)) {
20030
- const formattedValue = elem.util.toNorthAmericanFormat(elem.value, elem.format);
20031
- const valueDate = new Date(formattedValue.dateForComparison);
20970
+ return;
20971
+ }
20972
+
20973
+ // Guard Clause: If the value is too long for the type
20974
+ if (elem.value?.length > elem.lengthForType) {
20975
+
20976
+ elem.validity = 'tooLong';
20977
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
20978
+ return;
20979
+ }
20980
+
20981
+ // Validate that the date passed was the correct format
20982
+ if (!dateAndFormatMatch(elem.value, elem.format)) {
20983
+ elem.validity = 'patternMismatch';
20984
+ elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || 'Invalid Date Format Entered';
20985
+ return;
20986
+ }
20987
+
20988
+ // Validate that the date passed was a valid date
20989
+ if (!validDateStr(elem.value, elem.format)) {
20990
+ elem.validity = 'invalidDate';
20991
+ elem.errorMessage = elem.setCustomValidityInvalidDate || elem.setCustomValidity || 'Invalid Date Entered';
20992
+ return;
20993
+ }
20032
20994
 
20033
- // validate max
20034
- if (elem.max?.length === elem.lengthForType) {
20035
- const maxDate = new Date(elem.util.toNorthAmericanFormat(elem.max, elem.format).dateForComparison);
20995
+ // Perform the rest of the validation
20996
+ const formattedValue = toNorthAmericanFormat(elem.value, elem.format);
20997
+ const valueDate = new Date(formattedValue);
20036
20998
 
20037
- if (valueDate > maxDate) {
20038
- elem.validity = 'rangeOverflow';
20039
- elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
20040
- }
20999
+ // // Validate max date
21000
+ if (elem.max?.length === elem.lengthForType) {
21001
+
21002
+ const maxDate = new Date(toNorthAmericanFormat(elem.max, elem.format));
21003
+
21004
+ if (valueDate > maxDate) {
21005
+ elem.validity = 'rangeOverflow';
21006
+ elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
21007
+ return;
20041
21008
  }
21009
+ }
20042
21010
 
20043
- // validate min
20044
- if (elem.min?.length === elem.lengthForType) {
20045
- const minDate = new Date(elem.util.toNorthAmericanFormat(elem.min, elem.format).dateForComparison);
21011
+ // Validate min date
21012
+ if (elem.min?.length === elem.lengthForType) {
21013
+ const minDate = new Date(toNorthAmericanFormat(elem.min, elem.format));
20046
21014
 
20047
- if (valueDate < minDate) {
20048
- elem.validity = 'rangeUnderflow';
20049
- elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
20050
- }
21015
+ if (valueDate < minDate) {
21016
+ elem.validity = 'rangeUnderflow';
21017
+ elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
21018
+ return;
20051
21019
  }
20052
21020
  }
20053
21021
  }
@@ -20166,7 +21134,7 @@ class AuroFormValidation {
20166
21134
  if (input.validationMessage.length > 0) {
20167
21135
  elem.errorMessage = input.validationMessage;
20168
21136
  }
20169
- } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
21137
+ } else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
20170
21138
  const firstInput = this.inputElements[0];
20171
21139
 
20172
21140
  if (firstInput.validationMessage.length > 0) {
@@ -20288,6 +21256,33 @@ class BaseInput extends r$2 {
20288
21256
  static get properties() {
20289
21257
  return {
20290
21258
 
21259
+ /**
21260
+ * The value for the role attribute.
21261
+ */
21262
+ a11yRole: {
21263
+ type: String,
21264
+ attribute: true,
21265
+ reflect: true
21266
+ },
21267
+
21268
+ /**
21269
+ * The value for the aria-expanded attribute.
21270
+ */
21271
+ a11yExpanded: {
21272
+ type: Boolean,
21273
+ attribute: true,
21274
+ reflect: true
21275
+ },
21276
+
21277
+ /**
21278
+ * The value for the aria-controls attribute.
21279
+ */
21280
+ a11yControls: {
21281
+ type: String,
21282
+ attribute: true,
21283
+ reflect: true
21284
+ },
21285
+
20291
21286
  /**
20292
21287
  * If set, the label will remain fixed in the active position.
20293
21288
  */
@@ -20929,6 +21924,10 @@ class BaseInput extends r$2 {
20929
21924
  } else if (this.type === 'number') {
20930
21925
  this.inputMode = 'numeric';
20931
21926
  }
21927
+
21928
+ if (this.type === "date" && !this.format) {
21929
+ this.format = 'mm/dd/yyyy';
21930
+ }
20932
21931
  }
20933
21932
 
20934
21933
  /**
@@ -22172,6 +23171,7 @@ var helpTextVersion = '1.0.0';
22172
23171
 
22173
23172
  // build the component class
22174
23173
  class AuroInput extends BaseInput {
23174
+
22175
23175
  constructor() {
22176
23176
  super();
22177
23177
 
@@ -22284,7 +23284,7 @@ class AuroInput extends BaseInput {
22284
23284
  ?required="${this.required}"
22285
23285
  ?disabled="${this.disabled}"
22286
23286
  aria-describedby="${this.uniqueId}"
22287
- aria-invalid="${this.validity !== 'valid'}"
23287
+ ?aria-invalid="${this.validity !== 'valid'}"
22288
23288
  placeholder=${this.getPlaceholder()}
22289
23289
  lang="${o(this.lang)}"
22290
23290
  ?activeLabel="${this.activeLabel}"
@@ -22293,7 +23293,10 @@ class AuroInput extends BaseInput {
22293
23293
  autocapitalize="${o(this.autocapitalize ? this.autocapitalize : undefined)}"
22294
23294
  autocomplete="${o(this.autocomplete ? this.autocomplete : undefined)}"
22295
23295
  part="input"
22296
- />
23296
+ role="${o(this.a11yRole)}"
23297
+ aria-expanded="${o(this.a11yExpanded)}"
23298
+ aria-controls="${o(this.a11yControls)}"
23299
+ />
22297
23300
  </div>
22298
23301
  <div
22299
23302
  class="notificationIcons"