@ministryofjustice/frontend 5.1.0 → 5.1.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.
@@ -312,7 +312,7 @@ function createAll(Component, config, createAllOptions) {
312
312
  *
313
313
  * {@link https://github.com/ministryofjustice/moj-frontend/releases}
314
314
  */
315
- const version = '5.1.0';
315
+ const version = '5.1.2';
316
316
 
317
317
  class AddAnother extends Component {
318
318
  /**
@@ -388,7 +388,7 @@ class AddAnother extends Component {
388
388
  */
389
389
  updateAttributes($item, index) {
390
390
  $item.querySelectorAll('[data-name]').forEach($input => {
391
- if (!($input instanceof HTMLInputElement)) {
391
+ if (!this.isValidInputElement($input)) {
392
392
  return;
393
393
  }
394
394
  const name = $input.getAttribute('data-name') || '';
@@ -419,13 +419,23 @@ class AddAnother extends Component {
419
419
  */
420
420
  resetItem($item) {
421
421
  $item.querySelectorAll('[data-name], [data-id]').forEach($input => {
422
- if (!($input instanceof HTMLInputElement)) {
422
+ if (!this.isValidInputElement($input)) {
423
423
  return;
424
424
  }
425
- if ($input.type === 'checkbox' || $input.type === 'radio') {
426
- $input.checked = false;
427
- } else {
425
+ if ($input instanceof HTMLSelectElement) {
426
+ $input.selectedIndex = -1;
427
+ $input.value = '';
428
+ } else if ($input instanceof HTMLTextAreaElement) {
428
429
  $input.value = '';
430
+ } else {
431
+ switch ($input.type) {
432
+ case 'checkbox':
433
+ case 'radio':
434
+ $input.checked = false;
435
+ break;
436
+ default:
437
+ $input.value = '';
438
+ }
429
439
  }
430
440
  });
431
441
  }
@@ -455,6 +465,13 @@ class AddAnother extends Component {
455
465
  }
456
466
  }
457
467
 
468
+ /**
469
+ * @param {Element} $input - the input to validate
470
+ */
471
+ isValidInputElement($input) {
472
+ return $input instanceof HTMLInputElement || $input instanceof HTMLSelectElement || $input instanceof HTMLTextAreaElement;
473
+ }
474
+
458
475
  /**
459
476
  * Name for the component used when initialising using data-module attributes.
460
477
  */
@@ -3097,8 +3114,21 @@ class SortableTable extends ConfigurableComponent {
3097
3114
  }
3098
3115
  this.$head = $head;
3099
3116
  this.$body = $body;
3117
+ this.$caption = this.$root.querySelector('caption');
3118
+ this.$upArrow = `<svg width="22" height="22" focusable="false" aria-hidden="true" role="img" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
3119
+ <path d="M6.5625 15.5L11 6.63125L15.4375 15.5H6.5625Z" fill="currentColor"/>
3120
+ </svg>`;
3121
+ this.$downArrow = `<svg width="22" height="22" focusable="false" aria-hidden="true" role="img" vviewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
3122
+ <path d="M15.4375 7L11 15.8687L6.5625 7L15.4375 7Z" fill="currentColor"/>
3123
+ </svg>`;
3124
+ this.$upDownArrow = `<svg width="22" height="22" focusable="false" aria-hidden="true" role="img" vviewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
3125
+ <path d="M8.1875 9.5L10.9609 3.95703L13.7344 9.5H8.1875Z" fill="currentColor"/>
3126
+ <path d="M13.7344 12.0781L10.9609 17.6211L8.1875 12.0781H13.7344Z" fill="currentColor"/>
3127
+ </svg>`;
3100
3128
  this.$headings = this.$head ? Array.from(this.$head.querySelectorAll('th')) : [];
3101
3129
  this.createHeadingButtons();
3130
+ this.updateCaption();
3131
+ this.updateDirectionIndicators();
3102
3132
  this.createStatusBox();
3103
3133
  this.initialiseSortedColumn();
3104
3134
  this.$head.addEventListener('click', this.onSortButtonClick.bind(this));
@@ -3134,7 +3164,7 @@ class SortableTable extends ConfigurableComponent {
3134
3164
  initialiseSortedColumn() {
3135
3165
  var _$sortButton$getAttri;
3136
3166
  const $rows = this.getTableRowsArray();
3137
- const $heading = this.$root.querySelector('th[aria-sort]');
3167
+ const $heading = this.$root.querySelector('th[aria-sort="ascending"], th[aria-sort="descending"]');
3138
3168
  const $sortButton = $heading == null ? void 0 : $heading.querySelector('button');
3139
3169
  const sortDirection = $heading == null ? void 0 : $heading.getAttribute('aria-sort');
3140
3170
  const columnNumber = Number.parseInt((_$sortButton$getAttri = $sortButton == null ? void 0 : $sortButton.getAttribute('data-index')) != null ? _$sortButton$getAttri : '0', 10);
@@ -3150,7 +3180,8 @@ class SortableTable extends ConfigurableComponent {
3150
3180
  */
3151
3181
  onSortButtonClick(event) {
3152
3182
  var _$button$getAttribute;
3153
- const $button = event.target;
3183
+ const $target = /** @type {HTMLElement} */event.target;
3184
+ const $button = $target.closest('button');
3154
3185
  if (!$button || !($button instanceof HTMLButtonElement) || !$button.parentElement) {
3155
3186
  return;
3156
3187
  }
@@ -3163,6 +3194,20 @@ class SortableTable extends ConfigurableComponent {
3163
3194
  this.addRows($sortedRows);
3164
3195
  this.removeButtonStates();
3165
3196
  this.updateButtonState($button, newSortDirection);
3197
+ this.updateDirectionIndicators();
3198
+ }
3199
+ updateCaption() {
3200
+ if (!this.$caption) {
3201
+ return;
3202
+ }
3203
+ let assistiveText = this.$caption.querySelector('.govuk-visually-hidden');
3204
+ if (assistiveText) {
3205
+ return;
3206
+ }
3207
+ assistiveText = document.createElement('span');
3208
+ assistiveText.classList.add('govuk-visually-hidden');
3209
+ assistiveText.textContent = ' (column headers with buttons are sortable).';
3210
+ this.$caption.appendChild(assistiveText);
3166
3211
  }
3167
3212
 
3168
3213
  /**
@@ -3179,6 +3224,27 @@ class SortableTable extends ConfigurableComponent {
3179
3224
  message = message.replace(/%direction%/, this.config[`${direction}Text`]);
3180
3225
  this.$status.textContent = message;
3181
3226
  }
3227
+ updateDirectionIndicators() {
3228
+ for (const $heading of this.$headings) {
3229
+ const $button = /** @type {HTMLButtonElement} */
3230
+ $heading.querySelector('button');
3231
+ if ($heading.hasAttribute('aria-sort') && $button) {
3232
+ var _$button$querySelecto;
3233
+ const direction = $heading.getAttribute('aria-sort');
3234
+ (_$button$querySelecto = $button.querySelector('svg')) == null || _$button$querySelecto.remove();
3235
+ switch (direction) {
3236
+ case 'ascending':
3237
+ $button.insertAdjacentHTML('beforeend', this.$upArrow);
3238
+ break;
3239
+ case 'descending':
3240
+ $button.insertAdjacentHTML('beforeend', this.$downArrow);
3241
+ break;
3242
+ default:
3243
+ $button.insertAdjacentHTML('beforeend', this.$upDownArrow);
3244
+ }
3245
+ }
3246
+ }
3247
+ }
3182
3248
  removeButtonStates() {
3183
3249
  for (const $heading of this.$headings) {
3184
3250
  $heading.setAttribute('aria-sort', 'none');