@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.
- package/CHANGELOG.md +19 -1
- package/components/checkbox/README.md +1 -1
- package/components/checkbox/demo/api.min.js +468 -25
- package/components/checkbox/demo/index.min.js +468 -25
- package/components/checkbox/demo/readme.md +1 -1
- package/components/checkbox/dist/index.js +468 -25
- package/components/checkbox/dist/registered.js +468 -25
- package/components/combobox/README.md +1 -1
- package/components/combobox/demo/api.min.js +1125 -74
- package/components/combobox/demo/index.min.js +1125 -74
- package/components/combobox/demo/readme.md +1 -1
- package/components/combobox/dist/auro-combobox.d.ts +30 -0
- package/components/combobox/dist/index.js +1125 -74
- package/components/combobox/dist/registered.js +1125 -74
- package/components/counter/README.md +1 -1
- package/components/counter/demo/api.min.js +570 -45
- package/components/counter/demo/index.min.js +570 -45
- package/components/counter/demo/readme.md +1 -1
- package/components/counter/dist/index.js +570 -45
- package/components/counter/dist/registered.js +570 -45
- package/components/datepicker/README.md +1 -1
- package/components/datepicker/demo/api.min.js +1073 -70
- package/components/datepicker/demo/index.min.js +1073 -70
- package/components/datepicker/demo/readme.md +1 -1
- package/components/datepicker/dist/index.js +1073 -70
- package/components/datepicker/dist/registered.js +1073 -70
- package/components/dropdown/README.md +1 -1
- package/components/dropdown/demo/api.md +8 -5
- package/components/dropdown/demo/api.min.js +104 -22
- package/components/dropdown/demo/index.min.js +104 -22
- package/components/dropdown/demo/readme.md +1 -1
- package/components/dropdown/dist/auro-dropdown.d.ts +29 -0
- package/components/dropdown/dist/index.js +104 -22
- package/components/dropdown/dist/registered.js +104 -22
- package/components/form/README.md +1 -1
- package/components/form/demo/readme.md +1 -1
- package/components/input/README.md +1 -1
- package/components/input/demo/api.md +4 -1
- package/components/input/demo/api.min.js +503 -25
- package/components/input/demo/index.min.js +503 -25
- package/components/input/demo/readme.md +1 -1
- package/components/input/dist/base-input.d.ts +24 -0
- package/components/input/dist/index.js +503 -25
- package/components/input/dist/registered.js +503 -25
- package/components/menu/README.md +1 -1
- package/components/menu/demo/readme.md +1 -1
- package/components/radio/README.md +1 -1
- package/components/radio/demo/api.min.js +468 -25
- package/components/radio/demo/index.min.js +468 -25
- package/components/radio/demo/readme.md +1 -1
- package/components/radio/dist/index.js +468 -25
- package/components/radio/dist/registered.js +468 -25
- package/components/select/README.md +1 -1
- package/components/select/demo/api.min.js +570 -45
- package/components/select/demo/index.min.js +570 -45
- package/components/select/demo/readme.md +1 -1
- package/components/select/dist/index.js +570 -45
- package/components/select/dist/registered.js +570 -45
- package/package.json +2 -2
|
@@ -962,11 +962,420 @@ let AuroIcon$2 = class AuroIcon extends BaseIcon$2 {
|
|
|
962
962
|
|
|
963
963
|
var iconVersion$2 = '8.0.1';
|
|
964
964
|
|
|
965
|
+
class DateFormatter {
|
|
966
|
+
|
|
967
|
+
constructor() {
|
|
968
|
+
|
|
969
|
+
/**
|
|
970
|
+
* @description Parses a date string into its components.
|
|
971
|
+
* @param {string} dateStr - Date string to parse.
|
|
972
|
+
* @param {string} format - Date format to parse.
|
|
973
|
+
* @returns {Object<key["month" | "day" | "year"]: number>|undefined}
|
|
974
|
+
*/
|
|
975
|
+
this.parseDate = (dateStr, format = 'mm/dd/yyyy') => {
|
|
976
|
+
|
|
977
|
+
// Guard Clause: Date string is defined
|
|
978
|
+
if (!dateStr) {
|
|
979
|
+
return undefined;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// Assume the separator is a "/" a defined in our code base
|
|
983
|
+
const separator = '/';
|
|
984
|
+
|
|
985
|
+
// Get the parts of the date and format
|
|
986
|
+
const valueParts = dateStr.split(separator);
|
|
987
|
+
const formatParts = format.split(separator);
|
|
988
|
+
|
|
989
|
+
// Check if the value and format have the correct number of parts
|
|
990
|
+
if (valueParts.length !== formatParts.length) {
|
|
991
|
+
throw new Error('AuroDatepickerUtilities | parseDate: Date string and format length do not match');
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// Holds the result to be returned
|
|
995
|
+
const result = formatParts.reduce((acc, part, index) => {
|
|
996
|
+
const value = valueParts[index];
|
|
997
|
+
|
|
998
|
+
if ((/m/iu).test(part)) {
|
|
999
|
+
acc.month = value;
|
|
1000
|
+
} else if ((/d/iu).test(part)) {
|
|
1001
|
+
acc.day = value;
|
|
1002
|
+
} else if ((/y/iu).test(part)) {
|
|
1003
|
+
acc.year = value;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
return acc;
|
|
1007
|
+
}, {});
|
|
1008
|
+
|
|
1009
|
+
// If we found all the parts, return the result
|
|
1010
|
+
if (result.month && result.year) {
|
|
1011
|
+
return result;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// Throw an error to let the dev know we were unable to parse the date string
|
|
1015
|
+
throw new Error('AuroDatepickerUtilities | parseDate: Unable to parse date string');
|
|
1016
|
+
};
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* Convert a date object to string format.
|
|
1020
|
+
* @param {Object} date - Date to convert to string.
|
|
1021
|
+
* @returns {Object} Returns the date as a string.
|
|
1022
|
+
*/
|
|
1023
|
+
this.getDateAsString = (date) => date.toLocaleDateString(undefined, {
|
|
1024
|
+
year: "numeric",
|
|
1025
|
+
month: "2-digit",
|
|
1026
|
+
day: "2-digit",
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* Converts a date string to a North American date format.
|
|
1031
|
+
* @param {String} dateStr - Date to validate.
|
|
1032
|
+
* @param {String} format - Date format to validate against.
|
|
1033
|
+
* @returns {Boolean}
|
|
1034
|
+
*/
|
|
1035
|
+
this.toNorthAmericanFormat = (dateStr, format) => {
|
|
1036
|
+
|
|
1037
|
+
if (format === 'mm/dd/yyyy') {
|
|
1038
|
+
return dateStr;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
const parsedDate = this.parseDate(dateStr, format);
|
|
1042
|
+
|
|
1043
|
+
if (!parsedDate) {
|
|
1044
|
+
throw new Error('AuroDatepickerUtilities | toNorthAmericanFormat: Unable to parse date string');
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
const { month, day, year } = parsedDate;
|
|
1048
|
+
|
|
1049
|
+
const dateParts = [];
|
|
1050
|
+
if (month) {
|
|
1051
|
+
dateParts.push(month);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
if (day) {
|
|
1055
|
+
dateParts.push(day);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
if (year) {
|
|
1059
|
+
dateParts.push(year);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
return dateParts.join('/');
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
const dateFormatter = new DateFormatter();
|
|
1067
|
+
|
|
1068
|
+
// filepath: dateConstraints.mjs
|
|
1069
|
+
const DATE_UTIL_CONSTRAINTS = {
|
|
1070
|
+
maxDay: 31,
|
|
1071
|
+
maxMonth: 12,
|
|
1072
|
+
maxYear: 2400,
|
|
1073
|
+
minDay: 1,
|
|
1074
|
+
minMonth: 1,
|
|
1075
|
+
minYear: 1900,
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1078
|
+
class AuroDateUtilitiesBase {
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* @description The maximum day value allowed by the various utilities in this class.
|
|
1082
|
+
* @readonly
|
|
1083
|
+
* @type {Number}
|
|
1084
|
+
*/
|
|
1085
|
+
get maxDay() {
|
|
1086
|
+
return DATE_UTIL_CONSTRAINTS.maxDay;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* @description The maximum month value allowed by the various utilities in this class.
|
|
1091
|
+
* @readonly
|
|
1092
|
+
* @type {Number}
|
|
1093
|
+
*/
|
|
1094
|
+
get maxMonth() {
|
|
1095
|
+
return DATE_UTIL_CONSTRAINTS.maxMonth;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
/**
|
|
1099
|
+
* @description The maximum year value allowed by the various utilities in this class.
|
|
1100
|
+
* @readonly
|
|
1101
|
+
* @type {Number}
|
|
1102
|
+
*/
|
|
1103
|
+
get maxYear() {
|
|
1104
|
+
return DATE_UTIL_CONSTRAINTS.maxYear;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* @description The minimum day value allowed by the various utilities in this class.
|
|
1109
|
+
* @readonly
|
|
1110
|
+
* @type {Number}
|
|
1111
|
+
*/
|
|
1112
|
+
get minDay() {
|
|
1113
|
+
return DATE_UTIL_CONSTRAINTS.minDay;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* @description The minimum month value allowed by the various utilities in this class.
|
|
1118
|
+
* @readonly
|
|
1119
|
+
* @type {Number}
|
|
1120
|
+
*/
|
|
1121
|
+
get minMonth() {
|
|
1122
|
+
return DATE_UTIL_CONSTRAINTS.minMonth;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* @description The minimum year value allowed by the various utilities in this class.
|
|
1127
|
+
* @readonly
|
|
1128
|
+
* @type {Number}
|
|
1129
|
+
*/
|
|
1130
|
+
get minYear() {
|
|
1131
|
+
return DATE_UTIL_CONSTRAINTS.minYear;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/* eslint-disable no-magic-numbers */
|
|
1136
|
+
|
|
1137
|
+
class AuroDateUtilities extends AuroDateUtilitiesBase {
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* Returns the current century.
|
|
1141
|
+
* @returns {String} The current century.
|
|
1142
|
+
*/
|
|
1143
|
+
getCentury () {
|
|
1144
|
+
return String(new Date().getFullYear()).slice(0, 2);
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
/**
|
|
1148
|
+
* Returns a four digit year.
|
|
1149
|
+
* @param {String} year - The year to convert to four digits.
|
|
1150
|
+
* @returns {String} The four digit year.
|
|
1151
|
+
*/
|
|
1152
|
+
getFourDigitYear (year) {
|
|
1153
|
+
|
|
1154
|
+
const strYear = String(year).trim();
|
|
1155
|
+
return strYear.length <= 2 ? this.getCentury() + strYear : strYear;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
constructor() {
|
|
1159
|
+
|
|
1160
|
+
super();
|
|
1161
|
+
|
|
1162
|
+
/**
|
|
1163
|
+
* Compares two dates to see if they match.
|
|
1164
|
+
* @param {Object} date1 - First date to compare.
|
|
1165
|
+
* @param {Object} date2 - Second date to compare.
|
|
1166
|
+
* @returns {Boolean} Returns true if the dates match.
|
|
1167
|
+
*/
|
|
1168
|
+
this.datesMatch = (date1, date2) => new Date(date1).getTime() === new Date(date2).getTime();
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Returns true if value passed in is a valid date.
|
|
1172
|
+
* @param {String} date - Date to validate.
|
|
1173
|
+
* @param {String} format - Date format to validate against.
|
|
1174
|
+
* @returns {Boolean}
|
|
1175
|
+
*/
|
|
1176
|
+
this.validDateStr = (date, format) => {
|
|
1177
|
+
|
|
1178
|
+
// The length we expect the date string to be
|
|
1179
|
+
const dateStrLength = format.length;
|
|
1180
|
+
|
|
1181
|
+
// Guard Clause: Date and format are defined
|
|
1182
|
+
if (typeof date === "undefined" || typeof format === "undefined") {
|
|
1183
|
+
throw new Error('AuroDatepickerUtilities | validateDateStr: Date and format are required');
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// Guard Clause: Date should be of type string
|
|
1187
|
+
if (typeof date !== "string") {
|
|
1188
|
+
throw new Error('AuroDatepickerUtilities | validateDateStr: Date must be a string');
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
// Guard Clause: Format should be of type string
|
|
1192
|
+
if (typeof format !== "string") {
|
|
1193
|
+
throw new Error('AuroDatepickerUtilities | validateDateStr: Format must be a string');
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
// Guard Clause: Length is what we expect it to be
|
|
1197
|
+
if (date.length !== dateStrLength) {
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
// Get a formatted date string and parse it
|
|
1201
|
+
const dateParts = dateFormatter.parseDate(date, format);
|
|
1202
|
+
|
|
1203
|
+
// Guard Clause: Date parse succeeded
|
|
1204
|
+
if (!dateParts) {
|
|
1205
|
+
return false;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
// Create the expected date string based on the date parts
|
|
1209
|
+
const expectedDateStr = `${dateParts.month}/${dateParts.day || "01"}/${this.getFourDigitYear(dateParts.year)}`;
|
|
1210
|
+
|
|
1211
|
+
// Generate a date object that we will extract a string date from to compare to the passed in date string
|
|
1212
|
+
const dateObj = new Date(this.getFourDigitYear(dateParts.year), dateParts.month - 1, dateParts.day || 1);
|
|
1213
|
+
|
|
1214
|
+
// Get the date string of the date object we created from the string date
|
|
1215
|
+
const actualDateStr = dateFormatter.getDateAsString(dateObj);
|
|
1216
|
+
|
|
1217
|
+
// Guard Clause: Generated date matches date string input
|
|
1218
|
+
if (expectedDateStr !== actualDateStr) {
|
|
1219
|
+
return false;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
// If we passed all other checks, we can assume the date is valid
|
|
1223
|
+
return true;
|
|
1224
|
+
};
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* Determines if a string date value matches the format provided.
|
|
1228
|
+
* @param {string} value = The date string value.
|
|
1229
|
+
* @param { string} format = The date format to match against.
|
|
1230
|
+
* @returns {boolean}
|
|
1231
|
+
*/
|
|
1232
|
+
this.dateAndFormatMatch = (value, format) => {
|
|
1233
|
+
|
|
1234
|
+
// Ensure we have both values we need to do the comparison
|
|
1235
|
+
if (!value || !format) {
|
|
1236
|
+
throw new Error('AuroFormValidation | dateFormatMatch: value and format are required');
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
// If the lengths are different, they cannot match
|
|
1240
|
+
if (value.length !== format.length) {
|
|
1241
|
+
return false;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// Get the parts of the date
|
|
1245
|
+
const dateParts = dateFormatter.parseDate(value, format);
|
|
1246
|
+
|
|
1247
|
+
// Validator for day
|
|
1248
|
+
const dayValueIsValid = (day) => {
|
|
1249
|
+
|
|
1250
|
+
// Guard clause: if there is no day in the dateParts, we can ignore this check.
|
|
1251
|
+
if (!dateParts.day) {
|
|
1252
|
+
return true;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
// Guard clause: ensure day exists.
|
|
1256
|
+
if (!day) {
|
|
1257
|
+
return false;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
// Convert day to number
|
|
1261
|
+
const numDay = Number.parseInt(day, 10);
|
|
1262
|
+
|
|
1263
|
+
// Guard clause: ensure day is a valid integer
|
|
1264
|
+
if (Number.isNaN(numDay)) {
|
|
1265
|
+
throw new Error('AuroDatepickerUtilities | dayValueIsValid: Unable to parse day value integer');
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// Guard clause: ensure day is within the valid range
|
|
1269
|
+
if (numDay < this.minDay || numDay > this.maxDay) {
|
|
1270
|
+
return false;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
// Default return
|
|
1274
|
+
return true;
|
|
1275
|
+
};
|
|
1276
|
+
|
|
1277
|
+
// Validator for month
|
|
1278
|
+
const monthValueIsValid = (month) => {
|
|
1279
|
+
|
|
1280
|
+
// Guard clause: ensure month exists.
|
|
1281
|
+
if (!month) {
|
|
1282
|
+
return false;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
// Convert month to number
|
|
1286
|
+
const numMonth = Number.parseInt(month, 10);
|
|
1287
|
+
|
|
1288
|
+
// Guard clause: ensure month is a valid integer
|
|
1289
|
+
if (Number.isNaN(numMonth)) {
|
|
1290
|
+
throw new Error('AuroDatepickerUtilities | monthValueIsValid: Unable to parse month value integer');
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
// Guard clause: ensure month is within the valid range
|
|
1294
|
+
if (numMonth < this.minMonth || numMonth > this.maxMonth) {
|
|
1295
|
+
return false;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
// Default return
|
|
1299
|
+
return true;
|
|
1300
|
+
};
|
|
1301
|
+
|
|
1302
|
+
// Validator for year
|
|
1303
|
+
const yearIsValid = (_year) => {
|
|
1304
|
+
|
|
1305
|
+
// Guard clause: ensure year exists.
|
|
1306
|
+
if (!_year) {
|
|
1307
|
+
return false;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
// Get the full year
|
|
1311
|
+
const year = this.getFourDigitYear(_year);
|
|
1312
|
+
|
|
1313
|
+
// Convert year to number
|
|
1314
|
+
const numYear = Number.parseInt(year, 10);
|
|
1315
|
+
|
|
1316
|
+
// Guard clause: ensure year is a valid integer
|
|
1317
|
+
if (Number.isNaN(numYear)) {
|
|
1318
|
+
throw new Error('AuroDatepickerUtilities | yearValueIsValid: Unable to parse year value integer');
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// Guard clause: ensure year is within the valid range
|
|
1322
|
+
if (numYear < this.minYear || numYear > this.maxYear) {
|
|
1323
|
+
return false;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
// Default return
|
|
1327
|
+
return true;
|
|
1328
|
+
};
|
|
1329
|
+
|
|
1330
|
+
// Self-contained checks for month, day, and year
|
|
1331
|
+
const checks = [
|
|
1332
|
+
monthValueIsValid(dateParts.month),
|
|
1333
|
+
dayValueIsValid(dateParts.day),
|
|
1334
|
+
yearIsValid(dateParts.year)
|
|
1335
|
+
];
|
|
1336
|
+
|
|
1337
|
+
// If any of the checks failed, the date format does not match and the result is invalid
|
|
1338
|
+
const isValid = checks.every((check) => check === true);
|
|
1339
|
+
|
|
1340
|
+
// If the check is invalid, return false
|
|
1341
|
+
if (!isValid) {
|
|
1342
|
+
return false;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
// Default case
|
|
1346
|
+
return true;
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
// Export a class instance
|
|
1352
|
+
const dateUtilities = new AuroDateUtilities();
|
|
1353
|
+
|
|
1354
|
+
// Export the class instance methods individually
|
|
1355
|
+
const {
|
|
1356
|
+
datesMatch,
|
|
1357
|
+
validDateStr,
|
|
1358
|
+
dateAndFormatMatch,
|
|
1359
|
+
minDay,
|
|
1360
|
+
minMonth,
|
|
1361
|
+
minYear,
|
|
1362
|
+
maxDay,
|
|
1363
|
+
maxMonth,
|
|
1364
|
+
maxYear
|
|
1365
|
+
} = dateUtilities;
|
|
1366
|
+
|
|
1367
|
+
const {
|
|
1368
|
+
toNorthAmericanFormat,
|
|
1369
|
+
parseDate,
|
|
1370
|
+
getDateAsString
|
|
1371
|
+
} = dateFormatter;
|
|
1372
|
+
|
|
965
1373
|
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
966
1374
|
// See LICENSE in the project root for license information.
|
|
967
1375
|
|
|
968
1376
|
|
|
969
1377
|
class AuroFormValidation {
|
|
1378
|
+
|
|
970
1379
|
constructor() {
|
|
971
1380
|
this.runtimeUtils = new AuroLibraryRuntimeUtils$3();
|
|
972
1381
|
}
|
|
@@ -1058,17 +1467,17 @@ class AuroFormValidation {
|
|
|
1058
1467
|
]
|
|
1059
1468
|
}
|
|
1060
1469
|
};
|
|
1061
|
-
|
|
1470
|
+
|
|
1062
1471
|
let elementType;
|
|
1063
1472
|
if (this.runtimeUtils.elementMatch(elem, 'auro-input')) {
|
|
1064
1473
|
elementType = 'input';
|
|
1065
1474
|
} else if (this.runtimeUtils.elementMatch(elem, 'auro-counter') || this.runtimeUtils.elementMatch(elem, 'auro-counter-group')) {
|
|
1066
1475
|
elementType = 'counter';
|
|
1067
1476
|
}
|
|
1068
|
-
|
|
1477
|
+
|
|
1069
1478
|
if (elementType) {
|
|
1070
1479
|
const rules = validationRules[elementType];
|
|
1071
|
-
|
|
1480
|
+
|
|
1072
1481
|
if (rules) {
|
|
1073
1482
|
Object.values(rules).flat().forEach(rule => {
|
|
1074
1483
|
if (rule.check(elem)) {
|
|
@@ -1094,48 +1503,82 @@ class AuroFormValidation {
|
|
|
1094
1503
|
if (!elem.value.match(emailRegex)) {
|
|
1095
1504
|
elem.validity = 'patternMismatch';
|
|
1096
1505
|
elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
|
|
1506
|
+
return;
|
|
1097
1507
|
}
|
|
1098
1508
|
} else if (elem.type === 'credit-card') {
|
|
1099
1509
|
if (elem.value.length > 0 && elem.value.length < elem.validationCCLength) {
|
|
1100
1510
|
elem.validity = 'tooShort';
|
|
1101
1511
|
elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
|
|
1512
|
+
return;
|
|
1102
1513
|
}
|
|
1103
1514
|
} else if (elem.type === 'number') {
|
|
1104
1515
|
if (elem.max !== undefined && Number(elem.max) < Number(elem.value)) {
|
|
1105
1516
|
elem.validity = 'rangeOverflow';
|
|
1106
1517
|
elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
|
|
1518
|
+
return;
|
|
1107
1519
|
}
|
|
1108
1520
|
|
|
1109
1521
|
if (elem.min !== undefined && elem.value?.length > 0 && Number(elem.min) > Number(elem.value)) {
|
|
1110
1522
|
elem.validity = 'rangeUnderflow';
|
|
1111
1523
|
elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
|
|
1524
|
+
return;
|
|
1112
1525
|
}
|
|
1113
|
-
} else if (elem.type === 'date') {
|
|
1114
|
-
|
|
1526
|
+
} else if (elem.type === 'date' && elem.value?.length > 0) {
|
|
1527
|
+
|
|
1528
|
+
// Guard Clause: if the value is too short
|
|
1529
|
+
if (elem.value.length < elem.lengthForType) {
|
|
1530
|
+
|
|
1115
1531
|
elem.validity = 'tooShort';
|
|
1116
1532
|
elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
// Guard Clause: If the value is too long for the type
|
|
1537
|
+
if (elem.value?.length > elem.lengthForType) {
|
|
1120
1538
|
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1539
|
+
elem.validity = 'tooLong';
|
|
1540
|
+
elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || '';
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
// Validate that the date passed was the correct format
|
|
1545
|
+
if (!dateAndFormatMatch(elem.value, elem.format)) {
|
|
1546
|
+
elem.validity = 'patternMismatch';
|
|
1547
|
+
elem.errorMessage = elem.setCustomValidityForType || elem.setCustomValidity || 'Invalid Date Format Entered';
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
// Validate that the date passed was a valid date
|
|
1552
|
+
if (!validDateStr(elem.value, elem.format)) {
|
|
1553
|
+
elem.validity = 'invalidDate';
|
|
1554
|
+
elem.errorMessage = elem.setCustomValidityInvalidDate || elem.setCustomValidity || 'Invalid Date Entered';
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1124
1557
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1558
|
+
// Perform the rest of the validation
|
|
1559
|
+
const formattedValue = toNorthAmericanFormat(elem.value, elem.format);
|
|
1560
|
+
const valueDate = new Date(formattedValue);
|
|
1561
|
+
|
|
1562
|
+
// // Validate max date
|
|
1563
|
+
if (elem.max?.length === elem.lengthForType) {
|
|
1564
|
+
|
|
1565
|
+
const maxDate = new Date(toNorthAmericanFormat(elem.max, elem.format));
|
|
1566
|
+
|
|
1567
|
+
if (valueDate > maxDate) {
|
|
1568
|
+
elem.validity = 'rangeOverflow';
|
|
1569
|
+
elem.errorMessage = elem.setCustomValidityRangeOverflow || elem.setCustomValidity || '';
|
|
1570
|
+
return;
|
|
1129
1571
|
}
|
|
1572
|
+
}
|
|
1130
1573
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1574
|
+
// Validate min date
|
|
1575
|
+
if (elem.min?.length === elem.lengthForType) {
|
|
1576
|
+
const minDate = new Date(toNorthAmericanFormat(elem.min, elem.format));
|
|
1134
1577
|
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1578
|
+
if (valueDate < minDate) {
|
|
1579
|
+
elem.validity = 'rangeUnderflow';
|
|
1580
|
+
elem.errorMessage = elem.setCustomValidityRangeUnderflow || elem.setCustomValidity || '';
|
|
1581
|
+
return;
|
|
1139
1582
|
}
|
|
1140
1583
|
}
|
|
1141
1584
|
}
|
|
@@ -1254,7 +1697,7 @@ class AuroFormValidation {
|
|
|
1254
1697
|
if (input.validationMessage.length > 0) {
|
|
1255
1698
|
elem.errorMessage = input.validationMessage;
|
|
1256
1699
|
}
|
|
1257
|
-
} else if (this.inputElements?.length > 0
|
|
1700
|
+
} else if (this.inputElements?.length > 0 && elem.errorMessage === '') {
|
|
1258
1701
|
const firstInput = this.inputElements[0];
|
|
1259
1702
|
|
|
1260
1703
|
if (firstInput.validationMessage.length > 0) {
|
|
@@ -3482,7 +3925,7 @@ class AuroFloatingUI {
|
|
|
3482
3925
|
/**
|
|
3483
3926
|
* @private
|
|
3484
3927
|
* getting called on 'blur' in trigger or `focusin` in document
|
|
3485
|
-
*
|
|
3928
|
+
*
|
|
3486
3929
|
* Hides the bib if focus moves outside of the trigger or bib, unless a 'noHideOnThisFocusLoss' flag is set.
|
|
3487
3930
|
* This method checks if the currently active element is still within the trigger or bib.
|
|
3488
3931
|
* If not, and if the bib isn't in fullscreen mode with focus lost, it hides the bib.
|
|
@@ -3598,7 +4041,7 @@ class AuroFloatingUI {
|
|
|
3598
4041
|
// Close any other dropdown that is already open
|
|
3599
4042
|
const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
|
|
3600
4043
|
if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this &&
|
|
3601
|
-
existedVisibleFloatingUI.isPopoverVisible &&
|
|
4044
|
+
existedVisibleFloatingUI.element.isPopoverVisible &&
|
|
3602
4045
|
document.expandedAuroFloater.eventPrefix === this.eventPrefix) {
|
|
3603
4046
|
document.expandedAuroFloater.hideBib();
|
|
3604
4047
|
}
|
|
@@ -3774,7 +4217,7 @@ class AuroFloatingUI {
|
|
|
3774
4217
|
this.id = window.crypto.randomUUID();
|
|
3775
4218
|
this.element.setAttribute('id', this.id);
|
|
3776
4219
|
}
|
|
3777
|
-
|
|
4220
|
+
|
|
3778
4221
|
this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
|
|
3779
4222
|
}
|
|
3780
4223
|
|
|
@@ -3827,7 +4270,7 @@ class AuroFloatingUI {
|
|
|
3827
4270
|
if (this.element.bib) {
|
|
3828
4271
|
this.element.shadowRoot.append(this.element.bib);
|
|
3829
4272
|
}
|
|
3830
|
-
|
|
4273
|
+
|
|
3831
4274
|
// Remove event & keyboard listeners
|
|
3832
4275
|
if (this.element?.trigger) {
|
|
3833
4276
|
this.element.trigger.removeEventListener('keydown', this.handleEvent);
|
|
@@ -4558,6 +5001,7 @@ var helpTextVersion = '1.0.0';
|
|
|
4558
5001
|
* @csspart helpText - The helpText content container.
|
|
4559
5002
|
* @event auroDropdown-triggerClick - Notifies that the trigger has been clicked.
|
|
4560
5003
|
* @event auroDropdown-toggled - Notifies that the visibility of the dropdown bib has changed.
|
|
5004
|
+
* @event auroDropdown-idAdded - Notifies consumers that the unique ID for the dropdown bib has been generated.
|
|
4561
5005
|
*/
|
|
4562
5006
|
class AuroDropdown extends r {
|
|
4563
5007
|
constructor() {
|
|
@@ -4603,7 +5047,9 @@ class AuroDropdown extends r {
|
|
|
4603
5047
|
this.rounded = false;
|
|
4604
5048
|
this.tabIndex = 0;
|
|
4605
5049
|
this.noToggle = false;
|
|
5050
|
+
this.a11yAutocomplete = 'none';
|
|
4606
5051
|
this.labeled = true;
|
|
5052
|
+
this.a11yRole = 'combobox';
|
|
4607
5053
|
this.onDark = false;
|
|
4608
5054
|
|
|
4609
5055
|
// floaterConfig
|
|
@@ -4739,6 +5185,16 @@ class AuroDropdown extends r {
|
|
|
4739
5185
|
type: Number
|
|
4740
5186
|
},
|
|
4741
5187
|
|
|
5188
|
+
/**
|
|
5189
|
+
* The unique ID for the dropdown bib element.
|
|
5190
|
+
* @private
|
|
5191
|
+
*/
|
|
5192
|
+
dropdownId: {
|
|
5193
|
+
type: String,
|
|
5194
|
+
reflect: false,
|
|
5195
|
+
attribute: false
|
|
5196
|
+
},
|
|
5197
|
+
|
|
4742
5198
|
/**
|
|
4743
5199
|
* If declared in combination with `bordered` property or `helpText` slot content, will apply red color to both.
|
|
4744
5200
|
*/
|
|
@@ -4906,6 +5362,23 @@ class AuroDropdown extends r {
|
|
|
4906
5362
|
*/
|
|
4907
5363
|
tabIndex: {
|
|
4908
5364
|
type: Number
|
|
5365
|
+
},
|
|
5366
|
+
|
|
5367
|
+
/**
|
|
5368
|
+
* The value for the role attribute of the trigger element.
|
|
5369
|
+
*/
|
|
5370
|
+
a11yRole: {
|
|
5371
|
+
type: String || undefined,
|
|
5372
|
+
attribute: false,
|
|
5373
|
+
reflect: false
|
|
5374
|
+
},
|
|
5375
|
+
|
|
5376
|
+
/**
|
|
5377
|
+
* The value for the aria-autocomplete attribute of the trigger element.
|
|
5378
|
+
*/
|
|
5379
|
+
a11yAutocomplete: {
|
|
5380
|
+
type: String,
|
|
5381
|
+
attribute: false,
|
|
4909
5382
|
}
|
|
4910
5383
|
};
|
|
4911
5384
|
}
|
|
@@ -4967,7 +5440,22 @@ class AuroDropdown extends r {
|
|
|
4967
5440
|
}
|
|
4968
5441
|
|
|
4969
5442
|
firstUpdated() {
|
|
5443
|
+
|
|
5444
|
+
// Configure the floater to, this will generate the ID for the bib
|
|
4970
5445
|
this.floater.configure(this, 'auroDropdown');
|
|
5446
|
+
|
|
5447
|
+
/**
|
|
5448
|
+
* @description Let subscribers know that the dropdown ID ha been generated and added.
|
|
5449
|
+
* @event auroDropdown-idAdded
|
|
5450
|
+
* @type {Object<key: 'id', value: string>} - The ID of the dropdown bib element.
|
|
5451
|
+
*/
|
|
5452
|
+
this.dispatchEvent(new CustomEvent('auroDropdown-idAdded', {detail: {id: this.floater.element.id}}));
|
|
5453
|
+
|
|
5454
|
+
// Set the bib ID locally if the user hasn't provided a focusable trigger
|
|
5455
|
+
if (!this.triggerContentFocusable) {
|
|
5456
|
+
this.dropdownId = this.floater.element.id;
|
|
5457
|
+
}
|
|
5458
|
+
|
|
4971
5459
|
this.bibContent = this.floater.element.bib;
|
|
4972
5460
|
|
|
4973
5461
|
// Add the tag name as an attribute if it is different than the component name
|
|
@@ -5119,6 +5607,30 @@ class AuroDropdown extends r {
|
|
|
5119
5607
|
});
|
|
5120
5608
|
}
|
|
5121
5609
|
|
|
5610
|
+
/*
|
|
5611
|
+
* Sets aria attributes for the trigger element if a custom one is passed in.
|
|
5612
|
+
* @private
|
|
5613
|
+
* @method setTriggerAriaAttributes
|
|
5614
|
+
* @param { HTMLElement } triggerElement - The custom trigger element.
|
|
5615
|
+
*/
|
|
5616
|
+
clearTriggerA11yAttributes(triggerElement) {
|
|
5617
|
+
|
|
5618
|
+
if (!triggerElement || !triggerElement.removeAttribute) {
|
|
5619
|
+
return;
|
|
5620
|
+
}
|
|
5621
|
+
|
|
5622
|
+
// Reset appropriate attributes for a11y
|
|
5623
|
+
triggerElement.removeAttribute('aria-labelledby');
|
|
5624
|
+
if (triggerElement.getAttribute('id') === `${this.id}-trigger-element`) {
|
|
5625
|
+
triggerElement.removeAttribute('id');
|
|
5626
|
+
}
|
|
5627
|
+
triggerElement.removeAttribute('role');
|
|
5628
|
+
triggerElement.removeAttribute('aria-expanded');
|
|
5629
|
+
|
|
5630
|
+
triggerElement.removeAttribute('aria-controls');
|
|
5631
|
+
triggerElement.removeAttribute('aria-autocomplete');
|
|
5632
|
+
}
|
|
5633
|
+
|
|
5122
5634
|
/**
|
|
5123
5635
|
* Handles changes to the trigger content slot and updates related properties.
|
|
5124
5636
|
*
|
|
@@ -5132,32 +5644,41 @@ class AuroDropdown extends r {
|
|
|
5132
5644
|
* @returns {void}
|
|
5133
5645
|
*/
|
|
5134
5646
|
handleTriggerContentSlotChange(event) {
|
|
5647
|
+
|
|
5135
5648
|
this.floater.handleTriggerTabIndex();
|
|
5136
5649
|
|
|
5650
|
+
// Get the trigger
|
|
5651
|
+
const trigger = this.shadowRoot.querySelector('#trigger');
|
|
5652
|
+
|
|
5653
|
+
// Get the trigger slot
|
|
5137
5654
|
const triggerSlot = this.shadowRoot.querySelector('.triggerContent slot');
|
|
5138
5655
|
|
|
5656
|
+
// If there's a trigger slot
|
|
5139
5657
|
if (triggerSlot) {
|
|
5140
5658
|
|
|
5659
|
+
// Get the content nodes to see if there are any children
|
|
5141
5660
|
const triggerContentNodes = triggerSlot.assignedNodes();
|
|
5142
5661
|
|
|
5662
|
+
// If there are children
|
|
5143
5663
|
if (triggerContentNodes) {
|
|
5144
5664
|
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
this.triggerContentFocusable = this.containsFocusableElement(node);
|
|
5148
|
-
}
|
|
5149
|
-
});
|
|
5150
|
-
}
|
|
5151
|
-
}
|
|
5665
|
+
// See if any of them are focusable elemeents
|
|
5666
|
+
this.triggerContentFocusable = triggerContentNodes.some((node) => this.containsFocusableElement(node));
|
|
5152
5667
|
|
|
5153
|
-
|
|
5668
|
+
// If any of them are focusable elements
|
|
5669
|
+
if (this.triggerContentFocusable) {
|
|
5154
5670
|
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5671
|
+
// Assume the consumer will be providing their own a11y in whatever they passed in
|
|
5672
|
+
this.clearTriggerA11yAttributes(trigger);
|
|
5673
|
+
|
|
5674
|
+
// Remove the tabindex from the trigger so it doesn't interrupt focus flow
|
|
5675
|
+
trigger.removeAttribute('tabindex');
|
|
5676
|
+
} else {
|
|
5677
|
+
|
|
5678
|
+
// Add the tabindex to the trigger so that it's in the focus flow
|
|
5679
|
+
trigger.setAttribute('tabindex', '0');
|
|
5680
|
+
}
|
|
5681
|
+
}
|
|
5161
5682
|
}
|
|
5162
5683
|
|
|
5163
5684
|
if (event) {
|
|
@@ -5167,6 +5688,7 @@ class AuroDropdown extends r {
|
|
|
5167
5688
|
|
|
5168
5689
|
if (this.triggerContentSlot) {
|
|
5169
5690
|
this.setupTriggerFocusEventBinding();
|
|
5691
|
+
|
|
5170
5692
|
this.hasTriggerContent = this.triggerContentSlot.some((slot) => {
|
|
5171
5693
|
if (slot.textContent.trim()) {
|
|
5172
5694
|
return true;
|
|
@@ -5234,10 +5756,13 @@ class AuroDropdown extends r {
|
|
|
5234
5756
|
id="trigger"
|
|
5235
5757
|
class="trigger"
|
|
5236
5758
|
part="trigger"
|
|
5237
|
-
aria-labelledby="triggerLabel"
|
|
5238
5759
|
tabindex="${this.tabIndex}"
|
|
5239
5760
|
?showBorder="${this.showTriggerBorders}"
|
|
5240
|
-
|
|
5761
|
+
role="${o(this.triggerContentFocusable ? undefined : this.a11yRole)}"
|
|
5762
|
+
aria-expanded="${o(this.triggerContentFocusable ? undefined : this.isPopoverVisible)}"
|
|
5763
|
+
aria-controls="${o(this.triggerContentFocusable ? undefined : this.dropdownId)}"
|
|
5764
|
+
aria-labelledby="${o(this.triggerContentFocusable ? undefined : 'triggerLabel')}"
|
|
5765
|
+
>
|
|
5241
5766
|
<div class="triggerContentWrapper">
|
|
5242
5767
|
<label class="label" id="triggerLabel" hasTrigger=${this.hasTriggerContent}>
|
|
5243
5768
|
<slot name="label" @slotchange="${this.handleLabelSlotChange}"></slot>
|
|
@@ -5271,12 +5796,12 @@ class AuroDropdown extends r {
|
|
|
5271
5796
|
<div id="bibSizer" part="size"></div>
|
|
5272
5797
|
<${this.dropdownBibTag}
|
|
5273
5798
|
id="bib"
|
|
5274
|
-
role="tooltip"
|
|
5275
5799
|
?data-show="${this.isPopoverVisible}"
|
|
5276
5800
|
?isfullscreen="${this.isBibFullscreen}"
|
|
5277
5801
|
?common="${this.common}"
|
|
5278
5802
|
?rounded="${this.common || this.rounded}"
|
|
5279
|
-
?inset="${this.common || this.inset}"
|
|
5803
|
+
?inset="${this.common || this.inset}"
|
|
5804
|
+
>
|
|
5280
5805
|
</${this.dropdownBibTag}>
|
|
5281
5806
|
</div>
|
|
5282
5807
|
`;
|