@ministryofjustice/frontend 3.4.0 → 3.6.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 (50) hide show
  1. package/moj/all.jquery.js +13378 -0
  2. package/moj/all.jquery.min.js +1 -144
  3. package/moj/all.js +2266 -2551
  4. package/moj/all.mjs +126 -0
  5. package/moj/components/add-another/add-another.js +110 -100
  6. package/moj/components/add-another/add-another.mjs +106 -0
  7. package/moj/components/alert/alert.js +319 -211
  8. package/moj/components/alert/alert.mjs +251 -0
  9. package/moj/components/alert/alert.spec.helper.js +12 -5
  10. package/moj/components/alert/alert.spec.helper.mjs +66 -0
  11. package/moj/components/button-menu/button-menu.js +302 -292
  12. package/moj/components/button-menu/button-menu.mjs +329 -0
  13. package/moj/components/date-picker/date-picker.js +850 -842
  14. package/moj/components/date-picker/date-picker.mjs +961 -0
  15. package/moj/components/filter-toggle-button/filter-toggle-button.js +98 -88
  16. package/moj/components/filter-toggle-button/filter-toggle-button.mjs +93 -0
  17. package/moj/components/form-validator/form-validator.js +195 -155
  18. package/moj/components/form-validator/form-validator.mjs +168 -0
  19. package/moj/components/multi-file-upload/multi-file-upload.js +158 -137
  20. package/moj/components/multi-file-upload/multi-file-upload.mjs +219 -0
  21. package/moj/components/multi-select/multi-select.js +75 -65
  22. package/moj/components/multi-select/multi-select.mjs +77 -0
  23. package/moj/components/password-reveal/password-reveal.js +40 -30
  24. package/moj/components/password-reveal/password-reveal.mjs +35 -0
  25. package/moj/components/rich-text-editor/rich-text-editor.js +92 -80
  26. package/moj/components/rich-text-editor/rich-text-editor.mjs +157 -0
  27. package/moj/components/search-toggle/search-toggle.js +55 -45
  28. package/moj/components/search-toggle/search-toggle.mjs +54 -0
  29. package/moj/components/sortable-table/sortable-table.js +141 -141
  30. package/moj/components/sortable-table/sortable-table.mjs +138 -0
  31. package/moj/helpers/_links.scss +1 -1
  32. package/moj/helpers.js +171 -152
  33. package/moj/helpers.mjs +123 -0
  34. package/moj/moj-frontend.min.js +1 -144
  35. package/moj/version.js +11 -1
  36. package/moj/version.mjs +3 -0
  37. package/package.json +13 -1
  38. package/moj/all.spec.js +0 -24
  39. package/moj/components/add-another/add-another.spec.js +0 -165
  40. package/moj/components/alert/alert.spec.js +0 -229
  41. package/moj/components/button-menu/button-menu.spec.js +0 -360
  42. package/moj/components/date-picker/date-picker.spec.js +0 -1178
  43. package/moj/components/filter-toggle-button/filter-toggle-button.spec.js +0 -302
  44. package/moj/components/multi-file-upload/multi-file-upload.spec.js +0 -510
  45. package/moj/components/multi-select/multi-select.spec.js +0 -128
  46. package/moj/components/password-reveal/password-reveal.spec.js +0 -57
  47. package/moj/components/search-toggle/search-toggle.spec.js +0 -129
  48. package/moj/components/sortable-table/sortable-table.spec.js +0 -362
  49. package/moj/helpers.spec.js +0 -235
  50. package/moj/namespace.js +0 -2
package/moj/helpers.js CHANGED
@@ -1,180 +1,199 @@
1
- MOJFrontend.removeAttributeValue = function (el, attr, value) {
2
- let re, m
3
- if (el.getAttribute(attr)) {
4
- if (el.getAttribute(attr) === value) {
5
- el.removeAttribute(attr)
6
- } else {
7
- re = new RegExp(`(^|\\s)${value}(\\s|$)`)
8
- m = el.getAttribute(attr).match(re)
9
- if (m && m.length === 3) {
10
- el.setAttribute(
11
- attr,
12
- el.getAttribute(attr).replace(re, m[1] && m[2] ? ' ' : '')
13
- )
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';
6
+
7
+ function removeAttributeValue(el, attr, value) {
8
+ let re, m;
9
+ if (el.getAttribute(attr)) {
10
+ if (el.getAttribute(attr) === value) {
11
+ el.removeAttribute(attr);
12
+ } else {
13
+ re = new RegExp(`(^|\\s)${value}(\\s|$)`);
14
+ m = el.getAttribute(attr).match(re);
15
+ if (m && m.length === 3) {
16
+ el.setAttribute(
17
+ attr,
18
+ el.getAttribute(attr).replace(re, m[1] && m[2] ? ' ' : '')
19
+ );
20
+ }
14
21
  }
15
22
  }
16
23
  }
17
- }
18
-
19
- MOJFrontend.addAttributeValue = function (el, attr, value) {
20
- let re
21
- if (!el.getAttribute(attr)) {
22
- el.setAttribute(attr, value)
23
- } else {
24
- re = new RegExp(`(^|\\s)${value}(\\s|$)`)
25
- if (!re.test(el.getAttribute(attr))) {
26
- el.setAttribute(attr, `${el.getAttribute(attr)} ${value}`)
24
+
25
+ function addAttributeValue(el, attr, value) {
26
+ let re;
27
+ if (!el.getAttribute(attr)) {
28
+ el.setAttribute(attr, value);
29
+ } else {
30
+ re = new RegExp(`(^|\\s)${value}(\\s|$)`);
31
+ if (!re.test(el.getAttribute(attr))) {
32
+ el.setAttribute(attr, `${el.getAttribute(attr)} ${value}`);
33
+ }
27
34
  }
28
35
  }
29
- }
30
-
31
- MOJFrontend.dragAndDropSupported = function () {
32
- const div = document.createElement('div')
33
- return typeof div.ondrop !== 'undefined'
34
- }
35
-
36
- MOJFrontend.formDataSupported = function () {
37
- return typeof FormData === 'function'
38
- }
39
-
40
- MOJFrontend.fileApiSupported = function () {
41
- const input = document.createElement('input')
42
- input.type = 'file'
43
- return typeof input.files !== 'undefined'
44
- }
45
-
46
- MOJFrontend.nodeListForEach = function (nodes, callback) {
47
- if (window.NodeList.prototype.forEach) {
48
- return nodes.forEach(callback)
49
- }
50
- for (let i = 0; i < nodes.length; i++) {
51
- callback.call(window, nodes[i], i, nodes)
36
+
37
+ function dragAndDropSupported() {
38
+ const div = document.createElement('div');
39
+ return typeof div.ondrop !== 'undefined'
52
40
  }
53
- }
54
-
55
- /**
56
- * Find an elements next sibling
57
- *
58
- * Utility function to find an elements next sibling matching the provided
59
- * selector.
60
- *
61
- * @param {HTMLElement} element - Element to find siblings for
62
- * @param {string} selector - selector for required sibling
63
- */
64
- MOJFrontend.getNextSibling = function ($element, selector) {
65
- if (!$element) return
66
- // Get the next sibling element
67
- let $sibling = $element.nextElementSibling
68
-
69
- // If there's no selector, return the first sibling
70
- if (!selector) return $sibling
71
-
72
- // If the sibling matches our selector, use it
73
- // If not, jump to the next sibling and continue the loop
74
- while ($sibling) {
75
- if ($sibling.matches(selector)) return $sibling
76
- $sibling = $sibling.nextElementSibling
41
+
42
+ function formDataSupported() {
43
+ return typeof FormData === 'function'
77
44
  }
78
- }
79
-
80
- /**
81
- * Find an elements preceding sibling
82
- *
83
- * Utility function to find an elements previous sibling matching the provided
84
- * selector.
85
- *
86
- * @param {HTMLElement} element - Element to find siblings for
87
- * @param {string} selector - selector for required sibling
88
- */
89
- MOJFrontend.getPreviousSibling = function ($element, selector) {
90
- if (!$element) return
91
- // Get the previous sibling element
92
- let $sibling = $element.previousElementSibling
93
-
94
- // If there's no selector, return the first sibling
95
- if (!selector) return $sibling
96
-
97
- // If the sibling matches our selector, use it
98
- // If not, jump to the next sibling and continue the loop
99
- while ($sibling) {
100
- if ($sibling.matches(selector)) return $sibling
101
- $sibling = $sibling.previousElementSibling
45
+
46
+ function fileApiSupported() {
47
+ const input = document.createElement('input');
48
+ input.type = 'file';
49
+ return typeof input.files !== 'undefined'
102
50
  }
103
- }
104
51
 
105
- MOJFrontend.findNearestMatchingElement = function ($element, selector) {
106
- // If no element or selector is provided, return null
107
- if (!$element) return
108
- if (!selector) return
52
+ function nodeListForEach(nodes, callback) {
53
+ if (window.NodeList.prototype.forEach) {
54
+ return nodes.forEach(callback)
55
+ }
56
+ for (let i = 0; i < nodes.length; i++) {
57
+ callback.call(window, nodes[i], i, nodes);
58
+ }
59
+ }
109
60
 
110
- // Start with the current element
111
- let $currentElement = $element
61
+ /**
62
+ * Find an elements next sibling
63
+ *
64
+ * Utility function to find an elements next sibling matching the provided
65
+ * selector.
66
+ *
67
+ * @param {HTMLElement} $element - Element to find siblings for
68
+ * @param {string} selector - selector for required sibling
69
+ */
70
+ function getNextSibling($element, selector) {
71
+ if (!$element) return
72
+ // Get the next sibling element
73
+ let $sibling = $element.nextElementSibling;
112
74
 
113
- while ($currentElement) {
114
- // First check the current element
115
- if ($currentElement.matches(selector)) {
116
- return $currentElement
117
- }
75
+ // If there's no selector, return the first sibling
76
+ if (!selector) return $sibling
118
77
 
119
- // Check all previous siblings
120
- let $sibling = $currentElement.previousElementSibling
78
+ // If the sibling matches our selector, use it
79
+ // If not, jump to the next sibling and continue the loop
121
80
  while ($sibling) {
122
- // Check if the sibling itself is a heading
123
- if ($sibling.matches(selector)) {
124
- return $sibling
125
- }
126
- $sibling = $sibling.previousElementSibling
81
+ if ($sibling.matches(selector)) return $sibling
82
+ $sibling = $sibling.nextElementSibling;
127
83
  }
128
-
129
- // If no match found in siblings, move up to parent
130
- $currentElement = $currentElement.parentElement
131
- }
132
- }
133
-
134
- /**
135
- * Move focus to element
136
- *
137
- * Sets tabindex to -1 to make the element programmatically focusable,
138
- * but removes it on blur as the element doesn't need to be focused again.
139
- *
140
- * @param {HTMLElement} $element - HTML element
141
- * @param {object} [options] - Handler options
142
- * @param {function(this: HTMLElement): void} [options.onBeforeFocus] - Callback before focus
143
- * @param {function(this: HTMLElement): void} [options.onBlur] - Callback on blur
144
- */
145
- MOJFrontend.setFocus = function ($element, options = {}) {
146
- const isFocusable = $element.getAttribute('tabindex')
147
-
148
- if (!isFocusable) {
149
- $element.setAttribute('tabindex', '-1')
150
84
  }
151
85
 
152
86
  /**
153
- * Handle element focus
87
+ * Find an elements preceding sibling
88
+ *
89
+ * Utility function to find an elements previous sibling matching the provided
90
+ * selector.
91
+ *
92
+ * @param {HTMLElement} $element - Element to find siblings for
93
+ * @param {string} selector - selector for required sibling
154
94
  */
155
- function onFocus() {
156
- $element.addEventListener('blur', onBlur, { once: true })
95
+ function getPreviousSibling($element, selector) {
96
+ if (!$element) return
97
+ // Get the previous sibling element
98
+ let $sibling = $element.previousElementSibling;
99
+
100
+ // If there's no selector, return the first sibling
101
+ if (!selector) return $sibling
102
+
103
+ // If the sibling matches our selector, use it
104
+ // If not, jump to the next sibling and continue the loop
105
+ while ($sibling) {
106
+ if ($sibling.matches(selector)) return $sibling
107
+ $sibling = $sibling.previousElementSibling;
108
+ }
109
+ }
110
+
111
+ function findNearestMatchingElement($element, selector) {
112
+ // If no element or selector is provided, return null
113
+ if (!$element) return
114
+ if (!selector) return
115
+
116
+ // Start with the current element
117
+ let $currentElement = $element;
118
+
119
+ while ($currentElement) {
120
+ // First check the current element
121
+ if ($currentElement.matches(selector)) {
122
+ return $currentElement
123
+ }
124
+
125
+ // Check all previous siblings
126
+ let $sibling = $currentElement.previousElementSibling;
127
+ while ($sibling) {
128
+ // Check if the sibling itself is a heading
129
+ if ($sibling.matches(selector)) {
130
+ return $sibling
131
+ }
132
+ $sibling = $sibling.previousElementSibling;
133
+ }
134
+
135
+ // If no match found in siblings, move up to parent
136
+ $currentElement = $currentElement.parentElement;
137
+ }
157
138
  }
158
139
 
159
140
  /**
160
- * Handle element blur
141
+ * Move focus to element
142
+ *
143
+ * Sets tabindex to -1 to make the element programmatically focusable,
144
+ * but removes it on blur as the element doesn't need to be focused again.
145
+ *
146
+ * @param {HTMLElement} $element - HTML element
147
+ * @param {object} [options] - Handler options
148
+ * @param {function(this: HTMLElement): void} [options.onBeforeFocus] - Callback before focus
149
+ * @param {function(this: HTMLElement): void} [options.onBlur] - Callback on blur
161
150
  */
162
- function onBlur() {
163
- if (options.onBlur) {
164
- options.onBlur.call($element)
165
- }
151
+ function setFocus($element, options = {}) {
152
+ const isFocusable = $element.getAttribute('tabindex');
166
153
 
167
154
  if (!isFocusable) {
168
- $element.removeAttribute('tabindex')
155
+ $element.setAttribute('tabindex', '-1');
169
156
  }
170
- }
171
157
 
172
- // Add listener to reset element on blur, after focus
173
- $element.addEventListener('focus', onFocus, { once: true })
158
+ /**
159
+ * Handle element focus
160
+ */
161
+ function onFocus() {
162
+ $element.addEventListener('blur', onBlur, { once: true });
163
+ }
164
+
165
+ /**
166
+ * Handle element blur
167
+ */
168
+ function onBlur() {
169
+ if (options.onBlur) {
170
+ options.onBlur.call($element);
171
+ }
172
+
173
+ if (!isFocusable) {
174
+ $element.removeAttribute('tabindex');
175
+ }
176
+ }
177
+
178
+ // Add listener to reset element on blur, after focus
179
+ $element.addEventListener('focus', onFocus, { once: true });
174
180
 
175
- // Focus element
176
- if (options.onBeforeFocus) {
177
- options.onBeforeFocus.call($element)
181
+ // Focus element
182
+ if (options.onBeforeFocus) {
183
+ options.onBeforeFocus.call($element);
184
+ }
185
+ $element.focus();
178
186
  }
179
- $element.focus()
180
- }
187
+
188
+ exports.addAttributeValue = addAttributeValue;
189
+ exports.dragAndDropSupported = dragAndDropSupported;
190
+ exports.fileApiSupported = fileApiSupported;
191
+ exports.findNearestMatchingElement = findNearestMatchingElement;
192
+ exports.formDataSupported = formDataSupported;
193
+ exports.getNextSibling = getNextSibling;
194
+ exports.getPreviousSibling = getPreviousSibling;
195
+ exports.nodeListForEach = nodeListForEach;
196
+ exports.removeAttributeValue = removeAttributeValue;
197
+ exports.setFocus = setFocus;
198
+
199
+ }));
@@ -0,0 +1,123 @@
1
+ function dragAndDropSupported() {
2
+ const div = document.createElement('div');
3
+ return typeof div.ondrop !== 'undefined'
4
+ }
5
+
6
+ function formDataSupported() {
7
+ return typeof FormData === 'function'
8
+ }
9
+
10
+ function fileApiSupported() {
11
+ const input = document.createElement('input');
12
+ input.type = 'file';
13
+ return typeof input.files !== 'undefined'
14
+ }
15
+
16
+ function nodeListForEach(nodes, callback) {
17
+ if (window.NodeList.prototype.forEach) {
18
+ return nodes.forEach(callback)
19
+ }
20
+ for (let i = 0; i < nodes.length; i++) {
21
+ callback.call(window, nodes[i], i, nodes);
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Find an elements preceding sibling
27
+ *
28
+ * Utility function to find an elements previous sibling matching the provided
29
+ * selector.
30
+ *
31
+ * @param {HTMLElement} $element - Element to find siblings for
32
+ * @param {string} selector - selector for required sibling
33
+ */
34
+ function getPreviousSibling($element, selector) {
35
+ if (!$element) return
36
+ // Get the previous sibling element
37
+ let $sibling = $element.previousElementSibling;
38
+
39
+ // If the sibling matches our selector, use it
40
+ // If not, jump to the next sibling and continue the loop
41
+ while ($sibling) {
42
+ if ($sibling.matches(selector)) return $sibling
43
+ $sibling = $sibling.previousElementSibling;
44
+ }
45
+ }
46
+
47
+ function findNearestMatchingElement($element, selector) {
48
+ // If no element or selector is provided, return null
49
+ if (!$element) return
50
+
51
+ // Start with the current element
52
+ let $currentElement = $element;
53
+
54
+ while ($currentElement) {
55
+ // First check the current element
56
+ if ($currentElement.matches(selector)) {
57
+ return $currentElement
58
+ }
59
+
60
+ // Check all previous siblings
61
+ let $sibling = $currentElement.previousElementSibling;
62
+ while ($sibling) {
63
+ // Check if the sibling itself is a heading
64
+ if ($sibling.matches(selector)) {
65
+ return $sibling
66
+ }
67
+ $sibling = $sibling.previousElementSibling;
68
+ }
69
+
70
+ // If no match found in siblings, move up to parent
71
+ $currentElement = $currentElement.parentElement;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Move focus to element
77
+ *
78
+ * Sets tabindex to -1 to make the element programmatically focusable,
79
+ * but removes it on blur as the element doesn't need to be focused again.
80
+ *
81
+ * @param {HTMLElement} $element - HTML element
82
+ * @param {object} [options] - Handler options
83
+ * @param {function(this: HTMLElement): void} [options.onBeforeFocus] - Callback before focus
84
+ * @param {function(this: HTMLElement): void} [options.onBlur] - Callback on blur
85
+ */
86
+ function setFocus($element, options = {}) {
87
+ const isFocusable = $element.getAttribute('tabindex');
88
+
89
+ if (!isFocusable) {
90
+ $element.setAttribute('tabindex', '-1');
91
+ }
92
+
93
+ /**
94
+ * Handle element focus
95
+ */
96
+ function onFocus() {
97
+ $element.addEventListener('blur', onBlur, { once: true });
98
+ }
99
+
100
+ /**
101
+ * Handle element blur
102
+ */
103
+ function onBlur() {
104
+ if (options.onBlur) {
105
+ options.onBlur.call($element);
106
+ }
107
+
108
+ if (!isFocusable) {
109
+ $element.removeAttribute('tabindex');
110
+ }
111
+ }
112
+
113
+ // Add listener to reset element on blur, after focus
114
+ $element.addEventListener('focus', onFocus, { once: true });
115
+
116
+ // Focus element
117
+ if (options.onBeforeFocus) {
118
+ options.onBeforeFocus.call($element);
119
+ }
120
+ $element.focus();
121
+ }
122
+
123
+ export { dragAndDropSupported, fileApiSupported, findNearestMatchingElement, formDataSupported, getPreviousSibling, nodeListForEach, setFocus };