From 3c507195b19128753366bcf352a33865fb85b71a Mon Sep 17 00:00:00 2001
From: Volker Schukai <volker.schukai@schukai.com>
Date: Sun, 22 Dec 2024 15:54:43 +0100
Subject: [PATCH] feat(log): auto update timestamp #270

---
 development/issues/{open => closed}/270.html |   6 +-
 development/issues/{open => closed}/270.mjs  |  11 +
 source/components/state/log.mjs              | 397 ++++++++++---------
 source/components/state/style/log.pcss       |  45 ++-
 source/components/state/stylesheet/log.mjs   |   2 +-
 source/types/validate.mjs                    |   1 +
 6 files changed, 250 insertions(+), 212 deletions(-)
 rename development/issues/{open => closed}/270.html (77%)
 rename development/issues/{open => closed}/270.mjs (88%)

diff --git a/development/issues/open/270.html b/development/issues/closed/270.html
similarity index 77%
rename from development/issues/open/270.html
rename to development/issues/closed/270.html
index 7b0659cde..5d6b58e64 100644
--- a/development/issues/open/270.html
+++ b/development/issues/closed/270.html
@@ -4,10 +4,10 @@
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>update and optimize data-bind #270</title>
-    <script src="./270.mjs" type="module"></script>
+    <script src="270.mjs" type="module"></script>
 </head>
 <body>
-    <h1>update and optimize data-bind #270</h1>
+    <h1>update and optimize log #270</h1>
     <p></p>
     <ul>
         <li><a href="https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/270">Issue #270</a></li>
@@ -18,7 +18,7 @@
 <monster-log id="Bai3A">
 
 </monster-log>
-
+        <p>This is an example of a log element.</p>
     </main>
 </body>
 </html>
diff --git a/development/issues/open/270.mjs b/development/issues/closed/270.mjs
similarity index 88%
rename from development/issues/open/270.mjs
rename to development/issues/closed/270.mjs
index 53d2603d1..04b9b8c6e 100644
--- a/development/issues/open/270.mjs
+++ b/development/issues/closed/270.mjs
@@ -44,3 +44,14 @@ for1Year2MonthsAnd3DaysDate.setMonth(for1Year2MonthsAnd3DaysDate.getMonth() - 2)
 for1Year2MonthsAnd3DaysDate.setDate(for1Year2MonthsAnd3DaysDate.getDate() - 3);
 
 element.addEntry(new Entry({title: "Test", message: "Test", user: "Administrator", date: for1Year2MonthsAnd3DaysDate}))
+
+
+setTimeout(() => {
+    element.addEntry(new Entry({title: "Test", message: "Test", user: "Administrator", date: new Date()}))
+
+
+    setTimeout(() => {
+        element.addEntry(new Entry({title: "Test", message: "Test", user: "Administrator", date: new Date()}))
+    }, 3000);
+
+}, 3000);
\ No newline at end of file
diff --git a/source/components/state/log.mjs b/source/components/state/log.mjs
index 2d9b15fd3..9a4a40874 100644
--- a/source/components/state/log.mjs
+++ b/source/components/state/log.mjs
@@ -12,19 +12,20 @@
  * SPDX-License-Identifier: AGPL-3.0
  */
 
-import { instanceSymbol } from "../../constants.mjs";
+import {instanceSymbol} from "../../constants.mjs";
 import {
-	assembleMethodSymbol,
-	CustomElement,
-	getSlottedElements,
-	registerCustomElement,
+    assembleMethodSymbol,
+    CustomElement,
+    getSlottedElements,
+    registerCustomElement,
 } from "../../dom/customelement.mjs";
-import { LogStyleSheet } from "./stylesheet/log.mjs";
-import { Entry } from "./log/entry.mjs";
+import {LogStyleSheet} from "./stylesheet/log.mjs";
+import {Entry} from "./log/entry.mjs";
 import {validateInstance, validateString} from "../../types/validate.mjs";
 import "./state.mjs";
+import {getWindow} from "../../dom/util.mjs";
 
-export { Log };
+export {Log};
 
 /**
  * @private
@@ -45,133 +46,148 @@ const emptyStateElementSymbol = Symbol("emptyStateElement");
  *
  * @example /examples/components/state/log-simple
  *
+ * @issue https://localhost.alvine.dev:8444/development/issues/closed/270.html
+ *
  * @since 3.74.0
  * @copyright schukai GmbH
  * @summary The log entry is a single entry in the log.
  **/
 class Log extends CustomElement {
-	/**
-	 * @return {void}
-	 */
-	[assembleMethodSymbol]() {
-		super[assembleMethodSymbol]();
-
-		initControlReferences.call(this);
-		initEventHandler.call(this);
-	}
-
-	/**
-	 * This method is called by the `instanceof` operator.
-	 * @return {symbol}
-	 */
-	static get [instanceSymbol]() {
-		return Symbol.for("@schukai/monster/components/state/log@@instance");
-	}
-
-	/**
-	 * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
-	 * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
-	 *
-	 * The individual configuration values can be found in the table.
-	 *
-	 * @property {Object} templates Template definitions
-	 * @property {string} templates.main Main template
-	 * @property {Object} labels Labels
-	 * @property {string} labels.nothingToReport Label for empty state
-	 */
-	get defaults() {
-		return Object.assign({}, super.defaults, {
-			templates: {
-				main: getTemplate(),
-			},
-
-			labels: {
-				nothingToReport: "There is nothing to report yet.",
-			},
-
-			entries: [],
-		});
-	}
-
-	/**
-	 * @return {void}
-	 */
-	connectedCallback() {
-		super.connectedCallback();
-
-		const slottedElements = getSlottedElements.call(this);
-		if (slottedElements.size > 0) {
-			this[emptyStateElementSymbol].style.display = "none";
-		}
-	}
-
-	/**
-	 * Clear the log
-	 *
-	 * @return {Log}
-	 */
-	clear() {
-		this[logElementSymbol].innerHTML = "";
-		this[emptyStateElementSymbol].style.display = "block";
-		return this;
-	}
-
-	/**
-	 * Add an entry to the log
-	 * @param {Entry} entry
-	 * @return {Log}
-	 */
-	addEntry(entry) {
-		validateInstance(entry, Entry);
-
-		const entries = this.getOption("entries");
-		entries.push(entry);
-
-		/** this field is not used, but triggers a change event */
-		this.setOption("length", entries.length - 1);
-
-		return this;
-	}
-
-	/**
-	 * Add a log message
-	 *
-	 * @param {string} message
-	 * @param {Date} date
-	 * @return {Log}
-	 * @throws {TypeError} message is not a string
-	 */
-	addMessage(message, date) {
-		if (!date) {
-			date = new Date();
-		}
-
-		validateString(message);
-
-		this.addEntry(
-			new Entry({
-				message: message,
-				date: date,
-			}),
-		);
-
-		return this;
-	}
-
-	/**
-	 *
-	 * @return {string}
-	 */
-	static getTag() {
-		return "monster-log";
-	}
-
-	/**
-	 * @return {CSSStyleSheet[]}
-	 */
-	static getCSSStyleSheet() {
-		return [LogStyleSheet];
-	}
+    /**
+     * @return {void}
+     */
+    [assembleMethodSymbol]() {
+        super[assembleMethodSymbol]();
+
+        initControlReferences.call(this);
+        initEventHandler.call(this);
+    }
+
+    /**
+     * This method is called by the `instanceof` operator.
+     * @return {symbol}
+     */
+    static get [instanceSymbol]() {
+        return Symbol.for("@schukai/monster/components/state/log@@instance");
+    }
+
+    /**
+     * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
+     * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
+     *
+     * The individual configuration values can be found in the table.
+     *
+     * @property {Object} templates Template definitions
+     * @property {string} templates.main Main template
+     * @property {Object} labels Labels
+     * @property {string} labels.nothingToReport Label for empty state
+     * @property {number} updateFrequency Update frequency in milliseconds for the timestamp
+     */
+    get defaults() {
+        return Object.assign({}, super.defaults, {
+            templates: {
+                main: getTemplate(),
+            },
+
+            labels: {
+                nothingToReport: "There is nothing to report yet.",
+            },
+
+            classes: {
+                direction: "vertical",
+            },
+
+            updateFrequency: 10000,
+
+            entries: [],
+
+            timestamp: 0,
+        });
+    }
+
+    /**
+     * @return {void}
+     */
+    connectedCallback() {
+        super.connectedCallback();
+
+        const slottedElements = getSlottedElements.call(this);
+        if (slottedElements.size > 0) {
+            this[emptyStateElementSymbol].style.display = "none";
+        }
+    }
+
+    /**
+     * Clear the log
+     *
+     * @return {Log}
+     */
+    clear() {
+        this[logElementSymbol].innerHTML = "";
+        this[emptyStateElementSymbol].style.display = "block";
+        return this;
+    }
+
+    /**
+     * Add an entry to the log
+     * @param {Entry} entry
+     * @return {Log}
+     */
+    addEntry(entry) {
+        validateInstance(entry, Entry);
+
+        if (entry.date === undefined || entry.date === null) {
+            entry.date = new Date();
+        }
+
+        const entries = this.getOption("entries");
+        entries.push(entry);
+
+        /** this field is not used, but triggers a change event */
+        this.setOption("length", entries.length - 1);
+
+        return this;
+    }
+
+    /**
+     * Add a log message
+     *
+     * @param {string} message
+     * @param {Date} date
+     * @return {Log}
+     * @throws {TypeError} message is not a string
+     */
+    addMessage(message, date) {
+        if (!date) {
+            date = new Date();
+        }
+
+        validateString(message);
+
+        this.addEntry(
+            new Entry({
+                message: message,
+                date: date,
+            }),
+        );
+
+        return this;
+    }
+
+    /**
+     *
+     * @return {string}
+     */
+    static getTag() {
+        return "monster-log";
+    }
+
+    /**
+     * @return {CSSStyleSheet[]}
+     */
+    static getCSSStyleSheet() {
+        return [LogStyleSheet];
+    }
 }
 
 /**
@@ -180,37 +196,44 @@ class Log extends CustomElement {
  * @throws {Error} no shadow-root is defined
  */
 function initControlReferences() {
-	if (!this.shadowRoot) {
-		throw new Error("no shadow-root is defined");
-	}
-
-	this[logElementSymbol] = this.shadowRoot.querySelector(
-		"[data-monster-role=control]",
-	);
-	this[emptyStateElementSymbol] = this.shadowRoot.querySelector(
-		"[data-monster-role=empty-state]",
-	);
+    if (!this.shadowRoot) {
+        throw new Error("no shadow-root is defined");
+    }
+
+    this[logElementSymbol] = this.shadowRoot.querySelector(
+        "[data-monster-role=control]",
+    );
+    this[emptyStateElementSymbol] = this.shadowRoot.querySelector(
+        "[data-monster-role=empty-state]",
+    );
 }
 
 /**
  * @private
  */
 function initEventHandler() {
-	if (!this.shadowRoot) {
-		throw new Error("no shadow-root is defined");
-	}
-
-	this.shadowRoot.addEventListener("slotchange", (event) => {
-		const slottedElements = getSlottedElements.call(this);
-
-		if (slottedElements.size > 0) {
-			this[emptyStateElementSymbol].style.display = "none";
-		} else {
-			this[emptyStateElementSymbol].style.display = "block";
-		}
-	});
-
-	return this;
+    if (!this.shadowRoot) {
+        throw new Error("no shadow-root is defined");
+    }
+
+    this.shadowRoot.addEventListener("slotchange", (event) => {
+        const slottedElements = getSlottedElements.call(this);
+
+        if (slottedElements.size > 0) {
+            this[emptyStateElementSymbol].style.display = "none";
+        } else {
+            this[emptyStateElementSymbol].style.display = "block";
+        }
+    });
+
+    setInterval(() => {
+        getWindow().requestAnimationFrame(() => {
+            const timestamp = (new Date()).toTimeString();
+            this.setOption("timestamp", timestamp);
+        });
+    }, this.getOption("updateFrequency"));
+
+    return this;
 }
 
 /**
@@ -218,41 +241,43 @@ function initEventHandler() {
  * @return {string}
  */
 function getTemplate() {
-	// language=HTML
-	return `<template id="entry">
-    <li data-monster-role="entry">
+    // language=HTML
+    return `
+        <template id="entry">
+            <li data-monster-role="entry">
         <span data-monster-replace="path:entry.user"
               data-monster-attributes="class path:entry.user | ?:user:hidden"></span>
-        <span data-monster-replace="path:entry.title"
-              data-monster-attributes="class path:entry.title | ?:title:hidden"></span>
-        <span data-monster-replace="path:entry.message"
-              data-monster-attributes="class path:entry.message | ?:message:hidden"></span>
-        <span data-monster-replace="path:entry.date | time-ago" data-monster-attributes="title path:entry.date | datetime"></span>
-        
-    </li>
-</template>
-
-<div part="control" data-monster-role="control">
-    <div data-monster-role="empty-state" data-monster-attributes="class path:entries | has-entries | ?:hidden:">
-        <monster-state>
-            <div part="visual">
-                <svg width="4rem" height="4rem" viewBox="0 -12 512.00032 512"
-                     xmlns="http://www.w3.org/2000/svg">
-                    <path d="m455.074219 172.613281 53.996093-53.996093c2.226563-2.222657 3.273438-5.367188 2.828126-8.480469-.441407-3.113281-2.328126-5.839844-5.085938-7.355469l-64.914062-35.644531c-4.839844-2.65625-10.917969-.886719-13.578126 3.953125-2.65625 4.84375-.890624 10.921875 3.953126 13.578125l53.234374 29.230469-46.339843 46.335937-166.667969-91.519531 46.335938-46.335938 46.839843 25.722656c4.839844 2.65625 10.921875.890626 13.578125-3.953124 2.660156-4.839844.890625-10.921876-3.953125-13.578126l-53.417969-29.335937c-3.898437-2.140625-8.742187-1.449219-11.882812 1.695313l-54 54-54-54c-3.144531-3.144532-7.988281-3.832032-11.882812-1.695313l-184.929688 101.546875c-2.757812 1.515625-4.644531 4.238281-5.085938 7.355469-.445312 3.113281.601563 6.257812 2.828126 8.480469l53.996093 53.996093-53.996093 53.992188c-2.226563 2.226562-3.273438 5.367187-2.828126 8.484375.441407 3.113281 2.328126 5.839844 5.085938 7.351562l55.882812 30.6875v102.570313c0 3.652343 1.988282 7.011719 5.1875 8.769531l184.929688 101.542969c1.5.824219 3.15625 1.234375 4.8125 1.234375s3.3125-.410156 4.8125-1.234375l184.929688-101.542969c3.199218-1.757812 5.1875-5.117188 5.1875-8.769531v-102.570313l55.882812-30.683594c2.757812-1.515624 4.644531-4.242187 5.085938-7.355468.445312-3.113282-.601563-6.257813-2.828126-8.480469zm-199.074219 90.132813-164.152344-90.136719 164.152344-90.140625 164.152344 90.140625zm-62.832031-240.367188 46.332031 46.335938-166.667969 91.519531-46.335937-46.335937zm-120.328125 162.609375 166.667968 91.519531-46.339843 46.339844-166.671875-91.519531zm358.089844 184.796875-164.929688 90.5625v-102.222656c0-5.523438-4.476562-10-10-10s-10 4.476562-10 10v102.222656l-164.929688-90.5625v-85.671875l109.046876 59.878907c1.511718.828124 3.167968 1.234374 4.808593 1.234374 2.589844 0 5.152344-1.007812 7.074219-2.929687l54-54 54 54c1.921875 1.925781 4.484375 2.929687 7.074219 2.929687 1.640625 0 3.296875-.40625 4.808593-1.234374l109.046876-59.878907zm-112.09375-46.9375-46.339844-46.34375 166.667968-91.515625 46.34375 46.335938zm0 0"/>
-                    <path d="m404.800781 68.175781c2.628907 0 5.199219-1.070312 7.070313-2.933593 1.859375-1.859376 2.929687-4.4375 2.929687-7.066407 0-2.632812-1.070312-5.210937-2.929687-7.070312-1.859375-1.863281-4.441406-2.929688-7.070313-2.929688-2.640625 0-5.210937 1.066407-7.070312 2.929688-1.871094 1.859375-2.929688 4.4375-2.929688 7.070312 0 2.628907 1.058594 5.207031 2.929688 7.066407 1.859375 1.863281 4.441406 2.933593 7.070312 2.933593zm0 0"/>
-                    <path d="m256 314.925781c-2.628906 0-5.210938 1.066407-7.070312 2.929688-1.859376 1.867187-2.929688 4.4375-2.929688 7.070312 0 2.636719 1.070312 5.207031 2.929688 7.078125 1.859374 1.859375 4.441406 2.921875 7.070312 2.921875s5.210938-1.0625 7.070312-2.921875c1.859376-1.871094 2.929688-4.441406 2.929688-7.078125 0-2.632812-1.070312-5.203125-2.929688-7.070312-1.859374-1.863281-4.441406-2.929688-7.070312-2.929688zm0 0"/>
-                </svg>
+                <span data-monster-replace="path:entry.title"
+                      data-monster-attributes="class path:entry.title | ?:title:hidden"></span>
+                <span data-monster-replace="path:entry.message"
+                      data-monster-attributes="class path:entry.message | ?:message:hidden"></span>
+                <span data-monster-replace="path:entry.date | time-ago"
+                      data-monster-attributes="title path:entry.date | datetime"></span>
+
+            </li>
+        </template>
+
+        <div part="control" data-monster-role="control">
+            <div data-monster-role="empty-state" data-monster-attributes="class path:entries | has-entries | ?:hidden:">
+                <monster-state>
+                    <div part="visual">
+                        <svg width="4rem" height="4rem" viewBox="0 -12 512.00032 512"
+                             xmlns="http://www.w3.org/2000/svg">
+                            <path d="m455.074219 172.613281 53.996093-53.996093c2.226563-2.222657 3.273438-5.367188 2.828126-8.480469-.441407-3.113281-2.328126-5.839844-5.085938-7.355469l-64.914062-35.644531c-4.839844-2.65625-10.917969-.886719-13.578126 3.953125-2.65625 4.84375-.890624 10.921875 3.953126 13.578125l53.234374 29.230469-46.339843 46.335937-166.667969-91.519531 46.335938-46.335938 46.839843 25.722656c4.839844 2.65625 10.921875.890626 13.578125-3.953124 2.660156-4.839844.890625-10.921876-3.953125-13.578126l-53.417969-29.335937c-3.898437-2.140625-8.742187-1.449219-11.882812 1.695313l-54 54-54-54c-3.144531-3.144532-7.988281-3.832032-11.882812-1.695313l-184.929688 101.546875c-2.757812 1.515625-4.644531 4.238281-5.085938 7.355469-.445312 3.113281.601563 6.257812 2.828126 8.480469l53.996093 53.996093-53.996093 53.992188c-2.226563 2.226562-3.273438 5.367187-2.828126 8.484375.441407 3.113281 2.328126 5.839844 5.085938 7.351562l55.882812 30.6875v102.570313c0 3.652343 1.988282 7.011719 5.1875 8.769531l184.929688 101.542969c1.5.824219 3.15625 1.234375 4.8125 1.234375s3.3125-.410156 4.8125-1.234375l184.929688-101.542969c3.199218-1.757812 5.1875-5.117188 5.1875-8.769531v-102.570313l55.882812-30.683594c2.757812-1.515624 4.644531-4.242187 5.085938-7.355468.445312-3.113282-.601563-6.257813-2.828126-8.480469zm-199.074219 90.132813-164.152344-90.136719 164.152344-90.140625 164.152344 90.140625zm-62.832031-240.367188 46.332031 46.335938-166.667969 91.519531-46.335937-46.335937zm-120.328125 162.609375 166.667968 91.519531-46.339843 46.339844-166.671875-91.519531zm358.089844 184.796875-164.929688 90.5625v-102.222656c0-5.523438-4.476562-10-10-10s-10 4.476562-10 10v102.222656l-164.929688-90.5625v-85.671875l109.046876 59.878907c1.511718.828124 3.167968 1.234374 4.808593 1.234374 2.589844 0 5.152344-1.007812 7.074219-2.929687l54-54 54 54c1.921875 1.925781 4.484375 2.929687 7.074219 2.929687 1.640625 0 3.296875-.40625 4.808593-1.234374l109.046876-59.878907zm-112.09375-46.9375-46.339844-46.34375 166.667968-91.515625 46.34375 46.335938zm0 0"/>
+                            <path d="m404.800781 68.175781c2.628907 0 5.199219-1.070312 7.070313-2.933593 1.859375-1.859376 2.929687-4.4375 2.929687-7.066407 0-2.632812-1.070312-5.210937-2.929687-7.070312-1.859375-1.863281-4.441406-2.929688-7.070313-2.929688-2.640625 0-5.210937 1.066407-7.070312 2.929688-1.871094 1.859375-2.929688 4.4375-2.929688 7.070312 0 2.628907 1.058594 5.207031 2.929688 7.066407 1.859375 1.863281 4.441406 2.933593 7.070312 2.933593zm0 0"/>
+                            <path d="m256 314.925781c-2.628906 0-5.210938 1.066407-7.070312 2.929688-1.859376 1.867187-2.929688 4.4375-2.929688 7.070312 0 2.636719 1.070312 5.207031 2.929688 7.078125 1.859374 1.859375 4.441406 2.921875 7.070312 2.921875s5.210938-1.0625 7.070312-2.921875c1.859376-1.871094 2.929688-4.441406 2.929688-7.078125 0-2.632812-1.070312-5.203125-2.929688-7.070312-1.859374-1.863281-4.441406-2.929688-7.070312-2.929688zm0 0"/>
+                        </svg>
+                    </div>
+                    <div part="content" data-monster-replace="path:labels.nothingToReport">
+                        There is nothing to report yet.
+                    </div>
+                </monster-state>
             </div>
-            <div part="content" data-monster-replace="path:labels.nothingToReport">
-                There is nothing to report yet.
+            <div data-monster-role="entries">
+                <ul data-monster-insert="entry path:entries">
+                </ul>
             </div>
-        </monster-state>
-    </div>
-    <div data-monster-role="entries">
-        <ul data-monster-insert="entry path:entries">
-        </ul>
-    </div>
-</div>
+        </div>
     `;
 }
 
diff --git a/source/components/state/style/log.pcss b/source/components/state/style/log.pcss
index 9fb652e60..89508bf78 100644
--- a/source/components/state/style/log.pcss
+++ b/source/components/state/style/log.pcss
@@ -8,55 +8,56 @@
 @import "../../style/mixin/hover.pcss";
 
 [data-monster-role=entries] {
-
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+    border: 0;
+    padding: 0;
+    margin: 0;
+    box-sizing: border-box;
+    position: relative;
 
     & ul {
         list-style-type: none;
         margin: 0;
-        padding: 0 0 0 1.8rem;
-        position: relative;
-        top: 0
+        padding: 0 0 0 1.8rem; /* Abstand links behalten */
+        width: 100%; /* Flex-Container-Anpassung */
     }
 
     & ul:before {
         content: "";
         display: block;
-        width: 0;
+        width: 2px;
         height: 100%;
-        border: 1px dashed var(--monster-color-primary-2);
+
+        border-left-color: var(--monster-bg-color-primary-3);
+        border-left-style: dotted;
+        border-left-width: 1px;
         position: absolute;
-        top: 0;
         left: 1rem;
-    }
-
-    .title {
-        font-weight: bold;
+        bottom: 0;
+        top: 0;
     }
 
     & ul li {
         margin: 0;
-        position: relative;
         padding: 0.1rem 0.3rem;
         color: var(--monster-color-primary-1);
         background-color: var(--monster-bg-color-primary-1);
         border-radius: 5px;
+        position: relative;
     }
 
-
     & ul li:before {
         content: "";
-        display: block;
-        width: 5px;
-        height: 5px;
+        width: 6px;
+        height: 6px;
+        box-sizing: border-box;
         border-radius: 50%;
         background: var(--monster-bg-color-primary-3);
         border: 1px solid var(--monster-color-primary-2);
         position: absolute;
-        left: -0.9rem;
+        left: calc(-1rem + (5px / 4));
         top: 0.6rem;
     }
-
-
-
-
-}
\ No newline at end of file
+}
diff --git a/source/components/state/stylesheet/log.mjs b/source/components/state/stylesheet/log.mjs
index fcf5bbfb4..f3b351e3f 100644
--- a/source/components/state/stylesheet/log.mjs
+++ b/source/components/state/stylesheet/log.mjs
@@ -24,7 +24,7 @@ const LogStyleSheet = new CSSStyleSheet();
 try {
   LogStyleSheet.insertRule(`
 @layer log { 
-[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] ul{list-style-type:none;margin:0;padding:0 0 0 1.8rem;position:relative;top:0}[data-monster-role=entries] ul:before{border:1px dashed var(--monster-color-primary-2);content:\"\";display:block;height:100%;left:1rem;position:absolute;top:0;width:0}[data-monster-role=entries] .title{font-weight:700}[data-monster-role=entries] ul li{background-color:var(--monster-bg-color-primary-1);border-radius:5px;color:var(--monster-color-primary-1);margin:0;padding:.1rem .3rem;position:relative}[data-monster-role=entries] ul li:before{background:var(--monster-bg-color-primary-3);border:1px solid var(--monster-color-primary-2);border-radius:50%;content:\"\";display:block;height:5px;left:-.9rem;position:absolute;top:.6rem;width:5px} 
+[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 1.8rem;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=entries] ul li{background-color:var(--monster-bg-color-primary-1);border-radius:5px;color:var(--monster-color-primary-1);margin:0;padding:.1rem .3rem;position:relative}[data-monster-role=entries] ul li: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 + 1.25px);position:absolute;top:.6rem;width:6px} 
 }`, 0);
 } catch (e) {
   addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + "");
diff --git a/source/types/validate.mjs b/source/types/validate.mjs
index 9b99b6058..f2ebafcee 100644
--- a/source/types/validate.mjs
+++ b/source/types/validate.mjs
@@ -185,6 +185,7 @@ function validateObject(value) {
  * ```
  *
  * @param {*} value
+ * @param {object} instance
  * @return {*}
  * @license AGPLv3
  * @since 1.5.0
-- 
GitLab