@schukai/monster 4.97.0 → 4.98.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 +8 -0
- package/package.json +1 -1
- package/source/components/datatable/columnbar.mjs +5 -1
- package/source/components/form/message-state-button.mjs +6 -8
- package/source/components/state/log.mjs +300 -15
- package/source/components/state/style/thread.pcss +172 -0
- package/source/components/state/stylesheet/thread.mjs +38 -0
- package/source/components/state/thread/entry.mjs +242 -0
- package/source/components/state/thread.mjs +1034 -0
- package/source/dom/updater.mjs +8 -0
package/CHANGELOG.md
CHANGED
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.
|
|
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.98.0"}
|
|
@@ -510,7 +510,11 @@ function updateDotsVisibility() {
|
|
|
510
510
|
|
|
511
511
|
let visibleDots = baseLimit;
|
|
512
512
|
if (needsIndicator) {
|
|
513
|
-
visibleDots = Math.min(
|
|
513
|
+
visibleDots = Math.min(
|
|
514
|
+
Math.max(1, maxDots - 1),
|
|
515
|
+
configLimit,
|
|
516
|
+
dots.length,
|
|
517
|
+
);
|
|
514
518
|
}
|
|
515
519
|
for (let i = visibleDots; i < dots.length; i++) {
|
|
516
520
|
dots[i].classList.add("dots-overflow-hidden");
|
|
@@ -129,9 +129,6 @@ class MessageStateButton extends Popper {
|
|
|
129
129
|
actions: {
|
|
130
130
|
click: (e) => {},
|
|
131
131
|
},
|
|
132
|
-
features: {
|
|
133
|
-
disableButton: false,
|
|
134
|
-
},
|
|
135
132
|
|
|
136
133
|
aria: {
|
|
137
134
|
role: null,
|
|
@@ -433,10 +430,6 @@ function initDisabledSync() {
|
|
|
433
430
|
|
|
434
431
|
const syncDisabled = () => {
|
|
435
432
|
const disabled = self.getOption("disabled", false);
|
|
436
|
-
if (self.getOption("features.disableButton", false) !== disabled) {
|
|
437
|
-
self.setOption("features.disableButton", disabled);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
433
|
const button =
|
|
441
434
|
self.shadowRoot?.querySelector(`[${ATTRIBUTE_ROLE}=button]`) ??
|
|
442
435
|
self[buttonElementSymbol];
|
|
@@ -468,6 +461,11 @@ function initDisabledSync() {
|
|
|
468
461
|
};
|
|
469
462
|
}
|
|
470
463
|
self.attachObserver(new Observer(syncDisabled));
|
|
464
|
+
if (typeof customElements?.whenDefined === "function") {
|
|
465
|
+
customElements.whenDefined("monster-state-button").then(() => {
|
|
466
|
+
syncDisabled();
|
|
467
|
+
});
|
|
468
|
+
}
|
|
471
469
|
}
|
|
472
470
|
|
|
473
471
|
/**
|
|
@@ -484,7 +482,7 @@ function getTemplate() {
|
|
|
484
482
|
data-monster-option-classes-button path:classes.button,
|
|
485
483
|
data-monster-option-aria-role path:aria.role,
|
|
486
484
|
data-monster-option-aria-label path:aria.label,
|
|
487
|
-
disabled path:
|
|
485
|
+
disabled path:disabled | if:true"
|
|
488
486
|
part="button"
|
|
489
487
|
name="button"
|
|
490
488
|
data-monster-role="button">
|
|
@@ -23,7 +23,11 @@ import { LogStyleSheet } from "./stylesheet/log.mjs";
|
|
|
23
23
|
import { Entry } from "./log/entry.mjs";
|
|
24
24
|
import { validateInstance, validateString } from "../../types/validate.mjs";
|
|
25
25
|
import "./state.mjs";
|
|
26
|
-
import {
|
|
26
|
+
import { ProxyObserver } from "../../types/proxyobserver.mjs";
|
|
27
|
+
import { Updater } from "../../dom/updater.mjs";
|
|
28
|
+
import { Pathfinder } from "../../data/pathfinder.mjs";
|
|
29
|
+
import { getLocaleOfDocument } from "../../dom/locale.mjs";
|
|
30
|
+
import { isArray } from "../../types/is.mjs";
|
|
27
31
|
|
|
28
32
|
export { Log };
|
|
29
33
|
|
|
@@ -38,6 +42,15 @@ const logElementSymbol = Symbol("logElement");
|
|
|
38
42
|
* @type {symbol}
|
|
39
43
|
*/
|
|
40
44
|
const emptyStateElementSymbol = Symbol("emptyStateElement");
|
|
45
|
+
const entriesSymbol = Symbol("entries");
|
|
46
|
+
const entriesListSymbol = Symbol("entriesList");
|
|
47
|
+
const entryTemplateSymbol = Symbol("entryTemplate");
|
|
48
|
+
const entryObserverMapSymbol = Symbol("entryObserverMap");
|
|
49
|
+
const entryUpdaterMapSymbol = Symbol("entryUpdaterMap");
|
|
50
|
+
const entryElementMapSymbol = Symbol("entryElementMap");
|
|
51
|
+
const entryMapSymbol = Symbol("entryMap");
|
|
52
|
+
const idCounterSymbol = Symbol("idCounter");
|
|
53
|
+
const timeAgoIntervalSymbol = Symbol("timeAgoInterval");
|
|
41
54
|
|
|
42
55
|
/**
|
|
43
56
|
* A log entry
|
|
@@ -60,6 +73,13 @@ class Log extends CustomElement {
|
|
|
60
73
|
super[assembleMethodSymbol]();
|
|
61
74
|
|
|
62
75
|
initControlReferences.call(this);
|
|
76
|
+
this[entriesSymbol] = [];
|
|
77
|
+
this[entryObserverMapSymbol] = new Map();
|
|
78
|
+
this[entryUpdaterMapSymbol] = new Map();
|
|
79
|
+
this[entryElementMapSymbol] = new Map();
|
|
80
|
+
this[entryMapSymbol] = new Map();
|
|
81
|
+
this[idCounterSymbol] = 0;
|
|
82
|
+
initTimeAgoTicker.call(this);
|
|
63
83
|
initEventHandler.call(this);
|
|
64
84
|
}
|
|
65
85
|
|
|
@@ -97,6 +117,7 @@ class Log extends CustomElement {
|
|
|
97
117
|
|
|
98
118
|
features: {
|
|
99
119
|
direction: "ascending",
|
|
120
|
+
timeAgoMaxHours: 12,
|
|
100
121
|
},
|
|
101
122
|
|
|
102
123
|
updateFrequency: 10000,
|
|
@@ -107,6 +128,62 @@ class Log extends CustomElement {
|
|
|
107
128
|
});
|
|
108
129
|
}
|
|
109
130
|
|
|
131
|
+
/**
|
|
132
|
+
* @param {string} path
|
|
133
|
+
* @param {*} defaultValue
|
|
134
|
+
* @return {*}
|
|
135
|
+
*/
|
|
136
|
+
getOption(path, defaultValue = undefined) {
|
|
137
|
+
if (path === "entries" || path?.startsWith("entries.")) {
|
|
138
|
+
try {
|
|
139
|
+
return new Pathfinder({
|
|
140
|
+
entries: this[entriesSymbol],
|
|
141
|
+
}).getVia(path);
|
|
142
|
+
} catch (e) {
|
|
143
|
+
return defaultValue;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return super.getOption(path, defaultValue);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @param {string} path
|
|
152
|
+
* @param {*} value
|
|
153
|
+
* @return {Log}
|
|
154
|
+
*/
|
|
155
|
+
setOption(path, value) {
|
|
156
|
+
if (path === "entries") {
|
|
157
|
+
const prepared = prepareEntries(value);
|
|
158
|
+
this[entriesSymbol] = prepared;
|
|
159
|
+
this[idCounterSymbol] = 0;
|
|
160
|
+
renderEntries.call(this, prepared);
|
|
161
|
+
super.setOption("length", prepared.length);
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
super.setOption(path, value);
|
|
166
|
+
return this;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @param {object|string} options
|
|
171
|
+
* @return {Log}
|
|
172
|
+
*/
|
|
173
|
+
setOptions(options) {
|
|
174
|
+
if (options && typeof options === "object" && options.entries) {
|
|
175
|
+
const { entries, ...rest } = options;
|
|
176
|
+
if (Object.keys(rest).length > 0) {
|
|
177
|
+
super.setOptions(rest);
|
|
178
|
+
}
|
|
179
|
+
this.setOption("entries", entries);
|
|
180
|
+
return this;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
super.setOptions(options);
|
|
184
|
+
return this;
|
|
185
|
+
}
|
|
186
|
+
|
|
110
187
|
/**
|
|
111
188
|
* @return {void}
|
|
112
189
|
*/
|
|
@@ -135,7 +212,7 @@ class Log extends CustomElement {
|
|
|
135
212
|
* @return {Log}
|
|
136
213
|
*/
|
|
137
214
|
addEntry(entry) {
|
|
138
|
-
|
|
215
|
+
entry = normalizeEntry(entry);
|
|
139
216
|
|
|
140
217
|
if (entry.date === undefined || entry.date === null) {
|
|
141
218
|
entry.date = new Date();
|
|
@@ -148,8 +225,19 @@ class Log extends CustomElement {
|
|
|
148
225
|
entries.push(entry);
|
|
149
226
|
}
|
|
150
227
|
|
|
151
|
-
|
|
152
|
-
|
|
228
|
+
if (this[entriesListSymbol]) {
|
|
229
|
+
renderEntry(this, entry, this[entriesListSymbol], {
|
|
230
|
+
prepend: this.getOption("features.direction") === "ascending",
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (this[emptyStateElementSymbol]) {
|
|
235
|
+
this[emptyStateElementSymbol].style.display =
|
|
236
|
+
entries.length > 0 ? "none" : "block";
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
super.setOption("length", entries.length);
|
|
240
|
+
updateTimeAgo(this);
|
|
153
241
|
|
|
154
242
|
return this;
|
|
155
243
|
}
|
|
@@ -211,6 +299,10 @@ function initControlReferences() {
|
|
|
211
299
|
this[emptyStateElementSymbol] = this.shadowRoot.querySelector(
|
|
212
300
|
"[data-monster-role=empty-state]",
|
|
213
301
|
);
|
|
302
|
+
this[entriesListSymbol] = this.shadowRoot.querySelector(
|
|
303
|
+
"[data-monster-role=entries-list]",
|
|
304
|
+
);
|
|
305
|
+
this[entryTemplateSymbol] = this.shadowRoot.querySelector("template#entry");
|
|
214
306
|
}
|
|
215
307
|
|
|
216
308
|
/**
|
|
@@ -231,16 +323,209 @@ function initEventHandler() {
|
|
|
231
323
|
}
|
|
232
324
|
});
|
|
233
325
|
|
|
234
|
-
setInterval(() => {
|
|
235
|
-
getWindow().requestAnimationFrame(() => {
|
|
236
|
-
const timestamp = new Date().toTimeString();
|
|
237
|
-
this.setOption("timestamp", timestamp);
|
|
238
|
-
});
|
|
239
|
-
}, this.getOption("updateFrequency"));
|
|
240
|
-
|
|
241
326
|
return this;
|
|
242
327
|
}
|
|
243
328
|
|
|
329
|
+
/**
|
|
330
|
+
* @private
|
|
331
|
+
* @return {void}
|
|
332
|
+
*/
|
|
333
|
+
function initTimeAgoTicker() {
|
|
334
|
+
if (this[timeAgoIntervalSymbol]) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const refresh = () => {
|
|
339
|
+
updateTimeAgo(this);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
const interval = Number(this.getOption("updateFrequency"));
|
|
343
|
+
const delay = Number.isFinite(interval) && interval > 0 ? interval : 10000;
|
|
344
|
+
|
|
345
|
+
refresh();
|
|
346
|
+
this[timeAgoIntervalSymbol] = setInterval(refresh, delay);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* @private
|
|
351
|
+
* @param {Entry|Object} entry
|
|
352
|
+
* @return {Entry}
|
|
353
|
+
*/
|
|
354
|
+
function normalizeEntry(entry) {
|
|
355
|
+
if (entry instanceof Entry) {
|
|
356
|
+
return entry;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (entry && typeof entry === "object") {
|
|
360
|
+
return new Entry(entry);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
validateInstance(entry, Entry);
|
|
364
|
+
return entry;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* @private
|
|
369
|
+
* @param {Entry[]|*} entries
|
|
370
|
+
* @return {Entry[]}
|
|
371
|
+
*/
|
|
372
|
+
function prepareEntries(entries) {
|
|
373
|
+
const list = isArray(entries) ? entries.map(normalizeEntry) : [];
|
|
374
|
+
return list;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* @private
|
|
379
|
+
* @param {Entry[]} entries
|
|
380
|
+
* @return {void}
|
|
381
|
+
*/
|
|
382
|
+
function renderEntries(entries) {
|
|
383
|
+
if (!this[entriesListSymbol]) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
clearContainer(this[entriesListSymbol]);
|
|
388
|
+
this[entryObserverMapSymbol] = new Map();
|
|
389
|
+
this[entryUpdaterMapSymbol] = new Map();
|
|
390
|
+
this[entryElementMapSymbol] = new Map();
|
|
391
|
+
this[entryMapSymbol] = new Map();
|
|
392
|
+
|
|
393
|
+
const fragment = document.createDocumentFragment();
|
|
394
|
+
for (const entry of entries) {
|
|
395
|
+
renderEntry(this, entry, fragment, {});
|
|
396
|
+
}
|
|
397
|
+
this[entriesListSymbol].appendChild(fragment);
|
|
398
|
+
|
|
399
|
+
if (this[emptyStateElementSymbol]) {
|
|
400
|
+
this[emptyStateElementSymbol].style.display =
|
|
401
|
+
entries.length > 0 ? "none" : "block";
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
updateTimeAgo(this);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* @private
|
|
409
|
+
* @param {Log} log
|
|
410
|
+
* @param {Entry} entry
|
|
411
|
+
* @param {HTMLElement|DocumentFragment} parentList
|
|
412
|
+
* @param {{prepend?: boolean}} options
|
|
413
|
+
* @return {void}
|
|
414
|
+
*/
|
|
415
|
+
function renderEntry(log, entry, parentList, { prepend } = {}) {
|
|
416
|
+
if (!entry.id) {
|
|
417
|
+
log[idCounterSymbol] += 1;
|
|
418
|
+
entry.id = `entry-${log[idCounterSymbol]}`;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const template = log[entryTemplateSymbol];
|
|
422
|
+
if (!template) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const fragment = template.content.cloneNode(true);
|
|
427
|
+
const item = fragment.querySelector("[data-monster-role=entry]");
|
|
428
|
+
if (!item) {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
item.setAttribute("data-entry-id", entry.id);
|
|
433
|
+
|
|
434
|
+
const observer = new ProxyObserver({ entry });
|
|
435
|
+
const updater = new Updater(item, observer);
|
|
436
|
+
updater.run().catch(() => {});
|
|
437
|
+
|
|
438
|
+
log[entryObserverMapSymbol].set(entry.id, observer);
|
|
439
|
+
log[entryUpdaterMapSymbol].set(entry.id, updater);
|
|
440
|
+
log[entryElementMapSymbol].set(entry.id, item);
|
|
441
|
+
log[entryMapSymbol].set(entry.id, entry);
|
|
442
|
+
|
|
443
|
+
if (prepend && parentList instanceof HTMLElement) {
|
|
444
|
+
parentList.insertBefore(item, parentList.firstChild);
|
|
445
|
+
} else {
|
|
446
|
+
parentList.appendChild(item);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* @private
|
|
452
|
+
* @param {Log} log
|
|
453
|
+
* @return {void}
|
|
454
|
+
*/
|
|
455
|
+
function updateTimeAgo(log) {
|
|
456
|
+
const locale = getLocaleOfDocument().toString();
|
|
457
|
+
const maxHours = Number(log.getOption("features.timeAgoMaxHours", 12));
|
|
458
|
+
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "always" });
|
|
459
|
+
for (const [entryId, element] of log[entryElementMapSymbol].entries()) {
|
|
460
|
+
const entry = log[entryMapSymbol]?.get(entryId);
|
|
461
|
+
if (!entry?.date) {
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
const timeElement = element.querySelector("[data-monster-role=time-ago]");
|
|
465
|
+
if (!timeElement) {
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
try {
|
|
469
|
+
timeElement.textContent = formatRelativeTime(
|
|
470
|
+
new Date(entry.date),
|
|
471
|
+
locale,
|
|
472
|
+
maxHours,
|
|
473
|
+
rtf,
|
|
474
|
+
);
|
|
475
|
+
} catch (e) {}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* @private
|
|
481
|
+
* @param {Date} date
|
|
482
|
+
* @param {string} locale
|
|
483
|
+
* @param {number} maxHours
|
|
484
|
+
* @param {Intl.RelativeTimeFormat} rtf
|
|
485
|
+
* @return {string}
|
|
486
|
+
*/
|
|
487
|
+
function formatRelativeTime(date, locale, maxHours, rtf) {
|
|
488
|
+
let diffSeconds = Math.floor((Date.now() - date.getTime()) / 1000);
|
|
489
|
+
if (!Number.isFinite(diffSeconds) || diffSeconds < 0) {
|
|
490
|
+
diffSeconds = 0;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (diffSeconds < 5) {
|
|
494
|
+
return "just now";
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if (diffSeconds < 60) {
|
|
498
|
+
return rtf.format(-diffSeconds, "second");
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const diffMinutes = Math.floor(diffSeconds / 60);
|
|
502
|
+
if (diffMinutes < 60) {
|
|
503
|
+
return rtf.format(-diffMinutes, "minute");
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const diffHours = Math.floor(diffMinutes / 60);
|
|
507
|
+
if (diffHours < maxHours) {
|
|
508
|
+
return rtf.format(-diffHours, "hour");
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return date.toLocaleDateString(locale, {
|
|
512
|
+
year: "numeric",
|
|
513
|
+
month: "2-digit",
|
|
514
|
+
day: "2-digit",
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* @private
|
|
520
|
+
* @param {HTMLElement} container
|
|
521
|
+
* @return {void}
|
|
522
|
+
*/
|
|
523
|
+
function clearContainer(container) {
|
|
524
|
+
while (container.firstChild) {
|
|
525
|
+
container.removeChild(container.firstChild);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
244
529
|
/**
|
|
245
530
|
* @private
|
|
246
531
|
* @return {string}
|
|
@@ -256,14 +541,15 @@ function getTemplate() {
|
|
|
256
541
|
data-monster-attributes="class path:entry.title | ?:title:hidden"></span>
|
|
257
542
|
<span data-monster-replace="path:entry.message"
|
|
258
543
|
data-monster-attributes="class path:entry.message | ?:message:hidden"></span>
|
|
259
|
-
<span data-monster-
|
|
544
|
+
<span data-monster-role="time-ago"
|
|
545
|
+
data-monster-replace="path:entry.date | time-ago"
|
|
260
546
|
data-monster-attributes="title path:entry.date | datetime"></span>
|
|
261
547
|
|
|
262
548
|
</li>
|
|
263
549
|
</template>
|
|
264
550
|
|
|
265
551
|
<div part="control" data-monster-role="control">
|
|
266
|
-
<div data-monster-role="empty-state"
|
|
552
|
+
<div data-monster-role="empty-state">
|
|
267
553
|
<monster-state>
|
|
268
554
|
<div part="visual">
|
|
269
555
|
<svg width="4rem" height="4rem" viewBox="0 -12 512.00032 512"
|
|
@@ -279,8 +565,7 @@ function getTemplate() {
|
|
|
279
565
|
</monster-state>
|
|
280
566
|
</div>
|
|
281
567
|
<div data-monster-role="entries">
|
|
282
|
-
<ul data-monster-
|
|
283
|
-
</ul>
|
|
568
|
+
<ul data-monster-role="entries-list"></ul>
|
|
284
569
|
</div>
|
|
285
570
|
</div>
|
|
286
571
|
`;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
@import "../../style/control.pcss";
|
|
2
|
+
@import "../../style/display.pcss";
|
|
3
|
+
@import "../../style/border.pcss";
|
|
4
|
+
@import "../../style/mixin/media.pcss";
|
|
5
|
+
@import "../../style/mixin/typography.pcss";
|
|
6
|
+
@import "../../style/mixin/button.pcss";
|
|
7
|
+
@import "../../style/mixin/hover.pcss";
|
|
8
|
+
|
|
9
|
+
[data-monster-role=entries] {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
align-items: flex-start;
|
|
13
|
+
border: 0;
|
|
14
|
+
padding: 0;
|
|
15
|
+
margin: 0;
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
position: relative;
|
|
18
|
+
|
|
19
|
+
& ul {
|
|
20
|
+
list-style-type: none;
|
|
21
|
+
margin: 0;
|
|
22
|
+
padding: 0 0 0 2rem;
|
|
23
|
+
position: relative;
|
|
24
|
+
width: 100%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
& ul:before {
|
|
28
|
+
content: "";
|
|
29
|
+
display: block;
|
|
30
|
+
width: 2px;
|
|
31
|
+
height: 100%;
|
|
32
|
+
|
|
33
|
+
border-left-color: var(--monster-bg-color-primary-3);
|
|
34
|
+
border-left-style: dotted;
|
|
35
|
+
border-left-width: 1px;
|
|
36
|
+
position: absolute;
|
|
37
|
+
left: 1rem;
|
|
38
|
+
bottom: 0;
|
|
39
|
+
top: 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[data-monster-role=entry] {
|
|
44
|
+
background-color: var(--monster-bg-color-primary-1);
|
|
45
|
+
border-radius: var(--monster-border-radius);
|
|
46
|
+
color: var(--monster-color-primary-1);
|
|
47
|
+
margin: 0 0 0.6rem 0;
|
|
48
|
+
padding: 0.45rem 0.5rem 0.45rem 0.8rem;
|
|
49
|
+
position: relative;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
[data-monster-role=entry]:before {
|
|
53
|
+
content: "";
|
|
54
|
+
width: 6px;
|
|
55
|
+
height: 6px;
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
border-radius: 50%;
|
|
58
|
+
background: var(--monster-bg-color-primary-3);
|
|
59
|
+
border: 1px solid var(--monster-color-primary-2);
|
|
60
|
+
position: absolute;
|
|
61
|
+
left: calc(-1rem - 2px);
|
|
62
|
+
top: 1rem;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
[data-monster-role=entry]:after {
|
|
66
|
+
content: "";
|
|
67
|
+
border-top: 1px dotted var(--monster-bg-color-primary-3);
|
|
68
|
+
position: absolute;
|
|
69
|
+
left: calc(-1rem + 1px);
|
|
70
|
+
top: 1.1rem;
|
|
71
|
+
width: calc(1rem - 1px);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
[data-monster-role=meta] {
|
|
75
|
+
align-items: center;
|
|
76
|
+
color: var(--monster-color-primary-2);
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-wrap: wrap;
|
|
79
|
+
font-size: 0.85rem;
|
|
80
|
+
gap: 0.4rem;
|
|
81
|
+
|
|
82
|
+
& .title {
|
|
83
|
+
font-stretch: expanded;
|
|
84
|
+
font-weight: 700;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
& .title:before {
|
|
88
|
+
content: "—";
|
|
89
|
+
font-weight: 400;
|
|
90
|
+
margin-right: 0.25rem;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
[data-monster-role=message] {
|
|
95
|
+
margin: 0.25rem 0 0.4rem 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
[data-monster-role=thread-controls] {
|
|
99
|
+
align-items: center;
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-wrap: wrap;
|
|
102
|
+
gap: 0.5rem;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
[data-monster-role=thread-controls] .monster-button-primary,
|
|
106
|
+
[data-monster-role=thread-controls] .monster-button-secondary,
|
|
107
|
+
[data-monster-role=thread-controls] .monster-button-tertiary,
|
|
108
|
+
[data-monster-role=thread-controls] .monster-button-outline-primary,
|
|
109
|
+
[data-monster-role=thread-controls] .monster-button-outline-secondary,
|
|
110
|
+
[data-monster-role=thread-controls] .monster-button-outline-tertiary {
|
|
111
|
+
border-radius: 999px;
|
|
112
|
+
font-size: 0.75rem;
|
|
113
|
+
gap: 0.4rem;
|
|
114
|
+
padding: 0.15rem 0.6rem;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
[data-monster-role=badge] {
|
|
118
|
+
background: var(--monster-color-secondary-4);
|
|
119
|
+
border-radius: 999px;
|
|
120
|
+
color: var(--monster-bg-color-secondary-4);
|
|
121
|
+
display: inline-flex;
|
|
122
|
+
font-size: 0.7rem;
|
|
123
|
+
line-height: 1;
|
|
124
|
+
padding: 0.15rem 0.4rem;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
[data-monster-role=thread-controls] [data-reply-count="0"] {
|
|
128
|
+
display: none;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
[data-monster-role=badge][data-reply-count="0"] {
|
|
132
|
+
display: none;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
[data-monster-role=entry][data-collapsed=true] [data-monster-role=children] {
|
|
136
|
+
display: none;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
[data-monster-role=actions] {
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-wrap: wrap;
|
|
142
|
+
gap: 0.4rem;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
[data-monster-role=actions] .monster-button-primary,
|
|
146
|
+
[data-monster-role=actions] .monster-button-secondary,
|
|
147
|
+
[data-monster-role=actions] .monster-button-tertiary,
|
|
148
|
+
[data-monster-role=actions] .monster-button-outline-primary,
|
|
149
|
+
[data-monster-role=actions] .monster-button-outline-secondary,
|
|
150
|
+
[data-monster-role=actions] .monster-button-outline-tertiary {
|
|
151
|
+
font-size: 0.85rem;
|
|
152
|
+
padding: 0.2rem 0.5rem;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
[data-monster-role=actions] button:hover {
|
|
156
|
+
box-shadow: var(--monster-box-shadow-1);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
[data-monster-role=editor] {
|
|
160
|
+
margin-top: 1rem;
|
|
161
|
+
padding-left: 2rem;
|
|
162
|
+
|
|
163
|
+
& ::slotted(textarea) {
|
|
164
|
+
box-sizing: border-box;
|
|
165
|
+
min-height: 6rem;
|
|
166
|
+
width: 100%;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
& ::slotted(button) {
|
|
170
|
+
margin-top: 0.5rem;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright © Volker Schukai and all contributing authors, 2026. 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
|
+
|
|
13
|
+
import { addAttributeToken } from "../../../dom/attributes.mjs";
|
|
14
|
+
import { ATTRIBUTE_ERRORMESSAGE } from "../../../dom/constants.mjs";
|
|
15
|
+
|
|
16
|
+
export { ThreadStyleSheet };
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @private
|
|
20
|
+
* @type {CSSStyleSheet}
|
|
21
|
+
*/
|
|
22
|
+
const ThreadStyleSheet = new CSSStyleSheet();
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
ThreadStyleSheet.insertRule(
|
|
26
|
+
`
|
|
27
|
+
@layer thread {
|
|
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}.block{display:block}.inline{display:inline}.inline-block{display:inline-block}.grid{display:grid}.inline-grid{display:inline-grid}.flex{display:flex}.inline-flex{display:inline-flex}.hidden,.hide,.none{display:none}.visible{visibility:visible}.invisible{visibility:hidden}.monster-border-primary-1,.monster-border-primary-2,.monster-border-primary-3,.monster-border-primary-4{border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width)}.monster-border-0{border-radius:0;border-style:none;border-width:0}.monster-border-primary-1{border-color:var(--monster-bg-color-primary-1)}.monster-border-primary-2{border-color:var(--monster-bg-color-primary-2)}.monster-border-primary-3{border-color:var(--monster-bg-color-primary-3)}.monster-border-primary-4{border-color:var(--monster-bg-color-primary-4)}.monster-border-secondary-1,.monster-border-secondary-2,.monster-border-secondary-3,.monster-border-secondary-4{border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width)}.monster-border-secondary-1{border-color:var(--monster-bg-color-secondary-1)}.monster-border-secondary-2{border-color:var(--monster-bg-color-secondary-2)}.monster-border-secondary-3{border-color:var(--monster-bg-color-secondary-3)}.monster-border-secondary-4{border-color:var(--monster-bg-color-secondary-4)}.monster-border-tertiary-1,.monster-border-tertiary-2,.monster-border-tertiary-3,.monster-border-tertiary-4{border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width)}.monster-border-tertiary-1{border-color:var(--monster-bg-color-tertiary-1)}.monster-border-tertiary-2{border-color:var(--monster-bg-color-tertiary-2)}.monster-border-tertiary-3{border-color:var(--monster-bg-color-tertiary-3)}.monster-border-tertiary-4{border-color:var(--monster-bg-color-tertiary-4)}[data-monster-role=entries]{align-items:flex-start;border:0;box-sizing:border-box;display:flex;flex-direction:column;margin:0;padding:0;position:relative}[data-monster-role=entries] ul{list-style-type:none;margin:0;padding:0 0 0 2rem;position:relative;width:100%}[data-monster-role=entries] ul:before{border-left:1px dotted var(--monster-bg-color-primary-3);bottom:0;content:\"\";display:block;height:100%;left:1rem;position:absolute;top:0;width:2px}[data-monster-role=entry]{background-color:var(--monster-bg-color-primary-1);border-radius:var(--monster-border-radius);color:var(--monster-color-primary-1);margin:0 0 .6rem;padding:.45rem .5rem .45rem .8rem;position:relative}[data-monster-role=entry]:before{background:var(--monster-bg-color-primary-3);border:1px solid var(--monster-color-primary-2);border-radius:50%;box-sizing:border-box;content:\"\";height:6px;left:calc(-1rem - 2px);position:absolute;top:1rem;width:6px}[data-monster-role=entry]:after{border-top:1px dotted var(--monster-bg-color-primary-3);content:\"\";left:calc(-1rem + 1px);position:absolute;top:1.1rem;width:calc(1rem - 1px)}[data-monster-role=meta]{align-items:center;color:var(--monster-color-primary-2);display:flex;flex-wrap:wrap;font-size:.85rem;gap:.4rem}[data-monster-role=meta] .title{font-stretch:expanded;font-weight:700}[data-monster-role=meta] .title:before{content:\"—\";font-weight:400;margin-right:.25rem}[data-monster-role=message]{margin:.25rem 0 .4rem}[data-monster-role=thread-controls]{align-items:center;display:flex;flex-wrap:wrap;gap:.5rem}[data-monster-role=thread-controls] .monster-button-outline-primary,[data-monster-role=thread-controls] .monster-button-outline-secondary,[data-monster-role=thread-controls] .monster-button-outline-tertiary,[data-monster-role=thread-controls] .monster-button-primary,[data-monster-role=thread-controls] .monster-button-secondary,[data-monster-role=thread-controls] .monster-button-tertiary{border-radius:999px;font-size:.75rem;gap:.4rem;padding:.15rem .6rem}[data-monster-role=badge]{background:var(--monster-color-secondary-4);border-radius:999px;color:var(--monster-bg-color-secondary-4);display:inline-flex;font-size:.7rem;line-height:1;padding:.15rem .4rem}[data-monster-role=badge][data-reply-count=\"0\"],[data-monster-role=entry][data-collapsed=true] [data-monster-role=children],[data-monster-role=thread-controls] [data-reply-count=\"0\"]{display:none}[data-monster-role=actions]{display:flex;flex-wrap:wrap;gap:.4rem}[data-monster-role=actions] .monster-button-outline-primary,[data-monster-role=actions] .monster-button-outline-secondary,[data-monster-role=actions] .monster-button-outline-tertiary,[data-monster-role=actions] .monster-button-primary,[data-monster-role=actions] .monster-button-secondary,[data-monster-role=actions] .monster-button-tertiary{font-size:.85rem;padding:.2rem .5rem}[data-monster-role=actions] button:hover{box-shadow:var(--monster-box-shadow-1)}[data-monster-role=editor]{margin-top:1rem;padding-left:2rem}[data-monster-role=editor] ::slotted(textarea){box-sizing:border-box;min-height:6rem;width:100%}[data-monster-role=editor] ::slotted(button){margin-top:.5rem}
|
|
29
|
+
}`,
|
|
30
|
+
0,
|
|
31
|
+
);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
addAttributeToken(
|
|
34
|
+
document.getRootNode().querySelector("html"),
|
|
35
|
+
ATTRIBUTE_ERRORMESSAGE,
|
|
36
|
+
e + "",
|
|
37
|
+
);
|
|
38
|
+
}
|