@ministryofjustice/frontend 5.1.0 → 5.1.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.
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * {@link https://github.com/ministryofjustice/moj-frontend/releases}
10
10
  */
11
- const version = '5.1.0';
11
+ const version = '5.1.1';
12
12
 
13
13
  export { version };
14
14
  //# sourceMappingURL=moj-frontend-version.mjs.map
@@ -2,9 +2,10 @@
2
2
 
3
3
  [aria-sort] button,
4
4
  [aria-sort] button:hover {
5
+ display: inline-flex;
5
6
  position: relative;
6
7
  margin: 0;
7
- padding: 0 10px 0 0;
8
+ padding: 0;
8
9
  border-width: 0;
9
10
  color: #005ea5;
10
11
  background-color: transparent;
@@ -15,6 +16,7 @@
15
16
  font-weight: inherit;
16
17
  text-align: inherit;
17
18
  cursor: pointer;
19
+ align-items: center;
18
20
  }
19
21
 
20
22
  [aria-sort] button:focus {
@@ -26,45 +28,4 @@
26
28
  0 4px $govuk-focus-text-colour;
27
29
  }
28
30
 
29
- [aria-sort]:first-child button {
30
- right: auto;
31
- }
32
-
33
- [aria-sort] button::before {
34
- content: " \25bc";
35
- position: absolute;
36
- top: 9px;
37
- right: -1px;
38
- font-size: 0.5em;
39
- }
40
-
41
- [aria-sort] button::after {
42
- content: " \25b2";
43
- position: absolute;
44
- top: 1px;
45
- right: -1px;
46
- font-size: 0.5em;
47
- }
48
-
49
- [aria-sort="ascending"] button::before,
50
- [aria-sort="descending"] button::before {
51
- content: none;
52
- }
53
-
54
- [aria-sort="ascending"] button::after {
55
- content: " \25b2";
56
- position: absolute;
57
- top: 2px;
58
- right: -5px;
59
- font-size: 0.8em;
60
- }
61
-
62
- [aria-sort="descending"] button::after {
63
- content: " \25bc";
64
- position: absolute;
65
- top: 2px;
66
- right: -5px;
67
- font-size: 0.8em;
68
- }
69
-
70
31
  /*# sourceMappingURL=_sortable-table.scss.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/moj/components/sortable-table/_sortable-table.scss"],"names":[],"mappings":"AAAA,uCAAuC;;AAEvC;;EAEE,kBAAkB;EAClB,SAAS;EACT,mBAAmB;EACnB,eAAe;EACf,cAAc;EACd,6BAA6B;EAG7B,mBAAmB;EACnB,oBAAoB;EACpB,kBAAkB;EAClB,cAAc;EACd,oBAAoB;EACpB,mBAAmB;EACnB,eAAe;AACjB;;AAEA;EACE,aAAa;EACb,+BAA+B;EAC/B,qCAAqC;EACrC;;kCAEgC;AAClC;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,iBAAiB;EACjB,kBAAkB;EAClB,QAAQ;EACR,WAAW;EACX,gBAAgB;AAClB;;AAEA;EACE,iBAAiB;EACjB,kBAAkB;EAClB,QAAQ;EACR,WAAW;EACX,gBAAgB;AAClB;;AAEA;;EAEE,aAAa;AACf;;AAEA;EACE,iBAAiB;EACjB,kBAAkB;EAClB,QAAQ;EACR,WAAW;EACX,gBAAgB;AAClB;;AAEA;EACE,iBAAiB;EACjB,kBAAkB;EAClB,QAAQ;EACR,WAAW;EACX,gBAAgB;AAClB","file":"_sortable-table.scss","sourcesContent":["@use \"../../vendor/govuk-frontend\" as *;\n\n[aria-sort] button,\n[aria-sort] button:hover {\n position: relative;\n margin: 0;\n padding: 0 10px 0 0;\n border-width: 0;\n color: #005ea5;\n background-color: transparent;\n -webkit-box-shadow: 0 0 0 0;\n -moz-box-shadow: 0 0 0 0;\n box-shadow: 0 0 0 0;\n font-family: inherit;\n font-size: inherit;\n font-size: 1em;\n font-weight: inherit;\n text-align: inherit;\n cursor: pointer;\n}\n\n[aria-sort] button:focus {\n outline: none;\n color: $govuk-focus-text-colour;\n background-color: $govuk-focus-colour;\n box-shadow:\n 0 -2px $govuk-focus-colour,\n 0 4px $govuk-focus-text-colour;\n}\n\n[aria-sort]:first-child button {\n right: auto;\n}\n\n[aria-sort] button::before {\n content: \" \\25bc\";\n position: absolute;\n top: 9px;\n right: -1px;\n font-size: 0.5em;\n}\n\n[aria-sort] button::after {\n content: \" \\25b2\";\n position: absolute;\n top: 1px;\n right: -1px;\n font-size: 0.5em;\n}\n\n[aria-sort=\"ascending\"] button::before,\n[aria-sort=\"descending\"] button::before {\n content: none;\n}\n\n[aria-sort=\"ascending\"] button::after {\n content: \" \\25b2\";\n position: absolute;\n top: 2px;\n right: -5px;\n font-size: 0.8em;\n}\n\n[aria-sort=\"descending\"] button::after {\n content: \" \\25bc\";\n position: absolute;\n top: 2px;\n right: -5px;\n font-size: 0.8em;\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/moj/components/sortable-table/_sortable-table.scss"],"names":[],"mappings":"AAAA,uCAAuC;;AAEvC;;EAEE,oBAAoB;EACpB,kBAAkB;EAClB,SAAS;EACT,UAAU;EACV,eAAe;EACf,cAAc;EACd,6BAA6B;EAG7B,mBAAmB;EACnB,oBAAoB;EACpB,kBAAkB;EAClB,cAAc;EACd,oBAAoB;EACpB,mBAAmB;EACnB,eAAe;EACf,mBAAmB;AACrB;;AAEA;EACE,aAAa;EACb,+BAA+B;EAC/B,qCAAqC;EACrC;;kCAEgC;AAClC","file":"_sortable-table.scss","sourcesContent":["@use \"../../vendor/govuk-frontend\" as *;\n\n[aria-sort] button,\n[aria-sort] button:hover {\n display: inline-flex;\n position: relative;\n margin: 0;\n padding: 0;\n border-width: 0;\n color: #005ea5;\n background-color: transparent;\n -webkit-box-shadow: 0 0 0 0;\n -moz-box-shadow: 0 0 0 0;\n box-shadow: 0 0 0 0;\n font-family: inherit;\n font-size: inherit;\n font-size: 1em;\n font-weight: inherit;\n text-align: inherit;\n cursor: pointer;\n align-items: center;\n}\n\n[aria-sort] button:focus {\n outline: none;\n color: $govuk-focus-text-colour;\n background-color: $govuk-focus-colour;\n box-shadow:\n 0 -2px $govuk-focus-colour,\n 0 4px $govuk-focus-text-colour;\n}\n"]}
@@ -21,8 +21,21 @@
21
21
  }
22
22
  this.$head = $head;
23
23
  this.$body = $body;
24
+ this.$caption = this.$root.querySelector('caption');
25
+ 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">
26
+ <path d="M6.5625 15.5L11 6.63125L15.4375 15.5H6.5625Z" fill="currentColor"/>
27
+ </svg>`;
28
+ 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">
29
+ <path d="M15.4375 7L11 15.8687L6.5625 7L15.4375 7Z" fill="currentColor"/>
30
+ </svg>`;
31
+ 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">
32
+ <path d="M8.1875 9.5L10.9609 3.95703L13.7344 9.5H8.1875Z" fill="currentColor"/>
33
+ <path d="M13.7344 12.0781L10.9609 17.6211L8.1875 12.0781H13.7344Z" fill="currentColor"/>
34
+ </svg>`;
24
35
  this.$headings = this.$head ? Array.from(this.$head.querySelectorAll('th')) : [];
25
36
  this.createHeadingButtons();
37
+ this.updateCaption();
38
+ this.updateDirectionIndicators();
26
39
  this.createStatusBox();
27
40
  this.initialiseSortedColumn();
28
41
  this.$head.addEventListener('click', this.onSortButtonClick.bind(this));
@@ -58,7 +71,7 @@
58
71
  initialiseSortedColumn() {
59
72
  var _$sortButton$getAttri;
60
73
  const $rows = this.getTableRowsArray();
61
- const $heading = this.$root.querySelector('th[aria-sort]');
74
+ const $heading = this.$root.querySelector('th[aria-sort="ascending"], th[aria-sort="descending"]');
62
75
  const $sortButton = $heading == null ? void 0 : $heading.querySelector('button');
63
76
  const sortDirection = $heading == null ? void 0 : $heading.getAttribute('aria-sort');
64
77
  const columnNumber = Number.parseInt((_$sortButton$getAttri = $sortButton == null ? void 0 : $sortButton.getAttribute('data-index')) != null ? _$sortButton$getAttri : '0', 10);
@@ -74,7 +87,8 @@
74
87
  */
75
88
  onSortButtonClick(event) {
76
89
  var _$button$getAttribute;
77
- const $button = event.target;
90
+ const $target = /** @type {HTMLElement} */event.target;
91
+ const $button = $target.closest('button');
78
92
  if (!$button || !($button instanceof HTMLButtonElement) || !$button.parentElement) {
79
93
  return;
80
94
  }
@@ -87,6 +101,20 @@
87
101
  this.addRows($sortedRows);
88
102
  this.removeButtonStates();
89
103
  this.updateButtonState($button, newSortDirection);
104
+ this.updateDirectionIndicators();
105
+ }
106
+ updateCaption() {
107
+ if (!this.$caption) {
108
+ return;
109
+ }
110
+ let assistiveText = this.$caption.querySelector('.govuk-visually-hidden');
111
+ if (assistiveText) {
112
+ return;
113
+ }
114
+ assistiveText = document.createElement('span');
115
+ assistiveText.classList.add('govuk-visually-hidden');
116
+ assistiveText.textContent = ' (column headers with buttons are sortable).';
117
+ this.$caption.appendChild(assistiveText);
90
118
  }
91
119
 
92
120
  /**
@@ -103,6 +131,27 @@
103
131
  message = message.replace(/%direction%/, this.config[`${direction}Text`]);
104
132
  this.$status.textContent = message;
105
133
  }
134
+ updateDirectionIndicators() {
135
+ for (const $heading of this.$headings) {
136
+ const $button = /** @type {HTMLButtonElement} */
137
+ $heading.querySelector('button');
138
+ if ($heading.hasAttribute('aria-sort') && $button) {
139
+ var _$button$querySelecto;
140
+ const direction = $heading.getAttribute('aria-sort');
141
+ (_$button$querySelecto = $button.querySelector('svg')) == null || _$button$querySelecto.remove();
142
+ switch (direction) {
143
+ case 'ascending':
144
+ $button.insertAdjacentHTML('beforeend', this.$upArrow);
145
+ break;
146
+ case 'descending':
147
+ $button.insertAdjacentHTML('beforeend', this.$downArrow);
148
+ break;
149
+ default:
150
+ $button.insertAdjacentHTML('beforeend', this.$upDownArrow);
151
+ }
152
+ }
153
+ }
154
+ }
106
155
  removeButtonStates() {
107
156
  for (const $heading of this.$headings) {
108
157
  $heading.setAttribute('aria-sort', 'none');
@@ -1 +1 @@
1
- {"version":3,"file":"sortable-table.bundle.js","sources":["../../../../src/moj/components/sortable-table/sortable-table.mjs"],"sourcesContent":["import { ConfigurableComponent } from 'govuk-frontend'\n\n/**\n * @augments {ConfigurableComponent<SortableTableConfig>}\n */\nexport class SortableTable extends ConfigurableComponent {\n /**\n * @param {Element | null} $root - HTML element to use for sortable table\n * @param {SortableTableConfig} [config] - Sortable table config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $head = $root?.querySelector('thead')\n const $body = $root?.querySelector('tbody')\n\n if (!$head || !$body) {\n return this\n }\n\n this.$head = $head\n this.$body = $body\n\n this.$headings = this.$head\n ? Array.from(this.$head.querySelectorAll('th'))\n : []\n\n this.createHeadingButtons()\n this.createStatusBox()\n this.initialiseSortedColumn()\n\n this.$head.addEventListener('click', this.onSortButtonClick.bind(this))\n }\n\n createHeadingButtons() {\n for (const $heading of this.$headings) {\n if ($heading.hasAttribute('aria-sort')) {\n this.createHeadingButton($heading)\n }\n }\n }\n\n /**\n * @param {HTMLTableCellElement} $heading\n */\n createHeadingButton($heading) {\n const index = this.$headings.indexOf($heading)\n const $button = document.createElement('button')\n\n $button.setAttribute('type', 'button')\n $button.setAttribute('data-index', `${index}`)\n $button.textContent = $heading.textContent\n\n $heading.textContent = ''\n $heading.appendChild($button)\n }\n\n createStatusBox() {\n this.$status = document.createElement('div')\n\n this.$status.setAttribute('aria-atomic', 'true')\n this.$status.setAttribute('aria-live', 'polite')\n this.$status.setAttribute('class', 'govuk-visually-hidden')\n this.$status.setAttribute('role', 'status')\n\n this.$root.insertAdjacentElement('afterend', this.$status)\n }\n\n initialiseSortedColumn() {\n const $rows = this.getTableRowsArray()\n\n const $heading = this.$root.querySelector('th[aria-sort]')\n const $sortButton = $heading?.querySelector('button')\n const sortDirection = $heading?.getAttribute('aria-sort')\n\n const columnNumber = Number.parseInt(\n $sortButton?.getAttribute('data-index') ?? '0',\n 10\n )\n\n if (\n !$heading ||\n !$sortButton ||\n !(sortDirection === 'ascending' || sortDirection === 'descending')\n ) {\n return\n }\n\n const $sortedRows = this.sort($rows, columnNumber, sortDirection)\n this.addRows($sortedRows)\n }\n\n /**\n * @param {MouseEvent} event - Click event\n */\n onSortButtonClick(event) {\n const $button = event.target\n\n if (\n !$button ||\n !($button instanceof HTMLButtonElement) ||\n !$button.parentElement\n ) {\n return\n }\n\n const $heading = $button.parentElement\n const sortDirection = $heading.getAttribute('aria-sort')\n\n const columnNumber = Number.parseInt(\n $button?.getAttribute('data-index') ?? '0',\n 10\n )\n\n const newSortDirection =\n sortDirection === 'none' || sortDirection === 'descending'\n ? 'ascending'\n : 'descending'\n\n const $rows = this.getTableRowsArray()\n const $sortedRows = this.sort($rows, columnNumber, newSortDirection)\n\n this.addRows($sortedRows)\n this.removeButtonStates()\n this.updateButtonState($button, newSortDirection)\n }\n\n /**\n * @param {HTMLButtonElement} $button\n * @param {string} direction\n */\n updateButtonState($button, direction) {\n if (!(direction === 'ascending' || direction === 'descending')) {\n return\n }\n\n $button.parentElement.setAttribute('aria-sort', direction)\n let message = this.config.statusMessage\n message = message.replace(/%heading%/, $button.textContent)\n message = message.replace(/%direction%/, this.config[`${direction}Text`])\n this.$status.textContent = message\n }\n\n removeButtonStates() {\n for (const $heading of this.$headings) {\n $heading.setAttribute('aria-sort', 'none')\n }\n }\n\n /**\n * @param {HTMLTableRowElement[]} $rows\n */\n addRows($rows) {\n for (const $row of $rows) {\n this.$body.append($row)\n }\n }\n\n getTableRowsArray() {\n return Array.from(this.$body.querySelectorAll('tr'))\n }\n\n /**\n * @param {HTMLTableRowElement[]} $rows\n * @param {number} columnNumber\n * @param {string} sortDirection\n */\n sort($rows, columnNumber, sortDirection) {\n return $rows.sort(($rowA, $rowB) => {\n const $tdA = $rowA.querySelectorAll('td, th')[columnNumber]\n const $tdB = $rowB.querySelectorAll('td, th')[columnNumber]\n\n if (\n !$tdA ||\n !$tdB ||\n !($tdA instanceof HTMLElement) ||\n !($tdB instanceof HTMLElement)\n ) {\n return 0\n }\n\n const valueA =\n sortDirection === 'ascending'\n ? this.getCellValue($tdA)\n : this.getCellValue($tdB)\n\n const valueB =\n sortDirection === 'ascending'\n ? this.getCellValue($tdB)\n : this.getCellValue($tdA)\n\n return !(typeof valueA === 'number' && typeof valueB === 'number')\n ? valueA.toString().localeCompare(valueB.toString())\n : valueA - valueB\n })\n }\n\n /**\n * @param {HTMLElement} $cell\n */\n getCellValue($cell) {\n const val = $cell.getAttribute('data-sort-value') || $cell.innerHTML\n const valAsNumber = Number(val)\n\n return Number.isFinite(valAsNumber)\n ? valAsNumber // Exclude invalid numbers, infinity etc\n : val\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-sortable-table'\n\n /**\n * Sortable table config\n *\n * @type {SortableTableConfig}\n */\n static defaults = Object.freeze({\n statusMessage: 'Sort by %heading% (%direction%)',\n ascendingText: 'ascending',\n descendingText: 'descending'\n })\n\n /**\n * Sortable table config schema\n *\n * @satisfies {Schema<SortableTableConfig>}\n */\n static schema = Object.freeze(\n /** @type {const} */ ({\n properties: {\n statusMessage: { type: 'string' },\n ascendingText: { type: 'string' },\n descendingText: { type: 'string' }\n }\n })\n )\n}\n\n/**\n * Sortable table config\n *\n * @typedef {object} SortableTableConfig\n * @property {string} [statusMessage] - Status message\n * @property {string} [ascendingText] - Ascending text\n * @property {string} [descendingText] - Descending text\n */\n\n/**\n * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'\n */\n"],"names":["SortableTable","ConfigurableComponent","constructor","$root","config","$head","querySelector","$body","$headings","Array","from","querySelectorAll","createHeadingButtons","createStatusBox","initialiseSortedColumn","addEventListener","onSortButtonClick","bind","$heading","hasAttribute","createHeadingButton","index","indexOf","$button","document","createElement","setAttribute","textContent","appendChild","$status","insertAdjacentElement","_$sortButton$getAttri","$rows","getTableRowsArray","$sortButton","sortDirection","getAttribute","columnNumber","Number","parseInt","$sortedRows","sort","addRows","event","_$button$getAttribute","target","HTMLButtonElement","parentElement","newSortDirection","removeButtonStates","updateButtonState","direction","message","statusMessage","replace","$row","append","$rowA","$rowB","$tdA","$tdB","HTMLElement","valueA","getCellValue","valueB","toString","localeCompare","$cell","val","innerHTML","valAsNumber","isFinite","moduleName","defaults","Object","freeze","ascendingText","descendingText","schema","properties","type"],"mappings":"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"}
1
+ {"version":3,"file":"sortable-table.bundle.js","sources":["../../../../src/moj/components/sortable-table/sortable-table.mjs"],"sourcesContent":["import { ConfigurableComponent } from 'govuk-frontend'\n\n/**\n * @augments {ConfigurableComponent<SortableTableConfig>}\n */\nexport class SortableTable extends ConfigurableComponent {\n /**\n * @param {Element | null} $root - HTML element to use for sortable table\n * @param {SortableTableConfig} [config] - Sortable table config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $head = $root?.querySelector('thead')\n const $body = $root?.querySelector('tbody')\n\n if (!$head || !$body) {\n return this\n }\n\n this.$head = $head\n this.$body = $body\n this.$caption = this.$root.querySelector('caption')\n\n 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\">\n<path d=\"M6.5625 15.5L11 6.63125L15.4375 15.5H6.5625Z\" fill=\"currentColor\"/>\n</svg>`\n 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\">\n<path d=\"M15.4375 7L11 15.8687L6.5625 7L15.4375 7Z\" fill=\"currentColor\"/>\n</svg>`\n 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\">\n<path d=\"M8.1875 9.5L10.9609 3.95703L13.7344 9.5H8.1875Z\" fill=\"currentColor\"/>\n<path d=\"M13.7344 12.0781L10.9609 17.6211L8.1875 12.0781H13.7344Z\" fill=\"currentColor\"/>\n</svg>`\n\n this.$headings = this.$head\n ? Array.from(this.$head.querySelectorAll('th'))\n : []\n\n this.createHeadingButtons()\n this.updateCaption()\n this.updateDirectionIndicators()\n this.createStatusBox()\n this.initialiseSortedColumn()\n\n this.$head.addEventListener('click', this.onSortButtonClick.bind(this))\n }\n\n createHeadingButtons() {\n for (const $heading of this.$headings) {\n if ($heading.hasAttribute('aria-sort')) {\n this.createHeadingButton($heading)\n }\n }\n }\n\n /**\n * @param {HTMLTableCellElement} $heading\n */\n createHeadingButton($heading) {\n const index = this.$headings.indexOf($heading)\n const $button = document.createElement('button')\n\n $button.setAttribute('type', 'button')\n $button.setAttribute('data-index', `${index}`)\n $button.textContent = $heading.textContent\n\n $heading.textContent = ''\n $heading.appendChild($button)\n }\n\n createStatusBox() {\n this.$status = document.createElement('div')\n\n this.$status.setAttribute('aria-atomic', 'true')\n this.$status.setAttribute('aria-live', 'polite')\n this.$status.setAttribute('class', 'govuk-visually-hidden')\n this.$status.setAttribute('role', 'status')\n\n this.$root.insertAdjacentElement('afterend', this.$status)\n }\n\n initialiseSortedColumn() {\n const $rows = this.getTableRowsArray()\n\n const $heading = this.$root.querySelector(\n 'th[aria-sort=\"ascending\"], th[aria-sort=\"descending\"]'\n )\n const $sortButton = $heading?.querySelector('button')\n const sortDirection = $heading?.getAttribute('aria-sort')\n\n const columnNumber = Number.parseInt(\n $sortButton?.getAttribute('data-index') ?? '0',\n 10\n )\n\n if (\n !$heading ||\n !$sortButton ||\n !(sortDirection === 'ascending' || sortDirection === 'descending')\n ) {\n return\n }\n\n const $sortedRows = this.sort($rows, columnNumber, sortDirection)\n this.addRows($sortedRows)\n }\n\n /**\n * @param {MouseEvent} event - Click event\n */\n onSortButtonClick(event) {\n const $target = /** @type {HTMLElement} */ (event.target)\n const $button = $target.closest('button')\n\n if (\n !$button ||\n !($button instanceof HTMLButtonElement) ||\n !$button.parentElement\n ) {\n return\n }\n\n const $heading = $button.parentElement\n const sortDirection = $heading.getAttribute('aria-sort')\n\n const columnNumber = Number.parseInt(\n $button?.getAttribute('data-index') ?? '0',\n 10\n )\n\n const newSortDirection =\n sortDirection === 'none' || sortDirection === 'descending'\n ? 'ascending'\n : 'descending'\n\n const $rows = this.getTableRowsArray()\n const $sortedRows = this.sort($rows, columnNumber, newSortDirection)\n\n this.addRows($sortedRows)\n this.removeButtonStates()\n this.updateButtonState($button, newSortDirection)\n this.updateDirectionIndicators()\n }\n\n updateCaption() {\n if (!this.$caption) {\n return\n }\n\n let assistiveText = this.$caption.querySelector('.govuk-visually-hidden')\n if (assistiveText) {\n return\n }\n\n assistiveText = document.createElement('span')\n assistiveText.classList.add('govuk-visually-hidden')\n assistiveText.textContent = ' (column headers with buttons are sortable).'\n\n this.$caption.appendChild(assistiveText)\n }\n\n /**\n * @param {HTMLButtonElement} $button\n * @param {string} direction\n */\n updateButtonState($button, direction) {\n if (!(direction === 'ascending' || direction === 'descending')) {\n return\n }\n\n $button.parentElement.setAttribute('aria-sort', direction)\n let message = this.config.statusMessage\n message = message.replace(/%heading%/, $button.textContent)\n message = message.replace(/%direction%/, this.config[`${direction}Text`])\n this.$status.textContent = message\n }\n\n updateDirectionIndicators() {\n for (const $heading of this.$headings) {\n const $button = /** @type {HTMLButtonElement} */ (\n $heading.querySelector('button')\n )\n if ($heading.hasAttribute('aria-sort') && $button) {\n const direction = $heading.getAttribute('aria-sort')\n $button.querySelector('svg')?.remove()\n\n switch (direction) {\n case 'ascending':\n $button.insertAdjacentHTML('beforeend', this.$upArrow)\n break\n case 'descending':\n $button.insertAdjacentHTML('beforeend', this.$downArrow)\n break\n default:\n $button.insertAdjacentHTML('beforeend', this.$upDownArrow)\n }\n }\n }\n }\n\n removeButtonStates() {\n for (const $heading of this.$headings) {\n $heading.setAttribute('aria-sort', 'none')\n }\n }\n\n /**\n * @param {HTMLTableRowElement[]} $rows\n */\n addRows($rows) {\n for (const $row of $rows) {\n this.$body.append($row)\n }\n }\n\n getTableRowsArray() {\n return Array.from(this.$body.querySelectorAll('tr'))\n }\n\n /**\n * @param {HTMLTableRowElement[]} $rows\n * @param {number} columnNumber\n * @param {string} sortDirection\n */\n sort($rows, columnNumber, sortDirection) {\n return $rows.sort(($rowA, $rowB) => {\n const $tdA = $rowA.querySelectorAll('td, th')[columnNumber]\n const $tdB = $rowB.querySelectorAll('td, th')[columnNumber]\n\n if (\n !$tdA ||\n !$tdB ||\n !($tdA instanceof HTMLElement) ||\n !($tdB instanceof HTMLElement)\n ) {\n return 0\n }\n\n const valueA =\n sortDirection === 'ascending'\n ? this.getCellValue($tdA)\n : this.getCellValue($tdB)\n\n const valueB =\n sortDirection === 'ascending'\n ? this.getCellValue($tdB)\n : this.getCellValue($tdA)\n\n return !(typeof valueA === 'number' && typeof valueB === 'number')\n ? valueA.toString().localeCompare(valueB.toString())\n : valueA - valueB\n })\n }\n\n /**\n * @param {HTMLElement} $cell\n */\n getCellValue($cell) {\n const val = $cell.getAttribute('data-sort-value') || $cell.innerHTML\n const valAsNumber = Number(val)\n\n return Number.isFinite(valAsNumber)\n ? valAsNumber // Exclude invalid numbers, infinity etc\n : val\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-sortable-table'\n\n /**\n * Sortable table config\n *\n * @type {SortableTableConfig}\n */\n static defaults = Object.freeze({\n statusMessage: 'Sort by %heading% (%direction%)',\n ascendingText: 'ascending',\n descendingText: 'descending'\n })\n\n /**\n * Sortable table config schema\n *\n * @satisfies {Schema<SortableTableConfig>}\n */\n static schema = Object.freeze(\n /** @type {const} */ ({\n properties: {\n statusMessage: { type: 'string' },\n ascendingText: { type: 'string' },\n descendingText: { type: 'string' }\n }\n })\n )\n}\n\n/**\n * Sortable table config\n *\n * @typedef {object} SortableTableConfig\n * @property {string} [statusMessage] - Status message\n * @property {string} [ascendingText] - Ascending text\n * @property {string} [descendingText] - Descending text\n */\n\n/**\n * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'\n */\n"],"names":["SortableTable","ConfigurableComponent","constructor","$root","config","$head","querySelector","$body","$caption","$upArrow","$downArrow","$upDownArrow","$headings","Array","from","querySelectorAll","createHeadingButtons","updateCaption","updateDirectionIndicators","createStatusBox","initialiseSortedColumn","addEventListener","onSortButtonClick","bind","$heading","hasAttribute","createHeadingButton","index","indexOf","$button","document","createElement","setAttribute","textContent","appendChild","$status","insertAdjacentElement","_$sortButton$getAttri","$rows","getTableRowsArray","$sortButton","sortDirection","getAttribute","columnNumber","Number","parseInt","$sortedRows","sort","addRows","event","_$button$getAttribute","$target","target","closest","HTMLButtonElement","parentElement","newSortDirection","removeButtonStates","updateButtonState","assistiveText","classList","add","direction","message","statusMessage","replace","_$button$querySelecto","remove","insertAdjacentHTML","$row","append","$rowA","$rowB","$tdA","$tdB","HTMLElement","valueA","getCellValue","valueB","toString","localeCompare","$cell","val","innerHTML","valAsNumber","isFinite","moduleName","defaults","Object","freeze","ascendingText","descendingText","schema","properties","type"],"mappings":";;;;;;EAEA;EACA;EACA;EACO,MAAMA,aAAa,SAASC,mCAAqB,CAAC;EACvD;EACF;EACA;EACA;EACEC,EAAAA,WAAWA,CAACC,KAAK,EAAEC,MAAM,GAAG,EAAE,EAAE;EAC9B,IAAA,KAAK,CAACD,KAAK,EAAEC,MAAM,CAAC;MAEpB,MAAMC,KAAK,GAAGF,KAAK,IAAA,IAAA,GAAA,MAAA,GAALA,KAAK,CAAEG,aAAa,CAAC,OAAO,CAAC;MAC3C,MAAMC,KAAK,GAAGJ,KAAK,IAAA,IAAA,GAAA,MAAA,GAALA,KAAK,CAAEG,aAAa,CAAC,OAAO,CAAC;EAE3C,IAAA,IAAI,CAACD,KAAK,IAAI,CAACE,KAAK,EAAE;EACpB,MAAA,OAAO,IAAI;EACb;MAEA,IAAI,CAACF,KAAK,GAAGA,KAAK;MAClB,IAAI,CAACE,KAAK,GAAGA,KAAK;MAClB,IAAI,CAACC,QAAQ,GAAG,IAAI,CAACL,KAAK,CAACG,aAAa,CAAC,SAAS,CAAC;MAEnD,IAAI,CAACG,QAAQ,GAAG,CAAA;AACpB;AACA,MAAO,CAAA;MACH,IAAI,CAACC,UAAU,GAAG,CAAA;AACtB;AACA,MAAO,CAAA;MACH,IAAI,CAACC,YAAY,GAAG,CAAA;AACxB;AACA;AACA,MAAO,CAAA;MAEH,IAAI,CAACC,SAAS,GAAG,IAAI,CAACP,KAAK,GACvBQ,KAAK,CAACC,IAAI,CAAC,IAAI,CAACT,KAAK,CAACU,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAC7C,EAAE;MAEN,IAAI,CAACC,oBAAoB,EAAE;MAC3B,IAAI,CAACC,aAAa,EAAE;MACpB,IAAI,CAACC,yBAAyB,EAAE;MAChC,IAAI,CAACC,eAAe,EAAE;MACtB,IAAI,CAACC,sBAAsB,EAAE;EAE7B,IAAA,IAAI,CAACf,KAAK,CAACgB,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACC,iBAAiB,CAACC,IAAI,CAAC,IAAI,CAAC,CAAC;EACzE;EAEAP,EAAAA,oBAAoBA,GAAG;EACrB,IAAA,KAAK,MAAMQ,QAAQ,IAAI,IAAI,CAACZ,SAAS,EAAE;EACrC,MAAA,IAAIY,QAAQ,CAACC,YAAY,CAAC,WAAW,CAAC,EAAE;EACtC,QAAA,IAAI,CAACC,mBAAmB,CAACF,QAAQ,CAAC;EACpC;EACF;EACF;;EAEA;EACF;EACA;IACEE,mBAAmBA,CAACF,QAAQ,EAAE;MAC5B,MAAMG,KAAK,GAAG,IAAI,CAACf,SAAS,CAACgB,OAAO,CAACJ,QAAQ,CAAC;EAC9C,IAAA,MAAMK,OAAO,GAAGC,QAAQ,CAACC,aAAa,CAAC,QAAQ,CAAC;EAEhDF,IAAAA,OAAO,CAACG,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;MACtCH,OAAO,CAACG,YAAY,CAAC,YAAY,EAAE,CAAGL,EAAAA,KAAK,EAAE,CAAC;EAC9CE,IAAAA,OAAO,CAACI,WAAW,GAAGT,QAAQ,CAACS,WAAW;MAE1CT,QAAQ,CAACS,WAAW,GAAG,EAAE;EACzBT,IAAAA,QAAQ,CAACU,WAAW,CAACL,OAAO,CAAC;EAC/B;EAEAV,EAAAA,eAAeA,GAAG;MAChB,IAAI,CAACgB,OAAO,GAAGL,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;MAE5C,IAAI,CAACI,OAAO,CAACH,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC;MAChD,IAAI,CAACG,OAAO,CAACH,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC;MAChD,IAAI,CAACG,OAAO,CAACH,YAAY,CAAC,OAAO,EAAE,uBAAuB,CAAC;MAC3D,IAAI,CAACG,OAAO,CAACH,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;MAE3C,IAAI,CAAC7B,KAAK,CAACiC,qBAAqB,CAAC,UAAU,EAAE,IAAI,CAACD,OAAO,CAAC;EAC5D;EAEAf,EAAAA,sBAAsBA,GAAG;EAAA,IAAA,IAAAiB,qBAAA;EACvB,IAAA,MAAMC,KAAK,GAAG,IAAI,CAACC,iBAAiB,EAAE;MAEtC,MAAMf,QAAQ,GAAG,IAAI,CAACrB,KAAK,CAACG,aAAa,CACvC,uDACF,CAAC;MACD,MAAMkC,WAAW,GAAGhB,QAAQ,IAAA,IAAA,GAAA,MAAA,GAARA,QAAQ,CAAElB,aAAa,CAAC,QAAQ,CAAC;MACrD,MAAMmC,aAAa,GAAGjB,QAAQ,IAAA,IAAA,GAAA,MAAA,GAARA,QAAQ,CAAEkB,YAAY,CAAC,WAAW,CAAC;MAEzD,MAAMC,YAAY,GAAGC,MAAM,CAACC,QAAQ,CAAAR,CAAAA,qBAAA,GAClCG,WAAW,IAAXA,IAAAA,GAAAA,MAAAA,GAAAA,WAAW,CAAEE,YAAY,CAAC,YAAY,CAAC,KAAA,IAAA,GAAAL,qBAAA,GAAI,GAAG,EAC9C,EACF,CAAC;EAED,IAAA,IACE,CAACb,QAAQ,IACT,CAACgB,WAAW,IACZ,EAAEC,aAAa,KAAK,WAAW,IAAIA,aAAa,KAAK,YAAY,CAAC,EAClE;EACA,MAAA;EACF;MAEA,MAAMK,WAAW,GAAG,IAAI,CAACC,IAAI,CAACT,KAAK,EAAEK,YAAY,EAAEF,aAAa,CAAC;EACjE,IAAA,IAAI,CAACO,OAAO,CAACF,WAAW,CAAC;EAC3B;;EAEA;EACF;EACA;IACExB,iBAAiBA,CAAC2B,KAAK,EAAE;EAAA,IAAA,IAAAC,qBAAA;EACvB,IAAA,MAAMC,OAAO,6BAA+BF,KAAK,CAACG,MAAO;EACzD,IAAA,MAAMvB,OAAO,GAAGsB,OAAO,CAACE,OAAO,CAAC,QAAQ,CAAC;EAEzC,IAAA,IACE,CAACxB,OAAO,IACR,EAAEA,OAAO,YAAYyB,iBAAiB,CAAC,IACvC,CAACzB,OAAO,CAAC0B,aAAa,EACtB;EACA,MAAA;EACF;EAEA,IAAA,MAAM/B,QAAQ,GAAGK,OAAO,CAAC0B,aAAa;EACtC,IAAA,MAAMd,aAAa,GAAGjB,QAAQ,CAACkB,YAAY,CAAC,WAAW,CAAC;MAExD,MAAMC,YAAY,GAAGC,MAAM,CAACC,QAAQ,CAAAK,CAAAA,qBAAA,GAClCrB,OAAO,IAAPA,IAAAA,GAAAA,MAAAA,GAAAA,OAAO,CAAEa,YAAY,CAAC,YAAY,CAAC,KAAA,IAAA,GAAAQ,qBAAA,GAAI,GAAG,EAC1C,EACF,CAAC;EAED,IAAA,MAAMM,gBAAgB,GACpBf,aAAa,KAAK,MAAM,IAAIA,aAAa,KAAK,YAAY,GACtD,WAAW,GACX,YAAY;EAElB,IAAA,MAAMH,KAAK,GAAG,IAAI,CAACC,iBAAiB,EAAE;MACtC,MAAMO,WAAW,GAAG,IAAI,CAACC,IAAI,CAACT,KAAK,EAAEK,YAAY,EAAEa,gBAAgB,CAAC;EAEpE,IAAA,IAAI,CAACR,OAAO,CAACF,WAAW,CAAC;MACzB,IAAI,CAACW,kBAAkB,EAAE;EACzB,IAAA,IAAI,CAACC,iBAAiB,CAAC7B,OAAO,EAAE2B,gBAAgB,CAAC;MACjD,IAAI,CAACtC,yBAAyB,EAAE;EAClC;EAEAD,EAAAA,aAAaA,GAAG;EACd,IAAA,IAAI,CAAC,IAAI,CAACT,QAAQ,EAAE;EAClB,MAAA;EACF;MAEA,IAAImD,aAAa,GAAG,IAAI,CAACnD,QAAQ,CAACF,aAAa,CAAC,wBAAwB,CAAC;EACzE,IAAA,IAAIqD,aAAa,EAAE;EACjB,MAAA;EACF;EAEAA,IAAAA,aAAa,GAAG7B,QAAQ,CAACC,aAAa,CAAC,MAAM,CAAC;EAC9C4B,IAAAA,aAAa,CAACC,SAAS,CAACC,GAAG,CAAC,uBAAuB,CAAC;MACpDF,aAAa,CAAC1B,WAAW,GAAG,8CAA8C;EAE1E,IAAA,IAAI,CAACzB,QAAQ,CAAC0B,WAAW,CAACyB,aAAa,CAAC;EAC1C;;EAEA;EACF;EACA;EACA;EACED,EAAAA,iBAAiBA,CAAC7B,OAAO,EAAEiC,SAAS,EAAE;MACpC,IAAI,EAAEA,SAAS,KAAK,WAAW,IAAIA,SAAS,KAAK,YAAY,CAAC,EAAE;EAC9D,MAAA;EACF;MAEAjC,OAAO,CAAC0B,aAAa,CAACvB,YAAY,CAAC,WAAW,EAAE8B,SAAS,CAAC;EAC1D,IAAA,IAAIC,OAAO,GAAG,IAAI,CAAC3D,MAAM,CAAC4D,aAAa;MACvCD,OAAO,GAAGA,OAAO,CAACE,OAAO,CAAC,WAAW,EAAEpC,OAAO,CAACI,WAAW,CAAC;EAC3D8B,IAAAA,OAAO,GAAGA,OAAO,CAACE,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC7D,MAAM,CAAC,CAAA,EAAG0D,SAAS,CAAA,IAAA,CAAM,CAAC,CAAC;EACzE,IAAA,IAAI,CAAC3B,OAAO,CAACF,WAAW,GAAG8B,OAAO;EACpC;EAEA7C,EAAAA,yBAAyBA,GAAG;EAC1B,IAAA,KAAK,MAAMM,QAAQ,IAAI,IAAI,CAACZ,SAAS,EAAE;EACrC,MAAA,MAAMiB,OAAO;EACXL,MAAAA,QAAQ,CAAClB,aAAa,CAAC,QAAQ,CAChC;QACD,IAAIkB,QAAQ,CAACC,YAAY,CAAC,WAAW,CAAC,IAAII,OAAO,EAAE;EAAA,QAAA,IAAAqC,qBAAA;EACjD,QAAA,MAAMJ,SAAS,GAAGtC,QAAQ,CAACkB,YAAY,CAAC,WAAW,CAAC;EACpD,QAAA,CAAAwB,qBAAA,GAAArC,OAAO,CAACvB,aAAa,CAAC,KAAK,CAAC,KAA5B4D,IAAAA,IAAAA,qBAAA,CAA8BC,MAAM,EAAE;EAEtC,QAAA,QAAQL,SAAS;EACf,UAAA,KAAK,WAAW;cACdjC,OAAO,CAACuC,kBAAkB,CAAC,WAAW,EAAE,IAAI,CAAC3D,QAAQ,CAAC;EACtD,YAAA;EACF,UAAA,KAAK,YAAY;cACfoB,OAAO,CAACuC,kBAAkB,CAAC,WAAW,EAAE,IAAI,CAAC1D,UAAU,CAAC;EACxD,YAAA;EACF,UAAA;cACEmB,OAAO,CAACuC,kBAAkB,CAAC,WAAW,EAAE,IAAI,CAACzD,YAAY,CAAC;EAC9D;EACF;EACF;EACF;EAEA8C,EAAAA,kBAAkBA,GAAG;EACnB,IAAA,KAAK,MAAMjC,QAAQ,IAAI,IAAI,CAACZ,SAAS,EAAE;EACrCY,MAAAA,QAAQ,CAACQ,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC;EAC5C;EACF;;EAEA;EACF;EACA;IACEgB,OAAOA,CAACV,KAAK,EAAE;EACb,IAAA,KAAK,MAAM+B,IAAI,IAAI/B,KAAK,EAAE;EACxB,MAAA,IAAI,CAAC/B,KAAK,CAAC+D,MAAM,CAACD,IAAI,CAAC;EACzB;EACF;EAEA9B,EAAAA,iBAAiBA,GAAG;EAClB,IAAA,OAAO1B,KAAK,CAACC,IAAI,CAAC,IAAI,CAACP,KAAK,CAACQ,gBAAgB,CAAC,IAAI,CAAC,CAAC;EACtD;;EAEA;EACF;EACA;EACA;EACA;EACEgC,EAAAA,IAAIA,CAACT,KAAK,EAAEK,YAAY,EAAEF,aAAa,EAAE;MACvC,OAAOH,KAAK,CAACS,IAAI,CAAC,CAACwB,KAAK,EAAEC,KAAK,KAAK;QAClC,MAAMC,IAAI,GAAGF,KAAK,CAACxD,gBAAgB,CAAC,QAAQ,CAAC,CAAC4B,YAAY,CAAC;QAC3D,MAAM+B,IAAI,GAAGF,KAAK,CAACzD,gBAAgB,CAAC,QAAQ,CAAC,CAAC4B,YAAY,CAAC;EAE3D,MAAA,IACE,CAAC8B,IAAI,IACL,CAACC,IAAI,IACL,EAAED,IAAI,YAAYE,WAAW,CAAC,IAC9B,EAAED,IAAI,YAAYC,WAAW,CAAC,EAC9B;EACA,QAAA,OAAO,CAAC;EACV;EAEA,MAAA,MAAMC,MAAM,GACVnC,aAAa,KAAK,WAAW,GACzB,IAAI,CAACoC,YAAY,CAACJ,IAAI,CAAC,GACvB,IAAI,CAACI,YAAY,CAACH,IAAI,CAAC;EAE7B,MAAA,MAAMI,MAAM,GACVrC,aAAa,KAAK,WAAW,GACzB,IAAI,CAACoC,YAAY,CAACH,IAAI,CAAC,GACvB,IAAI,CAACG,YAAY,CAACJ,IAAI,CAAC;EAE7B,MAAA,OAAO,EAAE,OAAOG,MAAM,KAAK,QAAQ,IAAI,OAAOE,MAAM,KAAK,QAAQ,CAAC,GAC9DF,MAAM,CAACG,QAAQ,EAAE,CAACC,aAAa,CAACF,MAAM,CAACC,QAAQ,EAAE,CAAC,GAClDH,MAAM,GAAGE,MAAM;EACrB,KAAC,CAAC;EACJ;;EAEA;EACF;EACA;IACED,YAAYA,CAACI,KAAK,EAAE;MAClB,MAAMC,GAAG,GAAGD,KAAK,CAACvC,YAAY,CAAC,iBAAiB,CAAC,IAAIuC,KAAK,CAACE,SAAS;EACpE,IAAA,MAAMC,WAAW,GAAGxC,MAAM,CAACsC,GAAG,CAAC;MAE/B,OAAOtC,MAAM,CAACyC,QAAQ,CAACD,WAAW,CAAC,GAC/BA,WAAW;EAAC,MACZF,GAAG;EACT;;EAEA;EACF;EACA;EA4BA;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;EAjTalF,aAAa,CAyQjBsF,UAAU,GAAG,oBAAoB;EAExC;EACF;EACA;EACA;EACA;EA/QatF,aAAa,CAgRjBuF,QAAQ,GAAGC,MAAM,CAACC,MAAM,CAAC;EAC9BzB,EAAAA,aAAa,EAAE,iCAAiC;EAChD0B,EAAAA,aAAa,EAAE,WAAW;EAC1BC,EAAAA,cAAc,EAAE;EAClB,CAAC,CAAC;EAEF;EACF;EACA;EACA;EACA;EA1Ra3F,aAAa,CA2RjB4F,MAAM,GAAGJ,MAAM,CAACC,MAAM,qBACL;EACpBI,EAAAA,UAAU,EAAE;EACV7B,IAAAA,aAAa,EAAE;EAAE8B,MAAAA,IAAI,EAAE;OAAU;EACjCJ,IAAAA,aAAa,EAAE;EAAEI,MAAAA,IAAI,EAAE;OAAU;EACjCH,IAAAA,cAAc,EAAE;EAAEG,MAAAA,IAAI,EAAE;EAAS;EACnC;EACF,CACF,CAAC;;;;;;;;"}
@@ -259,8 +259,21 @@ class SortableTable extends ConfigurableComponent {
259
259
  }
260
260
  this.$head = $head;
261
261
  this.$body = $body;
262
+ this.$caption = this.$root.querySelector('caption');
263
+ 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">
264
+ <path d="M6.5625 15.5L11 6.63125L15.4375 15.5H6.5625Z" fill="currentColor"/>
265
+ </svg>`;
266
+ 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">
267
+ <path d="M15.4375 7L11 15.8687L6.5625 7L15.4375 7Z" fill="currentColor"/>
268
+ </svg>`;
269
+ 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">
270
+ <path d="M8.1875 9.5L10.9609 3.95703L13.7344 9.5H8.1875Z" fill="currentColor"/>
271
+ <path d="M13.7344 12.0781L10.9609 17.6211L8.1875 12.0781H13.7344Z" fill="currentColor"/>
272
+ </svg>`;
262
273
  this.$headings = this.$head ? Array.from(this.$head.querySelectorAll('th')) : [];
263
274
  this.createHeadingButtons();
275
+ this.updateCaption();
276
+ this.updateDirectionIndicators();
264
277
  this.createStatusBox();
265
278
  this.initialiseSortedColumn();
266
279
  this.$head.addEventListener('click', this.onSortButtonClick.bind(this));
@@ -296,7 +309,7 @@ class SortableTable extends ConfigurableComponent {
296
309
  initialiseSortedColumn() {
297
310
  var _$sortButton$getAttri;
298
311
  const $rows = this.getTableRowsArray();
299
- const $heading = this.$root.querySelector('th[aria-sort]');
312
+ const $heading = this.$root.querySelector('th[aria-sort="ascending"], th[aria-sort="descending"]');
300
313
  const $sortButton = $heading == null ? void 0 : $heading.querySelector('button');
301
314
  const sortDirection = $heading == null ? void 0 : $heading.getAttribute('aria-sort');
302
315
  const columnNumber = Number.parseInt((_$sortButton$getAttri = $sortButton == null ? void 0 : $sortButton.getAttribute('data-index')) != null ? _$sortButton$getAttri : '0', 10);
@@ -312,7 +325,8 @@ class SortableTable extends ConfigurableComponent {
312
325
  */
313
326
  onSortButtonClick(event) {
314
327
  var _$button$getAttribute;
315
- const $button = event.target;
328
+ const $target = /** @type {HTMLElement} */event.target;
329
+ const $button = $target.closest('button');
316
330
  if (!$button || !($button instanceof HTMLButtonElement) || !$button.parentElement) {
317
331
  return;
318
332
  }
@@ -325,6 +339,20 @@ class SortableTable extends ConfigurableComponent {
325
339
  this.addRows($sortedRows);
326
340
  this.removeButtonStates();
327
341
  this.updateButtonState($button, newSortDirection);
342
+ this.updateDirectionIndicators();
343
+ }
344
+ updateCaption() {
345
+ if (!this.$caption) {
346
+ return;
347
+ }
348
+ let assistiveText = this.$caption.querySelector('.govuk-visually-hidden');
349
+ if (assistiveText) {
350
+ return;
351
+ }
352
+ assistiveText = document.createElement('span');
353
+ assistiveText.classList.add('govuk-visually-hidden');
354
+ assistiveText.textContent = ' (column headers with buttons are sortable).';
355
+ this.$caption.appendChild(assistiveText);
328
356
  }
329
357
 
330
358
  /**
@@ -341,6 +369,27 @@ class SortableTable extends ConfigurableComponent {
341
369
  message = message.replace(/%direction%/, this.config[`${direction}Text`]);
342
370
  this.$status.textContent = message;
343
371
  }
372
+ updateDirectionIndicators() {
373
+ for (const $heading of this.$headings) {
374
+ const $button = /** @type {HTMLButtonElement} */
375
+ $heading.querySelector('button');
376
+ if ($heading.hasAttribute('aria-sort') && $button) {
377
+ var _$button$querySelecto;
378
+ const direction = $heading.getAttribute('aria-sort');
379
+ (_$button$querySelecto = $button.querySelector('svg')) == null || _$button$querySelecto.remove();
380
+ switch (direction) {
381
+ case 'ascending':
382
+ $button.insertAdjacentHTML('beforeend', this.$upArrow);
383
+ break;
384
+ case 'descending':
385
+ $button.insertAdjacentHTML('beforeend', this.$downArrow);
386
+ break;
387
+ default:
388
+ $button.insertAdjacentHTML('beforeend', this.$upDownArrow);
389
+ }
390
+ }
391
+ }
392
+ }
344
393
  removeButtonStates() {
345
394
  for (const $heading of this.$headings) {
346
395
  $heading.setAttribute('aria-sort', 'none');
@@ -1 +1 @@
1
- {"version":3,"file":"sortable-table.bundle.mjs","sources":["../../../../node_modules/govuk-frontend/dist/govuk/common/index.mjs","../../../../node_modules/govuk-frontend/dist/govuk/errors/index.mjs","../../../../node_modules/govuk-frontend/dist/govuk/component.mjs","../../../../node_modules/govuk-frontend/dist/govuk/common/configuration.mjs","../../../../src/moj/components/sortable-table/sortable-table.mjs"],"sourcesContent":["function getFragmentFromUrl(url) {\n if (!url.includes('#')) {\n return undefined;\n }\n return url.split('#').pop();\n}\nfunction getBreakpoint(name) {\n const property = `--govuk-frontend-breakpoint-${name}`;\n const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);\n return {\n property,\n value: value || undefined\n };\n}\nfunction setFocus($element, options = {}) {\n var _options$onBeforeFocu;\n const isFocusable = $element.getAttribute('tabindex');\n if (!isFocusable) {\n $element.setAttribute('tabindex', '-1');\n }\n function onFocus() {\n $element.addEventListener('blur', onBlur, {\n once: true\n });\n }\n function onBlur() {\n var _options$onBlur;\n (_options$onBlur = options.onBlur) == null || _options$onBlur.call($element);\n if (!isFocusable) {\n $element.removeAttribute('tabindex');\n }\n }\n $element.addEventListener('focus', onFocus, {\n once: true\n });\n (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);\n $element.focus();\n}\nfunction isInitialised($root, moduleName) {\n return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);\n}\n\n/**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * Some browsers will load and run our JavaScript but GOV.UK Frontend\n * won't be supported.\n *\n * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support\n * @returns {boolean} Whether GOV.UK Frontend is supported on this page\n */\nfunction isSupported($scope = document.body) {\n if (!$scope) {\n return false;\n }\n return $scope.classList.contains('govuk-frontend-supported');\n}\nfunction isArray(option) {\n return Array.isArray(option);\n}\nfunction isObject(option) {\n return !!option && typeof option === 'object' && !isArray(option);\n}\nfunction formatErrorMessage(Component, message) {\n return `${Component.moduleName}: ${message}`;\n}\n/**\n * @typedef ComponentWithModuleName\n * @property {string} moduleName - Name of the component\n */\n/**\n * @import { ObjectNested } from './configuration.mjs'\n */\n\nexport { formatErrorMessage, getBreakpoint, getFragmentFromUrl, isInitialised, isObject, isSupported, setFocus };\n//# sourceMappingURL=index.mjs.map\n","import { formatErrorMessage } from '../common/index.mjs';\n\nclass GOVUKFrontendError extends Error {\n constructor(...args) {\n super(...args);\n this.name = 'GOVUKFrontendError';\n }\n}\nclass SupportError extends GOVUKFrontendError {\n /**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support\n */\n constructor($scope = document.body) {\n const supportMessage = 'noModule' in HTMLScriptElement.prototype ? 'GOV.UK Frontend initialised without `<body class=\"govuk-frontend-supported\">` from template `<script>` snippet' : 'GOV.UK Frontend is not supported in this browser';\n super($scope ? supportMessage : 'GOV.UK Frontend initialised without `<script type=\"module\">`');\n this.name = 'SupportError';\n }\n}\nclass ConfigError extends GOVUKFrontendError {\n constructor(...args) {\n super(...args);\n this.name = 'ConfigError';\n }\n}\nclass ElementError extends GOVUKFrontendError {\n constructor(messageOrOptions) {\n let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';\n if (typeof messageOrOptions === 'object') {\n const {\n component,\n identifier,\n element,\n expectedType\n } = messageOrOptions;\n message = identifier;\n message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';\n message = formatErrorMessage(component, message);\n }\n super(message);\n this.name = 'ElementError';\n }\n}\nclass InitError extends GOVUKFrontendError {\n constructor(componentOrMessage) {\n const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\\`$root\\`) already initialised`);\n super(message);\n this.name = 'InitError';\n }\n}\n/**\n * @import { ComponentWithModuleName } from '../common/index.mjs'\n */\n\nexport { ConfigError, ElementError, GOVUKFrontendError, InitError, SupportError };\n//# sourceMappingURL=index.mjs.map\n","import { isInitialised, isSupported } from './common/index.mjs';\nimport { InitError, ElementError, SupportError } from './errors/index.mjs';\n\nclass Component {\n /**\n * Returns the root element of the component\n *\n * @protected\n * @returns {RootElementType} - the root element of component\n */\n get $root() {\n return this._$root;\n }\n constructor($root) {\n this._$root = void 0;\n const childConstructor = this.constructor;\n if (typeof childConstructor.moduleName !== 'string') {\n throw new InitError(`\\`moduleName\\` not defined in component`);\n }\n if (!($root instanceof childConstructor.elementType)) {\n throw new ElementError({\n element: $root,\n component: childConstructor,\n identifier: 'Root element (`$root`)',\n expectedType: childConstructor.elementType.name\n });\n } else {\n this._$root = $root;\n }\n childConstructor.checkSupport();\n this.checkInitialised();\n const moduleName = childConstructor.moduleName;\n this.$root.setAttribute(`data-${moduleName}-init`, '');\n }\n checkInitialised() {\n const constructor = this.constructor;\n const moduleName = constructor.moduleName;\n if (moduleName && isInitialised(this.$root, moduleName)) {\n throw new InitError(constructor);\n }\n }\n static checkSupport() {\n if (!isSupported()) {\n throw new SupportError();\n }\n }\n}\n\n/**\n * @typedef ChildClass\n * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component\n */\n\n/**\n * @typedef {typeof Component & ChildClass} ChildClassConstructor\n */\nComponent.elementType = HTMLElement;\n\nexport { Component };\n//# sourceMappingURL=component.mjs.map\n","import { Component } from '../component.mjs';\nimport { ConfigError } from '../errors/index.mjs';\nimport { isObject, formatErrorMessage } from './index.mjs';\n\nconst configOverride = Symbol.for('configOverride');\nclass ConfigurableComponent extends Component {\n [configOverride](param) {\n return {};\n }\n\n /**\n * Returns the root element of the component\n *\n * @protected\n * @returns {ConfigurationType} - the root element of component\n */\n get config() {\n return this._config;\n }\n constructor($root, config) {\n super($root);\n this._config = void 0;\n const childConstructor = this.constructor;\n if (!isObject(childConstructor.defaults)) {\n throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));\n }\n const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);\n this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);\n }\n}\nfunction normaliseString(value, property) {\n const trimmedValue = value ? value.trim() : '';\n let output;\n let outputType = property == null ? void 0 : property.type;\n if (!outputType) {\n if (['true', 'false'].includes(trimmedValue)) {\n outputType = 'boolean';\n }\n if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {\n outputType = 'number';\n }\n }\n switch (outputType) {\n case 'boolean':\n output = trimmedValue === 'true';\n break;\n case 'number':\n output = Number(trimmedValue);\n break;\n default:\n output = value;\n }\n return output;\n}\nfunction normaliseDataset(Component, dataset) {\n if (!isObject(Component.schema)) {\n throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));\n }\n const out = {};\n const entries = Object.entries(Component.schema.properties);\n for (const entry of entries) {\n const [namespace, property] = entry;\n const field = namespace.toString();\n if (field in dataset) {\n out[field] = normaliseString(dataset[field], property);\n }\n if ((property == null ? void 0 : property.type) === 'object') {\n out[field] = extractConfigByNamespace(Component.schema, dataset, namespace);\n }\n }\n return out;\n}\nfunction mergeConfigs(...configObjects) {\n const formattedConfigObject = {};\n for (const configObject of configObjects) {\n for (const key of Object.keys(configObject)) {\n const option = formattedConfigObject[key];\n const override = configObject[key];\n if (isObject(option) && isObject(override)) {\n formattedConfigObject[key] = mergeConfigs(option, override);\n } else {\n formattedConfigObject[key] = override;\n }\n }\n }\n return formattedConfigObject;\n}\nfunction validateConfig(schema, config) {\n const validationErrors = [];\n for (const [name, conditions] of Object.entries(schema)) {\n const errors = [];\n if (Array.isArray(conditions)) {\n for (const {\n required,\n errorMessage\n } of conditions) {\n if (!required.every(key => !!config[key])) {\n errors.push(errorMessage);\n }\n }\n if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {\n validationErrors.push(...errors);\n }\n }\n }\n return validationErrors;\n}\nfunction extractConfigByNamespace(schema, dataset, namespace) {\n const property = schema.properties[namespace];\n if ((property == null ? void 0 : property.type) !== 'object') {\n return;\n }\n const newObject = {\n [namespace]: {}\n };\n for (const [key, value] of Object.entries(dataset)) {\n let current = newObject;\n const keyParts = key.split('.');\n for (const [index, name] of keyParts.entries()) {\n if (isObject(current)) {\n if (index < keyParts.length - 1) {\n if (!isObject(current[name])) {\n current[name] = {};\n }\n current = current[name];\n } else if (key !== namespace) {\n current[name] = normaliseString(value);\n }\n }\n }\n }\n return newObject[namespace];\n}\n/**\n * Schema for component config\n *\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType\n * @typedef {object} Schema\n * @property {Record<keyof ConfigurationType, SchemaProperty | undefined>} properties - Schema properties\n * @property {SchemaCondition<ConfigurationType>[]} [anyOf] - List of schema conditions\n */\n/**\n * Schema property for component config\n *\n * @typedef {object} SchemaProperty\n * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type\n */\n/**\n * Schema condition for component config\n *\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType\n * @typedef {object} SchemaCondition\n * @property {(keyof ConfigurationType)[]} required - List of required config fields\n * @property {string} errorMessage - Error message when required config fields not provided\n */\n/**\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]\n * @typedef ChildClass\n * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component\n * @property {Schema<ConfigurationType>} [schema] - The schema of the component configuration\n * @property {ConfigurationType} [defaults] - The default values of the configuration of the component\n */\n/**\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]\n * @typedef {typeof Component & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>\n */\n\nexport { ConfigurableComponent, configOverride, extractConfigByNamespace, mergeConfigs, normaliseDataset, normaliseString, validateConfig };\n//# sourceMappingURL=configuration.mjs.map\n","import { ConfigurableComponent } from 'govuk-frontend'\n\n/**\n * @augments {ConfigurableComponent<SortableTableConfig>}\n */\nexport class SortableTable extends ConfigurableComponent {\n /**\n * @param {Element | null} $root - HTML element to use for sortable table\n * @param {SortableTableConfig} [config] - Sortable table config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $head = $root?.querySelector('thead')\n const $body = $root?.querySelector('tbody')\n\n if (!$head || !$body) {\n return this\n }\n\n this.$head = $head\n this.$body = $body\n\n this.$headings = this.$head\n ? Array.from(this.$head.querySelectorAll('th'))\n : []\n\n this.createHeadingButtons()\n this.createStatusBox()\n this.initialiseSortedColumn()\n\n this.$head.addEventListener('click', this.onSortButtonClick.bind(this))\n }\n\n createHeadingButtons() {\n for (const $heading of this.$headings) {\n if ($heading.hasAttribute('aria-sort')) {\n this.createHeadingButton($heading)\n }\n }\n }\n\n /**\n * @param {HTMLTableCellElement} $heading\n */\n createHeadingButton($heading) {\n const index = this.$headings.indexOf($heading)\n const $button = document.createElement('button')\n\n $button.setAttribute('type', 'button')\n $button.setAttribute('data-index', `${index}`)\n $button.textContent = $heading.textContent\n\n $heading.textContent = ''\n $heading.appendChild($button)\n }\n\n createStatusBox() {\n this.$status = document.createElement('div')\n\n this.$status.setAttribute('aria-atomic', 'true')\n this.$status.setAttribute('aria-live', 'polite')\n this.$status.setAttribute('class', 'govuk-visually-hidden')\n this.$status.setAttribute('role', 'status')\n\n this.$root.insertAdjacentElement('afterend', this.$status)\n }\n\n initialiseSortedColumn() {\n const $rows = this.getTableRowsArray()\n\n const $heading = this.$root.querySelector('th[aria-sort]')\n const $sortButton = $heading?.querySelector('button')\n const sortDirection = $heading?.getAttribute('aria-sort')\n\n const columnNumber = Number.parseInt(\n $sortButton?.getAttribute('data-index') ?? '0',\n 10\n )\n\n if (\n !$heading ||\n !$sortButton ||\n !(sortDirection === 'ascending' || sortDirection === 'descending')\n ) {\n return\n }\n\n const $sortedRows = this.sort($rows, columnNumber, sortDirection)\n this.addRows($sortedRows)\n }\n\n /**\n * @param {MouseEvent} event - Click event\n */\n onSortButtonClick(event) {\n const $button = event.target\n\n if (\n !$button ||\n !($button instanceof HTMLButtonElement) ||\n !$button.parentElement\n ) {\n return\n }\n\n const $heading = $button.parentElement\n const sortDirection = $heading.getAttribute('aria-sort')\n\n const columnNumber = Number.parseInt(\n $button?.getAttribute('data-index') ?? '0',\n 10\n )\n\n const newSortDirection =\n sortDirection === 'none' || sortDirection === 'descending'\n ? 'ascending'\n : 'descending'\n\n const $rows = this.getTableRowsArray()\n const $sortedRows = this.sort($rows, columnNumber, newSortDirection)\n\n this.addRows($sortedRows)\n this.removeButtonStates()\n this.updateButtonState($button, newSortDirection)\n }\n\n /**\n * @param {HTMLButtonElement} $button\n * @param {string} direction\n */\n updateButtonState($button, direction) {\n if (!(direction === 'ascending' || direction === 'descending')) {\n return\n }\n\n $button.parentElement.setAttribute('aria-sort', direction)\n let message = this.config.statusMessage\n message = message.replace(/%heading%/, $button.textContent)\n message = message.replace(/%direction%/, this.config[`${direction}Text`])\n this.$status.textContent = message\n }\n\n removeButtonStates() {\n for (const $heading of this.$headings) {\n $heading.setAttribute('aria-sort', 'none')\n }\n }\n\n /**\n * @param {HTMLTableRowElement[]} $rows\n */\n addRows($rows) {\n for (const $row of $rows) {\n this.$body.append($row)\n }\n }\n\n getTableRowsArray() {\n return Array.from(this.$body.querySelectorAll('tr'))\n }\n\n /**\n * @param {HTMLTableRowElement[]} $rows\n * @param {number} columnNumber\n * @param {string} sortDirection\n */\n sort($rows, columnNumber, sortDirection) {\n return $rows.sort(($rowA, $rowB) => {\n const $tdA = $rowA.querySelectorAll('td, th')[columnNumber]\n const $tdB = $rowB.querySelectorAll('td, th')[columnNumber]\n\n if (\n !$tdA ||\n !$tdB ||\n !($tdA instanceof HTMLElement) ||\n !($tdB instanceof HTMLElement)\n ) {\n return 0\n }\n\n const valueA =\n sortDirection === 'ascending'\n ? this.getCellValue($tdA)\n : this.getCellValue($tdB)\n\n const valueB =\n sortDirection === 'ascending'\n ? this.getCellValue($tdB)\n : this.getCellValue($tdA)\n\n return !(typeof valueA === 'number' && typeof valueB === 'number')\n ? valueA.toString().localeCompare(valueB.toString())\n : valueA - valueB\n })\n }\n\n /**\n * @param {HTMLElement} $cell\n */\n getCellValue($cell) {\n const val = $cell.getAttribute('data-sort-value') || $cell.innerHTML\n const valAsNumber = Number(val)\n\n return Number.isFinite(valAsNumber)\n ? valAsNumber // Exclude invalid numbers, infinity etc\n : val\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-sortable-table'\n\n /**\n * Sortable table config\n *\n * @type {SortableTableConfig}\n */\n static defaults = Object.freeze({\n statusMessage: 'Sort by %heading% (%direction%)',\n ascendingText: 'ascending',\n descendingText: 'descending'\n })\n\n /**\n * Sortable table config schema\n *\n * @satisfies {Schema<SortableTableConfig>}\n */\n static schema = Object.freeze(\n /** @type {const} */ ({\n properties: {\n statusMessage: { type: 'string' },\n ascendingText: { type: 'string' },\n descendingText: { type: 'string' }\n }\n })\n )\n}\n\n/**\n * Sortable table config\n *\n * @typedef {object} SortableTableConfig\n * @property {string} [statusMessage] - Status message\n * @property {string} [ascendingText] - Ascending text\n * @property {string} [descendingText] - Descending text\n */\n\n/**\n * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'\n */\n"],"names":["isInitialised","$root","moduleName","HTMLElement","hasAttribute","isSupported","$scope","document","body","classList","contains","isArray","option","Array","isObject","formatErrorMessage","Component","message","GOVUKFrontendError","Error","constructor","args","name","SupportError","supportMessage","HTMLScriptElement","prototype","ConfigError","ElementError","messageOrOptions","component","identifier","element","expectedType","InitError","componentOrMessage","_$root","childConstructor","elementType","checkSupport","checkInitialised","setAttribute","configOverride","Symbol","for","ConfigurableComponent","param","config","_config","defaults","datasetConfig","normaliseDataset","dataset","mergeConfigs","normaliseString","value","property","trimmedValue","trim","output","outputType","type","includes","length","isFinite","Number","schema","out","entries","Object","properties","entry","namespace","field","toString","extractConfigByNamespace","configObjects","formattedConfigObject","configObject","key","keys","override","newObject","current","keyParts","split","index","SortableTable","$head","querySelector","$body","$headings","from","querySelectorAll","createHeadingButtons","createStatusBox","initialiseSortedColumn","addEventListener","onSortButtonClick","bind","$heading","createHeadingButton","indexOf","$button","createElement","textContent","appendChild","$status","insertAdjacentElement","_$sortButton$getAttri","$rows","getTableRowsArray","$sortButton","sortDirection","getAttribute","columnNumber","parseInt","$sortedRows","sort","addRows","event","_$button$getAttribute","target","HTMLButtonElement","parentElement","newSortDirection","removeButtonStates","updateButtonState","direction","statusMessage","replace","$row","append","$rowA","$rowB","$tdA","$tdB","valueA","getCellValue","valueB","localeCompare","$cell","val","innerHTML","valAsNumber","freeze","ascendingText","descendingText"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}
1
+ {"version":3,"file":"sortable-table.bundle.mjs","sources":["../../../../node_modules/govuk-frontend/dist/govuk/common/index.mjs","../../../../node_modules/govuk-frontend/dist/govuk/errors/index.mjs","../../../../node_modules/govuk-frontend/dist/govuk/component.mjs","../../../../node_modules/govuk-frontend/dist/govuk/common/configuration.mjs","../../../../src/moj/components/sortable-table/sortable-table.mjs"],"sourcesContent":["function getFragmentFromUrl(url) {\n if (!url.includes('#')) {\n return undefined;\n }\n return url.split('#').pop();\n}\nfunction getBreakpoint(name) {\n const property = `--govuk-frontend-breakpoint-${name}`;\n const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);\n return {\n property,\n value: value || undefined\n };\n}\nfunction setFocus($element, options = {}) {\n var _options$onBeforeFocu;\n const isFocusable = $element.getAttribute('tabindex');\n if (!isFocusable) {\n $element.setAttribute('tabindex', '-1');\n }\n function onFocus() {\n $element.addEventListener('blur', onBlur, {\n once: true\n });\n }\n function onBlur() {\n var _options$onBlur;\n (_options$onBlur = options.onBlur) == null || _options$onBlur.call($element);\n if (!isFocusable) {\n $element.removeAttribute('tabindex');\n }\n }\n $element.addEventListener('focus', onFocus, {\n once: true\n });\n (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);\n $element.focus();\n}\nfunction isInitialised($root, moduleName) {\n return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);\n}\n\n/**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * Some browsers will load and run our JavaScript but GOV.UK Frontend\n * won't be supported.\n *\n * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support\n * @returns {boolean} Whether GOV.UK Frontend is supported on this page\n */\nfunction isSupported($scope = document.body) {\n if (!$scope) {\n return false;\n }\n return $scope.classList.contains('govuk-frontend-supported');\n}\nfunction isArray(option) {\n return Array.isArray(option);\n}\nfunction isObject(option) {\n return !!option && typeof option === 'object' && !isArray(option);\n}\nfunction formatErrorMessage(Component, message) {\n return `${Component.moduleName}: ${message}`;\n}\n/**\n * @typedef ComponentWithModuleName\n * @property {string} moduleName - Name of the component\n */\n/**\n * @import { ObjectNested } from './configuration.mjs'\n */\n\nexport { formatErrorMessage, getBreakpoint, getFragmentFromUrl, isInitialised, isObject, isSupported, setFocus };\n//# sourceMappingURL=index.mjs.map\n","import { formatErrorMessage } from '../common/index.mjs';\n\nclass GOVUKFrontendError extends Error {\n constructor(...args) {\n super(...args);\n this.name = 'GOVUKFrontendError';\n }\n}\nclass SupportError extends GOVUKFrontendError {\n /**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support\n */\n constructor($scope = document.body) {\n const supportMessage = 'noModule' in HTMLScriptElement.prototype ? 'GOV.UK Frontend initialised without `<body class=\"govuk-frontend-supported\">` from template `<script>` snippet' : 'GOV.UK Frontend is not supported in this browser';\n super($scope ? supportMessage : 'GOV.UK Frontend initialised without `<script type=\"module\">`');\n this.name = 'SupportError';\n }\n}\nclass ConfigError extends GOVUKFrontendError {\n constructor(...args) {\n super(...args);\n this.name = 'ConfigError';\n }\n}\nclass ElementError extends GOVUKFrontendError {\n constructor(messageOrOptions) {\n let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';\n if (typeof messageOrOptions === 'object') {\n const {\n component,\n identifier,\n element,\n expectedType\n } = messageOrOptions;\n message = identifier;\n message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';\n message = formatErrorMessage(component, message);\n }\n super(message);\n this.name = 'ElementError';\n }\n}\nclass InitError extends GOVUKFrontendError {\n constructor(componentOrMessage) {\n const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\\`$root\\`) already initialised`);\n super(message);\n this.name = 'InitError';\n }\n}\n/**\n * @import { ComponentWithModuleName } from '../common/index.mjs'\n */\n\nexport { ConfigError, ElementError, GOVUKFrontendError, InitError, SupportError };\n//# sourceMappingURL=index.mjs.map\n","import { isInitialised, isSupported } from './common/index.mjs';\nimport { InitError, ElementError, SupportError } from './errors/index.mjs';\n\nclass Component {\n /**\n * Returns the root element of the component\n *\n * @protected\n * @returns {RootElementType} - the root element of component\n */\n get $root() {\n return this._$root;\n }\n constructor($root) {\n this._$root = void 0;\n const childConstructor = this.constructor;\n if (typeof childConstructor.moduleName !== 'string') {\n throw new InitError(`\\`moduleName\\` not defined in component`);\n }\n if (!($root instanceof childConstructor.elementType)) {\n throw new ElementError({\n element: $root,\n component: childConstructor,\n identifier: 'Root element (`$root`)',\n expectedType: childConstructor.elementType.name\n });\n } else {\n this._$root = $root;\n }\n childConstructor.checkSupport();\n this.checkInitialised();\n const moduleName = childConstructor.moduleName;\n this.$root.setAttribute(`data-${moduleName}-init`, '');\n }\n checkInitialised() {\n const constructor = this.constructor;\n const moduleName = constructor.moduleName;\n if (moduleName && isInitialised(this.$root, moduleName)) {\n throw new InitError(constructor);\n }\n }\n static checkSupport() {\n if (!isSupported()) {\n throw new SupportError();\n }\n }\n}\n\n/**\n * @typedef ChildClass\n * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component\n */\n\n/**\n * @typedef {typeof Component & ChildClass} ChildClassConstructor\n */\nComponent.elementType = HTMLElement;\n\nexport { Component };\n//# sourceMappingURL=component.mjs.map\n","import { Component } from '../component.mjs';\nimport { ConfigError } from '../errors/index.mjs';\nimport { isObject, formatErrorMessage } from './index.mjs';\n\nconst configOverride = Symbol.for('configOverride');\nclass ConfigurableComponent extends Component {\n [configOverride](param) {\n return {};\n }\n\n /**\n * Returns the root element of the component\n *\n * @protected\n * @returns {ConfigurationType} - the root element of component\n */\n get config() {\n return this._config;\n }\n constructor($root, config) {\n super($root);\n this._config = void 0;\n const childConstructor = this.constructor;\n if (!isObject(childConstructor.defaults)) {\n throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));\n }\n const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);\n this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);\n }\n}\nfunction normaliseString(value, property) {\n const trimmedValue = value ? value.trim() : '';\n let output;\n let outputType = property == null ? void 0 : property.type;\n if (!outputType) {\n if (['true', 'false'].includes(trimmedValue)) {\n outputType = 'boolean';\n }\n if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {\n outputType = 'number';\n }\n }\n switch (outputType) {\n case 'boolean':\n output = trimmedValue === 'true';\n break;\n case 'number':\n output = Number(trimmedValue);\n break;\n default:\n output = value;\n }\n return output;\n}\nfunction normaliseDataset(Component, dataset) {\n if (!isObject(Component.schema)) {\n throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));\n }\n const out = {};\n const entries = Object.entries(Component.schema.properties);\n for (const entry of entries) {\n const [namespace, property] = entry;\n const field = namespace.toString();\n if (field in dataset) {\n out[field] = normaliseString(dataset[field], property);\n }\n if ((property == null ? void 0 : property.type) === 'object') {\n out[field] = extractConfigByNamespace(Component.schema, dataset, namespace);\n }\n }\n return out;\n}\nfunction mergeConfigs(...configObjects) {\n const formattedConfigObject = {};\n for (const configObject of configObjects) {\n for (const key of Object.keys(configObject)) {\n const option = formattedConfigObject[key];\n const override = configObject[key];\n if (isObject(option) && isObject(override)) {\n formattedConfigObject[key] = mergeConfigs(option, override);\n } else {\n formattedConfigObject[key] = override;\n }\n }\n }\n return formattedConfigObject;\n}\nfunction validateConfig(schema, config) {\n const validationErrors = [];\n for (const [name, conditions] of Object.entries(schema)) {\n const errors = [];\n if (Array.isArray(conditions)) {\n for (const {\n required,\n errorMessage\n } of conditions) {\n if (!required.every(key => !!config[key])) {\n errors.push(errorMessage);\n }\n }\n if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {\n validationErrors.push(...errors);\n }\n }\n }\n return validationErrors;\n}\nfunction extractConfigByNamespace(schema, dataset, namespace) {\n const property = schema.properties[namespace];\n if ((property == null ? void 0 : property.type) !== 'object') {\n return;\n }\n const newObject = {\n [namespace]: {}\n };\n for (const [key, value] of Object.entries(dataset)) {\n let current = newObject;\n const keyParts = key.split('.');\n for (const [index, name] of keyParts.entries()) {\n if (isObject(current)) {\n if (index < keyParts.length - 1) {\n if (!isObject(current[name])) {\n current[name] = {};\n }\n current = current[name];\n } else if (key !== namespace) {\n current[name] = normaliseString(value);\n }\n }\n }\n }\n return newObject[namespace];\n}\n/**\n * Schema for component config\n *\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType\n * @typedef {object} Schema\n * @property {Record<keyof ConfigurationType, SchemaProperty | undefined>} properties - Schema properties\n * @property {SchemaCondition<ConfigurationType>[]} [anyOf] - List of schema conditions\n */\n/**\n * Schema property for component config\n *\n * @typedef {object} SchemaProperty\n * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type\n */\n/**\n * Schema condition for component config\n *\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType\n * @typedef {object} SchemaCondition\n * @property {(keyof ConfigurationType)[]} required - List of required config fields\n * @property {string} errorMessage - Error message when required config fields not provided\n */\n/**\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]\n * @typedef ChildClass\n * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component\n * @property {Schema<ConfigurationType>} [schema] - The schema of the component configuration\n * @property {ConfigurationType} [defaults] - The default values of the configuration of the component\n */\n/**\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]\n * @typedef {typeof Component & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>\n */\n\nexport { ConfigurableComponent, configOverride, extractConfigByNamespace, mergeConfigs, normaliseDataset, normaliseString, validateConfig };\n//# sourceMappingURL=configuration.mjs.map\n","import { ConfigurableComponent } from 'govuk-frontend'\n\n/**\n * @augments {ConfigurableComponent<SortableTableConfig>}\n */\nexport class SortableTable extends ConfigurableComponent {\n /**\n * @param {Element | null} $root - HTML element to use for sortable table\n * @param {SortableTableConfig} [config] - Sortable table config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $head = $root?.querySelector('thead')\n const $body = $root?.querySelector('tbody')\n\n if (!$head || !$body) {\n return this\n }\n\n this.$head = $head\n this.$body = $body\n this.$caption = this.$root.querySelector('caption')\n\n 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\">\n<path d=\"M6.5625 15.5L11 6.63125L15.4375 15.5H6.5625Z\" fill=\"currentColor\"/>\n</svg>`\n 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\">\n<path d=\"M15.4375 7L11 15.8687L6.5625 7L15.4375 7Z\" fill=\"currentColor\"/>\n</svg>`\n 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\">\n<path d=\"M8.1875 9.5L10.9609 3.95703L13.7344 9.5H8.1875Z\" fill=\"currentColor\"/>\n<path d=\"M13.7344 12.0781L10.9609 17.6211L8.1875 12.0781H13.7344Z\" fill=\"currentColor\"/>\n</svg>`\n\n this.$headings = this.$head\n ? Array.from(this.$head.querySelectorAll('th'))\n : []\n\n this.createHeadingButtons()\n this.updateCaption()\n this.updateDirectionIndicators()\n this.createStatusBox()\n this.initialiseSortedColumn()\n\n this.$head.addEventListener('click', this.onSortButtonClick.bind(this))\n }\n\n createHeadingButtons() {\n for (const $heading of this.$headings) {\n if ($heading.hasAttribute('aria-sort')) {\n this.createHeadingButton($heading)\n }\n }\n }\n\n /**\n * @param {HTMLTableCellElement} $heading\n */\n createHeadingButton($heading) {\n const index = this.$headings.indexOf($heading)\n const $button = document.createElement('button')\n\n $button.setAttribute('type', 'button')\n $button.setAttribute('data-index', `${index}`)\n $button.textContent = $heading.textContent\n\n $heading.textContent = ''\n $heading.appendChild($button)\n }\n\n createStatusBox() {\n this.$status = document.createElement('div')\n\n this.$status.setAttribute('aria-atomic', 'true')\n this.$status.setAttribute('aria-live', 'polite')\n this.$status.setAttribute('class', 'govuk-visually-hidden')\n this.$status.setAttribute('role', 'status')\n\n this.$root.insertAdjacentElement('afterend', this.$status)\n }\n\n initialiseSortedColumn() {\n const $rows = this.getTableRowsArray()\n\n const $heading = this.$root.querySelector(\n 'th[aria-sort=\"ascending\"], th[aria-sort=\"descending\"]'\n )\n const $sortButton = $heading?.querySelector('button')\n const sortDirection = $heading?.getAttribute('aria-sort')\n\n const columnNumber = Number.parseInt(\n $sortButton?.getAttribute('data-index') ?? '0',\n 10\n )\n\n if (\n !$heading ||\n !$sortButton ||\n !(sortDirection === 'ascending' || sortDirection === 'descending')\n ) {\n return\n }\n\n const $sortedRows = this.sort($rows, columnNumber, sortDirection)\n this.addRows($sortedRows)\n }\n\n /**\n * @param {MouseEvent} event - Click event\n */\n onSortButtonClick(event) {\n const $target = /** @type {HTMLElement} */ (event.target)\n const $button = $target.closest('button')\n\n if (\n !$button ||\n !($button instanceof HTMLButtonElement) ||\n !$button.parentElement\n ) {\n return\n }\n\n const $heading = $button.parentElement\n const sortDirection = $heading.getAttribute('aria-sort')\n\n const columnNumber = Number.parseInt(\n $button?.getAttribute('data-index') ?? '0',\n 10\n )\n\n const newSortDirection =\n sortDirection === 'none' || sortDirection === 'descending'\n ? 'ascending'\n : 'descending'\n\n const $rows = this.getTableRowsArray()\n const $sortedRows = this.sort($rows, columnNumber, newSortDirection)\n\n this.addRows($sortedRows)\n this.removeButtonStates()\n this.updateButtonState($button, newSortDirection)\n this.updateDirectionIndicators()\n }\n\n updateCaption() {\n if (!this.$caption) {\n return\n }\n\n let assistiveText = this.$caption.querySelector('.govuk-visually-hidden')\n if (assistiveText) {\n return\n }\n\n assistiveText = document.createElement('span')\n assistiveText.classList.add('govuk-visually-hidden')\n assistiveText.textContent = ' (column headers with buttons are sortable).'\n\n this.$caption.appendChild(assistiveText)\n }\n\n /**\n * @param {HTMLButtonElement} $button\n * @param {string} direction\n */\n updateButtonState($button, direction) {\n if (!(direction === 'ascending' || direction === 'descending')) {\n return\n }\n\n $button.parentElement.setAttribute('aria-sort', direction)\n let message = this.config.statusMessage\n message = message.replace(/%heading%/, $button.textContent)\n message = message.replace(/%direction%/, this.config[`${direction}Text`])\n this.$status.textContent = message\n }\n\n updateDirectionIndicators() {\n for (const $heading of this.$headings) {\n const $button = /** @type {HTMLButtonElement} */ (\n $heading.querySelector('button')\n )\n if ($heading.hasAttribute('aria-sort') && $button) {\n const direction = $heading.getAttribute('aria-sort')\n $button.querySelector('svg')?.remove()\n\n switch (direction) {\n case 'ascending':\n $button.insertAdjacentHTML('beforeend', this.$upArrow)\n break\n case 'descending':\n $button.insertAdjacentHTML('beforeend', this.$downArrow)\n break\n default:\n $button.insertAdjacentHTML('beforeend', this.$upDownArrow)\n }\n }\n }\n }\n\n removeButtonStates() {\n for (const $heading of this.$headings) {\n $heading.setAttribute('aria-sort', 'none')\n }\n }\n\n /**\n * @param {HTMLTableRowElement[]} $rows\n */\n addRows($rows) {\n for (const $row of $rows) {\n this.$body.append($row)\n }\n }\n\n getTableRowsArray() {\n return Array.from(this.$body.querySelectorAll('tr'))\n }\n\n /**\n * @param {HTMLTableRowElement[]} $rows\n * @param {number} columnNumber\n * @param {string} sortDirection\n */\n sort($rows, columnNumber, sortDirection) {\n return $rows.sort(($rowA, $rowB) => {\n const $tdA = $rowA.querySelectorAll('td, th')[columnNumber]\n const $tdB = $rowB.querySelectorAll('td, th')[columnNumber]\n\n if (\n !$tdA ||\n !$tdB ||\n !($tdA instanceof HTMLElement) ||\n !($tdB instanceof HTMLElement)\n ) {\n return 0\n }\n\n const valueA =\n sortDirection === 'ascending'\n ? this.getCellValue($tdA)\n : this.getCellValue($tdB)\n\n const valueB =\n sortDirection === 'ascending'\n ? this.getCellValue($tdB)\n : this.getCellValue($tdA)\n\n return !(typeof valueA === 'number' && typeof valueB === 'number')\n ? valueA.toString().localeCompare(valueB.toString())\n : valueA - valueB\n })\n }\n\n /**\n * @param {HTMLElement} $cell\n */\n getCellValue($cell) {\n const val = $cell.getAttribute('data-sort-value') || $cell.innerHTML\n const valAsNumber = Number(val)\n\n return Number.isFinite(valAsNumber)\n ? valAsNumber // Exclude invalid numbers, infinity etc\n : val\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-sortable-table'\n\n /**\n * Sortable table config\n *\n * @type {SortableTableConfig}\n */\n static defaults = Object.freeze({\n statusMessage: 'Sort by %heading% (%direction%)',\n ascendingText: 'ascending',\n descendingText: 'descending'\n })\n\n /**\n * Sortable table config schema\n *\n * @satisfies {Schema<SortableTableConfig>}\n */\n static schema = Object.freeze(\n /** @type {const} */ ({\n properties: {\n statusMessage: { type: 'string' },\n ascendingText: { type: 'string' },\n descendingText: { type: 'string' }\n }\n })\n )\n}\n\n/**\n * Sortable table config\n *\n * @typedef {object} SortableTableConfig\n * @property {string} [statusMessage] - Status message\n * @property {string} [ascendingText] - Ascending text\n * @property {string} [descendingText] - Descending text\n */\n\n/**\n * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'\n */\n"],"names":["isInitialised","$root","moduleName","HTMLElement","hasAttribute","isSupported","$scope","document","body","classList","contains","isArray","option","Array","isObject","formatErrorMessage","Component","message","GOVUKFrontendError","Error","constructor","args","name","SupportError","supportMessage","HTMLScriptElement","prototype","ConfigError","ElementError","messageOrOptions","component","identifier","element","expectedType","InitError","componentOrMessage","_$root","childConstructor","elementType","checkSupport","checkInitialised","setAttribute","configOverride","Symbol","for","ConfigurableComponent","param","config","_config","defaults","datasetConfig","normaliseDataset","dataset","mergeConfigs","normaliseString","value","property","trimmedValue","trim","output","outputType","type","includes","length","isFinite","Number","schema","out","entries","Object","properties","entry","namespace","field","toString","extractConfigByNamespace","configObjects","formattedConfigObject","configObject","key","keys","override","newObject","current","keyParts","split","index","SortableTable","$head","querySelector","$body","$caption","$upArrow","$downArrow","$upDownArrow","$headings","from","querySelectorAll","createHeadingButtons","updateCaption","updateDirectionIndicators","createStatusBox","initialiseSortedColumn","addEventListener","onSortButtonClick","bind","$heading","createHeadingButton","indexOf","$button","createElement","textContent","appendChild","$status","insertAdjacentElement","_$sortButton$getAttri","$rows","getTableRowsArray","$sortButton","sortDirection","getAttribute","columnNumber","parseInt","$sortedRows","sort","addRows","event","_$button$getAttribute","$target","target","closest","HTMLButtonElement","parentElement","newSortDirection","removeButtonStates","updateButtonState","assistiveText","add","direction","statusMessage","replace","_$button$querySelecto","remove","insertAdjacentHTML","$row","append","$rowA","$rowB","$tdA","$tdB","valueA","getCellValue","valueB","localeCompare","$cell","val","innerHTML","valAsNumber","freeze","ascendingText","descendingText"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}
@@ -17,8 +17,21 @@ class SortableTable extends ConfigurableComponent {
17
17
  }
18
18
  this.$head = $head;
19
19
  this.$body = $body;
20
+ this.$caption = this.$root.querySelector('caption');
21
+ 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">
22
+ <path d="M6.5625 15.5L11 6.63125L15.4375 15.5H6.5625Z" fill="currentColor"/>
23
+ </svg>`;
24
+ 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">
25
+ <path d="M15.4375 7L11 15.8687L6.5625 7L15.4375 7Z" fill="currentColor"/>
26
+ </svg>`;
27
+ 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">
28
+ <path d="M8.1875 9.5L10.9609 3.95703L13.7344 9.5H8.1875Z" fill="currentColor"/>
29
+ <path d="M13.7344 12.0781L10.9609 17.6211L8.1875 12.0781H13.7344Z" fill="currentColor"/>
30
+ </svg>`;
20
31
  this.$headings = this.$head ? Array.from(this.$head.querySelectorAll('th')) : [];
21
32
  this.createHeadingButtons();
33
+ this.updateCaption();
34
+ this.updateDirectionIndicators();
22
35
  this.createStatusBox();
23
36
  this.initialiseSortedColumn();
24
37
  this.$head.addEventListener('click', this.onSortButtonClick.bind(this));
@@ -54,7 +67,7 @@ class SortableTable extends ConfigurableComponent {
54
67
  initialiseSortedColumn() {
55
68
  var _$sortButton$getAttri;
56
69
  const $rows = this.getTableRowsArray();
57
- const $heading = this.$root.querySelector('th[aria-sort]');
70
+ const $heading = this.$root.querySelector('th[aria-sort="ascending"], th[aria-sort="descending"]');
58
71
  const $sortButton = $heading == null ? void 0 : $heading.querySelector('button');
59
72
  const sortDirection = $heading == null ? void 0 : $heading.getAttribute('aria-sort');
60
73
  const columnNumber = Number.parseInt((_$sortButton$getAttri = $sortButton == null ? void 0 : $sortButton.getAttribute('data-index')) != null ? _$sortButton$getAttri : '0', 10);
@@ -70,7 +83,8 @@ class SortableTable extends ConfigurableComponent {
70
83
  */
71
84
  onSortButtonClick(event) {
72
85
  var _$button$getAttribute;
73
- const $button = event.target;
86
+ const $target = /** @type {HTMLElement} */event.target;
87
+ const $button = $target.closest('button');
74
88
  if (!$button || !($button instanceof HTMLButtonElement) || !$button.parentElement) {
75
89
  return;
76
90
  }
@@ -83,6 +97,20 @@ class SortableTable extends ConfigurableComponent {
83
97
  this.addRows($sortedRows);
84
98
  this.removeButtonStates();
85
99
  this.updateButtonState($button, newSortDirection);
100
+ this.updateDirectionIndicators();
101
+ }
102
+ updateCaption() {
103
+ if (!this.$caption) {
104
+ return;
105
+ }
106
+ let assistiveText = this.$caption.querySelector('.govuk-visually-hidden');
107
+ if (assistiveText) {
108
+ return;
109
+ }
110
+ assistiveText = document.createElement('span');
111
+ assistiveText.classList.add('govuk-visually-hidden');
112
+ assistiveText.textContent = ' (column headers with buttons are sortable).';
113
+ this.$caption.appendChild(assistiveText);
86
114
  }
87
115
 
88
116
  /**
@@ -99,6 +127,27 @@ class SortableTable extends ConfigurableComponent {
99
127
  message = message.replace(/%direction%/, this.config[`${direction}Text`]);
100
128
  this.$status.textContent = message;
101
129
  }
130
+ updateDirectionIndicators() {
131
+ for (const $heading of this.$headings) {
132
+ const $button = /** @type {HTMLButtonElement} */
133
+ $heading.querySelector('button');
134
+ if ($heading.hasAttribute('aria-sort') && $button) {
135
+ var _$button$querySelecto;
136
+ const direction = $heading.getAttribute('aria-sort');
137
+ (_$button$querySelecto = $button.querySelector('svg')) == null || _$button$querySelecto.remove();
138
+ switch (direction) {
139
+ case 'ascending':
140
+ $button.insertAdjacentHTML('beforeend', this.$upArrow);
141
+ break;
142
+ case 'descending':
143
+ $button.insertAdjacentHTML('beforeend', this.$downArrow);
144
+ break;
145
+ default:
146
+ $button.insertAdjacentHTML('beforeend', this.$upDownArrow);
147
+ }
148
+ }
149
+ }
150
+ }
102
151
  removeButtonStates() {
103
152
  for (const $heading of this.$headings) {
104
153
  $heading.setAttribute('aria-sort', 'none');