@schukai/monster 4.119.0 → 4.120.1

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,22 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.120.1] - 2026-02-12
6
+
7
+ ### Bug Fixes
8
+
9
+ - new setContent/setPDF API for MonsterViewer
10
+
11
+
12
+
13
+ ## [4.120.0] - 2026-02-03
14
+
15
+ ### Add Features
16
+
17
+ - Improve option observer efficiency
18
+
19
+
20
+
5
21
  ## [4.119.0] - 2026-02-03
6
22
 
7
23
  ### 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.119.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.120.1"}
@@ -138,7 +138,14 @@ class Viewer extends CustomElement {
138
138
  /**
139
139
  * Sets the content of an element based on the provided content and media type.
140
140
  *
141
- * @param {string} content - The content to be set.
141
+ * Supported forms:
142
+ * - setContent(contentString, mediaType)
143
+ * - setContent({ mediaType, data, encoding })
144
+ *
145
+ * The declarative form requires an explicit `encoding` when `data` is a string.
146
+ * Use `encoding: "url"` for URLs and `encoding: "base64"` for base64 payloads.
147
+ *
148
+ * @param {string|object} content - The content to be set or a declarative payload.
142
149
  * @param {string} [mediaType="text/plain"] - The media type of the content. Defaults to "text/plain" if not specified.
143
150
  * @return {void} This method does not return a value.
144
151
  * @throws {Error} Throws an error if shadowRoot is not defined.
@@ -148,6 +155,44 @@ class Viewer extends CustomElement {
148
155
  throw new Error("no shadow-root is defined");
149
156
  }
150
157
 
158
+ let declarativePayload = null;
159
+ // Declarative form: { mediaType, data, encoding }
160
+ if (
161
+ content &&
162
+ typeof content === "object" &&
163
+ !isBlob(content) &&
164
+ !(content instanceof URL)
165
+ ) {
166
+ const { mediaType: mt, data, encoding } = content;
167
+ mediaType = mt ?? mediaType ?? "text/plain";
168
+ declarativePayload = { data, encoding };
169
+
170
+ if (isString(data)) {
171
+ if (!encoding) {
172
+ this.dispatchEvent(
173
+ new CustomEvent("viewer-error", {
174
+ detail: "String content requires explicit encoding",
175
+ }),
176
+ );
177
+ return;
178
+ }
179
+ if (encoding === "base64") {
180
+ content = data;
181
+ } else if (encoding === "url") {
182
+ content = data;
183
+ } else {
184
+ this.dispatchEvent(
185
+ new CustomEvent("viewer-error", {
186
+ detail: "Invalid encoding",
187
+ }),
188
+ );
189
+ return;
190
+ }
191
+ } else {
192
+ content = data;
193
+ }
194
+ }
195
+
151
196
  const renderers = this.getOption("renderers");
152
197
 
153
198
  const isDataURL = (value) => {
@@ -235,7 +280,10 @@ class Viewer extends CustomElement {
235
280
  switch (mediaTypeObject.subtype) {
236
281
  case "pdf":
237
282
  if (checkRenderer("pdf", mediaTypeObject.toString())) {
238
- renderers.pdf.call(this, content);
283
+ renderers.pdf.call(
284
+ this,
285
+ declarativePayload ? declarativePayload : content,
286
+ );
239
287
  }
240
288
  break;
241
289
 
@@ -426,13 +474,63 @@ class Viewer extends CustomElement {
426
474
  /**
427
475
  * Configures and embeds a PDF document into the application with customizable display settings.
428
476
  *
429
- * @param {Blob|URL|string} data The PDF data to be embedded. Can be provided as a Blob, URL, or base64 string.
477
+ * Supported forms:
478
+ * - setPDF(blobOrUrlOrBase64String, navigation, toolbar, scrollbar)
479
+ * - setPDF({ data, encoding, navigation, toolbar, scrollbar })
480
+ *
481
+ * The declarative form requires an explicit `encoding` when `data` is a string.
482
+ * Use `encoding: "url"` for URLs and `encoding: "base64"` for base64 payloads.
483
+ *
484
+ * @param {Blob|URL|string|object} data The PDF data to be embedded. Can be provided as a Blob, URL, or base64 string,
485
+ * or a declarative payload: { data, encoding, navigation, toolbar, scrollbar }.
430
486
  * @param {boolean} [navigation=true] Determines whether the navigation pane is displayed in the PDF viewer.
431
487
  * @param {boolean} [toolbar=true] Controls the visibility of the toolbar in the PDF viewer.
432
488
  * @param {boolean} [scrollbar=false] Configures the display of the scrollbar in the PDF viewer.
433
489
  * @return {void} This method returns nothing but sets the embedded PDF as the content.
434
490
  */
435
491
  setPDF(data, navigation = true, toolbar = true, scrollbar = false) {
492
+ let stringEncoding = null;
493
+ // Declarative form: { data, encoding, navigation, toolbar, scrollbar }
494
+ if (
495
+ data &&
496
+ typeof data === "object" &&
497
+ !isBlob(data) &&
498
+ !(data instanceof URL)
499
+ ) {
500
+ const payload = data;
501
+ data = payload.data;
502
+ stringEncoding = payload.encoding ?? null;
503
+ if (typeof payload.navigation === "boolean") {
504
+ navigation = payload.navigation;
505
+ }
506
+ if (typeof payload.toolbar === "boolean") {
507
+ toolbar = payload.toolbar;
508
+ }
509
+ if (typeof payload.scrollbar === "boolean") {
510
+ scrollbar = payload.scrollbar;
511
+ }
512
+ if (isString(data)) {
513
+ if (!payload.encoding) {
514
+ this.dispatchEvent(
515
+ new CustomEvent("viewer-error", {
516
+ detail: "String PDF data requires explicit encoding",
517
+ }),
518
+ );
519
+ return;
520
+ }
521
+ if (payload.encoding === "base64") {
522
+ // handled below as string/base64
523
+ } else if (payload.encoding === "url") {
524
+ // handled below as string/url
525
+ } else {
526
+ this.dispatchEvent(
527
+ new CustomEvent("viewer-error", { detail: "Invalid encoding" }),
528
+ );
529
+ return;
530
+ }
531
+ }
532
+ }
533
+
436
534
  const hashes =
437
535
  "#toolbar=" +
438
536
  (toolbar ? "1" : "0") +
@@ -440,7 +538,6 @@ class Viewer extends CustomElement {
440
538
  (navigation ? "1" : "0") +
441
539
  "&scrollbar=" +
442
540
  (scrollbar ? "1" : "0");
443
-
444
541
  let pdfURL = "";
445
542
  if (isBlob(data)) {
446
543
  pdfURL = URL.createObjectURL(data);
@@ -453,11 +550,18 @@ class Viewer extends CustomElement {
453
550
  pdfURL = data.toString();
454
551
  }
455
552
  } else if (isString(data)) {
456
- //URL.createObjectURL(data);
457
- const blobObj = new Blob([atob(data)], { type: "application/pdf" });
458
- const url = window.URL.createObjectURL(blobObj);
459
-
460
- pdfURL = data;
553
+ if (stringEncoding === "url") {
554
+ if (data.indexOf("#") === -1) {
555
+ pdfURL = data + hashes;
556
+ } else {
557
+ pdfURL = data;
558
+ }
559
+ } else {
560
+ // Default legacy behavior: treat string as base64
561
+ const blobObj = new Blob([atob(data)], { type: "application/pdf" });
562
+ const url = window.URL.createObjectURL(blobObj);
563
+ pdfURL = url + hashes;
564
+ }
461
565
  } else {
462
566
  this.dispatchEvent(
463
567
  new CustomEvent("viewer-error", { detail: "Blob or URL expected" }),
@@ -2238,15 +2238,19 @@ function initOptionObserver() {
2238
2238
  const strict =
2239
2239
  self.getOption("features.useStrictValueComparison") === true;
2240
2240
  const optionsVersion = self[optionsVersionSymbol] || 0;
2241
+ const optionsSnapshot = self[optionsSnapshotSymbol];
2242
+ const strictSnapshot = self[strictModeSnapshotSymbol];
2243
+ const optionsVersionSnapshot = self[optionsMapVersionSnapshotSymbol];
2244
+ const optionsChanged =
2245
+ options !== optionsSnapshot || strict !== strictSnapshot;
2246
+ const versionChanged = optionsVersion !== optionsVersionSnapshot;
2241
2247
 
2242
2248
  if (
2243
- options !== self[optionsSnapshotSymbol] ||
2244
- strict !== self[strictModeSnapshotSymbol] ||
2245
- optionsVersion !== self[optionsMapVersionSnapshotSymbol]
2249
+ optionsChanged ||
2250
+ versionChanged
2246
2251
  ) {
2247
2252
  self[optionsSnapshotSymbol] = options;
2248
2253
  self[strictModeSnapshotSymbol] = strict;
2249
- self[optionsMapVersionSnapshotSymbol] = optionsVersion;
2250
2254
 
2251
2255
  const map = new Map();
2252
2256
  if (isArray(options)) {
@@ -2272,7 +2276,11 @@ function initOptionObserver() {
2272
2276
  }
2273
2277
  self[optionsMapSymbol] = map;
2274
2278
 
2275
- const version = bumpOptionsVersion.call(self);
2279
+ let version = optionsVersion;
2280
+ if (!versionChanged) {
2281
+ version = bumpOptionsVersion.call(self);
2282
+ }
2283
+ self[optionsMapVersionSnapshotSymbol] = version;
2276
2284
  scheduleSelectionSync.call(self, version);
2277
2285
  }
2278
2286
 
@@ -156,7 +156,7 @@ function getMonsterVersion() {
156
156
  }
157
157
 
158
158
  /** don't touch, replaced by make with package.json version */
159
- monsterVersion = new Version("4.118.0");
159
+ monsterVersion = new Version("4.120.0");
160
160
 
161
161
  return monsterVersion;
162
162
  }
@@ -7,7 +7,7 @@ describe('Monster', function () {
7
7
  let monsterVersion
8
8
 
9
9
  /** don´t touch, replaced by make with package.json version */
10
- monsterVersion = new Version("4.118.0")
10
+ monsterVersion = new Version("4.120.0")
11
11
 
12
12
  let m = getMonsterVersion();
13
13
 
@@ -9,8 +9,8 @@
9
9
  </head>
10
10
  <body>
11
11
  <div id="headline" style="display: flex;align-items: center;justify-content: center;flex-direction: column;">
12
- <h1 style='margin-bottom: 0.1em;'>Monster 4.118.0</h1>
13
- <div id="lastupdate" style='font-size:0.7em'>last update Di 3. Feb 17:02:29 CET 2026</div>
12
+ <h1 style='margin-bottom: 0.1em;'>Monster 4.120.0</h1>
13
+ <div id="lastupdate" style='font-size:0.7em'>last update Do 12. Feb 21:50:57 CET 2026</div>
14
14
  </div>
15
15
  <div id="mocha-errors"
16
16
  style="color: red;font-weight: bold;display: flex;align-items: center;justify-content: center;flex-direction: column;margin:20px;"></div>