@schukai/monster 3.58.4 → 3.59.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 +12 -0
- package/package.json +1 -1
- package/source/components/form/tabs.mjs +5 -1026
- package/source/components/host/overlay.mjs +1 -1
- package/source/components/host/viewer.mjs +2 -14
- package/source/components/layout/namespace.mjs +13 -0
- package/source/components/layout/split-screen.mjs +341 -0
- package/source/components/layout/style/split-screen.pcss +59 -0
- package/source/components/{form → layout}/style/tabs.pcss +0 -3
- package/source/components/layout/stylesheet/split-screen.mjs +27 -0
- package/source/components/layout/tabs.mjs +1075 -0
- package/source/monster.mjs +5 -1
- package/source/types/version.mjs +1 -1
- package/test/cases/components/{form → layout}/tabs.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/web/import.js +1 -1
- package/test/web/test.html +2 -2
- package/test/web/tests.js +16158 -16161
- /package/source/components/{form → layout}/stylesheet/tabs.mjs +0 -0
@@ -106,7 +106,7 @@ class Overlay extends CustomElement {
|
|
106
106
|
* @returns {symbol}
|
107
107
|
*/
|
108
108
|
static get [instanceSymbol]() {
|
109
|
-
return Symbol.for("@schukai/
|
109
|
+
return Symbol.for("@schukai/monster/components/host/overlay@@instance");
|
110
110
|
}
|
111
111
|
|
112
112
|
/**
|
@@ -39,18 +39,10 @@ const viewerElementSymbol = Symbol("viewerElement");
|
|
39
39
|
* Or you can create this CustomControl directly in Javascript:
|
40
40
|
*
|
41
41
|
* ```js
|
42
|
-
* import '@schukai/
|
42
|
+
* import '@schukai/monster/components/host/viewer.mjs';
|
43
43
|
* document.createElement('monster-viewer');
|
44
44
|
* ```
|
45
45
|
*
|
46
|
-
* The Body should have a class "hidden" to ensure that the styles are applied correctly.
|
47
|
-
*
|
48
|
-
* ```css
|
49
|
-
* body.hidden {
|
50
|
-
* visibility: hidden;
|
51
|
-
* }
|
52
|
-
* ```
|
53
|
-
*
|
54
46
|
* @startuml viewer.png
|
55
47
|
* skinparam monochrome true
|
56
48
|
* skinparam shadowing false
|
@@ -62,10 +54,6 @@ const viewerElementSymbol = Symbol("viewerElement");
|
|
62
54
|
* @copyright schukai GmbH
|
63
55
|
* @memberOf Monster.Components.Host
|
64
56
|
* @summary A simple viewer component
|
65
|
-
* @fires Monster.Components.Host.Viewer.event:monster-viewer-before-open
|
66
|
-
* @fires Monster.Components.Host.Viewer.event:monster-viewer-open
|
67
|
-
* @fires Monster.Components.Host.Viewer.event:monster-viewer-before-close
|
68
|
-
* @fires Monster.Components.Host.Viewer.event:monster-viewer-closed
|
69
57
|
*/
|
70
58
|
class Viewer extends CustomElement {
|
71
59
|
/**
|
@@ -73,7 +61,7 @@ class Viewer extends CustomElement {
|
|
73
61
|
* @returns {symbol}
|
74
62
|
*/
|
75
63
|
static get [instanceSymbol]() {
|
76
|
-
return Symbol.for("@schukai/
|
64
|
+
return Symbol.for("@schukai/monster/components/host/viewer@@instance");
|
77
65
|
}
|
78
66
|
|
79
67
|
/**
|
@@ -0,0 +1,341 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 schukai GmbH
|
3
|
+
* SPDX-License-Identifier: AGPL-3.0
|
4
|
+
*/
|
5
|
+
|
6
|
+
import {
|
7
|
+
assembleMethodSymbol,
|
8
|
+
CustomElement,
|
9
|
+
registerCustomElement,
|
10
|
+
} from "../../dom/customelement.mjs";
|
11
|
+
import "../notify/notify.mjs";
|
12
|
+
import {Observer} from "../../types/observer.mjs";
|
13
|
+
import {SplitScreenStyleSheet} from "./stylesheet/split-screen.mjs";
|
14
|
+
import {instanceSymbol} from "../../constants.mjs";
|
15
|
+
import {internalSymbol} from "../../constants.mjs";
|
16
|
+
|
17
|
+
export {SplitScreen, TYPE_VERTICAL, TYPE_HORIZONTAL};
|
18
|
+
|
19
|
+
/**
|
20
|
+
* @private
|
21
|
+
* @type {symbol}
|
22
|
+
*/
|
23
|
+
const splitScreenElementSymbol = Symbol("splitScreenElement");
|
24
|
+
|
25
|
+
/**
|
26
|
+
* @private
|
27
|
+
* @type {symbol}
|
28
|
+
*/
|
29
|
+
const draggerElementSymbol = Symbol("draggerElement");
|
30
|
+
/**
|
31
|
+
* @private
|
32
|
+
* @type {symbol}
|
33
|
+
*/
|
34
|
+
const startPanelElementSymbol = Symbol("startPanelElement");
|
35
|
+
/**
|
36
|
+
* @private
|
37
|
+
* @type {symbol}
|
38
|
+
*/
|
39
|
+
const endPanelElementSymbol = Symbol("endPanelElement");
|
40
|
+
/**
|
41
|
+
* @private
|
42
|
+
* @type {symbol}
|
43
|
+
*/
|
44
|
+
const handleElementSymbol = Symbol("handleElement");
|
45
|
+
|
46
|
+
/**
|
47
|
+
*
|
48
|
+
* @type {string}
|
49
|
+
*/
|
50
|
+
const TYPE_VERTICAL = "vertical";
|
51
|
+
/**
|
52
|
+
*
|
53
|
+
* @type {string}
|
54
|
+
*/
|
55
|
+
const TYPE_HORIZONTAL = "horizontal";
|
56
|
+
|
57
|
+
|
58
|
+
/**
|
59
|
+
* The Viewer component is used to show a PDF, HTML or Image.
|
60
|
+
*
|
61
|
+
* <img src="./images/splitscreen.png">
|
62
|
+
*
|
63
|
+
* You can create this control either by specifying the HTML tag <monster-splitscreen />` directly in the HTML or using
|
64
|
+
* Javascript via the `document.createElement('monster-split-screen');` method.
|
65
|
+
*
|
66
|
+
* ```html
|
67
|
+
* <monster-split-screen></monster-split-screen>
|
68
|
+
* ```
|
69
|
+
*
|
70
|
+
* Or you can create this CustomControl directly in Javascript:
|
71
|
+
*
|
72
|
+
* ```js
|
73
|
+
* import '@schukai/monster/components/layout/split-screen.mjs';
|
74
|
+
* document.createElement('monster-split-screen');
|
75
|
+
* ```
|
76
|
+
*
|
77
|
+
* @startuml splitscreen.png
|
78
|
+
* skinparam monochrome true
|
79
|
+
* skinparam shadowing false
|
80
|
+
* HTMLElement <|-- CustomElement
|
81
|
+
* CustomElement <|-- CustomControl
|
82
|
+
* CustomControl <|-- SplitScreen
|
83
|
+
* @enduml
|
84
|
+
*
|
85
|
+
* @copyright schukai GmbH
|
86
|
+
* @memberOf Monster.Components.Layout
|
87
|
+
* @summary A simple split screen layout
|
88
|
+
*/
|
89
|
+
class SplitScreen extends CustomElement {
|
90
|
+
|
91
|
+
/**
|
92
|
+
* This method is called by the `instanceof` operator.
|
93
|
+
* @returns {symbol}
|
94
|
+
*/
|
95
|
+
static get [instanceSymbol]() {
|
96
|
+
return Symbol.for("@schukai/monster/components/layout/splitscreen");
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* To set the options via the html tag the attribute `data-monster-options` must be used.
|
101
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
102
|
+
*
|
103
|
+
* The individual configuration values can be found in the table.
|
104
|
+
*
|
105
|
+
* @property {Object} templates Template definitions
|
106
|
+
* @property {string} templates.main Main template
|
107
|
+
* @property {Object} classes Css classes
|
108
|
+
* @property {Object} features Feature definitions
|
109
|
+
*/
|
110
|
+
get defaults() {
|
111
|
+
return Object.assign({}, super.defaults, {
|
112
|
+
templates: {
|
113
|
+
main: getTemplate(),
|
114
|
+
},
|
115
|
+
splitType: TYPE_VERTICAL,
|
116
|
+
dimension: "20%",
|
117
|
+
classes: {},
|
118
|
+
features: {},
|
119
|
+
});
|
120
|
+
}
|
121
|
+
|
122
|
+
setContent(html) {
|
123
|
+
this.setOption("content", html);
|
124
|
+
return this;
|
125
|
+
}
|
126
|
+
|
127
|
+
/**
|
128
|
+
*
|
129
|
+
* @returns {Monster.Components.Host.Viewer}
|
130
|
+
*/
|
131
|
+
[assembleMethodSymbol]() {
|
132
|
+
super[assembleMethodSymbol]();
|
133
|
+
|
134
|
+
initControlReferences.call(this);
|
135
|
+
initEventHandler.call(this);
|
136
|
+
applyPanelDimensions.call(this);
|
137
|
+
}
|
138
|
+
|
139
|
+
setDimension(dimension) {
|
140
|
+
// check if percent and greater than100
|
141
|
+
if (dimension.includes("%")) {
|
142
|
+
if (parseInt(dimension) > 100) {
|
143
|
+
throw new Error("dimension must be less than 100%");
|
144
|
+
} else if (parseInt(dimension) < 0) {
|
145
|
+
throw new Error("dimension must be greater than 0%");
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
this.setOption("dimension", dimension);
|
150
|
+
return this;
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
/**
|
155
|
+
*
|
156
|
+
* @return {string}
|
157
|
+
*/
|
158
|
+
static getTag() {
|
159
|
+
return "monster-split-screen";
|
160
|
+
}
|
161
|
+
|
162
|
+
/**
|
163
|
+
* @return {CSSStyleSheet[]}
|
164
|
+
*/
|
165
|
+
static getCSSStyleSheet() {
|
166
|
+
return [SplitScreenStyleSheet];
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
|
171
|
+
/**
|
172
|
+
* Set the dimensions of the panel based on the split type.
|
173
|
+
*/
|
174
|
+
function applyPanelDimensions() {
|
175
|
+
|
176
|
+
const splitType = this.getOption("splitType");
|
177
|
+
const dimension = this.getOption("dimension");
|
178
|
+
|
179
|
+
if (splitType === TYPE_VERTICAL) {
|
180
|
+
this[startPanelElementSymbol].style.width = dimension;
|
181
|
+
this[endPanelElementSymbol].style.width = `calc(100% - ${dimension} - 5px)`;
|
182
|
+
this[draggerElementSymbol].style.cursor = "ew-resize";
|
183
|
+
this[splitScreenElementSymbol].classList.add("vertical");
|
184
|
+
this[splitScreenElementSymbol].classList.remove("horizontal");
|
185
|
+
|
186
|
+
} else {
|
187
|
+
this[startPanelElementSymbol].style.height = dimension;
|
188
|
+
this[endPanelElementSymbol].style.height = `calc(100% - ${dimension} - 5px)`;
|
189
|
+
this[draggerElementSymbol].style.cursor = "ns-resize";
|
190
|
+
this[splitScreenElementSymbol].classList.add("horizontal");
|
191
|
+
this[splitScreenElementSymbol].classList.remove("vertical");
|
192
|
+
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
|
197
|
+
/**
|
198
|
+
* @private
|
199
|
+
* @return {Select}
|
200
|
+
* @throws {Error} no shadow-root is defined
|
201
|
+
*/
|
202
|
+
function initControlReferences() {
|
203
|
+
if (!this.shadowRoot) {
|
204
|
+
throw new Error("no shadow-root is defined");
|
205
|
+
}
|
206
|
+
|
207
|
+
this[splitScreenElementSymbol] = this.shadowRoot.querySelector("[data-monster-role=split-screen]");
|
208
|
+
this[draggerElementSymbol] = this.shadowRoot.querySelector("[data-monster-role=dragger]");
|
209
|
+
this[handleElementSymbol] = this.shadowRoot.querySelector("[data-monster-role=handle]");
|
210
|
+
|
211
|
+
this[startPanelElementSymbol] = this.shadowRoot.querySelector("[data-monster-role=startPanel]");
|
212
|
+
this[endPanelElementSymbol] = this.shadowRoot.querySelector("[data-monster-role=endPanel]");
|
213
|
+
|
214
|
+
}
|
215
|
+
|
216
|
+
/**
|
217
|
+
* @private
|
218
|
+
*/
|
219
|
+
function initEventHandler() {
|
220
|
+
const self = this;
|
221
|
+
|
222
|
+
this[internalSymbol].getSubject().isDragging = false;
|
223
|
+
|
224
|
+
this[draggerElementSymbol].addEventListener('dblclick', () => {
|
225
|
+
self[internalSymbol].getSubject().isDragging = false;
|
226
|
+
applyPanelDimensions.call(this);
|
227
|
+
});
|
228
|
+
|
229
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
230
|
+
for (let entry of entries) {
|
231
|
+
console.log(entry.contentRect.width);
|
232
|
+
}
|
233
|
+
});
|
234
|
+
|
235
|
+
resizeObserver.observe(this[splitScreenElementSymbol]);
|
236
|
+
|
237
|
+
|
238
|
+
this[draggerElementSymbol].addEventListener('mousedown', () => {
|
239
|
+
self[internalSymbol].getSubject().isDragging = true;
|
240
|
+
|
241
|
+
document.addEventListener('mousemove', (e) => {
|
242
|
+
e.preventDefault();
|
243
|
+
if (!self[internalSymbol].getSubject().isDragging) {
|
244
|
+
return;
|
245
|
+
}
|
246
|
+
|
247
|
+
if (self.getOption("splitType") === TYPE_HORIZONTAL) {
|
248
|
+
const containerOffsetTop = self[splitScreenElementSymbol].offsetTop;
|
249
|
+
const topPanel = self[startPanelElementSymbol];
|
250
|
+
const bottomPanel = self[endPanelElementSymbol];
|
251
|
+
const newTopHeight = e.clientY - containerOffsetTop;
|
252
|
+
topPanel.style.height = `${newTopHeight}px`;
|
253
|
+
bottomPanel.style.height = `calc(100% - ${newTopHeight}px - 5px)`; // 5px is dragger height
|
254
|
+
|
255
|
+
|
256
|
+
} else {
|
257
|
+
|
258
|
+
const containerOffsetLeft = self[splitScreenElementSymbol].offsetLeft;
|
259
|
+
const leftPanel = self[startPanelElementSymbol];
|
260
|
+
const rightPanel = self[endPanelElementSymbol];
|
261
|
+
const newLeftWidth = e.clientX - containerOffsetLeft;
|
262
|
+
leftPanel.style.width = `${newLeftWidth}px`;
|
263
|
+
rightPanel.style.width = `calc(100% - ${newLeftWidth}px - 5px)`; // 5px is dragger width
|
264
|
+
}
|
265
|
+
|
266
|
+
});
|
267
|
+
|
268
|
+
document.addEventListener('mouseup', (e) => {
|
269
|
+
self[internalSymbol].getSubject().isDragging = false;
|
270
|
+
document.removeEventListener('mousemove', (e) => {
|
271
|
+
if (!self[internalSymbol].getSubject().isDragging) {
|
272
|
+
return;
|
273
|
+
}
|
274
|
+
|
275
|
+
if (self.getOption("splitType") === TYPE_VERTICAL) {
|
276
|
+
const containerOffsetTop = self[splitScreenElementSymbol].offsetTop;
|
277
|
+
const topPanel = self[startPanelElementSymbol];
|
278
|
+
const bottomPanel = self[endPanelElementSymbol];
|
279
|
+
const newTopHeight = e.clientY - containerOffsetTop;
|
280
|
+
topPanel.style.height = `${newTopHeight}px`;
|
281
|
+
bottomPanel.style.height = `calc(100% - ${newTopHeight}px - 5px)`; // 5px is dragger height
|
282
|
+
|
283
|
+
} else {
|
284
|
+
const containerOffsetLeft = self[splitScreenElementSymbol].offsetLeft;
|
285
|
+
const newLeftWidth = e.clientX - containerOffsetLeft;
|
286
|
+
const leftPanel = self[startPanelElementSymbol];
|
287
|
+
const rightPanel = self[endPanelElementSymbol];
|
288
|
+
leftPanel.style.width = `${newLeftWidth}px`;
|
289
|
+
rightPanel.style.width = `calc(100% - ${newLeftWidth}px - 5px)`; // 5px is dragger width
|
290
|
+
}
|
291
|
+
});
|
292
|
+
document.removeEventListener('mouseup', (e) => {
|
293
|
+
self[internalSymbol].getSubject().isDragging = false;
|
294
|
+
});
|
295
|
+
});
|
296
|
+
});
|
297
|
+
|
298
|
+
let lastDimension = this.getOption("dimension");
|
299
|
+
let lastType = this.getOption("splitType");
|
300
|
+
this[internalSymbol].attachObserver(
|
301
|
+
new Observer(() => {
|
302
|
+
if (lastDimension !== this.getOption("dimension")) {
|
303
|
+
lastDimension = this.getOption("dimension");
|
304
|
+
applyPanelDimensions.call(this);
|
305
|
+
}
|
306
|
+
|
307
|
+
if (lastType !== this.getOption("splitType")) {
|
308
|
+
lastType = this.getOption("splitType");
|
309
|
+
applyPanelDimensions.call(this);
|
310
|
+
}
|
311
|
+
|
312
|
+
}));
|
313
|
+
|
314
|
+
|
315
|
+
return this;
|
316
|
+
|
317
|
+
}
|
318
|
+
|
319
|
+
/**
|
320
|
+
* @private
|
321
|
+
* @return {string}
|
322
|
+
*/
|
323
|
+
function getTemplate() {
|
324
|
+
// language=HTML
|
325
|
+
return `
|
326
|
+
<div data-monster-role="split-screen" part="container">
|
327
|
+
<div data-monster-role="startPanel" class="panel" part="startPanel">
|
328
|
+
<slot name="start"></slot>
|
329
|
+
</div>
|
330
|
+
<div data-monster-role="dragger" part="dragger">
|
331
|
+
<div data-monster-role="handle"></div>
|
332
|
+
</div>
|
333
|
+
<div data-monster-role="endPanel" class="panel" part="endPanel">
|
334
|
+
<slot name="end"></slot>
|
335
|
+
</div>
|
336
|
+
|
337
|
+
|
338
|
+
</div>`;
|
339
|
+
}
|
340
|
+
|
341
|
+
registerCustomElement(SplitScreen);
|
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
[data-monster-role="split-screen"] {
|
4
|
+
|
5
|
+
box-sizing: border-box;
|
6
|
+
display: flex;
|
7
|
+
width: 100%;
|
8
|
+
height: auto;
|
9
|
+
flex-direction: row;
|
10
|
+
margin: 0;
|
11
|
+
padding: 0;
|
12
|
+
|
13
|
+
& .panel {
|
14
|
+
flex-grow: 1;
|
15
|
+
overflow: auto;
|
16
|
+
}
|
17
|
+
|
18
|
+
[data-monster-role="dragger"] {
|
19
|
+
background-color: var(--monster-bg-color-primary-4);
|
20
|
+
color: var(--monster-color-primary-4);
|
21
|
+
width: var(--monster-border-width);
|
22
|
+
height: auto;
|
23
|
+
|
24
|
+
position: relative;
|
25
|
+
|
26
|
+
& [data-monster-role=handle] {
|
27
|
+
position: absolute;
|
28
|
+
top: 50%;
|
29
|
+
left: 50%;
|
30
|
+
transform: translate(-50%, -50%);
|
31
|
+
cursor: pointer;
|
32
|
+
width: 5px;
|
33
|
+
height: 120px;
|
34
|
+
background-color: var(--monster-bg-color-primary-3);
|
35
|
+
color: var(--monster-color-primary-3);
|
36
|
+
z-index: var(--monster-z-index-outline);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
&.horizontal {
|
41
|
+
flex-direction: column;
|
42
|
+
|
43
|
+
[data-monster-role="dragger"] {
|
44
|
+
width: 100%;
|
45
|
+
height: var(--monster-border-width);
|
46
|
+
|
47
|
+
& [data-monster-role=handle] {
|
48
|
+
width: 120px;
|
49
|
+
height: 5px;
|
50
|
+
}
|
51
|
+
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
}
|
56
|
+
|
57
|
+
}
|
58
|
+
|
59
|
+
|
@@ -27,9 +27,6 @@ nav[data-monster-role=nav] {
|
|
27
27
|
border-bottom-style: var(--monster-border-style);
|
28
28
|
box-shadow: var(--monster-box-shadow-1);
|
29
29
|
border-color: var(--monster-bg-color-primary-2);
|
30
|
-
|
31
|
-
flex-wrap: nowrap;
|
32
|
-
|
33
30
|
}
|
34
31
|
|
35
32
|
[data-monster-role=nav] button .remove-tab {
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
/**
|
3
|
+
* Copyright schukai GmbH and contributors 2024. All Rights Reserved.
|
4
|
+
* Node module: @schukai/monster
|
5
|
+
* This file is licensed under the AGPLv3 License.
|
6
|
+
* License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
|
7
|
+
*/
|
8
|
+
|
9
|
+
import {addAttributeToken} from "../../../dom/attributes.mjs";
|
10
|
+
import {ATTRIBUTE_ERRORMESSAGE} from "../../../dom/constants.mjs";
|
11
|
+
|
12
|
+
export {SplitScreenStyleSheet}
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @private
|
16
|
+
* @type {CSSStyleSheet}
|
17
|
+
*/
|
18
|
+
const SplitScreenStyleSheet = new CSSStyleSheet();
|
19
|
+
|
20
|
+
try {
|
21
|
+
SplitScreenStyleSheet.insertRule(`
|
22
|
+
@layer splitscreen {
|
23
|
+
[data-monster-role=split-screen]{box-sizing:border-box;display:flex;flex-direction:row;height:auto;margin:0;padding:0;width:100%}[data-monster-role=split-screen] .panel{flex-grow:1;overflow:auto}[data-monster-role=split-screen] [data-monster-role=dragger]{background-color:var(--monster-bg-color-primary-4);color:var(--monster-color-primary-4);height:auto;position:relative;width:var(--monster-border-width)}[data-monster-role=split-screen] [data-monster-role=dragger] [data-monster-role=handle]{background-color:var(--monster-bg-color-primary-3);color:var(--monster-color-primary-3);cursor:pointer;height:120px;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);width:5px;z-index:var(--monster-z-index-outline)}.horizontal[data-monster-role=split-screen]{flex-direction:column}.horizontal[data-monster-role=split-screen] [data-monster-role=dragger]{height:var(--monster-border-width);width:100%}.horizontal[data-monster-role=split-screen] [data-monster-role=dragger] [data-monster-role=handle]{height:5px;width:120px}
|
24
|
+
}`, 0);
|
25
|
+
} catch (e) {
|
26
|
+
addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + "");
|
27
|
+
}
|