@schukai/monster 3.95.2 → 3.96.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/package.json +1 -1
  3. package/source/components/content/copy.mjs +1 -1
  4. package/source/components/datatable/dataset.mjs +29 -25
  5. package/source/components/datatable/datasource/dom.mjs +4 -6
  6. package/source/components/datatable/datasource/rest.mjs +472 -474
  7. package/source/components/datatable/datasource.mjs +0 -8
  8. package/source/components/datatable/pagination.mjs +434 -440
  9. package/source/components/datatable/status.mjs +1 -3
  10. package/source/components/datatable/stylesheet/pagination.mjs +13 -6
  11. package/source/components/datatable/util.mjs +1 -1
  12. package/source/components/form/api-bar.mjs +1 -1
  13. package/source/components/form/api-button.mjs +1 -1
  14. package/source/components/form/button-bar.mjs +1 -1
  15. package/source/components/form/button.mjs +2 -2
  16. package/source/components/form/confirm-button.mjs +1 -1
  17. package/source/components/form/form.mjs +7 -5
  18. package/source/components/form/select.mjs +2014 -2006
  19. package/source/components/form/style/field-set.pcss +9 -0
  20. package/source/components/form/style/toggle-switch.pcss +3 -0
  21. package/source/components/form/stylesheet/field-set.mjs +7 -14
  22. package/source/components/form/stylesheet/toggle-switch.mjs +7 -14
  23. package/source/components/form/toggle-switch.mjs +386 -334
  24. package/source/components/layout/tabs.mjs +900 -898
  25. package/source/components/layout/width-toggle.mjs +1 -1
  26. package/source/components/navigation/table-of-content.mjs +1 -1
  27. package/source/components/notify/message.mjs +11 -15
  28. package/source/components/notify/notify.mjs +11 -15
  29. package/source/components/notify/stylesheet/notify.mjs +13 -6
  30. package/source/components/state/log.mjs +185 -185
  31. package/source/components/state/state.mjs +1 -1
  32. package/source/components/state/stylesheet/log.mjs +13 -6
  33. package/source/components/style/theme.css +4 -4
  34. package/source/data/datasource/server/restapi.mjs +2 -3
  35. package/source/data/transformer.mjs +803 -806
  36. package/source/dom/constants.mjs +8 -5
  37. package/source/dom/customelement.mjs +0 -34
  38. package/source/dom/updater.mjs +764 -767
  39. package/source/i18n/time-ago.mjs +1352 -636
  40. package/source/monster.mjs +2 -0
  41. package/source/types/has.mjs +3 -6
  42. package/source/types/version.mjs +1 -1
  43. package/test/cases/components/form/form.mjs +166 -125
  44. package/test/cases/components/form/toggle-switch.mjs +80 -65
  45. package/test/cases/monster.mjs +1 -1
  46. package/test/web/import.js +1 -0
  47. package/test/web/test.html +2 -2
  48. package/test/web/tests.js +2080 -1433
@@ -12,26 +12,24 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import { instanceSymbol } from "../../constants.mjs";
16
- import { internalSymbol } from "../../constants.mjs";
17
- import { CustomControl } from "../../dom/customcontrol.mjs";
18
- import { Observer } from "../../types/observer.mjs";
19
- import { ProxyObserver } from "../../types/proxyobserver.mjs";
15
+ import {instanceSymbol, internalSymbol} from "../../constants.mjs";
16
+ import {CustomControl} from "../../dom/customcontrol.mjs";
17
+ import {Observer} from "../../types/observer.mjs";
18
+ import {ProxyObserver} from "../../types/proxyobserver.mjs";
20
19
 
21
- import { addAttributeToken } from "../../dom/attributes.mjs";
20
+ import {addAttributeToken} from "../../dom/attributes.mjs";
22
21
  import {
23
- assembleMethodSymbol,
24
- registerCustomElement,
25
- updaterTransformerMethodsSymbol,
22
+ assembleMethodSymbol,
23
+ registerCustomElement,
24
+ updaterTransformerMethodsSymbol,
26
25
  } from "../../dom/customelement.mjs";
27
- import { isObject, isFunction } from "../../types/is.mjs";
28
- import { ToggleSwitchStyleSheet } from "./stylesheet/toggle-switch.mjs";
29
- import {
30
- ATTRIBUTE_ERRORMESSAGE,
31
- ATTRIBUTE_ROLE,
32
- } from "../../dom/constants.mjs";
26
+ import {isFunction, isObject} from "../../types/is.mjs";
27
+ import {ToggleSwitchStyleSheet} from "./stylesheet/toggle-switch.mjs";
28
+ import {ATTRIBUTE_ERRORMESSAGE, ATTRIBUTE_ROLE,} from "../../dom/constants.mjs";
29
+ import {getWindow} from "../../dom/util.mjs";
30
+ import {fireEvent} from "../../dom/events.mjs";
33
31
 
34
- export { ToggleSwitch };
32
+ export {ToggleSwitch};
35
33
 
36
34
  /**
37
35
  * @private
@@ -54,7 +52,7 @@ export const STATE_OFF = "off";
54
52
  *
55
53
  * @fragments /fragments/components/form/toggle-switch
56
54
  *
57
- * @example /examples/components/form/toggle-switch-simple
55
+ * @example /examples/components/form/toggle-switch-simple Simple example
58
56
  *
59
57
  * @since 3.57.0
60
58
  * @copyright schukai GmbH
@@ -65,340 +63,374 @@ export const STATE_OFF = "off";
65
63
  * @fires monster-changed
66
64
  */
67
65
  class ToggleSwitch extends CustomControl {
68
- /**
69
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
70
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
71
- *
72
- * The individual configuration values can be found in the table.
73
- *
74
- * @property {string} value=current value of the element
75
- * @property {Boolean} disabled=disabled=false Disabled state
76
- * @property {Object} classes
77
- * @property {string} classes.on=specifies the class for the on state.
78
- * @property {string} classes.off=specifies the class for the off state.
79
- * @property {Object} values
80
- * @property {string} values.off=specifies the value of the element if it is not selected
81
- * @property {Object} labels
82
- * @property {string} labels.on=specifies the label for the on state.
83
- * @property {string} labels.off=specifies the label for the off state.
84
- * @property {string} actions
85
- * @property {string} actions.on=specifies the action for the on state.
86
- * @property {string} actions.off=specifies the action for the off state.
87
- * @property {Object} templates
88
- * @property {string} templates.main=specifies the main template used by the control.
89
- */
90
- get defaults() {
91
- return Object.assign({}, super.defaults, {
92
- value: null,
93
- disabled: false,
94
- classes: {
95
- on: "monster-theme-on",
96
- off: "monster-theme-off",
97
- handle: "monster-theme-primary-1",
98
- },
99
- values: {
100
- on: "on",
101
- off: "off",
102
- },
103
- labels: {
104
- toggleSwitchOn: "✔",
105
- toggleSwitchOff: "",
106
- },
107
- templates: {
108
- main: getTemplate(),
109
- },
110
- actions: {
111
- on: () => {
112
-
113
- },
114
- off: () => {
115
-
116
- },
117
- },
118
- });
119
- }
120
-
121
- /**
122
- * @return {ToggleSwitch}
123
- */
124
- [assembleMethodSymbol]() {
125
- const self = this;
126
- super[assembleMethodSymbol]();
127
- initControlReferences.call(this);
128
- initEventHandler.call(this);
129
-
130
- /**
131
- * init value to off
132
- * if the value was not defined before inserting it into the HTML
133
- */
134
- if (self.getOption("value") === null) {
135
- self.setOption("value", self.getOption("values.off"));
136
- }
137
-
138
- /**
139
- * value from attribute
140
- */
141
- if (self.hasAttribute("value")) {
142
- self.setOption("value", self.getAttribute("value"));
143
- }
144
-
145
- /**
146
- * validate value
147
- */
148
- validateAndSetValue.call(self);
149
-
150
- if (this.state === STATE_ON) {
151
- toggleClassOn.call(self);
152
- } else {
153
- toggleClassOff.call(self);
154
- }
155
-
156
- /**
157
- * is called when options changed
158
- */
159
- self[internalSymbol].attachObserver(
160
- new Observer(function () {
161
- if (isObject(this) && this instanceof ProxyObserver) {
162
- validateAndSetValue.call(self);
163
- toggleClass.call(self);
164
- }
165
- }),
166
- );
167
-
168
- return this;
169
- }
170
-
171
- /**
172
- * updater transformer methods for pipe
173
- *
174
- * @return {function}
175
- */
176
- [updaterTransformerMethodsSymbol]() {
177
- return {
178
- "state-callback": (Wert) => {
179
- return this.state;
180
- },
181
- };
182
- }
183
-
184
- /**
185
- * @return [CSSStyleSheet]
186
- */
187
- static getCSSStyleSheet() {
188
- return [ToggleSwitchStyleSheet];
189
- }
190
-
191
- /**
192
- * toggle switch
193
- *
194
- * ```
195
- * e = document.querySelector('monster-toggle-switch');
196
- * e.click()
197
- * ```
198
- */
199
- click() {
200
- toggleValues.call(this);
201
- }
202
-
203
- /**
204
- * toggle switch on/off
205
- *
206
- * ```
207
- * e = document.querySelector('monster-toggle-switch');
208
- * e.toggle()
209
- * ```
210
- *
211
- * @return {ToggleSwitch}
212
- */
213
- toggle() {
214
- this.click();
215
- return this;
216
- }
217
-
218
- /**
219
- * toggle switch on
220
- *
221
- * ```
222
- * e = document.querySelector('monster-toggle-switch');
223
- * e.toggleOn()
224
- * ```
225
- *
226
- * @return {ToggleSwitch}
227
- */
228
- toggleOn() {
229
- this.setOption("value", this.getOption("values.on"));
230
- return this;
231
- }
232
-
233
- /**
234
- * toggle switch off
235
- *
236
- * ```
237
- * e = document.querySelector('monster-toggle-switch');
238
- * e.toggleOff()
239
- * ```
240
- *
241
- * @return {ToggleSwitch}
242
- */
243
- toggleOff() {
244
- this.setOption("value", this.getOption("values.off"));
245
- return this;
246
- }
247
-
248
- /**
249
- * returns the status of the element
250
- *
251
- * ```
252
- * e = document.querySelector('monster-toggle-switch');
253
- * console.log(e.state)
254
- * // ↦ off
255
- * ```
256
- *
257
- * @return {string}
258
- */
259
- get state() {
260
- return this.getOption("value") === this.getOption("values.on")
261
- ? STATE_ON
262
- : STATE_OFF;
263
- }
264
-
265
- /**
266
- * The current value of the Switch
267
- *
268
- * ```
269
- * e = document.querySelector('monster-toggle-switch');
270
- * console.log(e.value)
271
- * // ↦ on
272
- * ```
273
- *
274
- * @return {string}
275
- */
276
- get value() {
277
- return this.state === STATE_ON
278
- ? this.getOption("values.on")
279
- : this.getOption("values.off");
280
- }
281
-
282
- /**
283
- * Set value
284
- *
285
- * ```
286
- * e = document.querySelector('monster-toggle-switch');
287
- * e.value="on"
288
- * ```
289
- *
290
- * @property {string} value
291
- */
292
- set value(value) {
293
- this.setOption("value", value);
294
- }
295
-
296
- /**
297
- * This method is called by the `instanceof` operator.
298
- * @return {symbol}
299
- */
300
- static get [instanceSymbol]() {
301
- return Symbol.for(
302
- "@schukai/monster/components/form/toggle-switch@@instance",
303
- );
304
- }
305
-
306
- static getTag() {
307
- return "monster-toggle-switch";
308
- }
66
+ /**
67
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
68
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
69
+ *
70
+ * The individual configuration values can be found in the table.
71
+ *
72
+ * @property {string} value=current value of the element
73
+ * @property {Boolean} disabled=disabled=false Disabled state
74
+ * @property {Object} classes
75
+ * @property {string} classes.on=specifies the class for the on state.
76
+ * @property {string} classes.off=specifies the class for the off state.
77
+ * @property {Object} values
78
+ * @property {string} values.off=specifies the value of the element if it is not selected
79
+ * @property {Object} labels
80
+ * @property {string} labels.on=specifies the label for the on state.
81
+ * @property {string} labels.off=specifies the label for the off state.
82
+ * @property {string} actions
83
+ * @property {string} actions.on=specifies the action for the on state.
84
+ * @property {string} actions.off=specifies the action for the off state.
85
+ * @property {Object} templates
86
+ * @property {string} templates.main the main template used by the control.
87
+ */
88
+ get defaults() {
89
+ return Object.assign({}, super.defaults, {
90
+ value: null,
91
+ disabled: false,
92
+ classes: {
93
+ on: "monster-theme-on",
94
+ off: "monster-theme-off",
95
+ handle: "monster-theme-primary-1",
96
+ error: "monster-theme-error-1",
97
+ },
98
+ values: {
99
+ on: "on",
100
+ off: "off",
101
+ },
102
+ labels: {
103
+ toggleSwitchOn: "",
104
+ toggleSwitchOff: "✖",
105
+ },
106
+ templates: {
107
+ main: getTemplate(),
108
+ },
109
+ actions: {
110
+ on: () => {
111
+ },
112
+ off: () => {
113
+ },
114
+ },
115
+ });
116
+ }
117
+
118
+ /**
119
+ * @return {void}
120
+ */
121
+ [assembleMethodSymbol]() {
122
+ const self = this;
123
+ super[assembleMethodSymbol]();
124
+
125
+ initControlReferences.call(this);
126
+ initEventHandler.call(this);
127
+
128
+ getWindow().requestAnimationFrame(() => {
129
+
130
+ /**
131
+ * init value to off
132
+ * if the value was not defined before inserting it into the HTML
133
+ */
134
+ if (self.getOption("value") === null) {
135
+ self.setOption("value", self.getOption("values.off"));
136
+ }
137
+
138
+ /**
139
+ * value from attribute
140
+ */
141
+ if (self.hasAttribute("value")) {
142
+ self.setOption("value", self.getAttribute("value"));
143
+ }
144
+
145
+ /**
146
+ * validate value
147
+ */
148
+ validateAndSetValue.call(self);
149
+
150
+ // this state is a getter
151
+ if (this.state === STATE_ON) {
152
+ toggleOn.call(self);
153
+ } else {
154
+ toggleOff.call(self);
155
+ }
156
+
157
+ });
158
+
159
+ }
160
+
161
+ /**
162
+ * updater transformer methods for pipe
163
+ *
164
+ * @return {function}
165
+ */
166
+ [updaterTransformerMethodsSymbol]() {
167
+ return {
168
+ "state-callback": (Wert) => {
169
+ return this.state;
170
+ },
171
+ };
172
+ }
173
+
174
+ /**
175
+ * @return [CSSStyleSheet]
176
+ */
177
+ static getCSSStyleSheet() {
178
+ return [ToggleSwitchStyleSheet];
179
+ }
180
+
181
+ /**
182
+ * toggle switch
183
+ *
184
+ * ```
185
+ * e = document.querySelector('monster-toggle-switch');
186
+ * e.click()
187
+ * ```
188
+ */
189
+ click() {
190
+ this.toggle();
191
+ }
192
+
193
+ /**
194
+ * toggle switch on/off
195
+ *
196
+ * ```
197
+ * e = document.querySelector('monster-toggle-switch');
198
+ * e.toggle()
199
+ * ```
200
+ *
201
+ * @return {ToggleSwitch}
202
+ */
203
+ toggle() {
204
+ if (this.getOption("value") === this.getOption("values.on")) {
205
+ return this.toggleOff()
206
+ }
207
+ return this.toggleOn()
208
+ }
209
+
210
+ /**
211
+ * toggle switch on
212
+ *
213
+ * ```
214
+ * e = document.querySelector('monster-toggle-switch');
215
+ * e.toggleOn()
216
+ * ```
217
+ *
218
+ * @return {ToggleSwitch}
219
+ */
220
+ toggleOn() {
221
+ this.setOption("value", this.getOption("values.on"));
222
+ fireEvent(this, "change");
223
+ return this;
224
+ }
225
+
226
+ /**
227
+ * toggle switch off
228
+ *
229
+ * ```
230
+ * e = document.querySelector('monster-toggle-switch');
231
+ * e.toggleOff()
232
+ * ```
233
+ *
234
+ * @return {ToggleSwitch}
235
+ */
236
+ toggleOff() {
237
+ this.setOption("value", this.getOption("values.off"));
238
+ fireEvent(this, "change");
239
+ return this;
240
+ }
241
+
242
+ /**
243
+ * returns the status of the element
244
+ *
245
+ * ```
246
+ * e = document.querySelector('monster-toggle-switch');
247
+ * console.log(e.state)
248
+ * // ↦ off
249
+ * ```
250
+ *
251
+ * @return {string}
252
+ */
253
+ get state() {
254
+ return this.getOption("value") === this.getOption("values.on")
255
+ ? STATE_ON
256
+ : STATE_OFF;
257
+ }
258
+
259
+ /**
260
+ * The current value of the Switch
261
+ *
262
+ * ```
263
+ * e = document.querySelector('monster-toggle-switch');
264
+ * console.log(e.value)
265
+ * // ↦ on
266
+ * ```
267
+ *
268
+ * @return {string}
269
+ */
270
+ get value() {
271
+ return this.getOption("value");
272
+ }
273
+
274
+ /**
275
+ * Set value
276
+ *
277
+ * ```
278
+ * e = document.querySelector('monster-toggle-switch');
279
+ * e.value="on"
280
+ * ```
281
+ *
282
+ * @property {string} value
283
+ */
284
+ set value(value) {
285
+
286
+ if (value === this.getOption("values.on") || value === this.getOption("values.off")) {
287
+ if (this.state !== (value === this.getOption("values.on") ? STATE_ON : STATE_OFF)) {
288
+ this.setOption("value", value);
289
+ }
290
+ return;
291
+ }
292
+
293
+ addAttributeToken(
294
+ this,
295
+ ATTRIBUTE_ERRORMESSAGE,
296
+ 'The value "' +
297
+ value +
298
+ '" must be "' +
299
+ this.getOption("values.on") +
300
+ '" or "' +
301
+ this.getOption("values.off"),
302
+ );
303
+
304
+ showError.call(this);
305
+
306
+
307
+ }
308
+
309
+ /**
310
+ * This method is called by the `instanceof` operator.
311
+ * @return {symbol}
312
+ */
313
+ static get [instanceSymbol]() {
314
+ return Symbol.for(
315
+ "@schukai/monster/components/form/toggle-switch@@instance",
316
+ );
317
+ }
318
+
319
+ /**
320
+ *
321
+ * @returns {string}
322
+ */
323
+ static getTag() {
324
+ return "monster-toggle-switch";
325
+ }
309
326
  }
310
327
 
311
328
  /**
312
329
  * @private
313
330
  */
314
331
  function initControlReferences() {
315
- this[switchElementSymbol] = this.shadowRoot.querySelector(
316
- `[${ATTRIBUTE_ROLE}=switch]`,
317
- );
332
+ this[switchElementSymbol] = this.shadowRoot.querySelector(
333
+ `[${ATTRIBUTE_ROLE}=switch]`,
334
+ );
318
335
  }
319
336
 
320
- /**
321
- * @private
322
- */
323
- function toggleClassOn() {
324
- this[switchElementSymbol].classList.remove(this.getOption("classes.off")); // change color
325
- this[switchElementSymbol].classList.add(this.getOption("classes.on")); // change color
326
- }
327
337
 
328
338
  /**
329
339
  * @private
330
340
  */
331
- function toggleClassOff() {
332
- this[switchElementSymbol].classList.remove(this.getOption("classes.on")); // change color
333
- this[switchElementSymbol].classList.add(this.getOption("classes.off")); // change color
334
- }
341
+ function toggleOn() {
335
342
 
336
- /**
337
- * @private
338
- */
339
- function toggleClass() {
340
- if (this.getOption("value") === this.getOption("values.on")) {
341
- toggleClassOn.call(this);
342
- } else {
343
- toggleClassOff.call(this);
344
- }
343
+ if (!this[switchElementSymbol]) {
344
+ return;
345
+ }
346
+
347
+ this[switchElementSymbol].classList.remove(this.getOption("classes.off")); // change color
348
+ this[switchElementSymbol].classList.add(this.getOption("classes.on")); // change color
349
+
350
+ const callback = this.getOption("actions.on");
351
+ if (isFunction(callback)) {
352
+ callback.call(this);
353
+ }
354
+
355
+ if (typeof this.setFormValue === "function") {
356
+ this.setFormValue(this.getOption("values.on"));
357
+ }
345
358
  }
346
359
 
347
360
  /**
348
361
  * @private
349
362
  */
350
- function toggleValues() {
351
- if (this.getOption("disabled") === true) {
352
- return;
353
- }
363
+ function toggleOff() {
364
+
365
+ if (!this[switchElementSymbol]) {
366
+ return;
367
+ }
354
368
 
355
- let callback, value;
369
+ this[switchElementSymbol].classList.remove(this.getOption("classes.on")); // change color
370
+ this[switchElementSymbol].classList.add(this.getOption("classes.off")); // change color
356
371
 
357
- if (this.getOption("value") === this.getOption("values.on")) {
358
- value = this.getOption("values.off");
359
- callback = this.getOption("actions.off");
360
- } else {
361
- value = this.getOption("values.on");
362
- callback = this.getOption("actions.on");
363
- }
372
+ const callback = this.getOption("actions.off");
373
+ if (isFunction(callback)) {
374
+ callback.call(this);
375
+ }
364
376
 
365
- this.setOption("value", value);
366
- this?.setFormValue(value);
377
+ if (typeof this.setFormValue === "function") {
378
+ this.setFormValue(this.getOption("values.off"));
379
+ }
367
380
 
368
- if (isFunction(callback)) {
369
- callback.call(this);
370
- }
371
381
 
372
- this.setOption("state", this.state);
382
+ }
383
+
384
+ function showError() {
385
+
386
+ if (!this[switchElementSymbol]) {
387
+ return;
388
+ }
389
+
390
+ this[switchElementSymbol].classList.remove(this.getOption("classes.on"));
391
+ this[switchElementSymbol].classList.remove(this.getOption("classes.off"));
392
+ this[switchElementSymbol].classList.add(this.getOption("classes.error"));
373
393
  }
374
394
 
375
395
  /**
376
396
  * @private
377
397
  */
378
398
  function validateAndSetValue() {
379
- const value = this.getOption("value");
380
-
381
- const validatedValues = [];
382
- validatedValues.push(this.getOption("values.on"));
383
- validatedValues.push(this.getOption("values.off"));
384
-
385
- if (validatedValues.includes(value) === false) {
386
- addAttributeToken(
387
- this,
388
- ATTRIBUTE_ERRORMESSAGE,
389
- 'The value "' +
390
- value +
391
- '" must be "' +
392
- this.getOption("values.on") +
393
- '" or "' +
394
- this.getOption("values.off"),
395
- );
396
- this.setOption("disabled", true);
397
- this.formDisabledCallback(true);
398
- } else {
399
- this.setOption("disabled", false);
400
- this.formDisabledCallback(false);
401
- }
399
+
400
+ const value = this.getOption("value");
401
+
402
+ const validatedValues = [];
403
+ validatedValues.push(this.getOption("values.on"));
404
+ validatedValues.push(this.getOption("values.off"));
405
+
406
+ if (validatedValues.includes(value) === false) {
407
+ addAttributeToken(
408
+ this,
409
+ ATTRIBUTE_ERRORMESSAGE,
410
+ 'The value "' +
411
+ value +
412
+ '" must be "' +
413
+ this.getOption("values.on") +
414
+ '" or "' +
415
+ this.getOption("values.off"),
416
+ );
417
+ this.setOption("disabled", true);
418
+ this.formDisabledCallback(true);
419
+ showError.call(this);
420
+ return;
421
+ }
422
+
423
+ this.setOption("disabled", false);
424
+ this.formDisabledCallback(false);
425
+
426
+ if (value === this.getOption("values.on")) {
427
+ toggleOn.call(this);
428
+ return;
429
+ }
430
+
431
+ toggleOff.call(this);
432
+
433
+
402
434
  }
403
435
 
404
436
  /**
@@ -406,16 +438,36 @@ function validateAndSetValue() {
406
438
  * @return {initEventHandler}
407
439
  */
408
440
  function initEventHandler() {
409
- const self = this;
410
- self.addEventListener("keyup", function (event) {
411
- if (event.code === "Space") {
412
- self[switchElementSymbol].click();
413
- }
414
- });
415
- self.addEventListener("click", function (event) {
416
- toggleValues.call(self);
417
- });
418
- return this;
441
+ const self = this;
442
+
443
+ let lastValue = self.value;
444
+ self[internalSymbol].attachObserver(
445
+ new Observer(function () {
446
+ if (isObject(this) && this instanceof ProxyObserver) {
447
+ const n = this.getSubject()?.options?.value;
448
+ if (lastValue !== n) {
449
+ lastValue = n;
450
+ validateAndSetValue.call(self);
451
+ }
452
+ }
453
+ }),
454
+ );
455
+
456
+ self.addEventListener("keyup", (event) => {
457
+ if (event.keyCode === 32) {
458
+ self.toggle();
459
+ }
460
+ });
461
+
462
+ self.addEventListener("click", (event) => {
463
+ self.toggle();
464
+ });
465
+
466
+ self.addEventListener("touch", (event) => {
467
+ self.toggle();
468
+ });
469
+
470
+ return this;
419
471
  }
420
472
 
421
473
  /**
@@ -423,8 +475,8 @@ function initEventHandler() {
423
475
  * @return {string}
424
476
  */
425
477
  function getTemplate() {
426
- // language=HTML
427
- return `
478
+ // language=HTML
479
+ return `
428
480
  <div data-monster-role="control" part="control" tabindex="0">
429
481
  <div class="switch" data-monster-role="switch"
430
482
  data-monster-attributes="data-monster-state path:value | call:state-callback">