@schukai/monster 4.85.1 → 4.85.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 +8 -0
- package/package.json +1 -1
- package/source/components/datatable/status.mjs +2 -1
- package/source/data/diff.mjs +10 -1
- package/source/dom/controlflow.mjs +1 -2
- package/source/dom/customelement.mjs +5 -0
- package/source/util/clone.mjs +23 -0
- package/test/cases/data/diff.mjs +26 -2
- package/test/cases/dom/customelement.mjs +55 -1
- package/test/cases/util/clone.mjs +35 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
## [4.85.2] - 2026-01-08
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Rename issue [#368](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/368) to closed and add issue [#369](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/369)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
5
13
|
## [4.85.1] - 2026-01-08
|
|
6
14
|
|
|
7
15
|
### Bug Fixes
|
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.85.
|
|
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.85.2"}
|
|
@@ -166,7 +166,8 @@ function initControlReferences() {
|
|
|
166
166
|
this[errorElementSymbol] = this.shadowRoot.querySelector(
|
|
167
167
|
"monster-context-error",
|
|
168
168
|
);
|
|
169
|
-
this[spinnerElementSymbol] =
|
|
169
|
+
this[spinnerElementSymbol] =
|
|
170
|
+
this.shadowRoot.querySelector(".monster-spinner");
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
/**
|
package/source/data/diff.mjs
CHANGED
|
@@ -68,7 +68,16 @@ function doDiff(a, b, path, diff) {
|
|
|
68
68
|
const currDiff = diff || [];
|
|
69
69
|
|
|
70
70
|
if (typeA === typeB && (typeA === "object" || typeA === "array")) {
|
|
71
|
-
getKeys(a, b, typeA)
|
|
71
|
+
const keys = getKeys(a, b, typeA);
|
|
72
|
+
if (keys.size === 0) {
|
|
73
|
+
const o = getOperator(a, b, typeA, typeB);
|
|
74
|
+
if (o !== undefined) {
|
|
75
|
+
currDiff.push(buildResult(a, b, o, currPath));
|
|
76
|
+
}
|
|
77
|
+
return currDiff;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
keys.forEach((v) => {
|
|
72
81
|
if (!Object.prototype.hasOwnProperty.call(a, v)) {
|
|
73
82
|
currDiff.push(buildResult(a[v], b[v], "add", currPath.concat(v)));
|
|
74
83
|
} else if (!Object.prototype.hasOwnProperty.call(b, v)) {
|
|
@@ -1101,6 +1101,11 @@ function syncUpdaterSubject(target, source) {
|
|
|
1101
1101
|
}
|
|
1102
1102
|
|
|
1103
1103
|
if (isObject(value)) {
|
|
1104
|
+
const proto = Object.getPrototypeOf(value);
|
|
1105
|
+
if (proto && proto !== Object.prototype) {
|
|
1106
|
+
target[key] = value;
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1104
1109
|
if (!isObject(target?.[key]) || isArray(target?.[key])) {
|
|
1105
1110
|
target[key] = {};
|
|
1106
1111
|
}
|
package/source/util/clone.mjs
CHANGED
|
@@ -80,6 +80,29 @@ function clone(obj) {
|
|
|
80
80
|
return new URL(obj.toString());
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
// Handle RegExp
|
|
84
|
+
if (obj instanceof RegExp) {
|
|
85
|
+
return new RegExp(obj.source, obj.flags);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Handle Map
|
|
89
|
+
if (obj instanceof Map) {
|
|
90
|
+
const copy = new Map();
|
|
91
|
+
for (const [key, value] of obj.entries()) {
|
|
92
|
+
copy.set(clone(key), clone(value));
|
|
93
|
+
}
|
|
94
|
+
return copy;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Handle Set
|
|
98
|
+
if (obj instanceof Set) {
|
|
99
|
+
const copy = new Set();
|
|
100
|
+
for (const value of obj.values()) {
|
|
101
|
+
copy.add(clone(value));
|
|
102
|
+
}
|
|
103
|
+
return copy;
|
|
104
|
+
}
|
|
105
|
+
|
|
83
106
|
/** Do not clone DOM nodes */
|
|
84
107
|
if (typeof Element !== "undefined" && obj instanceof Element) return obj;
|
|
85
108
|
if (typeof Document !== "undefined" && obj instanceof Document) return obj;
|
package/test/cases/data/diff.mjs
CHANGED
|
@@ -65,7 +65,7 @@ describe('Diff', function () {
|
|
|
65
65
|
|
|
66
66
|
it('Diff value with null ', function () {
|
|
67
67
|
let d = diff(obj1, obj2);
|
|
68
|
-
expect(JSON.stringify(d)).is.equal('[{"operator":"update","path":["count"],"first":{"value":1,"type":"number"},"second":{"value":2,"type":"number"}},{"operator":"delete","path":["info"],"first":{"value":"test","type":"string"}}]');
|
|
68
|
+
expect(JSON.stringify(d)).is.equal('[{"operator":"update","path":["count"],"first":{"value":1,"type":"number"},"second":{"value":2,"type":"number"}},{"operator":"delete","path":["info"],"first":{"value":"test","type":"string"}},{"operator":"update","path":["exchange"],"first":{"value":[],"type":"object"},"second":{"value":[],"type":"object"}}]');
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
it('Diff identical value with null ', function () {
|
|
@@ -86,6 +86,21 @@ describe('Diff', function () {
|
|
|
86
86
|
const date5 = new Date(Date.parse('04 Dec 1995 00:12:01 GMT')); // Date
|
|
87
87
|
const date6 = new Date(Date.parse('04 Dec 1995 00:12:02 GMT')); // Date
|
|
88
88
|
|
|
89
|
+
const hiddenKey = Symbol("hidden");
|
|
90
|
+
class HiddenState {
|
|
91
|
+
constructor(value) {
|
|
92
|
+
this[hiddenKey] = value;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get value() {
|
|
96
|
+
return this[hiddenKey];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
getClone() {
|
|
100
|
+
return new HiddenState(this.value);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
89
104
|
[
|
|
90
105
|
|
|
91
106
|
[
|
|
@@ -146,6 +161,15 @@ describe('Diff', function () {
|
|
|
146
161
|
},
|
|
147
162
|
'[]'
|
|
148
163
|
],
|
|
164
|
+
[
|
|
165
|
+
{
|
|
166
|
+
a: new HiddenState("a")
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
a: new HiddenState("b")
|
|
170
|
+
},
|
|
171
|
+
'[{"operator":"update","path":["a"],"first":{"value":{},"type":"object","instance":"HiddenState"},"second":{"value":{},"type":"object","instance":"HiddenState"}}]'
|
|
172
|
+
],
|
|
149
173
|
[
|
|
150
174
|
{},
|
|
151
175
|
{
|
|
@@ -238,4 +262,4 @@ describe('Diff', function () {
|
|
|
238
262
|
|
|
239
263
|
});
|
|
240
264
|
|
|
241
|
-
})
|
|
265
|
+
})
|
|
@@ -27,7 +27,7 @@ const updaterSymbolSymbol = Symbol.for(updaterSymbolKey);
|
|
|
27
27
|
|
|
28
28
|
describe('DOM', function () {
|
|
29
29
|
|
|
30
|
-
let CustomElement, registerCustomElement, TestComponent, document, TestComponent2, assignUpdaterToElement,
|
|
30
|
+
let CustomElement, registerCustomElement, TestComponent, document, TestComponent2, TestStateComponent, HiddenStateClass, assignUpdaterToElement,
|
|
31
31
|
addObjectWithUpdaterToElement;
|
|
32
32
|
|
|
33
33
|
describe("assignUpdaterToElement", function () {
|
|
@@ -184,6 +184,40 @@ describe('DOM', function () {
|
|
|
184
184
|
|
|
185
185
|
registerCustomElement(TestComponent2)
|
|
186
186
|
|
|
187
|
+
const hiddenKey = Symbol("hidden");
|
|
188
|
+
class HiddenState {
|
|
189
|
+
constructor(presentation) {
|
|
190
|
+
this[hiddenKey] = presentation;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
get presentation() {
|
|
194
|
+
return this[hiddenKey];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
getClone() {
|
|
198
|
+
return new HiddenState(this.presentation);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
HiddenStateClass = HiddenState;
|
|
203
|
+
|
|
204
|
+
TestStateComponent = class extends CustomElement {
|
|
205
|
+
static getTag() {
|
|
206
|
+
return "monster-testclass-state"
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
get defaults() {
|
|
210
|
+
return Object.assign({}, super.defaults, {
|
|
211
|
+
current: new HiddenStateClass(""),
|
|
212
|
+
templates: {
|
|
213
|
+
main: '<div id="state" data-monster-replace="path:current.presentation"></div>'
|
|
214
|
+
}
|
|
215
|
+
})
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
registerCustomElement(TestStateComponent)
|
|
220
|
+
|
|
187
221
|
document = getDocument();
|
|
188
222
|
done()
|
|
189
223
|
} catch (e) {
|
|
@@ -292,6 +326,26 @@ describe('DOM', function () {
|
|
|
292
326
|
|
|
293
327
|
})
|
|
294
328
|
|
|
329
|
+
describe('Updater sync for instance values', function () {
|
|
330
|
+
it('should keep class instances and update presentation', function (done) {
|
|
331
|
+
let d = document.createElement('monster-testclass-state');
|
|
332
|
+
document.getElementById('test1').appendChild(d);
|
|
333
|
+
|
|
334
|
+
setTimeout(function () {
|
|
335
|
+
d.setOption('current', new HiddenStateClass('OK'));
|
|
336
|
+
|
|
337
|
+
setTimeout(function () {
|
|
338
|
+
try {
|
|
339
|
+
expect(d.shadowRoot.querySelector('#state').textContent).to.equal('OK');
|
|
340
|
+
done();
|
|
341
|
+
} catch (e) {
|
|
342
|
+
done(e);
|
|
343
|
+
}
|
|
344
|
+
}, 20);
|
|
345
|
+
}, 10);
|
|
346
|
+
});
|
|
347
|
+
})
|
|
348
|
+
|
|
295
349
|
describe('setOptions()', function () {
|
|
296
350
|
[
|
|
297
351
|
['shadowMode', 'x1'],
|
|
@@ -119,6 +119,41 @@ describe('Clone', function () {
|
|
|
119
119
|
|
|
120
120
|
})
|
|
121
121
|
|
|
122
|
+
describe('.clone(Map)', function () {
|
|
123
|
+
it('.clone(Map) should preserve entries', function () {
|
|
124
|
+
let a = new Map([
|
|
125
|
+
['x', 1],
|
|
126
|
+
['y', {z: 2}],
|
|
127
|
+
]);
|
|
128
|
+
let b = clone(a);
|
|
129
|
+
expect(b).to.be.instanceOf(Map);
|
|
130
|
+
expect(b).not.equal(a);
|
|
131
|
+
expect(b.get('x')).to.equal(1);
|
|
132
|
+
expect(JSON.stringify(b.get('y'))).to.equal(JSON.stringify({z: 2}));
|
|
133
|
+
});
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
describe('.clone(Set)', function () {
|
|
137
|
+
it('.clone(Set) should preserve values', function () {
|
|
138
|
+
let a = new Set([1, 2, 3]);
|
|
139
|
+
let b = clone(a);
|
|
140
|
+
expect(b).to.be.instanceOf(Set);
|
|
141
|
+
expect(b).not.equal(a);
|
|
142
|
+
expect([...b]).to.deep.equal([1, 2, 3]);
|
|
143
|
+
});
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
describe('.clone(RegExp)', function () {
|
|
147
|
+
it('.clone(RegExp) should preserve pattern and flags', function () {
|
|
148
|
+
let a = /test/gi;
|
|
149
|
+
let b = clone(a);
|
|
150
|
+
expect(b).to.be.instanceOf(RegExp);
|
|
151
|
+
expect(b).not.equal(a);
|
|
152
|
+
expect(b.source).to.equal(a.source);
|
|
153
|
+
expect(b.flags).to.equal(a.flags);
|
|
154
|
+
});
|
|
155
|
+
})
|
|
156
|
+
|
|
122
157
|
describe('.clone()', function () {
|
|
123
158
|
|
|
124
159
|
[
|
|
@@ -152,4 +187,3 @@ describe('Clone', function () {
|
|
|
152
187
|
});
|
|
153
188
|
|
|
154
189
|
});
|
|
155
|
-
|