@schukai/monster 4.43.1 → 4.43.3

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 (29) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.json +1 -1
  3. package/source/components/accessibility/locale-picker.mjs +538 -538
  4. package/source/components/accessibility/locale-select.mjs +172 -172
  5. package/source/components/content/viewer.mjs +823 -823
  6. package/source/components/datatable/constants.mjs +15 -15
  7. package/source/components/datatable/datatable/header.mjs +253 -253
  8. package/source/components/datatable/datatable.mjs +1284 -1284
  9. package/source/components/datatable/filter.mjs +1339 -1342
  10. package/source/components/datatable/pagination.mjs +502 -502
  11. package/source/components/datatable/stylesheet/datatable.mjs +13 -6
  12. package/source/components/form/quantity.mjs +229 -229
  13. package/source/components/form/select.mjs +2963 -2963
  14. package/source/components/form/stylesheet/quantity.mjs +13 -6
  15. package/source/components/form/stylesheet/select.mjs +13 -6
  16. package/source/components/navigation/site-navigation.mjs +383 -210
  17. package/source/components/navigation/style/site-navigation.pcss +103 -15
  18. package/source/components/navigation/stylesheet/site-navigation.mjs +14 -7
  19. package/source/components/style/typography.css +4 -2
  20. package/source/dom/customelement.mjs +959 -963
  21. package/source/dom/slotted.mjs +87 -87
  22. package/source/i18n/util.mjs +149 -149
  23. package/source/monster.mjs +3 -0
  24. package/source/types/is.mjs +64 -64
  25. package/source/types/typeof.mjs +16 -16
  26. package/source/types/version.mjs +1 -1
  27. package/test/cases/monster.mjs +1 -1
  28. package/test/web/test.html +2 -2
  29. package/test/web/tests.js +2724 -1287
@@ -13,9 +13,9 @@
13
13
  */
14
14
 
15
15
  import {
16
- assembleMethodSymbol,
17
- CustomElement,
18
- registerCustomElement,
16
+ assembleMethodSymbol,
17
+ CustomElement,
18
+ registerCustomElement,
19
19
  } from "../../dom/customelement.mjs";
20
20
  import { findElementWithSelectorUpwards, getWindow } from "../../dom/util.mjs";
21
21
  import { DeadMansSwitch } from "../../util/deadmansswitch.mjs";
@@ -82,335 +82,335 @@ const debounceSizeSymbol = Symbol("debounceSize");
82
82
  * @summary The Pagination component is used to show the current page and the total number of pages.
83
83
  */
84
84
  class Pagination extends CustomElement {
85
- /**
86
- */
87
- constructor() {
88
- super();
89
- this[datasourceLinkedElementSymbol] = null;
90
- }
91
-
92
- /**
93
- * This method is called by the `instanceof` operator.
94
- * @return {symbol}
95
- */
96
- static get [instanceSymbol]() {
97
- return Symbol.for("@schukai/monster/components/pagination");
98
- }
99
-
100
- /**
101
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
102
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
103
- *
104
- * The individual configuration values can be found in the table.
105
- *
106
- * @property {Object} templates Template definitions
107
- * @property {string} templates.main Main template
108
- * @property {Object} datasource Datasource configuration
109
- * @property {string} datasource.selector Datasource selector
110
- * @property {Object} labels Label definitions
111
- * @property {string} labels.page Page label
112
- * @property {string} labels.description Description label
113
- * @property {string} labels.previous Previous label
114
- * @property {string} labels.next Next label
115
- * @property {string} labels.of Of label
116
- * @property {string} href Href
117
- * @property {number} currentPage Current page
118
- * @property {number} pages Pages
119
- * @property {number} objectsPerPage Objects per page
120
- * @property {Object} mapping Mapping
121
- * @property {string} mapping.pages Pages mapping
122
- * @property {string} mapping.objectsPerPage Objects per page mapping
123
- * @property {string} mapping.currentPage Current page mapping
124
- */
125
- get defaults() {
126
- return Object.assign(
127
- {},
128
- super.defaults,
129
- {
130
- templates: {
131
- main: getTemplate(),
132
- },
133
-
134
- datasource: {
135
- selector: null,
136
- },
137
-
138
- labels: getTranslations(),
139
-
140
- callbacks: {
141
- click: null,
142
- },
143
-
144
- href: "page-${page}",
145
-
146
- pages: null,
147
- objectsPerPage: 20,
148
- currentPage: null,
149
-
150
- mapping: {
151
- pages: "sys.pagination.pages",
152
- objectsPerPage: "sys.pagination.objectsPerPage",
153
- currentPage: "sys.pagination.currentPage",
154
- },
155
-
156
- /* @private */
157
- pagination: {
158
- items: [],
159
- },
160
- },
161
- initOptionsFromArguments.call(this),
162
- );
163
- }
164
- /**
165
- * Sets the pagination state directly, without requiring a datasource.
166
- * This is useful for controlling the component programmatically.
167
- *
168
- * @param {object} state - The state object for the pagination.
169
- * @param {number} state.currentPage - The current active page number.
170
- * @param {number} state.totalPages - The total number of available pages.
171
- * @return {void}
172
- */
173
- setPaginationState({ currentPage, totalPages }) {
174
- if (typeof currentPage !== "number" || typeof totalPages !== "number") {
175
- console.error(
176
- "setPaginationState requires currentPage and totalPages to be numbers.",
177
- );
178
- return;
179
- }
180
-
181
- // 1. Update the component's internal options with the new values.
182
- this.setOption("currentPage", currentPage);
183
- this.setOption("pages", totalPages);
184
-
185
- // 2. Call the existing buildPagination function to recalculate the links.
186
- const pagination = buildPagination.call(
187
- this,
188
- this.getOption("currentPage"),
189
- this.getOption("pages"),
190
- );
191
-
192
- // 3. Preserve the responsive visibility of page numbers.
193
- if (this?.[sizeDataSymbol]?.showNumbers !== true) {
194
- pagination.items = [];
195
- }
196
-
197
- // 4. Set the 'pagination' option, which will trigger the component to re-render.
198
- this.setOption("pagination", pagination);
199
- }
200
- /**
201
- *
202
- * @return {string}
203
- */
204
- static getTag() {
205
- return "monster-pagination";
206
- }
207
-
208
- /**
209
- * @return {void}
210
- */
211
- disconnectedCallback() {
212
- super.disconnectedCallback();
213
- if (this?.[resizeObserverSymbol] instanceof ResizeObserver) {
214
- this[resizeObserverSymbol].disconnect();
215
- }
216
- if (this?.[debounceSizeSymbol] instanceof DeadMansSwitch) {
217
- try {
218
- this[debounceSizeSymbol].defuse();
219
- delete this[debounceSizeSymbol];
220
- } catch (e) {
221
- // already fired
222
- }
223
- }
224
- }
225
-
226
- /**
227
- * @return {void}
228
- */
229
- connectedCallback() {
230
- super.connectedCallback();
231
-
232
- const parentNode = this.parentNode;
233
- if (!parentNode) {
234
- return;
235
- }
236
-
237
- try {
238
- handleDataSourceChanges.call(this);
239
- } catch (e) {
240
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e?.message || `${e}`);
241
- }
242
-
243
- requestAnimationFrame(() => {
244
- const parentParentNode = parentNode?.parentNode || parentNode;
245
-
246
- const parentWidth = parentParentNode.offsetWidth;
247
- const ownWidth = this.offsetWidth;
248
-
249
- this[sizeDataSymbol] = {
250
- last: {
251
- parentWidth: 0,
252
- },
253
- showNumbers: ownWidth < parentWidth,
254
- };
255
-
256
- this[resizeObserverSymbol] = new ResizeObserver(() => {
257
- if (this[debounceSizeSymbol] instanceof DeadMansSwitch) {
258
- try {
259
- this[debounceSizeSymbol].touch();
260
- return;
261
- } catch (e) {
262
- delete this[debounceSizeSymbol];
263
- }
264
- }
265
-
266
- this[debounceSizeSymbol] = new DeadMansSwitch(250, () => {
267
- queueMicrotask(() => {
268
- const parentWidth = parentParentNode.offsetWidth;
269
- const ownWidth = this.clientWidth;
270
-
271
- if (this[sizeDataSymbol]?.last?.parentWidth === parentWidth) {
272
- return;
273
- }
274
-
275
- this[sizeDataSymbol].last = {
276
- parentWidth: parentWidth,
277
- };
278
-
279
- this[sizeDataSymbol].showNumbers = ownWidth <= parentWidth;
280
- handleDataSourceChanges.call(this);
281
- });
282
- });
283
- });
284
-
285
- this[resizeObserverSymbol].observe(this?.parentNode?.parentNode);
286
- });
287
- }
288
-
289
- /**
290
- * @return {void}
291
- */
292
- [assembleMethodSymbol]() {
293
- super[assembleMethodSymbol]();
294
-
295
- initControlReferences.call(this);
296
- initEventHandler.call(this);
297
-
298
- const selector = this.getOption("datasource.selector", "");
299
-
300
- if (isString(selector)) {
301
- const element = findElementWithSelectorUpwards(this, selector);
302
- if (element === null) {
303
- throw new Error("the selector must match exactly one element");
304
- }
305
-
306
- if (!(element instanceof Datasource)) {
307
- throw new TypeError("the element must be a datasource");
308
- }
309
-
310
- this[datasourceLinkedElementSymbol] = element;
311
- element.datasource.attachObserver(
312
- new Observer(handleDataSourceChanges.bind(this)),
313
- );
314
-
315
- element.attachObserver(new Observer(handleDataSourceChanges.bind(this)));
316
-
317
- handleDataSourceChanges.call(this);
318
- }
319
- }
320
-
321
- /**
322
- * @private
323
- * @return {CSSStyleSheet}
324
- */
325
- static getControlCSSStyleSheet() {
326
- return PaginationStyleSheet;
327
- }
328
-
329
- /**
330
- * @return {CSSStyleSheet[]}
331
- */
332
- static getCSSStyleSheet() {
333
- return [this.getControlCSSStyleSheet(), DisplayStyleSheet, ThemeStyleSheet];
334
- }
85
+ /**
86
+ */
87
+ constructor() {
88
+ super();
89
+ this[datasourceLinkedElementSymbol] = null;
90
+ }
91
+
92
+ /**
93
+ * This method is called by the `instanceof` operator.
94
+ * @return {symbol}
95
+ */
96
+ static get [instanceSymbol]() {
97
+ return Symbol.for("@schukai/monster/components/pagination");
98
+ }
99
+
100
+ /**
101
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
102
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
103
+ *
104
+ * The individual configuration values can be found in the table.
105
+ *
106
+ * @property {Object} templates Template definitions
107
+ * @property {string} templates.main Main template
108
+ * @property {Object} datasource Datasource configuration
109
+ * @property {string} datasource.selector Datasource selector
110
+ * @property {Object} labels Label definitions
111
+ * @property {string} labels.page Page label
112
+ * @property {string} labels.description Description label
113
+ * @property {string} labels.previous Previous label
114
+ * @property {string} labels.next Next label
115
+ * @property {string} labels.of Of label
116
+ * @property {string} href Href
117
+ * @property {number} currentPage Current page
118
+ * @property {number} pages Pages
119
+ * @property {number} objectsPerPage Objects per page
120
+ * @property {Object} mapping Mapping
121
+ * @property {string} mapping.pages Pages mapping
122
+ * @property {string} mapping.objectsPerPage Objects per page mapping
123
+ * @property {string} mapping.currentPage Current page mapping
124
+ */
125
+ get defaults() {
126
+ return Object.assign(
127
+ {},
128
+ super.defaults,
129
+ {
130
+ templates: {
131
+ main: getTemplate(),
132
+ },
133
+
134
+ datasource: {
135
+ selector: null,
136
+ },
137
+
138
+ labels: getTranslations(),
139
+
140
+ callbacks: {
141
+ click: null,
142
+ },
143
+
144
+ href: "page-${page}",
145
+
146
+ pages: null,
147
+ objectsPerPage: 20,
148
+ currentPage: null,
149
+
150
+ mapping: {
151
+ pages: "sys.pagination.pages",
152
+ objectsPerPage: "sys.pagination.objectsPerPage",
153
+ currentPage: "sys.pagination.currentPage",
154
+ },
155
+
156
+ /* @private */
157
+ pagination: {
158
+ items: [],
159
+ },
160
+ },
161
+ initOptionsFromArguments.call(this),
162
+ );
163
+ }
164
+ /**
165
+ * Sets the pagination state directly, without requiring a datasource.
166
+ * This is useful for controlling the component programmatically.
167
+ *
168
+ * @param {object} state - The state object for the pagination.
169
+ * @param {number} state.currentPage - The current active page number.
170
+ * @param {number} state.totalPages - The total number of available pages.
171
+ * @return {void}
172
+ */
173
+ setPaginationState({ currentPage, totalPages }) {
174
+ if (typeof currentPage !== "number" || typeof totalPages !== "number") {
175
+ console.error(
176
+ "setPaginationState requires currentPage and totalPages to be numbers.",
177
+ );
178
+ return;
179
+ }
180
+
181
+ // 1. Update the component's internal options with the new values.
182
+ this.setOption("currentPage", currentPage);
183
+ this.setOption("pages", totalPages);
184
+
185
+ // 2. Call the existing buildPagination function to recalculate the links.
186
+ const pagination = buildPagination.call(
187
+ this,
188
+ this.getOption("currentPage"),
189
+ this.getOption("pages"),
190
+ );
191
+
192
+ // 3. Preserve the responsive visibility of page numbers.
193
+ if (this?.[sizeDataSymbol]?.showNumbers !== true) {
194
+ pagination.items = [];
195
+ }
196
+
197
+ // 4. Set the 'pagination' option, which will trigger the component to re-render.
198
+ this.setOption("pagination", pagination);
199
+ }
200
+ /**
201
+ *
202
+ * @return {string}
203
+ */
204
+ static getTag() {
205
+ return "monster-pagination";
206
+ }
207
+
208
+ /**
209
+ * @return {void}
210
+ */
211
+ disconnectedCallback() {
212
+ super.disconnectedCallback();
213
+ if (this?.[resizeObserverSymbol] instanceof ResizeObserver) {
214
+ this[resizeObserverSymbol].disconnect();
215
+ }
216
+ if (this?.[debounceSizeSymbol] instanceof DeadMansSwitch) {
217
+ try {
218
+ this[debounceSizeSymbol].defuse();
219
+ delete this[debounceSizeSymbol];
220
+ } catch (e) {
221
+ // already fired
222
+ }
223
+ }
224
+ }
225
+
226
+ /**
227
+ * @return {void}
228
+ */
229
+ connectedCallback() {
230
+ super.connectedCallback();
231
+
232
+ const parentNode = this.parentNode;
233
+ if (!parentNode) {
234
+ return;
235
+ }
236
+
237
+ try {
238
+ handleDataSourceChanges.call(this);
239
+ } catch (e) {
240
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e?.message || `${e}`);
241
+ }
242
+
243
+ requestAnimationFrame(() => {
244
+ const parentParentNode = parentNode?.parentNode || parentNode;
245
+
246
+ const parentWidth = parentParentNode.offsetWidth;
247
+ const ownWidth = this.offsetWidth;
248
+
249
+ this[sizeDataSymbol] = {
250
+ last: {
251
+ parentWidth: 0,
252
+ },
253
+ showNumbers: ownWidth < parentWidth,
254
+ };
255
+
256
+ this[resizeObserverSymbol] = new ResizeObserver(() => {
257
+ if (this[debounceSizeSymbol] instanceof DeadMansSwitch) {
258
+ try {
259
+ this[debounceSizeSymbol].touch();
260
+ return;
261
+ } catch (e) {
262
+ delete this[debounceSizeSymbol];
263
+ }
264
+ }
265
+
266
+ this[debounceSizeSymbol] = new DeadMansSwitch(250, () => {
267
+ queueMicrotask(() => {
268
+ const parentWidth = parentParentNode.offsetWidth;
269
+ const ownWidth = this.clientWidth;
270
+
271
+ if (this[sizeDataSymbol]?.last?.parentWidth === parentWidth) {
272
+ return;
273
+ }
274
+
275
+ this[sizeDataSymbol].last = {
276
+ parentWidth: parentWidth,
277
+ };
278
+
279
+ this[sizeDataSymbol].showNumbers = ownWidth <= parentWidth;
280
+ handleDataSourceChanges.call(this);
281
+ });
282
+ });
283
+ });
284
+
285
+ this[resizeObserverSymbol].observe(this?.parentNode?.parentNode);
286
+ });
287
+ }
288
+
289
+ /**
290
+ * @return {void}
291
+ */
292
+ [assembleMethodSymbol]() {
293
+ super[assembleMethodSymbol]();
294
+
295
+ initControlReferences.call(this);
296
+ initEventHandler.call(this);
297
+
298
+ const selector = this.getOption("datasource.selector", "");
299
+
300
+ if (isString(selector)) {
301
+ const element = findElementWithSelectorUpwards(this, selector);
302
+ if (element === null) {
303
+ throw new Error("the selector must match exactly one element");
304
+ }
305
+
306
+ if (!(element instanceof Datasource)) {
307
+ throw new TypeError("the element must be a datasource");
308
+ }
309
+
310
+ this[datasourceLinkedElementSymbol] = element;
311
+ element.datasource.attachObserver(
312
+ new Observer(handleDataSourceChanges.bind(this)),
313
+ );
314
+
315
+ element.attachObserver(new Observer(handleDataSourceChanges.bind(this)));
316
+
317
+ handleDataSourceChanges.call(this);
318
+ }
319
+ }
320
+
321
+ /**
322
+ * @private
323
+ * @return {CSSStyleSheet}
324
+ */
325
+ static getControlCSSStyleSheet() {
326
+ return PaginationStyleSheet;
327
+ }
328
+
329
+ /**
330
+ * @return {CSSStyleSheet[]}
331
+ */
332
+ static getCSSStyleSheet() {
333
+ return [this.getControlCSSStyleSheet(), DisplayStyleSheet, ThemeStyleSheet];
334
+ }
335
335
  }
336
336
 
337
337
  function getTranslations() {
338
- const locale = getLocaleOfDocument();
339
- switch (locale.language) {
340
- case "de":
341
- return {
342
- page: "${page}",
343
- description: "Seite ${page}",
344
- previous: "Vorherige",
345
- next: "Nächste",
346
- of: "von",
347
- };
348
- case "fr":
349
- return {
350
- page: "${page}",
351
- description: "Page ${page}",
352
- previous: "Précédent",
353
- next: "Suivant",
354
- of: "de",
355
- };
356
- case "sp":
357
- return {
358
- page: "${page}",
359
- description: "Página ${page}",
360
- previous: "Anterior",
361
- next: "Siguiente",
362
- of: "de",
363
- };
364
- case "it":
365
- return {
366
- page: "${page}",
367
- description: "Pagina ${page}",
368
- previous: "Precedente",
369
- next: "Successivo",
370
- of: "di",
371
- };
372
- case "pl":
373
- return {
374
- page: "${page}",
375
- description: "Strona ${page}",
376
- previous: "Poprzednia",
377
- next: "Następna",
378
- of: "z",
379
- };
380
- case "no":
381
- return {
382
- page: "${page}",
383
- description: "Side ${page}",
384
- previous: "Forrige",
385
- next: "Neste",
386
- of: "av",
387
- };
388
- case "dk":
389
- return {
390
- page: "${page}",
391
- description: "Side ${page}",
392
- previous: "Forrige",
393
- next: "Næste",
394
- of: "af",
395
- };
396
- case "sw":
397
- return {
398
- page: "${page}",
399
- description: "Sida ${page}",
400
- previous: "Föregående",
401
- next: "Nästa",
402
- of: "av",
403
- };
404
- default:
405
- case "en":
406
- return {
407
- page: "${page}",
408
- description: "Page ${page}",
409
- previous: "Previous",
410
- next: "Next",
411
- of: "of",
412
- };
413
- }
338
+ const locale = getLocaleOfDocument();
339
+ switch (locale.language) {
340
+ case "de":
341
+ return {
342
+ page: "${page}",
343
+ description: "Seite ${page}",
344
+ previous: "Vorherige",
345
+ next: "Nächste",
346
+ of: "von",
347
+ };
348
+ case "fr":
349
+ return {
350
+ page: "${page}",
351
+ description: "Page ${page}",
352
+ previous: "Précédent",
353
+ next: "Suivant",
354
+ of: "de",
355
+ };
356
+ case "sp":
357
+ return {
358
+ page: "${page}",
359
+ description: "Página ${page}",
360
+ previous: "Anterior",
361
+ next: "Siguiente",
362
+ of: "de",
363
+ };
364
+ case "it":
365
+ return {
366
+ page: "${page}",
367
+ description: "Pagina ${page}",
368
+ previous: "Precedente",
369
+ next: "Successivo",
370
+ of: "di",
371
+ };
372
+ case "pl":
373
+ return {
374
+ page: "${page}",
375
+ description: "Strona ${page}",
376
+ previous: "Poprzednia",
377
+ next: "Następna",
378
+ of: "z",
379
+ };
380
+ case "no":
381
+ return {
382
+ page: "${page}",
383
+ description: "Side ${page}",
384
+ previous: "Forrige",
385
+ next: "Neste",
386
+ of: "av",
387
+ };
388
+ case "dk":
389
+ return {
390
+ page: "${page}",
391
+ description: "Side ${page}",
392
+ previous: "Forrige",
393
+ next: "Næste",
394
+ of: "af",
395
+ };
396
+ case "sw":
397
+ return {
398
+ page: "${page}",
399
+ description: "Sida ${page}",
400
+ previous: "Föregående",
401
+ next: "Nästa",
402
+ of: "av",
403
+ };
404
+ default:
405
+ case "en":
406
+ return {
407
+ page: "${page}",
408
+ description: "Page ${page}",
409
+ previous: "Previous",
410
+ next: "Next",
411
+ of: "of",
412
+ };
413
+ }
414
414
  }
415
415
 
416
416
  /**
@@ -419,13 +419,13 @@ function getTranslations() {
419
419
  * @throws {Error} no shadow-root is defined
420
420
  */
421
421
  function initControlReferences() {
422
- if (!this.shadowRoot) {
423
- throw new Error("no shadow-root is defined");
424
- }
422
+ if (!this.shadowRoot) {
423
+ throw new Error("no shadow-root is defined");
424
+ }
425
425
 
426
- this[paginationElementSymbol] = this.shadowRoot.querySelector(
427
- "[data-monster-role=pagination]",
428
- );
426
+ this[paginationElementSymbol] = this.shadowRoot.querySelector(
427
+ "[data-monster-role=pagination]",
428
+ );
429
429
  }
430
430
 
431
431
  /**
@@ -435,41 +435,41 @@ function initControlReferences() {
435
435
  * @private
436
436
  */
437
437
  function initEventHandler() {
438
- const self = this;
439
-
440
- self[paginationElementSymbol].addEventListener("click", function (event) {
441
- let element =
442
- findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "pagination-item") ||
443
- findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "pagination-next") ||
444
- findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "pagination-prev");
445
-
446
- if (
447
- !(element instanceof HTMLElement) ||
448
- !element.hasAttribute("data-page-no")
449
- ) {
450
- return;
451
- }
452
-
453
- const page = element.getAttribute("data-page-no");
454
-
455
- if (!page || page === "…" || page === "null" || page === "undefined") {
456
- return;
457
- }
458
-
459
- event.preventDefault();
460
-
461
- const datasource = self[datasourceLinkedElementSymbol];
462
- const clickCallback = self.getOption("callbacks.click");
463
-
464
- if (datasource && typeof datasource.setParameters === "function") {
465
- datasource.setParameters({ page });
466
- if (typeof datasource.reload === "function") {
467
- datasource.reload();
468
- }
469
- } else if (typeof clickCallback === "function") {
470
- clickCallback(parseInt(page, 10), event);
471
- }
472
- });
438
+ const self = this;
439
+
440
+ self[paginationElementSymbol].addEventListener("click", function (event) {
441
+ let element =
442
+ findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "pagination-item") ||
443
+ findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "pagination-next") ||
444
+ findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "pagination-prev");
445
+
446
+ if (
447
+ !(element instanceof HTMLElement) ||
448
+ !element.hasAttribute("data-page-no")
449
+ ) {
450
+ return;
451
+ }
452
+
453
+ const page = element.getAttribute("data-page-no");
454
+
455
+ if (!page || page === "…" || page === "null" || page === "undefined") {
456
+ return;
457
+ }
458
+
459
+ event.preventDefault();
460
+
461
+ const datasource = self[datasourceLinkedElementSymbol];
462
+ const clickCallback = self.getOption("callbacks.click");
463
+
464
+ if (datasource && typeof datasource.setParameters === "function") {
465
+ datasource.setParameters({ page });
466
+ if (typeof datasource.reload === "function") {
467
+ datasource.reload();
468
+ }
469
+ } else if (typeof clickCallback === "function") {
470
+ clickCallback(parseInt(page, 10), event);
471
+ }
472
+ });
473
473
  }
474
474
 
475
475
  /**
@@ -485,52 +485,52 @@ function initEventHandler() {
485
485
  * @throws {Error} the datasource could not be initialized
486
486
  */
487
487
  function initOptionsFromArguments() {
488
- const options = {};
489
- const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
490
- if (selector) {
491
- options.datasource = { selector: selector };
492
- }
488
+ const options = {};
489
+ const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
490
+ if (selector) {
491
+ options.datasource = { selector: selector };
492
+ }
493
493
 
494
- return options;
494
+ return options;
495
495
  }
496
496
 
497
497
  /**
498
498
  * @private
499
499
  */
500
500
  function handleDataSourceChanges() {
501
- let pagination;
502
-
503
- if (!this[datasourceLinkedElementSymbol]) {
504
- return;
505
- }
506
-
507
- const mapping = this.getOption("mapping");
508
- const pf = new Pathfinder(this[datasourceLinkedElementSymbol].data);
509
-
510
- for (const key in mapping) {
511
- const path = mapping[key];
512
-
513
- if (pf.exists(path)) {
514
- const value = pf.getVia(path);
515
- this.setOption(key, value);
516
- }
517
-
518
- const o = this[datasourceLinkedElementSymbol].getOption(path);
519
- if (o !== undefined && o !== null) {
520
- this.setOption(key, o);
521
- }
522
- }
523
-
524
- pagination = buildPagination.call(
525
- this,
526
- this.getOption("currentPage"),
527
- this.getOption("pages"),
528
- );
529
- if (this?.[sizeDataSymbol]?.showNumbers !== true) {
530
- pagination.items = [];
531
- }
532
-
533
- this.setOption("pagination", pagination);
501
+ let pagination;
502
+
503
+ if (!this[datasourceLinkedElementSymbol]) {
504
+ return;
505
+ }
506
+
507
+ const mapping = this.getOption("mapping");
508
+ const pf = new Pathfinder(this[datasourceLinkedElementSymbol].data);
509
+
510
+ for (const key in mapping) {
511
+ const path = mapping[key];
512
+
513
+ if (pf.exists(path)) {
514
+ const value = pf.getVia(path);
515
+ this.setOption(key, value);
516
+ }
517
+
518
+ const o = this[datasourceLinkedElementSymbol].getOption(path);
519
+ if (o !== undefined && o !== null) {
520
+ this.setOption(key, o);
521
+ }
522
+ }
523
+
524
+ pagination = buildPagination.call(
525
+ this,
526
+ this.getOption("currentPage"),
527
+ this.getOption("pages"),
528
+ );
529
+ if (this?.[sizeDataSymbol]?.showNumbers !== true) {
530
+ pagination.items = [];
531
+ }
532
+
533
+ this.setOption("pagination", pagination);
534
534
  }
535
535
 
536
536
  /**
@@ -540,97 +540,97 @@ function handleDataSourceChanges() {
540
540
  * @return {object}
541
541
  */
542
542
  function buildPagination(current, max) {
543
- current = parseInt(current, 10);
544
- max = parseInt(max, 10);
545
-
546
- let prev = current === 1 ? null : current - 1;
547
- let next = current === max ? null : current + 1;
548
- const itemList = [1];
549
-
550
- if (current > 4) itemList.push(-1);
551
-
552
- const r = 2;
553
- const r1 = current - r;
554
- const r2 = current + r;
555
-
556
- for (let i = r1 > 2 ? r1 : 2; i <= Math.min(max, r2); i++) itemList.push(i);
557
-
558
- if (r2 + 1 < max) itemList.push(-1);
559
- if (r2 < max) itemList.push(max);
560
-
561
- let prevClass = "";
562
-
563
- if (prev === null) {
564
- prevClass = " disabled";
565
- }
566
-
567
- let nextClass = "";
568
- if (next === null) {
569
- nextClass = " disabled";
570
- }
571
-
572
- const items = itemList.map((item) => {
573
- let p = `${item}`;
574
-
575
- if (item === -1) {
576
- item = null;
577
- p = "…";
578
- }
579
-
580
- const c = `${current}`;
581
-
582
- const obj = {
583
- pageNo: item, // as integer
584
- page: p, // as string
585
- current: p === c,
586
- class: (p === c ? "current" : "").trim(),
587
- };
588
-
589
- if (item === null) {
590
- obj.class += " disabled".trim();
591
- }
592
-
593
- const formatter = new Formatter(obj);
594
-
595
- obj.description = formatter.format(this.getOption("labels.description"));
596
- obj.label = formatter.format(this.getOption("labels.page"));
597
- obj.href =
598
- item === null
599
- ? "#"
600
- : p === c
601
- ? "#"
602
- : p === "1"
603
- ? "#"
604
- : `#${formatter.format(this.getOption("href"))}`;
605
- return obj;
606
- });
607
-
608
- const nextNo = next;
609
- next = `${next}`;
610
-
611
- const nextHref =
612
- next === "null"
613
- ? "#"
614
- : `#${new Formatter({ page: next }).format(this.getOption("href"))}`;
615
- const prevNo = prev;
616
- prev = `${prev}`;
617
- const prevHref =
618
- prev === "null"
619
- ? "#"
620
- : `#${new Formatter({ page: prev }).format(this.getOption("href"))}`;
621
-
622
- return {
623
- current,
624
- nextNo,
625
- next,
626
- nextClass,
627
- nextHref,
628
- prevNo,
629
- prev,
630
- prevClass,
631
- prevHref,
632
- items,
633
- };
543
+ current = parseInt(current, 10);
544
+ max = parseInt(max, 10);
545
+
546
+ let prev = current === 1 ? null : current - 1;
547
+ let next = current === max ? null : current + 1;
548
+ const itemList = [1];
549
+
550
+ if (current > 4) itemList.push(-1);
551
+
552
+ const r = 2;
553
+ const r1 = current - r;
554
+ const r2 = current + r;
555
+
556
+ for (let i = r1 > 2 ? r1 : 2; i <= Math.min(max, r2); i++) itemList.push(i);
557
+
558
+ if (r2 + 1 < max) itemList.push(-1);
559
+ if (r2 < max) itemList.push(max);
560
+
561
+ let prevClass = "";
562
+
563
+ if (prev === null) {
564
+ prevClass = " disabled";
565
+ }
566
+
567
+ let nextClass = "";
568
+ if (next === null) {
569
+ nextClass = " disabled";
570
+ }
571
+
572
+ const items = itemList.map((item) => {
573
+ let p = `${item}`;
574
+
575
+ if (item === -1) {
576
+ item = null;
577
+ p = "…";
578
+ }
579
+
580
+ const c = `${current}`;
581
+
582
+ const obj = {
583
+ pageNo: item, // as integer
584
+ page: p, // as string
585
+ current: p === c,
586
+ class: (p === c ? "current" : "").trim(),
587
+ };
588
+
589
+ if (item === null) {
590
+ obj.class += " disabled".trim();
591
+ }
592
+
593
+ const formatter = new Formatter(obj);
594
+
595
+ obj.description = formatter.format(this.getOption("labels.description"));
596
+ obj.label = formatter.format(this.getOption("labels.page"));
597
+ obj.href =
598
+ item === null
599
+ ? "#"
600
+ : p === c
601
+ ? "#"
602
+ : p === "1"
603
+ ? "#"
604
+ : `#${formatter.format(this.getOption("href"))}`;
605
+ return obj;
606
+ });
607
+
608
+ const nextNo = next;
609
+ next = `${next}`;
610
+
611
+ const nextHref =
612
+ next === "null"
613
+ ? "#"
614
+ : `#${new Formatter({ page: next }).format(this.getOption("href"))}`;
615
+ const prevNo = prev;
616
+ prev = `${prev}`;
617
+ const prevHref =
618
+ prev === "null"
619
+ ? "#"
620
+ : `#${new Formatter({ page: prev }).format(this.getOption("href"))}`;
621
+
622
+ return {
623
+ current,
624
+ nextNo,
625
+ next,
626
+ nextClass,
627
+ nextHref,
628
+ prevNo,
629
+ prev,
630
+ prevClass,
631
+ prevHref,
632
+ items,
633
+ };
634
634
  }
635
635
 
636
636
  /**
@@ -638,8 +638,8 @@ function buildPagination(current, max) {
638
638
  * @return {string}
639
639
  */
640
640
  function getTemplate() {
641
- // language=HTML
642
- return `
641
+ // language=HTML
642
+ return `
643
643
 
644
644
  <template id="items">
645
645
  <li part="item"><a part="link"