@schukai/monster 3.73.5 → 3.73.6

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/CHANGELOG.md CHANGED
@@ -2,11 +2,19 @@
2
2
 
3
3
 
4
4
 
5
+ ## [3.73.6] - 2024-07-31
6
+
7
+ ### Bug Fixes
8
+
9
+ - repair url in tests [#230](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/230)
10
+ - improvement of the tree menu to avoid recursion. [#230](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/230)
11
+
12
+
5
13
  ## [3.73.5] - 2024-07-02
6
14
 
7
15
  ### Bug Fixes
8
16
 
9
- - originValues in the savebutton is now reset.
17
+ - originValues in the save button is now reset.
10
18
 
11
19
  ## [3.73.4] - 2024-07-02
12
20
 
package/package.json CHANGED
@@ -1 +1 @@
1
- {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.7","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.73.5"}
1
+ {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.7","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.73.6"}
@@ -12,33 +12,33 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import {instanceSymbol, internalSymbol} from "../../constants.mjs";
16
- import {diff} from "../../data/diff.mjs";
17
- import {addAttributeToken} from "../../dom/attributes.mjs";
18
- import {ATTRIBUTE_ERRORMESSAGE} from "../../dom/constants.mjs";
15
+ import { instanceSymbol, internalSymbol } from "../../constants.mjs";
16
+ import { diff } from "../../data/diff.mjs";
17
+ import { addAttributeToken } from "../../dom/attributes.mjs";
18
+ import { ATTRIBUTE_ERRORMESSAGE } from "../../dom/constants.mjs";
19
19
  import {
20
- assembleMethodSymbol,
21
- CustomElement,
22
- attributeObserverSymbol,
23
- registerCustomElement,
20
+ assembleMethodSymbol,
21
+ CustomElement,
22
+ attributeObserverSymbol,
23
+ registerCustomElement,
24
24
  } from "../../dom/customelement.mjs";
25
- import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
26
- import {isString, isArray} from "../../types/is.mjs";
27
- import {Observer} from "../../types/observer.mjs";
28
- import {TokenList} from "../../types/tokenlist.mjs";
29
- import {clone} from "../../util/clone.mjs";
30
- import {State} from "../form/types/state.mjs";
31
- import {ATTRIBUTE_DATASOURCE_SELECTOR} from "./constants.mjs";
32
- import {Datasource} from "./datasource.mjs";
33
- import {BadgeStyleSheet} from "../stylesheet/badge.mjs";
34
- import {SaveButtonStyleSheet} from "./stylesheet/save-button.mjs";
25
+ import { findElementWithSelectorUpwards } from "../../dom/util.mjs";
26
+ import { isString, isArray } from "../../types/is.mjs";
27
+ import { Observer } from "../../types/observer.mjs";
28
+ import { TokenList } from "../../types/tokenlist.mjs";
29
+ import { clone } from "../../util/clone.mjs";
30
+ import { State } from "../form/types/state.mjs";
31
+ import { ATTRIBUTE_DATASOURCE_SELECTOR } from "./constants.mjs";
32
+ import { Datasource } from "./datasource.mjs";
33
+ import { BadgeStyleSheet } from "../stylesheet/badge.mjs";
34
+ import { SaveButtonStyleSheet } from "./stylesheet/save-button.mjs";
35
35
 
36
36
  import {
37
- handleDataSourceChanges,
38
- datasourceLinkedElementSymbol,
37
+ handleDataSourceChanges,
38
+ datasourceLinkedElementSymbol,
39
39
  } from "./util.mjs";
40
40
 
41
- export {SaveButton};
41
+ export { SaveButton };
42
42
 
43
43
  /**
44
44
  * @private
@@ -59,185 +59,187 @@ const originValuesSymbol = Symbol("originValues");
59
59
  const badgeElementSymbol = Symbol("badgeElement");
60
60
 
61
61
  class SaveButton extends CustomElement {
62
- /**
63
- * This method is called by the `instanceof` operator.
64
- * @returns {symbol}
65
- */
66
- static get [instanceSymbol]() {
67
- return Symbol.for(
68
- "@schukai/monster/components/datasource/save-button@@instance",
69
- );
70
- }
71
-
72
- /**
73
- * To set the options via the html tag the attribute `data-monster-options` must be used.
74
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
75
- *
76
- * The individual configuration values can be found in the table.
77
- *
78
- * @property {Object} templates Template definitions
79
- * @property {string} templates.main Main template
80
- * @property {object} datasource The datasource
81
- * @property {string} datasource.selector The selector of the datasource
82
- * @property {string} labels.button The button label
83
- * @property {Object} classes The classes
84
- * @property {string} classes.bar The bar class
85
- * @property {string} classes.badge The badge class
86
- * @property {Array} ignoreChanges The ignore changes (regex)
87
- * @property {Array} data The data
88
- * @return {Object}
89
- */
90
- get defaults() {
91
- const obj = Object.assign({}, super.defaults, {
92
- templates: {
93
- main: getTemplate(),
94
- },
95
-
96
- labels: {
97
- button: "save",
98
- },
99
-
100
- classes: {
101
- bar: "monster-button-primary",
102
- badge: "monster-badge-secondary hidden",
103
- },
104
-
105
- datasource: {
106
- selector: null,
107
- },
108
-
109
- changes: "0",
110
-
111
- ignoreChanges: [],
112
-
113
- data: {},
114
-
115
- disabled: false,
116
- });
117
-
118
- updateOptionsFromArguments.call(this, obj);
119
- return obj;
120
- }
121
-
122
- /**
123
- *
124
- * @return {string}
125
- */
126
- static getTag() {
127
- return "monster-datasource-save-button";
128
- }
129
-
130
- /**
131
- * This method is responsible for assembling the component.
132
- *
133
- * It calls the parent's assemble method first, then initializes control references and event handlers.
134
- * If the `datasource.selector` option is provided and is a string, it searches for the corresponding
135
- * element in the DOM using that selector.
136
- *
137
- * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class.
138
- *
139
- * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component
140
- * attaches an observer to the datasource's changes.
141
- *
142
- * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component.
143
- * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges`
144
- * method in the component's context.
145
- */
146
- [assembleMethodSymbol]() {
147
- super[assembleMethodSymbol]();
148
- const self = this;
149
-
150
- initControlReferences.call(this);
151
- initEventHandler.call(this);
152
-
153
- const selector = this.getOption("datasource.selector");
154
-
155
- if (isString(selector)) {
156
- const element = findElementWithSelectorUpwards(this, selector);
157
- if (element === null) {
158
- throw new Error("the selector must match exactly one element");
159
- }
160
-
161
- if (!(element instanceof Datasource)) {
162
- throw new TypeError("the element must be a datasource");
163
- }
164
-
165
- this[datasourceLinkedElementSymbol] = element;
166
- element.datasource.attachObserver(
167
- new Observer(handleDataSourceChanges.bind(this)),
168
- );
169
-
170
- self[originValuesSymbol] = null;
171
-
172
- element.datasource.attachObserver(
173
- new Observer(function () {
174
- if (!self[originValuesSymbol]) {
175
- self[originValuesSymbol] = clone(self[datasourceLinkedElementSymbol].data);
176
- }
177
-
178
- const currentValues = this.getRealSubject();
179
- const ignoreChanges = self.getOption("ignoreChanges");
180
-
181
- const result = diff(self[originValuesSymbol], currentValues);
182
- if (isArray(ignoreChanges) && ignoreChanges.length > 0) {
183
- const itemsToRemove = [];
184
- for (const item of result) {
185
- for (const ignorePattern of ignoreChanges) {
186
- const p = new RegExp(ignorePattern);
187
- if (p.test(item.path)) {
188
- itemsToRemove.push(item);
189
- break;
190
- }
191
- }
192
- }
193
-
194
- for (const itemToRemove of itemsToRemove) {
195
- const index = result.indexOf(itemToRemove);
196
- if (index > -1) {
197
- result.splice(index, 1);
198
- }
199
- }
200
- }
201
-
202
- if (isArray(result) && result.length > 0) {
203
- self[stateButtonElementSymbol].setState("changed");
204
- self[stateButtonElementSymbol].setOption("disabled", false);
205
- self.setOption("changes", result.length);
206
- self.setOption(
207
- "classes.badge",
208
- new TokenList(self.getOption("classes.badge"))
209
- .remove("hidden")
210
- .toString(),
211
- );
212
- } else {
213
- self[stateButtonElementSymbol].removeState();
214
- self[stateButtonElementSymbol].setOption("disabled", true);
215
- self.setOption("changes", 0);
216
- self.setOption(
217
- "classes.badge",
218
- new TokenList(self.getOption("classes.badge"))
219
- .add("hidden")
220
- .toString(),
221
- );
222
- }
223
- }),
224
- );
225
- }
226
-
227
- this.attachObserver(
228
- new Observer(() => {
229
- handleDataSourceChanges.call(this);
230
- }),
231
- );
232
- }
233
-
234
- /**
235
- *
236
- * @return [CSSStyleSheet]
237
- */
238
- static getCSSStyleSheet() {
239
- return [SaveButtonStyleSheet, BadgeStyleSheet];
240
- }
62
+ /**
63
+ * This method is called by the `instanceof` operator.
64
+ * @returns {symbol}
65
+ */
66
+ static get [instanceSymbol]() {
67
+ return Symbol.for(
68
+ "@schukai/monster/components/datasource/save-button@@instance",
69
+ );
70
+ }
71
+
72
+ /**
73
+ * To set the options via the html tag the attribute `data-monster-options` must be used.
74
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
75
+ *
76
+ * The individual configuration values can be found in the table.
77
+ *
78
+ * @property {Object} templates Template definitions
79
+ * @property {string} templates.main Main template
80
+ * @property {object} datasource The datasource
81
+ * @property {string} datasource.selector The selector of the datasource
82
+ * @property {string} labels.button The button label
83
+ * @property {Object} classes The classes
84
+ * @property {string} classes.bar The bar class
85
+ * @property {string} classes.badge The badge class
86
+ * @property {Array} ignoreChanges The ignore changes (regex)
87
+ * @property {Array} data The data
88
+ * @return {Object}
89
+ */
90
+ get defaults() {
91
+ const obj = Object.assign({}, super.defaults, {
92
+ templates: {
93
+ main: getTemplate(),
94
+ },
95
+
96
+ labels: {
97
+ button: "save",
98
+ },
99
+
100
+ classes: {
101
+ bar: "monster-button-primary",
102
+ badge: "monster-badge-secondary hidden",
103
+ },
104
+
105
+ datasource: {
106
+ selector: null,
107
+ },
108
+
109
+ changes: "0",
110
+
111
+ ignoreChanges: [],
112
+
113
+ data: {},
114
+
115
+ disabled: false,
116
+ });
117
+
118
+ updateOptionsFromArguments.call(this, obj);
119
+ return obj;
120
+ }
121
+
122
+ /**
123
+ *
124
+ * @return {string}
125
+ */
126
+ static getTag() {
127
+ return "monster-datasource-save-button";
128
+ }
129
+
130
+ /**
131
+ * This method is responsible for assembling the component.
132
+ *
133
+ * It calls the parent's assemble method first, then initializes control references and event handlers.
134
+ * If the `datasource.selector` option is provided and is a string, it searches for the corresponding
135
+ * element in the DOM using that selector.
136
+ *
137
+ * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class.
138
+ *
139
+ * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component
140
+ * attaches an observer to the datasource's changes.
141
+ *
142
+ * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component.
143
+ * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges`
144
+ * method in the component's context.
145
+ */
146
+ [assembleMethodSymbol]() {
147
+ super[assembleMethodSymbol]();
148
+ const self = this;
149
+
150
+ initControlReferences.call(this);
151
+ initEventHandler.call(this);
152
+
153
+ const selector = this.getOption("datasource.selector");
154
+
155
+ if (isString(selector)) {
156
+ const element = findElementWithSelectorUpwards(this, selector);
157
+ if (element === null) {
158
+ throw new Error("the selector must match exactly one element");
159
+ }
160
+
161
+ if (!(element instanceof Datasource)) {
162
+ throw new TypeError("the element must be a datasource");
163
+ }
164
+
165
+ this[datasourceLinkedElementSymbol] = element;
166
+ element.datasource.attachObserver(
167
+ new Observer(handleDataSourceChanges.bind(this)),
168
+ );
169
+
170
+ self[originValuesSymbol] = null;
171
+
172
+ element.datasource.attachObserver(
173
+ new Observer(function () {
174
+ if (!self[originValuesSymbol]) {
175
+ self[originValuesSymbol] = clone(
176
+ self[datasourceLinkedElementSymbol].data,
177
+ );
178
+ }
179
+
180
+ const currentValues = this.getRealSubject();
181
+ const ignoreChanges = self.getOption("ignoreChanges");
182
+
183
+ const result = diff(self[originValuesSymbol], currentValues);
184
+ if (isArray(ignoreChanges) && ignoreChanges.length > 0) {
185
+ const itemsToRemove = [];
186
+ for (const item of result) {
187
+ for (const ignorePattern of ignoreChanges) {
188
+ const p = new RegExp(ignorePattern);
189
+ if (p.test(item.path)) {
190
+ itemsToRemove.push(item);
191
+ break;
192
+ }
193
+ }
194
+ }
195
+
196
+ for (const itemToRemove of itemsToRemove) {
197
+ const index = result.indexOf(itemToRemove);
198
+ if (index > -1) {
199
+ result.splice(index, 1);
200
+ }
201
+ }
202
+ }
203
+
204
+ if (isArray(result) && result.length > 0) {
205
+ self[stateButtonElementSymbol].setState("changed");
206
+ self[stateButtonElementSymbol].setOption("disabled", false);
207
+ self.setOption("changes", result.length);
208
+ self.setOption(
209
+ "classes.badge",
210
+ new TokenList(self.getOption("classes.badge"))
211
+ .remove("hidden")
212
+ .toString(),
213
+ );
214
+ } else {
215
+ self[stateButtonElementSymbol].removeState();
216
+ self[stateButtonElementSymbol].setOption("disabled", true);
217
+ self.setOption("changes", 0);
218
+ self.setOption(
219
+ "classes.badge",
220
+ new TokenList(self.getOption("classes.badge"))
221
+ .add("hidden")
222
+ .toString(),
223
+ );
224
+ }
225
+ }),
226
+ );
227
+ }
228
+
229
+ this.attachObserver(
230
+ new Observer(() => {
231
+ handleDataSourceChanges.call(this);
232
+ }),
233
+ );
234
+ }
235
+
236
+ /**
237
+ *
238
+ * @return [CSSStyleSheet]
239
+ */
240
+ static getCSSStyleSheet() {
241
+ return [SaveButtonStyleSheet, BadgeStyleSheet];
242
+ }
241
243
  }
242
244
 
243
245
  /**
@@ -245,78 +247,78 @@ class SaveButton extends CustomElement {
245
247
  * @return {Monster.Components.Datatable.Form}
246
248
  */
247
249
  function initControlReferences() {
248
- if (!this.shadowRoot) {
249
- throw new Error("no shadow-root is defined");
250
- }
251
-
252
- this[stateButtonElementSymbol] = this.shadowRoot.querySelector(
253
- "[data-monster-role=state-button]",
254
- );
255
-
256
- this[badgeElementSymbol] = this.shadowRoot.querySelector(
257
- "[data-monster-role=badge]",
258
- );
259
-
260
- if (this[stateButtonElementSymbol]) {
261
- setTimeout(() => {
262
- const states = {
263
- changed: new State(
264
- "changed",
265
- '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cloud-arrow-up" viewBox="0 0 16 16">\n' +
266
- ' <path fill-rule="evenodd" d="M7.646 5.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 6.707V10.5a.5.5 0 0 1-1 0V6.707L6.354 7.854a.5.5 0 1 1-.708-.708z"/>\n' +
267
- ' <path d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383m.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z"/>\n' +
268
- "</svg>",
269
- ),
270
- };
271
-
272
- this[stateButtonElementSymbol].removeState();
273
- this[stateButtonElementSymbol].setOption("disabled", "disabled");
274
- this[stateButtonElementSymbol].setOption("states", states);
275
- this[stateButtonElementSymbol].setOption(
276
- "labels.button",
277
- this.getOption("labels.button"),
278
- );
279
- }, 1);
280
- }
281
-
282
- return this;
250
+ if (!this.shadowRoot) {
251
+ throw new Error("no shadow-root is defined");
252
+ }
253
+
254
+ this[stateButtonElementSymbol] = this.shadowRoot.querySelector(
255
+ "[data-monster-role=state-button]",
256
+ );
257
+
258
+ this[badgeElementSymbol] = this.shadowRoot.querySelector(
259
+ "[data-monster-role=badge]",
260
+ );
261
+
262
+ if (this[stateButtonElementSymbol]) {
263
+ setTimeout(() => {
264
+ const states = {
265
+ changed: new State(
266
+ "changed",
267
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cloud-arrow-up" viewBox="0 0 16 16">\n' +
268
+ ' <path fill-rule="evenodd" d="M7.646 5.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 6.707V10.5a.5.5 0 0 1-1 0V6.707L6.354 7.854a.5.5 0 1 1-.708-.708z"/>\n' +
269
+ ' <path d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383m.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z"/>\n' +
270
+ "</svg>",
271
+ ),
272
+ };
273
+
274
+ this[stateButtonElementSymbol].removeState();
275
+ this[stateButtonElementSymbol].setOption("disabled", "disabled");
276
+ this[stateButtonElementSymbol].setOption("states", states);
277
+ this[stateButtonElementSymbol].setOption(
278
+ "labels.button",
279
+ this.getOption("labels.button"),
280
+ );
281
+ }, 1);
282
+ }
283
+
284
+ return this;
283
285
  }
284
286
 
285
287
  /**
286
288
  * @private
287
289
  */
288
290
  function initEventHandler() {
289
- setTimeout(() => {
290
- this[stateButtonElementSymbol].setOption("actions.click", () => {
291
- this[datasourceLinkedElementSymbol]
292
- .write()
293
- .then(() => {
294
- this[originValuesSymbol] = null;
295
- this[stateButtonElementSymbol].removeState();
296
- this[stateButtonElementSymbol].setOption("disabled", true);
297
- this.setOption("changes", 0);
298
- this.setOption(
299
- "classes.badge",
300
- new TokenList(this.getOption("classes.badge"))
301
- .add("hidden")
302
- .toString(),
303
- );
304
- })
305
- .catch((error) => {
306
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString());
307
- });
308
- });
309
- }, 1);
291
+ setTimeout(() => {
292
+ this[stateButtonElementSymbol].setOption("actions.click", () => {
293
+ this[datasourceLinkedElementSymbol]
294
+ .write()
295
+ .then(() => {
296
+ this[originValuesSymbol] = null;
297
+ this[stateButtonElementSymbol].removeState();
298
+ this[stateButtonElementSymbol].setOption("disabled", true);
299
+ this.setOption("changes", 0);
300
+ this.setOption(
301
+ "classes.badge",
302
+ new TokenList(this.getOption("classes.badge"))
303
+ .add("hidden")
304
+ .toString(),
305
+ );
306
+ })
307
+ .catch((error) => {
308
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString());
309
+ });
310
+ });
311
+ }, 1);
310
312
  }
311
313
 
312
314
  /**
313
315
  * @param {Object} options
314
316
  */
315
317
  function updateOptionsFromArguments(options) {
316
- const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
317
- if (selector) {
318
- options.datasource.selector = selector;
319
- }
318
+ const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
319
+ if (selector) {
320
+ options.datasource.selector = selector;
321
+ }
320
322
  }
321
323
 
322
324
  /**
@@ -324,8 +326,8 @@ function updateOptionsFromArguments(options) {
324
326
  * @return {string}
325
327
  */
326
328
  function getTemplate() {
327
- // language=HTML
328
- return `
329
+ // language=HTML
330
+ return `
329
331
  <div data-monster-role="control" part="control"
330
332
  data-monster-attributes="disabled path:disabled | if:true">
331
333
  <monster-state-button data-monster-role="state-button">save</monster-state-button>
@@ -51,7 +51,6 @@ export const buttonElementSymbol = Symbol("buttonElement");
51
51
  * @copyright schukai GmbH
52
52
  * @summary A beautiful button that can make your life easier and also looks good.
53
53
  * @fires monster-button-clicked this event is triggered when the button is clicked. It contains the field {button} with the button instance.
54
- *
55
54
  */
56
55
  class Button extends CustomControl {
57
56
  /**