@schukai/monster 3.96.0 → 3.96.2

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 (40) hide show
  1. package/CHANGELOG.md +22 -5
  2. package/package.json +1 -1
  3. package/source/components/content/copy.mjs +1 -1
  4. package/source/components/datatable/change-button.mjs +39 -41
  5. package/source/components/datatable/dataset.mjs +337 -327
  6. package/source/components/datatable/datasource/rest.mjs +3 -22
  7. package/source/components/datatable/embedded-pagination.mjs +3 -1
  8. package/source/components/datatable/pagination.mjs +14 -7
  9. package/source/components/datatable/save-button.mjs +25 -3
  10. package/source/components/datatable/status.mjs +21 -26
  11. package/source/components/datatable/style/status.pcss +12 -2
  12. package/source/components/datatable/stylesheet/status.mjs +1 -1
  13. package/source/components/datatable/util.mjs +1 -2
  14. package/source/components/form/api-bar.mjs +1 -1
  15. package/source/components/form/api-button.mjs +1 -1
  16. package/source/components/form/button-bar.mjs +1 -1
  17. package/source/components/form/button.mjs +2 -2
  18. package/source/components/form/confirm-button.mjs +1 -1
  19. package/source/components/form/form.mjs +6 -5
  20. package/source/components/form/select.mjs +12 -9
  21. package/source/components/form/style/field-set.pcss +35 -5
  22. package/source/components/form/style/toggle-switch.pcss +16 -2
  23. package/source/components/form/stylesheet/field-set.mjs +1 -1
  24. package/source/components/form/stylesheet/toggle-switch.mjs +1 -1
  25. package/source/components/form/toggle-switch.mjs +139 -91
  26. package/source/components/layout/tabs.mjs +4 -5
  27. package/source/components/layout/width-toggle.mjs +1 -1
  28. package/source/components/navigation/table-of-content.mjs +1 -1
  29. package/source/components/notify/message.mjs +1 -1
  30. package/source/components/notify/notify.mjs +2 -2
  31. package/source/components/state/log.mjs +1 -1
  32. package/source/components/state/state.mjs +1 -1
  33. package/source/components/style/theme.css +4 -4
  34. package/source/dom/constants.mjs +7 -5
  35. package/source/dom/updater.mjs +3 -6
  36. package/source/types/version.mjs +1 -1
  37. package/test/cases/components/form/toggle-switch.mjs +80 -65
  38. package/test/cases/monster.mjs +1 -1
  39. package/test/web/test.html +2 -2
  40. package/test/web/tests.js +154 -104
@@ -12,38 +12,42 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import {instanceSymbol} from "../../constants.mjs";
16
- import {Pathfinder} from "../../data/pathfinder.mjs";
15
+ import { instanceSymbol } from "../../constants.mjs";
16
+ import { Pathfinder } from "../../data/pathfinder.mjs";
17
17
  import {
18
- assembleMethodSymbol,
19
- CustomElement,
20
- attributeObserverSymbol,
21
- registerCustomElement,
18
+ assembleMethodSymbol,
19
+ CustomElement,
20
+ attributeObserverSymbol,
21
+ registerCustomElement,
22
22
  } from "../../dom/customelement.mjs";
23
- import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
24
- import {isString} from "../../types/is.mjs";
25
- import {Observer} from "../../types/observer.mjs";
26
23
  import {
27
- ATTRIBUTE_DATASOURCE_SELECTOR,
28
- ATTRIBUTE_DATATABLE_INDEX,
24
+ findElementWithSelectorUpwards,
25
+ getDocument,
26
+ getWindow,
27
+ } from "../../dom/util.mjs";
28
+ import { isString } from "../../types/is.mjs";
29
+ import { Observer } from "../../types/observer.mjs";
30
+ import {
31
+ ATTRIBUTE_DATASOURCE_SELECTOR,
32
+ ATTRIBUTE_DATATABLE_INDEX,
29
33
  } from "./constants.mjs";
30
- import {Datasource} from "./datasource.mjs";
31
- import {DatasetStyleSheet} from "./stylesheet/dataset.mjs";
34
+ import { Datasource } from "./datasource.mjs";
35
+ import { DatasetStyleSheet } from "./stylesheet/dataset.mjs";
32
36
  import {
33
- handleDataSourceChanges,
34
- datasourceLinkedElementSymbol,
37
+ handleDataSourceChanges,
38
+ datasourceLinkedElementSymbol,
35
39
  } from "./util.mjs";
36
- import {FormStyleSheet} from "../stylesheet/form.mjs";
40
+ import { FormStyleSheet } from "../stylesheet/form.mjs";
37
41
 
38
- export {DataSet};
42
+ export { DataSet };
39
43
 
40
44
  /**
41
45
  * A data set component
42
46
  *
43
47
  * @fragments /fragments/components/datatable/dataset
44
48
  *
45
- * @example /examples/components/datatable/dataset-dom
46
- * @example /examples/components/datatable/dataset-rest
49
+ * @example /examples/components/datatable/dataset-dom Dom dataset
50
+ * @example /examples/components/datatable/dataset-rest Rest dataset
47
51
  *
48
52
  * @issue https://localhost.alvine.dev:8443/development/issues/closed/272.html
49
53
  *
@@ -51,277 +55,283 @@ export {DataSet};
51
55
  * @summary A dataset component that can be used to show the data of a data source
52
56
  */
53
57
  class DataSet extends CustomElement {
54
- /**
55
- * This method is called by the `instanceof` operator.
56
- * @return {symbol}
57
- */
58
- static get [instanceSymbol]() {
59
- return Symbol.for("@schukai/monster/components/dataset@@instance");
60
- }
61
-
62
- /**
63
- * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
64
- *
65
- * @return {string[]}
66
- * @since 1.15.0
67
- */
68
- static get observedAttributes() {
69
- const attributes = super.observedAttributes;
70
- attributes.push(ATTRIBUTE_DATATABLE_INDEX);
71
- attributes.push("data-monster-option-mapping-index");
72
- return attributes;
73
- }
74
-
75
- /**
76
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
77
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
78
- *
79
- * The individual configuration values can be found in the table.
80
- *
81
- * @property {Object} templates Template definitions
82
- * @property {string} templates.main Main template
83
- * @property {object} datasource The datasource
84
- * @property {string} datasource.selector The selector of the datasource
85
- * @property {object} mapping The mapping
86
- * @property {string} mapping.data The data
87
- * @property {number} mapping.index The index
88
- * @property {object} features The features
89
- * @property {boolean} features.refreshOnMutation Refresh on mutation
90
- * @property {object} refreshOnMutation The refresh on mutation
91
- * @property {string} refreshOnMutation.selector The selector
92
- */
93
- get defaults() {
94
- const obj = Object.assign({}, super.defaults, {
95
- templates: {
96
- main: getTemplate(),
97
- },
98
-
99
- datasource: {
100
- selector: null,
101
- },
102
-
103
- mapping: {
104
- data: "dataset",
105
- index: 0,
106
- },
107
-
108
- features: {
109
- /**
110
- * @since 3.70.0
111
- * @type {boolean}
112
- */
113
- refreshOnMutation: true,
114
- },
115
-
116
- /**
117
- * @since 3.70.0
118
- * @type {boolean}
119
- */
120
- refreshOnMutation: {
121
- selector: "input, select, textarea",
122
- },
123
-
124
- data: {},
125
- });
126
-
127
- updateOptionsFromArguments.call(this, obj);
128
- return obj;
129
- }
130
-
131
- /**
132
- *
133
- * @return {string}
134
- */
135
- static getTag() {
136
- return "monster-dataset";
137
- }
138
-
139
- /**
140
- * This method is called when the component is created.
141
- * @since 3.70.0
142
- * @return {DataSet}
143
- */
144
- refresh() {
145
- // makes sure that handleDataSourceChanges is called
146
- this.setOption("data", {});
147
- return this;
148
- }
149
-
150
- /**
151
- *
152
- * @return {Promise<unknown>}
153
- */
154
- write() {
155
- return new Promise((resolve, reject) => {
156
- if (!this[datasourceLinkedElementSymbol]) {
157
- reject(new Error("No datasource"));
158
- return;
159
- }
160
-
161
- const internalUpdateCloneData = this.getInternalUpdateCloneData();
162
- if (!internalUpdateCloneData) {
163
- reject(new Error("No update data"));
164
- return;
165
- }
166
-
167
- const internalData = internalUpdateCloneData?.["data"];
168
- if (
169
- internalData === undefined ||
170
- internalData === null ||
171
- internalData === ""
172
- ) {
173
- reject(new Error("No data"));
174
- return;
175
- }
176
-
177
- queueMicrotask(() => {
178
- const path = this.getOption("mapping.data");
179
- const index = this.getOption("mapping.index");
180
-
181
- let pathWithIndex;
182
-
183
- if (isString(path) && path !== "") {
184
- pathWithIndex = path + "." + index;
185
- } else {
186
- pathWithIndex = String(index);
187
- }
188
-
189
- const data = this[datasourceLinkedElementSymbol]?.data;
190
- if (!data) {
191
- reject(new Error("No data"));
192
- return;
193
- }
194
-
195
- const unref = JSON.stringify(data);
196
- const ref = JSON.parse(unref);
197
-
198
- new Pathfinder(ref).setVia(pathWithIndex, internalData);
199
-
200
- this[datasourceLinkedElementSymbol].data = ref;
201
-
202
- resolve();
203
- });
204
- });
205
- }
206
-
207
- /**
208
- * This method is responsible for assembling the component.
209
- *
210
- * It calls the parent's assemble method first, then initializes control references and event handlers.
211
- * If the `datasource.selector` option is provided and is a string, it searches for the corresponding
212
- * element in the DOM using that selector.
213
- *
214
- * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class.
215
- *
216
- * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component
217
- * attaches an observer to the datasource's changes.
218
- *
219
- * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component.
220
- * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges`
221
- * method in the component's context.
222
- */
223
- [assembleMethodSymbol]() {
224
- super[assembleMethodSymbol]();
225
-
226
- requestAnimationFrame(() => {
227
- if (!this[datasourceLinkedElementSymbol]) {
228
- const selector = this.getOption("datasource.selector");
229
-
230
- if (isString(selector)) {
231
- const element = findElementWithSelectorUpwards(this, selector);
232
- if (element === null) {
233
- throw new Error("the selector must match exactly one element");
234
- }
235
-
236
- if (!(element instanceof Datasource)) {
237
- throw new TypeError("the element must be a datasource");
238
- }
239
-
240
- this[datasourceLinkedElementSymbol] = element;
241
- element.datasource.attachObserver(
242
- new Observer(handleDataSourceChanges.bind(this)),
243
- );
244
-
245
- handleDataSourceChanges.call(this);
246
- } else {
247
- throw new Error("the selector must be a string");
248
- }
249
- }
250
-
251
- if (
252
- this.getOption("features.refreshOnMutation") &&
253
- this.getOption("refreshOnMutation.selector")
254
- ) {
255
- initMutationObserver.call(this);
256
- }
257
-
258
- initEventHandler.call(this);
259
- });
260
- }
261
-
262
- /**
263
- * @return [CSSStyleSheet]
264
- */
265
- static getCSSStyleSheet() {
266
- return [FormStyleSheet, DatasetStyleSheet];
267
- }
58
+ /**
59
+ * This method is called by the `instanceof` operator.
60
+ * @return {symbol}
61
+ */
62
+ static get [instanceSymbol]() {
63
+ return Symbol.for(
64
+ "@schukai/monster/components/datatable/dataset@@instance",
65
+ );
66
+ }
67
+
68
+ /**
69
+ * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
70
+ *
71
+ * @return {string[]}
72
+ * @since 1.15.0
73
+ */
74
+ static get observedAttributes() {
75
+ const attributes = super.observedAttributes;
76
+ attributes.push(ATTRIBUTE_DATATABLE_INDEX);
77
+ attributes.push("data-monster-option-mapping-index");
78
+ return attributes;
79
+ }
80
+
81
+ /**
82
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
83
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
84
+ *
85
+ * The individual configuration values can be found in the table.
86
+ *
87
+ * @property {Object} templates Template definitions
88
+ * @property {string} templates.main Main template
89
+ * @property {object} datasource The datasource
90
+ * @property {string} datasource.selector The selector of the datasource
91
+ * @property {object} mapping The mapping
92
+ * @property {string} mapping.data The data
93
+ * @property {number} mapping.index The index
94
+ * @property {object} features The features
95
+ * @property {boolean} features.refreshOnMutation Refresh on mutation
96
+ * @property {object} refreshOnMutation The refresh on mutation
97
+ * @property {string} refreshOnMutation.selector The selector
98
+ */
99
+ get defaults() {
100
+ const obj = Object.assign({}, super.defaults, {
101
+ templates: {
102
+ main: getTemplate(),
103
+ },
104
+
105
+ datasource: {
106
+ selector: null,
107
+ },
108
+
109
+ mapping: {
110
+ data: "dataset",
111
+ index: 0,
112
+ },
113
+
114
+ features: {
115
+ /**
116
+ * @since 3.70.0
117
+ * @type {boolean}
118
+ */
119
+ refreshOnMutation: true,
120
+ },
121
+
122
+ /**
123
+ * @since 3.70.0
124
+ * @type {boolean}
125
+ */
126
+ refreshOnMutation: {
127
+ selector:
128
+ "input, select, textarea, monster-select, monster-toggle-switch",
129
+ },
130
+
131
+ data: {},
132
+ });
133
+
134
+ updateOptionsFromArguments.call(this, obj);
135
+ return obj;
136
+ }
137
+
138
+ /**
139
+ *
140
+ * @return {string}
141
+ */
142
+ static getTag() {
143
+ return "monster-dataset";
144
+ }
145
+
146
+ /**
147
+ * This method is called when the component is created.
148
+ * @since 3.70.0
149
+ * @return {Promise}
150
+ */
151
+ refresh() {
152
+ // makes sure that handleDataSourceChanges is called
153
+ this.setOption("data", {});
154
+ return Promise.resolve(this);
155
+ }
156
+
157
+ /**
158
+ *
159
+ * @return {Promise<unknown>}
160
+ */
161
+ write() {
162
+ return new Promise((resolve, reject) => {
163
+ if (!this[datasourceLinkedElementSymbol]) {
164
+ reject(new Error("No datasource"));
165
+ return;
166
+ }
167
+
168
+ const internalUpdateCloneData = this.getInternalUpdateCloneData();
169
+ if (!internalUpdateCloneData) {
170
+ reject(new Error("No update data"));
171
+ return;
172
+ }
173
+
174
+ const internalData = internalUpdateCloneData?.["data"];
175
+ if (
176
+ internalData === undefined ||
177
+ internalData === null ||
178
+ internalData === ""
179
+ ) {
180
+ reject(new Error("No data"));
181
+ return;
182
+ }
183
+
184
+ queueMicrotask(() => {
185
+ const path = this.getOption("mapping.data");
186
+ const index = this.getOption("mapping.index");
187
+
188
+ let pathWithIndex;
189
+
190
+ if (isString(path) && path !== "") {
191
+ pathWithIndex = path + "." + index;
192
+ } else {
193
+ pathWithIndex = String(index);
194
+ }
195
+
196
+ const data = this[datasourceLinkedElementSymbol]?.data;
197
+ if (!data) {
198
+ reject(new Error("No data"));
199
+ return;
200
+ }
201
+
202
+ const unref = JSON.stringify(data);
203
+ const ref = JSON.parse(unref);
204
+
205
+ new Pathfinder(ref).setVia(pathWithIndex, internalData);
206
+
207
+ this[datasourceLinkedElementSymbol].data = ref;
208
+
209
+ resolve();
210
+ });
211
+ });
212
+ }
213
+
214
+ /**
215
+ * This method is responsible for assembling the component.
216
+ *
217
+ * It calls the parent's assemble method first, then initializes control references and event handlers.
218
+ * If the `datasource.selector` option is provided and is a string, it searches for the corresponding
219
+ * element in the DOM using that selector.
220
+ *
221
+ * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class.
222
+ *
223
+ * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component
224
+ * attaches an observer to the datasource's changes.
225
+ *
226
+ * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component.
227
+ * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges`
228
+ * method in the component's context.
229
+ */
230
+ [assembleMethodSymbol]() {
231
+ super[assembleMethodSymbol]();
232
+
233
+ requestAnimationFrame(() => {
234
+ if (!this[datasourceLinkedElementSymbol]) {
235
+ const selector = this.getOption("datasource.selector");
236
+
237
+ if (isString(selector)) {
238
+ const element = findElementWithSelectorUpwards(this, selector);
239
+ if (element === null) {
240
+ throw new Error("the selector must match exactly one element");
241
+ }
242
+
243
+ if (!(element instanceof Datasource)) {
244
+ throw new TypeError("the element must be a datasource");
245
+ }
246
+
247
+ this[datasourceLinkedElementSymbol] = element;
248
+ element.datasource.attachObserver(
249
+ new Observer(handleDataSourceChanges.bind(this)),
250
+ );
251
+
252
+ handleDataSourceChanges.call(this);
253
+ } else {
254
+ throw new Error("the selector must be a string");
255
+ }
256
+ }
257
+
258
+ if (
259
+ this.getOption("features.refreshOnMutation") &&
260
+ this.getOption("refreshOnMutation.selector")
261
+ ) {
262
+ initMutationObserver.call(this);
263
+ }
264
+
265
+ initEventHandler.call(this);
266
+ });
267
+ }
268
+
269
+ /**
270
+ * @return [CSSStyleSheet]
271
+ */
272
+ static getCSSStyleSheet() {
273
+ return [FormStyleSheet, DatasetStyleSheet];
274
+ }
268
275
  }
269
276
 
270
277
  /**
271
278
  * @private
272
279
  */
273
280
  function initEventHandler() {
274
- this[attributeObserverSymbol][ATTRIBUTE_DATATABLE_INDEX] = () => {
275
- // @deprecated use data-monster-option-mapping-index
276
- const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
277
- if (index) {
278
- this.setOption("mapping.index", parseInt(index, 10));
279
- handleDataSourceChanges.call(this);
280
- }
281
- };
282
-
283
- this[attributeObserverSymbol]["data-monster-option-mapping-index"] = () => {
284
- const index = this.getAttribute("data-monster-option-mapping-index");
285
- if (index !== null && index !== undefined && index !== "") {
286
- this.setOption("mapping.index", parseInt(index, 10));
287
- handleDataSourceChanges.call(this);
288
- }
289
- };
290
-
291
- if (this[datasourceLinkedElementSymbol]) {
292
- this[datasourceLinkedElementSymbol].datasource.attachObserver(
293
- new Observer(() => {
294
-
295
- let index = 0;
296
- if (typeof this[datasourceLinkedElementSymbol]?.currentPage === "function") {
297
- const page = this[datasourceLinkedElementSymbol].currentPage();
298
- if (page !== null && page !== undefined && page !== "") {
299
- index = parseInt(page, 10) - 1;
300
- }
301
- }
302
-
303
- this.setOption("mapping.index", index);
304
- handleDataSourceChanges.call(this);
305
- }),
306
- );
307
-
308
- this[datasourceLinkedElementSymbol].attachObserver(
309
- new Observer(() => {
310
- let index = 0;
311
- if (typeof this[datasourceLinkedElementSymbol]?.currentPage === "function") {
312
- const page = this[datasourceLinkedElementSymbol].currentPage();
313
- if (page !== null && page !== undefined && page !== "") {
314
- index = parseInt(page, 10) - 1;
315
- }
316
- }
317
-
318
- this.setOption("mapping.index", index);
319
- handleDataSourceChanges.call(this);
320
- }),
321
- );
322
-
323
- handleDataSourceChanges.call(this);
324
- }
281
+ this[attributeObserverSymbol][ATTRIBUTE_DATATABLE_INDEX] = () => {
282
+ // @deprecated use data-monster-option-mapping-index
283
+ const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
284
+ if (index) {
285
+ this.setOption("mapping.index", parseInt(index, 10));
286
+ handleDataSourceChanges.call(this);
287
+ }
288
+ };
289
+
290
+ this[attributeObserverSymbol]["data-monster-option-mapping-index"] = () => {
291
+ const index = this.getAttribute("data-monster-option-mapping-index");
292
+ if (index !== null && index !== undefined && index !== "") {
293
+ this.setOption("mapping.index", parseInt(index, 10));
294
+ handleDataSourceChanges.call(this);
295
+ }
296
+ };
297
+
298
+ if (this[datasourceLinkedElementSymbol]) {
299
+ this[datasourceLinkedElementSymbol].datasource.attachObserver(
300
+ new Observer(() => {
301
+ let index = 0;
302
+ if (
303
+ typeof this[datasourceLinkedElementSymbol]?.currentPage === "function"
304
+ ) {
305
+ const page = this[datasourceLinkedElementSymbol].currentPage();
306
+ if (page !== null && page !== undefined && page !== "") {
307
+ index = parseInt(page, 10) - 1;
308
+ }
309
+ }
310
+
311
+ this.setOption("mapping.index", index);
312
+ handleDataSourceChanges.call(this);
313
+ }),
314
+ );
315
+
316
+ this[datasourceLinkedElementSymbol].attachObserver(
317
+ new Observer(() => {
318
+ let index = 0;
319
+ if (
320
+ typeof this[datasourceLinkedElementSymbol]?.currentPage === "function"
321
+ ) {
322
+ const page = this[datasourceLinkedElementSymbol].currentPage();
323
+ if (page !== null && page !== undefined && page !== "") {
324
+ index = parseInt(page, 10) - 1;
325
+ }
326
+ }
327
+
328
+ this.setOption("mapping.index", index);
329
+ handleDataSourceChanges.call(this);
330
+ }),
331
+ );
332
+
333
+ handleDataSourceChanges.call(this);
334
+ }
325
335
  }
326
336
 
327
337
  /**
@@ -329,56 +339,56 @@ function initEventHandler() {
329
339
  * @param {Object} options
330
340
  */
331
341
  function updateOptionsFromArguments(options) {
332
- const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX); // @deprecated use data-monster-option-mapping-index
342
+ const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX); // @deprecated use data-monster-option-mapping-index
333
343
 
334
- if (index !== null && index !== undefined) {
335
- options.mapping.index = parseInt(index, 10);
336
- }
344
+ if (index !== null && index !== undefined) {
345
+ options.mapping.index = parseInt(index, 10);
346
+ }
337
347
 
338
- const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
348
+ const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
339
349
 
340
- if (selector) {
341
- options.datasource.selector = selector;
342
- }
350
+ if (selector) {
351
+ options.datasource.selector = selector;
352
+ }
343
353
  }
344
354
 
345
355
  /**
346
356
  * @private
347
357
  */
348
358
  function initMutationObserver() {
349
- const config = {attributes: false, childList: true, subtree: true};
350
-
351
- const callback = (mutationList, observer) => {
352
- if (mutationList.length === 0) {
353
- return;
354
- }
355
-
356
- let doneFlag = false;
357
- for (const mutation of mutationList) {
358
- if (mutation.type === "childList") {
359
- for (const node of mutation.addedNodes) {
360
- if (
361
- node instanceof HTMLElement &&
362
- node.matches(this.getOption("refreshOnMutation.selector"))
363
- ) {
364
- doneFlag = true;
365
- break;
366
- }
367
- }
368
-
369
- if (doneFlag) {
370
- break;
371
- }
372
- }
373
- }
374
-
375
- if (doneFlag) {
376
- this.refresh();
377
- }
378
- };
379
-
380
- const observer = new MutationObserver(callback);
381
- observer.observe(this, config);
359
+ const config = { attributes: false, childList: true, subtree: true };
360
+
361
+ const callback = (mutationList, observer) => {
362
+ if (mutationList.length === 0) {
363
+ return;
364
+ }
365
+
366
+ let doneFlag = false;
367
+ for (const mutation of mutationList) {
368
+ if (mutation.type === "childList") {
369
+ for (const node of mutation.addedNodes) {
370
+ if (
371
+ node instanceof HTMLElement &&
372
+ node.matches(this.getOption("refreshOnMutation.selector"))
373
+ ) {
374
+ doneFlag = true;
375
+ break;
376
+ }
377
+ }
378
+
379
+ if (doneFlag) {
380
+ break;
381
+ }
382
+ }
383
+ }
384
+
385
+ if (doneFlag) {
386
+ this.refresh();
387
+ }
388
+ };
389
+
390
+ const observer = new MutationObserver(callback);
391
+ observer.observe(this, config);
382
392
  }
383
393
 
384
394
  /**
@@ -386,8 +396,8 @@ function initMutationObserver() {
386
396
  * @return {string}
387
397
  */
388
398
  function getTemplate() {
389
- // language=HTML
390
- return `
399
+ // language=HTML
400
+ return `
391
401
  <div data-monster-role="control" part="control">
392
402
  <slot></slot>
393
403
  </div>