@aurodesignsystem-dev/auro-formkit 0.0.0-pr1395.0 → 0.0.0-pr1395.2

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 (44) hide show
  1. package/components/checkbox/demo/api.min.js +1 -1
  2. package/components/checkbox/demo/index.min.js +1 -1
  3. package/components/checkbox/dist/index.js +1 -1
  4. package/components/checkbox/dist/registered.js +1 -1
  5. package/components/combobox/demo/api.min.js +151 -40
  6. package/components/combobox/demo/index.min.js +151 -40
  7. package/components/combobox/dist/index.js +3 -3
  8. package/components/combobox/dist/registered.js +3 -3
  9. package/components/counter/demo/api.min.js +2 -2
  10. package/components/counter/demo/index.min.js +2 -2
  11. package/components/counter/dist/index.js +2 -2
  12. package/components/counter/dist/registered.js +2 -2
  13. package/components/datepicker/demo/api.min.js +74 -13
  14. package/components/datepicker/demo/index.min.js +74 -13
  15. package/components/datepicker/dist/datepickerKeyboardStrategy.d.ts +4 -0
  16. package/components/datepicker/dist/index.js +74 -13
  17. package/components/datepicker/dist/registered.js +74 -13
  18. package/components/dropdown/demo/api.min.js +1 -1
  19. package/components/dropdown/demo/index.min.js +1 -1
  20. package/components/dropdown/dist/index.js +1 -1
  21. package/components/dropdown/dist/registered.js +1 -1
  22. package/components/form/demo/api.min.js +240 -63
  23. package/components/form/demo/index.min.js +240 -63
  24. package/components/input/demo/api.min.js +1 -1
  25. package/components/input/demo/index.min.js +1 -1
  26. package/components/input/dist/index.js +1 -1
  27. package/components/input/dist/registered.js +1 -1
  28. package/components/menu/demo/api.md +1 -1
  29. package/components/menu/demo/api.min.js +148 -37
  30. package/components/menu/demo/index.min.js +148 -37
  31. package/components/menu/dist/auro-menu.context.d.ts +15 -3
  32. package/components/menu/dist/auro-menu.d.ts +1 -1
  33. package/components/menu/dist/index.js +148 -37
  34. package/components/menu/dist/registered.js +148 -37
  35. package/components/radio/demo/api.min.js +1 -1
  36. package/components/radio/demo/index.min.js +1 -1
  37. package/components/radio/dist/index.js +1 -1
  38. package/components/radio/dist/registered.js +1 -1
  39. package/components/select/demo/api.min.js +158 -42
  40. package/components/select/demo/index.min.js +158 -42
  41. package/components/select/dist/index.js +10 -5
  42. package/components/select/dist/registered.js +10 -5
  43. package/custom-elements.json +1514 -1429
  44. package/package.json +11 -4
@@ -479,10 +479,20 @@ class AuroMenuOption extends AuroElement {
479
479
  subscribe: true
480
480
  });
481
481
 
482
- // Establish the key property as early as possible
482
+ // Establish the key property as early as possible.
483
+ // When a framework (e.g. Svelte) inserts the element into the DOM before
484
+ // setting its `value` property, both `getAttribute('value')` and
485
+ // `getAttribute('key')` return null here. Setting `this.key = null`
486
+ // would block the fallback in `updated()` that assigns key from the
487
+ // value property (the guard checked `=== undefined`). Only assign key
488
+ // if at least one source attribute is actually present so that the
489
+ // `updated()` fallback can run when the value property arrives later.
483
490
  const valueAttr = this.getAttribute('value');
484
491
  const keyAttr = this.getAttribute('key');
485
- this.key = keyAttr !== null ? keyAttr : valueAttr;
492
+ const resolvedKey = keyAttr !== null ? keyAttr : valueAttr;
493
+ if (resolvedKey !== null) {
494
+ this.key = resolvedKey;
495
+ }
486
496
  }
487
497
 
488
498
  firstUpdated() {
@@ -532,8 +542,14 @@ class AuroMenuOption extends AuroElement {
532
542
  this.updateTextHighlight();
533
543
  }
534
544
 
535
- // Set the key to be the passed value if no key is provided
536
- if (changedProperties.has('value') && this.key === undefined) {
545
+ // Set the key to be the passed value if no key is provided.
546
+ // Loose equality (== null) is intentional: it catches both null AND
547
+ // undefined. When a framework (e.g. Svelte, React) inserts the element
548
+ // before setting its value property, connectedCallback skips key
549
+ // assignment because both attributes are null at that point. The Lit
550
+ // property default for `key` is undefined (not null), so strict
551
+ // === null would miss the case and the fallback would never run.
552
+ if (changedProperties.has('value') && this.key == null) { // eslint-disable-line eqeqeq, no-eq-null
537
553
  this.key = this.value;
538
554
  }
539
555
  }
@@ -902,6 +918,9 @@ class MenuService {
902
918
  this._subscribers = [];
903
919
  this.internalUpdateInProgress = false;
904
920
  this.selectedOptions = [];
921
+ this._pendingValue = null;
922
+ this._pendingRetryScheduled = false;
923
+ this._pendingRetryCount = 0;
905
924
  }
906
925
 
907
926
  /**
@@ -941,6 +960,9 @@ class MenuService {
941
960
  hostDisconnected() {
942
961
  this._subscribers = [];
943
962
  this._menuOptions = [];
963
+ this._pendingValue = null;
964
+ this._pendingRetryScheduled = false;
965
+ this._pendingRetryCount = 0;
944
966
  }
945
967
 
946
968
  /**
@@ -1143,17 +1165,22 @@ class MenuService {
1143
1165
  * @param {string|number|Array<string|number>} value - The value(s) to select.
1144
1166
  */
1145
1167
  selectByValue(value) {
1146
- // Early exit for invalid/empty values or internal updates
1147
- if (this.internalUpdateInProgress ||
1148
- this.host.internalUpdateInProgress ||
1149
- value === undefined ||
1168
+ const isEmptyValue = value === undefined ||
1150
1169
  value === null ||
1151
1170
  (Array.isArray(value) && value.length === 0) ||
1152
- (typeof value === 'string' && value.trim() === '')) {
1171
+ (typeof value === 'string' && value.trim() === '');
1172
+
1173
+ // Early exit for invalid/empty values
1174
+ if (isEmptyValue) {
1153
1175
  return;
1154
1176
  }
1155
1177
 
1156
- this.reset();
1178
+ // If an internal update cycle is still in progress, defer value application
1179
+ // rather than dropping it.
1180
+ if (this.internalUpdateInProgress || this.host.internalUpdateInProgress) {
1181
+ this.queuePendingValue(value);
1182
+ return;
1183
+ }
1157
1184
 
1158
1185
  // Normalize values to array of strings
1159
1186
  const normalizedValues = this._getNormalizedValues(value);
@@ -1165,33 +1192,100 @@ class MenuService {
1165
1192
  validatedValues = [normalizedValues[0]];
1166
1193
  }
1167
1194
 
1195
+ if (this._menuOptions.length === 0) {
1196
+ this.queuePendingValue(value);
1197
+ return;
1198
+ }
1199
+
1168
1200
  // Find matching options by comparing available options to validated values
1169
1201
  const trackedKeys = new Set();
1170
1202
  const optionsToSelect = this._menuOptions.filter(option => {
1171
1203
  const passesFilter = validatedValues.includes(option.key);
1172
1204
  const alreadyTracked = trackedKeys.has(option.key);
1205
+ const isActive = option.isActive;
1173
1206
 
1174
1207
  trackedKeys.add(option.key);
1175
1208
 
1176
1209
  // Include the option in the options to be selected if it passes the filter check and
1177
1210
  // either hasn't been tracked yet or selectAllMatchingOptions is true
1178
- return passesFilter && (!alreadyTracked || (alreadyTracked && this.selectAllMatchingOptions));
1211
+ return isActive && passesFilter && (!alreadyTracked || (alreadyTracked && this.selectAllMatchingOptions));
1179
1212
  });
1180
1213
 
1181
- // Handle selection result
1182
- if (optionsToSelect.length && !this.optionsArraysMatch(optionsToSelect, this.selectedOptions)) {
1183
- this.selectOptions(optionsToSelect);
1184
- } else {
1185
- this.stageUpdate();
1214
+ // Handle no matches: clear existing selection, but do not dispatch an intermediate
1215
+ // undefined value that can overwrite the host value in parent components.
1216
+ if (!optionsToSelect.length) {
1217
+ const hasUnresolvedKeys = this._menuOptions.some((option) => option.isActive && option.key == null);
1218
+
1219
+ if (hasUnresolvedKeys) {
1220
+ this.queuePendingValue(value);
1221
+ return;
1222
+ }
1223
+
1224
+ this.clearPendingValue();
1225
+
1226
+ if (this.selectedOptions.length > 0) {
1227
+ this.selectedOptions = [];
1228
+ }
1229
+
1230
+ // Always notify so the host resets any stale invalid value, even when
1231
+ // selectedOptions was already empty (e.g. double-clicking set-invalid).
1232
+ this.stageUpdate({ reason: 'no-match' });
1233
+
1234
+ // Dispatch failure event if no matches found
1235
+ if (validatedValues.length) {
1236
+ this.dispatchChangeEvent('auroMenu-selectValueFailure', {
1237
+ message: 'No matching options found for the provided value(s).',
1238
+ values: validatedValues
1239
+ });
1240
+ }
1241
+
1242
+ return;
1186
1243
  }
1187
1244
 
1188
- // Dispatch failure event if no matches found
1189
- if (!optionsToSelect.length && validatedValues.length) {
1190
- this.dispatchChangeEvent('auroMenu-selectValueFailure', {
1191
- message: 'No matching options found for the provided value(s).',
1192
- values: validatedValues
1193
- });
1245
+ this.clearPendingValue();
1246
+
1247
+ if (this.optionsArraysMatch(optionsToSelect, this.selectedOptions)) {
1248
+ return;
1249
+ }
1250
+
1251
+ // Apply programmatic selection as a single transaction and emit one final state.
1252
+ this.selectedOptions = optionsToSelect;
1253
+ this.stageUpdate();
1254
+ }
1255
+
1256
+ /**
1257
+ * Queues a pending value and schedules a bounded retry.
1258
+ * @param {string|number|Array<string|number>} value - The value to retry.
1259
+ */
1260
+ queuePendingValue(value) {
1261
+ this._pendingValue = value;
1262
+
1263
+ if (this._pendingRetryScheduled || this._pendingRetryCount >= 5) {
1264
+ return;
1194
1265
  }
1266
+
1267
+ this._pendingRetryScheduled = true;
1268
+ this._pendingRetryCount += 1;
1269
+
1270
+ setTimeout(() => {
1271
+ this._pendingRetryScheduled = false;
1272
+
1273
+ if (this._pendingValue == null) {
1274
+ return;
1275
+ }
1276
+
1277
+ const pendingValue = this._pendingValue;
1278
+ this.selectByValue(pendingValue);
1279
+ }, 0);
1280
+ }
1281
+
1282
+ /**
1283
+ * Clears pending retry state.
1284
+ */
1285
+ clearPendingValue() {
1286
+ this._pendingValue = null;
1287
+ this._pendingRetryScheduled = false;
1288
+ this._pendingRetryCount = 0;
1195
1289
  }
1196
1290
 
1197
1291
  /**
@@ -1230,9 +1324,9 @@ class MenuService {
1230
1324
  /**
1231
1325
  * Stages an update to notify subscribers of state and value changes.
1232
1326
  */
1233
- stageUpdate() {
1234
- this.notifyStateChange();
1235
- this.notifyValueChange();
1327
+ stageUpdate(meta = {}) {
1328
+ this.notifyStateChange(meta);
1329
+ this.notifyValueChange(meta);
1236
1330
  }
1237
1331
 
1238
1332
  /**
@@ -1247,14 +1341,18 @@ class MenuService {
1247
1341
  /**
1248
1342
  * Notifies subscribers of a state change (selected options has changed).
1249
1343
  */
1250
- notifyStateChange() {
1251
- this.notify({ type: 'stateChange', selectedOptions: this.selectedOptions });
1344
+ notifyStateChange(meta = {}) {
1345
+ this.notify({
1346
+ type: 'stateChange',
1347
+ selectedOptions: this.selectedOptions,
1348
+ ...meta
1349
+ });
1252
1350
  }
1253
1351
 
1254
1352
  /**
1255
1353
  * Notifies subscribers of a value change (current value has changed).
1256
1354
  */
1257
- notifyValueChange() {
1355
+ notifyValueChange(meta = {}) {
1258
1356
 
1259
1357
  // Prepare details for the event
1260
1358
  const details = {
@@ -1270,10 +1368,9 @@ class MenuService {
1270
1368
 
1271
1369
  this.notify({
1272
1370
  type: 'valueChange',
1371
+ ...meta,
1273
1372
  ...details
1274
1373
  });
1275
-
1276
- this.dispatchChangeEvent('auroMenu-selectedOption', details);
1277
1374
  }
1278
1375
 
1279
1376
  /**
@@ -1301,6 +1398,10 @@ class MenuService {
1301
1398
  addMenuOption(option) {
1302
1399
  this._menuOptions.push(option);
1303
1400
  this.notify({ type: 'optionsChange', options: this._menuOptions });
1401
+
1402
+ if (this._pendingValue != null) {
1403
+ this.queuePendingValue(this._pendingValue);
1404
+ }
1304
1405
  }
1305
1406
 
1306
1407
  /**
@@ -1310,6 +1411,10 @@ class MenuService {
1310
1411
  removeMenuOption(option) {
1311
1412
  this._menuOptions = this._menuOptions.filter(opt => opt !== option);
1312
1413
  this.notify({ type: 'optionsChange', options: this._menuOptions });
1414
+
1415
+ if (this._menuOptions.length === 0) {
1416
+ this.clearPendingValue();
1417
+ }
1313
1418
  }
1314
1419
 
1315
1420
  /**
@@ -1583,7 +1688,7 @@ class AuroMenu extends AuroElement {
1583
1688
  },
1584
1689
 
1585
1690
  /**
1586
- * Available menu options
1691
+ * Available menu options.
1587
1692
  * @readonly
1588
1693
  */
1589
1694
  options: {
@@ -1650,7 +1755,7 @@ class AuroMenu extends AuroElement {
1650
1755
  /**
1651
1756
  * @readonly
1652
1757
  * @returns {Array<HTMLElement>} - Returns the array of available menu options.
1653
- * @deprecated use `options` property instead.
1758
+ * @deprecated Use `options` property instead.
1654
1759
  */
1655
1760
  get items() {
1656
1761
  return this.options;
@@ -1758,7 +1863,7 @@ class AuroMenu extends AuroElement {
1758
1863
  const newValue = event.stringValue;
1759
1864
 
1760
1865
  // Check if the option or value has actually changed
1761
- if (newValue === undefined || (this.optionSelected !== newOption || this.stringValue !== newValue)) {
1866
+ if (this.optionSelected !== newOption || this.stringValue !== newValue) {
1762
1867
  this.optionSelected = newOption;
1763
1868
  this.setInternalValue(newValue);
1764
1869
  }
@@ -1832,8 +1937,13 @@ class AuroMenu extends AuroElement {
1832
1937
  updated(changedProperties) {
1833
1938
  super.updated(changedProperties);
1834
1939
 
1835
- // Update menu service properties on host update
1836
- if (changedProperties.has('value')) {
1940
+ // Apply value selection synchronously so that static-HTML fixtures
1941
+ // resolve within a single update cycle. The refactored selectByValue
1942
+ // no longer calls reset() first, so the destructive intermediate-event
1943
+ // cascade that originally required deferral is eliminated. If option
1944
+ // keys are not yet resolved (framework mount-order race), selectByValue
1945
+ // queues a bounded retry automatically via queuePendingValue.
1946
+ if (changedProperties.has('value') && !this.internalUpdateInProgress) {
1837
1947
  this.menuService.selectByValue(this.value);
1838
1948
  }
1839
1949
 
@@ -2013,12 +2123,13 @@ class AuroMenu extends AuroElement {
2013
2123
  * @param {any} source - The source that triggers this event.
2014
2124
  * @private
2015
2125
  */
2016
- notifySelectionChange({value, stringValue, keys, options} = {}) {
2126
+ notifySelectionChange({value, stringValue, keys, options, reason} = {}) {
2017
2127
  dispatchMenuEvent(this, 'auroMenu-selectedOption', {
2018
2128
  value,
2019
2129
  stringValue,
2020
2130
  keys,
2021
- options
2131
+ options,
2132
+ reason
2022
2133
  });
2023
2134
  }
2024
2135
 
@@ -1645,7 +1645,7 @@ class AuroHelpText extends i$2 {
1645
1645
  }
1646
1646
  }
1647
1647
 
1648
- var formkitVersion = '202603241813';
1648
+ var formkitVersion = '202603241855';
1649
1649
 
1650
1650
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
1651
1651
  // See LICENSE in the project root for license information.
@@ -1620,7 +1620,7 @@ class AuroHelpText extends i$2 {
1620
1620
  }
1621
1621
  }
1622
1622
 
1623
- var formkitVersion = '202603241813';
1623
+ var formkitVersion = '202603241855';
1624
1624
 
1625
1625
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
1626
1626
  // See LICENSE in the project root for license information.
@@ -1573,7 +1573,7 @@ class AuroHelpText extends LitElement {
1573
1573
  }
1574
1574
  }
1575
1575
 
1576
- var formkitVersion = '202603241813';
1576
+ var formkitVersion = '202603241855';
1577
1577
 
1578
1578
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
1579
1579
  // See LICENSE in the project root for license information.
@@ -1573,7 +1573,7 @@ class AuroHelpText extends LitElement {
1573
1573
  }
1574
1574
  }
1575
1575
 
1576
- var formkitVersion = '202603241813';
1576
+ var formkitVersion = '202603241855';
1577
1577
 
1578
1578
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
1579
1579
  // See LICENSE in the project root for license information.