@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.
- package/moj/all.bundle.js +1549 -1062
- package/moj/all.bundle.js.map +1 -1
- package/moj/all.bundle.mjs +1845 -1054
- package/moj/all.bundle.mjs.map +1 -1
- package/moj/all.mjs +7 -90
- package/moj/all.mjs.map +1 -1
- package/moj/all.scss +1 -0
- package/moj/all.scss.map +1 -1
- package/moj/common/index.mjs +57 -0
- package/moj/common/index.mjs.map +1 -0
- package/moj/common/moj-frontend-version.mjs +14 -0
- package/moj/common/moj-frontend-version.mjs.map +1 -0
- package/moj/components/add-another/add-another.bundle.js +105 -76
- package/moj/components/add-another/add-another.bundle.js.map +1 -1
- package/moj/components/add-another/add-another.bundle.mjs +222 -71
- package/moj/components/add-another/add-another.bundle.mjs.map +1 -1
- package/moj/components/add-another/add-another.mjs +103 -72
- package/moj/components/add-another/add-another.mjs.map +1 -1
- package/moj/components/alert/alert.bundle.js +115 -191
- package/moj/components/alert/alert.bundle.js.map +1 -1
- package/moj/components/alert/alert.bundle.mjs +354 -186
- package/moj/components/alert/alert.bundle.mjs.map +1 -1
- package/moj/components/alert/alert.mjs +55 -140
- package/moj/components/alert/alert.mjs.map +1 -1
- package/moj/components/button-menu/README.md +3 -1
- package/moj/components/button-menu/button-menu.bundle.js +91 -120
- package/moj/components/button-menu/button-menu.bundle.js.map +1 -1
- package/moj/components/button-menu/button-menu.bundle.mjs +329 -114
- package/moj/components/button-menu/button-menu.bundle.mjs.map +1 -1
- package/moj/components/button-menu/button-menu.mjs +89 -116
- package/moj/components/button-menu/button-menu.mjs.map +1 -1
- package/moj/components/date-picker/date-picker.bundle.js +174 -154
- package/moj/components/date-picker/date-picker.bundle.js.map +1 -1
- package/moj/components/date-picker/date-picker.bundle.mjs +411 -147
- package/moj/components/date-picker/date-picker.bundle.mjs.map +1 -1
- package/moj/components/date-picker/date-picker.mjs +172 -150
- package/moj/components/date-picker/date-picker.mjs.map +1 -1
- package/moj/components/filter/template.njk +1 -1
- package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js +133 -44
- package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js.map +1 -1
- package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs +374 -41
- package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs.map +1 -1
- package/moj/components/filter-toggle-button/filter-toggle-button.mjs +131 -40
- package/moj/components/filter-toggle-button/filter-toggle-button.mjs.map +1 -1
- package/moj/components/form-validator/form-validator.bundle.js +159 -69
- package/moj/components/form-validator/form-validator.bundle.js.map +1 -1
- package/moj/components/form-validator/form-validator.bundle.mjs +399 -65
- package/moj/components/form-validator/form-validator.bundle.mjs.map +1 -1
- package/moj/components/form-validator/form-validator.mjs +134 -54
- package/moj/components/form-validator/form-validator.mjs.map +1 -1
- package/moj/components/multi-file-upload/multi-file-upload.bundle.js +291 -117
- package/moj/components/multi-file-upload/multi-file-upload.bundle.js.map +1 -1
- package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs +527 -109
- package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs.map +1 -1
- package/moj/components/multi-file-upload/multi-file-upload.mjs +288 -101
- package/moj/components/multi-file-upload/multi-file-upload.mjs.map +1 -1
- package/moj/components/multi-file-upload/template.njk +1 -1
- package/moj/components/multi-select/multi-select.bundle.js +106 -41
- package/moj/components/multi-select/multi-select.bundle.js.map +1 -1
- package/moj/components/multi-select/multi-select.bundle.mjs +346 -37
- package/moj/components/multi-select/multi-select.bundle.mjs.map +1 -1
- package/moj/components/multi-select/multi-select.mjs +104 -37
- package/moj/components/multi-select/multi-select.mjs.map +1 -1
- package/moj/components/password-reveal/_password-reveal.scss +3 -1
- package/moj/components/password-reveal/_password-reveal.scss.map +1 -1
- package/moj/components/password-reveal/password-reveal.bundle.js +32 -29
- package/moj/components/password-reveal/password-reveal.bundle.js.map +1 -1
- package/moj/components/password-reveal/password-reveal.bundle.mjs +149 -24
- package/moj/components/password-reveal/password-reveal.bundle.mjs.map +1 -1
- package/moj/components/password-reveal/password-reveal.mjs +30 -25
- package/moj/components/password-reveal/password-reveal.mjs.map +1 -1
- package/moj/components/rich-text-editor/README.md +4 -3
- package/moj/components/rich-text-editor/rich-text-editor.bundle.js +127 -62
- package/moj/components/rich-text-editor/rich-text-editor.bundle.js.map +1 -1
- package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs +367 -58
- package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs.map +1 -1
- package/moj/components/rich-text-editor/rich-text-editor.mjs +125 -58
- package/moj/components/rich-text-editor/rich-text-editor.mjs.map +1 -1
- package/moj/components/search-toggle/search-toggle.bundle.js +94 -26
- package/moj/components/search-toggle/search-toggle.bundle.js.map +1 -1
- package/moj/components/search-toggle/search-toggle.bundle.mjs +334 -22
- package/moj/components/search-toggle/search-toggle.bundle.mjs.map +1 -1
- package/moj/components/search-toggle/search-toggle.mjs +92 -22
- package/moj/components/search-toggle/search-toggle.mjs.map +1 -1
- package/moj/components/sortable-table/sortable-table.bundle.js +151 -83
- package/moj/components/sortable-table/sortable-table.bundle.js.map +1 -1
- package/moj/components/sortable-table/sortable-table.bundle.mjs +390 -78
- package/moj/components/sortable-table/sortable-table.bundle.mjs.map +1 -1
- package/moj/components/sortable-table/sortable-table.mjs +149 -79
- package/moj/components/sortable-table/sortable-table.mjs.map +1 -1
- package/moj/core/_all.scss +3 -0
- package/moj/core/_all.scss.map +1 -0
- package/moj/core/_moj-frontend-properties.scss +7 -0
- package/moj/core/_moj-frontend-properties.scss.map +1 -0
- package/moj/filters/prototype-kit-13-filters.js +4 -3
- package/moj/helpers.bundle.js +22 -77
- package/moj/helpers.bundle.js.map +1 -1
- package/moj/helpers.bundle.mjs +23 -74
- package/moj/helpers.bundle.mjs.map +1 -1
- package/moj/helpers.mjs +23 -74
- package/moj/helpers.mjs.map +1 -1
- package/moj/moj-frontend.min.css +1 -1
- package/moj/moj-frontend.min.css.map +1 -1
- package/moj/moj-frontend.min.js +1 -1
- package/moj/moj-frontend.min.js.map +1 -1
- package/package.json +1 -1
- package/moj/version.bundle.js +0 -12
- package/moj/version.bundle.js.map +0 -1
- package/moj/version.bundle.mjs +0 -4
- package/moj/version.bundle.mjs.map +0 -1
- package/moj/version.mjs +0 -4
- package/moj/version.mjs.map +0 -1
|
@@ -1,41 +1,166 @@
|
|
|
1
|
-
|
|
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 formatErrorMessage(Component, message) {
|
|
21
|
+
return `${Component.moduleName}: ${message}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
class GOVUKFrontendError extends Error {
|
|
25
|
+
constructor(...args) {
|
|
26
|
+
super(...args);
|
|
27
|
+
this.name = 'GOVUKFrontendError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
class SupportError extends GOVUKFrontendError {
|
|
2
31
|
/**
|
|
3
|
-
*
|
|
32
|
+
* Checks if GOV.UK Frontend is supported on this page
|
|
33
|
+
*
|
|
34
|
+
* @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support
|
|
4
35
|
*/
|
|
5
|
-
constructor(
|
|
6
|
-
|
|
7
|
-
|
|
36
|
+
constructor($scope = document.body) {
|
|
37
|
+
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';
|
|
38
|
+
super($scope ? supportMessage : 'GOV.UK Frontend initialised without `<script type="module">`');
|
|
39
|
+
this.name = 'SupportError';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
class ElementError extends GOVUKFrontendError {
|
|
43
|
+
constructor(messageOrOptions) {
|
|
44
|
+
let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
|
|
45
|
+
if (typeof messageOrOptions === 'object') {
|
|
46
|
+
const {
|
|
47
|
+
component,
|
|
48
|
+
identifier,
|
|
49
|
+
element,
|
|
50
|
+
expectedType
|
|
51
|
+
} = messageOrOptions;
|
|
52
|
+
message = identifier;
|
|
53
|
+
message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
|
|
54
|
+
message = formatErrorMessage(component, message);
|
|
55
|
+
}
|
|
56
|
+
super(message);
|
|
57
|
+
this.name = 'ElementError';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
class InitError extends GOVUKFrontendError {
|
|
61
|
+
constructor(componentOrMessage) {
|
|
62
|
+
const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\`$root\`) already initialised`);
|
|
63
|
+
super(message);
|
|
64
|
+
this.name = 'InitError';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
class Component {
|
|
69
|
+
/**
|
|
70
|
+
* Returns the root element of the component
|
|
71
|
+
*
|
|
72
|
+
* @protected
|
|
73
|
+
* @returns {RootElementType} - the root element of component
|
|
74
|
+
*/
|
|
75
|
+
get $root() {
|
|
76
|
+
return this._$root;
|
|
77
|
+
}
|
|
78
|
+
constructor($root) {
|
|
79
|
+
this._$root = void 0;
|
|
80
|
+
const childConstructor = this.constructor;
|
|
81
|
+
if (typeof childConstructor.moduleName !== 'string') {
|
|
82
|
+
throw new InitError(`\`moduleName\` not defined in component`);
|
|
8
83
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
84
|
+
if (!($root instanceof childConstructor.elementType)) {
|
|
85
|
+
throw new ElementError({
|
|
86
|
+
element: $root,
|
|
87
|
+
component: childConstructor,
|
|
88
|
+
identifier: 'Root element (`$root`)',
|
|
89
|
+
expectedType: childConstructor.elementType.name
|
|
90
|
+
});
|
|
91
|
+
} else {
|
|
92
|
+
this._$root = $root;
|
|
93
|
+
}
|
|
94
|
+
childConstructor.checkSupport();
|
|
95
|
+
this.checkInitialised();
|
|
96
|
+
const moduleName = childConstructor.moduleName;
|
|
97
|
+
this.$root.setAttribute(`data-${moduleName}-init`, '');
|
|
98
|
+
}
|
|
99
|
+
checkInitialised() {
|
|
100
|
+
const constructor = this.constructor;
|
|
101
|
+
const moduleName = constructor.moduleName;
|
|
102
|
+
if (moduleName && isInitialised(this.$root, moduleName)) {
|
|
103
|
+
throw new InitError(constructor);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
static checkSupport() {
|
|
107
|
+
if (!isSupported()) {
|
|
108
|
+
throw new SupportError();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @typedef ChildClass
|
|
115
|
+
* @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @typedef {typeof Component & ChildClass} ChildClassConstructor
|
|
120
|
+
*/
|
|
121
|
+
Component.elementType = HTMLElement;
|
|
122
|
+
|
|
123
|
+
class PasswordReveal extends Component {
|
|
124
|
+
/**
|
|
125
|
+
* @param {Element | null} $root - HTML element to use for password reveal
|
|
126
|
+
*/
|
|
127
|
+
constructor($root) {
|
|
128
|
+
super($root);
|
|
129
|
+
const $input = this.$root.querySelector('.govuk-input');
|
|
130
|
+
if (!$input || !($input instanceof HTMLInputElement)) {
|
|
12
131
|
return this;
|
|
13
132
|
}
|
|
14
|
-
this
|
|
15
|
-
this.
|
|
133
|
+
this.$input = $input;
|
|
134
|
+
this.$input.setAttribute('spellcheck', 'false');
|
|
16
135
|
this.createButton();
|
|
17
136
|
}
|
|
18
137
|
createButton() {
|
|
19
|
-
this
|
|
20
|
-
this
|
|
21
|
-
this
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
this.button
|
|
25
|
-
this
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
138
|
+
this.$group = document.createElement('div');
|
|
139
|
+
this.$button = document.createElement('button');
|
|
140
|
+
this.$button.setAttribute('type', 'button');
|
|
141
|
+
this.$root.classList.add('moj-password-reveal');
|
|
142
|
+
this.$group.classList.add('moj-password-reveal__wrapper');
|
|
143
|
+
this.$button.classList.add('govuk-button', 'govuk-button--secondary', 'moj-password-reveal__button');
|
|
144
|
+
this.$button.innerHTML = 'Show <span class="govuk-visually-hidden">password</span>';
|
|
145
|
+
this.$button.addEventListener('click', this.onButtonClick.bind(this));
|
|
146
|
+
this.$group.append(this.$input, this.$button);
|
|
147
|
+
this.$root.append(this.$group);
|
|
28
148
|
}
|
|
29
149
|
onButtonClick() {
|
|
30
|
-
if (this.
|
|
31
|
-
this.
|
|
32
|
-
this
|
|
150
|
+
if (this.$input.type === 'password') {
|
|
151
|
+
this.$input.type = 'text';
|
|
152
|
+
this.$button.innerHTML = 'Hide <span class="govuk-visually-hidden">password</span>';
|
|
33
153
|
} else {
|
|
34
|
-
this.
|
|
35
|
-
this
|
|
154
|
+
this.$input.type = 'password';
|
|
155
|
+
this.$button.innerHTML = 'Show <span class="govuk-visually-hidden">password</span>';
|
|
36
156
|
}
|
|
37
157
|
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Name for the component used when initialising using data-module attributes.
|
|
161
|
+
*/
|
|
38
162
|
}
|
|
163
|
+
PasswordReveal.moduleName = 'moj-password-reveal';
|
|
39
164
|
|
|
40
165
|
export { PasswordReveal };
|
|
41
166
|
//# sourceMappingURL=password-reveal.bundle.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-reveal.bundle.mjs","sources":["../../../../src/moj/components/password-reveal/password-reveal.mjs"],"sourcesContent":["export class PasswordReveal {\n /**\n * @param {Element | null} element - HTML element to use for password reveal\n */\n constructor(element) {\n if (!element || !(element instanceof HTMLInputElement)) {\n return this\n }\n\n this.el = element\n this.container = element.parentElement\n\n if (this.container.hasAttribute('data-moj-password-reveal-init')) {\n return this\n }\n\n this.container.setAttribute('data-moj-password-reveal-init', '')\n\n this.el.setAttribute('spellcheck', 'false')\n this.createButton()\n }\n\n createButton() {\n this.group = document.createElement('div')\n this.button = document.createElement('button')\n\n this.button.setAttribute('type', 'button')\n\n this.group.className = 'moj-password-reveal'\n\n this.button.className =\n 'govuk-button govuk-button--secondary moj-password-reveal__button'\n\n this.button.innerHTML =\n 'Show <span class=\"govuk-visually-hidden\">password</span>'\n\n this.button.addEventListener('click', this.onButtonClick.bind(this))\n\n this.group.append(this.el, this.button)\n this.container.append(this.group)\n }\n\n onButtonClick() {\n if (this.el.type === 'password') {\n this.el.type = 'text'\n this.button.innerHTML =\n 'Hide <span class=\"govuk-visually-hidden\">password</span>'\n } else {\n this.el.type = 'password'\n this.button.innerHTML =\n 'Show <span class=\"govuk-visually-hidden\">password</span>'\n }\n }\n}\n"],"names":["PasswordReveal","constructor","element","HTMLInputElement","el","container","parentElement","hasAttribute","setAttribute","createButton","group","document","createElement","button","className","innerHTML","addEventListener","onButtonClick","bind","append","type"],"mappings":"AAAO,MAAMA,cAAc,CAAC;AAC1B;AACF;AACA;EACEC,WAAWA,CAACC,OAAO,EAAE;IACnB,IAAI,CAACA,OAAO,IAAI,EAAEA,OAAO,YAAYC,gBAAgB,CAAC,EAAE;AACtD,MAAA,OAAO,IAAI;AACb;IAEA,IAAI,CAACC,EAAE,GAAGF,OAAO;AACjB,IAAA,IAAI,CAACG,SAAS,GAAGH,OAAO,CAACI,aAAa;IAEtC,IAAI,IAAI,CAACD,SAAS,CAACE,YAAY,CAAC,+BAA+B,CAAC,EAAE;AAChE,MAAA,OAAO,IAAI;AACb;IAEA,IAAI,CAACF,SAAS,CAACG,YAAY,CAAC,+BAA+B,EAAE,EAAE,CAAC;IAEhE,IAAI,CAACJ,EAAE,CAACI,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC;IAC3C,IAAI,CAACC,YAAY,EAAE;AACrB;AAEAA,EAAAA,YAAYA,GAAG;IACb,IAAI,CAACC,KAAK,GAAGC,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;IAC1C,IAAI,CAACC,MAAM,GAAGF,QAAQ,CAACC,aAAa,CAAC,QAAQ,CAAC;IAE9C,IAAI,CAACC,MAAM,CAACL,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;AAE1C,IAAA,IAAI,CAACE,KAAK,CAACI,SAAS,GAAG,qBAAqB;AAE5C,IAAA,IAAI,CAACD,MAAM,CAACC,SAAS,GACnB,kEAAkE;AAEpE,IAAA,IAAI,CAACD,MAAM,CAACE,SAAS,GACnB,0DAA0D;AAE5D,IAAA,IAAI,CAACF,MAAM,CAACG,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACC,aAAa,CAACC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEpE,IAAA,IAAI,CAACR,KAAK,CAACS,MAAM,CAAC,IAAI,CAACf,EAAE,EAAE,IAAI,CAACS,MAAM,CAAC;IACvC,IAAI,CAACR,SAAS,CAACc,MAAM,CAAC,IAAI,CAACT,KAAK,CAAC;AACnC;AAEAO,EAAAA,aAAaA,GAAG;AACd,IAAA,IAAI,IAAI,CAACb,EAAE,CAACgB,IAAI,KAAK,UAAU,EAAE;AAC/B,MAAA,IAAI,CAAChB,EAAE,CAACgB,IAAI,GAAG,MAAM;AACrB,MAAA,IAAI,CAACP,MAAM,CAACE,SAAS,GACnB,0DAA0D;AAC9D,KAAC,MAAM;AACL,MAAA,IAAI,CAACX,EAAE,CAACgB,IAAI,GAAG,UAAU;AACzB,MAAA,IAAI,CAACP,MAAM,CAACE,SAAS,GACnB,0DAA0D;AAC9D;AACF;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"password-reveal.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","../../../../src/moj/components/password-reveal/password-reveal.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 'govuk-frontend'\n\nexport class PasswordReveal extends Component {\n /**\n * @param {Element | null} $root - HTML element to use for password reveal\n */\n constructor($root) {\n super($root)\n\n const $input = this.$root.querySelector('.govuk-input')\n if (!$input || !($input instanceof HTMLInputElement)) {\n return this\n }\n\n this.$input = $input\n this.$input.setAttribute('spellcheck', 'false')\n\n this.createButton()\n }\n\n createButton() {\n this.$group = document.createElement('div')\n this.$button = document.createElement('button')\n\n this.$button.setAttribute('type', 'button')\n\n this.$root.classList.add('moj-password-reveal')\n this.$group.classList.add('moj-password-reveal__wrapper')\n this.$button.classList.add(\n 'govuk-button',\n 'govuk-button--secondary',\n 'moj-password-reveal__button'\n )\n\n this.$button.innerHTML =\n 'Show <span class=\"govuk-visually-hidden\">password</span>'\n\n this.$button.addEventListener('click', this.onButtonClick.bind(this))\n\n this.$group.append(this.$input, this.$button)\n this.$root.append(this.$group)\n }\n\n onButtonClick() {\n if (this.$input.type === 'password') {\n this.$input.type = 'text'\n this.$button.innerHTML =\n 'Hide <span class=\"govuk-visually-hidden\">password</span>'\n } else {\n this.$input.type = 'password'\n this.$button.innerHTML =\n 'Show <span class=\"govuk-visually-hidden\">password</span>'\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-password-reveal'\n}\n"],"names":["isInitialised","$root","moduleName","HTMLElement","hasAttribute","isSupported","$scope","document","body","classList","contains","formatErrorMessage","Component","message","GOVUKFrontendError","Error","constructor","args","name","SupportError","supportMessage","HTMLScriptElement","prototype","ElementError","messageOrOptions","component","identifier","element","expectedType","InitError","componentOrMessage","_$root","childConstructor","elementType","checkSupport","checkInitialised","setAttribute","PasswordReveal","$input","querySelector","HTMLInputElement","createButton","$group","createElement","$button","add","innerHTML","addEventListener","onButtonClick","bind","append","type"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
@@ -1,41 +1,46 @@
|
|
|
1
|
-
|
|
1
|
+
import { Component } from 'govuk-frontend';
|
|
2
|
+
|
|
3
|
+
class PasswordReveal extends Component {
|
|
2
4
|
/**
|
|
3
|
-
* @param {Element | null}
|
|
5
|
+
* @param {Element | null} $root - HTML element to use for password reveal
|
|
4
6
|
*/
|
|
5
|
-
constructor(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
this.el = element;
|
|
10
|
-
this.container = element.parentElement;
|
|
11
|
-
if (this.container.hasAttribute('data-moj-password-reveal-init')) {
|
|
7
|
+
constructor($root) {
|
|
8
|
+
super($root);
|
|
9
|
+
const $input = this.$root.querySelector('.govuk-input');
|
|
10
|
+
if (!$input || !($input instanceof HTMLInputElement)) {
|
|
12
11
|
return this;
|
|
13
12
|
}
|
|
14
|
-
this
|
|
15
|
-
this.
|
|
13
|
+
this.$input = $input;
|
|
14
|
+
this.$input.setAttribute('spellcheck', 'false');
|
|
16
15
|
this.createButton();
|
|
17
16
|
}
|
|
18
17
|
createButton() {
|
|
19
|
-
this
|
|
20
|
-
this
|
|
21
|
-
this
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
this.button
|
|
25
|
-
this
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
18
|
+
this.$group = document.createElement('div');
|
|
19
|
+
this.$button = document.createElement('button');
|
|
20
|
+
this.$button.setAttribute('type', 'button');
|
|
21
|
+
this.$root.classList.add('moj-password-reveal');
|
|
22
|
+
this.$group.classList.add('moj-password-reveal__wrapper');
|
|
23
|
+
this.$button.classList.add('govuk-button', 'govuk-button--secondary', 'moj-password-reveal__button');
|
|
24
|
+
this.$button.innerHTML = 'Show <span class="govuk-visually-hidden">password</span>';
|
|
25
|
+
this.$button.addEventListener('click', this.onButtonClick.bind(this));
|
|
26
|
+
this.$group.append(this.$input, this.$button);
|
|
27
|
+
this.$root.append(this.$group);
|
|
28
28
|
}
|
|
29
29
|
onButtonClick() {
|
|
30
|
-
if (this.
|
|
31
|
-
this.
|
|
32
|
-
this
|
|
30
|
+
if (this.$input.type === 'password') {
|
|
31
|
+
this.$input.type = 'text';
|
|
32
|
+
this.$button.innerHTML = 'Hide <span class="govuk-visually-hidden">password</span>';
|
|
33
33
|
} else {
|
|
34
|
-
this.
|
|
35
|
-
this
|
|
34
|
+
this.$input.type = 'password';
|
|
35
|
+
this.$button.innerHTML = 'Show <span class="govuk-visually-hidden">password</span>';
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Name for the component used when initialising using data-module attributes.
|
|
41
|
+
*/
|
|
38
42
|
}
|
|
43
|
+
PasswordReveal.moduleName = 'moj-password-reveal';
|
|
39
44
|
|
|
40
45
|
export { PasswordReveal };
|
|
41
46
|
//# sourceMappingURL=password-reveal.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-reveal.mjs","sources":["../../../../src/moj/components/password-reveal/password-reveal.mjs"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"password-reveal.mjs","sources":["../../../../src/moj/components/password-reveal/password-reveal.mjs"],"sourcesContent":["import { Component } from 'govuk-frontend'\n\nexport class PasswordReveal extends Component {\n /**\n * @param {Element | null} $root - HTML element to use for password reveal\n */\n constructor($root) {\n super($root)\n\n const $input = this.$root.querySelector('.govuk-input')\n if (!$input || !($input instanceof HTMLInputElement)) {\n return this\n }\n\n this.$input = $input\n this.$input.setAttribute('spellcheck', 'false')\n\n this.createButton()\n }\n\n createButton() {\n this.$group = document.createElement('div')\n this.$button = document.createElement('button')\n\n this.$button.setAttribute('type', 'button')\n\n this.$root.classList.add('moj-password-reveal')\n this.$group.classList.add('moj-password-reveal__wrapper')\n this.$button.classList.add(\n 'govuk-button',\n 'govuk-button--secondary',\n 'moj-password-reveal__button'\n )\n\n this.$button.innerHTML =\n 'Show <span class=\"govuk-visually-hidden\">password</span>'\n\n this.$button.addEventListener('click', this.onButtonClick.bind(this))\n\n this.$group.append(this.$input, this.$button)\n this.$root.append(this.$group)\n }\n\n onButtonClick() {\n if (this.$input.type === 'password') {\n this.$input.type = 'text'\n this.$button.innerHTML =\n 'Hide <span class=\"govuk-visually-hidden\">password</span>'\n } else {\n this.$input.type = 'password'\n this.$button.innerHTML =\n 'Show <span class=\"govuk-visually-hidden\">password</span>'\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-password-reveal'\n}\n"],"names":["PasswordReveal","Component","constructor","$root","$input","querySelector","HTMLInputElement","setAttribute","createButton","$group","document","createElement","$button","classList","add","innerHTML","addEventListener","onButtonClick","bind","append","type","moduleName"],"mappings":";;AAEO,MAAMA,cAAc,SAASC,SAAS,CAAC;AAC5C;AACF;AACA;EACEC,WAAWA,CAACC,KAAK,EAAE;IACjB,KAAK,CAACA,KAAK,CAAC;IAEZ,MAAMC,MAAM,GAAG,IAAI,CAACD,KAAK,CAACE,aAAa,CAAC,cAAc,CAAC;IACvD,IAAI,CAACD,MAAM,IAAI,EAAEA,MAAM,YAAYE,gBAAgB,CAAC,EAAE;AACpD,MAAA,OAAO,IAAI;AACb;IAEA,IAAI,CAACF,MAAM,GAAGA,MAAM;IACpB,IAAI,CAACA,MAAM,CAACG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC;IAE/C,IAAI,CAACC,YAAY,EAAE;AACrB;AAEAA,EAAAA,YAAYA,GAAG;IACb,IAAI,CAACC,MAAM,GAAGC,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;IAC3C,IAAI,CAACC,OAAO,GAAGF,QAAQ,CAACC,aAAa,CAAC,QAAQ,CAAC;IAE/C,IAAI,CAACC,OAAO,CAACL,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;IAE3C,IAAI,CAACJ,KAAK,CAACU,SAAS,CAACC,GAAG,CAAC,qBAAqB,CAAC;IAC/C,IAAI,CAACL,MAAM,CAACI,SAAS,CAACC,GAAG,CAAC,8BAA8B,CAAC;AACzD,IAAA,IAAI,CAACF,OAAO,CAACC,SAAS,CAACC,GAAG,CACxB,cAAc,EACd,yBAAyB,EACzB,6BACF,CAAC;AAED,IAAA,IAAI,CAACF,OAAO,CAACG,SAAS,GACpB,0DAA0D;AAE5D,IAAA,IAAI,CAACH,OAAO,CAACI,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACC,aAAa,CAACC,IAAI,CAAC,IAAI,CAAC,CAAC;AAErE,IAAA,IAAI,CAACT,MAAM,CAACU,MAAM,CAAC,IAAI,CAACf,MAAM,EAAE,IAAI,CAACQ,OAAO,CAAC;IAC7C,IAAI,CAACT,KAAK,CAACgB,MAAM,CAAC,IAAI,CAACV,MAAM,CAAC;AAChC;AAEAQ,EAAAA,aAAaA,GAAG;AACd,IAAA,IAAI,IAAI,CAACb,MAAM,CAACgB,IAAI,KAAK,UAAU,EAAE;AACnC,MAAA,IAAI,CAAChB,MAAM,CAACgB,IAAI,GAAG,MAAM;AACzB,MAAA,IAAI,CAACR,OAAO,CAACG,SAAS,GACpB,0DAA0D;AAC9D,KAAC,MAAM;AACL,MAAA,IAAI,CAACX,MAAM,CAACgB,IAAI,GAAG,UAAU;AAC7B,MAAA,IAAI,CAACR,OAAO,CAACG,SAAS,GACpB,0DAA0D;AAC9D;AACF;;AAEA;AACF;AACA;AAEA;AAzDaf,cAAc,CAwDlBqB,UAAU,GAAG,qBAAqB;;;;"}
|
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
```mjs
|
|
8
8
|
import { RichTextEditor } from '@ministryofjustice/frontend'
|
|
9
9
|
|
|
10
|
-
const $richTextEditor = document.querySelector(
|
|
10
|
+
const $richTextEditor = document.querySelector(
|
|
11
|
+
'[data-module="moj-rich-text-editor"]'
|
|
12
|
+
)
|
|
11
13
|
|
|
12
|
-
new RichTextEditor({
|
|
13
|
-
textarea: $richTextEditor,
|
|
14
|
+
new RichTextEditor($richTextEditor, {
|
|
14
15
|
toolbar: {
|
|
15
16
|
bold: true,
|
|
16
17
|
italic: true,
|
|
@@ -1,34 +1,27 @@
|
|
|
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
|
-
|
|
7
|
+
/**
|
|
8
|
+
* @augments {ConfigurableComponent<RichTextEditorConfig>}
|
|
9
|
+
*/
|
|
10
|
+
class RichTextEditor extends govukFrontend.ConfigurableComponent {
|
|
8
11
|
/**
|
|
9
|
-
* @param {
|
|
12
|
+
* @param {Element | null} $root - HTML element to use for rich text editor
|
|
13
|
+
* @param {RichTextEditorConfig} config
|
|
10
14
|
*/
|
|
11
|
-
constructor(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} = options;
|
|
15
|
-
if (!textarea || !textarea.parentElement || !(textarea instanceof HTMLTextAreaElement) || !('contentEditable' in document.documentElement)) {
|
|
15
|
+
constructor($root, config = {}) {
|
|
16
|
+
super($root, config);
|
|
17
|
+
if (!RichTextEditor.isSupported()) {
|
|
16
18
|
return this;
|
|
17
19
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
italic: false,
|
|
21
|
-
underline: false,
|
|
22
|
-
bullets: true,
|
|
23
|
-
numbers: true
|
|
24
|
-
};
|
|
25
|
-
this.textarea = textarea;
|
|
26
|
-
this.container = this.textarea.parentElement;
|
|
27
|
-
this.options = options;
|
|
28
|
-
if (this.container.hasAttribute('data-rich-text-editor-init')) {
|
|
20
|
+
const $textarea = this.$root.querySelector('.govuk-textarea');
|
|
21
|
+
if (!$textarea || !($textarea instanceof HTMLTextAreaElement)) {
|
|
29
22
|
return this;
|
|
30
23
|
}
|
|
31
|
-
this
|
|
24
|
+
this.$textarea = $textarea;
|
|
32
25
|
this.createToolbar();
|
|
33
26
|
this.hideDefault();
|
|
34
27
|
this.configureToolbar();
|
|
@@ -38,34 +31,42 @@
|
|
|
38
31
|
up: 38,
|
|
39
32
|
down: 40
|
|
40
33
|
};
|
|
41
|
-
this
|
|
42
|
-
this.
|
|
43
|
-
this
|
|
34
|
+
this.$content.addEventListener('input', this.onEditorInput.bind(this));
|
|
35
|
+
this.$root.querySelector('label').addEventListener('click', this.onLabelClick.bind(this));
|
|
36
|
+
this.$toolbar.addEventListener('keydown', this.onToolbarKeydown.bind(this));
|
|
44
37
|
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {KeyboardEvent} event - Click event
|
|
41
|
+
*/
|
|
45
42
|
onToolbarKeydown(event) {
|
|
46
|
-
let focusableButton;
|
|
43
|
+
let $focusableButton;
|
|
47
44
|
switch (event.keyCode) {
|
|
48
45
|
case this.keys.right:
|
|
49
46
|
case this.keys.down:
|
|
50
47
|
{
|
|
51
|
-
focusableButton = this
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
nextButton
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
$focusableButton = this.$buttons.find(button => button.getAttribute('tabindex') === '0');
|
|
49
|
+
if ($focusableButton) {
|
|
50
|
+
const $nextButton = $focusableButton.nextElementSibling;
|
|
51
|
+
if ($nextButton && $nextButton instanceof HTMLButtonElement) {
|
|
52
|
+
$nextButton.focus();
|
|
53
|
+
$focusableButton.setAttribute('tabindex', '-1');
|
|
54
|
+
$nextButton.setAttribute('tabindex', '0');
|
|
55
|
+
}
|
|
57
56
|
}
|
|
58
57
|
break;
|
|
59
58
|
}
|
|
60
59
|
case this.keys.left:
|
|
61
60
|
case this.keys.up:
|
|
62
61
|
{
|
|
63
|
-
focusableButton = this
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
previousButton
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
$focusableButton = this.$buttons.find(button => button.getAttribute('tabindex') === '0');
|
|
63
|
+
if ($focusableButton) {
|
|
64
|
+
const $previousButton = $focusableButton.previousElementSibling;
|
|
65
|
+
if ($previousButton && $previousButton instanceof HTMLButtonElement) {
|
|
66
|
+
$previousButton.focus();
|
|
67
|
+
$focusableButton.setAttribute('tabindex', '-1');
|
|
68
|
+
$previousButton.setAttribute('tabindex', '0');
|
|
69
|
+
}
|
|
69
70
|
}
|
|
70
71
|
break;
|
|
71
72
|
}
|
|
@@ -74,19 +75,19 @@
|
|
|
74
75
|
getToolbarHtml() {
|
|
75
76
|
let html = '';
|
|
76
77
|
html += '<div class="moj-rich-text-editor__toolbar" role="toolbar">';
|
|
77
|
-
if (this.
|
|
78
|
+
if (this.config.toolbar.bold) {
|
|
78
79
|
html += '<button class="moj-rich-text-editor__toolbar-button moj-rich-text-editor__toolbar-button--bold" type="button" data-command="bold"><span class="govuk-visually-hidden">Bold</span></button>';
|
|
79
80
|
}
|
|
80
|
-
if (this.
|
|
81
|
+
if (this.config.toolbar.italic) {
|
|
81
82
|
html += '<button class="moj-rich-text-editor__toolbar-button moj-rich-text-editor__toolbar-button--italic" type="button" data-command="italic"><span class="govuk-visually-hidden">Italic</span></button>';
|
|
82
83
|
}
|
|
83
|
-
if (this.
|
|
84
|
+
if (this.config.toolbar.underline) {
|
|
84
85
|
html += '<button class="moj-rich-text-editor__toolbar-button moj-rich-text-editor__toolbar-button--underline" type="button" data-command="underline"><span class="govuk-visually-hidden">Underline</span></button>';
|
|
85
86
|
}
|
|
86
|
-
if (this.
|
|
87
|
+
if (this.config.toolbar.bullets) {
|
|
87
88
|
html += '<button class="moj-rich-text-editor__toolbar-button moj-rich-text-editor__toolbar-button--unordered-list" type="button" data-command="insertUnorderedList"><span class="govuk-visually-hidden">Unordered list</span></button>';
|
|
88
89
|
}
|
|
89
|
-
if (this.
|
|
90
|
+
if (this.config.toolbar.numbers) {
|
|
90
91
|
html += '<button class="moj-rich-text-editor__toolbar-button moj-rich-text-editor__toolbar-button--ordered-list" type="button" data-command="insertOrderedList"><span class="govuk-visually-hidden">Ordered list</span></button>';
|
|
91
92
|
}
|
|
92
93
|
html += '</div>';
|
|
@@ -96,27 +97,31 @@
|
|
|
96
97
|
return `${this.getToolbarHtml()}<div class="govuk-textarea moj-rich-text-editor__content" contenteditable="true" spellcheck="false"></div>`;
|
|
97
98
|
}
|
|
98
99
|
hideDefault() {
|
|
99
|
-
this
|
|
100
|
-
this
|
|
101
|
-
this
|
|
100
|
+
this.$textarea.classList.add('govuk-visually-hidden');
|
|
101
|
+
this.$textarea.setAttribute('aria-hidden', 'true');
|
|
102
|
+
this.$textarea.setAttribute('tabindex', '-1');
|
|
102
103
|
}
|
|
103
104
|
createToolbar() {
|
|
104
|
-
this
|
|
105
|
-
this
|
|
106
|
-
this
|
|
107
|
-
this.
|
|
108
|
-
this
|
|
109
|
-
this.
|
|
110
|
-
this
|
|
105
|
+
this.$toolbar = document.createElement('div');
|
|
106
|
+
this.$toolbar.className = 'moj-rich-text-editor';
|
|
107
|
+
this.$toolbar.innerHTML = this.getEnhancedHtml();
|
|
108
|
+
this.$root.append(this.$toolbar);
|
|
109
|
+
this.$content = /** @type {HTMLElement} */
|
|
110
|
+
this.$root.querySelector('.moj-rich-text-editor__content');
|
|
111
|
+
this.$content.innerHTML = this.$textarea.value;
|
|
111
112
|
}
|
|
112
113
|
configureToolbar() {
|
|
113
|
-
this
|
|
114
|
-
this.
|
|
115
|
-
this
|
|
116
|
-
button.setAttribute('tabindex', !index ? '0' : '-1');
|
|
117
|
-
button.addEventListener('click', this.onButtonClick.bind(this));
|
|
114
|
+
this.$buttons = Array.from(/** @type {NodeListOf<HTMLButtonElement>} */
|
|
115
|
+
this.$root.querySelectorAll('.moj-rich-text-editor__toolbar-button'));
|
|
116
|
+
this.$buttons.forEach(($button, index) => {
|
|
117
|
+
$button.setAttribute('tabindex', !index ? '0' : '-1');
|
|
118
|
+
$button.addEventListener('click', this.onButtonClick.bind(this));
|
|
118
119
|
});
|
|
119
120
|
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {MouseEvent} event - Click event
|
|
124
|
+
*/
|
|
120
125
|
onButtonClick(event) {
|
|
121
126
|
if (!(event.currentTarget instanceof HTMLElement)) {
|
|
122
127
|
return;
|
|
@@ -124,21 +129,81 @@
|
|
|
124
129
|
document.execCommand(event.currentTarget.getAttribute('data-command'), false, undefined);
|
|
125
130
|
}
|
|
126
131
|
getContent() {
|
|
127
|
-
return this
|
|
132
|
+
return this.$content.innerHTML;
|
|
128
133
|
}
|
|
129
134
|
onEditorInput() {
|
|
130
135
|
this.updateTextarea();
|
|
131
136
|
}
|
|
132
137
|
updateTextarea() {
|
|
133
138
|
document.execCommand('defaultParagraphSeparator', false, 'p');
|
|
134
|
-
this
|
|
139
|
+
this.$textarea.value = this.getContent();
|
|
135
140
|
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @param {MouseEvent} event - Click event
|
|
144
|
+
*/
|
|
136
145
|
onLabelClick(event) {
|
|
137
146
|
event.preventDefault();
|
|
138
|
-
this
|
|
147
|
+
this.$content.focus();
|
|
139
148
|
}
|
|
149
|
+
static isSupported() {
|
|
150
|
+
return 'contentEditable' in document.documentElement;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Name for the component used when initialising using data-module attributes.
|
|
155
|
+
*/
|
|
140
156
|
}
|
|
141
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Rich text editor config
|
|
160
|
+
*
|
|
161
|
+
* @typedef {object} RichTextEditorConfig
|
|
162
|
+
* @property {RichTextEditorToolbar} [toolbar] - Toolbar options
|
|
163
|
+
*/
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Rich text editor toolbar options
|
|
167
|
+
*
|
|
168
|
+
* @typedef {object} RichTextEditorToolbar
|
|
169
|
+
* @property {boolean} [bold] - Show the bold button
|
|
170
|
+
* @property {boolean} [italic] - Show the italic button
|
|
171
|
+
* @property {boolean} [underline] - Show the underline button
|
|
172
|
+
* @property {boolean} [bullets] - Show the bullets button
|
|
173
|
+
* @property {boolean} [numbers] - Show the numbers button
|
|
174
|
+
*/
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'
|
|
178
|
+
*/
|
|
179
|
+
RichTextEditor.moduleName = 'moj-rich-text-editor';
|
|
180
|
+
/**
|
|
181
|
+
* Rich text editor config
|
|
182
|
+
*
|
|
183
|
+
* @type {RichTextEditorConfig}
|
|
184
|
+
*/
|
|
185
|
+
RichTextEditor.defaults = Object.freeze({
|
|
186
|
+
toolbar: {
|
|
187
|
+
bold: false,
|
|
188
|
+
italic: false,
|
|
189
|
+
underline: false,
|
|
190
|
+
bullets: true,
|
|
191
|
+
numbers: true
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
/**
|
|
195
|
+
* Rich text editor config schema
|
|
196
|
+
*
|
|
197
|
+
* @satisfies {Schema<RichTextEditorConfig>}
|
|
198
|
+
*/
|
|
199
|
+
RichTextEditor.schema = Object.freeze(/** @type {const} */{
|
|
200
|
+
properties: {
|
|
201
|
+
toolbar: {
|
|
202
|
+
type: 'object'
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
142
207
|
exports.RichTextEditor = RichTextEditor;
|
|
143
208
|
|
|
144
209
|
}));
|