From 1e45953b05da8177ceab6b13151fe8dbeb39704e Mon Sep 17 00:00:00 2001
From: Volker Schukai <volker.schukai@schukai.com>
Date: Sat, 13 Apr 2024 18:27:44 +0200
Subject: [PATCH] feat: new toc component #188

---
 .../scripts/createNewComponentClass.mjs       |   3 +-
 .../navigation/table-of-content.mjs           |   4 +
 .../components/navigation/design.html         |  22 +++
 .../components/navigation/overview.html       |  44 +++++
 .../components/navigation/show-it.html        |   2 +
 .../navigation/style/table-of-content.pcss    |   0
 .../stylesheet/table-of-content.mjs           |  31 +++
 .../navigation/table-of-content.mjs           | 177 ++++++++++++++++++
 8 files changed, 282 insertions(+), 1 deletion(-)
 create mode 100644 showroom/source/examples/components/navigation/table-of-content.mjs
 create mode 100644 showroom/source/fragments/components/navigation/design.html
 create mode 100644 showroom/source/fragments/components/navigation/overview.html
 create mode 100644 showroom/source/fragments/components/navigation/show-it.html
 create mode 100644 source/components/navigation/style/table-of-content.pcss
 create mode 100644 source/components/navigation/stylesheet/table-of-content.mjs
 create mode 100644 source/components/navigation/table-of-content.mjs

diff --git a/development/scripts/createNewComponentClass.mjs b/development/scripts/createNewComponentClass.mjs
index 5beafd8c7..b606e9953 100644
--- a/development/scripts/createNewComponentClass.mjs
+++ b/development/scripts/createNewComponentClass.mjs
@@ -28,6 +28,7 @@ import {
 	ATTRIBUTE_ROLE,
 } from "{{BACK_TO_ROOT_PATH}}/dom/constants.mjs";
 import { CustomControl } from "{{BACK_TO_ROOT_PATH}}/dom/customcontrol.mjs";
+import { CustomElement } from "{{BACK_TO_ROOT_PATH}}/dom/customelement.mjs";
 import {
 	assembleMethodSymbol,
 	registerCustomElement,
@@ -62,7 +63,7 @@ export const {{CLASSNAME_LOWER_FIRST}}ElementSymbol = Symbol("{{CLASSNAME_LOWER_
 	 * @returns {symbol}
 	 */
 	static get [instanceSymbol]() {
-		return Symbol.for("@schukai/monster/{{NAMESPACE_AS_PATH}}/{{CLASSNAME_LOWER}}@@instance");
+		return Symbol.for("@schukai/monster/{{NAMESPACE_AS_PATH}}/{{HTML_TAG_SUFFIX}}@@instance");
 	}
 
 	/**
diff --git a/showroom/source/examples/components/navigation/table-of-content.mjs b/showroom/source/examples/components/navigation/table-of-content.mjs
new file mode 100644
index 000000000..ef65203c4
--- /dev/null
+++ b/showroom/source/examples/components/navigation/table-of-content.mjs
@@ -0,0 +1,4 @@
+import "@schukai/monster/source/components/navigation/table-of-content.mjs";
+const element = document.createElement('monster-table-of-content');
+element.setOption('disable', 'false')
+document.body.appendChild(element);
diff --git a/showroom/source/fragments/components/navigation/design.html b/showroom/source/fragments/components/navigation/design.html
new file mode 100644
index 000000000..6fd96361e
--- /dev/null
+++ b/showroom/source/fragments/components/navigation/design.html
@@ -0,0 +1,22 @@
+
+    <h2>Design</h2>
+    <p>The control element can be adapted to your own requirements. To do this, the control element
+       can be designed with CSS like almost any other HTML element.</p>
+
+    <p>However, there are a few things to bear in mind. As the innards of the control are located
+    in a ShadowRoot, they cannot be accessed directly with CSS selectors. Only the elements specified
+    for this purpose can be accessed. These elements have the attribute <i>part</i>.</p>
+
+    <p>In CSS, these parts can then be used for styling via a CSS pseudo-element Parts.
+    Here you can see an example of how you can use this.</p>
+
+    <pre><code class="language-css">
+    ::part(container) {
+        border: 1px solid red;
+    }
+    </code></pre>
+
+    <!-- p>The following diagram shows the parts and the slots.</p>
+
+    <img src="assets/Components.Navigation.{{CLASSNAME_LOWER}}.svg" alt="Parts and slots of the TableOfContent"-->
+    
\ No newline at end of file
diff --git a/showroom/source/fragments/components/navigation/overview.html b/showroom/source/fragments/components/navigation/overview.html
new file mode 100644
index 000000000..b774ec0a4
--- /dev/null
+++ b/showroom/source/fragments/components/navigation/overview.html
@@ -0,0 +1,44 @@
+
+<h2>Introduction</h2>
+<p>
+    This is the Monster TableOfContent component. It is a versatile and customizable control element
+    to an interactive and engaging user experience that integrates seamlessly into various web applications.
+    Whether you are developing a simple website or a complex enterprise application, the Monster
+    Button is designed to increase user interaction and satisfaction.  
+</p>
+
+<h2>Key Features</h2>
+<ul>
+    <li><strong>Dynamic interaction</strong>: Users can interact with content dynamically,
+        making the Web experience more intuitive and user-centric.
+    </li>
+    <li><strong>Customizable appearance</strong>: Customize the appearance of the button
+        to match the design of your brand or application to improve visual consistency.
+    </li>
+    <li><strong>Accessibility</strong>: Designed with accessibility in mind to ensure all
+        users have a seamless experience regardless of their browsing context.
+    </li>
+    <li><strong>Programmatic Control</strong>: Provides methods such as click, focus,
+        and blur to programmatically control the behavior of the button, giving developers flexibility.
+    </li>
+</ul>
+
+<h2>Improving the user experience</h2>
+<p>
+    The Monster TableOfContent goes beyond the traditional functions of a TableOfContent  to provide an enhanced
+    and interactive user experience. 
+</p>
+
+<p>
+    These improvements are supported by user studies that show a positive impact on user
+    commitment and satisfaction.
+</p>
+
+<h2>Efficiency in the development process</h2>
+<p>
+    Integrating the Monster TableOfContent into your development process is easy. Its compatibility with
+    standard web technologies and ease of customization allow for seamless integration with
+    your existing tools and libraries. Whether you are working on a small project or a large
+    application, Monster TableOfContent's modular design guarantees easy integration that streamlines
+    your development process and increases your productivity.
+</p>
diff --git a/showroom/source/fragments/components/navigation/show-it.html b/showroom/source/fragments/components/navigation/show-it.html
new file mode 100644
index 000000000..fac442c40
--- /dev/null
+++ b/showroom/source/fragments/components/navigation/show-it.html
@@ -0,0 +1,2 @@
+
+<monster-table-of-content></monster-table-of-content>
diff --git a/source/components/navigation/style/table-of-content.pcss b/source/components/navigation/style/table-of-content.pcss
new file mode 100644
index 000000000..e69de29bb
diff --git a/source/components/navigation/stylesheet/table-of-content.mjs b/source/components/navigation/stylesheet/table-of-content.mjs
new file mode 100644
index 000000000..798ef9312
--- /dev/null
+++ b/source/components/navigation/stylesheet/table-of-content.mjs
@@ -0,0 +1,31 @@
+/**
+ * Copyright © schukai GmbH and all contributing authors, 2024. All rights reserved.
+ * Node module: @schukai/monster
+ *
+ * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
+ * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
+ *
+ * For those who do not wish to adhere to the AGPLv3, a commercial license is available.
+ * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
+ * For more information about purchasing a commercial license, please contact schukai GmbH.
+ */
+
+import {addAttributeToken} from "../../../dom/attributes.mjs";
+import {ATTRIBUTE_ERRORMESSAGE} from "../../../dom/constants.mjs";
+
+export {TableOfContentStyleSheet}
+
+/**
+ * @private
+ * @type {CSSStyleSheet}
+ */
+const TableOfContentStyleSheet = new CSSStyleSheet();
+
+try {
+  TableOfContentStyleSheet.insertRule(`
+@layer tableofcontent { 
+ 
+}`, 0);
+} catch (e) {
+  addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + "");
+}
diff --git a/source/components/navigation/table-of-content.mjs b/source/components/navigation/table-of-content.mjs
new file mode 100644
index 000000000..da8af84a6
--- /dev/null
+++ b/source/components/navigation/table-of-content.mjs
@@ -0,0 +1,177 @@
+/**
+ * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
+ * Node module: @schukai/monster
+ *
+ * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
+ * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
+ *
+ * For those who do not wish to adhere to the AGPLv3, a commercial license is available.
+ * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
+ * For more information about purchasing a commercial license, please contact schukai GmbH.
+ */
+
+import {instanceSymbol} from "../../constants.mjs";
+import {addAttributeToken} from "../../dom/attributes.mjs";
+import {
+    ATTRIBUTE_ERRORMESSAGE,
+    ATTRIBUTE_ROLE,
+} from "../../dom/constants.mjs";
+import {CustomElement} from "../../dom/customelement.mjs";
+import {
+    assembleMethodSymbol,
+    registerCustomElement,
+} from "../../dom/customelement.mjs";
+import {findTargetElementFromEvent} from "../../dom/events.mjs";
+import {isFunction} from "../../types/is.mjs";
+import {TableOfContentStyleSheet} from "./stylesheet/table-of-content.mjs";
+import {fireCustomEvent} from "../../dom/events.mjs";
+
+export {TableOfContent};
+
+/**
+ * @private
+ * @type {symbol}
+ */
+export const tableOfContentElementSymbol = Symbol("tableOfContentElement");
+
+/**
+ * A TableOfContent
+ *
+ * @fragments /fragments/components/form/table-of-content/
+ *
+ * @example /examples/components/form/table-of-content-simple
+ *
+ * @since 3.66.0
+ * @copyright schukai GmbH
+ * @summary A beautiful TableOfContent that can make your life easier and also looks good.
+ */
+class TableOfContent extends CustomElement {
+    /**
+     * This method is called by the `instanceof` operator.
+     * @returns {symbol}
+     */
+    static get [instanceSymbol]() {
+        return Symbol.for("@schukai/monster/components/navigation/table-of-content@@instance");
+    }
+
+    /**
+     *
+     * @return {Components.Navigation.TableOfContent
+     */
+    [assembleMethodSymbol]() {
+        super[assembleMethodSymbol]();
+        initControlReferences.call(this);
+        initEventHandler.call(this);
+        return this;
+    }
+
+    /**
+     * 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 Label definitions
+     * @property {Object} actions Callbacks
+     * @property {string} actions.click="throw Error" Callback when clicked
+     * @property {Object} features Features
+     * @property {Object} classes CSS classes
+     * @property {boolean} disabled=false Disabled state
+     */
+    get defaults() {
+        return Object.assign({}, super.defaults, {
+            templates: {
+                main: getTemplate(),
+            },
+            labels: {},
+            classes: {},
+            disabled: false,
+            features: {},
+            actions: {
+                click: () => {
+                    throw new Error("the click action is not defined");
+                },
+            }
+        });
+    }
+
+    /**
+     * @return {string}
+     */
+    static getTag() {
+        return "monster-table-of-content";
+    }
+
+    /**
+     * @return {CSSStyleSheet[]}
+     */
+    static getCSSStyleSheet() {
+        return [TableOfContentStyleSheet];
+    }
+
+
+}
+
+/**
+ * @private
+ * @return {initEventHandler}
+ * @fires monster-table-of-content-clicked
+ */
+function initEventHandler() {
+    const self = this;
+    const element = this[tableOfContentElementSymbol];
+
+    const type = "click";
+
+    element.addEventListener(type, function (event) {
+        const callback = self.getOption("actions.click");
+
+        fireCustomEvent(self, "monster-table-of-content-clicked", {
+            element: self,
+        });
+
+        if (!isFunction(callback)) {
+            return;
+        }
+
+        const element = findTargetElementFromEvent(
+            event,
+            ATTRIBUTE_ROLE,
+            "control",
+        );
+
+        if (!(element instanceof Node && self.hasNode(element))) {
+            return;
+        }
+
+        callback.call(self, event);
+    });
+
+    return this;
+}
+
+/**
+ * @private
+ * @return {void}
+ */
+function initControlReferences() {
+    this[tableOfContentElementSymbol] = this.shadowRoot.querySelector(
+        `[${ATTRIBUTE_ROLE}="control"]`,
+    );
+}
+
+/**
+ * @private
+ * @return {string}
+ */
+function getTemplate() {
+    // language=HTML
+    return `
+        <div data-monster-role="control" part="control">
+        </div>`;
+}
+
+
+registerCustomElement(TableOfContent);
-- 
GitLab