mirror of
https://github.com/jaandrle/deka-dom-el
synced 2025-07-01 04:12:14 +02:00
⚡ Docs
This commit is contained in:
@ -0,0 +1,23 @@
|
||||
import { customElementWithDDE, el, on } from "deka-dom-el";
|
||||
export class HTMLCustomElement extends HTMLElement{
|
||||
static tagName= "custom-element";
|
||||
connectedCallback(){
|
||||
this.append(
|
||||
el("p", "Hello from custom element!")
|
||||
);
|
||||
}
|
||||
}
|
||||
customElementWithDDE(HTMLCustomElement);
|
||||
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
|
||||
|
||||
const instance= el(HTMLCustomElement.tagName);
|
||||
on.connected( // preffered
|
||||
e=> console.log("Element connected to the DOM (v1):", e)
|
||||
)(instance);
|
||||
instance.addEventListener(
|
||||
"dde:connected",
|
||||
e=> console.log("Element connected to the DOM (v2):", e)
|
||||
);
|
||||
document.body.append(
|
||||
instance,
|
||||
);
|
33
docs/components/examples/customElement/dde.js
Normal file
33
docs/components/examples/customElement/dde.js
Normal file
@ -0,0 +1,33 @@
|
||||
import {
|
||||
customElementRender,
|
||||
customElementWithDDE,
|
||||
} from "deka-dom-el";
|
||||
export class HTMLCustomElement extends HTMLElement{
|
||||
static tagName= "custom-element";
|
||||
static observedAttributes= [ "attr" ];
|
||||
connectedCallback(){
|
||||
customElementRender(
|
||||
this,
|
||||
this.attachShadow({ mode: "open" }),
|
||||
ddeComponent
|
||||
);
|
||||
}
|
||||
set attr(value){ this.setAttribute("attr", value); }
|
||||
get attr(){ return this.getAttribute("attr"); }
|
||||
}
|
||||
|
||||
import { el, on, scope } from "deka-dom-el";
|
||||
function ddeComponent({ attr }){
|
||||
scope.host(
|
||||
on.connected(e=> console.log(e.target.outerHTML)),
|
||||
);
|
||||
return el().append(
|
||||
el("p", `Hello from Custom Element with attribute '${attr}'`)
|
||||
);
|
||||
}
|
||||
customElementWithDDE(HTMLCustomElement);
|
||||
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
|
||||
|
||||
document.body.append(
|
||||
el(HTMLCustomElement.tagName, { attr: "Attribute" })
|
||||
);
|
12
docs/components/examples/customElement/intro.js
Normal file
12
docs/components/examples/customElement/intro.js
Normal file
@ -0,0 +1,12 @@
|
||||
// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js
|
||||
import {
|
||||
customElementRender,
|
||||
customElementWithDDE,
|
||||
observedAttributes,
|
||||
} from "deka-dom-el";
|
||||
/** @type {ddePublicElementTagNameMap} */
|
||||
import { S } from "deka-dom-el/signals";
|
||||
S.observedAttributes;
|
||||
|
||||
// “internal” utils
|
||||
import { lifecyclesToEvents } from "deka-dom-el";
|
21
docs/components/examples/customElement/native-basic.js
Normal file
21
docs/components/examples/customElement/native-basic.js
Normal file
@ -0,0 +1,21 @@
|
||||
export class HTMLCustomElement extends HTMLElement{
|
||||
static tagName= "custom-element"; // just suggestion, we can use `el(HTMLCustomElement.tagName)`
|
||||
static observedAttributes= [ "custom-attribute" ];
|
||||
constructor(){
|
||||
super();
|
||||
// nice place to prepare custom element
|
||||
}
|
||||
connectedCallback(){
|
||||
// nice place to render custom element
|
||||
}
|
||||
attributeChangedCallback(name, oldValue, newValue){
|
||||
// listen to attribute changes (see `observedAttributes`)
|
||||
}
|
||||
disconnectedCallback(){
|
||||
// nice place to clean up
|
||||
}
|
||||
// for example, we can mirror get/set prop to attribute
|
||||
get customAttribute(){ return this.getAttribute("custom-attribute"); }
|
||||
set customAttribute(value){ this.setAttribute("custom-attribute", value); }
|
||||
}
|
||||
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
|
42
docs/components/examples/customElement/observedAttributes.js
Normal file
42
docs/components/examples/customElement/observedAttributes.js
Normal file
@ -0,0 +1,42 @@
|
||||
import {
|
||||
customElementRender,
|
||||
customElementWithDDE,
|
||||
observedAttributes,
|
||||
el, on, scope
|
||||
} from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
export class HTMLCustomElement extends HTMLElement{
|
||||
static tagName= "custom-element";
|
||||
static observedAttributes= [ "attr" ];
|
||||
connectedCallback(){
|
||||
console.log(observedAttributes(this));
|
||||
customElementRender(
|
||||
this,
|
||||
this.attachShadow({ mode: "open" }),
|
||||
ddeComponent,
|
||||
S.observedAttributes
|
||||
);
|
||||
}
|
||||
set attr(value){ this.setAttribute("attr", value); }
|
||||
get attr(){ return this.getAttribute("attr"); }
|
||||
}
|
||||
|
||||
/** @param {{ attr: ddeSignal<string, {}> }} props */
|
||||
function ddeComponent({ attr }){
|
||||
scope.host(
|
||||
on.connected(e=> console.log(e.target.outerHTML)),
|
||||
);
|
||||
return el().append(
|
||||
el("p", S(()=> `Hello from Custom Element with attribute '${attr()}'`))
|
||||
);
|
||||
}
|
||||
customElementWithDDE(HTMLCustomElement);
|
||||
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
|
||||
|
||||
document.body.append(
|
||||
el(HTMLCustomElement.tagName, { attr: "Attribute" })
|
||||
);
|
||||
setTimeout(
|
||||
()=> document.querySelector(HTMLCustomElement.tagName).setAttribute("attr", "New Value"),
|
||||
3*750
|
||||
);
|
69
docs/components/examples/customElement/shadowRoot.js
Normal file
69
docs/components/examples/customElement/shadowRoot.js
Normal file
@ -0,0 +1,69 @@
|
||||
import {
|
||||
el,
|
||||
customElementRender,
|
||||
customElementWithDDE,
|
||||
} from "deka-dom-el";
|
||||
function ddeComponent(){
|
||||
return el().append(
|
||||
el("style", `
|
||||
.red{ color: firebrick; }
|
||||
`),
|
||||
el("p", { className: "red" }).append(
|
||||
"Hello from ", el("slot", "Custom Element"), "!"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export class A extends HTMLElement{
|
||||
static tagName= "custom-element-without";
|
||||
connectedCallback(){
|
||||
customElementRender(
|
||||
this,
|
||||
this,
|
||||
ddeComponent
|
||||
);
|
||||
}
|
||||
}
|
||||
customElementWithDDE(A);
|
||||
customElements.define(A.tagName, A);
|
||||
export class B extends HTMLElement{
|
||||
static tagName= "custom-element-open";
|
||||
connectedCallback(){
|
||||
customElementRender(
|
||||
this,
|
||||
this.attachShadow({ mode: "open" }),
|
||||
ddeComponent
|
||||
);
|
||||
}
|
||||
}
|
||||
customElementWithDDE(B);
|
||||
customElements.define(B.tagName, B);
|
||||
export class C extends HTMLElement{
|
||||
static tagName= "custom-element-closed";
|
||||
connectedCallback(){
|
||||
customElementRender(
|
||||
this,
|
||||
this.attachShadow({ mode: "closed" }),
|
||||
ddeComponent
|
||||
);
|
||||
}
|
||||
}
|
||||
customElementWithDDE(C);
|
||||
customElements.define(C.tagName, C);
|
||||
|
||||
document.body.append(
|
||||
el(A.tagName).append("Without shadowRoot"),
|
||||
el("hr"),
|
||||
el(B.tagName).append("Open shadowRoot"),
|
||||
el("hr"),
|
||||
el(C.tagName).append("Closed shadowRoot"),
|
||||
el("style", `
|
||||
.red{ color: crimson; }
|
||||
`),
|
||||
);
|
||||
console.log(A.tagName, "expect modifications");
|
||||
document.body.querySelector(A.tagName).querySelector("p").textContent+= " (editable with JS)";
|
||||
console.log(B.tagName, "expect modifications");
|
||||
document.body.querySelector(B.tagName).shadowRoot.querySelector("p").textContent+= " (editable with JS)";
|
||||
console.log(C.tagName, "expect error ↓");
|
||||
document.body.querySelector(C.tagName).querySelector("p").textContent+= " (editable with JS)";
|
41
docs/components/examples/customElement/simulateSlots.js
Normal file
41
docs/components/examples/customElement/simulateSlots.js
Normal file
@ -0,0 +1,41 @@
|
||||
import {
|
||||
customElementRender,
|
||||
customElementWithDDE,
|
||||
el,
|
||||
simulateSlots
|
||||
} from "deka-dom-el";
|
||||
export class HTMLCustomElement extends HTMLElement{
|
||||
static tagName= "custom-slotting";
|
||||
connectedCallback(){
|
||||
const c= ()=> simulateSlots(this, ddeComponent());
|
||||
customElementRender(this, this, c);
|
||||
}
|
||||
}
|
||||
customElementWithDDE(HTMLCustomElement);
|
||||
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
|
||||
|
||||
document.body.append(
|
||||
el(HTMLCustomElement.tagName),
|
||||
el(HTMLCustomElement.tagName).append(
|
||||
"Slot"
|
||||
),
|
||||
el(ddeComponentSlot),
|
||||
el(ddeComponentSlot).append(
|
||||
"Slot"
|
||||
),
|
||||
);
|
||||
|
||||
function ddeComponent(){
|
||||
return el().append(
|
||||
el("p").append(
|
||||
"Hello ", el("slot", "World")
|
||||
)
|
||||
);
|
||||
}
|
||||
function ddeComponentSlot(){
|
||||
return simulateSlots(el().append(
|
||||
el("p").append(
|
||||
"Hello ", el("slot", "World")
|
||||
)
|
||||
));
|
||||
}
|
35
docs/components/examples/elements/dekaAppend.js
Normal file
35
docs/components/examples/elements/dekaAppend.js
Normal file
@ -0,0 +1,35 @@
|
||||
import { el } from "deka-dom-el";
|
||||
document.head.append(
|
||||
el("style").append(
|
||||
"tr, td{ border: 1px solid red; padding: 1em; }",
|
||||
"table{ border-collapse: collapse; }"
|
||||
)
|
||||
);
|
||||
document.body.append(
|
||||
el("p", "Example of a complex template. Using for example nesting lists:"),
|
||||
el("ul").append(
|
||||
el("li", "List item 1"),
|
||||
el("li").append(
|
||||
el("ul").append(
|
||||
el("li", "Nested list item 1"),
|
||||
)
|
||||
)
|
||||
),
|
||||
el("table").append(
|
||||
el("tr").append(
|
||||
el("td", "Row 1 – Col 1"),
|
||||
el("td", "Row 1 – Col 2")
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
import { chainableAppend } from "deka-dom-el";
|
||||
/** @param {keyof HTMLElementTagNameMap} tag */
|
||||
const createElement= tag=> chainableAppend(document.createElement(tag));
|
||||
document.body.append(
|
||||
createElement("p").append(
|
||||
createElement("em").append(
|
||||
"You can also use `chainableAppend`!"
|
||||
)
|
||||
)
|
||||
);
|
33
docs/components/examples/elements/dekaAssign.js
Normal file
33
docs/components/examples/elements/dekaAssign.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { assign, assignAttribute, classListDeclarative } from "deka-dom-el";
|
||||
const paragraph= document.createElement("p");
|
||||
|
||||
assignAttribute(paragraph, "textContent", "Hello, world!");
|
||||
|
||||
assignAttribute(paragraph, "style", "color: red; font-weight: bold;");
|
||||
assignAttribute(paragraph, "style", { color: "navy" });
|
||||
|
||||
assignAttribute(paragraph, "dataTest1", "v1");
|
||||
assignAttribute(paragraph, "dataset", { test2: "v2" });
|
||||
|
||||
assign(paragraph, { //textContent and style see above
|
||||
ariaLabel: "v1", //data* see above
|
||||
ariaset: { role: "none" }, // dataset see above
|
||||
"=onclick": "console.log(event)",
|
||||
onmouseout: console.info,
|
||||
".something": "something",
|
||||
classList: {} //see below
|
||||
});
|
||||
|
||||
classListDeclarative(paragraph, {
|
||||
classAdd: true,
|
||||
classRemove: false,
|
||||
classAdd1: 1,
|
||||
classRemove1: 0,
|
||||
classToggle: -1
|
||||
});
|
||||
|
||||
console.log(paragraph.outerHTML);
|
||||
console.log("paragraph.something=", paragraph.something);
|
||||
document.body.append(
|
||||
paragraph
|
||||
);
|
17
docs/components/examples/elements/dekaBasicComponent.js
Normal file
17
docs/components/examples/elements/dekaBasicComponent.js
Normal file
@ -0,0 +1,17 @@
|
||||
import { el } from "deka-dom-el";
|
||||
document.head.append(
|
||||
el("style").append(
|
||||
".class1{ font-weight: bold; }",
|
||||
".class2{ color: purple; }"
|
||||
)
|
||||
);
|
||||
document.body.append(
|
||||
el(component, { className: "class2", textContent: "Hello World!" }),
|
||||
component({ className: "class2", textContent: "Hello World!" })
|
||||
);
|
||||
|
||||
function component({ className, textContent }){
|
||||
return el("div", { className: [ "class1", className ] }).append(
|
||||
el("p", textContent)
|
||||
);
|
||||
}
|
11
docs/components/examples/elements/dekaCreateElement.js
Normal file
11
docs/components/examples/elements/dekaCreateElement.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { el, assign } from "deka-dom-el";
|
||||
const color= "lightcoral";
|
||||
document.body.append(
|
||||
el("p", { textContent: "Hello (first time)", style: { color } })
|
||||
);
|
||||
document.body.append(
|
||||
assign(
|
||||
document.createElement("p"),
|
||||
{ textContent: "Hello (second time)", style: { color } }
|
||||
)
|
||||
);
|
11
docs/components/examples/elements/dekaElNS.js
Normal file
11
docs/components/examples/elements/dekaElNS.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { elNS, assign } from "deka-dom-el";
|
||||
const elSVG= elNS("http://www.w3.org/2000/svg");
|
||||
const elMath= elNS("http://www.w3.org/1998/Math/MathML");
|
||||
document.body.append(
|
||||
elSVG("svg"), // see https://developer.mozilla.org/en-US/docs/Web/SVG and https://developer.mozilla.org/en-US/docs/Web/API/SVGElement
|
||||
elMath("math") // see https://developer.mozilla.org/en-US/docs/Web/MathML and https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes
|
||||
);
|
||||
|
||||
console.log(
|
||||
document.body.innerHTML.includes("<svg></svg><math></math>")
|
||||
)
|
14
docs/components/examples/elements/intro.js
Normal file
14
docs/components/examples/elements/intro.js
Normal file
@ -0,0 +1,14 @@
|
||||
// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js
|
||||
import {
|
||||
assign,
|
||||
el, createElement,
|
||||
elNS, createElementNS
|
||||
} from "deka-dom-el";
|
||||
el===createElement
|
||||
elNS===createElementNS
|
||||
// “internal” utils
|
||||
import {
|
||||
assignAttribute,
|
||||
classListDeclarative,
|
||||
chainableAppend
|
||||
} from "deka-dom-el";
|
11
docs/components/examples/elements/nativeAppend.js
Normal file
11
docs/components/examples/elements/nativeAppend.js
Normal file
@ -0,0 +1,11 @@
|
||||
document.body.append(
|
||||
document.createElement("div"),
|
||||
document.createElement("span"),
|
||||
document.createElement("main")
|
||||
);
|
||||
console.log(document.body.innerHTML.includes("<div></div><span></span><main></main>"));
|
||||
const template= document.createElement("main").append(
|
||||
document.createElement("div"),
|
||||
document.createElement("span"),
|
||||
);
|
||||
console.log(typeof template==="undefined");
|
14
docs/components/examples/elements/nativeCreateElement.js
Normal file
14
docs/components/examples/elements/nativeCreateElement.js
Normal file
@ -0,0 +1,14 @@
|
||||
document.body.append(
|
||||
document.createElement("div")
|
||||
);
|
||||
console.log(
|
||||
"Emty div is generated inside <body>:",
|
||||
document.body.innerHTML.includes("<div></div>")
|
||||
);
|
||||
|
||||
document.body.append(
|
||||
Object.assign(
|
||||
document.createElement("p"),
|
||||
{ textContent: "Element’s text content.", style: "color: coral;" }
|
||||
)
|
||||
);
|
13
docs/components/examples/events/abortSignal.js
Normal file
13
docs/components/examples/events/abortSignal.js
Normal file
@ -0,0 +1,13 @@
|
||||
import { el, on } from "deka-dom-el";
|
||||
const log= mark=> console.log.bind(console, mark);
|
||||
|
||||
const abort_controller= new AbortController();
|
||||
const { signal }= abort_controller;
|
||||
|
||||
const button= el("button", "Test click");
|
||||
button.addEventListener("click", log("`addEventListener`"), { signal });
|
||||
on("click", log("`on`"), { signal })(button);
|
||||
|
||||
document.body.append(
|
||||
button, " ", el("button", { textContent: "Off", onclick: ()=> abort_controller.abort() })
|
||||
);
|
10
docs/components/examples/events/compare.js
Normal file
10
docs/components/examples/events/compare.js
Normal file
@ -0,0 +1,10 @@
|
||||
import { el, on } from "deka-dom-el";
|
||||
const log= mark=> console.log.bind(console, mark);
|
||||
|
||||
const button= el("button", "Test click");
|
||||
button.addEventListener("click", log("`addEventListener`"), { once: true });
|
||||
on("click", log("`on`"), { once: true })(button);
|
||||
|
||||
document.body.append(
|
||||
button
|
||||
);
|
24
docs/components/examples/events/compareDispatch.js
Normal file
24
docs/components/examples/events/compareDispatch.js
Normal file
@ -0,0 +1,24 @@
|
||||
import { el, on, dispatchEvent } from "deka-dom-el";
|
||||
document.body.append(
|
||||
el("p", "Listenning to `test` event.", on("test", console.log)).append(
|
||||
el("br"),
|
||||
el("button", "native", on("click", native)),
|
||||
" ",
|
||||
el("button", "dde", on("click", dde)),
|
||||
" ",
|
||||
el("button", "dde with options", on("click", ddeOptions))
|
||||
)
|
||||
);
|
||||
function native(){
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("test",
|
||||
{ bubbles: true, detail: "hi" }
|
||||
)
|
||||
);
|
||||
}
|
||||
function dde(){
|
||||
dispatchEvent("test")(this.parentElement, "hi");
|
||||
}
|
||||
function ddeOptions(){
|
||||
dispatchEvent("test", { bubbles: true })(this, "hi");
|
||||
}
|
4
docs/components/examples/events/intro.js
Normal file
4
docs/components/examples/events/intro.js
Normal file
@ -0,0 +1,4 @@
|
||||
// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js
|
||||
import { on, dispatchEvent } from "deka-dom-el";
|
||||
|
||||
/** @type {ddeElementAddon} */
|
18
docs/components/examples/events/live-cycle.js
Normal file
18
docs/components/examples/events/live-cycle.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { el, on } from "deka-dom-el";
|
||||
const paragraph= el("p", "See live-cycle events in console.",
|
||||
el=> log({ type: "dde:created", detail: el }),
|
||||
on.connected(log),
|
||||
on.disconnected(log),
|
||||
on.attributeChanged(log));
|
||||
|
||||
document.body.append(
|
||||
paragraph,
|
||||
el("button", "Update attribute", on("click", ()=> paragraph.setAttribute("test", Math.random().toString()))),
|
||||
" ",
|
||||
el("button", "Remove", on("click", ()=> paragraph.remove()))
|
||||
);
|
||||
|
||||
/** @param {Partial<CustomEvent>} event */
|
||||
function log({ type, detail }){
|
||||
console.log({ _this: this, type, detail });
|
||||
}
|
24
docs/components/examples/events/templateWithListeners.js
Normal file
24
docs/components/examples/events/templateWithListeners.js
Normal file
@ -0,0 +1,24 @@
|
||||
import { el, on } from "deka-dom-el";
|
||||
const abort_controller= new AbortController();
|
||||
const { signal }= abort_controller;
|
||||
/** @type {ddeElementAddon<HTMLButtonElement>} */
|
||||
const onclickOff= on("click", ()=> abort_controller.abort(), { signal });
|
||||
/** @type {(ref?: HTMLOutputElement)=> HTMLOutputElement | null} */
|
||||
const ref= (store=> ref=> ref ? (store= ref) : store)(null);
|
||||
|
||||
document.body.append(
|
||||
el("button", "Test `on`",
|
||||
on("click", console.log, { signal }),
|
||||
on("click", update, { signal }),
|
||||
on("mouseup", update, { signal })),
|
||||
" ",
|
||||
el("button", "Off", onclickOff),
|
||||
el("output", { style: { display: "block", whiteSpace: "pre" } }, ref)
|
||||
);
|
||||
/** @param {MouseEvent} event @this {HTMLButtonElement} */
|
||||
function update(event){
|
||||
ref().append(
|
||||
event.type,
|
||||
"\n"
|
||||
);
|
||||
}
|
6
docs/components/examples/introducing/3ps.js
Normal file
6
docs/components/examples/introducing/3ps.js
Normal file
@ -0,0 +1,6 @@
|
||||
// pseudo code!
|
||||
const onchage=
|
||||
event=>
|
||||
console.log("Reacting to the:", event); // A
|
||||
input.addEventListener("change", onchange); // B
|
||||
input.dispatchEvent(new Event("change")); // C
|
15
docs/components/examples/introducing/helloWorld.js
Normal file
15
docs/components/examples/introducing/helloWorld.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { el } from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
const clicks= S(0); // A
|
||||
document.body.append(
|
||||
el().append(
|
||||
el("p", S(()=>
|
||||
"Hello World "+"🎉".repeat(clicks()) // B
|
||||
)),
|
||||
el("button", {
|
||||
type: "button",
|
||||
onclick: ()=> clicks(clicks()+1), // C
|
||||
textContent: "Fire",
|
||||
})
|
||||
)
|
||||
);
|
44
docs/components/examples/scopes/class-component.js
Normal file
44
docs/components/examples/scopes/class-component.js
Normal file
@ -0,0 +1,44 @@
|
||||
import { el } from "deka-dom-el";
|
||||
class Test {
|
||||
constructor(params){
|
||||
this._params= params;
|
||||
}
|
||||
render(){
|
||||
return el("div").append(
|
||||
this._params.textContent
|
||||
);
|
||||
}
|
||||
}
|
||||
document.body.append(
|
||||
elClass(Test, { textContent: "Hello World" })
|
||||
);
|
||||
|
||||
import { chainableAppend, scope } from "deka-dom-el";
|
||||
function elClass(_class, attributes, ...addons){
|
||||
let element, element_host;
|
||||
scope.push({
|
||||
scope: _class, //just informative purposes
|
||||
host: (...addons_append)=> addons_append.length
|
||||
? (
|
||||
!element
|
||||
? addons.unshift(...addons_append)
|
||||
: addons_append.forEach(c=> c(element_host))
|
||||
, undefined)
|
||||
: element_host
|
||||
});
|
||||
const instance= new _class(attributes);
|
||||
element= instance.render();
|
||||
const is_fragment= element instanceof DocumentFragment;
|
||||
const el_mark= el.mark({ //this creates html comment `<dde:mark …/>`
|
||||
type: "class-component",
|
||||
name: _class.name,
|
||||
host: is_fragment ? "this" : "parentElement",
|
||||
});
|
||||
element.prepend(el_mark);
|
||||
if(is_fragment) element_host= el_mark;
|
||||
|
||||
chainableAppend(element);
|
||||
addons.forEach(c=> c(element_host));
|
||||
scope.pop();
|
||||
return element;
|
||||
}
|
18
docs/components/examples/scopes/cleaning.js
Normal file
18
docs/components/examples/scopes/cleaning.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { el, empty, on } from "deka-dom-el";
|
||||
document.body.append(
|
||||
el(component),
|
||||
el("button", {
|
||||
textContent: "Remove",
|
||||
onclick: ()=> empty(document.body),
|
||||
type: "button"
|
||||
})
|
||||
);
|
||||
import { S } from "deka-dom-el/signals";
|
||||
function component(){
|
||||
const textContent= S("Click to change text.");
|
||||
|
||||
const onclickChange= on("click", function redispatch(){
|
||||
textContent("Text changed! "+(new Date()).toString())
|
||||
});
|
||||
return el("p", textContent, onclickChange);
|
||||
}
|
35
docs/components/examples/scopes/declarative.js
Normal file
35
docs/components/examples/scopes/declarative.js
Normal file
@ -0,0 +1,35 @@
|
||||
/* PSEUDO-CODE!!! */
|
||||
import { el } from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
function component(){
|
||||
/* prepare changeable data */
|
||||
const dataA= S("data");
|
||||
const dataB= S("data");
|
||||
/* define data flow (can be asynchronous) */
|
||||
fetchAPI().then(data_new=> dataA(data_new));
|
||||
setTimeout(()=> dataB("DATA"));
|
||||
/* declarative UI */
|
||||
return el().append(
|
||||
el("h1", {
|
||||
textContent: "Example",
|
||||
/* declarative attribute(s) */
|
||||
classList: { declarative: dataB }
|
||||
}),
|
||||
el("ul").append(
|
||||
/* declarative element(s) */
|
||||
S.el(dataA, data=> data.map(d=> el("li", d)))
|
||||
),
|
||||
el("ul").append(
|
||||
/* declarative component(s) */
|
||||
S.el(dataA, data=> data.map(d=> el(subcomponent, d)))
|
||||
)
|
||||
);
|
||||
}
|
||||
function subcomponent({ id }){
|
||||
/* prepare changeable data */
|
||||
const textContent= S("…");
|
||||
/* define data flow (can be asynchronous) */
|
||||
fetchAPI(id).then(text=> textContent(text));
|
||||
/* declarative UI */
|
||||
return el("li", { textContent, dataId: id });
|
||||
}
|
18
docs/components/examples/scopes/good-practise.js
Normal file
18
docs/components/examples/scopes/good-practise.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { el, scope, on, dispatchEvent } from "deka-dom-el";
|
||||
document.body.append(
|
||||
el(component)
|
||||
);
|
||||
function component(){
|
||||
const { host }= scope; // good practise!
|
||||
|
||||
host(
|
||||
console.log,
|
||||
on("click", function redispatch(){
|
||||
// this `host` ↘ still corresponds to the host ↖ of the component
|
||||
dispatchEvent("redispatch")(host());
|
||||
})
|
||||
);
|
||||
// this `host` ↘ still corresponds to the host ↖ of the component
|
||||
setTimeout(()=> dispatchEvent("timeout")(host()), 750)
|
||||
return el("p", "Clickable paragraph!");
|
||||
}
|
31
docs/components/examples/scopes/imperative.js
Normal file
31
docs/components/examples/scopes/imperative.js
Normal file
@ -0,0 +1,31 @@
|
||||
/* PSEUDO-CODE!!! */
|
||||
import { el, on, scope } from "deka-dom-el";
|
||||
function component(){
|
||||
const { host }= scope;
|
||||
const ul= el("ul");
|
||||
const ac= new AbortController();
|
||||
fetchAPI({ signal: ac.signal }).then(data=> {
|
||||
data.forEach(d=> ul.append(el("li", d)));
|
||||
});
|
||||
host(
|
||||
/* element was remove before data fetched */
|
||||
on.disconnected(()=> ac.abort())
|
||||
);
|
||||
return ul;
|
||||
/**
|
||||
* NEVER EVER!!
|
||||
* let data;
|
||||
* fetchAPI().then(d=> data= O(d));
|
||||
*
|
||||
* OR NEVER EVER!!
|
||||
* const ul= el("ul");
|
||||
* fetchAPI().then(d=> {
|
||||
* const data= O("data");
|
||||
* ul.append(el("li", data));
|
||||
* });
|
||||
*
|
||||
* // THE HOST IS PROBABLY DIFFERENT THAN
|
||||
* // YOU EXPECT AND OBSERVABLES MAY BE
|
||||
* // UNEXPECTEDLY REMOVED!!!
|
||||
* */
|
||||
}
|
3
docs/components/examples/scopes/intro.js
Normal file
3
docs/components/examples/scopes/intro.js
Normal file
@ -0,0 +1,3 @@
|
||||
// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js
|
||||
import { scope, el } from "deka-dom-el";
|
||||
/** @type {ddeElementAddon} */
|
33
docs/components/examples/scopes/scopes-and-hosts.js
Normal file
33
docs/components/examples/scopes/scopes-and-hosts.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { el, on, scope } from "deka-dom-el";
|
||||
const { host }= scope;
|
||||
host(
|
||||
element=> console.log(
|
||||
"This represents Addon/oninit for root",
|
||||
element.outerHTML
|
||||
)
|
||||
);
|
||||
console.log(
|
||||
"This represents the reference to the host element of root",
|
||||
host().outerHTML
|
||||
);
|
||||
document.body.append(
|
||||
el(component)
|
||||
);
|
||||
function component(){
|
||||
const { host }= scope;
|
||||
host(
|
||||
element=> console.log(
|
||||
"This represents Addon/oninit for the component",
|
||||
element.outerHTML
|
||||
)
|
||||
);
|
||||
const onclick= on("click", function(ev){
|
||||
console.log(
|
||||
"This represents the reference to the host element of the component",
|
||||
host().outerHTML
|
||||
);
|
||||
})
|
||||
return el("div", null, onclick).append(
|
||||
el("strong", "Component")
|
||||
);
|
||||
}
|
18
docs/components/examples/signals/actions-demo.js
Normal file
18
docs/components/examples/signals/actions-demo.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
const signal= S(0, {
|
||||
increaseOnlyOdd(add){
|
||||
console.info(add);
|
||||
if(add%2 === 0) return this.stopPropagation();
|
||||
this.value+= add;
|
||||
}
|
||||
});
|
||||
S.on(signal, console.log);
|
||||
const oninterval= ()=>
|
||||
S.action(signal, "increaseOnlyOdd", Math.floor(Math.random()*100));
|
||||
|
||||
const interval= 5*1000;
|
||||
setTimeout(
|
||||
clearInterval,
|
||||
10*interval,
|
||||
setInterval(oninterval, interval)
|
||||
);
|
56
docs/components/examples/signals/actions-todos.js
Normal file
56
docs/components/examples/signals/actions-todos.js
Normal file
@ -0,0 +1,56 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
const todos= S([], {
|
||||
push(item){
|
||||
this.value.push(S(item));
|
||||
},
|
||||
pop(){
|
||||
const removed= this.value.pop();
|
||||
if(removed) S.clear(removed);
|
||||
},
|
||||
[S.symbols.onclear](){ // this covers `O.clear(todos)`
|
||||
S.clear(...this.value);
|
||||
}
|
||||
});
|
||||
|
||||
import { el, on } from "deka-dom-el";
|
||||
/** @type {ddeElementAddon<HTMLFormElement>} */
|
||||
const onsubmit= on("submit", function(event){
|
||||
event.preventDefault();
|
||||
const data= new FormData(this);
|
||||
switch (data.get("op")){
|
||||
case "A"/*dd*/:
|
||||
S.action(todos, "push", data.get("todo"));
|
||||
break;
|
||||
case "E"/*dit*/: {
|
||||
const last= todos().at(-1);
|
||||
if(!last) break;
|
||||
last(data.get("todo"));
|
||||
break;
|
||||
}
|
||||
case "R"/*emove*/:
|
||||
S.action(todos, "pop");
|
||||
break;
|
||||
}
|
||||
});
|
||||
document.body.append(
|
||||
el("ul").append(
|
||||
S.el(todos, todos=>
|
||||
todos.map(textContent=> el("li", textContent)))
|
||||
),
|
||||
el("form", null, onsubmit).append(
|
||||
el("input", { type: "text", name: "todo", placeholder: "Todo’s text" }),
|
||||
el(radio, { textContent: "Add", checked: true }),
|
||||
el(radio, { textContent: "Edit last" }),
|
||||
el(radio, { textContent: "Remove" }),
|
||||
el("button", "Submit")
|
||||
)
|
||||
);
|
||||
document.head.append(
|
||||
el("style", "form{ display: flex; flex-flow: column nowrap; }")
|
||||
);
|
||||
function radio({ textContent, checked= false }){
|
||||
return el("label").append(
|
||||
el("input", { type: "radio", name: "op", value: textContent[0], checked }),
|
||||
" ",textContent
|
||||
)
|
||||
}
|
16
docs/components/examples/signals/computations-abort.js
Normal file
16
docs/components/examples/signals/computations-abort.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
const signal= S(0);
|
||||
// computation pattern
|
||||
const double= S(()=> 2*signal());
|
||||
|
||||
const ac= new AbortController();
|
||||
S.on(signal, v=> console.log("signal", v), { signal: ac.signal });
|
||||
S.on(double, v=> console.log("double", v), { signal: ac.signal });
|
||||
|
||||
signal(signal()+1);
|
||||
const interval= 5 * 1000;
|
||||
const id= setInterval(()=> signal(signal()+1), interval);
|
||||
ac.signal.addEventListener("abort",
|
||||
()=> setTimeout(()=> clearInterval(id), 2*interval));
|
||||
|
||||
setTimeout(()=> ac.abort(), 3*interval)
|
15
docs/components/examples/signals/dom-attrs.js
Normal file
15
docs/components/examples/signals/dom-attrs.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
const count= S(0);
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
document.body.append(
|
||||
el("p", S(()=> "Currently: "+count())),
|
||||
el("p", { classList: { red: S(()=> count()%2) }, dataset: { count }, textContent: "Attributes example" })
|
||||
);
|
||||
document.head.append(
|
||||
el("style", ".red { color: red; }")
|
||||
);
|
||||
|
||||
const interval= 5 * 1000;
|
||||
setTimeout(clearInterval, 10*interval,
|
||||
setInterval(()=> count(count()+1), interval));
|
26
docs/components/examples/signals/dom-el.js
Normal file
26
docs/components/examples/signals/dom-el.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
const count= S(0, {
|
||||
add(){ this.value= this.value + Math.round(Math.random()*10); }
|
||||
});
|
||||
const numbers= S([ count() ], {
|
||||
push(next){ this.value.push(next); }
|
||||
});
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
document.body.append(
|
||||
S.el(count, count=> count%2
|
||||
? el("p", "Last number is odd.")
|
||||
: el()
|
||||
),
|
||||
el("p", "Lucky numbers:"),
|
||||
el("ul").append(
|
||||
S.el(numbers, numbers=> numbers.toReversed()
|
||||
.map(n=> el("li", n)))
|
||||
)
|
||||
);
|
||||
|
||||
const interval= 5*1000;
|
||||
setTimeout(clearInterval, 10*interval, setInterval(function(){
|
||||
S.action(count, "add");
|
||||
S.action(numbers, "push", count());
|
||||
}, interval));
|
6
docs/components/examples/signals/intro.js
Normal file
6
docs/components/examples/signals/intro.js
Normal file
@ -0,0 +1,6 @@
|
||||
// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js
|
||||
import { S, signal } from "deka-dom-el/signals";
|
||||
S===signal
|
||||
/** @type {ddeSignal} */
|
||||
/** @type {ddeAction} */
|
||||
/** @type {ddeActions} */
|
12
docs/components/examples/signals/signals.js
Normal file
12
docs/components/examples/signals/signals.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
// α — `signal` represents a reactive value
|
||||
const signal= S(0);
|
||||
// β — just reacts on signal changes
|
||||
S.on(signal, console.log);
|
||||
// γ — just updates the value
|
||||
const update= ()=> signal(signal()+1);
|
||||
|
||||
update();
|
||||
const interval= 5*1000;
|
||||
setTimeout(clearInterval, 10*interval,
|
||||
setInterval(update, interval));
|
Reference in New Issue
Block a user