@schukai/monster 4.74.2 → 4.75.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,23 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.75.0] - 2026-01-04
6
+
7
+ ### Add Features
8
+
9
+ - Add demo for tracking click events with enhanced datasource behavior
10
+
11
+
12
+
13
+ ## [4.74.3] - 2026-01-03
14
+
15
+ ### Bug Fixes
16
+
17
+ - filter quotes
18
+ - export filter
19
+
20
+
21
+
5
22
  ## [4.74.2] - 2026-01-03
6
23
 
7
24
  ### 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.74.2"}
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.75.0"}
@@ -13,6 +13,7 @@
13
13
  */
14
14
 
15
15
  import { instanceSymbol } from "../../constants.mjs";
16
+ import { diff } from "../../data/diff.mjs";
16
17
  import { Pathfinder } from "../../data/pathfinder.mjs";
17
18
  import {
18
19
  assembleMethodSymbol,
@@ -121,6 +122,8 @@ class DataSet extends CustomElement {
121
122
  * @type {boolean}
122
123
  */
123
124
  refreshOnMutation: true,
125
+ // Feature flag: default-on no-op write suppression, can be rolled back.
126
+ skipNoopWrite: true,
124
127
  },
125
128
 
126
129
  /**
@@ -201,6 +204,22 @@ class DataSet extends CustomElement {
201
204
  pathWithIndex = String(index);
202
205
  }
203
206
 
207
+ if (this.getOption("features.skipNoopWrite") === true) {
208
+ const currentData = this[datasourceLinkedElementSymbol]?.data;
209
+ let currentValue;
210
+ if (currentData) {
211
+ try {
212
+ currentValue = new Pathfinder(currentData).getVia(pathWithIndex);
213
+ } catch (e) {
214
+ currentValue = undefined;
215
+ }
216
+ }
217
+ if (diff(currentValue, internalData).length === 0) {
218
+ resolve();
219
+ return;
220
+ }
221
+ }
222
+
204
223
  if (this.getOption("logLevel") === "debug") {
205
224
  console.log("monster-dataset: write", {
206
225
  path: pathWithIndex,
@@ -16,6 +16,7 @@ import {
16
16
  CustomElement,
17
17
  assembleMethodSymbol,
18
18
  } from "../../dom/customelement.mjs";
19
+ import { diff } from "../../data/diff.mjs";
19
20
  import { Datasource as DatasourceBase } from "../../data/datasource.mjs";
20
21
  import { instanceSymbol } from "../../constants.mjs";
21
22
 
@@ -70,6 +71,10 @@ class Datasource extends CustomElement {
70
71
  get defaults() {
71
72
  return Object.assign({}, super.defaults, {
72
73
  logLevel: "error",
74
+ features: {
75
+ // Feature flag: default-on no-op event suppression, can be rolled back.
76
+ skipNoopEvents: true,
77
+ },
73
78
  });
74
79
  }
75
80
 
@@ -98,6 +103,12 @@ class Datasource extends CustomElement {
98
103
  data: data,
99
104
  });
100
105
  }
106
+ if (this.getOption("features.skipNoopEvents") === true) {
107
+ const current = this[dataSourceSymbol].get();
108
+ if (diff(current, data).length === 0) {
109
+ return;
110
+ }
111
+ }
101
112
  this[dataSourceSymbol].set(data);
102
113
  }
103
114
 
@@ -17,6 +17,8 @@ import { getSummaryTemplate, Select } from "../../form/select.mjs";
17
17
  import { FilterControlsDefaultsStyleSheet } from "../stylesheet/filter-controls-defaults.mjs";
18
18
  import { FilterSelectStyleSheet } from "../stylesheet/filter-select.mjs";
19
19
 
20
+ export { FilterSelect, getSummaryTemplate };
21
+
20
22
  /**
21
23
  * This is a filter select for the datatable filter.
22
24
  *
@@ -36,37 +38,37 @@ import { FilterSelectStyleSheet } from "../stylesheet/filter-select.mjs";
36
38
 
37
39
  */
38
40
  class FilterSelect extends Select {
39
- /**
40
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
41
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
42
- *
43
- * The individual configuration values can be found in the table.
44
- */
45
- get defaults() {
46
- return Object.assign({}, super.defaults, {
47
- type: "checkbox",
48
- });
49
- }
41
+ /**
42
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
43
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
44
+ *
45
+ * The individual configuration values can be found in the table.
46
+ */
47
+ get defaults() {
48
+ return Object.assign({}, super.defaults, {
49
+ type: "checkbox",
50
+ });
51
+ }
50
52
 
51
- /**
52
- *
53
- * @return {string}
54
- */
55
- static getTag() {
56
- return "monster-filter-select";
57
- }
53
+ /**
54
+ *
55
+ * @return {string}
56
+ */
57
+ static getTag() {
58
+ return "monster-filter-select";
59
+ }
58
60
 
59
- /**
60
- * @return {CSSStyleSheet[]}
61
- */
62
- static getCSSStyleSheet() {
63
- const styleSheet = super.getCSSStyleSheet();
64
- return [
65
- ...styleSheet,
66
- FilterControlsDefaultsStyleSheet,
67
- FilterSelectStyleSheet,
68
- ];
69
- }
61
+ /**
62
+ * @return {CSSStyleSheet[]}
63
+ */
64
+ static getCSSStyleSheet() {
65
+ const styleSheet = super.getCSSStyleSheet();
66
+ return [
67
+ ...styleSheet,
68
+ FilterControlsDefaultsStyleSheet,
69
+ FilterSelectStyleSheet,
70
+ ];
71
+ }
70
72
  }
71
73
 
72
74
  registerCustomElement(FilterSelect);
@@ -719,7 +719,7 @@ function initFilter() {
719
719
  const v = valuesFromHash[element.id];
720
720
  const searchInput = element.firstElementChild;
721
721
  try {
722
- searchInput.value = v;
722
+ searchInput.value = normalizeFilterValue(v);
723
723
  } catch (error) {}
724
724
  }
725
725
 
@@ -738,6 +738,30 @@ function initFilter() {
738
738
  updateFilterSelections.call(this);
739
739
  }
740
740
 
741
+ /**
742
+ * @private
743
+ * @param {*} value
744
+ * @return {*}
745
+ */
746
+ function normalizeFilterValue(value) {
747
+ if (!isString(value)) {
748
+ return value;
749
+ }
750
+
751
+ const trimmed = value.trim();
752
+ if (trimmed.length < 2) {
753
+ return value;
754
+ }
755
+
756
+ const first = trimmed[0];
757
+ const last = trimmed[trimmed.length - 1];
758
+ if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
759
+ return trimmed.slice(1, -1);
760
+ }
761
+
762
+ return value;
763
+ }
764
+
741
765
  /**
742
766
  * @private
743
767
  * @param {string} input
@@ -19,6 +19,7 @@ import { parseDataURL } from "../types/dataurl.mjs";
19
19
  import { isString } from "../types/is.mjs";
20
20
  import { ProxyObserver } from "../types/proxyobserver.mjs";
21
21
  import { validateObject } from "../types/validate.mjs";
22
+ import { diff } from "./diff.mjs";
22
23
  import { extend } from "./extend.mjs";
23
24
  import { Pathfinder } from "./pathfinder.mjs";
24
25
 
@@ -109,7 +110,12 @@ class Datasource extends Base {
109
110
  * ```
110
111
  */
111
112
  get defaults() {
112
- return {};
113
+ return {
114
+ features: {
115
+ // Feature flag: default-on no-op event suppression, can be rolled back.
116
+ skipNoopEvents: true,
117
+ },
118
+ };
113
119
  }
114
120
 
115
121
  /**
@@ -195,6 +201,12 @@ class Datasource extends Base {
195
201
  * @return {Datasource}
196
202
  */
197
203
  set(data) {
204
+ if (this.getOption("features.skipNoopEvents") === true) {
205
+ const current = this[internalDataSymbol].getRealSubject();
206
+ if (diff(current, data).length === 0) {
207
+ return this;
208
+ }
209
+ }
198
210
  this[internalDataSymbol].setSubject(data);
199
211
  return this;
200
212
  }