@schukai/monster 4.122.0 → 4.122.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.122.2] - 2026-02-16
6
+
7
+ ### Bug Fixes
8
+
9
+ - Improve pagination logic and add corresponding tests
10
+
11
+
12
+
13
+ ## [4.122.1] - 2026-02-13
14
+
15
+ ### Bug Fixes
16
+
17
+ - Ensure proper context for placeAppointments function
18
+
19
+
20
+
5
21
  ## [4.122.0] - 2026-02-13
6
22
 
7
23
  ### Add Features
package/package.json CHANGED
@@ -1 +1 @@
1
- {"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.4","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.122.0"}
1
+ {"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.4","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.122.2"}
@@ -691,8 +691,16 @@ function handleDataSourceChanges() {
691
691
  * @return {object}
692
692
  */
693
693
  function buildPagination(current, max) {
694
- current = parseInt(current, 10);
695
- max = parseInt(max, 10);
694
+ const parsedCurrent = Number.parseInt(current, 10);
695
+ const parsedMax = Number.parseInt(max, 10);
696
+
697
+ max = Number.isFinite(parsedMax) && parsedMax >= 1 ? parsedMax : 1;
698
+ current = Number.isFinite(parsedCurrent) ? parsedCurrent : 1;
699
+ if (current < 1) {
700
+ current = 1;
701
+ } else if (current > max) {
702
+ current = max;
703
+ }
696
704
 
697
705
  let prev = current === 1 ? null : current - 1;
698
706
  let next = current === max ? null : current + 1;
@@ -1229,7 +1237,7 @@ function getTemplate() {
1229
1237
  data-monster-attributes="
1230
1238
  class path:pagination.prevClass | prefix: previous,
1231
1239
  data-page-no path:pagination.prevNo,
1232
- href path:pagination.prevHref | prefix: #"
1240
+ href path:pagination.prevHref"
1233
1241
  data-monster-replace="path:labels.previous">Previous</a></li>
1234
1242
  <li part="summary" data-monster-role="pagination-summary">
1235
1243
  <span data-monster-replace="path:pagination.summary"></span>
@@ -1239,7 +1247,7 @@ function getTemplate() {
1239
1247
  part="next-link"
1240
1248
  data-monster-attributes="class path:pagination.nextClass | prefix: next,
1241
1249
  data-page-no path:pagination.nextNo,
1242
- href path:pagination.nextHref | prefix: #"
1250
+ href path:pagination.nextHref"
1243
1251
  data-monster-replace="path:labels.next">Next</a></li>
1244
1252
  </ul>
1245
1253
  </nav>
@@ -177,7 +177,7 @@ class MonthCalendar extends CustomElement {
177
177
  this.setOption("data", {});
178
178
  queueMicrotask(() => {
179
179
  handleDataSourceChanges.call(this);
180
- placeAppointments();
180
+ placeAppointments.call(this);
181
181
  resolve();
182
182
  });
183
183
  });
@@ -0,0 +1,99 @@
1
+
2
+ import * as chai from 'chai';
3
+ import {chaiDom} from "../../../util/chai-dom.mjs";
4
+ import {initJSDOM} from "../../../util/jsdom.mjs";
5
+
6
+ let expect = chai.expect;
7
+ chai.use(chaiDom);
8
+
9
+ let Pagination;
10
+
11
+ describe('Pagination', function () {
12
+
13
+ before(function (done) {
14
+ initJSDOM().then(() => {
15
+ import("../../../../source/components/datatable/pagination.mjs").then((m) => {
16
+ Pagination = m['Pagination'];
17
+ done();
18
+ }).catch(e => done(e));
19
+ });
20
+ });
21
+
22
+ afterEach(() => {
23
+ let mocks = document.getElementById('mocks');
24
+ mocks.innerHTML = "";
25
+ });
26
+
27
+ it('normalizes NaN and avoids NaN hrefs', function (done) {
28
+ let mocks = document.getElementById('mocks');
29
+ const control = document.createElement('monster-pagination');
30
+ mocks.appendChild(control);
31
+
32
+ setTimeout(() => {
33
+ try {
34
+ control.setPaginationState({currentPage: Number.NaN, totalPages: Number.NaN});
35
+
36
+ const pagination = control.getOption('pagination');
37
+
38
+ expect(pagination.current).to.equal(1);
39
+ expect(pagination.prevHref).to.equal('#');
40
+ expect(pagination.nextHref).to.equal('#');
41
+
42
+ const hrefs = [pagination.prevHref, pagination.nextHref, ...pagination.items.map(i => i.href)];
43
+ hrefs.forEach((href) => {
44
+ expect(href).to.not.contain('NaN');
45
+ expect(href.startsWith('##')).to.equal(false);
46
+ });
47
+ } catch (e) {
48
+ return done(e);
49
+ }
50
+
51
+ done();
52
+ }, 0);
53
+ });
54
+
55
+ it('clamps current page and does not double-prefix hash', function (done) {
56
+ let mocks = document.getElementById('mocks');
57
+ const control = document.createElement('monster-pagination');
58
+ mocks.appendChild(control);
59
+
60
+ setTimeout(() => {
61
+ try {
62
+ control.setPaginationState({currentPage: 10, totalPages: 3});
63
+
64
+ const pagination = control.getOption('pagination');
65
+ expect(pagination.current).to.equal(3);
66
+ expect(pagination.nextHref).to.equal('#');
67
+ expect(pagination.prevHref).to.equal('#page-2');
68
+
69
+ setTimeout(() => {
70
+ try {
71
+ const prevLink = control.shadowRoot.querySelector(
72
+ 'a[data-monster-role=pagination-prev]'
73
+ );
74
+ const nextLink = control.shadowRoot.querySelector(
75
+ 'a[data-monster-role=pagination-next]'
76
+ );
77
+
78
+ expect(prevLink.getAttribute('href')).to.equal('#page-2');
79
+ expect(nextLink.getAttribute('href')).to.equal('#');
80
+ } catch (e) {
81
+ return done(e);
82
+ }
83
+
84
+ done();
85
+ }, 0);
86
+ } catch (e) {
87
+ return done(e);
88
+ }
89
+ }, 0);
90
+ });
91
+
92
+ describe('document.createElement', function () {
93
+ it('should instance of Pagination', function () {
94
+ expect(document.createElement('monster-pagination')).is.instanceof(Pagination);
95
+ });
96
+ });
97
+
98
+ });
99
+
@@ -22,6 +22,7 @@ import "../cases/components/host/overlay.mjs";
22
22
  import "../cases/components/host/util.mjs";
23
23
  import "../cases/components/host/details.mjs";
24
24
  import "../cases/components/datatable/writeback-sanitizer.mjs";
25
+ import "../cases/components/datatable/pagination.mjs";
25
26
  import "../cases/text/formatter.mjs";
26
27
  import "../cases/text/generate-range-comparison-expression.mjs";
27
28
  import "../cases/text/util.mjs";