@ministryofjustice/frontend 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/moj/all.bundle.js +1549 -1062
  2. package/moj/all.bundle.js.map +1 -1
  3. package/moj/all.bundle.mjs +1845 -1054
  4. package/moj/all.bundle.mjs.map +1 -1
  5. package/moj/all.mjs +7 -90
  6. package/moj/all.mjs.map +1 -1
  7. package/moj/all.scss +1 -0
  8. package/moj/all.scss.map +1 -1
  9. package/moj/common/index.mjs +57 -0
  10. package/moj/common/index.mjs.map +1 -0
  11. package/moj/common/moj-frontend-version.mjs +14 -0
  12. package/moj/common/moj-frontend-version.mjs.map +1 -0
  13. package/moj/components/add-another/add-another.bundle.js +105 -76
  14. package/moj/components/add-another/add-another.bundle.js.map +1 -1
  15. package/moj/components/add-another/add-another.bundle.mjs +222 -71
  16. package/moj/components/add-another/add-another.bundle.mjs.map +1 -1
  17. package/moj/components/add-another/add-another.mjs +103 -72
  18. package/moj/components/add-another/add-another.mjs.map +1 -1
  19. package/moj/components/alert/alert.bundle.js +115 -191
  20. package/moj/components/alert/alert.bundle.js.map +1 -1
  21. package/moj/components/alert/alert.bundle.mjs +354 -186
  22. package/moj/components/alert/alert.bundle.mjs.map +1 -1
  23. package/moj/components/alert/alert.mjs +55 -140
  24. package/moj/components/alert/alert.mjs.map +1 -1
  25. package/moj/components/button-menu/README.md +3 -1
  26. package/moj/components/button-menu/button-menu.bundle.js +91 -120
  27. package/moj/components/button-menu/button-menu.bundle.js.map +1 -1
  28. package/moj/components/button-menu/button-menu.bundle.mjs +329 -114
  29. package/moj/components/button-menu/button-menu.bundle.mjs.map +1 -1
  30. package/moj/components/button-menu/button-menu.mjs +89 -116
  31. package/moj/components/button-menu/button-menu.mjs.map +1 -1
  32. package/moj/components/date-picker/date-picker.bundle.js +174 -154
  33. package/moj/components/date-picker/date-picker.bundle.js.map +1 -1
  34. package/moj/components/date-picker/date-picker.bundle.mjs +411 -147
  35. package/moj/components/date-picker/date-picker.bundle.mjs.map +1 -1
  36. package/moj/components/date-picker/date-picker.mjs +172 -150
  37. package/moj/components/date-picker/date-picker.mjs.map +1 -1
  38. package/moj/components/filter/template.njk +1 -1
  39. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js +133 -44
  40. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js.map +1 -1
  41. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs +374 -41
  42. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs.map +1 -1
  43. package/moj/components/filter-toggle-button/filter-toggle-button.mjs +131 -40
  44. package/moj/components/filter-toggle-button/filter-toggle-button.mjs.map +1 -1
  45. package/moj/components/form-validator/form-validator.bundle.js +159 -69
  46. package/moj/components/form-validator/form-validator.bundle.js.map +1 -1
  47. package/moj/components/form-validator/form-validator.bundle.mjs +399 -65
  48. package/moj/components/form-validator/form-validator.bundle.mjs.map +1 -1
  49. package/moj/components/form-validator/form-validator.mjs +134 -54
  50. package/moj/components/form-validator/form-validator.mjs.map +1 -1
  51. package/moj/components/multi-file-upload/multi-file-upload.bundle.js +291 -117
  52. package/moj/components/multi-file-upload/multi-file-upload.bundle.js.map +1 -1
  53. package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs +527 -109
  54. package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs.map +1 -1
  55. package/moj/components/multi-file-upload/multi-file-upload.mjs +288 -101
  56. package/moj/components/multi-file-upload/multi-file-upload.mjs.map +1 -1
  57. package/moj/components/multi-file-upload/template.njk +1 -1
  58. package/moj/components/multi-select/multi-select.bundle.js +106 -41
  59. package/moj/components/multi-select/multi-select.bundle.js.map +1 -1
  60. package/moj/components/multi-select/multi-select.bundle.mjs +346 -37
  61. package/moj/components/multi-select/multi-select.bundle.mjs.map +1 -1
  62. package/moj/components/multi-select/multi-select.mjs +104 -37
  63. package/moj/components/multi-select/multi-select.mjs.map +1 -1
  64. package/moj/components/password-reveal/_password-reveal.scss +3 -1
  65. package/moj/components/password-reveal/_password-reveal.scss.map +1 -1
  66. package/moj/components/password-reveal/password-reveal.bundle.js +32 -29
  67. package/moj/components/password-reveal/password-reveal.bundle.js.map +1 -1
  68. package/moj/components/password-reveal/password-reveal.bundle.mjs +149 -24
  69. package/moj/components/password-reveal/password-reveal.bundle.mjs.map +1 -1
  70. package/moj/components/password-reveal/password-reveal.mjs +30 -25
  71. package/moj/components/password-reveal/password-reveal.mjs.map +1 -1
  72. package/moj/components/rich-text-editor/README.md +4 -3
  73. package/moj/components/rich-text-editor/rich-text-editor.bundle.js +127 -62
  74. package/moj/components/rich-text-editor/rich-text-editor.bundle.js.map +1 -1
  75. package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs +367 -58
  76. package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs.map +1 -1
  77. package/moj/components/rich-text-editor/rich-text-editor.mjs +125 -58
  78. package/moj/components/rich-text-editor/rich-text-editor.mjs.map +1 -1
  79. package/moj/components/search-toggle/search-toggle.bundle.js +94 -26
  80. package/moj/components/search-toggle/search-toggle.bundle.js.map +1 -1
  81. package/moj/components/search-toggle/search-toggle.bundle.mjs +334 -22
  82. package/moj/components/search-toggle/search-toggle.bundle.mjs.map +1 -1
  83. package/moj/components/search-toggle/search-toggle.mjs +92 -22
  84. package/moj/components/search-toggle/search-toggle.mjs.map +1 -1
  85. package/moj/components/sortable-table/sortable-table.bundle.js +151 -83
  86. package/moj/components/sortable-table/sortable-table.bundle.js.map +1 -1
  87. package/moj/components/sortable-table/sortable-table.bundle.mjs +390 -78
  88. package/moj/components/sortable-table/sortable-table.bundle.mjs.map +1 -1
  89. package/moj/components/sortable-table/sortable-table.mjs +149 -79
  90. package/moj/components/sortable-table/sortable-table.mjs.map +1 -1
  91. package/moj/core/_all.scss +3 -0
  92. package/moj/core/_all.scss.map +1 -0
  93. package/moj/core/_moj-frontend-properties.scss +7 -0
  94. package/moj/core/_moj-frontend-properties.scss.map +1 -0
  95. package/moj/filters/prototype-kit-13-filters.js +4 -3
  96. package/moj/helpers.bundle.js +22 -77
  97. package/moj/helpers.bundle.js.map +1 -1
  98. package/moj/helpers.bundle.mjs +23 -74
  99. package/moj/helpers.bundle.mjs.map +1 -1
  100. package/moj/helpers.mjs +23 -74
  101. package/moj/helpers.mjs.map +1 -1
  102. package/moj/moj-frontend.min.css +1 -1
  103. package/moj/moj-frontend.min.css.map +1 -1
  104. package/moj/moj-frontend.min.js +1 -1
  105. package/moj/moj-frontend.min.js.map +1 -1
  106. package/package.json +1 -1
  107. package/moj/version.bundle.js +0 -12
  108. package/moj/version.bundle.js.map +0 -1
  109. package/moj/version.bundle.mjs +0 -4
  110. package/moj/version.bundle.mjs.map +0 -1
  111. package/moj/version.mjs +0 -4
  112. package/moj/version.mjs.map +0 -1
@@ -1,77 +1,142 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MOJFrontend = global.MOJFrontend || {}));
5
- })(this, (function (exports) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('govuk-frontend')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'govuk-frontend'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MOJFrontend = global.MOJFrontend || {}, global.GOVUKFrontend));
5
+ })(this, (function (exports, govukFrontend) { 'use strict';
6
6
 
7
- class MultiSelect {
8
- constructor(options) {
9
- this.container = options.container;
10
- if (this.container.hasAttribute('data-moj-multi-select-init')) {
7
+ /**
8
+ * @augments {ConfigurableComponent<MultiSelectConfig>}
9
+ */
10
+ class MultiSelect extends govukFrontend.ConfigurableComponent {
11
+ /**
12
+ * @param {Element | null} $root - HTML element to use for multi select
13
+ * @param {MultiSelectConfig} [config] - Multi select config
14
+ */
15
+ constructor($root, config = {}) {
16
+ var _this$config$checkbox;
17
+ super($root, config);
18
+ const $container = this.$root.querySelector(`#${this.config.idPrefix}select-all`);
19
+ const $checkboxes = /** @type {NodeListOf<HTMLInputElement>} */(_this$config$checkbox = this.config.checkboxes.items) != null ? _this$config$checkbox : this.$root.querySelectorAll(this.config.checkboxes.selector);
20
+ if (!$container || !($container instanceof HTMLElement) || !$checkboxes.length) {
11
21
  return this;
12
22
  }
13
- this.container.setAttribute('data-moj-multi-select-init', '');
14
- const idPrefix = options.id_prefix;
15
- this.setupToggle(idPrefix);
16
- this.toggleButton = this.toggle.querySelector('input');
17
- this.toggleButton.addEventListener('click', this.onButtonClick.bind(this));
18
- this.container.append(this.toggle);
19
- this.checkboxes = Array.from(options.checkboxes);
20
- this.checkboxes.forEach(el => el.addEventListener('click', this.onCheckboxClick.bind(this)));
21
- this.checked = options.checked || false;
23
+ this.setupToggle(this.config.idPrefix);
24
+ this.$toggleButton = this.$toggle.querySelector('input');
25
+ this.$toggleButton.addEventListener('click', this.onButtonClick.bind(this));
26
+ this.$container = $container;
27
+ this.$container.append(this.$toggle);
28
+ this.$checkboxes = Array.from($checkboxes);
29
+ this.$checkboxes.forEach($input => $input.addEventListener('click', this.onCheckboxClick.bind(this)));
30
+ this.checked = config.checked || false;
22
31
  }
23
32
  setupToggle(idPrefix = '') {
24
33
  const id = `${idPrefix}checkboxes-all`;
25
- const toggle = document.createElement('div');
26
- const label = document.createElement('label');
27
- const input = document.createElement('input');
28
- const span = document.createElement('span');
29
- toggle.classList.add('govuk-checkboxes__item', 'govuk-checkboxes--small', 'moj-multi-select__checkbox');
30
- input.id = id;
31
- input.type = 'checkbox';
32
- input.classList.add('govuk-checkboxes__input');
33
- label.setAttribute('for', id);
34
- label.classList.add('govuk-label', 'govuk-checkboxes__label', 'moj-multi-select__toggle-label');
35
- span.classList.add('govuk-visually-hidden');
36
- span.textContent = 'Select all';
37
- label.append(span);
38
- toggle.append(input, label);
39
- this.toggle = toggle;
34
+ const $toggle = document.createElement('div');
35
+ const $label = document.createElement('label');
36
+ const $input = document.createElement('input');
37
+ const $span = document.createElement('span');
38
+ $toggle.classList.add('govuk-checkboxes__item', 'govuk-checkboxes--small', 'moj-multi-select__checkbox');
39
+ $input.id = id;
40
+ $input.type = 'checkbox';
41
+ $input.classList.add('govuk-checkboxes__input');
42
+ $label.setAttribute('for', id);
43
+ $label.classList.add('govuk-label', 'govuk-checkboxes__label', 'moj-multi-select__toggle-label');
44
+ $span.classList.add('govuk-visually-hidden');
45
+ $span.textContent = 'Select all';
46
+ $label.append($span);
47
+ $toggle.append($input, $label);
48
+ this.$toggle = $toggle;
40
49
  }
41
50
  onButtonClick() {
42
51
  if (this.checked) {
43
52
  this.uncheckAll();
44
- this.toggleButton.checked = false;
53
+ this.$toggleButton.checked = false;
45
54
  } else {
46
55
  this.checkAll();
47
- this.toggleButton.checked = true;
56
+ this.$toggleButton.checked = true;
48
57
  }
49
58
  }
50
59
  checkAll() {
51
- this.checkboxes.forEach(el => {
52
- el.checked = true;
60
+ this.$checkboxes.forEach($input => {
61
+ $input.checked = true;
53
62
  });
54
63
  this.checked = true;
55
64
  }
56
65
  uncheckAll() {
57
- this.checkboxes.forEach(el => {
58
- el.checked = false;
66
+ this.$checkboxes.forEach($input => {
67
+ $input.checked = false;
59
68
  });
60
69
  this.checked = false;
61
70
  }
71
+
72
+ /**
73
+ * @param {MouseEvent} event - Click event
74
+ */
62
75
  onCheckboxClick(event) {
76
+ if (!(event.target instanceof HTMLInputElement)) {
77
+ return;
78
+ }
63
79
  if (!event.target.checked) {
64
- this.toggleButton.checked = false;
80
+ this.$toggleButton.checked = false;
65
81
  this.checked = false;
66
82
  } else {
67
- if (this.checkboxes.filter(el => el.checked).length === this.checkboxes.length) {
68
- this.toggleButton.checked = true;
83
+ if (this.$checkboxes.filter($input => $input.checked).length === this.$checkboxes.length) {
84
+ this.$toggleButton.checked = true;
69
85
  this.checked = true;
70
86
  }
71
87
  }
72
88
  }
89
+
90
+ /**
91
+ * Name for the component used when initialising using data-module attributes.
92
+ */
73
93
  }
74
94
 
95
+ /**
96
+ * Multi select config
97
+ *
98
+ * @typedef {object} MultiSelectConfig
99
+ * @property {string} [idPrefix] - Prefix for the Select all" checkbox `id` attribute
100
+ * @property {boolean} [checked] - Whether the "Select all" checkbox is checked
101
+ * @property {object} [checkboxes] - Checkboxes config
102
+ * @property {string} [checkboxes.selector] - Checkboxes query selector
103
+ * @property {NodeListOf<HTMLInputElement>} [checkboxes.items] - Checkboxes query selector results
104
+ */
105
+
106
+ /**
107
+ * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'
108
+ */
109
+ MultiSelect.moduleName = 'moj-multi-select';
110
+ /**
111
+ * Multi select config
112
+ *
113
+ * @type {MultiSelectConfig}
114
+ */
115
+ MultiSelect.defaults = Object.freeze({
116
+ idPrefix: '',
117
+ checkboxes: {
118
+ selector: 'tbody input.govuk-checkboxes__input'
119
+ }
120
+ });
121
+ /**
122
+ * Multi select config schema
123
+ *
124
+ * @satisfies {Schema<MultiSelectConfig>}
125
+ */
126
+ MultiSelect.schema = Object.freeze(/** @type {const} */{
127
+ properties: {
128
+ idPrefix: {
129
+ type: 'string'
130
+ },
131
+ checked: {
132
+ type: 'boolean'
133
+ },
134
+ checkboxes: {
135
+ type: 'object'
136
+ }
137
+ }
138
+ });
139
+
75
140
  exports.MultiSelect = MultiSelect;
76
141
 
77
142
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"multi-select.bundle.js","sources":["../../../../src/moj/components/multi-select/multi-select.mjs"],"sourcesContent":["export class MultiSelect {\n constructor(options) {\n this.container = options.container\n\n if (this.container.hasAttribute('data-moj-multi-select-init')) {\n return this\n }\n\n this.container.setAttribute('data-moj-multi-select-init', '')\n\n const idPrefix = options.id_prefix\n this.setupToggle(idPrefix)\n\n this.toggleButton = this.toggle.querySelector('input')\n this.toggleButton.addEventListener('click', this.onButtonClick.bind(this))\n this.container.append(this.toggle)\n\n this.checkboxes = Array.from(options.checkboxes)\n this.checkboxes.forEach((el) =>\n el.addEventListener('click', this.onCheckboxClick.bind(this))\n )\n\n this.checked = options.checked || false\n }\n\n setupToggle(idPrefix = '') {\n const id = `${idPrefix}checkboxes-all`\n\n const toggle = document.createElement('div')\n const label = document.createElement('label')\n const input = document.createElement('input')\n const span = document.createElement('span')\n\n toggle.classList.add(\n 'govuk-checkboxes__item',\n 'govuk-checkboxes--small',\n 'moj-multi-select__checkbox'\n )\n\n input.id = id\n input.type = 'checkbox'\n input.classList.add('govuk-checkboxes__input')\n\n label.setAttribute('for', id)\n label.classList.add(\n 'govuk-label',\n 'govuk-checkboxes__label',\n 'moj-multi-select__toggle-label'\n )\n\n span.classList.add('govuk-visually-hidden')\n span.textContent = 'Select all'\n\n label.append(span)\n toggle.append(input, label)\n\n this.toggle = toggle\n }\n\n onButtonClick() {\n if (this.checked) {\n this.uncheckAll()\n this.toggleButton.checked = false\n } else {\n this.checkAll()\n this.toggleButton.checked = true\n }\n }\n\n checkAll() {\n this.checkboxes.forEach((el) => {\n el.checked = true\n })\n this.checked = true\n }\n\n uncheckAll() {\n this.checkboxes.forEach((el) => {\n el.checked = false\n })\n this.checked = false\n }\n\n onCheckboxClick(event) {\n if (!event.target.checked) {\n this.toggleButton.checked = false\n this.checked = false\n } else {\n if (\n this.checkboxes.filter((el) => el.checked).length ===\n this.checkboxes.length\n ) {\n this.toggleButton.checked = true\n this.checked = true\n }\n }\n }\n}\n"],"names":["MultiSelect","constructor","options","container","hasAttribute","setAttribute","idPrefix","id_prefix","setupToggle","toggleButton","toggle","querySelector","addEventListener","onButtonClick","bind","append","checkboxes","Array","from","forEach","el","onCheckboxClick","checked","id","document","createElement","label","input","span","classList","add","type","textContent","uncheckAll","checkAll","event","target","filter","length"],"mappings":"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"}
1
+ {"version":3,"file":"multi-select.bundle.js","sources":["../../../../src/moj/components/multi-select/multi-select.mjs"],"sourcesContent":["import { ConfigurableComponent } from 'govuk-frontend'\n\n/**\n * @augments {ConfigurableComponent<MultiSelectConfig>}\n */\nexport class MultiSelect extends ConfigurableComponent {\n /**\n * @param {Element | null} $root - HTML element to use for multi select\n * @param {MultiSelectConfig} [config] - Multi select config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $container = this.$root.querySelector(\n `#${this.config.idPrefix}select-all`\n )\n\n const $checkboxes = /** @type {NodeListOf<HTMLInputElement>} */ (\n this.config.checkboxes.items ??\n this.$root.querySelectorAll(this.config.checkboxes.selector)\n )\n\n if (\n !$container ||\n !($container instanceof HTMLElement) ||\n !$checkboxes.length\n ) {\n return this\n }\n\n this.setupToggle(this.config.idPrefix)\n\n this.$toggleButton = this.$toggle.querySelector('input')\n this.$toggleButton.addEventListener('click', this.onButtonClick.bind(this))\n\n this.$container = $container\n this.$container.append(this.$toggle)\n\n this.$checkboxes = Array.from($checkboxes)\n this.$checkboxes.forEach(($input) =>\n $input.addEventListener('click', this.onCheckboxClick.bind(this))\n )\n\n this.checked = config.checked || false\n }\n\n setupToggle(idPrefix = '') {\n const id = `${idPrefix}checkboxes-all`\n\n const $toggle = document.createElement('div')\n const $label = document.createElement('label')\n const $input = document.createElement('input')\n const $span = document.createElement('span')\n\n $toggle.classList.add(\n 'govuk-checkboxes__item',\n 'govuk-checkboxes--small',\n 'moj-multi-select__checkbox'\n )\n\n $input.id = id\n $input.type = 'checkbox'\n $input.classList.add('govuk-checkboxes__input')\n\n $label.setAttribute('for', id)\n $label.classList.add(\n 'govuk-label',\n 'govuk-checkboxes__label',\n 'moj-multi-select__toggle-label'\n )\n\n $span.classList.add('govuk-visually-hidden')\n $span.textContent = 'Select all'\n\n $label.append($span)\n $toggle.append($input, $label)\n\n this.$toggle = $toggle\n }\n\n onButtonClick() {\n if (this.checked) {\n this.uncheckAll()\n this.$toggleButton.checked = false\n } else {\n this.checkAll()\n this.$toggleButton.checked = true\n }\n }\n\n checkAll() {\n this.$checkboxes.forEach(($input) => {\n $input.checked = true\n })\n\n this.checked = true\n }\n\n uncheckAll() {\n this.$checkboxes.forEach(($input) => {\n $input.checked = false\n })\n\n this.checked = false\n }\n\n /**\n * @param {MouseEvent} event - Click event\n */\n onCheckboxClick(event) {\n if (!(event.target instanceof HTMLInputElement)) {\n return\n }\n\n if (!event.target.checked) {\n this.$toggleButton.checked = false\n this.checked = false\n } else {\n if (\n this.$checkboxes.filter(($input) => $input.checked).length ===\n this.$checkboxes.length\n ) {\n this.$toggleButton.checked = true\n this.checked = true\n }\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-multi-select'\n\n /**\n * Multi select config\n *\n * @type {MultiSelectConfig}\n */\n static defaults = Object.freeze({\n idPrefix: '',\n checkboxes: {\n selector: 'tbody input.govuk-checkboxes__input'\n }\n })\n\n /**\n * Multi select config schema\n *\n * @satisfies {Schema<MultiSelectConfig>}\n */\n static schema = Object.freeze(\n /** @type {const} */ ({\n properties: {\n idPrefix: { type: 'string' },\n checked: { type: 'boolean' },\n checkboxes: { type: 'object' }\n }\n })\n )\n}\n\n/**\n * Multi select config\n *\n * @typedef {object} MultiSelectConfig\n * @property {string} [idPrefix] - Prefix for the Select all\" checkbox `id` attribute\n * @property {boolean} [checked] - Whether the \"Select all\" checkbox is checked\n * @property {object} [checkboxes] - Checkboxes config\n * @property {string} [checkboxes.selector] - Checkboxes query selector\n * @property {NodeListOf<HTMLInputElement>} [checkboxes.items] - Checkboxes query selector results\n */\n\n/**\n * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'\n */\n"],"names":["MultiSelect","ConfigurableComponent","constructor","$root","config","_this$config$checkbox","$container","querySelector","idPrefix","$checkboxes","checkboxes","items","querySelectorAll","selector","HTMLElement","length","setupToggle","$toggleButton","$toggle","addEventListener","onButtonClick","bind","append","Array","from","forEach","$input","onCheckboxClick","checked","id","document","createElement","$label","$span","classList","add","type","setAttribute","textContent","uncheckAll","checkAll","event","target","HTMLInputElement","filter","moduleName","defaults","Object","freeze","schema","properties"],"mappings":"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"}
@@ -1,70 +1,379 @@
1
- class MultiSelect {
2
- constructor(options) {
3
- this.container = options.container;
4
- if (this.container.hasAttribute('data-moj-multi-select-init')) {
1
+ function isInitialised($root, moduleName) {
2
+ return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);
3
+ }
4
+
5
+ /**
6
+ * Checks if GOV.UK Frontend is supported on this page
7
+ *
8
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
9
+ * won't be supported.
10
+ *
11
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
12
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
13
+ */
14
+ function isSupported($scope = document.body) {
15
+ if (!$scope) {
16
+ return false;
17
+ }
18
+ return $scope.classList.contains('govuk-frontend-supported');
19
+ }
20
+ function isArray(option) {
21
+ return Array.isArray(option);
22
+ }
23
+ function isObject(option) {
24
+ return !!option && typeof option === 'object' && !isArray(option);
25
+ }
26
+ function formatErrorMessage(Component, message) {
27
+ return `${Component.moduleName}: ${message}`;
28
+ }
29
+
30
+ class GOVUKFrontendError extends Error {
31
+ constructor(...args) {
32
+ super(...args);
33
+ this.name = 'GOVUKFrontendError';
34
+ }
35
+ }
36
+ class SupportError extends GOVUKFrontendError {
37
+ /**
38
+ * Checks if GOV.UK Frontend is supported on this page
39
+ *
40
+ * @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support
41
+ */
42
+ constructor($scope = document.body) {
43
+ 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';
44
+ super($scope ? supportMessage : 'GOV.UK Frontend initialised without `<script type="module">`');
45
+ this.name = 'SupportError';
46
+ }
47
+ }
48
+ class ConfigError extends GOVUKFrontendError {
49
+ constructor(...args) {
50
+ super(...args);
51
+ this.name = 'ConfigError';
52
+ }
53
+ }
54
+ class ElementError extends GOVUKFrontendError {
55
+ constructor(messageOrOptions) {
56
+ let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
57
+ if (typeof messageOrOptions === 'object') {
58
+ const {
59
+ component,
60
+ identifier,
61
+ element,
62
+ expectedType
63
+ } = messageOrOptions;
64
+ message = identifier;
65
+ message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
66
+ message = formatErrorMessage(component, message);
67
+ }
68
+ super(message);
69
+ this.name = 'ElementError';
70
+ }
71
+ }
72
+ class InitError extends GOVUKFrontendError {
73
+ constructor(componentOrMessage) {
74
+ const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\`$root\`) already initialised`);
75
+ super(message);
76
+ this.name = 'InitError';
77
+ }
78
+ }
79
+
80
+ class Component {
81
+ /**
82
+ * Returns the root element of the component
83
+ *
84
+ * @protected
85
+ * @returns {RootElementType} - the root element of component
86
+ */
87
+ get $root() {
88
+ return this._$root;
89
+ }
90
+ constructor($root) {
91
+ this._$root = void 0;
92
+ const childConstructor = this.constructor;
93
+ if (typeof childConstructor.moduleName !== 'string') {
94
+ throw new InitError(`\`moduleName\` not defined in component`);
95
+ }
96
+ if (!($root instanceof childConstructor.elementType)) {
97
+ throw new ElementError({
98
+ element: $root,
99
+ component: childConstructor,
100
+ identifier: 'Root element (`$root`)',
101
+ expectedType: childConstructor.elementType.name
102
+ });
103
+ } else {
104
+ this._$root = $root;
105
+ }
106
+ childConstructor.checkSupport();
107
+ this.checkInitialised();
108
+ const moduleName = childConstructor.moduleName;
109
+ this.$root.setAttribute(`data-${moduleName}-init`, '');
110
+ }
111
+ checkInitialised() {
112
+ const constructor = this.constructor;
113
+ const moduleName = constructor.moduleName;
114
+ if (moduleName && isInitialised(this.$root, moduleName)) {
115
+ throw new InitError(constructor);
116
+ }
117
+ }
118
+ static checkSupport() {
119
+ if (!isSupported()) {
120
+ throw new SupportError();
121
+ }
122
+ }
123
+ }
124
+
125
+ /**
126
+ * @typedef ChildClass
127
+ * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
128
+ */
129
+
130
+ /**
131
+ * @typedef {typeof Component & ChildClass} ChildClassConstructor
132
+ */
133
+ Component.elementType = HTMLElement;
134
+
135
+ const configOverride = Symbol.for('configOverride');
136
+ class ConfigurableComponent extends Component {
137
+ [configOverride](param) {
138
+ return {};
139
+ }
140
+
141
+ /**
142
+ * Returns the root element of the component
143
+ *
144
+ * @protected
145
+ * @returns {ConfigurationType} - the root element of component
146
+ */
147
+ get config() {
148
+ return this._config;
149
+ }
150
+ constructor($root, config) {
151
+ super($root);
152
+ this._config = void 0;
153
+ const childConstructor = this.constructor;
154
+ if (!isObject(childConstructor.defaults)) {
155
+ throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
156
+ }
157
+ const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
158
+ this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
159
+ }
160
+ }
161
+ function normaliseString(value, property) {
162
+ const trimmedValue = value ? value.trim() : '';
163
+ let output;
164
+ let outputType = property == null ? void 0 : property.type;
165
+ if (!outputType) {
166
+ if (['true', 'false'].includes(trimmedValue)) {
167
+ outputType = 'boolean';
168
+ }
169
+ if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
170
+ outputType = 'number';
171
+ }
172
+ }
173
+ switch (outputType) {
174
+ case 'boolean':
175
+ output = trimmedValue === 'true';
176
+ break;
177
+ case 'number':
178
+ output = Number(trimmedValue);
179
+ break;
180
+ default:
181
+ output = value;
182
+ }
183
+ return output;
184
+ }
185
+ function normaliseDataset(Component, dataset) {
186
+ if (!isObject(Component.schema)) {
187
+ throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));
188
+ }
189
+ const out = {};
190
+ const entries = Object.entries(Component.schema.properties);
191
+ for (const entry of entries) {
192
+ const [namespace, property] = entry;
193
+ const field = namespace.toString();
194
+ if (field in dataset) {
195
+ out[field] = normaliseString(dataset[field], property);
196
+ }
197
+ if ((property == null ? void 0 : property.type) === 'object') {
198
+ out[field] = extractConfigByNamespace(Component.schema, dataset, namespace);
199
+ }
200
+ }
201
+ return out;
202
+ }
203
+ function mergeConfigs(...configObjects) {
204
+ const formattedConfigObject = {};
205
+ for (const configObject of configObjects) {
206
+ for (const key of Object.keys(configObject)) {
207
+ const option = formattedConfigObject[key];
208
+ const override = configObject[key];
209
+ if (isObject(option) && isObject(override)) {
210
+ formattedConfigObject[key] = mergeConfigs(option, override);
211
+ } else {
212
+ formattedConfigObject[key] = override;
213
+ }
214
+ }
215
+ }
216
+ return formattedConfigObject;
217
+ }
218
+ function extractConfigByNamespace(schema, dataset, namespace) {
219
+ const property = schema.properties[namespace];
220
+ if ((property == null ? void 0 : property.type) !== 'object') {
221
+ return;
222
+ }
223
+ const newObject = {
224
+ [namespace]: {}
225
+ };
226
+ for (const [key, value] of Object.entries(dataset)) {
227
+ let current = newObject;
228
+ const keyParts = key.split('.');
229
+ for (const [index, name] of keyParts.entries()) {
230
+ if (isObject(current)) {
231
+ if (index < keyParts.length - 1) {
232
+ if (!isObject(current[name])) {
233
+ current[name] = {};
234
+ }
235
+ current = current[name];
236
+ } else if (key !== namespace) {
237
+ current[name] = normaliseString(value);
238
+ }
239
+ }
240
+ }
241
+ }
242
+ return newObject[namespace];
243
+ }
244
+
245
+ /**
246
+ * @augments {ConfigurableComponent<MultiSelectConfig>}
247
+ */
248
+ class MultiSelect extends ConfigurableComponent {
249
+ /**
250
+ * @param {Element | null} $root - HTML element to use for multi select
251
+ * @param {MultiSelectConfig} [config] - Multi select config
252
+ */
253
+ constructor($root, config = {}) {
254
+ var _this$config$checkbox;
255
+ super($root, config);
256
+ const $container = this.$root.querySelector(`#${this.config.idPrefix}select-all`);
257
+ const $checkboxes = /** @type {NodeListOf<HTMLInputElement>} */(_this$config$checkbox = this.config.checkboxes.items) != null ? _this$config$checkbox : this.$root.querySelectorAll(this.config.checkboxes.selector);
258
+ if (!$container || !($container instanceof HTMLElement) || !$checkboxes.length) {
5
259
  return this;
6
260
  }
7
- this.container.setAttribute('data-moj-multi-select-init', '');
8
- const idPrefix = options.id_prefix;
9
- this.setupToggle(idPrefix);
10
- this.toggleButton = this.toggle.querySelector('input');
11
- this.toggleButton.addEventListener('click', this.onButtonClick.bind(this));
12
- this.container.append(this.toggle);
13
- this.checkboxes = Array.from(options.checkboxes);
14
- this.checkboxes.forEach(el => el.addEventListener('click', this.onCheckboxClick.bind(this)));
15
- this.checked = options.checked || false;
261
+ this.setupToggle(this.config.idPrefix);
262
+ this.$toggleButton = this.$toggle.querySelector('input');
263
+ this.$toggleButton.addEventListener('click', this.onButtonClick.bind(this));
264
+ this.$container = $container;
265
+ this.$container.append(this.$toggle);
266
+ this.$checkboxes = Array.from($checkboxes);
267
+ this.$checkboxes.forEach($input => $input.addEventListener('click', this.onCheckboxClick.bind(this)));
268
+ this.checked = config.checked || false;
16
269
  }
17
270
  setupToggle(idPrefix = '') {
18
271
  const id = `${idPrefix}checkboxes-all`;
19
- const toggle = document.createElement('div');
20
- const label = document.createElement('label');
21
- const input = document.createElement('input');
22
- const span = document.createElement('span');
23
- toggle.classList.add('govuk-checkboxes__item', 'govuk-checkboxes--small', 'moj-multi-select__checkbox');
24
- input.id = id;
25
- input.type = 'checkbox';
26
- input.classList.add('govuk-checkboxes__input');
27
- label.setAttribute('for', id);
28
- label.classList.add('govuk-label', 'govuk-checkboxes__label', 'moj-multi-select__toggle-label');
29
- span.classList.add('govuk-visually-hidden');
30
- span.textContent = 'Select all';
31
- label.append(span);
32
- toggle.append(input, label);
33
- this.toggle = toggle;
272
+ const $toggle = document.createElement('div');
273
+ const $label = document.createElement('label');
274
+ const $input = document.createElement('input');
275
+ const $span = document.createElement('span');
276
+ $toggle.classList.add('govuk-checkboxes__item', 'govuk-checkboxes--small', 'moj-multi-select__checkbox');
277
+ $input.id = id;
278
+ $input.type = 'checkbox';
279
+ $input.classList.add('govuk-checkboxes__input');
280
+ $label.setAttribute('for', id);
281
+ $label.classList.add('govuk-label', 'govuk-checkboxes__label', 'moj-multi-select__toggle-label');
282
+ $span.classList.add('govuk-visually-hidden');
283
+ $span.textContent = 'Select all';
284
+ $label.append($span);
285
+ $toggle.append($input, $label);
286
+ this.$toggle = $toggle;
34
287
  }
35
288
  onButtonClick() {
36
289
  if (this.checked) {
37
290
  this.uncheckAll();
38
- this.toggleButton.checked = false;
291
+ this.$toggleButton.checked = false;
39
292
  } else {
40
293
  this.checkAll();
41
- this.toggleButton.checked = true;
294
+ this.$toggleButton.checked = true;
42
295
  }
43
296
  }
44
297
  checkAll() {
45
- this.checkboxes.forEach(el => {
46
- el.checked = true;
298
+ this.$checkboxes.forEach($input => {
299
+ $input.checked = true;
47
300
  });
48
301
  this.checked = true;
49
302
  }
50
303
  uncheckAll() {
51
- this.checkboxes.forEach(el => {
52
- el.checked = false;
304
+ this.$checkboxes.forEach($input => {
305
+ $input.checked = false;
53
306
  });
54
307
  this.checked = false;
55
308
  }
309
+
310
+ /**
311
+ * @param {MouseEvent} event - Click event
312
+ */
56
313
  onCheckboxClick(event) {
314
+ if (!(event.target instanceof HTMLInputElement)) {
315
+ return;
316
+ }
57
317
  if (!event.target.checked) {
58
- this.toggleButton.checked = false;
318
+ this.$toggleButton.checked = false;
59
319
  this.checked = false;
60
320
  } else {
61
- if (this.checkboxes.filter(el => el.checked).length === this.checkboxes.length) {
62
- this.toggleButton.checked = true;
321
+ if (this.$checkboxes.filter($input => $input.checked).length === this.$checkboxes.length) {
322
+ this.$toggleButton.checked = true;
63
323
  this.checked = true;
64
324
  }
65
325
  }
66
326
  }
327
+
328
+ /**
329
+ * Name for the component used when initialising using data-module attributes.
330
+ */
67
331
  }
68
332
 
333
+ /**
334
+ * Multi select config
335
+ *
336
+ * @typedef {object} MultiSelectConfig
337
+ * @property {string} [idPrefix] - Prefix for the Select all" checkbox `id` attribute
338
+ * @property {boolean} [checked] - Whether the "Select all" checkbox is checked
339
+ * @property {object} [checkboxes] - Checkboxes config
340
+ * @property {string} [checkboxes.selector] - Checkboxes query selector
341
+ * @property {NodeListOf<HTMLInputElement>} [checkboxes.items] - Checkboxes query selector results
342
+ */
343
+
344
+ /**
345
+ * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'
346
+ */
347
+ MultiSelect.moduleName = 'moj-multi-select';
348
+ /**
349
+ * Multi select config
350
+ *
351
+ * @type {MultiSelectConfig}
352
+ */
353
+ MultiSelect.defaults = Object.freeze({
354
+ idPrefix: '',
355
+ checkboxes: {
356
+ selector: 'tbody input.govuk-checkboxes__input'
357
+ }
358
+ });
359
+ /**
360
+ * Multi select config schema
361
+ *
362
+ * @satisfies {Schema<MultiSelectConfig>}
363
+ */
364
+ MultiSelect.schema = Object.freeze(/** @type {const} */{
365
+ properties: {
366
+ idPrefix: {
367
+ type: 'string'
368
+ },
369
+ checked: {
370
+ type: 'boolean'
371
+ },
372
+ checkboxes: {
373
+ type: 'object'
374
+ }
375
+ }
376
+ });
377
+
69
378
  export { MultiSelect };
70
379
  //# sourceMappingURL=multi-select.bundle.mjs.map