@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 +22 -0
- package/package.json +1 -1
- package/source/components/datatable/filter/date-presets.mjs +447 -0
- package/source/components/datatable/filter/date-time.mjs +148 -0
- package/source/components/datatable/filter/date.mjs +148 -0
- package/source/components/datatable/filter/text-operator.mjs +389 -0
- package/source/components/datatable/filter/time.mjs +148 -0
- package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +1 -1
- package/source/components/files/file-manager.mjs +2397 -0
- package/source/components/files/stylesheet/file-manager.mjs +55 -0
- package/source/components/layout/panel.mjs +8 -0
- package/source/components/layout/split-panel.mjs +8 -0
- package/source/components/layout/tabs.mjs +48 -19
- package/source/monster.mjs +11 -1
- 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 +56 -22
|
@@ -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 { DateFilter };
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* local symbol
|
|
28
|
+
* @private
|
|
29
|
+
* @type {symbol}
|
|
30
|
+
*/
|
|
31
|
+
const inputElementSymbol = Symbol("inputElement");
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The FilterDate component is used to filter by a single date.
|
|
35
|
+
*
|
|
36
|
+
* @fragments /fragments/components/datatable/filter/date
|
|
37
|
+
*
|
|
38
|
+
* @example /examples/components/datatable/filter-controls Filter controls
|
|
39
|
+
*
|
|
40
|
+
* @copyright Volker Schukai
|
|
41
|
+
* @summary The FilterDate component is used to show and handle date values.
|
|
42
|
+
*/
|
|
43
|
+
class DateFilter 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@@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";
|
|
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 {DateFilter}
|
|
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="date" name="query" data-monster-role="query" data-monster-attributes="value path:query">
|
|
144
|
+
</div>
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
registerCustomElement(DateFilter);
|
|
@@ -0,0 +1,389 @@
|
|
|
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
|
+
import "../../form/input-group.mjs";
|
|
25
|
+
|
|
26
|
+
export { TextOperator };
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* local symbol
|
|
30
|
+
* @private
|
|
31
|
+
* @type {symbol}
|
|
32
|
+
*/
|
|
33
|
+
const operatorElementSymbol = Symbol("operatorElement");
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* local symbol
|
|
37
|
+
* @private
|
|
38
|
+
* @type {symbol}
|
|
39
|
+
*/
|
|
40
|
+
const inputElementSymbol = Symbol("inputElement");
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The FilterTextOperator component combines operator and input fields for text filters.
|
|
44
|
+
*
|
|
45
|
+
* @fragments /fragments/components/datatable/filter/text-operator
|
|
46
|
+
*
|
|
47
|
+
* @example /examples/components/datatable/filter-controls Filter controls
|
|
48
|
+
*
|
|
49
|
+
* @copyright Volker Schukai
|
|
50
|
+
* @summary The FilterTextOperator component combines operator and query input.
|
|
51
|
+
*/
|
|
52
|
+
class TextOperator extends CustomControl {
|
|
53
|
+
/**
|
|
54
|
+
* This method is called by the `instanceof` operator.
|
|
55
|
+
* @return {symbol}
|
|
56
|
+
*/
|
|
57
|
+
static get [instanceSymbol]() {
|
|
58
|
+
return Symbol.for(
|
|
59
|
+
"@schukai/monster/components/filter/text-operator@@instance",
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* To set the options via the HTML tag, the attribute `data-monster-options` must be used.
|
|
65
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
|
66
|
+
*
|
|
67
|
+
* The individual configuration values can be found in the table.
|
|
68
|
+
*
|
|
69
|
+
* @property {Object} templates Template definitions
|
|
70
|
+
* @property {string} templates.main Main template
|
|
71
|
+
* @property {Object} labels Text labels
|
|
72
|
+
*/
|
|
73
|
+
get defaults() {
|
|
74
|
+
return Object.assign({}, super.defaults, {
|
|
75
|
+
templates: {
|
|
76
|
+
main: getTemplate(),
|
|
77
|
+
},
|
|
78
|
+
labels: getTranslations(),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
* @return {string}
|
|
85
|
+
*/
|
|
86
|
+
static getTag() {
|
|
87
|
+
return "monster-filter-text-operator";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
* @return {FilterButton}
|
|
93
|
+
*/
|
|
94
|
+
[assembleMethodSymbol]() {
|
|
95
|
+
super[assembleMethodSymbol]();
|
|
96
|
+
|
|
97
|
+
initControlReferences.call(this);
|
|
98
|
+
updateOptions.call(this);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @return Array<CSSStyleSheet>
|
|
103
|
+
*/
|
|
104
|
+
static getCSSStyleSheet() {
|
|
105
|
+
return [FilterControlsDefaultsStyleSheet, FilterStyleSheet];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
|
|
110
|
+
*
|
|
111
|
+
* @param {*} value
|
|
112
|
+
*/
|
|
113
|
+
set value(value) {
|
|
114
|
+
const parsed = parseValue(value);
|
|
115
|
+
this[operatorElementSymbol].value = parsed.operator;
|
|
116
|
+
this[inputElementSymbol].value = parsed.query;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @return {*}
|
|
121
|
+
*/
|
|
122
|
+
get value() {
|
|
123
|
+
const query = `${this[inputElementSymbol].value || ""}`.trim();
|
|
124
|
+
if (!query) {
|
|
125
|
+
return "";
|
|
126
|
+
}
|
|
127
|
+
return `${this[operatorElementSymbol].value}${query}`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @private
|
|
133
|
+
* @returns {Object}
|
|
134
|
+
*/
|
|
135
|
+
function getTranslations() {
|
|
136
|
+
const locale = getLocaleOfDocument();
|
|
137
|
+
switch (locale.language) {
|
|
138
|
+
case "de":
|
|
139
|
+
return {
|
|
140
|
+
contains: "Enthält",
|
|
141
|
+
equals: "Gleich",
|
|
142
|
+
notEqual: "Ungleich",
|
|
143
|
+
startsWith: "Beginnt mit",
|
|
144
|
+
endsWith: "Endet mit",
|
|
145
|
+
};
|
|
146
|
+
case "es":
|
|
147
|
+
return {
|
|
148
|
+
contains: "Contiene",
|
|
149
|
+
equals: "Igual",
|
|
150
|
+
notEqual: "Distinto",
|
|
151
|
+
startsWith: "Empieza con",
|
|
152
|
+
endsWith: "Termina con",
|
|
153
|
+
};
|
|
154
|
+
case "zh":
|
|
155
|
+
return {
|
|
156
|
+
contains: "包含",
|
|
157
|
+
equals: "等于",
|
|
158
|
+
notEqual: "不等于",
|
|
159
|
+
startsWith: "开头为",
|
|
160
|
+
endsWith: "结尾为",
|
|
161
|
+
};
|
|
162
|
+
case "hi":
|
|
163
|
+
return {
|
|
164
|
+
contains: "शामिल है",
|
|
165
|
+
equals: "समान",
|
|
166
|
+
notEqual: "समान नहीं",
|
|
167
|
+
startsWith: "से शुरू",
|
|
168
|
+
endsWith: "पर समाप्त",
|
|
169
|
+
};
|
|
170
|
+
case "bn":
|
|
171
|
+
return {
|
|
172
|
+
contains: "অন্তর্ভুক্ত",
|
|
173
|
+
equals: "সমান",
|
|
174
|
+
notEqual: "সমান নয়",
|
|
175
|
+
startsWith: "দিয়ে শুরু",
|
|
176
|
+
endsWith: "দিয়ে শেষ",
|
|
177
|
+
};
|
|
178
|
+
case "pt":
|
|
179
|
+
return {
|
|
180
|
+
contains: "Contém",
|
|
181
|
+
equals: "Igual",
|
|
182
|
+
notEqual: "Diferente",
|
|
183
|
+
startsWith: "Começa com",
|
|
184
|
+
endsWith: "Termina com",
|
|
185
|
+
};
|
|
186
|
+
case "ru":
|
|
187
|
+
return {
|
|
188
|
+
contains: "Содержит",
|
|
189
|
+
equals: "Равно",
|
|
190
|
+
notEqual: "Не равно",
|
|
191
|
+
startsWith: "Начинается с",
|
|
192
|
+
endsWith: "Заканчивается на",
|
|
193
|
+
};
|
|
194
|
+
case "ja":
|
|
195
|
+
return {
|
|
196
|
+
contains: "含む",
|
|
197
|
+
equals: "等しい",
|
|
198
|
+
notEqual: "等しくない",
|
|
199
|
+
startsWith: "で始まる",
|
|
200
|
+
endsWith: "で終わる",
|
|
201
|
+
};
|
|
202
|
+
case "pa":
|
|
203
|
+
return {
|
|
204
|
+
contains: "ਸ਼ਾਮਲ ਹੈ",
|
|
205
|
+
equals: "ਬਰਾਬਰ",
|
|
206
|
+
notEqual: "ਬਰਾਬਰ ਨਹੀਂ",
|
|
207
|
+
startsWith: "ਨਾਲ ਸ਼ੁਰੂ",
|
|
208
|
+
endsWith: "ਨਾਲ ਖਤਮ",
|
|
209
|
+
};
|
|
210
|
+
case "mr":
|
|
211
|
+
return {
|
|
212
|
+
contains: "समाविष्ट",
|
|
213
|
+
equals: "समान",
|
|
214
|
+
notEqual: "समान नाही",
|
|
215
|
+
startsWith: "ने सुरू",
|
|
216
|
+
endsWith: "ने समाप्त",
|
|
217
|
+
};
|
|
218
|
+
case "fr":
|
|
219
|
+
return {
|
|
220
|
+
contains: "Contient",
|
|
221
|
+
equals: "Égal",
|
|
222
|
+
notEqual: "Différent",
|
|
223
|
+
startsWith: "Commence par",
|
|
224
|
+
endsWith: "Se termine par",
|
|
225
|
+
};
|
|
226
|
+
case "it":
|
|
227
|
+
return {
|
|
228
|
+
contains: "Contiene",
|
|
229
|
+
equals: "Uguale",
|
|
230
|
+
notEqual: "Diverso",
|
|
231
|
+
startsWith: "Inizia con",
|
|
232
|
+
endsWith: "Finisce con",
|
|
233
|
+
};
|
|
234
|
+
case "nl":
|
|
235
|
+
return {
|
|
236
|
+
contains: "Bevat",
|
|
237
|
+
equals: "Gelijk",
|
|
238
|
+
notEqual: "Niet gelijk",
|
|
239
|
+
startsWith: "Begint met",
|
|
240
|
+
endsWith: "Eindigt met",
|
|
241
|
+
};
|
|
242
|
+
case "sv":
|
|
243
|
+
return {
|
|
244
|
+
contains: "Innehåller",
|
|
245
|
+
equals: "Lika med",
|
|
246
|
+
notEqual: "Inte lika",
|
|
247
|
+
startsWith: "Börjar med",
|
|
248
|
+
endsWith: "Slutar med",
|
|
249
|
+
};
|
|
250
|
+
case "pl":
|
|
251
|
+
return {
|
|
252
|
+
contains: "Zawiera",
|
|
253
|
+
equals: "Równe",
|
|
254
|
+
notEqual: "Nie równe",
|
|
255
|
+
startsWith: "Zaczyna się od",
|
|
256
|
+
endsWith: "Kończy się na",
|
|
257
|
+
};
|
|
258
|
+
case "da":
|
|
259
|
+
return {
|
|
260
|
+
contains: "Indeholder",
|
|
261
|
+
equals: "Lig med",
|
|
262
|
+
notEqual: "Ikke lig med",
|
|
263
|
+
startsWith: "Starter med",
|
|
264
|
+
endsWith: "Slutter med",
|
|
265
|
+
};
|
|
266
|
+
case "fi":
|
|
267
|
+
return {
|
|
268
|
+
contains: "Sisältää",
|
|
269
|
+
equals: "Yhtä kuin",
|
|
270
|
+
notEqual: "Ei yhtä kuin",
|
|
271
|
+
startsWith: "Alkaa",
|
|
272
|
+
endsWith: "Päättyy",
|
|
273
|
+
};
|
|
274
|
+
case "no":
|
|
275
|
+
return {
|
|
276
|
+
contains: "Inneholder",
|
|
277
|
+
equals: "Lik",
|
|
278
|
+
notEqual: "Ikke lik",
|
|
279
|
+
startsWith: "Starter med",
|
|
280
|
+
endsWith: "Slutter med",
|
|
281
|
+
};
|
|
282
|
+
case "cs":
|
|
283
|
+
return {
|
|
284
|
+
contains: "Obsahuje",
|
|
285
|
+
equals: "Rovno",
|
|
286
|
+
notEqual: "Nerovno",
|
|
287
|
+
startsWith: "Začíná na",
|
|
288
|
+
endsWith: "Končí na",
|
|
289
|
+
};
|
|
290
|
+
default:
|
|
291
|
+
case "en":
|
|
292
|
+
return {
|
|
293
|
+
contains: "Contains",
|
|
294
|
+
equals: "Equals",
|
|
295
|
+
notEqual: "Not equal",
|
|
296
|
+
startsWith: "Starts with",
|
|
297
|
+
endsWith: "Ends with",
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* @private
|
|
304
|
+
* @return {TextOperator}
|
|
305
|
+
*/
|
|
306
|
+
function initControlReferences() {
|
|
307
|
+
if (!this.shadowRoot) {
|
|
308
|
+
throw new Error("no shadow-root is defined");
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
this[operatorElementSymbol] = this.shadowRoot.querySelector(
|
|
312
|
+
"[data-monster-role=operator]",
|
|
313
|
+
);
|
|
314
|
+
this[inputElementSymbol] = this.shadowRoot.querySelector(
|
|
315
|
+
"[data-monster-role=query]",
|
|
316
|
+
);
|
|
317
|
+
return this;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* @private
|
|
322
|
+
* @return {void}
|
|
323
|
+
*/
|
|
324
|
+
function updateOptions() {
|
|
325
|
+
const labels = this.getOption("labels");
|
|
326
|
+
const currentValue = this[operatorElementSymbol].value;
|
|
327
|
+
|
|
328
|
+
const operators = [
|
|
329
|
+
{ value: ":", label: labels.contains },
|
|
330
|
+
{ value: "=", label: labels.equals },
|
|
331
|
+
{ value: "!=", label: labels.notEqual },
|
|
332
|
+
{ value: "^=", label: labels.startsWith },
|
|
333
|
+
{ value: "$=", label: labels.endsWith },
|
|
334
|
+
];
|
|
335
|
+
|
|
336
|
+
this[operatorElementSymbol].innerHTML = "";
|
|
337
|
+
for (const operator of operators) {
|
|
338
|
+
const option = document.createElement("option");
|
|
339
|
+
option.value = operator.value;
|
|
340
|
+
option.textContent = operator.label;
|
|
341
|
+
this[operatorElementSymbol].append(option);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (currentValue) {
|
|
345
|
+
this[operatorElementSymbol].value = currentValue;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* @private
|
|
351
|
+
* @param {string} value
|
|
352
|
+
* @return {{operator: string, query: string}}
|
|
353
|
+
*/
|
|
354
|
+
function parseValue(value) {
|
|
355
|
+
if (!value) {
|
|
356
|
+
return { operator: ":", query: "" };
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const operators = ["!=", "<>", "^=", "$=", "=", ":"];
|
|
360
|
+
for (const op of operators) {
|
|
361
|
+
if (value.startsWith(op)) {
|
|
362
|
+
return {
|
|
363
|
+
operator: op === "<>" ? "!=" : op,
|
|
364
|
+
query: value.slice(op.length),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return { operator: ":", query: value };
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* @private
|
|
374
|
+
* @return {string}
|
|
375
|
+
*/
|
|
376
|
+
function getTemplate() {
|
|
377
|
+
// language=HTML
|
|
378
|
+
return `
|
|
379
|
+
<div data-monster-role="control" part="control">
|
|
380
|
+
<slot></slot>
|
|
381
|
+
<monster-input-group>
|
|
382
|
+
<select slot="prefix" data-monster-role="operator" name="operator"></select>
|
|
383
|
+
<input type="search" data-monster-role="query" name="query" data-monster-attributes="value path:query">
|
|
384
|
+
</monster-input-group>
|
|
385
|
+
</div>
|
|
386
|
+
`;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
registerCustomElement(TextOperator);
|
|
@@ -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 { TimeFilter };
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* local symbol
|
|
28
|
+
* @private
|
|
29
|
+
* @type {symbol}
|
|
30
|
+
*/
|
|
31
|
+
const inputElementSymbol = Symbol("inputElement");
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The FilterTime component is used to filter by a time value.
|
|
35
|
+
*
|
|
36
|
+
* @fragments /fragments/components/datatable/filter/time
|
|
37
|
+
*
|
|
38
|
+
* @example /examples/components/datatable/filter-controls Filter controls
|
|
39
|
+
*
|
|
40
|
+
* @copyright Volker Schukai
|
|
41
|
+
* @summary The FilterTime component is used to show and handle time values.
|
|
42
|
+
*/
|
|
43
|
+
class TimeFilter 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/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-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 {TimeFilter}
|
|
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="time" name="query" data-monster-role="query" data-monster-attributes="value path:query">
|
|
144
|
+
</div>
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
registerCustomElement(TimeFilter);
|
|
@@ -25,7 +25,7 @@ try {
|
|
|
25
25
|
FilterControlsDefaultsStyleSheet.insertRule(
|
|
26
26
|
`
|
|
27
27
|
@layer filtercontrolsdefaults {
|
|
28
|
-
[data-monster-role=control]{box-sizing:border-box;outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:host{box-sizing:border-box;display:block}div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}input,meter,progress,select,textarea{accent-color:var(--monster-color-secondary-2);background-color:var(--monster-bg-color-primary-1);border-color:var(--monster-theme-control-border-color);border-radius:var(--monster-theme-control-border-radius);border-style:var(--monster-theme-control-border-style);border-width:var(--monster-theme-control-border-width);box-sizing:border-box;color:var(--monster-color-primary-1);font-family:inherit;font-size:100%;margin:0;outline:none}input,select,textarea{height:-moz-fit-content;height:fit-content;padding:.4rem .6rem}textarea{min-height:6rem;resize:vertical}input[type=color]{height:2rem;margin:0;padding:.1rem;width:2rem}input:hover:not([type=radio]):not([type=checkbox]):not([type=range]),select:hover,textarea:hover{box-shadow:var(--monster-box-shadow-2);transition:background .8s,color .25s .0833333333s}input:focus,select:focus,textarea:focus{outline:1px dashed var(--monster-color-selection-3);outline-offset:3px}:host{height:100%;width:100%}div[data-monster-role=control]{display:flex;height:100%;position:relative}div[data-monster-role=control] .form-container{margin:0 auto;max-width:600px}:is(div[data-monster-role=control] .form-container) .form-group{margin-bottom:.2rem}:is(:is(div[data-monster-role=control] .form-container) .form-group) input[type=number]{text-align:right;width:5rem}:is(:is(div[data-monster-role=control] .form-container) .form-group) input[type=number]::-webkit-inner-spin-button,:is(:is(div[data-monster-role=control] .form-container) .form-group) input[type=number]::-webkit-outer-spin-button{margin-left:10px}:is(:is(div[data-monster-role=control] .form-container) .form-group) input[type=radio]{accent-color:var(--monster-bg-color-primary-3)}[data-monster-role=popper]{position:absolute}
|
|
28
|
+
[data-monster-role=control]{box-sizing:border-box;outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:host{box-sizing:border-box;display:block}div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}input,meter,progress,select,textarea{accent-color:var(--monster-color-secondary-2);background-color:var(--monster-bg-color-primary-1);border-color:var(--monster-theme-control-border-color);border-radius:var(--monster-theme-control-border-radius);border-style:var(--monster-theme-control-border-style);border-width:var(--monster-theme-control-border-width);box-sizing:border-box;color:var(--monster-color-primary-1);font-family:inherit;font-size:100%;margin:0;outline:none}input,select,textarea{height:-moz-fit-content;height:fit-content;padding:.4rem .6rem}textarea{min-height:6rem;resize:vertical}input[type=color]{height:2rem;margin:0;padding:.1rem;width:2rem}input:hover:not([type=radio]):not([type=checkbox]):not([type=range]),select:hover,textarea:hover{box-shadow:var(--monster-box-shadow-2);transition:background .8s,color .25s .0833333333s}input:focus,select:focus,textarea:focus{outline:1px dashed var(--monster-color-selection-3);outline-offset:3px}:host{height:100%;width:100%}div[data-monster-role=control]{display:flex;height:100%;position:relative}div[data-monster-role=control] .form-container{margin:0 auto;max-width:600px}:is(div[data-monster-role=control] .form-container) .form-group{margin-bottom:.2rem}:is(:is(div[data-monster-role=control] .form-container) .form-group) input[type=number]{text-align:right;width:5rem}:is(:is(div[data-monster-role=control] .form-container) .form-group) input[type=number]::-webkit-inner-spin-button,:is(:is(div[data-monster-role=control] .form-container) .form-group) input[type=number]::-webkit-outer-spin-button{margin-left:10px}:is(:is(div[data-monster-role=control] .form-container) .form-group) input[type=radio]{accent-color:var(--monster-bg-color-primary-3)}[data-monster-role=popper]{position:absolute}@media (prefers-color-scheme:dark){input[type=date],input[type=time],input[type=datetime-local]{color-scheme:dark}input[type=date]::-webkit-calendar-picker-indicator,input[type=time]::-webkit-calendar-picker-indicator,input[type=datetime-local]::-webkit-calendar-picker-indicator{-webkit-filter:invert(1)!important;filter:invert(1)!important;opacity:.85}}
|
|
29
29
|
}`,
|
|
30
30
|
0,
|
|
31
31
|
);
|