@schukai/monster 4.98.1 → 4.99.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/form/checklist.mjs +361 -0
- package/source/components/form/style/checklist.pcss +49 -0
- package/source/components/form/stylesheet/checklist.mjs +31 -0
- package/source/components/state/stylesheet/thread-message.mjs +38 -0
- package/source/components/state/thread/message.mjs +80 -0
- package/source/components/state/thread.mjs +3 -3
- package/source/monster.mjs +1 -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.99.0"}
|
|
@@ -0,0 +1,361 @@
|
|
|
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 { CustomControl } from "../../dom/customcontrol.mjs";
|
|
17
|
+
import { Observer } from "../../types/observer.mjs";
|
|
18
|
+
import { clone } from "../../util/clone.mjs";
|
|
19
|
+
import { isArray, isObject, isString, isNumber } from "../../types/is.mjs";
|
|
20
|
+
import {
|
|
21
|
+
assembleMethodSymbol,
|
|
22
|
+
registerCustomElement,
|
|
23
|
+
attributeObserverSymbol,
|
|
24
|
+
} from "../../dom/customelement.mjs";
|
|
25
|
+
import { fireCustomEvent, fireEvent, findTargetElementFromEvent } from "../../dom/events.mjs";
|
|
26
|
+
import { ChecklistStyleSheet } from "./stylesheet/checklist.mjs";
|
|
27
|
+
import { addAttributeToken } from "../../dom/attributes.mjs";
|
|
28
|
+
import { ATTRIBUTE_ERRORMESSAGE } from "../../dom/constants.mjs";
|
|
29
|
+
|
|
30
|
+
export { Checklist };
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @private
|
|
34
|
+
* @type {symbol}
|
|
35
|
+
*/
|
|
36
|
+
const controlElementSymbol = Symbol("controlElement");
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Checklist control for displaying and tracking a list of items.
|
|
40
|
+
*
|
|
41
|
+
* @summary A checklist control with change events and form integration.
|
|
42
|
+
*/
|
|
43
|
+
class Checklist extends CustomControl {
|
|
44
|
+
/**
|
|
45
|
+
* To set the options via the HTML tag, the attribute `data-monster-options` must be used.
|
|
46
|
+
*
|
|
47
|
+
* @property {Array} items The checklist items.
|
|
48
|
+
* @property {boolean} disabled Disabled state.
|
|
49
|
+
* @property {Object} templates Template definitions.
|
|
50
|
+
* @property {string} templates.main Main template.
|
|
51
|
+
*/
|
|
52
|
+
get defaults() {
|
|
53
|
+
return Object.assign({}, super.defaults, {
|
|
54
|
+
items: [],
|
|
55
|
+
disabled: false,
|
|
56
|
+
templates: {
|
|
57
|
+
main: getTemplate(),
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @return {void}
|
|
64
|
+
*/
|
|
65
|
+
[assembleMethodSymbol]() {
|
|
66
|
+
super[assembleMethodSymbol]();
|
|
67
|
+
initControlReferences.call(this);
|
|
68
|
+
initEventHandler.call(this);
|
|
69
|
+
initAttributeObservers.call(this);
|
|
70
|
+
normalizeItemsOption.call(this);
|
|
71
|
+
syncFormValue.call(this);
|
|
72
|
+
|
|
73
|
+
this.attachObserver(
|
|
74
|
+
new Observer(() => {
|
|
75
|
+
syncFormValue.call(this);
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @return {CSSStyleSheet[]}
|
|
82
|
+
*/
|
|
83
|
+
static getCSSStyleSheet() {
|
|
84
|
+
return [ChecklistStyleSheet];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @return {string}
|
|
89
|
+
*/
|
|
90
|
+
static getTag() {
|
|
91
|
+
return "monster-checklist";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @returns {Array}
|
|
96
|
+
*/
|
|
97
|
+
get value() {
|
|
98
|
+
return getCheckedIds.call(this);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @param {Array} value
|
|
103
|
+
*/
|
|
104
|
+
set value(value) {
|
|
105
|
+
if (!isArray(value)) {
|
|
106
|
+
value = [];
|
|
107
|
+
}
|
|
108
|
+
setCheckedIds.call(this, value);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @return {Array}
|
|
113
|
+
*/
|
|
114
|
+
getItems() {
|
|
115
|
+
return clone(this.getOption("items", []));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @return {Array}
|
|
120
|
+
*/
|
|
121
|
+
getCheckedItems() {
|
|
122
|
+
return this.getItems().filter((item) => Boolean(item?.checked));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @param {Array} items
|
|
127
|
+
* @return {Checklist}
|
|
128
|
+
*/
|
|
129
|
+
setItems(items) {
|
|
130
|
+
const normalized = normalizeItems(items);
|
|
131
|
+
this.setOption("items", normalized.items);
|
|
132
|
+
syncFormValue.call(this);
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @private
|
|
139
|
+
*/
|
|
140
|
+
function initControlReferences() {
|
|
141
|
+
this[controlElementSymbol] = this.shadowRoot?.querySelector(
|
|
142
|
+
"[data-monster-role=control]",
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @private
|
|
148
|
+
*/
|
|
149
|
+
function initEventHandler() {
|
|
150
|
+
this.addEventListener("change", (event) => {
|
|
151
|
+
const checkbox = findTargetElementFromEvent(
|
|
152
|
+
event,
|
|
153
|
+
"data-monster-role",
|
|
154
|
+
"checkbox",
|
|
155
|
+
);
|
|
156
|
+
if (!(checkbox instanceof HTMLInputElement)) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (this.getOption("disabled") === true) {
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const itemId = checkbox.getAttribute("data-item-id");
|
|
166
|
+
if (!itemId) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const items = this.getOption("items", []);
|
|
171
|
+
const updated = clone(items).map((item) => {
|
|
172
|
+
if (item?.id === itemId) {
|
|
173
|
+
return Object.assign({}, item, { checked: checkbox.checked });
|
|
174
|
+
}
|
|
175
|
+
return item;
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
this.setOption("items", updated);
|
|
179
|
+
syncFormValue.call(this);
|
|
180
|
+
|
|
181
|
+
fireEvent(this, "change");
|
|
182
|
+
fireCustomEvent(this, "monster-checklist-change", {
|
|
183
|
+
id: itemId,
|
|
184
|
+
checked: checkbox.checked,
|
|
185
|
+
item: updated.find((item) => item?.id === itemId),
|
|
186
|
+
items: clone(updated),
|
|
187
|
+
value: getCheckedIds.call(this),
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @private
|
|
194
|
+
*/
|
|
195
|
+
function normalizeItemsOption() {
|
|
196
|
+
if (applyItemsAttribute.call(this)) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const normalized = normalizeItems(this.getOption("items", []));
|
|
200
|
+
if (normalized.changed) {
|
|
201
|
+
this.setOption("items", normalized.items);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @private
|
|
207
|
+
* @param {Array} items
|
|
208
|
+
* @return {{items: Array, changed: boolean}}
|
|
209
|
+
*/
|
|
210
|
+
function normalizeItems(items) {
|
|
211
|
+
const normalized = [];
|
|
212
|
+
let changed = false;
|
|
213
|
+
|
|
214
|
+
if (!isArray(items)) {
|
|
215
|
+
return { items: [], changed: true };
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
for (const [index, entry] of Object.entries(items)) {
|
|
219
|
+
const idx = Number(index);
|
|
220
|
+
let item = entry;
|
|
221
|
+
|
|
222
|
+
if (isString(item) || isNumber(item)) {
|
|
223
|
+
item = {
|
|
224
|
+
id: `item-${idx}`,
|
|
225
|
+
label: String(item),
|
|
226
|
+
checked: false,
|
|
227
|
+
disabled: false,
|
|
228
|
+
};
|
|
229
|
+
changed = true;
|
|
230
|
+
} else if (isObject(item)) {
|
|
231
|
+
item = Object.assign({}, item, {
|
|
232
|
+
id: item.id ?? `item-${idx}`,
|
|
233
|
+
label: item.label ?? "",
|
|
234
|
+
checked: Boolean(item.checked),
|
|
235
|
+
disabled: Boolean(item.disabled),
|
|
236
|
+
});
|
|
237
|
+
if (item.id !== entry.id || item.label !== entry.label) {
|
|
238
|
+
changed = true;
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
item = {
|
|
242
|
+
id: `item-${idx}`,
|
|
243
|
+
label: "",
|
|
244
|
+
checked: false,
|
|
245
|
+
disabled: false,
|
|
246
|
+
};
|
|
247
|
+
changed = true;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
normalized.push(item);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return { items: normalized, changed };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* @private
|
|
258
|
+
* @return {boolean}
|
|
259
|
+
*/
|
|
260
|
+
function applyItemsAttribute() {
|
|
261
|
+
if (!this.hasAttribute("data-monster-option-items")) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const raw = this.getAttribute("data-monster-option-items");
|
|
266
|
+
if (!raw) {
|
|
267
|
+
this.setOption("items", []);
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
try {
|
|
272
|
+
const parsed = JSON.parse(raw);
|
|
273
|
+
if (!isArray(parsed)) {
|
|
274
|
+
addAttributeToken(
|
|
275
|
+
this,
|
|
276
|
+
ATTRIBUTE_ERRORMESSAGE,
|
|
277
|
+
"data-monster-option-items must be a JSON array",
|
|
278
|
+
);
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
const normalized = normalizeItems(parsed);
|
|
282
|
+
this.setOption("items", normalized.items);
|
|
283
|
+
return true;
|
|
284
|
+
} catch (error) {
|
|
285
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message || String(error));
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* @private
|
|
292
|
+
*/
|
|
293
|
+
function initAttributeObservers() {
|
|
294
|
+
this[attributeObserverSymbol]["data-monster-option-items"] = () => {
|
|
295
|
+
applyItemsAttribute.call(this);
|
|
296
|
+
syncFormValue.call(this);
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* @private
|
|
302
|
+
* @return {Array}
|
|
303
|
+
*/
|
|
304
|
+
function getCheckedIds() {
|
|
305
|
+
const items = this.getOption("items", []);
|
|
306
|
+
return items.filter((item) => item?.checked).map((item) => item.id);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* @private
|
|
311
|
+
* @param {Array} ids
|
|
312
|
+
*/
|
|
313
|
+
function setCheckedIds(ids) {
|
|
314
|
+
const items = this.getOption("items", []);
|
|
315
|
+
const updated = clone(items).map((item) =>
|
|
316
|
+
Object.assign({}, item, { checked: ids.includes(item?.id) }),
|
|
317
|
+
);
|
|
318
|
+
this.setOption("items", updated);
|
|
319
|
+
syncFormValue.call(this);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @private
|
|
324
|
+
*/
|
|
325
|
+
function syncFormValue() {
|
|
326
|
+
const value = JSON.stringify(getCheckedIds.call(this));
|
|
327
|
+
if (typeof this.setFormValue === "function") {
|
|
328
|
+
this.setFormValue(value);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* @private
|
|
334
|
+
* @return {string}
|
|
335
|
+
*/
|
|
336
|
+
function getTemplate() {
|
|
337
|
+
// language=HTML
|
|
338
|
+
return `
|
|
339
|
+
<template id="item">
|
|
340
|
+
<label data-monster-role="item"
|
|
341
|
+
part="item"
|
|
342
|
+
data-monster-attributes="data-item-id path:item.id, class path:item.disabled | ?:disabled">
|
|
343
|
+
<input type="checkbox"
|
|
344
|
+
data-monster-role="checkbox"
|
|
345
|
+
part="checkbox"
|
|
346
|
+
data-monster-attributes="data-item-id path:item.id, checked path:item.checked | ?:checked, disabled path:item.disabled | ?:disabled">
|
|
347
|
+
<span data-monster-role="label"
|
|
348
|
+
part="label"
|
|
349
|
+
data-monster-replace="path:item.label | default: "></span>
|
|
350
|
+
</label>
|
|
351
|
+
</template>
|
|
352
|
+
|
|
353
|
+
<div data-monster-role="control" part="control">
|
|
354
|
+
<div data-monster-role="items"
|
|
355
|
+
part="items"
|
|
356
|
+
data-monster-insert="item path:items"></div>
|
|
357
|
+
</div>
|
|
358
|
+
`;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
registerCustomElement(Checklist);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
:host {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
color: var(--monster-color-primary-1);
|
|
5
|
+
display: block;
|
|
6
|
+
font-family: var(--monster-font-family);
|
|
7
|
+
font-size: 1rem;
|
|
8
|
+
line-height: 1.4;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
*,
|
|
12
|
+
*::before,
|
|
13
|
+
*::after {
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
[data-monster-role="control"] {
|
|
18
|
+
display: block;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
[data-monster-role="items"] {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
gap: 0.4rem;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
[data-monster-role="item"] {
|
|
28
|
+
align-items: flex-start;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
display: flex;
|
|
31
|
+
gap: 0.5rem;
|
|
32
|
+
line-height: 1.4;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
[data-monster-role="item"].disabled {
|
|
36
|
+
cursor: not-allowed;
|
|
37
|
+
opacity: 0.6;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
[data-monster-role="checkbox"] {
|
|
41
|
+
accent-color: var(--monster-color-secondary-1);
|
|
42
|
+
margin-top: 0.2rem;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
[data-monster-role="label"] {
|
|
46
|
+
display: inline-block;
|
|
47
|
+
min-width: 0;
|
|
48
|
+
word-break: break-word;
|
|
49
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
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 {ChecklistStyleSheet}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @private
|
|
20
|
+
* @type {CSSStyleSheet}
|
|
21
|
+
*/
|
|
22
|
+
const ChecklistStyleSheet = new CSSStyleSheet();
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
ChecklistStyleSheet.insertRule(`
|
|
26
|
+
@layer checklist {
|
|
27
|
+
:host{box-sizing:border-box;color:var(--monster-color-primary-1);display:block;font-family:var(--monster-font-family);font-size:1rem;line-height:1.4}*,:after,:before{box-sizing:border-box}[data-monster-role=control]{display:block}[data-monster-role=items]{display:flex;flex-direction:column;gap:.4rem}[data-monster-role=item]{align-items:flex-start;cursor:pointer;display:flex;gap:.5rem;line-height:1.4}[data-monster-role=item].disabled{cursor:not-allowed;opacity:.6}[data-monster-role=checkbox]{accent-color:var(--monster-color-secondary-1);margin-top:.2rem}[data-monster-role=label]{display:inline-block;min-width:0;word-break:break-word}
|
|
28
|
+
}`, 0);
|
|
29
|
+
} catch (e) {
|
|
30
|
+
addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + "");
|
|
31
|
+
}
|
|
@@ -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 { ThreadMessageStyleSheet };
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @private
|
|
20
|
+
* @type {CSSStyleSheet}
|
|
21
|
+
*/
|
|
22
|
+
const ThreadMessageStyleSheet = new CSSStyleSheet();
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
ThreadMessageStyleSheet.insertRule(
|
|
26
|
+
`
|
|
27
|
+
@layer thread-message {
|
|
28
|
+
:host{box-sizing:border-box;color:var(--monster-color-primary-1);display:block;font-family:var(--monster-font-family);font-size:1rem;font-weight:400;line-height:1.4}*,*::before,*::after{box-sizing:border-box}[data-monster-role=content]{display:block}a,a:active,a:focus,a:hover,a:link,a:visited{color:var(--monster-color-secondary-1);text-decoration:none;transition:color .3s ease-in-out,text-decoration-color .3s ease-in-out}a:active,a:focus,a:hover{color:var(--monster-color-primary-2);text-decoration:underline;text-decoration-color:var(--monster-color-secondary-1);text-decoration-thickness:1px}a:focus{outline:1px dashed var(--monster-color-selection-1);outline-offset:2px}@media (prefers-color-scheme: dark){a,a:active,a:focus,a:hover,a:link,a:visited{color:var(--monster-color-amber-2)}a:focus{outline:1px dashed var(--monster-color-selection-4)}}p{font-size:1rem;font-weight:400;line-height:1.6;margin:0 0 .65rem;text-align:justify}p:last-child{margin-bottom:0}.monster-paragraph{font-size:1rem;font-weight:400;line-height:1.6;text-align:justify}code{font-family:var(--monster-font-family-monospace)}h1{font-size:3rem;font-weight:400;line-height:1.15;margin:4rem 0 1.5rem}h2{font-size:2.5rem;font-weight:400;line-height:1.2;margin:4rem 0 1.5rem}h3{font-size:2rem;font-weight:400;line-height:1.25;margin:4rem 0 1.25rem}h4{font-size:1.5rem;font-weight:400;line-height:1.3;margin:4rem 0 1.25rem}h5{font-size:1.4rem;font-weight:bolder;line-height:1.3;margin:4rem 0 1.25rem}h6{font-size:1.3rem;font-weight:700;line-height:1.3;margin:4rem 0 1.25rem}p+h1{margin-top:3.75rem}p+h2{margin-top:3rem}p+h3{margin-top:2.25rem}p+h4{margin-top:1.5rem}p+h5{margin-top:.75rem}p+h6{margin-top:0}blockquote+h1,ol+h1,p+h1,pre+h1,table+h1,ul+h1{margin-top:2rem}article+h1,div+h1,section+h1{margin-top:0}blockquote+h2,ol+h2,p+h2,pre+h2,table+h2,ul+h2{margin-top:2rem}article+h2,div+h2,section+h2{margin-top:0}blockquote+h3,ol+h3,p+h3,pre+h3,table+h3,ul+h3{margin-top:2rem}article+h3,div+h3,section+h3{margin-top:0}blockquote+h4,ol+h4,p+h4,pre+h4,table+h4,ul+h4{margin-top:2rem}article+h4,div+h4,section+h4{margin-top:0}blockquote+h5,ol+h5,p+h5,pre+h5,table+h5,ul+h5{margin-top:2rem}article+h5,div+h5,section+h5{margin-top:0}blockquote+h6,ol+h6,p+h6,pre+h6,table+h6,ul+h6{margin-top:2rem}article+h6,div+h6,section+h6{margin-top:0}ul,ol{margin:0 0 .65rem;padding-left:1.25rem}li{margin:0 0 .25rem}blockquote{margin:0 0 .65rem;padding:0 0 0 .75rem;border-left:2px solid var(--monster-bg-color-primary-3)}img{height:auto;max-width:100%}
|
|
29
|
+
}`,
|
|
30
|
+
0,
|
|
31
|
+
);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
addAttributeToken(
|
|
34
|
+
document.getRootNode().querySelector("html"),
|
|
35
|
+
ATTRIBUTE_ERRORMESSAGE,
|
|
36
|
+
e + "",
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
CustomElement,
|
|
18
|
+
registerCustomElement,
|
|
19
|
+
} from "../../../dom/customelement.mjs";
|
|
20
|
+
import { ThreadMessageStyleSheet } from "../stylesheet/thread-message.mjs";
|
|
21
|
+
|
|
22
|
+
export { ThreadMessage };
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The ThreadMessage component encapsulates a message in a shadow root
|
|
26
|
+
* to prevent list styling from the thread control from leaking in.
|
|
27
|
+
*
|
|
28
|
+
* @summary Isolated message content for thread entries.
|
|
29
|
+
*/
|
|
30
|
+
class ThreadMessage extends CustomElement {
|
|
31
|
+
/**
|
|
32
|
+
* This method is called by the `instanceof` operator.
|
|
33
|
+
* @return {symbol}
|
|
34
|
+
*/
|
|
35
|
+
static get [instanceSymbol]() {
|
|
36
|
+
return Symbol.for(
|
|
37
|
+
"@schukai/monster/components/state/thread-message@@instance",
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @return {object}
|
|
43
|
+
*/
|
|
44
|
+
get defaults() {
|
|
45
|
+
return Object.assign({}, super.defaults, {
|
|
46
|
+
content: "",
|
|
47
|
+
templates: {
|
|
48
|
+
main: getTemplate(),
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @return {string}
|
|
55
|
+
*/
|
|
56
|
+
static getTag() {
|
|
57
|
+
return "monster-thread-message";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @return {CSSStyleSheet[]}
|
|
62
|
+
*/
|
|
63
|
+
static getCSSStyleSheet() {
|
|
64
|
+
return [ThreadMessageStyleSheet];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @private
|
|
70
|
+
* @return {string}
|
|
71
|
+
*/
|
|
72
|
+
function getTemplate() {
|
|
73
|
+
// language=HTML
|
|
74
|
+
return `
|
|
75
|
+
<div data-monster-role="content" part="content"
|
|
76
|
+
data-monster-replace="path:content"></div>
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
registerCustomElement(ThreadMessage);
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
} from "../../dom/customelement.mjs";
|
|
21
21
|
import { ThreadStyleSheet } from "./stylesheet/thread.mjs";
|
|
22
22
|
import { Entry } from "./thread/entry.mjs";
|
|
23
|
+
import "./thread/message.mjs";
|
|
23
24
|
import { validateInstance, validateString } from "../../types/validate.mjs";
|
|
24
25
|
import "./state.mjs";
|
|
25
26
|
import { isArray } from "../../types/is.mjs";
|
|
@@ -983,9 +984,8 @@ function getTemplate() {
|
|
|
983
984
|
data-monster-replace="path:entry.date | time-ago"
|
|
984
985
|
data-monster-attributes="title path:entry.date | datetime"></span>
|
|
985
986
|
</div>
|
|
986
|
-
<
|
|
987
|
-
data-monster-
|
|
988
|
-
data-monster-attributes="class path:entry.message | ?:message:hidden"></div>
|
|
987
|
+
<monster-thread-message data-monster-role="message"
|
|
988
|
+
data-monster-attributes="data-monster-option-content path:entry.message | default: , class path:entry.message | ?:message:hidden"></monster-thread-message>
|
|
989
989
|
<div data-monster-role="thread-controls">
|
|
990
990
|
<button type="button"
|
|
991
991
|
class="monster-button-outline-secondary"
|
package/source/monster.mjs
CHANGED
|
@@ -76,6 +76,7 @@ export * from "./components/form/shadow-reload.mjs";
|
|
|
76
76
|
export * from "./components/form/button.mjs";
|
|
77
77
|
export * from "./components/form/field-set.mjs";
|
|
78
78
|
export * from "./components/form/toggle-switch.mjs";
|
|
79
|
+
export * from "./components/form/checklist.mjs";
|
|
79
80
|
export * from "./components/form/types/state.mjs";
|
|
80
81
|
export * from "./components/form/template.mjs";
|
|
81
82
|
export * from "./components/form/constants.mjs";
|