@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 CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.98.0] - 2026-01-14
6
+
7
+ ### Add Features
8
+
9
+ - Add new thread/comment dialog with support for actions
10
+
11
+
12
+
5
13
  ## [4.97.0] - 2026-01-14
6
14
 
7
15
  ### Add Features
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.97.0"}
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(Math.max(1, maxDots - 1), configLimit, dots.length);
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:features.disableButton | if:true"
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 { getWindow } from "../../dom/util.mjs";
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
- validateInstance(entry, Entry);
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
- /** this field is not used, but triggers a change event */
152
- this.setOption("length", entries.length - 1);
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-replace="path:entry.date | time-ago"
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" data-monster-attributes="class path:entries | has-entries | ?:hidden:">
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-insert="entry path:entries">
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
+ }