@schukai/monster 4.29.0 → 4.29.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.29.1] - 2025-07-07
6
+
7
+ ### Bug Fixes
8
+
9
+ - handle updates better
10
+
11
+
12
+
5
13
  ## [4.29.0] - 2025-07-07
6
14
 
7
15
  ### Add Features
package/package.json CHANGED
@@ -1 +1 @@
1
- {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.2","@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.29.0"}
1
+ {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.2","@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.29.1"}
@@ -60,6 +60,18 @@ export { Updater, addObjectWithUpdaterToElement };
60
60
  */
61
61
  const timerElementEventHandlerSymbol = Symbol("timerElementEventHandler");
62
62
 
63
+ /**
64
+ * @private
65
+ * @type {symbol}
66
+ */
67
+ const pendingDiffsSymbol = Symbol("pendingDiffs");
68
+
69
+ /**
70
+ * @private
71
+ * @type {symbol}
72
+ */
73
+ const processingSymbol = Symbol("processing");
74
+
63
75
  /**
64
76
  * The updater class connects an object with the DOM. In this way, structures and contents in the DOM can be
65
77
  * programmatically adapted via attributes.
@@ -85,6 +97,7 @@ const timerElementEventHandlerSymbol = Symbol("timerElementEventHandler");
85
97
  * @summary The updater class connects an object with the dom
86
98
  */
87
99
  class Updater extends Base {
100
+
88
101
  /**
89
102
  * @since 1.8.0
90
103
  * @param {HTMLElement} element
@@ -117,39 +130,50 @@ class Updater extends Base {
117
130
  getCheckStateCallback.call(this),
118
131
  );
119
132
 
120
- this[internalSymbol].subject.attachObserver(
121
- new Observer(() => {
122
- const s = this[internalSymbol].subject.getRealSubject();
123
-
124
- const diffResult = diff(this[internalSymbol].last, s);
125
- this[internalSymbol].last = clone(s);
126
-
127
- const promises = [];
128
-
129
- for (const [, change] of Object.entries(diffResult)) {
130
- promises.push(
131
- new Promise((resolve, reject) => {
132
- getWindow().requestAnimationFrame(() => {
133
- try {
134
- removeElement.call(this, change);
135
- insertElement.call(this, change);
136
- updateContent.call(this, change);
137
- updateAttributes.call(this, change);
138
-
139
- resolve();
140
- } catch (error) {
141
- reject(error);
142
- }
143
- });
144
- }),
145
- );
146
- }
133
+ this[pendingDiffsSymbol] = [];
134
+ this[processingSymbol] = false;
147
135
 
148
- return Promise.all(promises);
149
- }),
136
+ this[internalSymbol].subject.attachObserver(
137
+ new Observer(() => {
138
+ const real = this[internalSymbol].subject.getRealSubject();
139
+ const diffResult = diff(this[internalSymbol].last, real);
140
+ this[internalSymbol].last = clone(real);
141
+ this[pendingDiffsSymbol].push(diffResult);
142
+ return this.#processQueue();
143
+ }),
150
144
  );
151
145
  }
152
146
 
147
+ /**
148
+ * @private
149
+ * @return {Promise}
150
+ */
151
+ async #processQueue() {
152
+ if ( this[processingSymbol]) {
153
+ return Promise.resolve();
154
+ }
155
+ this[processingSymbol] = true;
156
+
157
+ while (this[pendingDiffsSymbol].length > 0) {
158
+ const diffResult = this[pendingDiffsSymbol].shift();
159
+ for (const [, change] of Object.entries(diffResult)) {
160
+ await new Promise((resolve, reject) => {
161
+ try {
162
+ removeElement.call(this, change);
163
+ insertElement.call(this, change);
164
+ updateContent.call(this, change);
165
+ updateAttributes.call(this, change);
166
+ resolve();
167
+ } catch (err) {
168
+ reject(err);
169
+ }
170
+ });
171
+ }
172
+ }
173
+
174
+ this[processingSymbol] = false;
175
+ }
176
+
153
177
  /**
154
178
  * Defaults: 'keyup', 'click', 'change', 'drop', 'touchend'
155
179
  *