1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2024-11-21 23:39:37 +01:00

💥 📝

This commit is contained in:
Jan Andrle 2023-11-10 17:15:59 +01:00
parent 4d3a513713
commit 2569b9cd45
Signed by: jaandrle
GPG Key ID: B3A25AED155AFFAB
30 changed files with 420 additions and 361 deletions

View File

@ -2,48 +2,25 @@
/* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */
echo("Building static documentation files…");
echo("Preparing…");
const path_target= {
root: "docs/",
css: "docs/"
};
import { path_target, pages, styles, dispatchEvent } from "../docs_src/ssr.js";
import { createHTMl } from "./docs/jsdom.js";
import { register } from "../jsdom.js";
const pkg= s.cat("package.json").xargs(JSON.parse);
const pages= [
{ id: "index", title: "Introduction", description: "Introducing a library and motivations." },
{ id: "elements", title: "Elements", description: "Basic concepts of elements modifications and creations." }
];
for(const info of pages){
const { id }= info;
echo(`Generating ${id}.html…`);
const ssr= createHTMl("");
const { el }= await register(ssr.dom);
const { page, css }= await import(`../docs_src/${id}.html.js`); //→ TODO: important to mention in docs!!!
const { page }= await import(`../docs_src/${id}.html.js`); //→ TODO: important to mention in docs!!!
document.body.append(
el(page, { pkg, info, path_target, pages, registerClientFile }),
el(page, { pkg, info }),
);
echo.use("-R", `Writing ${id}.html…`);
dispatchEvent("oneachrender", document);
s.echo(ssr.serialize()).to(path_target.root+id+".html");
s.echo(css.content).to(path_target.css+id+".css");
}
s.echo(styles.content).to(path_target.css+styles.name);
dispatchEvent("onssrend");
echo("Done");
/**
* @typedef registerClientFile
* @type {function}
* @param {URL} url
* @param {HTMLScriptElement|HTMLLinkElement} [element_head]
* */
function registerClientFile(url, element_head){
const file_name= url.pathname.split("/").pop();
s.cat(url).to(path_target.root+file_name);
if(!element_head) return;
element_head[element_head instanceof HTMLScriptElement ? "src" : "href"]= file_name;
document.head.append(
element_head
);
}

File diff suppressed because one or more lines are too long

18
dist/dde.js vendored

File diff suppressed because one or more lines are too long

View File

@ -121,7 +121,7 @@ interface On{
) : EE;
}
export const on: On;
type Scope= { scope: Node | Function | Object, host: ddeElementModifier<any>, prevent: boolean, inherit_host: boolean, }
type Scope= { scope: Node | Function | Object, host: ddeElementModifier<any>, custom_element: false | HTMLElement, prevent: boolean }
/** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */
export const scope: {
current: Scope,
@ -431,6 +431,10 @@ declare global{
/** Elements returned by {@link el} return parent element for `.append` method. **Regullarly created elements are untouched.** */
append: ddeAppend<DocumentFragment>;
}
interface SVGElement{
/** Elements returned by {@link el} return parent element for `.append` method. **Regullarly created elements are untouched.** */
append: ddeAppend<SVGElement>;
}
}
export type Signal<V, A>= (set?: V)=> V & A;
type Action<V>= (this: { value: V }, ...a: any[])=> typeof S._ | void;

File diff suppressed because one or more lines are too long

6
dist/esm.d.ts vendored
View File

@ -121,7 +121,7 @@ interface On{
) : EE;
}
export const on: On;
type Scope= { scope: Node | Function | Object, host: ddeElementModifier<any>, prevent: boolean, inherit_host: boolean, }
type Scope= { scope: Node | Function | Object, host: ddeElementModifier<any>, custom_element: false | HTMLElement, prevent: boolean }
/** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */
export const scope: {
current: Scope,
@ -431,4 +431,8 @@ declare global{
/** Elements returned by {@link el} return parent element for `.append` method. **Regullarly created elements are untouched.** */
append: ddeAppend<DocumentFragment>;
}
interface SVGElement{
/** Elements returned by {@link el} return parent element for `.append` method. **Regullarly created elements are untouched.** */
append: ddeAppend<SVGElement>;
}
}

2
dist/esm.js vendored

File diff suppressed because one or more lines are too long

12
docs/code.js.js Normal file
View File

@ -0,0 +1,12 @@
const highlighter= await shiki.getHighlighter({
theme: "css-variables",
langs: ["js", "ts", "css", "html", "shell"],
});
const codeBlocks= document.querySelectorAll('code[class*="language-"]');
codeBlocks.forEach((block)=> {
const lang= block.className.replace("language-", "");
block.parentElement.dataset.js= "done";
const html= highlighter.codeToHtml(block.textContent, { lang });
block.innerHTML= html;
});

View File

@ -1,4 +1,4 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="elements.css"><meta name="description" content="Basic concepts of elements modifications and creations."><!--<dde:mark type="component" name="metaTwitter" host="this"/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this"/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><title>`deka-dom-el` — Elements</title><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script></head><body><!--<dde:mark type="component" name="page" host="this"/>--><!--<dde:mark type="component" name="header" host="this"/>--><header><h1>`deka-dom-el` — Elements</h1><p>Basic concepts of elements modifications and creations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewbox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement"/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library and motivations.">1. Introduction</a><a href="elements" title="Basic concepts of elements modifications and creations." class="current">2. Elements</a></nav><main><h2>Native JavaScript DOM elements creations</h2><p>Lets go through all patterns we would like to use and what needs to be improved for better experience.</p><h3>Creating element(s) (with custom attributes)</h3><p>You can create a native DOM element by using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement" title="MDN documentation for document.createElement()"><code>document.createElement()</code></a>. It is also possible to provide a&nbsp;some attribute(s) declaratively using <code>Object.assign()</code>. More precisely, this way you can sets some <a href="https://developer.mozilla.org/en-US/docs/Glossary/IDL" title="MDN page about Interface Description Language"><abbr title="Interface Description Language">IDL</abbr></a>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-m4hdt" class="example"><pre><code class="language-javascript">document.body.append(
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Basic concepts of elements modifications and creations."><title>`deka-dom-el` — Elements</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr="true"/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr="true"/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr="true"/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr="true"/>--><!--<dde:mark type="component" name="header" host="this" ssr="true"/>--><header><h1>`deka-dom-el` — Elements</h1><p>Basic concepts of elements modifications and creations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewbox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr="true"/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library and motivations.">1. Introduction</a><a href="elements" title="Basic concepts of elements modifications and creations." class="current">2. Elements</a></nav><main><h2>Native JavaScript DOM elements creations</h2><p>Lets go through all patterns we would like to use and what needs to be improved for better experience.</p><h3>Creating element(s) (with custom attributes)</h3><p>You can create a native DOM element by using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement" title="MDN documentation for document.createElement()"><code>document.createElement()</code></a>. It is also possible to provide a&nbsp;some attribute(s) declaratively using <code>Object.assign()</code>. More precisely, this way you can sets some <a href="https://developer.mozilla.org/en-US/docs/Glossary/IDL" title="MDN page about Interface Description Language"><abbr title="Interface Description Language">IDL</abbr></a>.</p><!--<dde:mark type="component" name="example" host="this" ssr="true"/>--><div id="code-e263u" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr="true"/>--><code class="language-js">document.body.append(
document.createElement("div")
);
console.log(
@ -12,7 +12,7 @@ document.body.append(
{ textContent: "Elements text content.", style: "color: coral;" }
)
);
</code></pre></div><script>Flems(document.getElementById("code-m4hdt"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"document.body.append(\\n\\tdocument.createElement(\\\"div\\\")\\n);\\nconsole.log(\\n\\t\\\"Emty div is generated inside <body>:\\\",\\n\\tdocument.body.innerHTML.includes(\\\"<div></div>\\\")\\n);\\n\\ndocument.body.append(\\n\\tObject.assign(\\n\\t\\tdocument.createElement(\\\"p\\\"),\\n\\t\\t{ textContent: \\\"Elements text content.\\\", style: \\\"color: coral;\\\" }\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><p>To make this easier, you can use the <code>el</code> function. Internally in basic examples, it is wrapper around <code>assign(document.createElement(…), { … })</code>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-5855d" class="example"><pre><code class="language-javascript">import { el, assign } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
</code></div><script>Flems(document.getElementById("code-e263u"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"document.body.append(\\n\\tdocument.createElement(\\\"div\\\")\\n);\\nconsole.log(\\n\\t\\\"Emty div is generated inside <body>:\\\",\\n\\tdocument.body.innerHTML.includes(\\\"<div></div>\\\")\\n);\\n\\ndocument.body.append(\\n\\tObject.assign(\\n\\t\\tdocument.createElement(\\\"p\\\"),\\n\\t\\t{ textContent: \\\"Elements text content.\\\", style: \\\"color: coral;\\\" }\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><p>To make this easier, you can use the <code>el</code> function. Internally in basic examples, it is wrapper around <code>assign(document.createElement(…), { … })</code>.</p><!--<dde:mark type="component" name="example" host="this" ssr="true"/>--><div id="code-xpmns" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr="true"/>--><code class="language-js">import { el, assign } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
const color= "lightcoral";
document.body.append(
el("p", { textContent: "Hello (first time)", style: { color } })
@ -23,7 +23,7 @@ document.body.append(
{ textContent: "Hello (second time)", style: { color } }
)
);
</code></pre></div><script>Flems(document.getElementById("code-5855d"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, assign } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst color= \\\"lightcoral\\\";\\ndocument.body.append(\\n\\tel(\\\"p\\\", { textContent: \\\"Hello (first time)\\\", style: { color } })\\n);\\ndocument.body.append(\\n\\tassign(\\n\\t\\tdocument.createElement(\\\"p\\\"),\\n\\t\\t{ textContent: \\\"Hello (second time)\\\", style: { color } }\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><p>The <code>assign</code> function provides improved behaviour of <code>Object.assign()</code>. You can declaratively sets any IDL and attribute of the given element. Function prefers IDL and fallback to the <code>element.setAttribute</code> if there is no writable property in the element prototype.</p><p>You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements inherits from <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement">HTMLElement</a>. To see all available IDLs for example for paragraphs, see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement">HTMLParagraphElement</a>. Moreover, the <code>assign</code> provides a&nbsp;way to sets declaratively some convenient properties:</p><ul><li>It is possible to sets <code>data-*</code>/<code>aria-*</code> attributes using object notation.</li><li>In opposite, it is also possible to sets <code>data-*</code>/<code>aria-*</code> attribute using camelCase notation.</li><li>You can use string or object as a&nbsp;value for <code>style</code> property.</li><li><code>className</code> (IDL preffered)/<code>class</code> are ways to add CSS class to the element. You can use string (similarly to <code>class="…"</code> syntax in HTML) or array of strings. This is handy to concat conditional classes.</li><li>Use <code>classList</code> to toggle specific classes. This will be handy later when the reactivity via signals is beeing introduced.</li><li>The <code>assign</code> also accepts the <code>undefined</code> as a&nbsp;value for any property to remove it from the element declaratively. Also for some IDL the corresponding attribute is removed as it can be confusing. <em>For example, natievly the elements <code>id</code> is removed by setting the IDL to an empty string.</em></li></ul><p>For processing, the <code>assign</code> internally uses <code>assignAttribute</code> and <code>classListDeclarative</code>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-5f8sp" class="example"><pre><code class="language-javascript">import { assignAttribute, classListDeclarative } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
</code></div><script>Flems(document.getElementById("code-xpmns"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, assign } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst color= \\\"lightcoral\\\";\\ndocument.body.append(\\n\\tel(\\\"p\\\", { textContent: \\\"Hello (first time)\\\", style: { color } })\\n);\\ndocument.body.append(\\n\\tassign(\\n\\t\\tdocument.createElement(\\\"p\\\"),\\n\\t\\t{ textContent: \\\"Hello (second time)\\\", style: { color } }\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><p>The <code>assign</code> function provides improved behaviour of <code>Object.assign()</code>. You can declaratively sets any IDL and attribute of the given element. Function prefers IDL and fallback to the <code>element.setAttribute</code> if there is no writable property in the element prototype.</p><p>You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements inherits from <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement">HTMLElement</a>. To see all available IDLs for example for paragraphs, see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement">HTMLParagraphElement</a>. Moreover, the <code>assign</code> provides a&nbsp;way to sets declaratively some convenient properties:</p><ul><li>It is possible to sets <code>data-*</code>/<code>aria-*</code> attributes using object notation.</li><li>In opposite, it is also possible to sets <code>data-*</code>/<code>aria-*</code> attribute using camelCase notation.</li><li>You can use string or object as a&nbsp;value for <code>style</code> property.</li><li><code>className</code> (IDL preffered)/<code>class</code> are ways to add CSS class to the element. You can use string (similarly to <code>class="…"</code> syntax in HTML) or array of strings. This is handy to concat conditional classes.</li><li>Use <code>classList</code> to toggle specific classes. This will be handy later when the reactivity via signals is beeing introduced.</li><li>The <code>assign</code> also accepts the <code>undefined</code> as a&nbsp;value for any property to remove it from the element declaratively. Also for some IDL the corresponding attribute is removed as it can be confusing. <em>For example, natievly the elements <code>id</code> is removed by setting the IDL to an empty string.</em></li></ul><p>For processing, the <code>assign</code> internally uses <code>assignAttribute</code> and <code>classListDeclarative</code>.</p><!--<dde:mark type="component" name="example" host="this" ssr="true"/>--><div id="code-htu1k" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr="true"/>--><code class="language-js">import { assignAttribute, classListDeclarative } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
const paragraph= document.createElement("p");
assignAttribute(paragraph, "textContent", "Hello, world!");
@ -48,7 +48,7 @@ console.log(paragraph.outerHTML);
document.body.append(
paragraph
);
</code></pre></div><script>Flems(document.getElementById("code-5f8sp"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { assignAttribute, classListDeclarative } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst paragraph= document.createElement(\\\"p\\\");\\n\\nassignAttribute(paragraph, \\\"textContent\\\", \\\"Hello, world!\\\");\\nassignAttribute(paragraph, \\\"style\\\", { color: \\\"navy\\\" });\\n\\nassignAttribute(paragraph, \\\"dataTest1\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"dataset\\\", { test2: \\\"v2\\\" });\\n\\nassignAttribute(paragraph, \\\"ariaLabel\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"ariaset\\\", { role: \\\"none\\\" });\\n\\n\\nclassListDeclarative(paragraph, {\\n\\tclassAdd: true,\\n\\tclassRemove: false,\\n\\tclassAdd1: 1,\\n\\tclassRemove1: 0,\\n\\tclassToggle: -1\\n});\\n\\nconsole.log(paragraph.outerHTML);\\ndocument.body.append(\\n\\tparagraph\\n);\\n\"}],\"toolbar\":false}"));</script><h3>Native JavaScript templating</h3><p>By default, the native JS has no good way to define HTML template using DOM API:</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-48dwd" class="example"><pre><code class="language-javascript">document.body.append(
</code></div><script>Flems(document.getElementById("code-htu1k"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { assignAttribute, classListDeclarative } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst paragraph= document.createElement(\\\"p\\\");\\n\\nassignAttribute(paragraph, \\\"textContent\\\", \\\"Hello, world!\\\");\\nassignAttribute(paragraph, \\\"style\\\", { color: \\\"navy\\\" });\\n\\nassignAttribute(paragraph, \\\"dataTest1\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"dataset\\\", { test2: \\\"v2\\\" });\\n\\nassignAttribute(paragraph, \\\"ariaLabel\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"ariaset\\\", { role: \\\"none\\\" });\\n\\n\\nclassListDeclarative(paragraph, {\\n\\tclassAdd: true,\\n\\tclassRemove: false,\\n\\tclassAdd1: 1,\\n\\tclassRemove1: 0,\\n\\tclassToggle: -1\\n});\\n\\nconsole.log(paragraph.outerHTML);\\ndocument.body.append(\\n\\tparagraph\\n);\\n\"}],\"toolbar\":false}"));</script><h3>Native JavaScript templating</h3><p>By default, the native JS has no good way to define HTML template using DOM API:</p><!--<dde:mark type="component" name="example" host="this" ssr="true"/>--><div id="code-8845d" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr="true"/>--><code class="language-js">document.body.append(
document.createElement("div"),
document.createElement("span"),
document.createElement("main")
@ -59,7 +59,7 @@ const template= document.createElement("main").append(
document.createElement("span"),
);
console.log(typeof template==="undefined");
</code></pre></div><script>Flems(document.getElementById("code-48dwd"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"document.body.append(\\n\\tdocument.createElement(\\\"div\\\"),\\n\\tdocument.createElement(\\\"span\\\"),\\n\\tdocument.createElement(\\\"main\\\")\\n);\\nconsole.log(document.body.innerHTML.includes(\\\"<div></div><span></span><main></main>\\\"));\\nconst template= document.createElement(\\\"main\\\").append(\\n\\tdocument.createElement(\\\"div\\\"),\\n\\tdocument.createElement(\\\"span\\\"),\\n);\\nconsole.log(typeof template===\\\"undefined\\\");\\n\"}],\"toolbar\":false}"));</script><p>This library therefore overwrites the <code>append</code> method of created elements to always return parent element.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-k8b3j" class="example"><pre><code class="language-javascript">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
</code></div><script>Flems(document.getElementById("code-8845d"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"document.body.append(\\n\\tdocument.createElement(\\\"div\\\"),\\n\\tdocument.createElement(\\\"span\\\"),\\n\\tdocument.createElement(\\\"main\\\")\\n);\\nconsole.log(document.body.innerHTML.includes(\\\"<div></div><span></span><main></main>\\\"));\\nconst template= document.createElement(\\\"main\\\").append(\\n\\tdocument.createElement(\\\"div\\\"),\\n\\tdocument.createElement(\\\"span\\\"),\\n);\\nconsole.log(typeof template===\\\"undefined\\\");\\n\"}],\"toolbar\":false}"));</script><p>This library therefore overwrites the <code>append</code> method of created elements to always return parent element.</p><!--<dde:mark type="component" name="example" host="this" ssr="true"/>--><div id="code-5w6nn" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr="true"/>--><code class="language-js">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
document.head.append(
el("style").append(
"tr, td{ border: 1px solid red; padding: 1em; }",
@ -83,7 +83,7 @@ document.body.append(
)
)
);
</code></pre></div><script>Flems(document.getElementById("code-k8b3j"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\"tr, td{ border: 1px solid red; padding: 1em; }\\\",\\n\\t\\t\\\"table{ border-collapse: collapse; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(\\\"p\\\", \\\"Example of a complex template. Using for example nesting lists:\\\"),\\n\\tel(\\\"ul\\\").append(\\n\\t\\tel(\\\"li\\\", \\\"List item 1\\\"),\\n\\t\\tel(\\\"li\\\").append(\\n\\t\\t\\tel(\\\"ul\\\").append(\\n\\t\\t\\t\\tel(\\\"li\\\", \\\"Nested list item 1\\\"),\\n\\t\\t\\t)\\n\\t\\t)\\n\\t),\\n\\tel(\\\"table\\\").append(\\n\\t\\tel(\\\"tr\\\").append(\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 Col 1\\\"),\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 Col 2\\\")\\n\\t\\t)\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><h2>Creating advanced (reactive) templates and components</h2><h3>Basic components</h3><p>You can use functions for encapsulation (repeating) logic. The <code>el</code> accepts function as first argument. In that case, the function should return dom elements and the second argument for <code>el</code> is argument for given element.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-4qwvd" class="example"><pre><code class="language-javascript">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
</code></div><script>Flems(document.getElementById("code-5w6nn"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\"tr, td{ border: 1px solid red; padding: 1em; }\\\",\\n\\t\\t\\\"table{ border-collapse: collapse; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(\\\"p\\\", \\\"Example of a complex template. Using for example nesting lists:\\\"),\\n\\tel(\\\"ul\\\").append(\\n\\t\\tel(\\\"li\\\", \\\"List item 1\\\"),\\n\\t\\tel(\\\"li\\\").append(\\n\\t\\t\\tel(\\\"ul\\\").append(\\n\\t\\t\\t\\tel(\\\"li\\\", \\\"Nested list item 1\\\"),\\n\\t\\t\\t)\\n\\t\\t)\\n\\t),\\n\\tel(\\\"table\\\").append(\\n\\t\\tel(\\\"tr\\\").append(\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 Col 1\\\"),\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 Col 2\\\")\\n\\t\\t)\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><h3>Basic (state-less) components</h3><p>You can use functions for encapsulation (repeating) logic. The <code>el</code> accepts function as first argument. In that case, the function should return dom elements and the second argument for <code>el</code> is argument for given element.</p><!--<dde:mark type="component" name="example" host="this" ssr="true"/>--><div id="code-qvyuf" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr="true"/>--><code class="language-js">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
document.head.append(
el("style").append(
".class1{ font-weight: bold; }",
@ -100,4 +100,4 @@ function component({ className, textContent }){
el("p", textContent)
);
}
</code></pre></div><script>Flems(document.getElementById("code-4qwvd"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\".class1{ font-weight: bold; }\\\",\\n\\t\\t\\\".class2{ color: purple; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(component, { className: \\\"class2\\\", textContent: \\\"Hello World!\\\" }),\\n\\tcomponent({ className: \\\"class2\\\", textContent: \\\"Hello World!\\\" })\\n);\\n\\nfunction component({ className, textContent }){\\n\\treturn el(\\\"div\\\", { className: [ \\\"class1\\\", className ] }).append(\\n\\t\\tel(\\\"p\\\", textContent)\\n\\t);\\n}\\n\"}],\"toolbar\":false}"));</script><p>It is nice to use similar naming convention as native DOM API.</p></main></body></html>
</code></div><script>Flems(document.getElementById("code-qvyuf"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\".class1{ font-weight: bold; }\\\",\\n\\t\\t\\\".class2{ color: purple; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(component, { className: \\\"class2\\\", textContent: \\\"Hello World!\\\" }),\\n\\tcomponent({ className: \\\"class2\\\", textContent: \\\"Hello World!\\\" })\\n);\\n\\nfunction component({ className, textContent }){\\n\\treturn el(\\\"div\\\", { className: [ \\\"class1\\\", className ] }).append(\\n\\t\\tel(\\\"p\\\", textContent)\\n\\t);\\n}\\n\"}],\"toolbar\":false}"));</script><p>It is nice to use similar naming convention as native DOM API.</p><h3>Creating non-HTML elements</h3><div class="prevNext"><!--<dde:mark type="component" name="prevNext" host="parentElement" ssr="true"/>--><a rel="prev" href="./" title="Introducing a&nbsp;library and motivations."><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr="true"/>-->Introduction (previous)</a><!--<dde:mark type="component" name="pageLink" host="this" ssr="true"/>--></div></main></body></html>

View File

@ -38,21 +38,21 @@ body > nav{
flex-flow: column nowrap;
}
body > nav {
font-size:1rem;
line-height:2;
padding:1rem 0 0 0
font-size: 1rem;
line-height: 2;
padding: 1rem 0 0 0;
}
body > nav ol,
body > nav ul {
align-content:space-around;
align-items:center;
display:flex;
flex-direction:row;
flex-wrap:wrap;
justify-content:center;
list-style-type:none;
margin:0;
padding:0
align-content: space-around;
align-items: center;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
list-style-type: none;
margin: 0;
padding: 0;
}
body > nav ol li,
body > nav ul li {
@ -96,10 +96,13 @@ body > nav a:hover{
main{
grid-area: content;
display: grid;
grid-template-columns: 1fr min(var(--body-max-width), 90%) 1fr;
grid-template-columns:
[full-main-start] 1fr
[main-start] min(var(--body-max-width), 90%) [main-end]
1fr [full-main-end];
}
main > *{
grid-column: 2;
grid-column: main;
}
.icon {
vertical-align: sub;
@ -116,10 +119,49 @@ main > *{
font-size: .9rem;
font-style: italic;
}
.code{
--shiki-color-text: #e9eded;
--shiki-color-background: #212121;
--shiki-token-constant: #82b1ff;
--shiki-token-string: #c3e88d;
--shiki-token-comment: #546e7a;
--shiki-token-keyword: #c792ea;
--shiki-token-parameter: #AA0000;
--shiki-token-function: #80cbae;
--shiki-token-string-expression: #c3e88d;
--shiki-token-punctuation: var(--code);
--shiki-token-link: #EE0000;
white-space: pre;
}
.code[data-js=todo]{
border: 1px solid var(--border);
border-radius: var(--standard-border-radius);
margin-bottom: 1rem;
margin-top: 18.4px;
padding: 1rem 1.4rem;
}
.example{
grid-column: 1/-1;
grid-column: full-main;
width: 100%;
max-width: calc(9/5 * var(--body-max-width));
height: calc(3/5 * var(--body-max-width));
margin-inline: auto;
}
.CodeMirror, .CodeMirror-gutters {
background: #212121 !important;
border: 1px solid white;
}
.prevNext{
display: grid;
grid-template-columns: 1fr 2fr 1fr;
margin-top: 1rem;
border-top: 1px solid var(--border);
}
.prevNext [rel=prev]{
grid-column: 1;
}
.prevNext [rel=next]{
grid-column: 3;
text-align: right;
}

View File

@ -1,4 +1,4 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="index.css"><meta name="description" content="Introducing a&nbsp;library and motivations."><!--<dde:mark type="component" name="metaTwitter" host="this"/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this"/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><title>`deka-dom-el` — Introduction</title><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script></head><body><!--<dde:mark type="component" name="page" host="this"/>--><!--<dde:mark type="component" name="header" host="this"/>--><header><h1>`deka-dom-el` — Introduction</h1><p>Introducing a&nbsp;library and motivations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewbox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement"/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library and motivations." class="current">1. Introduction</a><a href="elements" title="Basic concepts of elements modifications and creations.">2. Elements</a></nav><main><p>The library tries to provide pure JavaScript tool(s) to create reactive interfaces. </p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-duj4w" class="example"><pre><code class="language-javascript">import { el, S } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Introducing a&nbsp;library and motivations."><title>`deka-dom-el` — Introduction</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr="true"/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr="true"/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr="true"/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr="true"/>--><!--<dde:mark type="component" name="header" host="this" ssr="true"/>--><header><h1>`deka-dom-el` — Introduction</h1><p>Introducing a&nbsp;library and motivations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewbox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr="true"/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library and motivations." class="current">1. Introduction</a><a href="elements" title="Basic concepts of elements modifications and creations.">2. Elements</a></nav><main><p>The library tries to provide pure JavaScript tool(s) to create reactive interfaces.</p><!--<dde:mark type="component" name="example" host="this" ssr="true"/>--><div id="code-dn64k" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr="true"/>--><code class="language-js">import { el, S } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
const clicks= S(0);
document.body.append(
el().append(
@ -12,4 +12,4 @@ document.body.append(
})
)
);
</code></pre></div><script>Flems(document.getElementById("code-duj4w"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, S } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst clicks= S(0);\\ndocument.body.append(\\n\\tel().append(\\n\\t\\tel(\\\"p\\\", S(()=>\\n\\t\\t\\t\\\"Hello World \\\"+\\\"🎉\\\".repeat(clicks())\\n\\t\\t)),\\n\\t\\tel(\\\"button\\\", {\\n\\t\\t\\ttype: \\\"button\\\",\\n\\t\\t\\tonclick: ()=> clicks(clicks()+1),\\n\\t\\t\\ttextContent: \\\"Fire\\\"\\n\\t\\t})\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script></main></body></html>
</code></div><script>Flems(document.getElementById("code-dn64k"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, S } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst clicks= S(0);\\ndocument.body.append(\\n\\tel().append(\\n\\t\\tel(\\\"p\\\", S(()=>\\n\\t\\t\\t\\\"Hello World \\\"+\\\"🎉\\\".repeat(clicks())\\n\\t\\t)),\\n\\t\\tel(\\\"button\\\", {\\n\\t\\t\\ttype: \\\"button\\\",\\n\\t\\t\\tonclick: ()=> clicks(clicks()+1),\\n\\t\\t\\ttextContent: \\\"Fire\\\"\\n\\t\\t})\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><div class="prevNext"><!--<dde:mark type="component" name="prevNext" host="parentElement" ssr="true"/>--><!--<dde:mark type="component" name="pageLink" host="this" ssr="true"/>--><a rel="next" href="elements" title="Basic concepts of elements modifications and creations."><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr="true"/>-->(next) Elements</a></div></main></body></html>

View File

@ -0,0 +1,59 @@
import { registerClientFile, styles } from "../ssr.js";
styles.scope(code).css`
:host{
--shiki-color-text: #e9eded;
--shiki-color-background: #212121;
--shiki-token-constant: #82b1ff;
--shiki-token-string: #c3e88d;
--shiki-token-comment: #546e7a;
--shiki-token-keyword: #c792ea;
--shiki-token-parameter: #AA0000;
--shiki-token-function: #80cbae;
--shiki-token-string-expression: #c3e88d;
--shiki-token-punctuation: var(--code);
--shiki-token-link: #EE0000;
white-space: pre;
}
:host[data-js=todo]{
border: 1px solid var(--border);
border-radius: var(--standard-border-radius);
margin-bottom: 1rem;
${/* to fix shift when → dataJS=done */""}
margin-top: 18.4px;
padding: 1rem 1.4rem;
}
`;
import { el } from "deka-dom-el";
/**
* Prints code to the page and registers flems to make it interactive.
* @param {object} attrs
* @param {string} [attrs.id]
* @param {string} [attrs.className]
* @param {string} attrs.content Example code file path
* @param {"js"|"ts"|"html"|"css"} [attrs.language="js"] Language of the code
* @param {string} [attrs.page_id] ID of the page, if setted it registers shiki
* */
export function code({ id, content, language= "js", className= "code", page_id }){
let dataJS;
if(page_id){
registerClientPart(page_id);
dataJS= "todo";
}
return el("div", { id, className, dataJS }).append(
el("code", { className: "language-"+language, textContent: content })
);
}
let is_registered= {};
/** @param {string} page_id */
function registerClientPart(page_id){
if(is_registered[page_id]) return;
document.head.append(
el("script", { src: "https://cdn.jsdelivr.net/npm/shiki", defer: true }),
);
registerClientFile(
new URL("./code.js.js", import.meta.url),
el("script", { type: "module" })
);
is_registered[page_id]= true;
}

View File

@ -0,0 +1,12 @@
const highlighter= await shiki.getHighlighter({
theme: "css-variables",
langs: ["js", "ts", "css", "html", "shell"],
});
const codeBlocks= document.querySelectorAll('code[class*="language-"]');
codeBlocks.forEach((block)=> {
const lang= block.className.replace("language-", "");
block.parentElement.dataset.js= "done";
const html= highlighter.codeToHtml(block.textContent, { lang });
block.innerHTML= html;
});

View File

@ -1,59 +1,50 @@
let is_registered= {};
import { styles } from "../index.css.js";
export const css= styles().scope(example).css`
import { styles } from "../ssr.js";
styles.scope(example).css`
:host{
grid-column: 1/-1;
grid-column: full-main;
width: 100%;
max-width: calc(9/5 * var(--body-max-width));
height: calc(3/5 * var(--body-max-width));
margin-inline: auto;
}
.CodeMirror, .CodeMirror-gutters {
background: #212121 !important;
border: 1px solid white;
}
`
import { el } from "deka-dom-el";
import { code } from "./code.html.js";
/**
* Prints code to the page and registers flems to make it interactive.
* @param {object} attrs
* @param {URL} attrs.src Example code file path
* @param {string} [attrs.language="javascript"] Language of the code
* @param {"js"|"ts"|"html"|"css"} [attrs.language="js"] Language of the code
* @param {string} attrs.page_id ID of the page
* @param {import("../types.d.ts").registerClientFile} attrs.registerClientFile
* */
export function example({ src, language= "javascript", page_id, registerClientFile }){
registerClientPart(page_id, registerClientFile);
const code= s.cat(src).toString()
export function example({ src, language= "js", page_id }){
registerClientPart(page_id);
const content= s.cat(src).toString()
.replaceAll(' from "../../../index-with-signals.js";', ' 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);
return el().append(
el("div", { id, className: example.name }).append(
el("pre").append(
el("code", { className: "language-"+language, textContent: code })
)
),
elCode({ id, content: code })
el(code, { id, content, language, className: example.name }),
elCode({ id, content, extension: "."+language })
);
}
function elCode({ id, content }){
function elCode({ id, content, extension: name }){
const options= JSON.stringify({
files: [{ name: ".js", content }],
files: [{ name, content }],
toolbar: false
});
return el("script", `Flems(document.getElementById("${id}"), JSON.parse(${JSON.stringify(options)}));`);
}
function registerClientPart(page_id, registerClientFile){
let is_registered= {};
/** @param {string} page_id */
function registerClientPart(page_id){
if(is_registered[page_id]) return;
//★ Highlite code when no flems?
document.head.append(
el("script", { src: "https://flems.io/flems.html", type: "text/javascript", charset: "utf-8" }),
//★ el("script", { src: "https://cdn.jsdelivr.net/npm/shiki", defer: true }),
);
const d= el("div");
/** @param {HTMLDivElement} a */
const f= (a)=> a;
f(d); //←
//★ egisterClientFile(
//★ new URL("./example.js.js", import.meta.url),
//★ el("script", { type: "module" })
//★ ;
is_registered[page_id]= true;
}

View File

@ -1,19 +0,0 @@
const langs= {
javascript: 'js',
js: 'js',
html: 'html',
};
const highlighter= await shiki.getHighlighter({
theme: 'css-variables',
langs: ['js', 'html', 'shell'],
});
const codeBlocks= document.querySelectorAll('pre code[class*="language-"]');
codeBlocks.forEach((block)=> {
const lang= block.className.replace('language-', '');
const html= highlighter.codeToHtml(block.textContent, {
lang: langs[lang] || lang,
});
block.innerHTML= html;
});

View File

@ -0,0 +1,41 @@
import { pages, styles } from "../ssr.js";
styles.scope(prevNext).css`
:host{
display: grid;
grid-template-columns: 1fr 2fr 1fr;
margin-top: 1rem;
border-top: 1px solid var(--border);
}
:host [rel=prev]{
grid-column: 1;
}
:host [rel=next]{
grid-column: 3;
text-align: right;
}
`;
import { el } from "../../index.js";
/**
* @param {import("../types.d.ts").Info} page
* */
export function prevNext(page){
const page_index= pages.indexOf(page);
return el("div", { className: prevNext.name }).append(
el(pageLink, { rel: "prev", page: pages[page_index-1] }),
el(pageLink, { rel: "next", page: pages[page_index+1] })
);
}
/**
* @param {Object} attrs
* @param {"prev"|"next"} attrs.rel
* @param {import("../types.d.ts").Info} [attrs.page]
* */
function pageLink({ rel, page }){
if(!page) return el();
let { href, title, description }= page;
return el("a", { rel, href, title: description }).append(
rel==="next" ?"(next) " : "",
title,
rel==="prev" ? " (previous)" : "",
);
}

View File

@ -1,22 +1,16 @@
import "./global.css.js";
import { el } from "deka-dom-el";
import { styles, common } from "./index.css.js";
import { example, css as example_css } from "./components/example.html.js";
export const css= styles()
.include(common)
.css`
.note{
font-size: .9rem;
font-style: italic;
}
`
.include(example_css);
import { example } from "./components/example.html.js";
/** @param {string} url */
const fileURL= url=> new URL(url, import.meta.url);
import { header } from "./layout/head.html.js";
import { prevNext } from "./components/prevNext.html.js";
/** @param {import("./types.d.ts").PageAttrs} attrs */
export function page({ pkg, info, path_target, pages, registerClientFile }){
export function page({ pkg, info }){
const page_id= info.id;
return el().append(
el(header, { info, pkg, path_target, pages }),
el(header, { info, pkg }),
el("main").append(
el("h2", "Native JavaScript DOM elements creations"),
el("p", "Lets go through all patterns we would like to use and what needs to be improved for better experience."),
@ -36,12 +30,12 @@ export function page({ pkg, info, path_target, pages, registerClientFile }){
el("abbr", { textContent: "IDL", title: "Interface Description Language" })
), "."
),
el(example, { src: new URL("./components/examples/nativeCreateElement.js", import.meta.url), page_id, registerClientFile }),
el(example, { src: fileURL("./components/examples/nativeCreateElement.js"), page_id }),
el("p").append(
"To make this easier, you can use the ", el("code", "el"), " function. ",
"Internally in basic examples, it is wrapper around ", el("code", "assign(document.createElement(…), { … })"), "."
),
el(example, { src: new URL("./components/examples/dekaCreateElement.js", import.meta.url), page_id, registerClientFile }),
el(example, { src: fileURL("./components/examples/dekaCreateElement.js"), page_id }),
el("p").append(
"The ", el("code", "assign"), " function provides improved behaviour of ", el("code", "Object.assign()"), ". ",
"You can declaratively sets any IDL and attribute of the given element. ",
@ -82,27 +76,30 @@ export function page({ pkg, info, path_target, pages, registerClientFile }){
el("p").append(
"For processing, the ", el("code", "assign"), " internally uses ", el("code", "assignAttribute"), " and ", el("code", "classListDeclarative"), "."
),
el(example, { src: new URL("./components/examples/dekaAssign.js", import.meta.url), page_id, registerClientFile }),
el(example, { src: fileURL("./components/examples/dekaAssign.js"), page_id }),
el("h3", "Native JavaScript templating"),
el("p", "By default, the native JS has no good way to define HTML template using DOM API:"),
el(example, { src: new URL("./components/examples/nativeAppend.js", import.meta.url), page_id, registerClientFile }),
el(example, { src: fileURL("./components/examples/nativeAppend.js"), page_id }),
el("p").append(
"This library therefore overwrites the ", el("code", "append"), " method of created elements to always return parent element."
),
el(example, { src: new URL("./components/examples/dekaAppend.js", import.meta.url), page_id, registerClientFile }),
el(example, { src: fileURL("./components/examples/dekaAppend.js"), page_id }),
el("h2", "Creating advanced (reactive) templates and components"),
el("h3", "Basic components"),
el("h3", "Basic (state-less) components"),
el("p").append(
"You can use functions for encapsulation (repeating) logic. ",
"The ", el("code", "el"), " accepts function as first argument. ",
"In that case, the function should return dom elements and the second argument for ", el("code", "el"), " is argument for given element."
),
el(example, { src: new URL("./components/examples/dekaBasicComponent.js", import.meta.url), page_id, registerClientFile }),
el("p", "It is nice to use similar naming convention as native DOM API.")
el(example, { src: fileURL("./components/examples/dekaBasicComponent.js"), page_id }),
el("p", "It is nice to use similar naming convention as native DOM API."),
el("h3", "Creating non-HTML elements"),
// example & notes
el(prevNext, info)
)
);
}

View File

@ -1,3 +1,5 @@
import { styles } from "./ssr.js";
styles.scope(import.meta.url).css`
@import url(https://cdn.simplecss.org/simple.min.css);
:root{
--body-max-width: 45rem;
@ -38,21 +40,21 @@ body > nav{
flex-flow: column nowrap;
}
body > nav {
font-size:1rem;
line-height:2;
padding:1rem 0 0 0
font-size: 1rem;
line-height: 2;
padding: 1rem 0 0 0;
}
body > nav ol,
body > nav ul {
align-content:space-around;
align-items:center;
display:flex;
flex-direction:row;
flex-wrap:wrap;
justify-content:center;
list-style-type:none;
margin:0;
padding:0
align-content: space-around;
align-items: center;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
list-style-type: none;
margin: 0;
padding: 0;
}
body > nav ol li,
body > nav ul li {
@ -96,10 +98,13 @@ body > nav a:hover{
main{
grid-area: content;
display: grid;
grid-template-columns: 1fr min(var(--body-max-width), 90%) 1fr;
grid-template-columns:
[full-main-start] 1fr
[main-start] min(var(--body-max-width), 90%) [main-end]
1fr [full-main-end];
}
main > *{
grid-column: 2;
grid-column: main;
}
.icon {
vertical-align: sub;
@ -116,10 +121,4 @@ main > *{
font-size: .9rem;
font-style: italic;
}
.example{
grid-column: 1/-1;
width: 100%;
max-width: calc(9/5 * var(--body-max-width));
height: calc(3/5 * var(--body-max-width));
margin-inline: auto;
}
`;

View File

@ -1,145 +0,0 @@
const scopes= new WeakSet();
const s= {
scope(s){
if(!scopes.has(s)){
scopes.add(s);
this.host= s.name;
}
return this;
},
css(...a){
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;
},
include(...i){
if(this.content) this.content+= "\n";
this.content+= i.map(i=> typeof i === "string" ? i : i.content).join("\n");
return this;
}
};
export function css(...a){
return String.raw(...a).trim();
}
export function styles(){ return Object.assign(Object.create(s), { content: "" }); }
export const common= css`
@import url(https://cdn.simplecss.org/simple.min.css);
:root{
--body-max-width: 45rem;
--marked: #fb3779;
--code: #0d47a1;
--accent: #d81b60;
}
@media (prefers-color-scheme:dark) {
:root {
--accent: #f06292;
--code: #62c1f0;
}
}
body {
grid-template-columns: 100%;
grid-template-areas: "header" "sidebar" "content";
}
@media (min-width:768px) {
body{
grid-template-rows: auto auto;
grid-template-columns: calc(var(--body-max-width) / 3) auto;
grid-template-areas:
"header header"
"sidebar content"
}
}
body > *{
grid-column: unset;
}
body > header{
grid-area: header;
padding: 0;
}
body > nav{
grid-area: sidebar;
background-color: var(--accent-bg);
display: flex;
flex-flow: column nowrap;
}
body > nav {
font-size:1rem;
line-height:2;
padding:1rem 0 0 0
}
body > nav ol,
body > nav ul {
align-content:space-around;
align-items:center;
display:flex;
flex-direction:row;
flex-wrap:wrap;
justify-content:center;
list-style-type:none;
margin:0;
padding:0
}
body > nav ol li,
body > nav ul li {
display:inline-block
}
body > nav a,
body > nav a:visited {
margin: 0 .5rem 1rem .5rem;
border: 1px solid currentColor;
border-radius: var(--standard-border-radius);
color: var(--text-light);
display: inline-block;
padding: .1rem 1rem;
text-decoration: none;
cursor: pointer;
transition: all .15s;
}
body > nav a.current,
body > nav a[aria-current=page] {
background-color: var(--bg);
color: var(--text);
}
body > nav a:hover{
background-color: var(--bg);
color: var(--accent);
}
@media only screen and (max-width:720px) {
body > nav{
flex-flow: row wrap;
padding-block: .5rem;
}
body > nav a {
border:none;
text-decoration:underline;
margin-block: .1rem;
padding-block:.1rem;
line-height: 1rem;
font-size: .9rem;
}
}
main{
grid-area: content;
display: grid;
grid-template-columns: 1fr min(var(--body-max-width), 90%) 1fr;
}
main > *{
grid-column: 2;
}
.icon {
vertical-align: sub;
padding-right: .25rem;
display: inline-block;
width: 1em;
height: 1.3em;
margin-right: 0.2rem;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
}
`;

View File

@ -1,25 +1,18 @@
import { el } from "deka-dom-el";
import { styles, common } from "./index.css.js";
import { example, css as example_css } from "./components/example.html.js";
export const css= styles()
.include(common)
.css`
.note{
font-size: .9rem;
font-style: italic;
}
`
.include(example_css);
import "./global.css.js";
import { example } from "./components/example.html.js";
import { header } from "./layout/head.html.js";
import { prevNext } from "./components/prevNext.html.js";
/** @param {import("./types.d.ts").PageAttrs} attrs */
export function page({ pkg, info, path_target, pages, registerClientFile }){
export function page({ pkg, info }){
const page_id= info.id;
return el().append(
el(header, { info, pkg, path_target, pages }),
el(header, { info, pkg }),
el("main").append(
el("p", "The library tries to provide pure JavaScript tool(s) to create reactive interfaces. "),
el(example, { src: new URL("./components/examples/helloWorld.js", import.meta.url), page_id, registerClientFile }),
el("p", "The library tries to provide pure JavaScript tool(s) to create reactive interfaces."),
el(example, { src: new URL("./components/examples/helloWorld.js", import.meta.url), page_id }),
el(prevNext, info)
)
);
}

View File

@ -1,4 +1,5 @@
import { el, elNS, scope } from "deka-dom-el";
import { el, elNS } from "deka-dom-el";
import { pages } from "../ssr.js";
/**
* @param {object} def
* @param {import("../types.d.ts").Info} def.info
@ -6,12 +7,12 @@ import { el, elNS, scope } from "deka-dom-el";
* @param {string} def.pkg.name
* @param {string} def.pkg.description
* @param {string} def.pkg.homepage
* @param {{ root: string, css: string}} def.path_target Final URL where the page will be rendered.
* @param {import("../types.js").Pages} def.pages
* */
export function header({ info: { id, title, description }, pkg, path_target, pages }){
export function header({ info: { href, title, description }, pkg }){
title= `\`${pkg.name}\`${title}`;
document.head.append(head({ id, title, description, pkg, path_target }));
document.head.append(
head({ title, description, pkg })
);
return el().append(
el("header").append(
el("h1", title),
@ -23,23 +24,29 @@ export function header({ info: { id, title, description }, pkg, path_target, pag
"GitHub"
),
...pages.map((p, i)=> el("a", {
href: p.id==="index" ? "./" : p.id,
href: p.href==="index" ? "./" : p.href,
textContent: (i+1) + ". " + p.title,
title: p.description,
classList: { current: p.id===id }
classList: { current: p.href===href }
}))
)
);
}
function head({ id, title, description, pkg, path_target }){
function head({ title, description, pkg }){
return el().append(
el("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
el("link", { rel: "stylesheet", href: stylesheetHref(path_target, id) }),
el("meta", { name: "description", content: description }),
el("title", title),
el(metaAuthor),
el(metaTwitter, pkg),
el(metaFacebook, pkg),
el("title", title),
);
}
function metaAuthor(){
return el().append(
el("meta", { name: "author", content: "Jan Andrle" }),
el("link", { type: "text/plain", rel: "author", href: "https://jaandrle.github.io/humans.txt" }),
el("meta", { name: "generator", content: "deka-dom-el" }),
);
}
function metaTwitter({ name, description, homepage }){
@ -62,9 +69,6 @@ function metaFacebook({ name, description, homepage }){
el("meta", { name: "og:creator", content: "@jaandrle" }),
);
}
function stylesheetHref(path_target, name){
return path_target.css.replace(path_target.root, "")+name+".css";
}
function iconGitHub(){
const el= elNS("http://www.w3.org/2000/svg");
return el("svg", { className: "icon", viewBox: "0 0 32 32" }).append(

77
docs_src/ssr.js Normal file
View File

@ -0,0 +1,77 @@
export const path_target= {
root: "docs/",
css: "docs/"
};
export const pages= [
{ id: "index", href: "./", title: "Introduction", description: "Introducing a library and motivations." },
{ id: "elements", href: "elements", title: "Elements", description: "Basic concepts of elements modifications and creations." }
];
/**
* @typedef registerClientFile
* @type {function}
* @param {URL} url
* @param {HTMLScriptElement|HTMLLinkElement} [element_head]
* */
export function registerClientFile(url, element_head){
const file_name= url.pathname.split("/").pop();
s.cat(url).to(path_target.root+file_name);
if(!element_head) return;
element_head[element_head instanceof HTMLScriptElement ? "src" : "href"]= file_name;
document.head.append(
element_head
);
}
const events= {
oneachrender: new Set(),
onssrend: new Set()
};
/** @param {keyof typeof events} name @param {function} listener */
export function addEventListener(name, listener){
events[name].add(listener);
}
/** @param {keyof typeof events} name @param {any} a */
export function dispatchEvent(name, a){
const ls= events[name];
ls.forEach(l=> l(a));
if(name!=="oneachrender")
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 })
));
/** @type {typeof String.raw} */
function css(...a){ return String.raw(...a).trim(); }

1
docs_src/types.d.ts vendored
View File

@ -2,6 +2,7 @@
export type Pkg= Record<string, string>
export type Info= {
id: string,
href: string,
title: string,
description: string,
}

View File

@ -48,7 +48,7 @@ lifecycleToEvents(CustomHTMLTestElement)
customElements.define(CustomHTMLTestElement.tagName, CustomHTMLTestElement);
function customElementRender(_this, render){
scope.push({ scope: _this, host: (...a)=> a.length ? a[0](_this) : _this, inherit_host: true });
scope.push({ scope: _this, host: (...a)=> a.length ? a[0](_this) : _this, custom_element: _this });
const out= render(_this);
scope.pop();
return out;

6
index.d.ts vendored
View File

@ -127,7 +127,7 @@ interface On{
}
export const on: On;
type Scope= { scope: Node | Function | Object, host: ddeElementModifier<any>, prevent: boolean, inherit_host: boolean, }
type Scope= { scope: Node | Function | Object, host: ddeElementModifier<any>, custom_element: false | HTMLElement, prevent: boolean }
/** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */
export const scope: {
current: Scope,
@ -438,4 +438,8 @@ declare global{
/** Elements returned by {@link el} return parent element for `.append` method. **Regullarly created elements are untouched.** */
append: ddeAppend<DocumentFragment>;
}
interface SVGElement{
/** Elements returned by {@link el} return parent element for `.append` method. **Regullarly created elements are untouched.** */
append: ddeAppend<SVGElement>;
}
}

2
jsdom.d.ts vendored
View File

@ -1,6 +1,6 @@
import { el, assign, on } from "./index.d";
export * from "./index.d";
export function register(dom: typeof document): Promise<{
export function register(dom: JSDOM): Promise<{
el: typeof el,
assign: typeof assign,
on: typeof on

View File

@ -1,8 +1,9 @@
//TODO: https://www.npmjs.com/package/html-element
import { prop_process } from './src/dom-common.js';
const { setDeleteAttr }= prop_process;
import { enviroment } from './src/dom-common.js';
enviroment.ssr= true;
const { setDeleteAttr }= enviroment;
/** @param {HTMLElement} obj */
prop_process.setDeleteAttr= function(obj, prop, value){
enviroment.setDeleteAttr= function(obj, prop, value){
if("value"===prop) return obj.setAttribute(prop, value);
if("checked"!==prop) return setDeleteAttr(obj, prop, value);
if(value) return obj.setAttribute(prop, "");

View File

@ -1,4 +1,4 @@
export const prop_process= { setDeleteAttr };
export const enviroment= { setDeleteAttr, ssr: false };
import { isUndef } from './helpers.js';
function setDeleteAttr(obj, prop, val){
/* Issue

View File

@ -1,11 +1,12 @@
import { signals } from "./signals-common.js";
import { enviroment } from './dom-common.js';
/** @type {{ scope: object, prevent: boolean, host: function }[]} */
const scopes= [ {
scope: document.body,
host: c=> c ? c(document.body) : document.body,
custom_element: false,
prevent: true,
inherit_host: false,
} ];
export const scope= {
get current(){ return scopes[scopes.length-1]; },
@ -25,7 +26,7 @@ export const scope= {
};
let namespace;
export function createElement(tag, attributes, ...modifiers){
/* jshint maxcomplexity: 16 */
/* jshint maxcomplexity: 15 */
const s= signals(this);
let scoped= 0;
let el, el_host;
@ -35,15 +36,14 @@ export function createElement(tag, attributes, ...modifiers){
switch(true){
case typeof tag==="function": {
scoped= 1;
const { inherit_host, host: hostParent }= scope.current;
const host= inherit_host ? hostParent : c=> c ? (scoped===1 ? modifiers.unshift(c) : c(el_host), undefined) : el_host;
scope.push({ scope: tag, host, inherit_host });
scope.push({ scope: tag, host: c=> c ? (scoped===1 ? modifiers.unshift(c) : c(el_host), undefined) : el_host });
el= tag(attributes || undefined);
const is_fragment= el instanceof DocumentFragment;
if(el.nodeName==="#comment") break;
const el_mark= createElement.mark({
type: "component",
name: tag.name,
host: is_fragment ? "this" : ( el.nodeName==="#comment" ? "previousLater" : "parentElement" )
host: is_fragment ? "this" : "parentElement",
});
el.prepend(el_mark);
if(is_fragment) el_host= el_mark;
@ -66,6 +66,7 @@ export function createElement(tag, attributes, ...modifiers){
* @param {boolean} [is_open=false]
* */
createElement.mark= function(attrs, is_open= false){
if(enviroment.ssr) attrs.ssr= true;
attrs= Object.entries(attrs).map(([ n, v ])=> n+`="${v}"`).join(" ");
const end= is_open ? "" : "/";
const out= document.createComment(`<dde:mark ${attrs}${end}>`);
@ -91,8 +92,7 @@ export function createElementNS(ns){
}
export { createElementNS as elNS };
import { prop_process } from './dom-common.js';
const { setDeleteAttr }= prop_process;
const { setDeleteAttr }= enviroment;
const assign_context= new WeakMap();
export function assign(element, ...attributes){
if(!attributes.length) return element;

View File

@ -13,14 +13,17 @@ export function on(event, listener, options){
const c_ch_o= connectionsChangesObserverConstructor();
const els_attribute_store= new WeakSet();
import { scope } from "./dom.js";
import { onAbort } from './helpers.js';
//TODO: cleanUp when event before abort?
on.connected= function(listener, options){
const { custom_element }= scope.current;
const name= "connected";
if(typeof options !== "object")
options= {};
options.once= true;
return function registerElement(element){
if(custom_element) element= custom_element;
const event= "dde:"+name;
element.addEventListener(event, listener, options);
if(element.__dde_lifecycleToEvents) return element;
@ -32,11 +35,13 @@ on.connected= function(listener, options){
};
};
on.disconnected= function(listener, options){
const { custom_element }= scope.current;
const name= "disconnected";
if(typeof options !== "object")
options= {};
options.once= true;
return function registerElement(element){
if(custom_element) element= custom_element;
const event= "dde:"+name;
element.addEventListener(event, listener, options);
if(element.__dde_lifecycleToEvents) return element;