@schukai/monster 3.91.0 → 3.92.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 +19 -0
- package/package.json +1 -1
- package/source/components/datatable/save-button.mjs +3 -0
- package/source/components/form/context-error.mjs +2 -13
- package/source/components/form/context-help.mjs +1 -1
- package/source/components/form/password.mjs +2 -2
- package/source/components/form/reload.mjs +1 -1
- package/source/components/form/shadow-reload.mjs +1 -1
- package/source/components/form/template.mjs +49 -18
- package/source/components/form/tree-select.mjs +60 -42
- package/source/components/layout/tabs.mjs +889 -825
- package/source/types/version.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/web/test.html +2 -2
- package/test/web/tests.js +136 -59
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
+
## [3.92.1] - 2024-12-18
|
6
|
+
|
7
|
+
### Bug Fixes
|
8
|
+
|
9
|
+
- **tabs:** Only activate the closing behaviour if the closed tab was previously active. [#264](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/264)
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
## [3.92.0] - 2024-12-18
|
14
|
+
|
15
|
+
### Add Features
|
16
|
+
|
17
|
+
- **tabs:** new feature flag removeBehavior [#268](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/268) , update form/template and tree-select
|
18
|
+
### Changes
|
19
|
+
|
20
|
+
- update project
|
21
|
+
|
22
|
+
|
23
|
+
|
5
24
|
## [3.91.0] - 2024-12-15
|
6
25
|
|
7
26
|
### Add Features
|
package/package.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.12","@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":"3.
|
1
|
+
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.12","@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":"3.92.1"}
|
@@ -53,23 +53,12 @@ const popperElementSymbol = Symbol("popperElement");
|
|
53
53
|
*/
|
54
54
|
const iconElementSymbol = Symbol("iconElement");
|
55
55
|
|
56
|
-
/**
|
57
|
-
* The ContextError control shows an error message in a popper.
|
58
|
-
*
|
59
|
-
* @fragments /fragments/components/form/context-error/
|
60
|
-
*
|
61
|
-
* @example /examples/components/form/context-error-simple
|
62
|
-
*
|
63
|
-
* @copyright schukai GmbH
|
64
|
-
* @summary A control that can be used to display a tooltip or a popover with an error message.
|
65
|
-
**/
|
66
|
-
|
67
56
|
/**
|
68
57
|
* A context error control.
|
69
58
|
*
|
70
|
-
* @fragments /fragments/components/form/
|
59
|
+
* @fragments /fragments/components/form/context-error
|
71
60
|
*
|
72
|
-
* @example /examples/components/form/
|
61
|
+
* @example /examples/components/form/context-error-simple
|
73
62
|
*
|
74
63
|
* @since 3.55.0
|
75
64
|
* @copyright schukai GmbH
|
@@ -50,9 +50,9 @@ export const inputElementSymbol = Symbol("inputIconElement");
|
|
50
50
|
/**
|
51
51
|
* A password field
|
52
52
|
*
|
53
|
-
* @fragments /fragments/components/
|
53
|
+
* @fragments /fragments/components/form/password
|
54
54
|
*
|
55
|
-
* @example /examples/components/
|
55
|
+
* @example /examples/components/form/password-simple
|
56
56
|
*
|
57
57
|
* @since 3.89.0
|
58
58
|
* @copyright schukai GmbH
|
@@ -121,7 +121,7 @@ class Reload extends CustomElement {
|
|
121
121
|
* @property {string} url=undefined
|
122
122
|
* @property {string} reload=undefined currently the values defined are `onshow` and `always`. The default `onshow` removes the IntersectionObserver. This means that the content is only loaded once. reloading of the content does not occur.
|
123
123
|
* @property {string} filter=undefined dom selectors to search for elements, if undefined then everything is taken
|
124
|
-
* @property {
|
124
|
+
* @property {Object[]} processors
|
125
125
|
* @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
|
126
126
|
* @property {String} fetch.redirect=error
|
127
127
|
* @property {String} fetch.method=GET
|
@@ -50,7 +50,7 @@ class ShadowReload extends Reload {
|
|
50
50
|
* @property {string} url=undefined
|
51
51
|
* @property {string} reload=undefined currently the values defined are `onshow` and `always`. The default `onshow` removes the IntersectionObserver. This means that the content is only loaded once. reloading of the content does not occur.
|
52
52
|
* @property {string} filter=undefined dom selectors to search for elements, if undefined then everything is taken
|
53
|
-
* @property {
|
53
|
+
* @property {Object[]} processors
|
54
54
|
* @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
|
55
55
|
* @property {String} fetch.redirect=error
|
56
56
|
* @property {String} fetch.method=GET
|
@@ -40,9 +40,12 @@ const intersectionObserverWasInitialized = Symbol("wasInitialized");
|
|
40
40
|
/**
|
41
41
|
* A Template control is a control that can be used to load content from a URL and display it in the ShadowRoot.
|
42
42
|
*
|
43
|
-
* @fragments /fragments/components/form/template
|
43
|
+
* @fragments /fragments/components/form/template
|
44
44
|
*
|
45
45
|
* @example /examples/components/form/template-simple
|
46
|
+
* @example /examples/components/form/template-with-default
|
47
|
+
* @example /examples/components/form/template-with-processor
|
48
|
+
* @example /examples/components/form/template-onshow
|
46
49
|
*
|
47
50
|
* @since 1.11.0
|
48
51
|
* @copyright schukai GmbH
|
@@ -69,7 +72,7 @@ class Template extends CustomElement {
|
|
69
72
|
* @property {string} templates.main Main template
|
70
73
|
* @property {string} url=undefined
|
71
74
|
* @property {string} reload=undefined currently the only value defined is `onshow`. Currently the only value defined is onshow. this removes the IntersectionObserver. this means that the content is only loaded once. reloading of the content does not occur.
|
72
|
-
* @property {
|
75
|
+
* @property {Object[]} processors
|
73
76
|
* @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
|
74
77
|
* @property {String} fetch.redirect=error
|
75
78
|
* @property {String} fetch.method=GET
|
@@ -85,8 +88,8 @@ class Template extends CustomElement {
|
|
85
88
|
templates: {
|
86
89
|
main: getTemplate(),
|
87
90
|
},
|
88
|
-
url:
|
89
|
-
reload:
|
91
|
+
url: null,
|
92
|
+
reload: null,
|
90
93
|
processors: [],
|
91
94
|
fetch: {
|
92
95
|
redirect: "error",
|
@@ -123,8 +126,6 @@ class Template extends CustomElement {
|
|
123
126
|
this[attributeObserverSymbol][ATTRIBUTE_FORM_URL] = (url) => {
|
124
127
|
if (this.hasAttribute(ATTRIBUTE_FORM_URL)) {
|
125
128
|
this.setOption("url", new URL(url, document.location).toString());
|
126
|
-
} else {
|
127
|
-
this.setOption("url", undefined);
|
128
129
|
}
|
129
130
|
};
|
130
131
|
}
|
@@ -139,7 +140,7 @@ class Template extends CustomElement {
|
|
139
140
|
* @throws {Error} not found
|
140
141
|
* @throws {Error} undefined status or type
|
141
142
|
* @fires monster-fetched
|
142
|
-
* @return {
|
143
|
+
* @return {void}
|
143
144
|
*/
|
144
145
|
[assembleMethodSymbol]() {
|
145
146
|
super[assembleMethodSymbol]();
|
@@ -181,13 +182,6 @@ class Template extends CustomElement {
|
|
181
182
|
}
|
182
183
|
}
|
183
184
|
|
184
|
-
/**
|
185
|
-
* @typedef {Object} Processor
|
186
|
-
* @property {String} destination
|
187
|
-
* @property {String} source
|
188
|
-
* @since 1.11.8
|
189
|
-
*/
|
190
|
-
|
191
185
|
/**
|
192
186
|
* This attribute can be used to pass a URL to this select.
|
193
187
|
*
|
@@ -276,7 +270,12 @@ function loadContent() {
|
|
276
270
|
throw new Error("no shadow-root is defined");
|
277
271
|
}
|
278
272
|
|
279
|
-
|
273
|
+
let url = this.getOption("url", undefined);
|
274
|
+
|
275
|
+
if (url instanceof URL) {
|
276
|
+
url = url.toString();
|
277
|
+
}
|
278
|
+
|
280
279
|
if (!isString(url) || url === "") {
|
281
280
|
throw new Error("missing url");
|
282
281
|
}
|
@@ -303,6 +302,7 @@ function loadContent() {
|
|
303
302
|
loadAndAssignContent(container, url, options)
|
304
303
|
.then(() => {
|
305
304
|
defaultSlot.style.display = "none";
|
305
|
+
container.style.display = "block";
|
306
306
|
runProcessors.call(this);
|
307
307
|
})
|
308
308
|
.catch((e) => {
|
@@ -316,15 +316,40 @@ function loadContent() {
|
|
316
316
|
*/
|
317
317
|
function runProcessors() {
|
318
318
|
const processors = this.getOption("processors");
|
319
|
-
if (!isArray(processors)) return;
|
319
|
+
if (!isArray(processors)) return this;
|
320
320
|
|
321
321
|
for (const [, processor] of processors.entries()) {
|
322
322
|
const source = processor?.source;
|
323
|
-
|
323
|
+
let destination = processor?.destination;
|
324
|
+
|
325
|
+
if (source === null) {
|
326
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "missing source");
|
327
|
+
continue;
|
328
|
+
}
|
329
|
+
|
330
|
+
if (
|
331
|
+
destination === null ||
|
332
|
+
destination === undefined ||
|
333
|
+
destination === ""
|
334
|
+
) {
|
335
|
+
destination = "[" + ATTRIBUTE_ROLE + "=container]";
|
336
|
+
}
|
324
337
|
|
325
338
|
if (isString(source) && isString(destination)) {
|
326
339
|
const sourceNode = this.shadowRoot.querySelector(source);
|
327
|
-
|
340
|
+
let destinationNode = document.querySelector(destination);
|
341
|
+
|
342
|
+
if (destinationNode === null) {
|
343
|
+
destinationNode = this.shadowRoot.querySelector(destination);
|
344
|
+
if (destinationNode === null) {
|
345
|
+
addAttributeToken(
|
346
|
+
this,
|
347
|
+
ATTRIBUTE_ERRORMESSAGE,
|
348
|
+
"destination not found",
|
349
|
+
);
|
350
|
+
continue;
|
351
|
+
}
|
352
|
+
}
|
328
353
|
|
329
354
|
if (
|
330
355
|
sourceNode instanceof HTMLElement &&
|
@@ -332,6 +357,12 @@ function runProcessors() {
|
|
332
357
|
) {
|
333
358
|
destinationNode.innerHTML = sourceNode.cloneNode(true).innerHTML;
|
334
359
|
}
|
360
|
+
} else {
|
361
|
+
addAttributeToken(
|
362
|
+
this,
|
363
|
+
ATTRIBUTE_ERRORMESSAGE,
|
364
|
+
"invalid source or destination",
|
365
|
+
);
|
335
366
|
}
|
336
367
|
}
|
337
368
|
|
@@ -13,8 +13,12 @@
|
|
13
13
|
*/
|
14
14
|
|
15
15
|
import { buildTree } from "../../data/buildtree.mjs";
|
16
|
-
import { findClosestByAttribute } from "../../dom/attributes.mjs";
|
17
16
|
import {
|
17
|
+
addAttributeToken,
|
18
|
+
findClosestByAttribute,
|
19
|
+
} from "../../dom/attributes.mjs";
|
20
|
+
import {
|
21
|
+
ATTRIBUTE_ERRORMESSAGE,
|
18
22
|
ATTRIBUTE_ROLE,
|
19
23
|
ATTRIBUTE_UPDATER_INSERT_REFERENCE,
|
20
24
|
} from "../../dom/constants.mjs";
|
@@ -57,7 +61,7 @@ const keyEventHandler = Symbol("keyEventHandler");
|
|
57
61
|
*
|
58
62
|
* @fragments /fragments/components/form/tree-select
|
59
63
|
*
|
60
|
-
* @example /examples/components/form/tree-select
|
64
|
+
* @example /examples/components/form/tree-select-simple
|
61
65
|
*
|
62
66
|
* @since 1.9.0
|
63
67
|
* @copyright schukai GmbH
|
@@ -98,8 +102,12 @@ class TreeSelect extends Select {
|
|
98
102
|
{
|
99
103
|
mapping: {
|
100
104
|
rootReferences: ["0", undefined, null],
|
101
|
-
|
102
|
-
|
105
|
+
id: "id",
|
106
|
+
parent: "parent",
|
107
|
+
|
108
|
+
selector: "*",
|
109
|
+
labelTemplate: "",
|
110
|
+
valueTemplate: "",
|
103
111
|
},
|
104
112
|
formatter: {
|
105
113
|
selection: formatHierarchicalSelection,
|
@@ -145,54 +153,58 @@ class TreeSelect extends Select {
|
|
145
153
|
const filter = mappingOptions?.["filter"];
|
146
154
|
const rootReferences = mappingOptions?.["rootReferences"];
|
147
155
|
|
148
|
-
const id = this.getOption("mapping.
|
149
|
-
const parentID = this.getOption("mapping.
|
156
|
+
const id = this.getOption("mapping.id", "id");
|
157
|
+
const parentID = this.getOption("mapping.parent", "parent");
|
150
158
|
|
151
159
|
const selector = mappingOptions?.["selector"];
|
152
|
-
|
153
|
-
const nodes = buildTree(data, selector, id, parentID, {
|
154
|
-
filter,
|
155
|
-
rootReferences,
|
156
|
-
});
|
157
|
-
|
158
160
|
const options = [];
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
const
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
161
|
+
|
162
|
+
try {
|
163
|
+
const nodes = buildTree(data, selector, id, parentID, {
|
164
|
+
filter,
|
165
|
+
rootReferences,
|
166
|
+
});
|
167
|
+
|
168
|
+
for (const node of nodes) {
|
169
|
+
const iterator = new NodeRecursiveIterator(node);
|
170
|
+
for (const n of iterator) {
|
171
|
+
const formattedValues = formatKeyLabel.call(this, n);
|
172
|
+
|
173
|
+
const label = formattedValues.label;
|
174
|
+
const value = formattedValues.value;
|
175
|
+
const intend = n.level;
|
176
|
+
|
177
|
+
const visibility = intend > 0 ? "hidden" : "visible";
|
178
|
+
const state = "close";
|
179
|
+
|
180
|
+
this[internalNodesSymbol].set(value, n);
|
181
|
+
|
182
|
+
options.push({
|
183
|
+
value,
|
184
|
+
label,
|
185
|
+
intend,
|
186
|
+
state,
|
187
|
+
visibility,
|
188
|
+
["has-children"]: n.hasChildNodes(),
|
189
|
+
});
|
190
|
+
}
|
181
191
|
}
|
182
|
-
}
|
183
192
|
|
184
|
-
|
193
|
+
this.setOption("options", options);
|
185
194
|
|
186
|
-
|
187
|
-
|
188
|
-
|
195
|
+
fireCustomEvent(this, "monster-options-set", {
|
196
|
+
options,
|
197
|
+
});
|
198
|
+
} catch (e) {
|
199
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e?.message || e);
|
200
|
+
}
|
189
201
|
|
190
202
|
return this;
|
191
203
|
}
|
192
204
|
|
193
205
|
/**
|
194
206
|
*
|
195
|
-
* @return {
|
207
|
+
* @return {TreeSelect}
|
196
208
|
*/
|
197
209
|
[assembleMethodSymbol]() {
|
198
210
|
super[assembleMethodSymbol]();
|
@@ -251,10 +263,16 @@ function closeOrOpenCurrentOption(event, mode) {
|
|
251
263
|
function formatKeyLabel(node) {
|
252
264
|
validateInstance(node, Node);
|
253
265
|
|
254
|
-
const
|
266
|
+
const v = node.value;
|
267
|
+
if (v === undefined) {
|
268
|
+
throw new Error("the object has no value for the specified id");
|
269
|
+
}
|
270
|
+
|
271
|
+
const label = new Formatter(v).format(
|
255
272
|
this.getOption("mapping.labelTemplate", ""),
|
256
273
|
);
|
257
|
-
|
274
|
+
|
275
|
+
const value = new Formatter(v).format(
|
258
276
|
this.getOption("mapping.valueTemplate", ""),
|
259
277
|
);
|
260
278
|
|