mirror of
https://github.com/jaandrle/deka-dom-el
synced 2025-07-01 04:12:14 +02:00
🔨 docs
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import { registerClientFile, styles } from "../ssr.js";
|
||||
styles.scope(code).css`
|
||||
:host{
|
||||
const host= "."+code.name;
|
||||
styles.css`
|
||||
${host}{
|
||||
--shiki-color-text: #e9eded;
|
||||
--shiki-color-background: #212121;
|
||||
--shiki-token-constant: #82b1ff;
|
||||
@ -14,7 +15,7 @@ styles.scope(code).css`
|
||||
--shiki-token-link: #EE0000;
|
||||
white-space: pre;
|
||||
}
|
||||
:host[data-js=todo]{
|
||||
${host}[data-js=todo]{
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--standard-border-radius);
|
||||
margin-bottom: 1rem;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { styles } from "../ssr.js";
|
||||
styles.scope(example).css`
|
||||
:host{
|
||||
const host= "."+example.name;
|
||||
styles.css`
|
||||
${host}{
|
||||
grid-column: full-main;
|
||||
width: 100%;
|
||||
max-width: calc(9/5 * var(--body-max-width));
|
||||
@ -14,6 +15,7 @@ styles.scope(example).css`
|
||||
`
|
||||
import { el } from "deka-dom-el";
|
||||
import { code } from "./code.html.js";
|
||||
import { relative } from "node:path";
|
||||
/**
|
||||
* Prints code to the page and registers flems to make it interactive.
|
||||
* @param {object} attrs
|
||||
@ -25,7 +27,7 @@ export function example({ src, language= "js", page_id }){
|
||||
registerClientPart(page_id);
|
||||
const content= s.cat(src).toString()
|
||||
.replaceAll(/ from "deka-dom-el(\/signals)?";/g, ' from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";');
|
||||
const id= "code-"+Math.random().toString(36).slice(2, 7);
|
||||
const id= "code-example-"+generateCodeId(src);
|
||||
return el().append(
|
||||
el(code, { id, content, language, className: example.name }),
|
||||
elCode({ id, content, extension: "."+language })
|
||||
@ -48,3 +50,16 @@ function registerClientPart(page_id){
|
||||
);
|
||||
is_registered[page_id]= true;
|
||||
}
|
||||
const store_prev= new Map();
|
||||
/** @param {URL} src */
|
||||
function generateCodeId(src){
|
||||
const candidate= parseInt(relative((new URL("..", import.meta.url)).pathname, src.pathname)
|
||||
.split("")
|
||||
.map(ch=> ch.charCodeAt(0))
|
||||
.join(""), 10)
|
||||
.toString(36)
|
||||
.replace(/000+/g, "");
|
||||
const count= 1 + ( store_prev.get(candidate) || 0 );
|
||||
store_prev.set(candidate, count);
|
||||
return count.toString()+"-"+candidate;
|
||||
}
|
||||
|
@ -9,6 +9,16 @@ document.body.append(
|
||||
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"); }
|
||||
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");
|
||||
}
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { pages, styles } from "../ssr.js";
|
||||
styles.scope(prevNext).css`
|
||||
:host{
|
||||
const host= "."+prevNext.name;
|
||||
styles.css`
|
||||
${host}{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 2fr 1fr;
|
||||
margin-top: 1rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
:host [rel=prev]{
|
||||
${host} [rel=prev]{
|
||||
grid-column: 1;
|
||||
}
|
||||
:host [rel=next]{
|
||||
${host} [rel=next]{
|
||||
grid-column: 3;
|
||||
text-align: right;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { styles } from "./ssr.js";
|
||||
styles.scope(import.meta.url).css`
|
||||
styles.css`
|
||||
@import url(https://cdn.simplecss.org/simple.min.css);
|
||||
:root{
|
||||
--body-max-width: 45rem;
|
||||
|
120
docs_src/p04-signals.html.js
Normal file
120
docs_src/p04-signals.html.js
Normal file
@ -0,0 +1,120 @@
|
||||
import "./global.css.js";
|
||||
import { el } from "deka-dom-el";
|
||||
|
||||
import { header } from "./layout/head.html.js";
|
||||
import { example } from "./components/example.html.js";
|
||||
import { h3, prevNext } from "./components/pageUtils.html.js";
|
||||
|
||||
/** @param {string} url */
|
||||
const fileURL= url=> new URL(url, import.meta.url);
|
||||
|
||||
/** @param {import("./types.d.ts").PageAttrs} attrs */
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el().append(
|
||||
el(header, { info, pkg }),
|
||||
el("main").append(
|
||||
el("h2", "Listenning to the native DOM events and other Addons"),
|
||||
el("p").append(
|
||||
"We quickly introduce helper to listening to the native DOM events.",
|
||||
" ",
|
||||
"And library syntax/pattern so-called ", el("em", "Addon"), " to",
|
||||
" incorporate not only this in UI templates declaratively."
|
||||
),
|
||||
|
||||
el(h3, "Events and listenners"),
|
||||
el("p").append(
|
||||
"In JavaScript you can listen to the native DOM events of the given element by using ",
|
||||
el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener", title: "addEventListener on MDN" }).append(
|
||||
el("code", "element.addEventListener(type, listener, options)")
|
||||
), ".",
|
||||
" ",
|
||||
"The library provides an alternative (", el("code", "on"), ") accepting the differen order",
|
||||
" of the arguments:"
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/events/compare.js"), page_id }),
|
||||
el("p").append(
|
||||
"…this is actually one of the two differences. The another one is that ", el("code", "on"),
|
||||
" accepts only object as the ", el("code", "options"), " (but it is still optional)."
|
||||
),
|
||||
el("p", { className: "notice" }).append(
|
||||
"The other difference is that there is ", el("strong", "no"), " ", el("code", "off"), " function.",
|
||||
" ",
|
||||
"You can remove listener declaratively using ", el("a", { textContent: "AbortSignal", href: "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#signal", title: "part of addEventListener on MDN" }),
|
||||
":"
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/events/abortSignal.js"), page_id }),
|
||||
el("div", { className: "notice" }).append(
|
||||
el("p", "So, there are (typically) three ways to handle events. You can use:"),
|
||||
el("ul").append(
|
||||
el("li").append( el("code", `el("button", { textContent: "click me", "=onclick": "console.log(event)" })`)),
|
||||
el("li").append( el("code", `el("button", { textContent: "click me", onclick: console.log })`)),
|
||||
el("li").append( el("code", `el("button", { textContent: "click me" }, on("click", console.log))`))
|
||||
),
|
||||
el("p").append(
|
||||
"In the first example we force to use HTML attribute (it corresponds to ", el("code", `<button onclick="console.log(event)">click me</button>`), ").",
|
||||
" ",
|
||||
el("em", "Side note: this can be useful in case of SSR."),
|
||||
" ",
|
||||
"To study difference, you can read a nice summary here: ", el("a", { href: "https://gist.github.com/WebReflection/b404c36f46371e3b1173bf5492acc944", textContent: "GIST @WebReflection/web_events.md" }), "."
|
||||
)
|
||||
),
|
||||
|
||||
el(h3, "Addons"),
|
||||
el("p").append(
|
||||
"From practical point of view, ", el("em", "Addons"), " are just functions that accept any html element",
|
||||
" as their first parameter. You can see that the ", el("code", "on(…)"), " fullfills this requirement."
|
||||
),
|
||||
el("p").append(
|
||||
"You can use Addons as ≥3rd argument of ", el("code", "el"), " function. This way is possible to extends",
|
||||
" you templates by additional (3rd party) functionalities. But for now mainly, you can add events listeners:"
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/events/templateWithListeners.js"), page_id }),
|
||||
el("p").append(
|
||||
"As the example shows, you can also provide types in JSDoc+TypeScript by using global type ", el("code", "ddeElementAddon"), ".",
|
||||
" ",
|
||||
"Also notice, you can use Addons to get element reference.",
|
||||
),
|
||||
el(h3, "Life-cycle events"),
|
||||
el("p").append(
|
||||
"Addons are called immediately when the element is created, even it is not connected to live DOM yet.",
|
||||
" ",
|
||||
"Therefore, you can understand the Addon to be “oncreate” event."
|
||||
),
|
||||
el("p").append(
|
||||
"The library provide three additional live-cycle events corresponding to how they are named in",
|
||||
" a case of custom elements: ", el("code", "on.connected"), ", ", el("code", "on.disconnected"),
|
||||
" and ", el("code", "on.attributeChanged"), "."
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/events/live-cycle.js"), page_id }),
|
||||
el("p").append(
|
||||
"For Custom elements, we will later introduce a way to replace ", el("code", "*Callback"),
|
||||
" syntax with ", el("code", "dde:*"), " events. The ", el("code", "on.*"), " functions then",
|
||||
" listen to the appropriate Custom Elements events (see ", el("a", { textContent: "Custom element lifecycle callbacks | MDN", href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks" }), ")."
|
||||
),
|
||||
el("p").append(
|
||||
"But, in case of regular elemnets the ", el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver" }).append(el("code", "MutationObserver"), " | MDN"),
|
||||
" is internaly used to track these events. Therefore, there are some drawbacks:",
|
||||
),
|
||||
el("ul").append(
|
||||
el("li").append(
|
||||
"To proper listener registration, you need to use ", el("code", "on.*"), " not `on(\"dde:*\", …)`!"
|
||||
),
|
||||
el("li").append(
|
||||
"Use sparingly! Internally, library must loop of all registered events and fires event properly.",
|
||||
" ",
|
||||
el("strong", "It is good practice to use the fact that if an element is removed, its children are also removed!"),
|
||||
" ",
|
||||
"In this spirit, we will introduce later the ", el("strong", "host"), " syntax to register",
|
||||
" clean up procedures when the component is removed from the app."
|
||||
),
|
||||
),
|
||||
|
||||
el(h3, "Final notes"),
|
||||
el("p", "The library also provides a method to dispatch the events."),
|
||||
el(example, { src: fileURL("./components/examples/events/compareDispatch.js"), page_id }),
|
||||
|
||||
el(prevNext, info)
|
||||
)
|
||||
);
|
||||
}
|
@ -4,8 +4,8 @@ export const path_target= {
|
||||
};
|
||||
export const pages= [
|
||||
{ id: "index", href: "./", title: "Introduction", description: "Introducing a library." },
|
||||
{ id: "elements", href: "elements", title: "Elements", description: "Basic concepts of elements modifications and creations." },
|
||||
{ id: "events", href: "events", title: "Events and Addons", description: "Using not only events in UI declaratively." },
|
||||
{ id: "p02-elements", href: "p02-elements", title: "Elements", description: "Basic concepts of elements modifications and creations." },
|
||||
{ id: "p03-events", href: "p03-events", title: "Events and Addons", description: "Using not only events in UI declaratively." },
|
||||
];
|
||||
/**
|
||||
* @typedef registerClientFile
|
||||
@ -40,37 +40,20 @@ export function dispatchEvent(name, a){
|
||||
ls.clear();
|
||||
}
|
||||
|
||||
const scopes= new Set();
|
||||
export const styles= {
|
||||
element: null,
|
||||
name: "global.css",
|
||||
get location(){ return path_target.css.replace(path_target.root, "")+this.name; },
|
||||
content: "",
|
||||
|
||||
skip: false,
|
||||
/** @param {function|string} s */
|
||||
scope(s){
|
||||
if(scopes.has(s)){ this.skip= true; return this; }
|
||||
|
||||
scopes.add(s);
|
||||
if(typeof s==="function") this.host= s.name;
|
||||
return this;
|
||||
},
|
||||
/** @param {Parameters<typeof String.raw>} a */
|
||||
css(...a){
|
||||
if(this.skip){ this.skip= false; return this; }
|
||||
|
||||
let c= css(...a);
|
||||
if(this.host){
|
||||
c= c.replaceAll(":host", "."+this.host);
|
||||
this.host= "";
|
||||
}
|
||||
if(this.content) this.content+= "\n";
|
||||
this.content+= c;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
addEventListener("onssrend", ()=> scopes.clear());
|
||||
addEventListener("oneachrender", ()=> document.head.append(
|
||||
Object.assign(document.createElement("link"), { rel: "stylesheet", href: styles.location })
|
||||
));
|
||||
|
Reference in New Issue
Block a user