From e81ac9a3e516a9437a3f38e576a1de7e5921e1cc Mon Sep 17 00:00:00 2001
From: Jan Andrle <andrle.jan@centrum.cz>
Date: Fri, 13 Dec 2024 15:01:18 +0100
Subject: [PATCH] :abc: Improves and updates docs

- customElementRender
- introduction example
---
 README.md                                     | 21 +++++----
 dist/esm-with-signals.d.ts                    |  1 -
 dist/esm.d.ts                                 |  1 -
 docs/components/examples/customElement/dde.js |  1 -
 .../customElement/observedAttributes.js       |  1 -
 .../examples/customElement/shadowRoot.js      |  8 +---
 .../examples/customElement/simulateSlots.js   |  2 +-
 .../examples/introducing/helloWorld.js        | 44 +++++++++++++------
 .../components/mnemonic/customElement-init.js |  6 +--
 index.d.ts                                    |  1 -
 src/dom.js                                    |  1 +
 src/events.js                                 |  1 +
 12 files changed, 50 insertions(+), 38 deletions(-)

diff --git a/README.md b/README.md
index d0e3051..eae793f 100644
--- a/README.md
+++ b/README.md
@@ -8,12 +8,17 @@
 
 ```javascript
 document.body.append(
-	el(HelloWorldComponent)
+	el(HelloWorldComponent, { initial: "🚀" })
 );
-function HelloWorldComponent(){
+/** @typedef {"🎉" | "🚀"} Emoji */
+/** @param {{ initial: Emoji }} attrs */
+function HelloWorldComponent({ initial }){
 	const clicks= S(0);
-	const emoji= S("🚀");
-	const isSelected= el=> (el.selected= el.value===emoji());
+	const emoji= S(initial);
+	/** @param {HTMLOptionElement} el */
+	const isSelected= el=> (el.selected= el.value===initial);
+	// @ts-expect-error 2339: The <select> has only two options with {@link Emoji}
+	const onChange= on("change", event=> emoji(event.target.value));
 
 	return el().append(
 		el("p", {
@@ -27,11 +32,9 @@ function HelloWorldComponent(){
 			on("click", ()=> clicks(clicks() + 1)),
 			on("keyup", ()=> clicks(clicks() - 2)),
 		),
-		el("select", {
-			onchange: event=> emoji(event.target.value),
-		}).append(
-			el(OptionComponent, "🎉", isSelected),
-			el(OptionComponent, "🚀", isSelected),
+		el("select", null, onChange).append(
+			el(OptionComponent, "🎉", isSelected),//OR { textContent: "🎉" }
+			el(OptionComponent, "🚀", isSelected),//OR { textContent: "🚀" }
 		)
 	);
 }
diff --git a/dist/esm-with-signals.d.ts b/dist/esm-with-signals.d.ts
index 8780bac..7d1283d 100644
--- a/dist/esm-with-signals.d.ts
+++ b/dist/esm-with-signals.d.ts
@@ -227,7 +227,6 @@ export function customElementRender<
 	EL extends HTMLElement,
 	P extends any = Record<string, string | ddeSignal<string>>
 >(
-	custom_element: EL,
 	target: ShadowRoot | EL,
 	render: (props: P)=> SupportedElement | DocumentFragment,
 	props?: P | ((el: EL)=> P)
diff --git a/dist/esm.d.ts b/dist/esm.d.ts
index 6d1fd8a..9efeb24 100644
--- a/dist/esm.d.ts
+++ b/dist/esm.d.ts
@@ -227,7 +227,6 @@ export function customElementRender<
 	EL extends HTMLElement,
 	P extends any = Record<string, string | ddeSignal<string>>
 >(
-	custom_element: EL,
 	target: ShadowRoot | EL,
 	render: (props: P)=> SupportedElement | DocumentFragment,
 	props?: P | ((el: EL)=> P)
diff --git a/docs/components/examples/customElement/dde.js b/docs/components/examples/customElement/dde.js
index 4cde9a6..27d159c 100644
--- a/docs/components/examples/customElement/dde.js
+++ b/docs/components/examples/customElement/dde.js
@@ -7,7 +7,6 @@ export class HTMLCustomElement extends HTMLElement{
 	static observedAttributes= [ "attr" ];
 	connectedCallback(){
 		customElementRender(
-			this,
 			this.attachShadow({ mode: "open" }),
 			ddeComponent
 		);
diff --git a/docs/components/examples/customElement/observedAttributes.js b/docs/components/examples/customElement/observedAttributes.js
index 035618a..3d2583c 100644
--- a/docs/components/examples/customElement/observedAttributes.js
+++ b/docs/components/examples/customElement/observedAttributes.js
@@ -11,7 +11,6 @@ export class HTMLCustomElement extends HTMLElement{
 	connectedCallback(){
 		console.log(observedAttributes(this));
 		customElementRender(
-			this,
 			this.attachShadow({ mode: "open" }),
 			ddeComponent,
 			S.observedAttributes
diff --git a/docs/components/examples/customElement/shadowRoot.js b/docs/components/examples/customElement/shadowRoot.js
index 3aad1ae..e723944 100644
--- a/docs/components/examples/customElement/shadowRoot.js
+++ b/docs/components/examples/customElement/shadowRoot.js
@@ -17,11 +17,7 @@ function ddeComponent(){
 export class A extends HTMLElement{
 	static tagName= "custom-element-without";
 	connectedCallback(){
-		customElementRender(
-			this,
-			this,
-			ddeComponent
-		);
+		customElementRender(this, ddeComponent);
 	}
 }
 customElementWithDDE(A);
@@ -30,7 +26,6 @@ export class B extends HTMLElement{
 	static tagName= "custom-element-open";
 	connectedCallback(){
 		customElementRender(
-			this,
 			this.attachShadow({ mode: "open" }),
 			ddeComponent
 		);
@@ -42,7 +37,6 @@ export class C extends HTMLElement{
 	static tagName= "custom-element-closed";
 	connectedCallback(){
 		customElementRender(
-			this,
 			this.attachShadow({ mode: "closed" }),
 			ddeComponent
 		);
diff --git a/docs/components/examples/customElement/simulateSlots.js b/docs/components/examples/customElement/simulateSlots.js
index 59fc900..9b5bea3 100644
--- a/docs/components/examples/customElement/simulateSlots.js
+++ b/docs/components/examples/customElement/simulateSlots.js
@@ -8,7 +8,7 @@ export class HTMLCustomElement extends HTMLElement{
 	static tagName= "custom-slotting";
 	connectedCallback(){
 		const c= ()=> simulateSlots(this, ddeComponent());
-		customElementRender(this, this, c);
+		customElementRender(this, c);
 	}
 }
 customElementWithDDE(HTMLCustomElement);
diff --git a/docs/components/examples/introducing/helloWorld.js b/docs/components/examples/introducing/helloWorld.js
index 71d4340..e476f35 100644
--- a/docs/components/examples/introducing/helloWorld.js
+++ b/docs/components/examples/introducing/helloWorld.js
@@ -1,18 +1,36 @@
-import { el } from "deka-dom-el";
+import { el, on } from "deka-dom-el";
 import { S } from "deka-dom-el/signals";
 document.body.append(
-	el(HelloWorldComponent)
+	el(HelloWorldComponent, { initial: "🚀" })
 );
-function HelloWorldComponent(){
-	const clicksS= S(0); // A
+/** @typedef {"🎉" | "🚀"} Emoji */
+/** @param {{ initial: Emoji }} attrs */
+function HelloWorldComponent({ initial }){
+	const clicks= S(0);
+	const emoji= S(initial);
+	/** @param {HTMLOptionElement} el */
+	const isSelected= el=> (el.selected= el.value===initial);
+	// @ts-expect-error 2339: The <select> has only two options with {@link Emoji}
+	const onChange= on("change", event=> emoji(event.target.value));
+
 	return el().append(
-		el("p", S(()=>
-			"Hello World "+"🎉".repeat(clicksS()) // B
-		)),
-		el("button", {
-			type: "button",
-			onclick: ()=> clicksS(clicksS()+1), // C
-			textContent: "Fire",
-		})
-	)
+		el("p", {
+			textContent: S(() => `Hello World ${emoji().repeat(clicks())}`),
+			className: "example",
+			ariaLive: "polite", //OR ariaset: { live: "polite" },
+			dataset: { example: "Example" }, //OR dataExample: "Example",
+		}),
+		el("button",
+			{ textContent: "Fire", type: "button" },
+			on("click", ()=> clicks(clicks() + 1)),
+			on("keyup", ()=> clicks(clicks() - 2)),
+		),
+		el("select", null, onChange).append(
+			el(OptionComponent, "🎉", isSelected),//OR { textContent: "🎉" }
+			el(OptionComponent, "🚀", isSelected),//OR { textContent: "🚀" }
+		)
+	);
+}
+function OptionComponent({ textContent }){
+	return el("option", { value: textContent, textContent })
 }
diff --git a/docs/components/mnemonic/customElement-init.js b/docs/components/mnemonic/customElement-init.js
index d8bd5af..301f3e2 100644
--- a/docs/components/mnemonic/customElement-init.js
+++ b/docs/components/mnemonic/customElement-init.js
@@ -4,8 +4,8 @@ import { mnemonicUl } from "../mnemonicUl.html.js";
 export function mnemonic(){
 	return mnemonicUl().append(
 		el("li").append(
-			el("code", "customElementRender(<custom-element>, <connect-target>, <render-function>[, <properties>])"),
-			" — use function to render DOM structure for given <custom-element>",
+			el("code", "customElementRender(<connect-target>, <render-function>[, <properties>])"),
+			" — use function to render DOM structure for given custom element (or its Shadow DOM)",
 		),
 		el("li").append(
 			el("code", "customElementWithDDE(<custom-element>)"),
@@ -24,7 +24,7 @@ export function mnemonic(){
 			" — convert lifecycle methods to events, can be also used as decorator",
 		),
 		el("li").append(
-			el("code", "simulateSlots(<class-instance>, <body>[, <mapper>])"),
+			el("code", "simulateSlots(<class-instance>, <body>)"),
 			" — simulate slots for Custom Elements without shadow DOM",
 		),
 		el("li").append(
diff --git a/index.d.ts b/index.d.ts
index 8f420a7..63effa8 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -227,7 +227,6 @@ export function customElementRender<
 	EL extends HTMLElement,
 	P extends any = Record<string, string | ddeSignal<string>>
 >(
-	custom_element: EL,
 	target: ShadowRoot | EL,
 	render: (props: P)=> SupportedElement | DocumentFragment,
 	props?: P | ((el: EL)=> P)
diff --git a/src/dom.js b/src/dom.js
index 4ad5b39..0daccff 100644
--- a/src/dom.js
+++ b/src/dom.js
@@ -1,6 +1,7 @@
 import { signals } from "./signals-common.js";
 import { enviroment as env } from './dom-common.js';
 
+//TODO: add type, docs ≡ make it public
 export function queue(promise){ return env.q(promise); }
 /** @type {{ scope: object, prevent: boolean, host: function }[]} */
 const scopes= [ {
diff --git a/src/events.js b/src/events.js
index 392caaf..282f13d 100644
--- a/src/events.js
+++ b/src/events.js
@@ -8,6 +8,7 @@ export function dispatchEvent(name, options, host){
 			d.unshift(element);
 			element= typeof host==="function"? host() : host;
 		}
+		//TODO: what about re-emmitting?
 		const event= d.length ? new CustomEvent(name, Object.assign({ detail: d[0] }, options)) : new Event(name, options);
 		return element.dispatchEvent(event);
 	};