@schukai/monster 4.43.1 → 4.43.3
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 +16 -0
- package/package.json +1 -1
- package/source/components/accessibility/locale-picker.mjs +538 -538
- package/source/components/accessibility/locale-select.mjs +172 -172
- package/source/components/content/viewer.mjs +823 -823
- package/source/components/datatable/constants.mjs +15 -15
- package/source/components/datatable/datatable/header.mjs +253 -253
- package/source/components/datatable/datatable.mjs +1284 -1284
- package/source/components/datatable/filter.mjs +1339 -1342
- package/source/components/datatable/pagination.mjs +502 -502
- package/source/components/datatable/stylesheet/datatable.mjs +13 -6
- package/source/components/form/quantity.mjs +229 -229
- package/source/components/form/select.mjs +2963 -2963
- package/source/components/form/stylesheet/quantity.mjs +13 -6
- package/source/components/form/stylesheet/select.mjs +13 -6
- package/source/components/navigation/site-navigation.mjs +383 -210
- package/source/components/navigation/style/site-navigation.pcss +103 -15
- package/source/components/navigation/stylesheet/site-navigation.mjs +14 -7
- package/source/components/style/typography.css +4 -2
- package/source/dom/customelement.mjs +959 -963
- package/source/dom/slotted.mjs +87 -87
- package/source/i18n/util.mjs +149 -149
- package/source/monster.mjs +3 -0
- package/source/types/is.mjs +64 -64
- package/source/types/typeof.mjs +16 -16
- 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 +2724 -1287
@@ -14,8 +14,8 @@ import { instanceSymbol } from "../../constants.mjs";
|
|
14
14
|
import { ATTRIBUTE_ROLE } from "../../dom/constants.mjs";
|
15
15
|
import { CustomControl } from "../../dom/customcontrol.mjs";
|
16
16
|
import {
|
17
|
-
|
18
|
-
|
17
|
+
assembleMethodSymbol,
|
18
|
+
registerCustomElement,
|
19
19
|
} from "../../dom/customelement.mjs";
|
20
20
|
import { fireCustomEvent } from "../../dom/events.mjs";
|
21
21
|
|
@@ -61,100 +61,100 @@ const holdIntervalSymbol = Symbol("holdInterval");
|
|
61
61
|
* @fires monster-quantity-change
|
62
62
|
*/
|
63
63
|
class Quantity extends CustomControl {
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
64
|
+
static get [instanceSymbol]() {
|
65
|
+
return Symbol.for("@schukai/monster/components/form/quantity@@instance");
|
66
|
+
}
|
67
|
+
|
68
|
+
[assembleMethodSymbol]() {
|
69
|
+
super[assembleMethodSymbol]();
|
70
|
+
|
71
|
+
initControlReferences.call(this);
|
72
|
+
initEventHandler.call(this);
|
73
|
+
applyEditableState.call(this);
|
74
|
+
clampAndRender.call(this, this.getOption("value"));
|
75
|
+
|
76
|
+
return this;
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Current numeric value
|
81
|
+
* @return {number|null}
|
82
|
+
*/
|
83
|
+
get value() {
|
84
|
+
return this.getOption("value");
|
85
|
+
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Sets the value programmatically (including clamping & FormValue)
|
89
|
+
* @param {number|string|null} v
|
90
|
+
*/
|
91
|
+
set value(v) {
|
92
|
+
const n = normalizeNumber(v, this.getOption("precision"));
|
93
|
+
clampAndRender.call(this, n);
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* Options
|
98
|
+
*
|
99
|
+
* @property {Object} templates
|
100
|
+
* @property {string} templates.main Main template
|
101
|
+
* @property {Object} templateMapping
|
102
|
+
* @property {string} templateMapping.plus Icon (SVG-Path) Plus
|
103
|
+
* @property {string} templateMapping.minus Icon (SVG-Path) Minus
|
104
|
+
* @property {Object} classes CSS classes
|
105
|
+
* @property {string} classes.button Button class (e.g. monster-button-outline-primary)
|
106
|
+
* @property {string} classes.input Additional class for input
|
107
|
+
* @property {Object} features Feature toggles
|
108
|
+
* @property {boolean} features.editable Allow manual input
|
109
|
+
* @property {boolean} features.hold Press-and-hold accelerates
|
110
|
+
* @property {boolean} features.enforceBounds Clamp value when manual input is out of bounds
|
111
|
+
* @property {number} value Current value
|
112
|
+
* @property {number} min Use Number.NEGATIVE_INFINITY and Number.POSITIVE_INFINITY for no bounds
|
113
|
+
* @property {number} max Use Number.NEGATIVE_INFINITY and Number.POSITIVE_INFINITY for no bounds
|
114
|
+
* @property {number} step Increment/decrement step
|
115
|
+
* @property {number} precision Round to N decimal places (null = no explicit rounding)
|
116
|
+
* @property {boolean} disabled Disable the input field (also disables manual input)
|
117
|
+
* @property {string} placeholder Placeholder text
|
118
|
+
* @property {string} inputmode For mobile keyboards
|
119
|
+
*/
|
120
|
+
get defaults() {
|
121
|
+
return Object.assign({}, super.defaults, {
|
122
|
+
templates: { main: getTemplate() },
|
123
|
+
templateMapping: {
|
124
|
+
plus: `
|
125
125
|
<path d="M8 1a1 1 0 0 1 1 1v5h5a1 1 0 1 1 0 2H9v5a1 1 0 1 1-2 0V9H2a1 1 0 1 1 0-2h5V2a1 1 0 0 1 1-1z"/>`,
|
126
|
-
|
126
|
+
minus: `
|
127
127
|
<path d="M2 7.5a1 1 0 0 0 0 1H14a1 1 0 1 0 0-2H2a1 1 0 0 0 0 1z"/>`,
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
128
|
+
},
|
129
|
+
classes: {
|
130
|
+
button: "monster-button-outline-primary",
|
131
|
+
input: "",
|
132
|
+
},
|
133
|
+
features: {
|
134
|
+
editable: true,
|
135
|
+
hold: true,
|
136
|
+
enforceBounds: true,
|
137
|
+
},
|
138
|
+
value: 0,
|
139
|
+
min: 0,
|
140
|
+
max: Number.POSITIVE_INFINITY,
|
141
|
+
step: 1,
|
142
|
+
precision: null,
|
143
|
+
|
144
|
+
disabled: false,
|
145
|
+
placeholder: "",
|
146
|
+
inputmode: "decimal",
|
147
|
+
});
|
148
|
+
}
|
149
|
+
|
150
|
+
static getTag() {
|
151
|
+
return "monster-quantity";
|
152
|
+
}
|
153
|
+
|
154
|
+
// If you want a stylesheet, return it here.
|
155
|
+
static getCSSStyleSheet() {
|
156
|
+
return [QuantityStyleSheet];
|
157
|
+
}
|
158
158
|
}
|
159
159
|
|
160
160
|
/**
|
@@ -164,18 +164,18 @@ class Quantity extends CustomControl {
|
|
164
164
|
* @return {void}
|
165
165
|
*/
|
166
166
|
function initControlReferences() {
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
167
|
+
this[controlElementSymbol] = this.shadowRoot.querySelector(
|
168
|
+
`[${ATTRIBUTE_ROLE}="control"]`,
|
169
|
+
);
|
170
|
+
this[decrementButtonSymbol] = this.shadowRoot.querySelector(
|
171
|
+
`[${ATTRIBUTE_ROLE}="decrement"]`,
|
172
|
+
);
|
173
|
+
this[incrementButtonSymbol] = this.shadowRoot.querySelector(
|
174
|
+
`[${ATTRIBUTE_ROLE}="increment"]`,
|
175
|
+
);
|
176
|
+
this[inputElementSymbol] = this.shadowRoot.querySelector(
|
177
|
+
`[${ATTRIBUTE_ROLE}="input"]`,
|
178
|
+
);
|
179
179
|
}
|
180
180
|
|
181
181
|
/**
|
@@ -185,150 +185,150 @@ function initControlReferences() {
|
|
185
185
|
* @return {void}
|
186
186
|
*/
|
187
187
|
function initEventHandler() {
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
188
|
+
const stepOnce = (dir) => {
|
189
|
+
const step = Number(this.getOption("step")) || 1;
|
190
|
+
const cur = toNumberOr(this.value, 0);
|
191
|
+
const next = cur + (dir > 0 ? step : -step);
|
192
|
+
clampAndRender.call(this, next, {
|
193
|
+
fire: true,
|
194
|
+
kind: dir > 0 ? "increment" : "decrement",
|
195
|
+
});
|
196
|
+
};
|
197
|
+
|
198
|
+
const startHold = (dir) => {
|
199
|
+
if (!this.getOption("features.hold")) return;
|
200
|
+
clearTimeout(this[holdTimerSymbol]);
|
201
|
+
clearInterval(this[holdIntervalSymbol]);
|
202
|
+
|
203
|
+
// After a short delay, repeat faster
|
204
|
+
this[holdTimerSymbol] = setTimeout(() => {
|
205
|
+
this[holdIntervalSymbol] = setInterval(() => stepOnce(dir), 60);
|
206
|
+
}, 300);
|
207
|
+
};
|
208
|
+
|
209
|
+
const stopHold = () => {
|
210
|
+
clearTimeout(this[holdTimerSymbol]);
|
211
|
+
clearInterval(this[holdIntervalSymbol]);
|
212
|
+
};
|
213
|
+
|
214
|
+
// Buttons
|
215
|
+
this[decrementButtonSymbol].addEventListener("click", (e) => stepOnce(-1));
|
216
|
+
this[incrementButtonSymbol].addEventListener("click", (e) => stepOnce(1));
|
217
|
+
|
218
|
+
// Press & hold (Mouse/Touch)
|
219
|
+
["mousedown", "pointerdown", "touchstart"].forEach((ev) => {
|
220
|
+
this[decrementButtonSymbol].addEventListener(ev, () => startHold(-1));
|
221
|
+
this[incrementButtonSymbol].addEventListener(ev, () => startHold(1));
|
222
|
+
});
|
223
|
+
["mouseup", "mouseleave", "pointerup", "touchend", "touchcancel"].forEach(
|
224
|
+
(ev) => {
|
225
|
+
this[decrementButtonSymbol].addEventListener(ev, stopHold);
|
226
|
+
this[incrementButtonSymbol].addEventListener(ev, stopHold);
|
227
|
+
},
|
228
|
+
);
|
229
|
+
|
230
|
+
// Keyboard on input
|
231
|
+
this[inputElementSymbol].addEventListener("keydown", (e) => {
|
232
|
+
if (e.key === "ArrowUp") {
|
233
|
+
e.preventDefault();
|
234
|
+
stepOnce(1);
|
235
|
+
} else if (e.key === "ArrowDown") {
|
236
|
+
e.preventDefault();
|
237
|
+
stepOnce(-1);
|
238
|
+
}
|
239
|
+
});
|
240
|
+
|
241
|
+
// Manual input
|
242
|
+
this[inputElementSymbol].addEventListener("input", () => {
|
243
|
+
if (!this.getOption("features.editable")) return;
|
244
|
+
// Only store temporarily, clamp on blur/enter – but update FormValue immediately
|
245
|
+
const raw = this[inputElementSymbol].value;
|
246
|
+
const n = normalizeNumber(raw, this.getOption("precision"));
|
247
|
+
this.setOption("value", n);
|
248
|
+
this.setFormValue(n);
|
249
|
+
fireChanged.call(this, "input");
|
250
|
+
});
|
251
|
+
|
252
|
+
this[inputElementSymbol].addEventListener("blur", () => {
|
253
|
+
if (!this.getOption("features.editable")) return;
|
254
|
+
const n = normalizeNumber(
|
255
|
+
this[inputElementSymbol].value,
|
256
|
+
this.getOption("precision"),
|
257
|
+
);
|
258
|
+
clampAndRender.call(this, n, { fire: true, kind: "blur" });
|
259
|
+
});
|
260
260
|
}
|
261
261
|
|
262
262
|
function applyEditableState() {
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
263
|
+
const editable = !!this.getOption("features.editable");
|
264
|
+
this[inputElementSymbol].toggleAttribute("readonly", !editable);
|
265
|
+
this[inputElementSymbol].toggleAttribute(
|
266
|
+
"disabled",
|
267
|
+
!!this.getOption("disabled"),
|
268
|
+
);
|
269
269
|
}
|
270
270
|
|
271
271
|
function clampAndRender(n, opts = {}) {
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
272
|
+
const min = Number.isFinite(this.getOption("min"))
|
273
|
+
? Number(this.getOption("min"))
|
274
|
+
: Number.NEGATIVE_INFINITY;
|
275
|
+
const max = Number.isFinite(this.getOption("max"))
|
276
|
+
? Number(this.getOption("max"))
|
277
|
+
: Number.POSITIVE_INFINITY;
|
278
|
+
|
279
|
+
let value = n;
|
280
|
+
if (this.getOption("features.enforceBounds")) {
|
281
|
+
value = Math.min(max, Math.max(min, toNumberOr(n, 0)));
|
282
|
+
}
|
283
|
+
|
284
|
+
// Precision
|
285
|
+
const p = this.getOption("precision");
|
286
|
+
if (Number.isInteger(p) && p >= 0) {
|
287
|
+
value = Number(toFixedSafe(value, p));
|
288
|
+
}
|
289
|
+
|
290
|
+
// Render into input
|
291
|
+
this[inputElementSymbol].value =
|
292
|
+
value === null || Number.isNaN(value) ? "" : String(value);
|
293
|
+
|
294
|
+
// Options + FormValue
|
295
|
+
this.setOption("value", value);
|
296
|
+
this.setFormValue(value);
|
297
|
+
|
298
|
+
if (opts.fire) fireChanged.call(this, opts.kind || "programmatic");
|
299
299
|
}
|
300
300
|
|
301
301
|
function fireChanged(kind) {
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
302
|
+
fireCustomEvent(this, "monster-quantity-change", {
|
303
|
+
element: this,
|
304
|
+
value: this.value,
|
305
|
+
kind, // 'increment' | 'decrement' | 'input' | 'blur' | 'programmatic'
|
306
|
+
});
|
307
307
|
}
|
308
308
|
|
309
309
|
function normalizeNumber(v, precision) {
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
310
|
+
if (v === null || v === undefined || v === "") return null;
|
311
|
+
let n = Number(v);
|
312
|
+
if (!Number.isFinite(n)) return null;
|
313
|
+
if (Number.isInteger(precision) && precision >= 0) {
|
314
|
+
n = Number(toFixedSafe(n, precision));
|
315
|
+
}
|
316
|
+
return n;
|
317
317
|
}
|
318
318
|
|
319
319
|
function toNumberOr(v, dflt) {
|
320
|
-
|
321
|
-
|
320
|
+
const n = Number(v);
|
321
|
+
return Number.isFinite(n) ? n : dflt;
|
322
322
|
}
|
323
323
|
|
324
324
|
function toFixedSafe(n, p) {
|
325
|
-
|
326
|
-
|
325
|
+
// Prevents 1.00000000000002 effects
|
326
|
+
return (Math.round(n * Math.pow(10, p)) / Math.pow(10, p)).toFixed(p);
|
327
327
|
}
|
328
328
|
|
329
329
|
function getTemplate() {
|
330
|
-
|
331
|
-
|
330
|
+
// language=HTML
|
331
|
+
return `
|
332
332
|
<div data-monster-role="control" part="control">
|
333
333
|
<monster-input-group part="input-group">
|
334
334
|
<button type="button"
|