@schukai/monster 4.104.0 → 4.106.0

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,27 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.106.0] - 2026-01-22
6
+
7
+ ### Add Features
8
+
9
+ - Add new password change functionality for issue [#377](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/377)
10
+
11
+
12
+
13
+ ## [4.105.0] - 2026-01-22
14
+
15
+ ### Add Features
16
+
17
+ - Shorten tab labels for better readability
18
+ - Add write-back sanitizer for cleaner dataset diffs
19
+ ### Bug Fixes
20
+
21
+ - tabs labels
22
+ - update
23
+
24
+
25
+
5
26
  ## [4.104.0] - 2026-01-19
6
27
 
7
28
  ### 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.104.0"}
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.106.0"}
@@ -26,7 +26,7 @@ import {
26
26
  getDocument,
27
27
  getWindow,
28
28
  } from "../../dom/util.mjs";
29
- import { isString } from "../../types/is.mjs";
29
+ import { isArray, isObject, isString } from "../../types/is.mjs";
30
30
  import { Observer } from "../../types/observer.mjs";
31
31
  import {
32
32
  ATTRIBUTE_DATASOURCE_SELECTOR,
@@ -40,6 +40,8 @@ import {
40
40
  } from "./util.mjs";
41
41
  import { FormStyleSheet } from "../stylesheet/form.mjs";
42
42
  import { addErrorAttribute } from "../../dom/error.mjs";
43
+ import { Pipe } from "../../data/pipe.mjs";
44
+ import { clone } from "../../util/clone.mjs";
43
45
 
44
46
  export { DataSet };
45
47
 
@@ -135,6 +137,11 @@ class DataSet extends CustomElement {
135
137
  "input, select, textarea, monster-select, monster-toggle-switch",
136
138
  },
137
139
 
140
+ writeBack: {
141
+ transformer: null,
142
+ callbacks: null,
143
+ },
144
+
138
145
  data: {},
139
146
  });
140
147
 
@@ -204,6 +211,17 @@ class DataSet extends CustomElement {
204
211
  pathWithIndex = String(index);
205
212
  }
206
213
 
214
+ let sanitizedData;
215
+ try {
216
+ sanitizedData = applyWriteBackTransform.call(
217
+ this,
218
+ clone(internalData),
219
+ );
220
+ } catch (e) {
221
+ reject(e);
222
+ return;
223
+ }
224
+
207
225
  if (this.getOption("features.skipNoopWrite") === true) {
208
226
  const currentData = this[datasourceLinkedElementSymbol]?.data;
209
227
  let currentValue;
@@ -214,7 +232,7 @@ class DataSet extends CustomElement {
214
232
  currentValue = undefined;
215
233
  }
216
234
  }
217
- if (diff(currentValue, internalData).length === 0) {
235
+ if (diff(currentValue, sanitizedData).length === 0) {
218
236
  resolve();
219
237
  return;
220
238
  }
@@ -223,7 +241,7 @@ class DataSet extends CustomElement {
223
241
  if (this.getOption("logLevel") === "debug") {
224
242
  console.log("monster-dataset: write", {
225
243
  path: pathWithIndex,
226
- data: internalData,
244
+ data: sanitizedData,
227
245
  });
228
246
  }
229
247
 
@@ -236,7 +254,7 @@ class DataSet extends CustomElement {
236
254
  const unref = JSON.stringify(data);
237
255
  const ref = JSON.parse(unref);
238
256
 
239
- new Pathfinder(ref).setVia(pathWithIndex, internalData);
257
+ new Pathfinder(ref).setVia(pathWithIndex, sanitizedData);
240
258
 
241
259
  this[datasourceLinkedElementSymbol].data = ref;
242
260
 
@@ -447,4 +465,45 @@ function getTemplate() {
447
465
  `;
448
466
  }
449
467
 
468
+ /**
469
+ * @private
470
+ * @param {Object|Array} data
471
+ * @return {Object|Array}
472
+ */
473
+ function applyWriteBackTransform(data) {
474
+ const transformer = this.getOption("writeBack.transformer");
475
+ if (transformer === undefined || transformer === null || transformer === "") {
476
+ return clone(data);
477
+ }
478
+
479
+ const pipe = new Pipe(transformer);
480
+ const callbacks = this.getOption("writeBack.callbacks");
481
+
482
+ if (isArray(callbacks)) {
483
+ for (const callback of callbacks) {
484
+ if (typeof callback === "function") {
485
+ pipe.setCallback(callback);
486
+ }
487
+ }
488
+ }
489
+
490
+ if (isObject(callbacks)) {
491
+ for (const key in callbacks) {
492
+ if (
493
+ Object.prototype.hasOwnProperty.call(callbacks, key) &&
494
+ typeof callbacks[key] === "function"
495
+ ) {
496
+ pipe.setCallback(key, callbacks[key]);
497
+ }
498
+ }
499
+ }
500
+
501
+ const result = pipe.run(data);
502
+ if (typeof result === "undefined") {
503
+ return clone(data);
504
+ }
505
+
506
+ return clone(result);
507
+ }
508
+
450
509
  registerCustomElement(DataSet);