@schukai/monster 3.69.2 → 3.71.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. package/CHANGELOG.md +29 -4
  2. package/package.json +1 -1
  3. package/source/components/datatable/dataset.mjs +278 -202
  4. package/source/components/datatable/datasource/dom.mjs +1 -1
  5. package/source/components/datatable/datasource/rest.mjs +410 -404
  6. package/source/components/datatable/filter.mjs +1 -0
  7. package/source/components/datatable/save-button.mjs +1 -9
  8. package/source/components/datatable/style/datatable.pcss +1 -1
  9. package/source/components/datatable/style/filter-controls-defaults.pcss +1 -1
  10. package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +8 -17
  11. package/source/components/form/context-error.mjs +2 -0
  12. package/source/components/form/context-help.mjs +1 -0
  13. package/source/components/form/field-set.mjs +222 -225
  14. package/source/components/form/form.mjs +185 -545
  15. package/source/components/form/select.mjs +24 -9
  16. package/source/components/form/style/field-set.pcss +84 -7
  17. package/source/components/form/style/form.pcss +5 -3
  18. package/source/components/form/style/select.pcss +5 -4
  19. package/source/components/form/stylesheet/field-set.mjs +7 -14
  20. package/source/components/form/stylesheet/form.mjs +8 -17
  21. package/source/components/form/stylesheet/select.mjs +7 -14
  22. package/source/components/layout/style/collapse.pcss +0 -2
  23. package/source/components/layout/stylesheet/collapse.mjs +7 -14
  24. package/source/components/style/form.pcss +66 -3
  25. package/source/components/style/mixin/property.pcss +8 -1
  26. package/source/components/style/typography.pcss +4 -12
  27. package/source/components/stylesheet/form.mjs +8 -17
  28. package/source/components/stylesheet/mixin/form.mjs +7 -16
  29. package/source/components/stylesheet/mixin/property.mjs +6 -13
  30. package/source/components/stylesheet/typography.mjs +7 -16
  31. package/source/data/datasource/server/restapi.mjs +191 -180
  32. package/source/data/datasource/server.mjs +118 -74
  33. package/source/data/diff.mjs +1 -1
  34. package/source/dom/customelement.mjs +4 -0
  35. package/source/dom/updater.mjs +1 -1
  36. package/source/types/tokenlist.mjs +2 -2
  37. package/test/cases/components/form/form.mjs +1 -182
  38. package/test/cases/components/host/details.mjs +1 -1
  39. package/test/cases/components/host/host.mjs +1 -1
  40. package/test/cases/components/host/overlay.mjs +1 -1
  41. package/test/cases/data/diff.mjs +37 -0
  42. package/test/cases/dom/customcontrol.mjs +1 -1
  43. package/test/cases/dom/customelement.mjs +2 -2
  44. package/source/components/style/mixin/form.pcss +0 -242
package/CHANGELOG.md CHANGED
@@ -2,21 +2,46 @@
2
2
 
3
3
 
4
4
 
5
- ## [3.69.2] - 2024-06-24
5
+ ## [3.71.0] - 2024-06-25
6
+
7
+ ### Add Features
8
+
9
+ - new feature for transfer the part that has been changed [#217](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/217)
10
+
11
+ ## [3.70.0] - 2024-06-25
12
+
13
+ ### Add Features
14
+
15
+ - complete change of form control to a derivation of dataset [#216](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/216)
16
+ - new dataset feature refreshOnMutation [#215](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/215)
17
+ - new comprehensive options display [#213](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/213)
6
18
 
7
19
  ### Bug Fixes
8
20
 
9
- - the rest datasource should not reload if the query is undefined [#211](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/211)
21
+ - initialize of loaded html fields [#210](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/210)
22
+ - values from the value attribute are now displayed correctly after loading the options. [#212](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/212)
23
+ - If a value is specified in the select, it is now also displayed with a label from the options. [#212](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/212)
10
24
 
25
+ ### Changes
11
26
 
27
+ - doc, little bugs and tidy
28
+ - test adjustments and minor layout adjustments
12
29
 
13
- ## [3.69.1] - 2024-06-23
30
+ ### Code Refactoring
31
+
32
+ - adjustments to the form stylesheets [#214](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/214)
33
+
34
+ ## [3.69.2] - 2024-06-24
14
35
 
15
36
  ### Bug Fixes
16
37
 
17
- - small css adjustments to the field set [#209](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/209)
38
+ - the rest datasource should not reload if the query is undefined [#211](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/211)
18
39
 
40
+ ## [3.69.1] - 2024-06-23
19
41
 
42
+ ### Bug Fixes
43
+
44
+ - small css adjustments to the field set [#209](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/209)
20
45
 
21
46
  ## [3.69.0] - 2024-06-23
22
47
 
package/package.json CHANGED
@@ -1 +1 @@
1
- {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.5","@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.69.2"}
1
+ {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.5","@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.71.0"}
@@ -12,33 +12,33 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import { instanceSymbol, internalSymbol } from "../../constants.mjs";
16
- import { Pathfinder } from "../../data/pathfinder.mjs";
17
- import { getLinkedObjects, hasObjectLink } from "../../dom/attributes.mjs";
18
- import { customElementUpdaterLinkSymbol } from "../../dom/constants.mjs";
15
+ import {instanceSymbol, internalSymbol} from "../../constants.mjs";
16
+ import {Pathfinder} from "../../data/pathfinder.mjs";
17
+ import {getLinkedObjects, hasObjectLink} from "../../dom/attributes.mjs";
18
+ import {customElementUpdaterLinkSymbol} from "../../dom/constants.mjs";
19
19
  import {
20
- assembleMethodSymbol,
21
- CustomElement,
22
- attributeObserverSymbol,
23
- registerCustomElement,
20
+ assembleMethodSymbol,
21
+ CustomElement,
22
+ attributeObserverSymbol,
23
+ registerCustomElement,
24
24
  } from "../../dom/customelement.mjs";
25
- import { findElementWithSelectorUpwards } from "../../dom/util.mjs";
26
- import { isString } from "../../types/is.mjs";
27
- import { Observer } from "../../types/observer.mjs";
28
- import { clone } from "../../util/clone.mjs";
25
+ import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
26
+ import {isString} from "../../types/is.mjs";
27
+ import {Observer} from "../../types/observer.mjs";
28
+ import {clone} from "../../util/clone.mjs";
29
29
  import {
30
- ATTRIBUTE_DATASOURCE_SELECTOR,
31
- ATTRIBUTE_DATATABLE_INDEX,
30
+ ATTRIBUTE_DATASOURCE_SELECTOR,
31
+ ATTRIBUTE_DATATABLE_INDEX,
32
32
  } from "./constants.mjs";
33
- import { Datasource } from "./datasource.mjs";
34
- import { DatasetStyleSheet } from "./stylesheet/dataset.mjs";
33
+ import {Datasource} from "./datasource.mjs";
34
+ import {DatasetStyleSheet} from "./stylesheet/dataset.mjs";
35
35
  import {
36
- handleDataSourceChanges,
37
- datasourceLinkedElementSymbol,
36
+ handleDataSourceChanges,
37
+ datasourceLinkedElementSymbol,
38
38
  } from "./util.mjs";
39
- import { FormStyleSheet } from "../stylesheet/form.mjs";
39
+ import {FormStyleSheet} from "../stylesheet/form.mjs";
40
40
 
41
- export { DataSet };
41
+ export {DataSet};
42
42
 
43
43
  /**
44
44
  * The data set component is used to show the data of a data source.
@@ -79,184 +79,219 @@ export { DataSet };
79
79
  * @summary A data set
80
80
  */
81
81
  class DataSet extends CustomElement {
82
- /**
83
- * This method is called by the `instanceof` operator.
84
- * @returns {symbol}
85
- */
86
- static get [instanceSymbol]() {
87
- return Symbol.for("@schukai/monster/components/dataset@@instance");
88
- }
89
-
90
- /**
91
- * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
92
- *
93
- * @return {string[]}
94
- * @since 1.15.0
95
- */
96
- static get observedAttributes() {
97
- const attributes = super.observedAttributes;
98
- attributes.push(ATTRIBUTE_DATATABLE_INDEX);
99
- return attributes;
100
- }
101
-
102
- /**
103
- * To set the options via the html tag the attribute `data-monster-options` must be used.
104
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
105
- *
106
- * The individual configuration values can be found in the table.
107
- *
108
- * @property {Object} templates Template definitions
109
- * @property {string} templates.main Main template
110
- * @property {object} datasource The datasource
111
- * @property {string} datasource.selector The selector of the datasource
112
- * @property {object} mapping The mapping
113
- * @property {string} mapping.data The data
114
- * @property {number} mapping.index The index
115
- * @property {Array} data The data
116
- */
117
- get defaults() {
118
- const obj = Object.assign({}, super.defaults, {
119
- templates: {
120
- main: getTemplate(),
121
- },
122
-
123
- datasource: {
124
- selector: null,
125
- },
126
-
127
- mapping: {
128
- data: "dataset",
129
- index: 0,
130
- },
131
-
132
- data: {},
133
- });
134
-
135
- updateOptionsFromArguments.call(this, obj);
136
- return obj;
137
- }
138
-
139
- /**
140
- *
141
- * @return {string}
142
- */
143
- static getTag() {
144
- return "monster-dataset";
145
- }
146
-
147
- write() {
148
- return new Promise((resolve, reject) => {
149
- if (!this[datasourceLinkedElementSymbol]) {
150
- reject(new Error("No datasource"));
151
- return;
152
- }
153
-
154
- const internalUpdateCloneData = this.getInternalUpdateCloneData();
155
- if (!internalUpdateCloneData) {
156
- reject(new Error("No update data"));
157
- return;
158
- }
159
-
160
- const internalData = internalUpdateCloneData?.["data"];
161
- if (
162
- internalData === undefined ||
163
- internalData === null ||
164
- internalData === ""
165
- ) {
166
- reject(new Error("No data"));
167
- return;
168
- }
169
-
170
- setTimeout(() => {
171
- const path = this.getOption("mapping.data");
172
- const index = this.getOption("mapping.index");
173
-
174
- let pathWithIndex;
175
-
176
- if (isString(path) && path !== "") {
177
- pathWithIndex = path + "." + index;
178
- } else {
179
- pathWithIndex = index;
180
- }
181
-
182
- const data = this[datasourceLinkedElementSymbol].data;
183
- const unref = JSON.stringify(data);
184
- const ref = JSON.parse(unref);
185
-
186
- new Pathfinder(ref).setVia(pathWithIndex, internalData);
187
-
188
- this[datasourceLinkedElementSymbol].data = ref;
189
-
190
- resolve();
191
- }, 0);
192
- });
193
- }
194
-
195
- /**
196
- * This method is responsible for assembling the component.
197
- *
198
- * It calls the parent's assemble method first, then initializes control references and event handlers.
199
- * If the `datasource.selector` option is provided and is a string, it searches for the corresponding
200
- * element in the DOM using that selector.
201
- *
202
- * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class.
203
- *
204
- * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component
205
- * attaches an observer to the datasource's changes.
206
- *
207
- * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component.
208
- * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges`
209
- * method in the component's context.
210
- */
211
- [assembleMethodSymbol]() {
212
- super[assembleMethodSymbol]();
213
-
214
- // initControlReferences.call(self);
215
- initEventHandler.call(this);
216
-
217
- const selector = this.getOption("datasource.selector");
218
-
219
- if (isString(selector)) {
220
- const element = findElementWithSelectorUpwards(this, selector);
221
- if (element === null) {
222
- throw new Error("the selector must match exactly one element");
223
- }
224
-
225
- if (!(element instanceof Datasource)) {
226
- throw new TypeError("the element must be a datasource");
227
- }
228
-
229
- this[datasourceLinkedElementSymbol] = element;
230
- element.datasource.attachObserver(
231
- new Observer(handleDataSourceChanges.bind(this)),
232
- );
233
- }
234
-
235
- this.attachObserver(
236
- new Observer(() => {
237
- handleDataSourceChanges.call(this);
238
- }),
239
- );
240
- }
241
-
242
- /**
243
- * @return [CSSStyleSheet]
244
- */
245
- static getCSSStyleSheet() {
246
- return [FormStyleSheet, DatasetStyleSheet];
247
- }
82
+ /**
83
+ * This method is called by the `instanceof` operator.
84
+ * @returns {symbol}
85
+ */
86
+ static get [instanceSymbol]() {
87
+ return Symbol.for("@schukai/monster/components/dataset@@instance");
88
+ }
89
+
90
+ /**
91
+ * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
92
+ *
93
+ * @return {string[]}
94
+ * @since 1.15.0
95
+ */
96
+ static get observedAttributes() {
97
+ const attributes = super.observedAttributes;
98
+ attributes.push(ATTRIBUTE_DATATABLE_INDEX);
99
+ return attributes;
100
+ }
101
+
102
+ /**
103
+ * To set the options via the html tag the attribute `data-monster-options` must be used.
104
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
105
+ *
106
+ * The individual configuration values can be found in the table.
107
+ *
108
+ * @property {Object} templates Template definitions
109
+ * @property {string} templates.main Main template
110
+ * @property {object} datasource The datasource
111
+ * @property {string} datasource.selector The selector of the datasource
112
+ * @property {object} mapping The mapping
113
+ * @property {string} mapping.data The data
114
+ * @property {number} mapping.index The index
115
+ * @property {Array} data The data
116
+ */
117
+ get defaults() {
118
+ const obj = Object.assign({}, super.defaults, {
119
+ templates: {
120
+ main: getTemplate(),
121
+ },
122
+
123
+ datasource: {
124
+ selector: null,
125
+ },
126
+
127
+ mapping: {
128
+ data: "dataset",
129
+ index: 0,
130
+ },
131
+
132
+ features: {
133
+ /**
134
+ * @since 3.70.0
135
+ * @type {boolean}
136
+ */
137
+ refreshOnMutation: true,
138
+ },
139
+
140
+ /**
141
+ * @since 3.70.0
142
+ * @type {boolean}
143
+ */
144
+ refreshOnMutation: {
145
+ selector: "input, select, textarea"
146
+ },
147
+
148
+ data: {},
149
+ });
150
+
151
+ updateOptionsFromArguments.call(this, obj);
152
+ return obj;
153
+ }
154
+
155
+ /**
156
+ *
157
+ * @return {string}
158
+ */
159
+ static getTag() {
160
+ return "monster-dataset";
161
+ }
162
+
163
+ /**
164
+ * This method is called when the component is created.
165
+ * @since 3.70.0
166
+ * @returns {DataSet}
167
+ */
168
+ refresh() {
169
+ // makes sure that handleDataSourceChanges is called
170
+ this.setOption("data", {});
171
+ return this;
172
+ }
173
+
174
+ /**
175
+ *
176
+ * @returns {Promise<unknown>}
177
+ */
178
+ write() {
179
+ return new Promise((resolve, reject) => {
180
+ if (!this[datasourceLinkedElementSymbol]) {
181
+ reject(new Error("No datasource"));
182
+ return;
183
+ }
184
+
185
+ const internalUpdateCloneData = this.getInternalUpdateCloneData();
186
+ if (!internalUpdateCloneData) {
187
+ reject(new Error("No update data"));
188
+ return;
189
+ }
190
+
191
+ const internalData = internalUpdateCloneData?.["data"];
192
+ if (
193
+ internalData === undefined ||
194
+ internalData === null ||
195
+ internalData === ""
196
+ ) {
197
+ reject(new Error("No data"));
198
+ return;
199
+ }
200
+
201
+ setTimeout(() => {
202
+ const path = this.getOption("mapping.data");
203
+ const index = this.getOption("mapping.index");
204
+
205
+ let pathWithIndex;
206
+
207
+ if (isString(path) && path !== "") {
208
+ pathWithIndex = path + "." + index;
209
+ } else {
210
+ pathWithIndex = String(index);
211
+ }
212
+
213
+ const data = this[datasourceLinkedElementSymbol].data;
214
+ const unref = JSON.stringify(data);
215
+ const ref = JSON.parse(unref);
216
+
217
+ new Pathfinder(ref).setVia(pathWithIndex, internalData);
218
+
219
+ this[datasourceLinkedElementSymbol].data = ref;
220
+
221
+ resolve();
222
+ }, 0);
223
+ });
224
+ }
225
+
226
+ /**
227
+ * This method is responsible for assembling the component.
228
+ *
229
+ * It calls the parent's assemble method first, then initializes control references and event handlers.
230
+ * If the `datasource.selector` option is provided and is a string, it searches for the corresponding
231
+ * element in the DOM using that selector.
232
+ *
233
+ * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class.
234
+ *
235
+ * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component
236
+ * attaches an observer to the datasource's changes.
237
+ *
238
+ * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component.
239
+ * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges`
240
+ * method in the component's context.
241
+ */
242
+ [assembleMethodSymbol]() {
243
+ super[assembleMethodSymbol]();
244
+
245
+ initEventHandler.call(this);
246
+
247
+ const selector = this.getOption("datasource.selector");
248
+
249
+ if (isString(selector)) {
250
+ const element = findElementWithSelectorUpwards(this, selector);
251
+ if (element === null) {
252
+ throw new Error("the selector must match exactly one element");
253
+ }
254
+
255
+ if (!(element instanceof Datasource)) {
256
+ throw new TypeError("the element must be a datasource");
257
+ }
258
+
259
+ this[datasourceLinkedElementSymbol] = element;
260
+ element.datasource.attachObserver(
261
+ new Observer(handleDataSourceChanges.bind(this)),
262
+ );
263
+ }
264
+
265
+ this.attachObserver(
266
+ new Observer(() => {
267
+ handleDataSourceChanges.call(this);
268
+ }),
269
+ );
270
+
271
+ if (this.getOption("features.refreshOnMutation")&&this.getOption("refreshOnMutation.selector")) {
272
+ initMutationObserver.call(this);
273
+ }
274
+
275
+ }
276
+
277
+ /**
278
+ * @return [CSSStyleSheet]
279
+ */
280
+ static getCSSStyleSheet() {
281
+ return [FormStyleSheet, DatasetStyleSheet];
282
+ }
248
283
  }
249
284
 
250
285
  /**
251
286
  * @private
252
287
  */
253
288
  function initEventHandler() {
254
- this[attributeObserverSymbol][ATTRIBUTE_DATATABLE_INDEX] = () => {
255
- const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
256
- if (index) {
257
- this.setOption("mapping.index", parseInt(index, 10));
258
- }
259
- };
289
+ this[attributeObserverSymbol][ATTRIBUTE_DATATABLE_INDEX] = () => {
290
+ const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
291
+ if (index) {
292
+ this.setOption("mapping.index", parseInt(index, 10));
293
+ }
294
+ };
260
295
  }
261
296
 
262
297
  /**
@@ -264,26 +299,67 @@ function initEventHandler() {
264
299
  * @param {Object} options
265
300
  */
266
301
  function updateOptionsFromArguments(options) {
267
- const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
302
+ const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
268
303
 
269
- if (index !== null && index !== undefined) {
270
- options.mapping.index = parseInt(index, 10);
271
- }
304
+ if (index !== null && index !== undefined) {
305
+ options.mapping.index = parseInt(index, 10);
306
+ }
272
307
 
273
- const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
308
+ const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
274
309
 
275
- if (selector) {
276
- options.datasource.selector = selector;
277
- }
310
+ if (selector) {
311
+ options.datasource.selector = selector;
312
+ }
278
313
  }
279
314
 
315
+ /**
316
+ * @private
317
+ */
318
+ function initMutationObserver() {
319
+
320
+ const config = {attributes: false, childList: true, subtree: true};
321
+
322
+ const callback = (mutationList, observer) => {
323
+
324
+ if (mutationList.length === 0) {
325
+ return;
326
+ }
327
+
328
+ let doneFlag = false;
329
+ for (const mutation of mutationList) {
330
+
331
+ if (mutation.type === "childList") {
332
+ for (const node of mutation.addedNodes) {
333
+ if(node instanceof HTMLElement && node.matches(this.getOption("refreshOnMutation.selector"))) {
334
+ doneFlag = true;
335
+ break;
336
+ }
337
+ }
338
+
339
+ if (doneFlag) {
340
+ break;
341
+ }
342
+ }
343
+ }
344
+
345
+ if (doneFlag) {
346
+ this.refresh();
347
+ }
348
+ };
349
+
350
+ const observer = new MutationObserver(callback);
351
+ observer.observe(this, config);
352
+
353
+ }
354
+
355
+
280
356
  /**
281
357
  * @private
282
358
  * @return {string}
283
359
  */
284
360
  function getTemplate() {
285
- // language=HTML
286
- return `
361
+ // language=HTML
362
+ return `
287
363
  <div data-monster-role="control" part="control">
288
364
  <slot></slot>
289
365
  </div>
@@ -81,7 +81,7 @@ class Dom extends Datasource {
81
81
 
82
82
  /**
83
83
  *
84
- * @return {Monster.Components.Form.Form}
84
+ * @return {void}
85
85
  */
86
86
  [assembleMethodSymbol]() {
87
87
  super[assembleMethodSymbol]();