govuk_publishing_components 65.1.0 → 65.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/component_guide/application.scss +13 -15
  3. data/app/assets/stylesheets/govuk_publishing_components/all-components.scss +0 -1
  4. data/app/assets/stylesheets/govuk_publishing_components/components/_contents-list.scss +25 -0
  5. data/app/assets/stylesheets/govuk_publishing_components/components/_details.scss +34 -0
  6. data/app/assets/stylesheets/govuk_publishing_components/components/_heading.scss +1 -0
  7. data/app/assets/stylesheets/govuk_publishing_components/components/helpers/_markdown-typography.scss +4 -0
  8. data/app/assets/stylesheets/govuk_publishing_components/specific-components.scss +0 -1
  9. data/app/controllers/govuk_publishing_components/applications_page_controller.rb +1 -1
  10. data/app/controllers/govuk_publishing_components/audit_controller.rb +0 -1
  11. data/app/models/govuk_publishing_components/component_doc.rb +10 -3
  12. data/app/models/govuk_publishing_components/component_wrapper_helper_options.rb +4 -2
  13. data/app/views/govuk_publishing_components/component_guide/component_doc/_component.html.erb +1 -1
  14. data/app/views/govuk_publishing_components/component_guide/component_doc/_preview.html.erb +2 -2
  15. data/app/views/govuk_publishing_components/component_guide/show.html.erb +47 -33
  16. data/app/views/govuk_publishing_components/components/_details.html.erb +4 -0
  17. data/app/views/govuk_publishing_components/components/_devolved_nations.html.erb +2 -2
  18. data/app/views/govuk_publishing_components/components/_option_select.html.erb +2 -2
  19. data/app/views/govuk_publishing_components/components/docs/details.yml +16 -0
  20. data/lib/govuk_publishing_components/presenters/devolved_nations_helper.rb +13 -7
  21. data/lib/govuk_publishing_components/version.rb +1 -1
  22. data/node_modules/choices.js/README.md +140 -30
  23. data/node_modules/choices.js/package.json +10 -13
  24. data/node_modules/choices.js/public/assets/scripts/choices.js +144 -89
  25. data/node_modules/choices.js/public/assets/scripts/choices.min.js +2 -2
  26. data/node_modules/choices.js/public/assets/scripts/choices.mjs +144 -89
  27. data/node_modules/choices.js/public/assets/scripts/choices.search-basic.js +144 -86
  28. data/node_modules/choices.js/public/assets/scripts/choices.search-basic.min.js +2 -2
  29. data/node_modules/choices.js/public/assets/scripts/choices.search-basic.mjs +144 -86
  30. data/node_modules/choices.js/public/assets/scripts/choices.search-kmp.js +139 -77
  31. data/node_modules/choices.js/public/assets/scripts/choices.search-kmp.min.js +2 -2
  32. data/node_modules/choices.js/public/assets/scripts/choices.search-kmp.mjs +139 -77
  33. data/node_modules/choices.js/public/assets/scripts/choices.search-prefix.js +137 -76
  34. data/node_modules/choices.js/public/assets/scripts/choices.search-prefix.min.js +2 -2
  35. data/node_modules/choices.js/public/assets/scripts/choices.search-prefix.mjs +137 -76
  36. data/node_modules/choices.js/public/assets/styles/base.css +39 -9
  37. data/node_modules/choices.js/public/assets/styles/base.css.map +1 -1
  38. data/node_modules/choices.js/public/assets/styles/base.min.css +1 -1
  39. data/node_modules/choices.js/public/assets/styles/choices.css +93 -95
  40. data/node_modules/choices.js/public/assets/styles/choices.css.map +1 -1
  41. data/node_modules/choices.js/public/assets/styles/choices.min.css +1 -1
  42. data/node_modules/choices.js/public/types/src/scripts/choices.d.ts +11 -0
  43. data/node_modules/choices.js/public/types/src/scripts/components/container.d.ts +2 -0
  44. data/node_modules/choices.js/public/types/src/scripts/interfaces/choice-full.d.ts +2 -1
  45. data/node_modules/choices.js/public/types/src/scripts/interfaces/class-names.d.ts +2 -0
  46. data/node_modules/choices.js/public/types/src/scripts/interfaces/input-choice.d.ts +2 -1
  47. data/node_modules/choices.js/public/types/src/scripts/interfaces/options.d.ts +19 -3
  48. data/node_modules/choices.js/public/types/src/scripts/interfaces/store.d.ts +2 -1
  49. data/node_modules/choices.js/public/types/src/scripts/interfaces/types.d.ts +2 -1
  50. data/node_modules/choices.js/public/types/src/scripts/lib/utils.d.ts +3 -1
  51. data/node_modules/choices.js/src/scripts/choices.ts +110 -64
  52. data/node_modules/choices.js/src/scripts/components/container.ts +8 -0
  53. data/node_modules/choices.js/src/scripts/components/wrapped-select.ts +3 -1
  54. data/node_modules/choices.js/src/scripts/defaults.ts +12 -7
  55. data/node_modules/choices.js/src/scripts/interfaces/choice-full.ts +2 -1
  56. data/node_modules/choices.js/src/scripts/interfaces/class-names.ts +2 -0
  57. data/node_modules/choices.js/src/scripts/interfaces/event-choice.ts +1 -0
  58. data/node_modules/choices.js/src/scripts/interfaces/input-choice.ts +4 -2
  59. data/node_modules/choices.js/src/scripts/interfaces/options.ts +21 -3
  60. data/node_modules/choices.js/src/scripts/interfaces/store.ts +2 -1
  61. data/node_modules/choices.js/src/scripts/interfaces/types.ts +3 -1
  62. data/node_modules/choices.js/src/scripts/lib/utils.ts +27 -4
  63. data/node_modules/choices.js/src/scripts/search/kmp.ts +2 -1
  64. data/node_modules/choices.js/src/scripts/store/store.ts +4 -1
  65. data/node_modules/choices.js/src/scripts/templates.ts +6 -3
  66. data/node_modules/choices.js/src/styles/base.scss +42 -9
  67. data/node_modules/choices.js/src/styles/choices.scss +119 -93
  68. metadata +2 -3
  69. data/app/assets/stylesheets/govuk_publishing_components/components/helpers/_contents-list-helper.scss +0 -24
@@ -1,4 +1,4 @@
1
- /*! choices.js v11.1.0 | © 2025 Josh Johnson | https://github.com/jshjohnson/Choices#readme */
1
+ /*! choices.js v11.2.1 | © 2026 Josh Johnson | https://github.com/Choices-js/Choices#readme */
2
2
 
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -217,9 +217,6 @@
217
217
  return firstChild;
218
218
  };
219
219
  })();
220
- var resolveNoticeFunction = function (fn, value) {
221
- return typeof fn === 'function' ? fn(sanitise(value), value) : fn;
222
- };
223
220
  var resolveStringFunction = function (fn) {
224
221
  return typeof fn === 'function' ? fn() : fn;
225
222
  };
@@ -251,6 +248,26 @@
251
248
  }
252
249
  return '';
253
250
  };
251
+ var getChoiceForOutput = function (choice, keyCode) {
252
+ return {
253
+ id: choice.id,
254
+ highlighted: choice.highlighted,
255
+ labelClass: choice.labelClass,
256
+ labelDescription: unwrapStringForRaw(choice.labelDescription),
257
+ customProperties: choice.customProperties,
258
+ disabled: choice.disabled,
259
+ active: choice.active,
260
+ label: choice.label,
261
+ placeholder: choice.placeholder,
262
+ value: choice.value,
263
+ groupValue: choice.group ? choice.group.label : undefined,
264
+ element: choice.element,
265
+ keyCode: keyCode,
266
+ };
267
+ };
268
+ var resolveNoticeFunction = function (fn, value, item) {
269
+ return typeof fn === 'function' ? fn(sanitise(value), unwrapStringForRaw(value), item) : fn;
270
+ };
254
271
  var escapeForTemplate = function (allowHTML, s) {
255
272
  return allowHTML ? unwrapStringForEscaped(s) : sanitise(s);
256
273
  };
@@ -418,6 +435,12 @@
418
435
  Container.prototype.removeFocusState = function () {
419
436
  removeClassesFromElement(this.element, this.classNames.focusState);
420
437
  };
438
+ Container.prototype.addInvalidState = function () {
439
+ addClassesToElement(this.element, this.classNames.invalidState);
440
+ };
441
+ Container.prototype.removeInvalidState = function () {
442
+ removeClassesFromElement(this.element, this.classNames.invalidState);
443
+ };
421
444
  Container.prototype.enable = function () {
422
445
  removeClassesFromElement(this.element, this.classNames.disabledState);
423
446
  this.element.removeAttribute('aria-disabled');
@@ -883,7 +906,9 @@
883
906
  highlighted: false,
884
907
  placeholder: this.extractPlaceholder && (!option.value || option.hasAttribute('placeholder')),
885
908
  labelClass: typeof option.dataset.labelClass !== 'undefined' ? stringToHtmlClass(option.dataset.labelClass) : undefined,
886
- labelDescription: typeof option.dataset.labelDescription !== 'undefined' ? option.dataset.labelDescription : undefined,
909
+ labelDescription: typeof option.dataset.labelDescription !== 'undefined'
910
+ ? { trusted: option.dataset.labelDescription }
911
+ : undefined,
887
912
  customProperties: parseCustomProperties(option.dataset.customProperties),
888
913
  };
889
914
  };
@@ -929,6 +954,7 @@
929
954
  selectedState: ['is-selected'],
930
955
  flippedState: ['is-flipped'],
931
956
  loadingState: ['is-loading'],
957
+ invalidState: ['is-invalid'],
932
958
  notice: ['choices__notice'],
933
959
  addChoice: ['choices__item--selectable', 'add-choice'],
934
960
  noResults: ['has-no-results'],
@@ -956,6 +982,7 @@
956
982
  paste: true,
957
983
  searchEnabled: true,
958
984
  searchChoices: true,
985
+ searchDisabledChoices: false,
959
986
  searchFloor: 1,
960
987
  searchResultLimit: 4,
961
988
  searchFields: ['label', 'value'],
@@ -971,6 +998,7 @@
971
998
  prependValue: null,
972
999
  appendValue: null,
973
1000
  renderSelectedChoices: 'auto',
1001
+ searchRenderSelectedChoices: true,
974
1002
  loadingText: 'Loading...',
975
1003
  noResultsText: 'No results found',
976
1004
  noChoicesText: 'No choices to choose from',
@@ -979,7 +1007,9 @@
979
1007
  customAddItemText: 'Only values matching specific conditions can be added',
980
1008
  addItemText: function (value) { return "Press Enter to add <b>\"".concat(value, "\"</b>"); },
981
1009
  removeItemIconText: function () { return "Remove item"; },
982
- removeItemLabelText: function (value) { return "Remove item: ".concat(value); },
1010
+ removeItemLabelText: function (value, _valueRaw, i) {
1011
+ return "Remove item: ".concat(i ? sanitise(i.label) : value);
1012
+ },
983
1013
  maxItemText: function (maxItemCount) { return "Only ".concat(maxItemCount, " values can be added"); },
984
1014
  valueComparer: function (value1, value2) { return value1 === value2; },
985
1015
  fuseOptions: {
@@ -1280,7 +1310,8 @@
1280
1310
  * Get choices that can be searched (excluding placeholders or disabled choices)
1281
1311
  */
1282
1312
  get: function () {
1283
- return this.choices.filter(function (choice) { return !choice.disabled && !choice.placeholder; });
1313
+ var context = this._context;
1314
+ return this.choices.filter(function (choice) { return !choice.placeholder && (context.searchDisabledChoices || !choice.disabled); });
1284
1315
  },
1285
1316
  enumerable: false,
1286
1317
  configurable: true
@@ -1338,9 +1369,9 @@
1338
1369
  function _defineProperty(e, r, t) {
1339
1370
  return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
1340
1371
  value: t,
1341
- enumerable: !0,
1342
- configurable: !0,
1343
- writable: !0
1372
+ enumerable: true,
1373
+ configurable: true,
1374
+ writable: true
1344
1375
  }) : e[r] = t, e;
1345
1376
  }
1346
1377
  function ownKeys(e, r) {
@@ -1356,7 +1387,7 @@
1356
1387
  function _objectSpread2(e) {
1357
1388
  for (var r = 1; r < arguments.length; r++) {
1358
1389
  var t = null != arguments[r] ? arguments[r] : {};
1359
- r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
1390
+ r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
1360
1391
  _defineProperty(e, r, t[r]);
1361
1392
  }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
1362
1393
  Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
@@ -1368,7 +1399,7 @@
1368
1399
  if ("object" != typeof t || !t) return t;
1369
1400
  var e = t[Symbol.toPrimitive];
1370
1401
  if (void 0 !== e) {
1371
- var i = e.call(t, r || "default");
1402
+ var i = e.call(t, r);
1372
1403
  if ("object" != typeof i) return i;
1373
1404
  throw new TypeError("@@toPrimitive must return a primitive value.");
1374
1405
  }
@@ -1391,16 +1422,13 @@
1391
1422
  function isArray(value) {
1392
1423
  return !Array.isArray ? getTag(value) === '[object Array]' : Array.isArray(value);
1393
1424
  }
1394
-
1395
- // Adapted from: https://github.com/lodash/lodash/blob/master/.internal/baseToString.js
1396
- const INFINITY = 1 / 0;
1397
1425
  function baseToString(value) {
1398
1426
  // Exit early for strings to avoid a performance hit in some environments.
1399
1427
  if (typeof value == 'string') {
1400
1428
  return value;
1401
1429
  }
1402
1430
  let result = value + '';
1403
- return result == '0' && 1 / value == -INFINITY ? '-0' : result;
1431
+ return result == '0' && 1 / value == -Infinity ? '-0' : result;
1404
1432
  }
1405
1433
  function toString(value) {
1406
1434
  return value == null ? '' : baseToString(value);
@@ -2269,7 +2297,7 @@
2269
2297
  class Fuse {
2270
2298
  constructor(docs, options = {}, index) {
2271
2299
  this.options = _objectSpread2(_objectSpread2({}, Config), options);
2272
- if (this.options.useExtendedSearch && !false) {
2300
+ if (this.options.useExtendedSearch && true) {
2273
2301
  throw new Error(EXTENDED_SEARCH_UNAVAILABLE);
2274
2302
  }
2275
2303
  this._keyStore = new KeyStore(this.options.keys);
@@ -2542,7 +2570,7 @@
2542
2570
  dataset.labelClass = getClassNames(labelClass).join(' ');
2543
2571
  }
2544
2572
  if (labelDescription) {
2545
- dataset.labelDescription = labelDescription;
2573
+ dataset.labelDescription = unwrapStringForRaw(labelDescription);
2546
2574
  }
2547
2575
  if (withCustomProperties && customProperties) {
2548
2576
  if (typeof customProperties === 'string') {
@@ -2649,8 +2677,9 @@
2649
2677
  var removeButton = document.createElement('button');
2650
2678
  removeButton.type = 'button';
2651
2679
  addClassesToElement(removeButton, button);
2652
- setElementHtml(removeButton, true, resolveNoticeFunction(removeItemIconText, choice.value));
2653
- var REMOVE_ITEM_LABEL = resolveNoticeFunction(removeItemLabelText, choice.value);
2680
+ var eventChoice = getChoiceForOutput(choice);
2681
+ setElementHtml(removeButton, true, resolveNoticeFunction(removeItemIconText, choice.value, eventChoice));
2682
+ var REMOVE_ITEM_LABEL = resolveNoticeFunction(removeItemLabelText, choice.value, eventChoice);
2654
2683
  if (REMOVE_ITEM_LABEL) {
2655
2684
  removeButton.setAttribute('aria-label', REMOVE_ITEM_LABEL);
2656
2685
  }
@@ -2755,6 +2784,7 @@
2755
2784
  else {
2756
2785
  addClassesToElement(div, itemSelectable);
2757
2786
  div.dataset.choiceSelectable = '';
2787
+ div.setAttribute('aria-selected', choice.selected ? 'true' : 'false');
2758
2788
  }
2759
2789
  return div;
2760
2790
  },
@@ -2924,7 +2954,7 @@
2924
2954
  this.initialised = false;
2925
2955
  this._store = new Store(config);
2926
2956
  this._currentValue = '';
2927
- config.searchEnabled = (!isText && config.searchEnabled) || isSelectMultiple;
2957
+ config.searchEnabled = !isText && config.searchEnabled;
2928
2958
  this._canSearch = config.searchEnabled;
2929
2959
  this._isScrollingOnIe = false;
2930
2960
  this._highlightPosition = 0;
@@ -2964,6 +2994,8 @@
2964
2994
  this._onEscapeKey = this._onEscapeKey.bind(this);
2965
2995
  this._onDirectionKey = this._onDirectionKey.bind(this);
2966
2996
  this._onDeleteKey = this._onDeleteKey.bind(this);
2997
+ this._onChange = this._onChange.bind(this);
2998
+ this._onInvalid = this._onInvalid.bind(this);
2967
2999
  // If element has already been initialised with Choices, fail silently
2968
3000
  if (this.passedElement.isActive) {
2969
3001
  if (!config.silent) {
@@ -3070,7 +3102,7 @@
3070
3102
  }
3071
3103
  this._store.dispatch(highlightItem(choice, true));
3072
3104
  if (runEvent) {
3073
- this.passedElement.triggerEvent(EventType.highlightItem, this._getChoiceForOutput(choice));
3105
+ this.passedElement.triggerEvent(EventType.highlightItem, getChoiceForOutput(choice));
3074
3106
  }
3075
3107
  return this;
3076
3108
  };
@@ -3085,7 +3117,7 @@
3085
3117
  }
3086
3118
  this._store.dispatch(highlightItem(choice, false));
3087
3119
  if (runEvent) {
3088
- this.passedElement.triggerEvent(EventType.unhighlightItem, this._getChoiceForOutput(choice));
3120
+ this.passedElement.triggerEvent(EventType.unhighlightItem, getChoiceForOutput(choice));
3089
3121
  }
3090
3122
  return this;
3091
3123
  };
@@ -3095,7 +3127,7 @@
3095
3127
  _this._store.items.forEach(function (item) {
3096
3128
  if (!item.highlighted) {
3097
3129
  _this._store.dispatch(highlightItem(item, true));
3098
- _this.passedElement.triggerEvent(EventType.highlightItem, _this._getChoiceForOutput(item));
3130
+ _this.passedElement.triggerEvent(EventType.highlightItem, getChoiceForOutput(item));
3099
3131
  }
3100
3132
  });
3101
3133
  });
@@ -3107,7 +3139,7 @@
3107
3139
  _this._store.items.forEach(function (item) {
3108
3140
  if (item.highlighted) {
3109
3141
  _this._store.dispatch(highlightItem(item, false));
3110
- _this.passedElement.triggerEvent(EventType.highlightItem, _this._getChoiceForOutput(item));
3142
+ _this.passedElement.triggerEvent(EventType.highlightItem, getChoiceForOutput(item));
3111
3143
  }
3112
3144
  });
3113
3145
  });
@@ -3162,6 +3194,11 @@
3162
3194
  _this.input.focus();
3163
3195
  }
3164
3196
  _this.passedElement.triggerEvent(EventType.showDropdown);
3197
+ var activeElement = _this.choiceList.element.querySelector(getClassNamesSelector(_this.config.classNames.selectedState));
3198
+ if (activeElement !== null && !isScrolledIntoView(activeElement, _this.choiceList.element)) {
3199
+ // We use the native scrollIntoView function instead of choiceList.scrollToChildElement to avoid animated scroll.
3200
+ activeElement.scrollIntoView();
3201
+ }
3165
3202
  });
3166
3203
  return this;
3167
3204
  };
@@ -3170,6 +3207,7 @@
3170
3207
  if (!this.dropdown.isActive) {
3171
3208
  return this;
3172
3209
  }
3210
+ this._removeHighlightedChoices();
3173
3211
  requestAnimationFrame(function () {
3174
3212
  _this.dropdown.hide();
3175
3213
  _this.containerOuter.close();
@@ -3182,9 +3220,8 @@
3182
3220
  return this;
3183
3221
  };
3184
3222
  Choices.prototype.getValue = function (valueOnly) {
3185
- var _this = this;
3186
3223
  var values = this._store.items.map(function (item) {
3187
- return (valueOnly ? item.value : _this._getChoiceForOutput(item));
3224
+ return (valueOnly ? item.value : getChoiceForOutput(item));
3188
3225
  });
3189
3226
  return this._isSelectOneElement || this.config.singleModeForMultiSelect ? values[0] : values;
3190
3227
  };
@@ -3442,7 +3479,7 @@
3442
3479
  // @todo integrate with Store
3443
3480
  this._searcher.reset();
3444
3481
  if (choice.selected) {
3445
- this.passedElement.triggerEvent(EventType.removeItem, this._getChoiceForOutput(choice));
3482
+ this.passedElement.triggerEvent(EventType.removeItem, getChoiceForOutput(choice));
3446
3483
  }
3447
3484
  return this;
3448
3485
  };
@@ -3525,13 +3562,7 @@
3525
3562
  }
3526
3563
  var _a = this, config = _a.config, isSearching = _a._isSearching;
3527
3564
  var _b = this._store, activeGroups = _b.activeGroups, activeChoices = _b.activeChoices;
3528
- var renderLimit = 0;
3529
- if (isSearching && config.searchResultLimit > 0) {
3530
- renderLimit = config.searchResultLimit;
3531
- }
3532
- else if (config.renderChoiceLimit > 0) {
3533
- renderLimit = config.renderChoiceLimit;
3534
- }
3565
+ var renderLimit = isSearching ? config.searchResultLimit : config.renderChoiceLimit;
3535
3566
  if (this._isSelectElement) {
3536
3567
  var backingOptions = activeChoices.filter(function (choice) { return !choice.element; });
3537
3568
  if (backingOptions.length) {
@@ -3541,11 +3572,16 @@
3541
3572
  var fragment = document.createDocumentFragment();
3542
3573
  var renderableChoices = function (choices) {
3543
3574
  return choices.filter(function (choice) {
3544
- return !choice.placeholder && (isSearching ? !!choice.rank : config.renderSelectedChoices || !choice.selected);
3575
+ return !choice.placeholder &&
3576
+ (isSearching
3577
+ ? (config.searchRenderSelectedChoices || !choice.selected) && !!choice.rank
3578
+ : config.renderSelectedChoices || !choice.selected);
3545
3579
  });
3546
3580
  };
3581
+ var showLabel = config.appendGroupInSearch && isSearching;
3547
3582
  var selectableChoices = false;
3548
- var renderChoices = function (choices, withinGroup, groupLabel) {
3583
+ var highlightedEl = null;
3584
+ var renderChoices = function (choices, withinGroup) {
3549
3585
  if (isSearching) {
3550
3586
  // sortByRank is used to ensure stable sorting, as scores are non-unique
3551
3587
  // this additionally ensures fuseOptions.sortFn is not ignored
@@ -3555,16 +3591,20 @@
3555
3591
  choices.sort(config.sorter);
3556
3592
  }
3557
3593
  var choiceLimit = choices.length;
3558
- choiceLimit = !withinGroup && renderLimit && choiceLimit > renderLimit ? renderLimit : choiceLimit;
3594
+ choiceLimit = !withinGroup && renderLimit > 0 && choiceLimit > renderLimit ? renderLimit : choiceLimit;
3559
3595
  choiceLimit--;
3560
3596
  choices.every(function (choice, index) {
3561
3597
  // choiceEl being empty signals the contents has probably significantly changed
3562
- var dropdownItem = choice.choiceEl || _this._templates.choice(config, choice, config.itemSelectText, groupLabel);
3598
+ var dropdownItem = choice.choiceEl ||
3599
+ _this._templates.choice(config, choice, config.itemSelectText, showLabel && choice.group ? choice.group.label : undefined);
3563
3600
  choice.choiceEl = dropdownItem;
3564
3601
  fragment.appendChild(dropdownItem);
3565
3602
  if (isSearching || !choice.selected) {
3566
3603
  selectableChoices = true;
3567
3604
  }
3605
+ else if (!highlightedEl) {
3606
+ highlightedEl = dropdownItem;
3607
+ }
3568
3608
  return index < choiceLimit;
3569
3609
  });
3570
3610
  };
@@ -3574,7 +3614,7 @@
3574
3614
  }
3575
3615
  if (!this._hasNonChoicePlaceholder && !isSearching && this._isSelectOneElement) {
3576
3616
  // If we have a placeholder choice along with groups
3577
- renderChoices(activeChoices.filter(function (choice) { return choice.placeholder && !choice.group; }), false, undefined);
3617
+ renderChoices(activeChoices.filter(function (choice) { return choice.placeholder && !choice.group; }), false);
3578
3618
  }
3579
3619
  // If we have grouped options
3580
3620
  if (activeGroups.length && !isSearching) {
@@ -3583,7 +3623,7 @@
3583
3623
  }
3584
3624
  // render Choices without group first, regardless of sort, otherwise they won't be distinguishable
3585
3625
  // from the last group
3586
- renderChoices(activeChoices.filter(function (choice) { return !choice.placeholder && !choice.group; }), false, undefined);
3626
+ renderChoices(activeChoices.filter(function (choice) { return !choice.placeholder && !choice.group; }), false);
3587
3627
  activeGroups.forEach(function (group) {
3588
3628
  var groupChoices = renderableChoices(group.choices);
3589
3629
  if (groupChoices.length) {
@@ -3593,12 +3633,12 @@
3593
3633
  dropdownGroup.remove();
3594
3634
  fragment.appendChild(dropdownGroup);
3595
3635
  }
3596
- renderChoices(groupChoices, true, config.appendGroupInSearch && isSearching ? group.label : undefined);
3636
+ renderChoices(groupChoices, true);
3597
3637
  }
3598
3638
  });
3599
3639
  }
3600
3640
  else {
3601
- renderChoices(renderableChoices(activeChoices), false, undefined);
3641
+ renderChoices(renderableChoices(activeChoices), false);
3602
3642
  }
3603
3643
  }
3604
3644
  if (!selectableChoices && (isSearching || !fragment.children.length || !config.renderSelectedChoices)) {
@@ -3612,9 +3652,7 @@
3612
3652
  }
3613
3653
  this._renderNotice(fragment);
3614
3654
  this.choiceList.element.replaceChildren(fragment);
3615
- if (selectableChoices) {
3616
- this._highlightChoice();
3617
- }
3655
+ this._highlightChoice(highlightedEl);
3618
3656
  };
3619
3657
  Choices.prototype._renderItems = function () {
3620
3658
  var _this = this;
@@ -3724,23 +3762,12 @@
3724
3762
  }
3725
3763
  }
3726
3764
  };
3765
+ /**
3766
+ * @deprecated Use utils.getChoiceForOutput
3767
+ */
3727
3768
  // eslint-disable-next-line class-methods-use-this
3728
3769
  Choices.prototype._getChoiceForOutput = function (choice, keyCode) {
3729
- return {
3730
- id: choice.id,
3731
- highlighted: choice.highlighted,
3732
- labelClass: choice.labelClass,
3733
- labelDescription: choice.labelDescription,
3734
- customProperties: choice.customProperties,
3735
- disabled: choice.disabled,
3736
- active: choice.active,
3737
- label: choice.label,
3738
- placeholder: choice.placeholder,
3739
- value: choice.value,
3740
- groupValue: choice.group ? choice.group.label : undefined,
3741
- element: choice.element,
3742
- keyCode: keyCode,
3743
- };
3770
+ return getChoiceForOutput(choice, keyCode);
3744
3771
  };
3745
3772
  Choices.prototype._triggerChange = function (value) {
3746
3773
  if (value === undefined || value === null) {
@@ -3756,7 +3783,7 @@
3756
3783
  if (!items.length || !this.config.removeItems || !this.config.removeItemButton) {
3757
3784
  return;
3758
3785
  }
3759
- var id = element && parseDataSetId(element.parentElement);
3786
+ var id = element && parseDataSetId(element.closest('[data-id]'));
3760
3787
  var itemToRemove = id && items.find(function (item) { return item.id === id; });
3761
3788
  if (!itemToRemove) {
3762
3789
  return;
@@ -3945,7 +3972,7 @@
3945
3972
  var notice = '';
3946
3973
  if (canAddItem && typeof config.addItemFilter === 'function' && !config.addItemFilter(value)) {
3947
3974
  canAddItem = false;
3948
- notice = resolveNoticeFunction(config.customAddItemText, value);
3975
+ notice = resolveNoticeFunction(config.customAddItemText, value, undefined);
3949
3976
  }
3950
3977
  if (canAddItem) {
3951
3978
  var foundChoice = this._store.choices.find(function (choice) { return config.valueComparer(choice.value, value); });
@@ -3957,12 +3984,12 @@
3957
3984
  }
3958
3985
  if (!config.duplicateItemsAllowed) {
3959
3986
  canAddItem = false;
3960
- notice = resolveNoticeFunction(config.uniqueItemText, value);
3987
+ notice = resolveNoticeFunction(config.uniqueItemText, value, undefined);
3961
3988
  }
3962
3989
  }
3963
3990
  }
3964
3991
  if (canAddItem) {
3965
- notice = resolveNoticeFunction(config.addItemText, value);
3992
+ notice = resolveNoticeFunction(config.addItemText, value, undefined);
3966
3993
  }
3967
3994
  if (notice) {
3968
3995
  this._displayNotice(notice, NoticeTypes.addChoice);
@@ -4013,6 +4040,7 @@
4013
4040
  var documentElement = this._docRoot;
4014
4041
  var outerElement = this.containerOuter.element;
4015
4042
  var inputElement = this.input.element;
4043
+ var passedElement = this.passedElement.element;
4016
4044
  // capture events - can cancel event processing or propagation
4017
4045
  documentElement.addEventListener('touchend', this._onTouchEnd, true);
4018
4046
  outerElement.addEventListener('keydown', this._onKeyDown, true);
@@ -4050,12 +4078,21 @@
4050
4078
  passive: true,
4051
4079
  });
4052
4080
  }
4081
+ if (passedElement.hasAttribute('required')) {
4082
+ passedElement.addEventListener('change', this._onChange, {
4083
+ passive: true,
4084
+ });
4085
+ passedElement.addEventListener('invalid', this._onInvalid, {
4086
+ passive: true,
4087
+ });
4088
+ }
4053
4089
  this.input.addEventListeners();
4054
4090
  };
4055
4091
  Choices.prototype._removeEventListeners = function () {
4056
4092
  var documentElement = this._docRoot;
4057
4093
  var outerElement = this.containerOuter.element;
4058
4094
  var inputElement = this.input.element;
4095
+ var passedElement = this.passedElement.element;
4059
4096
  documentElement.removeEventListener('touchend', this._onTouchEnd, true);
4060
4097
  outerElement.removeEventListener('keydown', this._onKeyDown, true);
4061
4098
  outerElement.removeEventListener('mousedown', this._onMouseDown, true);
@@ -4073,6 +4110,10 @@
4073
4110
  if (inputElement.form) {
4074
4111
  inputElement.form.removeEventListener('reset', this._onFormReset);
4075
4112
  }
4113
+ if (passedElement.hasAttribute('required')) {
4114
+ passedElement.removeEventListener('change', this._onChange);
4115
+ passedElement.removeEventListener('invalid', this._onInvalid);
4116
+ }
4076
4117
  this.input.removeEventListeners();
4077
4118
  };
4078
4119
  Choices.prototype._onKeyDown = function (event) {
@@ -4322,7 +4363,7 @@
4322
4363
  */
4323
4364
  Choices.prototype._onMouseDown = function (event) {
4324
4365
  var target = event.target;
4325
- if (!(target instanceof HTMLElement)) {
4366
+ if (!(target instanceof Element)) {
4326
4367
  return;
4327
4368
  }
4328
4369
  // If we have our mouse down on the scrollbar and are on IE11...
@@ -4431,7 +4472,7 @@
4431
4472
  // Remove the focus state when the past outerContainer was the target
4432
4473
  containerOuter.removeFocusState();
4433
4474
  // Also close the dropdown if search is disabled
4434
- if (!this._canSearch) {
4475
+ if (!this.config.searchEnabled) {
4435
4476
  this.hideDropdown(true);
4436
4477
  }
4437
4478
  }
@@ -4455,13 +4496,19 @@
4455
4496
  }
4456
4497
  });
4457
4498
  };
4458
- Choices.prototype._highlightChoice = function (el) {
4459
- if (el === void 0) { el = null; }
4460
- var choices = Array.from(this.dropdown.element.querySelectorAll(selectableChoiceIdentifier));
4461
- if (!choices.length) {
4499
+ Choices.prototype._onChange = function (event) {
4500
+ if (!event.target.checkValidity()) {
4462
4501
  return;
4463
4502
  }
4464
- var passedEl = el;
4503
+ this.containerOuter.removeInvalidState();
4504
+ };
4505
+ Choices.prototype._onInvalid = function () {
4506
+ this.containerOuter.addInvalidState();
4507
+ };
4508
+ /**
4509
+ * Removes any highlighted choice options
4510
+ */
4511
+ Choices.prototype._removeHighlightedChoices = function () {
4465
4512
  var highlightedState = this.config.classNames.highlightedState;
4466
4513
  var highlightedChoices = Array.from(this.dropdown.element.querySelectorAll(getClassNamesSelector(highlightedState)));
4467
4514
  // Remove any highlighted choices
@@ -4469,6 +4516,16 @@
4469
4516
  removeClassesFromElement(choice, highlightedState);
4470
4517
  choice.setAttribute('aria-selected', 'false');
4471
4518
  });
4519
+ };
4520
+ Choices.prototype._highlightChoice = function (el) {
4521
+ if (el === void 0) { el = null; }
4522
+ var choices = Array.from(this.dropdown.element.querySelectorAll(selectableChoiceIdentifier));
4523
+ if (!choices.length) {
4524
+ return;
4525
+ }
4526
+ var passedEl = el;
4527
+ var highlightedState = this.config.classNames.highlightedState;
4528
+ this._removeHighlightedChoices();
4472
4529
  if (passedEl) {
4473
4530
  this._highlightPosition = choices.indexOf(passedEl);
4474
4531
  }
@@ -4509,9 +4566,10 @@
4509
4566
  }
4510
4567
  this._store.dispatch(addItem(item));
4511
4568
  if (withEvents) {
4512
- this.passedElement.triggerEvent(EventType.addItem, this._getChoiceForOutput(item));
4569
+ var eventChoice = getChoiceForOutput(item);
4570
+ this.passedElement.triggerEvent(EventType.addItem, eventChoice);
4513
4571
  if (userTriggered) {
4514
- this.passedElement.triggerEvent(EventType.choice, this._getChoiceForOutput(item));
4572
+ this.passedElement.triggerEvent(EventType.choice, eventChoice);
4515
4573
  }
4516
4574
  }
4517
4575
  };
@@ -4524,7 +4582,7 @@
4524
4582
  if (notice && notice.type === NoticeTypes.noChoices) {
4525
4583
  this._clearNotice();
4526
4584
  }
4527
- this.passedElement.triggerEvent(EventType.removeItem, this._getChoiceForOutput(item));
4585
+ this.passedElement.triggerEvent(EventType.removeItem, getChoiceForOutput(item));
4528
4586
  };
4529
4587
  Choices.prototype._addChoice = function (choice, withEvents, userTriggered) {
4530
4588
  if (withEvents === void 0) { withEvents = true; }
@@ -4639,25 +4697,25 @@
4639
4697
  containerInner.wrap(passedElement.element);
4640
4698
  // Wrapper inner container with outer container
4641
4699
  containerOuter.wrap(containerInner.element);
4700
+ containerOuter.element.appendChild(containerInner.element);
4701
+ containerOuter.element.appendChild(dropdownElement);
4702
+ containerInner.element.appendChild(this.itemList.element);
4703
+ dropdownElement.appendChild(this.choiceList.element);
4642
4704
  if (this._isSelectOneElement) {
4643
4705
  this.input.placeholder = this.config.searchPlaceholderValue || '';
4706
+ if (this.config.searchEnabled) {
4707
+ dropdownElement.insertBefore(this.input.element, dropdownElement.firstChild);
4708
+ }
4644
4709
  }
4645
4710
  else {
4711
+ if (!this._isSelectMultipleElement || this.config.searchEnabled) {
4712
+ containerInner.element.appendChild(this.input.element);
4713
+ }
4646
4714
  if (this._placeholderValue) {
4647
4715
  this.input.placeholder = this._placeholderValue;
4648
4716
  }
4649
4717
  this.input.setWidth();
4650
4718
  }
4651
- containerOuter.element.appendChild(containerInner.element);
4652
- containerOuter.element.appendChild(dropdownElement);
4653
- containerInner.element.appendChild(this.itemList.element);
4654
- dropdownElement.appendChild(this.choiceList.element);
4655
- if (!this._isSelectOneElement) {
4656
- containerInner.element.appendChild(this.input.element);
4657
- }
4658
- else if (this.config.searchEnabled) {
4659
- dropdownElement.insertBefore(this.input.element, dropdownElement.firstChild);
4660
- }
4661
4719
  this._highlightPosition = 0;
4662
4720
  this._isSearching = false;
4663
4721
  };
@@ -4739,7 +4797,7 @@
4739
4797
  throw new TypeError("".concat(caller, " called for an element which has multiple instances of Choices initialised on it"));
4740
4798
  }
4741
4799
  };
4742
- Choices.version = '11.1.0';
4800
+ Choices.version = '11.2.1';
4743
4801
  return Choices;
4744
4802
  }());
4745
4803