mirror of
https://github.com/jaandrle/deka-dom-el
synced 2024-11-24 09:29:37 +01:00
Compare commits
No commits in common. "3866b29436281deeb16d3780d453b9b3835fef74" and "7d21b7799f97cf5833f2dc92ed9af6c4dbe01df7" have entirely different histories.
3866b29436
...
7d21b7799f
52
bs/docs.js
52
bs/docs.js
@ -1,49 +1,23 @@
|
||||
#!/usr/bin/env nodejsscript
|
||||
/* 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/",
|
||||
html: "docs/index.html",
|
||||
css: "docs/"
|
||||
};
|
||||
import { createHTMl } from "./docs/jsdom.js";
|
||||
const ssr= createHTMl("");
|
||||
import { register } from "../jsdom.js";
|
||||
const { el }= await register(ssr.dom);
|
||||
|
||||
echo("Loading components…");
|
||||
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." }
|
||||
];
|
||||
const { page, css }= await import("../docs_src/index.html.js"); //→ TODO: important to mention in docs!!!
|
||||
document.body.append(
|
||||
el(page, { pkg, path_target }),
|
||||
el("script", { src: "https://cdn.jsdelivr.net/npm/shiki" }),
|
||||
el("script", { src: "index.js", type: "module" })
|
||||
);
|
||||
|
||||
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!!!
|
||||
document.body.append(
|
||||
el(page, { pkg, info, path_target, pages, registerClientFile }),
|
||||
);
|
||||
|
||||
echo.use("-R", `Writing ${id}.html…`);
|
||||
s.echo(ssr.serialize()).to(path_target.root+id+".html");
|
||||
s.echo(css.content).to(path_target.css+id+".css");
|
||||
}
|
||||
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
|
||||
);
|
||||
}
|
||||
s.echo(ssr.serialize()).to(path_target.html);
|
||||
s.echo(css.content).to(path_target.css+"index.css");
|
||||
|
@ -1,125 +0,0 @@
|
||||
@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;
|
||||
}
|
||||
.note{
|
||||
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;
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
<!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 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>Let’s 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 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-hk0h5" class="example"><pre><code class="language-javascript">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;" }
|
||||
)
|
||||
);
|
||||
</code></pre></div><script>Flems(document.getElementById("code-hk0h5"), 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: \\\"Element’s 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-smzmf" 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";
|
||||
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 } }
|
||||
)
|
||||
);
|
||||
</code></pre></div><script>Flems(document.getElementById("code-smzmf"), 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 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 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 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 element’s <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-r0ona" 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";
|
||||
const paragraph= document.createElement("p");
|
||||
|
||||
assignAttribute(paragraph, "textContent", "Hello, world!");
|
||||
assignAttribute(paragraph, "style", { color: "navy" });
|
||||
|
||||
assignAttribute(paragraph, "dataTest1", "v1");
|
||||
assignAttribute(paragraph, "dataset", { test2: "v2" });
|
||||
|
||||
assignAttribute(paragraph, "ariaLabel", "v1");
|
||||
assignAttribute(paragraph, "ariaset", { role: "none" });
|
||||
|
||||
|
||||
classListDeclarative(paragraph, {
|
||||
classAdd: true,
|
||||
classRemove: false,
|
||||
classAdd1: 1,
|
||||
classRemove1: 0,
|
||||
classToggle: -1
|
||||
});
|
||||
|
||||
console.log(paragraph.outerHTML);
|
||||
document.body.append(
|
||||
paragraph
|
||||
);
|
||||
</code></pre></div><script>Flems(document.getElementById("code-r0ona"), 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-1ytxj" class="example"><pre><code class="language-javascript">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");
|
||||
</code></pre></div><script>Flems(document.getElementById("code-1ytxj"), 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 ooverwrites the <code>append</code> method to always return parent element.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-eynbh" class="example"><pre><code class="language-javascript">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; }",
|
||||
"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")
|
||||
)
|
||||
)
|
||||
);
|
||||
</code></pre></div><script>Flems(document.getElementById("code-eynbh"), 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-1tggr" class="example"><pre><code class="language-javascript">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; }",
|
||||
".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)
|
||||
);
|
||||
}
|
||||
</code></pre></div><script>Flems(document.getElementById("code-1tggr"), 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>
|
@ -6,100 +6,17 @@
|
||||
--accent: #d81b60;
|
||||
}
|
||||
@media (prefers-color-scheme:dark) {
|
||||
:root {
|
||||
::backdrop, :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;
|
||||
nav a.current {
|
||||
color: var(--accent) !important;
|
||||
border-color: var(--accent) !important;
|
||||
}
|
||||
.icon {
|
||||
vertical-align: sub;
|
||||
@ -117,7 +34,7 @@ main > *{
|
||||
font-style: italic;
|
||||
}
|
||||
.example{
|
||||
grid-column: 1/-1;
|
||||
grid-column: 1/4;
|
||||
width: 100%;
|
||||
max-width: calc(9/5 * var(--body-max-width));
|
||||
height: calc(3/5 * var(--body-max-width));
|
||||
|
106
docs/index.html
106
docs/index.html
@ -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 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 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 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><p>The main goals are:</p><ul><li>provide a small wrappers/utilities around the native JavaScript DOM</li><li>keep library size around 10kB at maximum (if possible)</li><li>zero dependencies (if possible)</li><li>prefer a declarative/functional approach</li><li>unopinionated (allow alternative methods)</li></ul><p class="note">It is, in fact, an reimplementation of <a href="https://github.com/jaandrle/dollar_dom_component" title="GitHub repository of library. Motto: Functional DOM components without JSX and virtual DOM.">jaandrle/dollar_dom_component</a>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-p1z06" 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"><link rel="stylesheet" href="index.css"><meta name="description" content="Introducing basic concepts."><!--<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/Guide</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"/>--><header><!--<dde:mark type="component" name="header" host="parentElement"/>--><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></nav><h1>`deka-dom-el` — Introduction/Guide</h1><p>The library tries to provide pure JavaScript tool(s) to create reactive interfaces. </p></header><p>The main goals are:</p><ul><li>provide a small wrappers/utilities around the native JavaScript DOM</li><li>keep library size around 10kB at maximum (if possible)</li><li>zero dependencies (if possible)</li><li>prefer a declarative/functional approach</li><li>unopinionated (allow alternative methods)</li></ul><p class="note">It is, in fact, an reimplementation of <a href="https://github.com/jaandrle/dollar_dom_component" title="GitHub repository of library. Motto: Functional DOM components without JSX and virtual DOM.">jaandrle/dollar_dom_component</a>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-tbn7w" 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";
|
||||
const clicks= S(0);
|
||||
document.body.append(
|
||||
el().append(
|
||||
@ -12,4 +12,106 @@ document.body.append(
|
||||
})
|
||||
)
|
||||
);
|
||||
</code></pre></div><script>Flems(document.getElementById("code-p1z06"), 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></pre></div><script>Flems(document.getElementById("code-tbn7w"), 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><h2>Native JavaScript DOM elements creations</h2><p>Let’s 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 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-6qkk3" class="example"><pre><code class="language-javascript">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;" }
|
||||
)
|
||||
);
|
||||
</code></pre></div><script>Flems(document.getElementById("code-6qkk3"), 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: \\\"Element’s 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-neqkq" 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";
|
||||
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 } }
|
||||
)
|
||||
);
|
||||
</code></pre></div><script>Flems(document.getElementById("code-neqkq"), 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 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 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 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 element’s <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-vc3nn" 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";
|
||||
const paragraph= document.createElement("p");
|
||||
|
||||
assignAttribute(paragraph, "textContent", "Hello, world!");
|
||||
assignAttribute(paragraph, "style", { color: "navy" });
|
||||
|
||||
assignAttribute(paragraph, "dataTest1", "v1");
|
||||
assignAttribute(paragraph, "dataset", { test2: "v2" });
|
||||
|
||||
assignAttribute(paragraph, "ariaLabel", "v1");
|
||||
assignAttribute(paragraph, "ariaset", { role: "none" });
|
||||
|
||||
|
||||
classListDeclarative(paragraph, {
|
||||
classAdd: true,
|
||||
classRemove: false,
|
||||
classAdd1: 1,
|
||||
classRemove1: 0,
|
||||
classToggle: -1
|
||||
});
|
||||
|
||||
console.log(paragraph.outerHTML);
|
||||
document.body.append(
|
||||
paragraph
|
||||
);
|
||||
</code></pre></div><script>Flems(document.getElementById("code-vc3nn"), 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-hn5qm" class="example"><pre><code class="language-javascript">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");
|
||||
</code></pre></div><script>Flems(document.getElementById("code-hn5qm"), 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 ooverwrites the <code>append</code> method to always return parent element.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-ek9lw" class="example"><pre><code class="language-javascript">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; }",
|
||||
"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")
|
||||
)
|
||||
)
|
||||
);
|
||||
</code></pre></div><script>Flems(document.getElementById("code-ek9lw"), 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-r6cen" class="example"><pre><code class="language-javascript">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; }",
|
||||
".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)
|
||||
);
|
||||
}
|
||||
</code></pre></div><script>Flems(document.getElementById("code-r6cen"), 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><script src="https://cdn.jsdelivr.net/npm/shiki"></script><script src="index.js" type="module"></script></body></html>
|
@ -1,8 +1,8 @@
|
||||
let is_registered= {};
|
||||
let is_registered= false;
|
||||
import { styles } from "../index.css.js";
|
||||
export const css= styles().scope(example).css`
|
||||
:host{
|
||||
grid-column: 1/-1;
|
||||
grid-column: 1/4;
|
||||
width: 100%;
|
||||
max-width: calc(9/5 * var(--body-max-width));
|
||||
height: calc(3/5 * var(--body-max-width));
|
||||
@ -10,17 +10,12 @@ export const css= styles().scope(example).css`
|
||||
}
|
||||
`
|
||||
import { el } from "deka-dom-el";
|
||||
/**
|
||||
* 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 {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= "javascript" }){
|
||||
register();
|
||||
const cwd= "components";
|
||||
src= "."+src.slice(src.indexOf(cwd)+cwd.length);
|
||||
const code= s.cat(new URL(src, import.meta.url))
|
||||
.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(
|
||||
@ -39,17 +34,10 @@ function elCode({ id, content }){
|
||||
});
|
||||
return el("script", `Flems(document.getElementById("${id}"), JSON.parse(${JSON.stringify(options)}));`);
|
||||
}
|
||||
function registerClientPart(page_id, registerClientFile){
|
||||
if(is_registered[page_id]) return;
|
||||
|
||||
//★ Highlite code when no flems?
|
||||
function register(){
|
||||
if(is_registered) return;
|
||||
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 }),
|
||||
el("script", { src: "https://flems.io/flems.html", type: "text/javascript", charset: "utf-8" })
|
||||
);
|
||||
//★ egisterClientFile(
|
||||
//★ new URL("./example.js.js", import.meta.url),
|
||||
//★ el("script", { type: "module" })
|
||||
//★ ;
|
||||
is_registered[page_id]= true;
|
||||
is_registered= true;
|
||||
}
|
||||
|
@ -1,108 +0,0 @@
|
||||
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 { header } from "./layout/head.html.js";
|
||||
/** @param {import("./types.d.ts").PageAttrs} attrs */
|
||||
export function page({ pkg, info, path_target, pages, registerClientFile }){
|
||||
const page_id= info.id;
|
||||
return el().append(
|
||||
el(header, { info, pkg, path_target, pages }),
|
||||
el("main").append(
|
||||
el("h2", "Native JavaScript DOM elements creations"),
|
||||
el("p", "Let’s go through all patterns we would like to use and what needs to be improved for better experience."),
|
||||
|
||||
el("h3", "Creating element(s) (with custom attributes)"),
|
||||
el("p").append(
|
||||
"You can create a native DOM element by using the ",
|
||||
el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement", title: "MDN documentation for document.createElement()" }).append(
|
||||
el("code", "document.createElement()")
|
||||
), ". ",
|
||||
"It is also possible to provide a some attribute(s) declaratively using ", el("code", "Object.assign()"), ". ",
|
||||
"More precisely, this way you can sets some ",
|
||||
el("a", {
|
||||
href: "https://developer.mozilla.org/en-US/docs/Glossary/IDL",
|
||||
title: "MDN page about Interface Description Language"
|
||||
}).append(
|
||||
el("abbr", { textContent: "IDL", title: "Interface Description Language" })
|
||||
), "."
|
||||
),
|
||||
el(example, { src: new URL("./components/examples/nativeCreateElement.js", import.meta.url), page_id, registerClientFile }),
|
||||
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("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. ",
|
||||
"Function prefers IDL and fallback to the ", el("code", "element.setAttribute"), " if there is no writable property in the element prototype."
|
||||
),
|
||||
el("p").append(
|
||||
"You can study all JavaScript elements interfaces to the corresponding HTML elements. ",
|
||||
"All HTML elements inherits from ", el("a", { textContent: "HTMLElement", href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement" }), ". ",
|
||||
"To see all available IDLs for example for paragraphs, see ", el("a", { textContent: "HTMLParagraphElement", href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement" }), ". ",
|
||||
"Moreover, the ", el("code", "assign"), " provides a way to sets declaratively some convenient properties:"
|
||||
),
|
||||
el("ul").append(
|
||||
el("li").append(
|
||||
"It is possible to sets ", el("code", "data-*"), "/", el("code", "aria-*"), " attributes using object notation."
|
||||
),
|
||||
el("li").append(
|
||||
"In opposite, it is also possible to sets ", el("code", "data-*"), "/", el("code", "aria-*"), " attribute using camelCase notation."
|
||||
),
|
||||
el("li").append(
|
||||
"You can use string or object as a value for ", el("code", "style"), " property."
|
||||
),
|
||||
el("li").append(
|
||||
el("code", "className"), " (IDL – preffered)/", el("code", "class"), " are ways to add CSS class to the element. ",
|
||||
"You can use string (similarly to ", el("code", "class=\"…\"") ," syntax in HTML) or array of strings. ",
|
||||
"This is handy to concat conditional classes."
|
||||
),
|
||||
el("li").append(
|
||||
"Use ", el("code", "classList"), " to toggle specific classes. This will be handy later when the reactivity via signals is beeing introduced.",
|
||||
),
|
||||
el("li").append(
|
||||
"The ", el("code", "assign"), " also accepts the ", el("code", "undefined"), " as a 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. ",
|
||||
el("em").append(
|
||||
"For example, natievly the element’s ", el("code", "id"), " is removed by setting the IDL to an empty string."
|
||||
)
|
||||
)
|
||||
),
|
||||
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("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("p").append(
|
||||
"This library therefore ooverwrites the ", el("code", "append"), " method to always return parent element."
|
||||
),
|
||||
el(example, { src: new URL("./components/examples/dekaAppend.js", import.meta.url), page_id, registerClientFile }),
|
||||
|
||||
|
||||
el("h2", "Creating advanced (reactive) templates and components"),
|
||||
|
||||
el("h3", "Basic 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.")
|
||||
)
|
||||
);
|
||||
}
|
@ -36,100 +36,17 @@ export const common= css`
|
||||
--accent: #d81b60;
|
||||
}
|
||||
@media (prefers-color-scheme:dark) {
|
||||
:root {
|
||||
::backdrop, :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;
|
||||
nav a.current {
|
||||
color: var(--accent) !important;
|
||||
border-color: var(--accent) !important;
|
||||
}
|
||||
.icon {
|
||||
vertical-align: sub;
|
||||
|
@ -12,13 +12,14 @@ export const css= styles()
|
||||
.include(example_css);
|
||||
|
||||
import { header } from "./layout/head.html.js";
|
||||
/** @param {import("./types.d.ts").PageAttrs} attrs */
|
||||
export function page({ pkg, info, path_target, pages, registerClientFile }){
|
||||
const page_id= info.id;
|
||||
export function page({ pkg, path_target }){
|
||||
return el().append(
|
||||
el(header, { info, pkg, path_target, pages }),
|
||||
el("main").append(
|
||||
el("p", "The library tries to provide pure JavaScript tool(s) to create reactive interfaces. "),
|
||||
el(header, {
|
||||
id: "index",
|
||||
title: "Introduction/Guide",
|
||||
description: "Introducing basic concepts.",
|
||||
pkg, path_target
|
||||
}),
|
||||
el("p", "The main goals are:"),
|
||||
el("ul").append(
|
||||
el("li", "provide a small wrappers/utilities around the native JavaScript DOM"),
|
||||
@ -36,7 +37,93 @@ export function page({ pkg, info, path_target, pages, registerClientFile }){
|
||||
}),
|
||||
".",
|
||||
),
|
||||
el(example, { src: new URL("./components/examples/helloWorld.js", import.meta.url), page_id, registerClientFile }),
|
||||
el(example, { src: "./components/examples/helloWorld.js" }),
|
||||
|
||||
|
||||
el("h2", "Native JavaScript DOM elements creations"),
|
||||
el("p", "Let’s go through all patterns we would like to use and what needs to be improved for better experience."),
|
||||
|
||||
el("h3", "Creating element(s) (with custom attributes)"),
|
||||
el("p").append(
|
||||
"You can create a native DOM element by using the ",
|
||||
el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement", title: "MDN documentation for document.createElement()" }).append(
|
||||
el("code", "document.createElement()")
|
||||
), ". ",
|
||||
"It is also possible to provide a some attribute(s) declaratively using ", el("code", "Object.assign()"), ". ",
|
||||
"More precisely, this way you can sets some ",
|
||||
el("a", {
|
||||
href: "https://developer.mozilla.org/en-US/docs/Glossary/IDL",
|
||||
title: "MDN page about Interface Description Language"
|
||||
}).append(
|
||||
el("abbr", { textContent: "IDL", title: "Interface Description Language" })
|
||||
), "."
|
||||
),
|
||||
el(example, { src: "./components/examples/nativeCreateElement.js" }),
|
||||
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: "./components/examples/dekaCreateElement.js" }),
|
||||
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. ",
|
||||
"Function prefers IDL and fallback to the ", el("code", "element.setAttribute"), " if there is no writable property in the element prototype."
|
||||
),
|
||||
el("p").append(
|
||||
"You can study all JavaScript elements interfaces to the corresponding HTML elements. ",
|
||||
"All HTML elements inherits from ", el("a", { textContent: "HTMLElement", href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement" }), ". ",
|
||||
"To see all available IDLs for example for paragraphs, see ", el("a", { textContent: "HTMLParagraphElement", href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement" }), ". ",
|
||||
"Moreover, the ", el("code", "assign"), " provides a way to sets declaratively some convenient properties:"
|
||||
),
|
||||
el("ul").append(
|
||||
el("li").append(
|
||||
"It is possible to sets ", el("code", "data-*"), "/", el("code", "aria-*"), " attributes using object notation."
|
||||
),
|
||||
el("li").append(
|
||||
"In opposite, it is also possible to sets ", el("code", "data-*"), "/", el("code", "aria-*"), " attribute using camelCase notation."
|
||||
),
|
||||
el("li").append(
|
||||
"You can use string or object as a value for ", el("code", "style"), " property."
|
||||
),
|
||||
el("li").append(
|
||||
el("code", "className"), " (IDL – preffered)/", el("code", "class"), " are ways to add CSS class to the element. ",
|
||||
"You can use string (similarly to ", el("code", "class=\"…\"") ," syntax in HTML) or array of strings. ",
|
||||
"This is handy to concat conditional classes."
|
||||
),
|
||||
el("li").append(
|
||||
"Use ", el("code", "classList"), " to toggle specific classes. This will be handy later when the reactivity via signals is beeing introduced.",
|
||||
),
|
||||
el("li").append(
|
||||
"The ", el("code", "assign"), " also accepts the ", el("code", "undefined"), " as a 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. ",
|
||||
el("em").append(
|
||||
"For example, natievly the element’s ", el("code", "id"), " is removed by setting the IDL to an empty string."
|
||||
)
|
||||
)
|
||||
),
|
||||
el("p").append(
|
||||
"For processing, the ", el("code", "assign"), " internally uses ", el("code", "assignAttribute"), " and ", el("code", "classListDeclarative"), "."
|
||||
),
|
||||
el(example, { src: "./components/examples/dekaAssign.js" }),
|
||||
|
||||
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: "./components/examples/nativeAppend.js" }),
|
||||
el("p").append(
|
||||
"This library therefore ooverwrites the ", el("code", "append"), " method to always return parent element."
|
||||
),
|
||||
el(example, { src: "./components/examples/dekaAppend.js" }),
|
||||
|
||||
|
||||
el("h2", "Creating advanced (reactive) templates and components"),
|
||||
|
||||
el("h3", "Basic 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: "./components/examples/dekaBasicComponent.js" }),
|
||||
el("p", "It is nice to use similar naming convention as native DOM API.")
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"include": [ "*.js", "**/*.js", "../node_modules/nodejsscript/index.d.ts" ],
|
||||
"compilerOptions": {
|
||||
"module": "NodeNext",
|
||||
"noEmit": true,
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"downlevelIteration": true,
|
||||
"maxNodeModuleJsDepth": 1
|
||||
}
|
||||
}
|
@ -1,34 +1,62 @@
|
||||
import { el, scope } from "deka-dom-el";
|
||||
/**
|
||||
* @param {object} def
|
||||
* @param {import("../types.d.ts").Info} def.info
|
||||
* @param {string} def.id Page `id` is used as stylesheet name.
|
||||
* @param {string} def.title Page `title` is also used as `h1`
|
||||
* @param {string} def.description Page 'description'.
|
||||
* @param {object} def.pkg Package information.
|
||||
* @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
|
||||
* @param {object} def
|
||||
* */
|
||||
export function header({ info: { id, title, description }, pkg, path_target, pages }){
|
||||
export function header({ id, title, description, pkg, path_target }){
|
||||
title= `\`${pkg.name}\` — ${title}`;
|
||||
document.head.append(head({ id, title, description, pkg, path_target }));
|
||||
return el().append(
|
||||
el("header").append(
|
||||
el("h1", title),
|
||||
el("p", description)
|
||||
),
|
||||
return el("header").append(
|
||||
el("nav").append(
|
||||
el("a", { href: pkg.homepage }).append(
|
||||
el(iconGitHub),
|
||||
"GitHub"
|
||||
),
|
||||
...pages.map((p, i)=> el("a", {
|
||||
href: p.id==="index" ? "./" : p.id,
|
||||
textContent: (i+1) + ". " + p.title,
|
||||
title: p.description,
|
||||
classList: { current: p.id===id }
|
||||
}))
|
||||
)
|
||||
),
|
||||
el("h1", title),
|
||||
el("p", "The library tries to provide pure JavaScript tool(s) to create reactive interfaces. ")
|
||||
);
|
||||
}
|
||||
function iconGitHub(){
|
||||
scope.namespace= "svg";
|
||||
return el("svg", { className: "icon", viewBox: "0 0 32 32" }).append(
|
||||
el("path", { d: [ //see https://svg-path-visualizer.netlify.app/#M16%200.395c-8.836%200-16%207.163-16%2016%200%207.069%204.585%2013.067%2010.942%2015.182%200.8%200.148%201.094-0.347%201.094-0.77%200-0.381-0.015-1.642-0.022-2.979-4.452%200.968-5.391-1.888-5.391-1.888-0.728-1.849-1.776-2.341-1.776-2.341-1.452-0.993%200.11-0.973%200.11-0.973%201.606%200.113%202.452%201.649%202.452%201.649%201.427%202.446%203.743%201.739%204.656%201.33%200.143-1.034%200.558-1.74%201.016-2.14-3.554-0.404-7.29-1.777-7.29-7.907%200-1.747%200.625-3.174%201.649-4.295-0.166-0.403-0.714-2.030%200.155-4.234%200%200%201.344-0.43%204.401%201.64%201.276-0.355%202.645-0.532%204.005-0.539%201.359%200.006%202.729%200.184%204.008%200.539%203.054-2.070%204.395-1.64%204.395-1.64%200.871%202.204%200.323%203.831%200.157%204.234%201.026%201.12%201.647%202.548%201.647%204.295%200%206.145-3.743%207.498-7.306%207.895%200.574%200.497%201.085%201.47%201.085%202.963%200%202.141-0.019%203.864-0.019%204.391%200%200.426%200.288%200.925%201.099%200.768%206.354-2.118%2010.933-8.113%2010.933-15.18%200-8.837-7.164-16-16-16z
|
||||
"M 16,0.395",
|
||||
"c -8.836,0 -16,7.163 -16,16",
|
||||
"c 0,7.069 4.585,13.067 10.942,15.182",
|
||||
"c 0.8,0.148 1.094,-0.347 1.094,-0.77",
|
||||
"c 0,-0.381 -0.015,-1.642 -0.022,-2.979",
|
||||
"c -4.452,0.968 -5.391,-1.888 -5.391,-1.888",
|
||||
"c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341",
|
||||
"c -1.452,-0.993 0.11,-0.973 0.11,-0.973",
|
||||
"c 1.606,0.113 2.452,1.649 2.452,1.649",
|
||||
"c 1.427,2.446 3.743,1.739 4.656,1.33",
|
||||
"c 0.143,-1.034 0.558,-1.74 1.016,-2.14",
|
||||
"c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907",
|
||||
"c 0,-1.747 0.625,-3.174 1.649,-4.295",
|
||||
"c -0.166,-0.403 -0.714,-2.03 0.155,-4.234",
|
||||
"c 0,0 1.344,-0.43 4.401,1.64",
|
||||
"c 1.276,-0.355 2.645,-0.532 4.005,-0.539",
|
||||
"c 1.359,0.006 2.729,0.184 4.008,0.539",
|
||||
"c 3.054,-2.07 4.395,-1.64 4.395,-1.64",
|
||||
"c 0.871,2.204 0.323,3.831 0.157,4.234",
|
||||
"c 1.026,1.12 1.647,2.548 1.647,4.295",
|
||||
"c 0,6.145 -3.743,7.498 -7.306,7.895",
|
||||
"c 0.574,0.497 1.085,1.47 1.085,2.963",
|
||||
"c 0,2.141 -0.019,3.864 -0.019,4.391",
|
||||
"c 0,0.426 0.288,0.925 1.099,0.768",
|
||||
"c 6.354,-2.118 10.933,-8.113 10.933,-15.18",
|
||||
"c 0,-8.837 -7.164,-16 -16,-16",
|
||||
"Z"
|
||||
].join("") })
|
||||
);
|
||||
}
|
||||
function head({ id, title, description, pkg, path_target }){
|
||||
@ -65,37 +93,3 @@ function metaFacebook({ name, description, homepage }){
|
||||
function stylesheetHref(path_target, name){
|
||||
return path_target.css.replace(path_target.root, "")+name+".css";
|
||||
}
|
||||
function iconGitHub(){
|
||||
scope.namespace= "svg";
|
||||
return el("svg", { className: "icon", viewBox: "0 0 32 32" }).append(
|
||||
el("path", { d: [ //see https://svg-path-visualizer.netlify.app/#M16%200.395c-8.836%200-16%207.163-16%2016%200%207.069%204.585%2013.067%2010.942%2015.182%200.8%200.148%201.094-0.347%201.094-0.77%200-0.381-0.015-1.642-0.022-2.979-4.452%200.968-5.391-1.888-5.391-1.888-0.728-1.849-1.776-2.341-1.776-2.341-1.452-0.993%200.11-0.973%200.11-0.973%201.606%200.113%202.452%201.649%202.452%201.649%201.427%202.446%203.743%201.739%204.656%201.33%200.143-1.034%200.558-1.74%201.016-2.14-3.554-0.404-7.29-1.777-7.29-7.907%200-1.747%200.625-3.174%201.649-4.295-0.166-0.403-0.714-2.030%200.155-4.234%200%200%201.344-0.43%204.401%201.64%201.276-0.355%202.645-0.532%204.005-0.539%201.359%200.006%202.729%200.184%204.008%200.539%203.054-2.070%204.395-1.64%204.395-1.64%200.871%202.204%200.323%203.831%200.157%204.234%201.026%201.12%201.647%202.548%201.647%204.295%200%206.145-3.743%207.498-7.306%207.895%200.574%200.497%201.085%201.47%201.085%202.963%200%202.141-0.019%203.864-0.019%204.391%200%200.426%200.288%200.925%201.099%200.768%206.354-2.118%2010.933-8.113%2010.933-15.18%200-8.837-7.164-16-16-16z
|
||||
"M 16,0.395",
|
||||
"c -8.836,0 -16,7.163 -16,16",
|
||||
"c 0,7.069 4.585,13.067 10.942,15.182",
|
||||
"c 0.8,0.148 1.094,-0.347 1.094,-0.77",
|
||||
"c 0,-0.381 -0.015,-1.642 -0.022,-2.979",
|
||||
"c -4.452,0.968 -5.391,-1.888 -5.391,-1.888",
|
||||
"c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341",
|
||||
"c -1.452,-0.993 0.11,-0.973 0.11,-0.973",
|
||||
"c 1.606,0.113 2.452,1.649 2.452,1.649",
|
||||
"c 1.427,2.446 3.743,1.739 4.656,1.33",
|
||||
"c 0.143,-1.034 0.558,-1.74 1.016,-2.14",
|
||||
"c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907",
|
||||
"c 0,-1.747 0.625,-3.174 1.649,-4.295",
|
||||
"c -0.166,-0.403 -0.714,-2.03 0.155,-4.234",
|
||||
"c 0,0 1.344,-0.43 4.401,1.64",
|
||||
"c 1.276,-0.355 2.645,-0.532 4.005,-0.539",
|
||||
"c 1.359,0.006 2.729,0.184 4.008,0.539",
|
||||
"c 3.054,-2.07 4.395,-1.64 4.395,-1.64",
|
||||
"c 0.871,2.204 0.323,3.831 0.157,4.234",
|
||||
"c 1.026,1.12 1.647,2.548 1.647,4.295",
|
||||
"c 0,6.145 -3.743,7.498 -7.306,7.895",
|
||||
"c 0.574,0.497 1.085,1.47 1.085,2.963",
|
||||
"c 0,2.141 -0.019,3.864 -0.019,4.391",
|
||||
"c 0,0.426 0.288,0.925 1.099,0.768",
|
||||
"c 6.354,-2.118 10.933,-8.113 10.933,-15.18",
|
||||
"c 0,-8.837 -7.164,-16 -16,-16",
|
||||
"Z"
|
||||
].join("") })
|
||||
);
|
||||
}
|
||||
|
21
docs_src/types.d.ts
vendored
21
docs_src/types.d.ts
vendored
@ -1,21 +0,0 @@
|
||||
/** See `package.json` */
|
||||
export type Pkg= Record<string, string>
|
||||
export type Info= {
|
||||
id: string,
|
||||
title: string,
|
||||
description: string,
|
||||
}
|
||||
export type Pages=Info[];
|
||||
export type PathTarget= {
|
||||
root: string,
|
||||
css: string
|
||||
}
|
||||
export type registerClientFile= import("../bs/docs.js").registerClientFile;
|
||||
export type PageAttrs= {
|
||||
pkg: Pkg,
|
||||
info: Info,
|
||||
pages: Pages,
|
||||
path_target: PathTarget,
|
||||
registerClientFile: registerClientFile
|
||||
}
|
||||
|
36
index.d.ts
vendored
36
index.d.ts
vendored
@ -1,8 +1,8 @@
|
||||
declare global {
|
||||
type ddeComponentAttributes= Record<any, any> | undefined | string;
|
||||
type ddeElementModifier<El extends HTMLElement | SVGElement | Comment | DocumentFragment>= (element: El)=> El;
|
||||
type ddeElementExtender<El extends Element>= (element: El)=> El;
|
||||
}
|
||||
type ElementTagNameMap= HTMLElementTagNameMap & { // & SVGElementTagNameMap
|
||||
type ElementTagNameMap= HTMLElementTagNameMap & SVGElementTagNameMap & {
|
||||
'#text': Text
|
||||
}
|
||||
type Element= ElementTagNameMap[keyof ElementTagNameMap];
|
||||
@ -14,7 +14,7 @@ type AttrsModified= {
|
||||
/**
|
||||
* Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` for others.
|
||||
*/
|
||||
classList: Record<string,-1|0|1|boolean>,
|
||||
classList: Record<string,-1|0|1>,
|
||||
/**
|
||||
* By default simiral to `className`, but also supports `string[]`
|
||||
* */
|
||||
@ -41,7 +41,7 @@ export function assign<El extends Element>(element: El, ...attrs_array: Partial<
|
||||
export function el<TAG extends keyof ElementTagNameMap>(
|
||||
tag_name: TAG,
|
||||
attrs?: Partial<ElementAttributes<ElementTagNameMap[TAG]>>,
|
||||
...modifiers: ddeElementModifier<ElementTagNameMap[TAG]>[]
|
||||
...extenders: ddeElementExtender<ElementTagNameMap[TAG]>[]
|
||||
): ElementTagNameMap[TAG]
|
||||
export function el<T>(
|
||||
tag_name?: "<>",
|
||||
@ -49,39 +49,33 @@ export function el<T>(
|
||||
|
||||
export function el<
|
||||
A extends ddeComponentAttributes,
|
||||
C extends (attr: A)=> Element | DocumentFragment>(
|
||||
C extends (attr: A)=> Element>(
|
||||
fComponent: C,
|
||||
attrs?: A,
|
||||
...modifiers: ddeElementModifier<ReturnType<C>>[]
|
||||
...extenders: ddeElementExtender<ReturnType<C>>[]
|
||||
): ReturnType<C>
|
||||
|
||||
export function el(
|
||||
tag_name: string,
|
||||
attrs?: Record<string, any>,
|
||||
...modifiers: ddeElementModifier<HTMLElement | SVGElement>[]
|
||||
): HTMLElement
|
||||
|
||||
export function dispatchEvent(element: HTMLElement, name: keyof DocumentEventMap): void;
|
||||
export function dispatchEvent(element: HTMLElement, name: string, data: any): void;
|
||||
interface On{
|
||||
<
|
||||
EE extends ddeElementModifier<Element>,
|
||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never ),
|
||||
EE extends ddeElementExtender<Element>,
|
||||
El extends ( EE extends ddeElementExtender<infer El> ? El : never ),
|
||||
Event extends keyof DocumentEventMap>(
|
||||
type: Event,
|
||||
listener: (this: El, ev: DocumentEventMap[Event]) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : EE;
|
||||
connected<
|
||||
EE extends ddeElementModifier<Element>,
|
||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||
EE extends ddeElementExtender<Element>,
|
||||
El extends ( EE extends ddeElementExtender<infer El> ? El : never )
|
||||
>(
|
||||
listener: (el: El) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : EE;
|
||||
disconnected<
|
||||
EE extends ddeElementModifier<Element>,
|
||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||
EE extends ddeElementExtender<Element>,
|
||||
El extends ( EE extends ddeElementExtender<infer El> ? El : never )
|
||||
>(
|
||||
listener: (el: El) => any,
|
||||
options?: AddEventListenerOptions
|
||||
@ -89,12 +83,6 @@ interface On{
|
||||
}
|
||||
export const on: On;
|
||||
|
||||
export const scope: {
|
||||
namespace: string,
|
||||
host: ddeElementModifier<any>,
|
||||
elNamespace: (ns: string)=> ({ append(...els: (HTMLElement | SVGElement)[]): HTMLElement | SVGElement | DocumentFragment })
|
||||
};
|
||||
|
||||
//TODO for SVG
|
||||
declare global{
|
||||
interface HTMLDivElement{ append(...nodes: (Node | string)[]): HTMLDivElement; }
|
||||
|
5
index.js
5
index.js
@ -1,7 +1,6 @@
|
||||
if(typeof document.createDocumentFragment().append()==="undefined")
|
||||
[ HTMLElement, SVGElement, DocumentFragment ].forEach(c=> {
|
||||
[ HTMLElement, SVGElement, DocumentFragment ].forEach(c=> {
|
||||
const { append }= c.prototype;
|
||||
c.prototype.append= function(...els){ append.apply(this, els); return this; };
|
||||
});
|
||||
});
|
||||
export * from "./src/dom.js";
|
||||
export * from "./src/events.js";
|
||||
|
6
jsdom.js
6
jsdom.js
@ -19,12 +19,6 @@ export function register(dom, keys_aditional= []){
|
||||
globalThis.window= w;
|
||||
w.console= globalThis.console;
|
||||
}
|
||||
if(typeof document.createDocumentFragment().append()==="undefined")
|
||||
[ HTMLElement, SVGElement, DocumentFragment ].forEach(c=> {
|
||||
const { append }= c.prototype;
|
||||
c.prototype.append= function(...els){ append.apply(this, els); return this; };
|
||||
});
|
||||
dom_last= dom;
|
||||
|
||||
return import("./index.js");
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ export const scope= {
|
||||
},
|
||||
pop(){ return scopes.pop(); },
|
||||
};
|
||||
export function createElement(tag, attributes, ...modifiers){
|
||||
export function createElement(tag, attributes, ...connect){
|
||||
const s= signals(this);
|
||||
const { namespace }= scope;
|
||||
let scoped= 0;
|
||||
@ -50,7 +50,7 @@ export function createElement(tag, attributes, ...modifiers){
|
||||
switch(true){
|
||||
case typeof tag==="function": {
|
||||
scoped= 1;
|
||||
scope.push({ scope: tag, host: c=> c ? (scoped===1 ? modifiers.unshift(c) : c(el_host), undefined) : el_host });
|
||||
scope.push({ scope: tag, host: c=> c ? (scoped===1 ? connect.unshift(c) : c(el_host), undefined) : el_host });
|
||||
el= tag(attributes || undefined);
|
||||
const is_fragment= el instanceof DocumentFragment;
|
||||
const el_mark= document.createComment(`<dde:mark type="component" name="${tag.name}" host="${is_fragment ? "this" : "parentElement"}"/>`);
|
||||
@ -64,7 +64,7 @@ export function createElement(tag, attributes, ...modifiers){
|
||||
case !el: el= assign.call(this, document.createElement(tag), attributes);
|
||||
}
|
||||
if(!el_host) el_host= el;
|
||||
modifiers.forEach(c=> c(el_host));
|
||||
connect.forEach(c=> c(el_host));
|
||||
if(scoped) scope.pop();
|
||||
scoped= 2;
|
||||
return el;
|
||||
|
Loading…
Reference in New Issue
Block a user