@schukai/monster 4.85.0 → 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 +16 -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 +16 -0
- package/source/types/proxyobserver.mjs +9 -1
- 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,22 @@
|
|
|
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
|
+
|
|
13
|
+
## [4.85.1] - 2026-01-08
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
- Add new issue page and enhanced message state button functionality
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
5
21
|
## [4.85.0] - 2026-01-08
|
|
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.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)) {
|
|
@@ -22,6 +22,7 @@ import { parseDataURL } from "../types/dataurl.mjs";
|
|
|
22
22
|
import { getGlobalObject } from "../types/global.mjs";
|
|
23
23
|
import {
|
|
24
24
|
isArray,
|
|
25
|
+
isElement,
|
|
25
26
|
isFunction,
|
|
26
27
|
isIterable,
|
|
27
28
|
isObject,
|
|
@@ -1080,6 +1081,16 @@ function syncUpdaterSubject(target, source) {
|
|
|
1080
1081
|
}
|
|
1081
1082
|
|
|
1082
1083
|
for (const [key, value] of Object.entries(source)) {
|
|
1084
|
+
if (
|
|
1085
|
+
isElement(value) ||
|
|
1086
|
+
(typeof Document !== "undefined" && value instanceof Document) ||
|
|
1087
|
+
(typeof DocumentFragment !== "undefined" &&
|
|
1088
|
+
value instanceof DocumentFragment)
|
|
1089
|
+
) {
|
|
1090
|
+
target[key] = value;
|
|
1091
|
+
continue;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1083
1094
|
if (isArray(value)) {
|
|
1084
1095
|
if (!isArray(target?.[key])) {
|
|
1085
1096
|
target[key] = [];
|
|
@@ -1090,6 +1101,11 @@ function syncUpdaterSubject(target, source) {
|
|
|
1090
1101
|
}
|
|
1091
1102
|
|
|
1092
1103
|
if (isObject(value)) {
|
|
1104
|
+
const proto = Object.getPrototypeOf(value);
|
|
1105
|
+
if (proto && proto !== Object.prototype) {
|
|
1106
|
+
target[key] = value;
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1093
1109
|
if (!isObject(target?.[key]) || isArray(target?.[key])) {
|
|
1094
1110
|
target[key] = {};
|
|
1095
1111
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { Base } from "./base.mjs";
|
|
16
|
-
import { isArray, isObject, isPrimitive } from "./is.mjs";
|
|
16
|
+
import { isArray, isElement, isObject, isPrimitive } from "./is.mjs";
|
|
17
17
|
import { Observer } from "./observer.mjs";
|
|
18
18
|
import { ObserverList } from "./observerlist.mjs";
|
|
19
19
|
import { validateObject } from "./validate.mjs";
|
|
@@ -165,6 +165,14 @@ function getHandler() {
|
|
|
165
165
|
return value;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
if (isElement(value)) {
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (typeof Node !== "undefined" && value instanceof Node) {
|
|
173
|
+
return value;
|
|
174
|
+
}
|
|
175
|
+
|
|
168
176
|
// set value as proxy if object or array
|
|
169
177
|
if (isArray(value) || isObject(value)) {
|
|
170
178
|
if (proxy.objectMap.has(value)) {
|
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
|
-
|