@schukai/monster 4.66.2 → 4.68.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,28 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.68.0] - 2026-01-01
6
+
7
+ ### Add Features
8
+
9
+ - Add a file manager component for managing and editing files [#355](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/355)
10
+ ### Changes
11
+
12
+ - update project
13
+
14
+
15
+
16
+ ## [4.67.0] - 2025-12-31
17
+
18
+ ### Add Features
19
+
20
+ - Add new filter controls for date, datetime, and time [#354](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/354)
21
+ ### Changes
22
+
23
+ - close issue [#354](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/354)
24
+
25
+
26
+
5
27
  ## [4.66.2] - 2025-12-31
6
28
 
7
29
  ### 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.66.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.68.0"}
@@ -0,0 +1,447 @@
1
+ /**
2
+ * Copyright © Volker Schukai and all contributing authors, {{copyRightYear}}. All rights reserved.
3
+ * Node module: @schukai/monster
4
+ *
5
+ * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
6
+ * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
7
+ *
8
+ * For those who do not wish to adhere to the AGPLv3, a commercial license is available.
9
+ * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
10
+ * For more information about purchasing a commercial license, please contact Volker Schukai.
11
+ *
12
+ * SPDX-License-Identifier: AGPL-3.0
13
+ */
14
+
15
+ import { instanceSymbol } from "../../../constants.mjs";
16
+ import {
17
+ assembleMethodSymbol,
18
+ registerCustomElement,
19
+ } from "../../../dom/customelement.mjs";
20
+ import { CustomControl } from "../../../dom/customcontrol.mjs";
21
+ import { FilterControlsDefaultsStyleSheet } from "../stylesheet/filter-controls-defaults.mjs";
22
+ import { FilterStyleSheet } from "../stylesheet/filter.mjs";
23
+ import { getLocaleOfDocument } from "../../../dom/locale.mjs";
24
+
25
+ export { DatePresets };
26
+
27
+ /**
28
+ * local symbol
29
+ * @private
30
+ * @type {symbol}
31
+ */
32
+ const selectElementSymbol = Symbol("selectElement");
33
+
34
+ /**
35
+ * The FilterDatePresets component provides pre-defined date ranges.
36
+ *
37
+ * @fragments /fragments/components/datatable/filter/date-presets
38
+ *
39
+ * @example /examples/components/datatable/filter-controls Filter controls
40
+ *
41
+ * @copyright Volker Schukai
42
+ * @summary The FilterDatePresets component provides quick date presets.
43
+ */
44
+ class DatePresets extends CustomControl {
45
+ /**
46
+ * This method is called by the `instanceof` operator.
47
+ * @return {symbol}
48
+ */
49
+ static get [instanceSymbol]() {
50
+ return Symbol.for(
51
+ "@schukai/monster/components/filter/date-presets@@instance",
52
+ );
53
+ }
54
+
55
+ /**
56
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
57
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
58
+ *
59
+ * The individual configuration values can be found in the table.
60
+ *
61
+ * @property {Object} templates Template definitions
62
+ * @property {string} templates.main Main template
63
+ * @property {Object} labels Text labels
64
+ */
65
+ get defaults() {
66
+ return Object.assign({}, super.defaults, {
67
+ templates: {
68
+ main: getTemplate(),
69
+ },
70
+ labels: getTranslations(),
71
+ });
72
+ }
73
+
74
+ /**
75
+ *
76
+ * @return {string}
77
+ */
78
+ static getTag() {
79
+ return "monster-filter-date-presets";
80
+ }
81
+
82
+ /**
83
+ *
84
+ * @return {FilterButton}
85
+ */
86
+ [assembleMethodSymbol]() {
87
+ super[assembleMethodSymbol]();
88
+
89
+ initControlReferences.call(this);
90
+ updateOptions.call(this);
91
+ }
92
+
93
+ /**
94
+ * @return Array<CSSStyleSheet>
95
+ */
96
+ static getCSSStyleSheet() {
97
+ return [FilterControlsDefaultsStyleSheet, FilterStyleSheet];
98
+ }
99
+
100
+ /**
101
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
102
+ *
103
+ * @param {*} value
104
+ */
105
+ set value(value) {
106
+ this[selectElementSymbol].value = value;
107
+ }
108
+
109
+ /**
110
+ * @return {*}
111
+ */
112
+ get value() {
113
+ return this[selectElementSymbol].value;
114
+ }
115
+ }
116
+
117
+ /**
118
+ * @private
119
+ * @returns {Object}
120
+ */
121
+ function getTranslations() {
122
+ const locale = getLocaleOfDocument();
123
+ switch (locale.language) {
124
+ case "de":
125
+ return {
126
+ any: "Beliebig",
127
+ today: "Heute",
128
+ yesterday: "Gestern",
129
+ last7: "Letzte 7 Tage",
130
+ last30: "Letzte 30 Tage",
131
+ thisMonth: "Dieser Monat",
132
+ lastMonth: "Letzter Monat",
133
+ };
134
+ case "es":
135
+ return {
136
+ any: "Cualquiera",
137
+ today: "Hoy",
138
+ yesterday: "Ayer",
139
+ last7: "Últimos 7 días",
140
+ last30: "Últimos 30 días",
141
+ thisMonth: "Este mes",
142
+ lastMonth: "Mes pasado",
143
+ };
144
+ case "zh":
145
+ return {
146
+ any: "不限",
147
+ today: "今天",
148
+ yesterday: "昨天",
149
+ last7: "最近7天",
150
+ last30: "最近30天",
151
+ thisMonth: "本月",
152
+ lastMonth: "上个月",
153
+ };
154
+ case "hi":
155
+ return {
156
+ any: "कोई भी",
157
+ today: "आज",
158
+ yesterday: "कल",
159
+ last7: "पिछले 7 दिन",
160
+ last30: "पिछले 30 दिन",
161
+ thisMonth: "इस माह",
162
+ lastMonth: "पिछला माह",
163
+ };
164
+ case "bn":
165
+ return {
166
+ any: "যেকোনো",
167
+ today: "আজ",
168
+ yesterday: "গতকাল",
169
+ last7: "শেষ ৭ দিন",
170
+ last30: "শেষ ৩০ দিন",
171
+ thisMonth: "এই মাস",
172
+ lastMonth: "গত মাস",
173
+ };
174
+ case "pt":
175
+ return {
176
+ any: "Qualquer",
177
+ today: "Hoje",
178
+ yesterday: "Ontem",
179
+ last7: "Últimos 7 dias",
180
+ last30: "Últimos 30 dias",
181
+ thisMonth: "Este mês",
182
+ lastMonth: "Mês passado",
183
+ };
184
+ case "ru":
185
+ return {
186
+ any: "Любой",
187
+ today: "Сегодня",
188
+ yesterday: "Вчера",
189
+ last7: "Последние 7 дней",
190
+ last30: "Последние 30 дней",
191
+ thisMonth: "Этот месяц",
192
+ lastMonth: "Прошлый месяц",
193
+ };
194
+ case "ja":
195
+ return {
196
+ any: "指定なし",
197
+ today: "今日",
198
+ yesterday: "昨日",
199
+ last7: "過去7日",
200
+ last30: "過去30日",
201
+ thisMonth: "今月",
202
+ lastMonth: "先月",
203
+ };
204
+ case "pa":
205
+ return {
206
+ any: "ਕੋਈ ਵੀ",
207
+ today: "ਅੱਜ",
208
+ yesterday: "ਕੱਲ੍ਹ",
209
+ last7: "ਪਿਛਲੇ 7 ਦਿਨ",
210
+ last30: "ਪਿਛਲੇ 30 ਦਿਨ",
211
+ thisMonth: "ਇਸ ਮਹੀਨੇ",
212
+ lastMonth: "ਪਿਛਲਾ ਮਹੀਨਾ",
213
+ };
214
+ case "mr":
215
+ return {
216
+ any: "कोणतेही",
217
+ today: "आज",
218
+ yesterday: "काल",
219
+ last7: "मागील 7 दिवस",
220
+ last30: "मागील 30 दिवस",
221
+ thisMonth: "हा महिना",
222
+ lastMonth: "मागील महिना",
223
+ };
224
+ case "fr":
225
+ return {
226
+ any: "Tout",
227
+ today: "Aujourd'hui",
228
+ yesterday: "Hier",
229
+ last7: "7 derniers jours",
230
+ last30: "30 derniers jours",
231
+ thisMonth: "Ce mois",
232
+ lastMonth: "Mois dernier",
233
+ };
234
+ case "it":
235
+ return {
236
+ any: "Qualsiasi",
237
+ today: "Oggi",
238
+ yesterday: "Ieri",
239
+ last7: "Ultimi 7 giorni",
240
+ last30: "Ultimi 30 giorni",
241
+ thisMonth: "Questo mese",
242
+ lastMonth: "Mese scorso",
243
+ };
244
+ case "nl":
245
+ return {
246
+ any: "Elke",
247
+ today: "Vandaag",
248
+ yesterday: "Gisteren",
249
+ last7: "Laatste 7 dagen",
250
+ last30: "Laatste 30 dagen",
251
+ thisMonth: "Deze maand",
252
+ lastMonth: "Vorige maand",
253
+ };
254
+ case "sv":
255
+ return {
256
+ any: "Alla",
257
+ today: "Idag",
258
+ yesterday: "Igår",
259
+ last7: "Senaste 7 dagar",
260
+ last30: "Senaste 30 dagar",
261
+ thisMonth: "Denna månad",
262
+ lastMonth: "Förra månaden",
263
+ };
264
+ case "pl":
265
+ return {
266
+ any: "Dowolny",
267
+ today: "Dzisiaj",
268
+ yesterday: "Wczoraj",
269
+ last7: "Ostatnie 7 dni",
270
+ last30: "Ostatnie 30 dni",
271
+ thisMonth: "Ten miesiąc",
272
+ lastMonth: "Poprzedni miesiąc",
273
+ };
274
+ case "da":
275
+ return {
276
+ any: "Alle",
277
+ today: "I dag",
278
+ yesterday: "I går",
279
+ last7: "Seneste 7 dage",
280
+ last30: "Seneste 30 dage",
281
+ thisMonth: "Denne måned",
282
+ lastMonth: "Sidste måned",
283
+ };
284
+ case "fi":
285
+ return {
286
+ any: "Kaikki",
287
+ today: "Tänään",
288
+ yesterday: "Eilen",
289
+ last7: "Viimeiset 7 päivää",
290
+ last30: "Viimeiset 30 päivää",
291
+ thisMonth: "Tämä kuukausi",
292
+ lastMonth: "Edellinen kuukausi",
293
+ };
294
+ case "no":
295
+ return {
296
+ any: "Alle",
297
+ today: "I dag",
298
+ yesterday: "I går",
299
+ last7: "Siste 7 dager",
300
+ last30: "Siste 30 dager",
301
+ thisMonth: "Denne måneden",
302
+ lastMonth: "Forrige måned",
303
+ };
304
+ case "cs":
305
+ return {
306
+ any: "Libovolný",
307
+ today: "Dnes",
308
+ yesterday: "Včera",
309
+ last7: "Posledních 7 dní",
310
+ last30: "Posledních 30 dní",
311
+ thisMonth: "Tento měsíc",
312
+ lastMonth: "Minulý měsíc",
313
+ };
314
+ default:
315
+ case "en":
316
+ return {
317
+ any: "Any",
318
+ today: "Today",
319
+ yesterday: "Yesterday",
320
+ last7: "Last 7 days",
321
+ last30: "Last 30 days",
322
+ thisMonth: "This month",
323
+ lastMonth: "Last month",
324
+ };
325
+ }
326
+ }
327
+
328
+ /**
329
+ * @private
330
+ * @return {DatePresets}
331
+ */
332
+ function initControlReferences() {
333
+ if (!this.shadowRoot) {
334
+ throw new Error("no shadow-root is defined");
335
+ }
336
+
337
+ this[selectElementSymbol] = this.shadowRoot.querySelector(
338
+ "[data-monster-role=query]",
339
+ );
340
+ return this;
341
+ }
342
+
343
+ /**
344
+ * @private
345
+ * @return {void}
346
+ */
347
+ function updateOptions() {
348
+ const labels = this.getOption("labels");
349
+ const currentValue = this[selectElementSymbol].value;
350
+ const presets = buildPresets(labels);
351
+
352
+ this[selectElementSymbol].innerHTML = "";
353
+
354
+ for (const preset of presets) {
355
+ const option = document.createElement("option");
356
+ option.value = preset.value;
357
+ option.textContent = preset.label;
358
+ this[selectElementSymbol].append(option);
359
+ }
360
+
361
+ if (currentValue) {
362
+ this[selectElementSymbol].value = currentValue;
363
+ }
364
+ }
365
+
366
+ /**
367
+ * @private
368
+ * @param {Object} labels
369
+ * @return {Array<{label: string, value: string}>}
370
+ */
371
+ function buildPresets(labels) {
372
+ const today = new Date();
373
+ const todayString = formatDate(today);
374
+ const yesterday = formatDate(addDays(today, -1));
375
+ const last7 = buildRange(addDays(today, -6), today);
376
+ const last30 = buildRange(addDays(today, -29), today);
377
+ const thisMonthStart = new Date(today.getFullYear(), today.getMonth(), 1);
378
+ const thisMonthEnd = new Date(today.getFullYear(), today.getMonth() + 1, 0);
379
+ const lastMonthStart = new Date(today.getFullYear(), today.getMonth() - 1, 1);
380
+ const lastMonthEnd = new Date(today.getFullYear(), today.getMonth(), 0);
381
+
382
+ return [
383
+ { label: labels.any, value: "" },
384
+ { label: labels.today, value: todayString },
385
+ { label: labels.yesterday, value: yesterday },
386
+ { label: labels.last7, value: last7 },
387
+ { label: labels.last30, value: last30 },
388
+ {
389
+ label: labels.thisMonth,
390
+ value: buildRange(thisMonthStart, thisMonthEnd),
391
+ },
392
+ {
393
+ label: labels.lastMonth,
394
+ value: buildRange(lastMonthStart, lastMonthEnd),
395
+ },
396
+ ];
397
+ }
398
+
399
+ /**
400
+ * @private
401
+ * @param {Date} date
402
+ * @return {string}
403
+ */
404
+ function formatDate(date) {
405
+ const year = date.getFullYear();
406
+ const month = String(date.getMonth() + 1).padStart(2, "0");
407
+ const day = String(date.getDate()).padStart(2, "0");
408
+ return `${year}-${month}-${day}`;
409
+ }
410
+
411
+ /**
412
+ * @private
413
+ * @param {Date} from
414
+ * @param {Date} to
415
+ * @return {string}
416
+ */
417
+ function buildRange(from, to) {
418
+ return `${formatDate(from)} - ${formatDate(to)}`;
419
+ }
420
+
421
+ /**
422
+ * @private
423
+ * @param {Date} date
424
+ * @param {number} amount
425
+ * @return {Date}
426
+ */
427
+ function addDays(date, amount) {
428
+ const d = new Date(date);
429
+ d.setDate(d.getDate() + amount);
430
+ return d;
431
+ }
432
+
433
+ /**
434
+ * @private
435
+ * @return {string}
436
+ */
437
+ function getTemplate() {
438
+ // language=HTML
439
+ return `
440
+ <div data-monster-role="control" part="control">
441
+ <slot></slot>
442
+ <select name="query" data-monster-role="query" data-monster-attributes="value path:query"></select>
443
+ </div>
444
+ `;
445
+ }
446
+
447
+ registerCustomElement(DatePresets);
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Copyright © Volker Schukai and all contributing authors, {{copyRightYear}}. All rights reserved.
3
+ * Node module: @schukai/monster
4
+ *
5
+ * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
6
+ * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
7
+ *
8
+ * For those who do not wish to adhere to the AGPLv3, a commercial license is available.
9
+ * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
10
+ * For more information about purchasing a commercial license, please contact Volker Schukai.
11
+ *
12
+ * SPDX-License-Identifier: AGPL-3.0
13
+ */
14
+
15
+ import { instanceSymbol } from "../../../constants.mjs";
16
+ import {
17
+ assembleMethodSymbol,
18
+ registerCustomElement,
19
+ } from "../../../dom/customelement.mjs";
20
+ import { CustomControl } from "../../../dom/customcontrol.mjs";
21
+ import { FilterControlsDefaultsStyleSheet } from "../stylesheet/filter-controls-defaults.mjs";
22
+ import { FilterStyleSheet } from "../stylesheet/filter.mjs";
23
+
24
+ export { DateTimeFilter };
25
+
26
+ /**
27
+ * local symbol
28
+ * @private
29
+ * @type {symbol}
30
+ */
31
+ const inputElementSymbol = Symbol("inputElement");
32
+
33
+ /**
34
+ * The FilterDateTime component is used to filter by a date and time value.
35
+ *
36
+ * @fragments /fragments/components/datatable/filter/date-time
37
+ *
38
+ * @example /examples/components/datatable/filter-controls Filter controls
39
+ *
40
+ * @copyright Volker Schukai
41
+ * @summary The FilterDateTime component is used to show and handle datetime values.
42
+ */
43
+ class DateTimeFilter extends CustomControl {
44
+ /**
45
+ * This method is called by the `instanceof` operator.
46
+ * @return {symbol}
47
+ */
48
+ static get [instanceSymbol]() {
49
+ return Symbol.for("@schukai/monster/components/filter/date-time@@instance");
50
+ }
51
+
52
+ /**
53
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
54
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
55
+ *
56
+ * The individual configuration values can be found in the table.
57
+ *
58
+ * @property {Object} templates Template definitions
59
+ * @property {string} templates.main Main template
60
+ * @property {object} datasource The datasource
61
+ * @property {boolean} autoLoad If true, the datasource is called immediately after the control is created.
62
+ */
63
+ get defaults() {
64
+ return Object.assign({}, super.defaults, {
65
+ templates: {
66
+ main: getTemplate(),
67
+ },
68
+ });
69
+ }
70
+
71
+ /**
72
+ *
73
+ * @return {string}
74
+ */
75
+ static getTag() {
76
+ return "monster-filter-date-time";
77
+ }
78
+
79
+ /**
80
+ *
81
+ * @return {FilterButton}
82
+ */
83
+ [assembleMethodSymbol]() {
84
+ super[assembleMethodSymbol]();
85
+
86
+ initControlReferences.call(this);
87
+ initEventHandler.call(this);
88
+ }
89
+
90
+ /**
91
+ * @return Array<CSSStyleSheet>
92
+ */
93
+ static getCSSStyleSheet() {
94
+ return [FilterControlsDefaultsStyleSheet, FilterStyleSheet];
95
+ }
96
+
97
+ /**
98
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
99
+ *
100
+ * @param {*} value
101
+ */
102
+ set value(value) {
103
+ this[inputElementSymbol].value = value;
104
+ }
105
+
106
+ /**
107
+ * @return {*}
108
+ */
109
+ get value() {
110
+ return this[inputElementSymbol].value;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * @private
116
+ * @return {DateTimeFilter}
117
+ */
118
+ function initControlReferences() {
119
+ if (!this.shadowRoot) {
120
+ throw new Error("no shadow-root is defined");
121
+ }
122
+
123
+ this[inputElementSymbol] = this.shadowRoot.querySelector(
124
+ "[data-monster-role=query]",
125
+ );
126
+ return this;
127
+ }
128
+
129
+ /**
130
+ * @private
131
+ */
132
+ function initEventHandler() {}
133
+
134
+ /**
135
+ * @private
136
+ * @return {string}
137
+ */
138
+ function getTemplate() {
139
+ // language=HTML
140
+ return `
141
+ <div data-monster-role="control" part="control">
142
+ <slot></slot>
143
+ <input type="datetime-local" name="query" data-monster-role="query" data-monster-attributes="value path:query">
144
+ </div>
145
+ `;
146
+ }
147
+
148
+ registerCustomElement(DateTimeFilter);