@schukai/monster 3.69.2 → 3.71.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. package/CHANGELOG.md +29 -4
  2. package/package.json +1 -1
  3. package/source/components/datatable/dataset.mjs +278 -202
  4. package/source/components/datatable/datasource/dom.mjs +1 -1
  5. package/source/components/datatable/datasource/rest.mjs +410 -404
  6. package/source/components/datatable/filter.mjs +1 -0
  7. package/source/components/datatable/save-button.mjs +1 -9
  8. package/source/components/datatable/style/datatable.pcss +1 -1
  9. package/source/components/datatable/style/filter-controls-defaults.pcss +1 -1
  10. package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +8 -17
  11. package/source/components/form/context-error.mjs +2 -0
  12. package/source/components/form/context-help.mjs +1 -0
  13. package/source/components/form/field-set.mjs +222 -225
  14. package/source/components/form/form.mjs +185 -545
  15. package/source/components/form/select.mjs +24 -9
  16. package/source/components/form/style/field-set.pcss +84 -7
  17. package/source/components/form/style/form.pcss +5 -3
  18. package/source/components/form/style/select.pcss +5 -4
  19. package/source/components/form/stylesheet/field-set.mjs +7 -14
  20. package/source/components/form/stylesheet/form.mjs +8 -17
  21. package/source/components/form/stylesheet/select.mjs +7 -14
  22. package/source/components/layout/style/collapse.pcss +0 -2
  23. package/source/components/layout/stylesheet/collapse.mjs +7 -14
  24. package/source/components/style/form.pcss +66 -3
  25. package/source/components/style/mixin/property.pcss +8 -1
  26. package/source/components/style/typography.pcss +4 -12
  27. package/source/components/stylesheet/form.mjs +8 -17
  28. package/source/components/stylesheet/mixin/form.mjs +7 -16
  29. package/source/components/stylesheet/mixin/property.mjs +6 -13
  30. package/source/components/stylesheet/typography.mjs +7 -16
  31. package/source/data/datasource/server/restapi.mjs +191 -180
  32. package/source/data/datasource/server.mjs +118 -74
  33. package/source/data/diff.mjs +1 -1
  34. package/source/dom/customelement.mjs +4 -0
  35. package/source/dom/updater.mjs +1 -1
  36. package/source/types/tokenlist.mjs +2 -2
  37. package/test/cases/components/form/form.mjs +1 -182
  38. package/test/cases/components/host/details.mjs +1 -1
  39. package/test/cases/components/host/host.mjs +1 -1
  40. package/test/cases/components/host/overlay.mjs +1 -1
  41. package/test/cases/data/diff.mjs +37 -0
  42. package/test/cases/dom/customcontrol.mjs +1 -1
  43. package/test/cases/dom/customelement.mjs +2 -2
  44. package/source/components/style/mixin/form.pcss +0 -242
@@ -12,25 +12,27 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import { addAttributeToken } from "../../../dom/attributes.mjs";
16
- import { ATTRIBUTE_ERRORMESSAGE } from "../../../dom/constants.mjs";
17
- import { Datasource, dataSourceSymbol } from "../datasource.mjs";
18
- import { DatasourceStyleSheet } from "../stylesheet/datasource.mjs";
19
- import { instanceSymbol } from "../../../constants.mjs";
15
+ import {diff} from "../../../data/diff.mjs";
16
+ import {addAttributeToken} from "../../../dom/attributes.mjs";
17
+ import {ATTRIBUTE_ERRORMESSAGE} from "../../../dom/constants.mjs";
18
+ import {isArray} from "../../../types/is.mjs";
19
+ import {Datasource, dataSourceSymbol} from "../datasource.mjs";
20
+ import {DatasourceStyleSheet} from "../stylesheet/datasource.mjs";
21
+ import {instanceSymbol} from "../../../constants.mjs";
20
22
  import {
21
- assembleMethodSymbol,
22
- registerCustomElement,
23
+ assembleMethodSymbol,
24
+ registerCustomElement,
23
25
  } from "../../../dom/customelement.mjs";
24
- import { RestAPI } from "../../../data/datasource/server/restapi.mjs";
25
- import { Formatter } from "../../../text/formatter.mjs";
26
- import { clone } from "../../../util/clone.mjs";
27
- import { validateBoolean } from "../../../types/validate.mjs";
28
- import { findElementWithIdUpwards } from "../../../dom/util.mjs";
29
- import { Observer } from "../../../types/observer.mjs";
30
- import { Pathfinder } from "../../../data/pathfinder.mjs";
31
- import { fireCustomEvent } from "../../../dom/events.mjs";
26
+ import {RestAPI} from "../../../data/datasource/server/restapi.mjs";
27
+ import {Formatter} from "../../../text/formatter.mjs";
28
+ import {clone} from "../../../util/clone.mjs";
29
+ import {validateBoolean} from "../../../types/validate.mjs";
30
+ import {findElementWithIdUpwards} from "../../../dom/util.mjs";
31
+ import {Observer} from "../../../types/observer.mjs";
32
+ import {Pathfinder} from "../../../data/pathfinder.mjs";
33
+ import {fireCustomEvent} from "../../../dom/events.mjs";
32
34
 
33
- export { Rest };
35
+ export {Rest};
34
36
 
35
37
  /**
36
38
  * @private
@@ -44,7 +46,7 @@ const intersectionObserverHandlerSymbol = Symbol("intersectionObserverHandler");
44
46
  * @type {symbol}
45
47
  */
46
48
  const rawDataSymbol = Symbol.for(
47
- "@schukai/monster/data/datasource/server/restapi/rawdata",
49
+ "@schukai/monster/data/datasource/server/restapi/rawdata",
48
50
  );
49
51
 
50
52
  /**
@@ -52,7 +54,7 @@ const rawDataSymbol = Symbol.for(
52
54
  * @type {symbol}
53
55
  */
54
56
  const intersectionObserverObserverSymbol = Symbol(
55
- "intersectionObserverObserver",
57
+ "intersectionObserverObserver",
56
58
  );
57
59
 
58
60
  /**
@@ -81,23 +83,23 @@ const filterObserverSymbol = Symbol("filterObserver");
81
83
  * @summary A rest api datasource
82
84
  */
83
85
  class Rest extends Datasource {
84
- /**
85
- * the constructor of the class
86
- */
87
- constructor() {
88
- super();
89
- this[dataSourceSymbol] = new RestAPI();
90
- }
91
-
92
- /**
93
- * This method is called by the `instanceof` operator.
94
- * @returns {symbol}
95
- */
96
- static get [instanceSymbol]() {
97
- return Symbol.for("@schukai/monster/components/datasource/rest@@instance");
98
- }
99
-
100
- /**
86
+ /**
87
+ * the constructor of the class
88
+ */
89
+ constructor() {
90
+ super();
91
+ this[dataSourceSymbol] = new RestAPI();
92
+ }
93
+
94
+ /**
95
+ * This method is called by the `instanceof` operator.
96
+ * @returns {symbol}
97
+ */
98
+ static get [instanceSymbol]() {
99
+ return Symbol.for("@schukai/monster/components/datasource/rest@@instance");
100
+ }
101
+
102
+ /**
101
103
  * To set the options via the html tag the attribute `data-monster-options` must be used.
102
104
  * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
103
105
  *
@@ -128,405 +130,409 @@ class Rest extends Datasource {
128
130
  * @property {Object} write Write configuration
129
131
 
130
132
  */
131
- get defaults() {
132
- const restOptions = new RestAPI().defaults;
133
-
134
- restOptions.read.parameters = {
135
- filter: undefined,
136
- oderBy: undefined,
137
- page: "1",
138
- };
139
-
140
- return Object.assign({}, super.defaults, restOptions, {
141
- templates: {
142
- main: getTemplate(),
143
- },
144
-
145
- features: {
146
- autoInit: false,
147
- filter: false,
148
- },
149
-
150
- autoInit: {
151
- intersectionObserver: false,
152
- oneTime: true,
153
- },
154
-
155
- filter: {
156
- id: undefined,
157
- },
158
-
159
- datatable: {
160
- id: undefined,
161
- },
162
-
163
- response: {
164
- path: {
165
- message: "sys.message",
166
- code: "sys.code",
167
- },
168
- },
169
- });
170
- }
171
-
172
- /**
173
- *
174
- * @param {string} page
175
- * @param {string} query
176
- * @param {string} orderBy
177
- * @returns {Monster.Components.Datatable.Datasource.Rest}
178
- */
179
- setParameters({ page, query, orderBy }) {
180
- const parameters = this.getOption("read.parameters");
181
- if (query !== undefined) {
182
- parameters.query = `${query}`;
183
- parameters.page = "1";
184
- }
185
-
186
- // after a query the page is set to 1, so if the page is not set, it is set to 1
187
- if (page !== undefined) parameters.page = `${page}`;
188
- if (orderBy !== undefined) parameters.order = `${orderBy}`;
189
- this.setOption("read.parameters", parameters);
190
- return this;
191
- }
192
-
193
- /**
194
- *
195
- * @return {Monster.Components.Form.Form}
196
- */
197
- [assembleMethodSymbol]() {
198
- super[assembleMethodSymbol]();
199
-
200
- initEventHandler.call(this);
201
- initAutoInit.call(this);
202
- }
203
-
204
- /**
205
- * @deprecated 2023-06-25
206
- * @returns {Promise<never>|*}
207
- */
208
- reload() {
209
- return this.fetch();
210
- }
211
-
212
- /**
213
- * Fetches the data from the rest api
214
- * @returns {Promise<never>|*}
215
- */
216
- fetch() {
217
- const opt = clone(this.getOption("read"));
218
- this[dataSourceSymbol].setOption("read", opt);
219
-
220
- let url = this.getOption("read.url");
221
- const formatter = new Formatter(this.getOption("read.parameters"));
222
-
223
- if (!url) {
224
- return Promise.reject(new Error("No url defined"));
225
- }
226
-
227
- url = formatter.format(url);
228
-
229
- this[dataSourceSymbol].setOption("read.url", url);
230
-
231
- return new Promise((resolve, reject) => {
232
- fireCustomEvent(this, "monster-datasource-fetch", {
233
- datasource: this,
234
- });
235
-
236
- setTimeout(() => {
237
- this[dataSourceSymbol]
238
- .read()
239
- .then((response) => {
240
- fireCustomEvent(this, "monster-datasource-fetched", {
241
- datasource: this,
242
- });
243
-
244
- resolve(response);
245
- })
246
- .catch((error) => {
247
- fireCustomEvent(this, "monster-datasource-error", {
248
- error: error,
249
- });
250
-
251
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString());
252
- reject(error);
253
- });
254
- }, 0);
255
- });
256
- }
257
-
258
- /**
259
- *
260
- * @return {CSSStyleSheet[]}
261
- */
262
- static getCSSStyleSheet() {
263
- return [DatasourceStyleSheet];
264
- }
265
-
266
- /**
267
- * @private
268
- * @return {string}
269
- */
270
- static getTag() {
271
- return "monster-datasource-rest";
272
- }
273
-
274
- /**
275
- * This method activates the intersection observer manually.
276
- * For this purpose, the option `autoInit.intersectionObserver` must be set to `false`.
277
- *
278
- * @returns {Monster.Components.Datatable.Datasource.Rest}
279
- */
280
- initIntersectionObserver() {
281
- initIntersectionObserver.call(this);
282
- return this;
283
- }
284
-
285
- /**
286
- * @private
287
- */
288
- connectedCallback() {
289
- super.connectedCallback();
290
-
291
- setTimeout(() => {
292
- if (this.getOption("features.filter", false) === true) {
293
- initFilter.call(this);
294
- }
295
- }, 0);
296
- }
297
-
298
- /**
299
- * @private
300
- */
301
- disconnectedCallback() {
302
- super.disconnectedCallback();
303
- removeFilter.call(this);
304
- }
305
-
306
- read() {
307
- return this.fetch();
308
- }
309
-
310
- /**
311
- * Fetches the data from the rest api
312
- * @returns {Promise<never>|*}
313
- */
314
- write() {
315
- const opt = clone(this.getOption("write"));
316
- this[dataSourceSymbol].setOption("write", opt);
317
-
318
- let url = this.getOption("write.url");
319
- const formatter = new Formatter(this.getOption("write.parameters"));
320
-
321
- if (!url) {
322
- return Promise.reject(new Error("No url defined"));
323
- }
324
-
325
- url = formatter.format(url);
326
-
327
- this[dataSourceSymbol].setOption("write.url", url);
328
-
329
- return new Promise((resolve, reject) => {
330
- fireCustomEvent(this, "monster-datasource-fetch", {
331
- datasource: this,
332
- });
333
-
334
- setTimeout(() => {
335
- this[dataSourceSymbol]
336
- .write()
337
- .then((response) => {
338
- fireCustomEvent(this, "monster-datasource-fetched", {
339
- datasource: this,
340
- });
341
-
342
- resolve(response);
343
- })
344
- .catch((error) => {
345
- fireCustomEvent(this, "monster-datasource-error", {
346
- error: error,
347
- });
348
-
349
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString());
350
- reject(error);
351
- });
352
- }, 0);
353
- });
354
- }
133
+ get defaults() {
134
+ const restOptions = new RestAPI().defaults;
135
+
136
+ restOptions.read.parameters = {
137
+ filter: undefined,
138
+ oderBy: undefined,
139
+ page: "1",
140
+ };
141
+
142
+ return Object.assign({}, super.defaults, restOptions, {
143
+ templates: {
144
+ main: getTemplate(),
145
+ },
146
+
147
+ features: {
148
+ autoInit: false,
149
+ filter: false,
150
+ },
151
+
152
+ autoInit: {
153
+ intersectionObserver: false,
154
+ oneTime: true,
155
+ },
156
+
157
+ filter: {
158
+ id: undefined,
159
+ },
160
+
161
+ datatable: {
162
+ id: undefined,
163
+ },
164
+
165
+ response: {
166
+ path: {
167
+ message: "sys.message",
168
+ code: "sys.code",
169
+ },
170
+ },
171
+ });
172
+ }
173
+
174
+ /**
175
+ *
176
+ * @param {string} page
177
+ * @param {string} query
178
+ * @param {string} orderBy
179
+ * @returns {Monster.Components.Datatable.Datasource.Rest}
180
+ */
181
+ setParameters({page, query, orderBy}) {
182
+ const parameters = this.getOption("read.parameters");
183
+ if (query !== undefined) {
184
+ parameters.query = `${query}`;
185
+ parameters.page = "1";
186
+ }
187
+
188
+ // after a query the page is set to 1, so if the page is not set, it is set to 1
189
+ if (page !== undefined) parameters.page = `${page}`;
190
+ if (orderBy !== undefined) parameters.order = `${orderBy}`;
191
+ this.setOption("read.parameters", parameters);
192
+ return this;
193
+ }
194
+
195
+ /**
196
+ * @return {void}
197
+ */
198
+ [assembleMethodSymbol]() {
199
+ super[assembleMethodSymbol]();
200
+
201
+ initEventHandler.call(this);
202
+ initAutoInit.call(this);
203
+ }
204
+
205
+ /**
206
+ * @deprecated 2023-06-25
207
+ * @returns {Promise<never>|*}
208
+ */
209
+ reload() {
210
+ return this.fetch();
211
+ }
212
+
213
+ /**
214
+ * Fetches the data from the rest api
215
+ * @returns {Promise<never>|*}
216
+ */
217
+ fetch() {
218
+ const opt = clone(this.getOption("read"));
219
+ this[dataSourceSymbol].setOption("read", opt);
220
+
221
+ let url = this.getOption("read.url");
222
+ const formatter = new Formatter(this.getOption("read.parameters"));
223
+
224
+ if (!url) {
225
+ return Promise.reject(new Error("No url defined"));
226
+ }
227
+
228
+ url = formatter.format(url);
229
+
230
+ this[dataSourceSymbol].setOption("read.url", url);
231
+
232
+ return new Promise((resolve, reject) => {
233
+ fireCustomEvent(this, "monster-datasource-fetch", {
234
+ datasource: this,
235
+ });
236
+
237
+ setTimeout(() => {
238
+ this[dataSourceSymbol]
239
+ .read()
240
+ .then((response) => {
241
+ fireCustomEvent(this, "monster-datasource-fetched", {
242
+ datasource: this,
243
+ });
244
+
245
+ resolve(response);
246
+ })
247
+ .catch((error) => {
248
+ fireCustomEvent(this, "monster-datasource-error", {
249
+ error: error,
250
+ });
251
+
252
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString());
253
+ reject(error);
254
+ });
255
+ }, 0);
256
+ });
257
+ }
258
+
259
+ /**
260
+ *
261
+ * @return {CSSStyleSheet[]}
262
+ */
263
+ static getCSSStyleSheet() {
264
+ return [DatasourceStyleSheet];
265
+ }
266
+
267
+ /**
268
+ * @private
269
+ * @return {string}
270
+ */
271
+ static getTag() {
272
+ return "monster-datasource-rest";
273
+ }
274
+
275
+ /**
276
+ * This method activates the intersection observer manually.
277
+ * For this purpose, the option `autoInit.intersectionObserver` must be set to `false`.
278
+ *
279
+ * @returns {Monster.Components.Datatable.Datasource.Rest}
280
+ */
281
+ initIntersectionObserver() {
282
+ initIntersectionObserver.call(this);
283
+ return this;
284
+ }
285
+
286
+ /**
287
+ * @private
288
+ */
289
+ connectedCallback() {
290
+ super.connectedCallback();
291
+
292
+ setTimeout(() => {
293
+ if (this.getOption("features.filter", false) === true) {
294
+ initFilter.call(this);
295
+ }
296
+ }, 0);
297
+ }
298
+
299
+ /**
300
+ * @private
301
+ */
302
+ disconnectedCallback() {
303
+ super.disconnectedCallback();
304
+ removeFilter.call(this);
305
+ }
306
+
307
+ /**
308
+ * @returns {Promise<never>|*}
309
+ */
310
+ read() {
311
+ return this.fetch();
312
+ }
313
+
314
+ /**
315
+ * Fetches the data from the rest api
316
+ * @returns {Promise<never>|*}
317
+ */
318
+ write() {
319
+ const opt = clone(this.getOption("write"));
320
+ this[dataSourceSymbol].setOption("write", opt);
321
+
322
+ let url = this.getOption("write.url");
323
+ const formatter = new Formatter(this.getOption("write.parameters"));
324
+
325
+ if (!url) {
326
+ return Promise.reject(new Error("No url defined"));
327
+ }
328
+
329
+ url = formatter.format(url);
330
+
331
+ this[dataSourceSymbol].setOption("write.url", url);
332
+
333
+ return new Promise((resolve, reject) => {
334
+ fireCustomEvent(this, "monster-datasource-fetch", {
335
+ datasource: this,
336
+ });
337
+
338
+ setTimeout(() => {
339
+ this[dataSourceSymbol]
340
+ .write()
341
+ .then((response) => {
342
+ fireCustomEvent(this, "monster-datasource-fetched", {
343
+ datasource: this,
344
+ });
345
+
346
+ resolve(response);
347
+ })
348
+ .catch((error) => {
349
+ fireCustomEvent(this, "monster-datasource-error", {
350
+ error: error,
351
+ });
352
+
353
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString());
354
+ reject(error);
355
+ });
356
+ }, 0);
357
+ });
358
+ }
355
359
  }
356
360
 
357
361
  /**
358
362
  * @private
359
363
  */
360
364
  function removeFilter() {
361
- const filterID = this.getOption("filter.id", undefined);
362
- if (!filterID) return;
365
+ const filterID = this.getOption("filter.id", undefined);
366
+ if (!filterID) return;
363
367
 
364
- const filterControl = findElementWithIdUpwards(this, filterID);
368
+ const filterControl = findElementWithIdUpwards(this, filterID);
365
369
 
366
- if (filterControl && this[filterObserverSymbol]) {
367
- filterControl?.detachObserver(this[filterObserverSymbol]);
368
- }
370
+ if (filterControl && this[filterObserverSymbol]) {
371
+ filterControl?.detachObserver(this[filterObserverSymbol]);
372
+ }
369
373
  }
370
374
 
371
375
  /**
372
376
  * @private
373
377
  */
374
378
  function initFilter() {
375
- const filterID = this.getOption("filter.id", undefined);
376
-
377
- if (!filterID)
378
- throw new Error("filter feature is enabled but no filter id is defined");
379
-
380
- const filterControl = findElementWithIdUpwards(this, filterID);
381
- if (!filterControl)
382
- throw new Error(
383
- "filter feature is enabled but no filter control with id " +
384
- filterID +
385
- " is found",
386
- );
387
-
388
- this[filterObserverSymbol] = new Observer(() => {
389
- const query = filterControl.getOption("query");
390
- if ( query===undefined) {
391
- return;
392
- }
393
- this.setParameters({ query: query });
394
- this.fetch()
395
- .then((response) => {
396
- if (!(response instanceof Response)) {
397
- throw new Error("Response is not an instance of Response");
398
- }
399
-
400
- if (response?.ok === true) {
401
- this.dispatchEvent(new CustomEvent("reload", { bubbles: true }));
402
- filterControl?.showSuccess();
403
- }
404
-
405
- if (response.bodyUsed === true) {
406
- return handleIntersectionObserver.call(
407
- this,
408
- response[rawDataSymbol],
409
- response,
410
- filterControl,
411
- );
412
- }
413
-
414
- response
415
- .text()
416
- .then((jsonAsText) => {
417
- let json;
418
- try {
419
- json = JSON.parse(jsonAsText);
420
- } catch (e) {
421
- const message = e instanceof Error ? e.message : `${e}`;
422
- filterControl?.showFailureMessage(message);
423
- return Promise.reject(e);
424
- }
425
-
426
- return handleIntersectionObserver.call(
427
- this,
428
- json,
429
- response,
430
- filterControl,
431
- );
432
- })
433
- .catch((e) => {
434
- filterControl?.showFailureMessage(e.message);
435
- });
436
- })
437
- .catch((e) => {
438
- this.dispatchEvent(
439
- new CustomEvent("error", { bubbles: true, detail: e }),
440
- );
441
-
442
- if (!(e instanceof Error)) {
443
- e = new Error(e);
444
- }
445
-
446
- filterControl?.showFailureMessage(e.message);
447
- return Promise.reject(e);
448
- });
449
- });
450
-
451
- filterControl.attachObserver(this[filterObserverSymbol]);
379
+ const filterID = this.getOption("filter.id", undefined);
380
+
381
+ if (!filterID)
382
+ throw new Error("filter feature is enabled but no filter id is defined");
383
+
384
+ const filterControl = findElementWithIdUpwards(this, filterID);
385
+ if (!filterControl)
386
+ throw new Error(
387
+ "filter feature is enabled but no filter control with id " +
388
+ filterID +
389
+ " is found",
390
+ );
391
+
392
+ this[filterObserverSymbol] = new Observer(() => {
393
+ const query = filterControl.getOption("query");
394
+ if (query === undefined) {
395
+ return;
396
+ }
397
+ this.setParameters({query: query});
398
+ this.fetch()
399
+ .then((response) => {
400
+ if (!(response instanceof Response)) {
401
+ throw new Error("Response is not an instance of Response");
402
+ }
403
+
404
+ if (response?.ok === true) {
405
+ this.dispatchEvent(new CustomEvent("reload", {bubbles: true}));
406
+ filterControl?.showSuccess();
407
+ }
408
+
409
+ if (response.bodyUsed === true) {
410
+ return handleIntersectionObserver.call(
411
+ this,
412
+ response[rawDataSymbol],
413
+ response,
414
+ filterControl,
415
+ );
416
+ }
417
+
418
+ response
419
+ .text()
420
+ .then((jsonAsText) => {
421
+ let json;
422
+ try {
423
+ json = JSON.parse(jsonAsText);
424
+ } catch (e) {
425
+ const message = e instanceof Error ? e.message : `${e}`;
426
+ filterControl?.showFailureMessage(message);
427
+ return Promise.reject(e);
428
+ }
429
+
430
+ return handleIntersectionObserver.call(
431
+ this,
432
+ json,
433
+ response,
434
+ filterControl,
435
+ );
436
+ })
437
+ .catch((e) => {
438
+ filterControl?.showFailureMessage(e.message);
439
+ });
440
+ })
441
+ .catch((e) => {
442
+ this.dispatchEvent(
443
+ new CustomEvent("error", {bubbles: true, detail: e}),
444
+ );
445
+
446
+ if (!(e instanceof Error)) {
447
+ e = new Error(e);
448
+ }
449
+
450
+ filterControl?.showFailureMessage(e.message);
451
+ return Promise.reject(e);
452
+ });
453
+ });
454
+
455
+ filterControl.attachObserver(this[filterObserverSymbol]);
452
456
  }
453
457
 
454
458
  function handleIntersectionObserver(json, response, filterControl) {
455
- const path = new Pathfinder(json);
456
-
457
- const codePath = this.getOption("response.path.code");
458
-
459
- if (path.exists(codePath)) {
460
- const code = `${path.getVia(codePath)}`;
461
- if (code && code === "200") {
462
- filterControl?.showSuccess();
463
- return Promise.resolve(response);
464
- }
465
-
466
- const messagePath = this.getOption("response.path.message");
467
- if (path.exists(messagePath)) {
468
- const message = path.getVia(messagePath);
469
- filterControl?.showFailureMessage(message);
470
- return Promise.reject(new Error(message));
471
- }
472
-
473
- return Promise.reject(new Error("Response code is not 200"));
474
- }
459
+ const path = new Pathfinder(json);
460
+
461
+ const codePath = this.getOption("response.path.code");
462
+
463
+ if (path.exists(codePath)) {
464
+ const code = `${path.getVia(codePath)}`;
465
+ if (code && code === "200") {
466
+ filterControl?.showSuccess();
467
+ return Promise.resolve(response);
468
+ }
469
+
470
+ const messagePath = this.getOption("response.path.message");
471
+ if (path.exists(messagePath)) {
472
+ const message = path.getVia(messagePath);
473
+ filterControl?.showFailureMessage(message);
474
+ return Promise.reject(new Error(message));
475
+ }
476
+
477
+ return Promise.reject(new Error("Response code is not 200"));
478
+ }
475
479
  }
476
480
 
477
481
  /**
478
482
  * @private
479
483
  */
480
484
  function initAutoInit() {
481
- const autoInit = this.getOption("features.autoInit");
482
- validateBoolean(autoInit);
483
485
 
484
- if (autoInit !== true) return;
486
+ const autoInit = this.getOption("features.autoInit");
487
+ validateBoolean(autoInit);
488
+
489
+ if (autoInit !== true) return;
485
490
 
486
- if (this.getOption("autoInit.intersectionObserver") === true) {
487
- initIntersectionObserver.call(this);
488
- return;
489
- }
491
+ if (this.getOption("autoInit.intersectionObserver") === true) {
492
+ initIntersectionObserver.call(this);
493
+ return;
494
+ }
490
495
 
491
- setTimeout(() => {
492
- this.fetch().catch(() => {});
493
- }, 0);
496
+ setTimeout(() => {
497
+ this.fetch().catch(() => {
498
+ });
499
+ }, 0);
494
500
  }
495
501
 
496
502
  function initEventHandler() {
497
- this[intersectionObserverHandlerSymbol] = (entries) => {
498
- entries.forEach((entry) => {
499
- if (entry.isIntersecting) {
500
- if (entry.intersectionRatio > 0) {
501
- this.fetch();
502
- }
503
-
504
- // only load once
505
- if (
506
- this.getOption("autoInit.oneTime") === true &&
507
- this[intersectionObserverObserverSymbol] !== undefined
508
- ) {
509
- this[intersectionObserverObserverSymbol].unobserve(this);
510
- }
511
- }
512
- });
513
- };
503
+ this[intersectionObserverHandlerSymbol] = (entries) => {
504
+ entries.forEach((entry) => {
505
+ if (entry.isIntersecting) {
506
+ if (entry.intersectionRatio > 0) {
507
+ this.fetch();
508
+ }
509
+
510
+ // only load once
511
+ if (
512
+ this.getOption("autoInit.oneTime") === true &&
513
+ this[intersectionObserverObserverSymbol] !== undefined
514
+ ) {
515
+ this[intersectionObserverObserverSymbol].unobserve(this);
516
+ }
517
+ }
518
+ });
519
+ };
514
520
  }
515
521
 
516
522
  function initIntersectionObserver() {
517
- this.classList.add("intersection-observer");
518
-
519
- const options = {
520
- root: null,
521
- rootMargin: "0px",
522
- threshold: 0.1,
523
- };
524
-
525
- this[intersectionObserverObserverSymbol] = new IntersectionObserver(
526
- this[intersectionObserverHandlerSymbol],
527
- options,
528
- );
529
- this[intersectionObserverObserverSymbol].observe(this);
523
+ this.classList.add("intersection-observer");
524
+
525
+ const options = {
526
+ root: null,
527
+ rootMargin: "0px",
528
+ threshold: 0.1,
529
+ };
530
+
531
+ this[intersectionObserverObserverSymbol] = new IntersectionObserver(
532
+ this[intersectionObserverHandlerSymbol],
533
+ options,
534
+ );
535
+ this[intersectionObserverObserverSymbol].observe(this);
530
536
  }
531
537
 
532
538
  /**
@@ -534,8 +540,8 @@ function initIntersectionObserver() {
534
540
  * @return {string}
535
541
  */
536
542
  function getTemplate() {
537
- // language=HTML
538
- return `
543
+ // language=HTML
544
+ return `
539
545
  <slot></slot>`;
540
546
  }
541
547