mirror of
https://github.com/jaandrle/deka-dom-el
synced 2024-11-23 17:19:37 +01:00
🎉 ⚡
This commit is contained in:
parent
b50f8449aa
commit
576b33921b
36
README.md
36
README.md
@ -1,4 +1,6 @@
|
|||||||
**WIP** (the experimentation phase) | [source code on GitHub](https://github.com/jaandrle/deka-dom-el) | [*mirrored* on Gitea](https://gitea.jaandrle.cz/jaandrle/deka-dom-el)
|
**WIP** (the experimentation phase)
|
||||||
|
| [source code on GitHub](https://github.com/jaandrle/deka-dom-el)
|
||||||
|
| [*mirrored* on Gitea](https://gitea.jaandrle.cz/jaandrle/deka-dom-el)
|
||||||
|
|
||||||
***Vanilla for flavouring — a full-fledged feast for large projects***
|
***Vanilla for flavouring — a full-fledged feast for large projects***
|
||||||
|
|
||||||
@ -10,11 +12,14 @@ document.body.append(
|
|||||||
el("p", "See some syntax examples here:"),
|
el("p", "See some syntax examples here:"),
|
||||||
el("ul").append(
|
el("ul").append(
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("a", { textContent: "Link to the library repo", title: "Deka DOM El — GitHub", href: "https://github.com/jaandrle/deka-dom-el" })
|
el("a", { textContent: "Link to the library repo",
|
||||||
|
title: "Deka DOM El — GitHub",
|
||||||
|
href: "https://github.com/jaandrle/deka-dom-el" })
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
"Use extended Vanilla JavaScript DOM/IDL API: ",
|
"Use extended Vanilla JavaScript DOM/IDL API: ",
|
||||||
el("span", { textContent: "» this is a span with class=cN and data-a=A, data-b=B «", className: "cN", dataset: { a: "A", b: "B" } })
|
el("span", { textContent: "» this is a span with class=cN and data-a=A, data-b=B «",
|
||||||
|
className: "cN", dataset: { a: "A", b: "B" } })
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el(component, { textContent: "A component", className: "example" }, on("change", console.log))
|
el(component, { textContent: "A component", className: "example" }, on("change", console.log))
|
||||||
@ -35,18 +40,22 @@ function component({ textContent, className }){
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
# Deka DOM Elements
|
# Deka DOM Elements
|
||||||
Creating reactive elements, components and Web components using [IDL](https://developer.mozilla.org/en-US/docs/Glossary/IDL)/JavaScript DOM API and [**signals/observables**](#signals).
|
Creating reactive elements, components and Web components using [IDL](https://developer.mozilla.org/en-US/docs/
|
||||||
|
Glossary/IDL)/JavaScript DOM API and [**signals/observables**](#signals).
|
||||||
|
|
||||||
## Inspiration and suggested alternatives
|
## Inspiration and suggested alternatives
|
||||||
- my previous library (mostly used internaly): [jaandrle/dollar_dom_component: Functional DOM components without JSX and virtual DOM.](https://github.com/jaandrle/dollar_dom_component)
|
- my previous library (mostly used internaly): [jaandrle/dollar_dom_component: Functional DOM components without
|
||||||
- [vanjs-org/van: 🍦 VanJS: World's smallest reactive UI framework. Incredibly Powerful, Insanely Small - Everyone can build a useful UI app in an hour.](https://github.com/vanjs-org/van)
|
JSX and virtual DOM.](https://github.com/jaandrle/dollar_dom_component)
|
||||||
|
- [vanjs-org/van: 🍦 VanJS: World's smallest reactive UI framework. Incredibly Powerful, Insanely Small -
|
||||||
|
Everyone can build a useful UI app in an hour.](https://github.com/vanjs-org/van)
|
||||||
- [hyperhype/hyperscript: Create HyperText with JavaScript.](https://github.com/hyperhype/hyperscript)
|
- [hyperhype/hyperscript: Create HyperText with JavaScript.](https://github.com/hyperhype/hyperscript)
|
||||||
- [adamhaile/S: S.js - Simple, Clean, Fast Reactive Programming in Javascript](https://github.com/adamhaile/S) ([adamhaile/surplus: High performance JSX web views for S.js applications](https://github.com/adamhaile/surplus))
|
- [adamhaile/S: S.js - Simple, Clean, Fast Reactive Programming in Javascript](https://github.com/adamhaile/S)
|
||||||
|
([adamhaile/surplus: High performance JSX web views for S.js applications](https://github.com/adamhaile/surplus))
|
||||||
- [potch/signals: a small reactive signals library](https://github.com/potch/signals)
|
- [potch/signals: a small reactive signals library](https://github.com/potch/signals)
|
||||||
|
|
||||||
## Why an another one?
|
## Why an another one?
|
||||||
This library falls somewhere between van/hyperscript and [solid-js](https://github.com/solidjs/solid) in terms of size, complexity,
|
This library falls somewhere between van/hyperscript and [solid-js](https://github.com/solidjs/solid) in terms of size,
|
||||||
and usability.
|
complexity, and usability.
|
||||||
|
|
||||||
Another goal is to proceed in the best spirit of functional programming. This involves starting with
|
Another goal is to proceed in the best spirit of functional programming. This involves starting with
|
||||||
pure JavaScript (DOM API) and gradually adding auxiliary functions, ranging from “minor” improvements
|
pure JavaScript (DOM API) and gradually adding auxiliary functions, ranging from “minor” improvements
|
||||||
@ -74,7 +83,10 @@ To balance these requirements, numerous compromises have been made. To summarize
|
|||||||
- [dist/](dist/) (`https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/`…)
|
- [dist/](dist/) (`https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/`…)
|
||||||
|
|
||||||
## Signals
|
## Signals
|
||||||
- [Signals — whats going on behind the scenes | by Ryan Hoffnan | ITNEXT](https://itnext.io/signals-whats-going-on-behind-the-scenes-ec858589ea63)
|
- [Signals — whats going on behind the scenes | by Ryan Hoffnan | ITNEXT](https://itnext.io/
|
||||||
- [The Evolution of Signals in JavaScript - DEV Community](https://dev.to/this-is-learning/the-evolution-of-signals-in-javascript-8ob)
|
signals-whats-going-on-behind-the-scenes-ec858589ea63)
|
||||||
- there is also [tc39/proposal-signals: A proposal to add signals to JavaScript.](https://github.com/tc39/proposal-signals)
|
- [The Evolution of Signals in JavaScript - DEV Community](https://dev.to/this-is-learning/the-evolution-of-signals-in-
|
||||||
|
javascript-8ob)
|
||||||
|
- there is also [tc39/proposal-signals: A proposal to add signals to JavaScript.](https://github.com/tc39/proposal-
|
||||||
|
signals)
|
||||||
- [Observer pattern - Wikipedia](https://en.wikipedia.org/wiki/Observer_pattern)
|
- [Observer pattern - Wikipedia](https://en.wikipedia.org/wiki/Observer_pattern)
|
||||||
|
17
bs/README.md
17
bs/README.md
@ -1 +1,16 @@
|
|||||||
[jaandrle/bs: The simplest possible build system using executables](https://github.com/jaandrle/bs/)
|
## bs: Build system based on executables
|
||||||
|
This project uses [jaandrle/bs: The simplest possible build system using executable/bash scripts](
|
||||||
|
https://github.com/jaandrle/bs).
|
||||||
|
|
||||||
|
#### bs/build.js [--minify|--help]
|
||||||
|
Generates alternative versions of the project (other than native ESM code).
|
||||||
|
Also generates typescript definitions.
|
||||||
|
|
||||||
|
#### bs/docs.js
|
||||||
|
Generates documentation, from `docs/`. Uses “SSR” technique, using deka-dom-el itself.
|
||||||
|
|
||||||
|
#### bs/lint.sh
|
||||||
|
Lints size of the project, jshint. See configs:
|
||||||
|
|
||||||
|
- `package.json`: key `size-limit`
|
||||||
|
- `package.json`: key `jshintConfig`
|
||||||
|
@ -46,7 +46,10 @@ $.api("", true)
|
|||||||
|
|
||||||
let content= s.cat(file).toString().split(/export ?{/);
|
let content= s.cat(file).toString().split(/export ?{/);
|
||||||
content.splice(1, 0, `\nglobalThis.${name}= {`);
|
content.splice(1, 0, `\nglobalThis.${name}= {`);
|
||||||
content[2]= content[2].replace(/,(?!\n)/g, ",\n").replace(/(?<!\n)}/, "\n}").replace(/^(\t*)(.*) as ([^,\n]*)(,?)$/mg, "$1$3: $2$4");
|
content[2]= content[2]
|
||||||
|
.replace(/,(?!\n)/g, ",\n")
|
||||||
|
.replace(/(?<!\n)}/, "\n}")
|
||||||
|
.replace(/^(\t*)(.*) as ([^,\n]*)(,?)$/mg, "$1$3: $2$4");
|
||||||
s.echo([
|
s.echo([
|
||||||
`//deka-dom-el library is available via global namespace \`${name}\``,
|
`//deka-dom-el library is available via global namespace \`${name}\``,
|
||||||
"(()=> {",
|
"(()=> {",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env -S npx nodejsscript
|
#!/usr/bin/env -S npx nodejsscript
|
||||||
/* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */
|
/* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */// editorconfig-checker-disable-line
|
||||||
echo("Building static documentation files…");
|
echo("Building static documentation files…");
|
||||||
echo("Preparing…");
|
echo("Preparing…");
|
||||||
import { path_target, pages as pages_registered, styles, dispatchEvent, t } from "../docs/ssr.js";
|
import { path_target, pages as pages_registered, styles, dispatchEvent, t } from "../docs/ssr.js";
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
set -eou pipefail
|
||||||
|
npx editorconfig-checker -format gcc
|
||||||
npx size-limit
|
npx size-limit
|
||||||
npx jshint index.js src
|
npx jshint index.js src
|
||||||
|
@ -2,8 +2,8 @@ import { elNS, assign } from "deka-dom-el";
|
|||||||
const elSVG= elNS("http://www.w3.org/2000/svg");
|
const elSVG= elNS("http://www.w3.org/2000/svg");
|
||||||
const elMath= elNS("http://www.w3.org/1998/Math/MathML");
|
const elMath= elNS("http://www.w3.org/1998/Math/MathML");
|
||||||
document.body.append(
|
document.body.append(
|
||||||
elSVG("svg"), // see https://developer.mozilla.org/en-US/docs/Web/SVG and https://developer.mozilla.org/en-US/docs/Web/API/SVGElement
|
elSVG("svg"), // see https://developer.mozilla.org/en-US/docs/Web/SVG and https://developer.mozilla.org/en-US/docs/Web/API/SVGElement // editorconfig-checker-disable-line
|
||||||
elMath("math") // see https://developer.mozilla.org/en-US/docs/Web/MathML and https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes
|
elMath("math") // see https://developer.mozilla.org/en-US/docs/Web/MathML and https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes // editorconfig-checker-disable-line
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -4,25 +4,32 @@ import { mnemonicUl } from "../mnemonicUl.html.js";
|
|||||||
export function mnemonic(){
|
export function mnemonic(){
|
||||||
return mnemonicUl().append(
|
return mnemonicUl().append(
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "customElementRender(<custom-element>, <connect-target>, <render-function>[, <properties>])"), " — use function to render DOM structure for given <custom-element>",
|
el("code", "customElementRender(<custom-element>, <connect-target>, <render-function>[, <properties>])"),
|
||||||
|
" — use function to render DOM structure for given <custom-element>",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "customElementWithDDE(<custom-element>)"), " — register <custom-element> to DDE library, see also `lifecyclesToEvents`, can be also used as decorator",
|
el("code", "customElementWithDDE(<custom-element>)"),
|
||||||
|
" — register <custom-element> to DDE library, see also `lifecyclesToEvents`, can be also used as decorator",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "observedAttributes(<custom-element>)"), " — returns record of observed attributes (keys uses camelCase)",
|
el("code", "observedAttributes(<custom-element>)"),
|
||||||
|
" — returns record of observed attributes (keys uses camelCase)",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "S.observedAttributes(<custom-element>)"), " — returns record of observed attributes (keys uses camelCase and values are signals)",
|
el("code", "S.observedAttributes(<custom-element>)"),
|
||||||
|
" — returns record of observed attributes (keys uses camelCase and values are signals)",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "lifecyclesToEvents(<class-declaration>)"), " — convert lifecycle methods to events, can be also used as decorator",
|
el("code", "lifecyclesToEvents(<class-declaration>)"),
|
||||||
|
" — convert lifecycle methods to events, can be also used as decorator",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "simulateSlots(<class-instance>, <body>[, <mapper>])"), " — simulate slots for Custom Elements without shadow DOM",
|
el("code", "simulateSlots(<class-instance>, <body>[, <mapper>])"),
|
||||||
|
" — simulate slots for Custom Elements without shadow DOM",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "simulateSlots(<dde-component>[, <mapper>])"), " — simulate slots for “dde”/functional components",
|
el("code", "simulateSlots(<dde-component>[, <mapper>])"),
|
||||||
|
" — simulate slots for “dde”/functional components",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,22 +4,28 @@ import { mnemonicUl } from "../mnemonicUl.html.js";
|
|||||||
export function mnemonic(){
|
export function mnemonic(){
|
||||||
return mnemonicUl().append(
|
return mnemonicUl().append(
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "assign(<element>, ...<idl-objects>): <element>"), " — assign properties to the element",
|
el("code", "assign(<element>, ...<idl-objects>): <element>"),
|
||||||
|
" — assign properties to the element",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "el(<tag-name>, <primitive>)[.append(...)]: <element-from-tag-name>"), " — simple element containing only text",
|
el("code", "el(<tag-name>, <primitive>)[.append(...)]: <element-from-tag-name>"),
|
||||||
|
" — simple element containing only text",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "el(<tag-name>, <idl-object>)[.append(...)]: <element-from-tag-name>"), " — element with more properties",
|
el("code", "el(<tag-name>, <idl-object>)[.append(...)]: <element-from-tag-name>"),
|
||||||
|
" — element with more properties",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function>"), " — using component represented by function",
|
el("code", "el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function>"),
|
||||||
|
" — using component represented by function",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "el(<...>, <...>, ...<addons>)"), " — see following page"
|
el("code", "el(<...>, <...>, ...<addons>)"),
|
||||||
|
" — see following page"
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "elNS(<namespace>)(<as-el-see-above>)[.append(...)]: <element-based-on-arguments>"), " — typically SVG elements",
|
el("code", "elNS(<namespace>)(<as-el-see-above>)[.append(...)]: <element-based-on-arguments>"),
|
||||||
|
" — typically SVG elements",
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,21 @@ import { mnemonicUl } from "../mnemonicUl.html.js";
|
|||||||
export function mnemonic(){
|
export function mnemonic(){
|
||||||
return mnemonicUl().append(
|
return mnemonicUl().append(
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "on(<event>, <listener>[, <options>])(<element>)"), " — just ", el("code", "<element>.addEventListener(<event>, <listener>[, <options>])")
|
el("code", "on(<event>, <listener>[, <options>])(<element>)"),
|
||||||
|
" — just ", el("code", "<element>.addEventListener(<event>, <listener>[, <options>])")
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "on.<live-cycle>(<event>, <listener>[, <options>])(<element>)"), " — corresponds to custom elemnets callbacks ", el("code", "<live-cycle>Callback(...){...}"),
|
el("code", "on.<live-cycle>(<event>, <listener>[, <options>])(<element>)"),
|
||||||
|
" — corresponds to custom elemnets callbacks ", el("code", "<live-cycle>Callback(...){...}"),
|
||||||
". To connect to custom element see following page, else it is simulated by MutationObserver."
|
". To connect to custom element see following page, else it is simulated by MutationObserver."
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "dispatchEvent(<event>[, <options>])(element)"), " — just ", el("code", "<element>.dispatchEvent(new Event(<event>[, <options>]))")
|
el("code", "dispatchEvent(<event>[, <options>])(element)"),
|
||||||
|
" — just ", el("code", "<element>.dispatchEvent(new Event(<event>[, <options>]))")
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "dispatchEvent(<event>[, <options>])(element, detail)"), " — just ", el("code", "<element>.dispatchEvent(new CustomEvent(<event>, { detail, ...<options> }))")
|
el("code", "dispatchEvent(<event>[, <options>])(element, detail)"),
|
||||||
|
" — just ", el("code", "<element>.dispatchEvent(new CustomEvent(<event>, { detail, ...<options> }))")
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,16 @@ import { mnemonicUl } from "../mnemonicUl.html.js";
|
|||||||
export function mnemonic(){
|
export function mnemonic(){
|
||||||
return mnemonicUl().append(
|
return mnemonicUl().append(
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function>"), " — using component represented by function",
|
el("code", "el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function>"),
|
||||||
|
" — using component represented by function",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "scope.host()"), " — get current component reference"
|
el("code", "scope.host()"),
|
||||||
|
" — get current component reference"
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "scope.host(...<addons>)"), " — use addons to current component",
|
el("code", "scope.host(...<addons>)"),
|
||||||
|
" — use addons to current component",
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,22 +7,28 @@ export function mnemonic(){
|
|||||||
el("code", "S(<value>)"), " — signal: reactive value",
|
el("code", "S(<value>)"), " — signal: reactive value",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "S(()=> <computation>)"), " — read-only signal: reactive value dependent on calculation using other signals",
|
el("code", "S(()=> <computation>)"),
|
||||||
|
" — read-only signal: reactive value dependent on calculation using other signals",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "S.on(<signal>, <listener>[, <options>])"), " — listen to the signal value changes",
|
el("code", "S.on(<signal>, <listener>[, <options>])"),
|
||||||
|
" — listen to the signal value changes",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "S.clear(...<signals>)"), " — off and clear signals",
|
el("code", "S.clear(...<signals>)"),
|
||||||
|
" — off and clear signals",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "S(<value>, <actions>)"), " — signal: pattern to create complex reactive objects/arrays",
|
el("code", "S(<value>, <actions>)"),
|
||||||
|
" — signal: pattern to create complex reactive objects/arrays",
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "S.action(<signal>, <action-name>, ...<action-arguments>)"), " — invoke an action for given signal"
|
el("code", "S.action(<signal>, <action-name>, ...<action-arguments>)"),
|
||||||
|
" — invoke an action for given signal"
|
||||||
),
|
),
|
||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "S.el(<signal>, <function-returning-dom>)"), " — render partial dom structure (template) based on the current signal value",
|
el("code", "S.el(<signal>, <function-returning-dom>)"),
|
||||||
|
" — render partial dom structure (template) based on the current signal value",
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ function metaFacebook({ name, description, homepage }){
|
|||||||
function iconGitHub(){
|
function iconGitHub(){
|
||||||
const el= elNS("http://www.w3.org/2000/svg");
|
const el= elNS("http://www.w3.org/2000/svg");
|
||||||
return el("svg", { className: "icon", viewBox: "0 0 32 32" }).append(
|
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
|
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 // editorconfig-checker-disable-line
|
||||||
"M 16,0.395",
|
"M 16,0.395",
|
||||||
"c -8.836,0 -16,7.163 -16,16",
|
"c -8.836,0 -16,7.163 -16,16",
|
||||||
"c 0,7.069 4.585,13.067 10.942,15.182",
|
"c 0,7.069 4.585,13.067 10.942,15.182",
|
||||||
|
@ -77,8 +77,9 @@ export function page({ pkg, info }){
|
|||||||
el("p").append(...T`
|
el("p").append(...T`
|
||||||
You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements
|
You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements
|
||||||
inherits from ${el("a", { textContent: "HTMLElement", ...references.mdn_el })}. To see
|
inherits from ${el("a", { textContent: "HTMLElement", ...references.mdn_el })}. To see
|
||||||
all available IDLs for example for paragraphs, see ${el("a", { textContent: "HTMLParagraphElement", ...references.mdn_p })}.
|
all available IDLs for example for paragraphs, see ${el("a", { textContent: "HTMLParagraphElement",
|
||||||
Moreover, the ${el("code", "assign")} provides a way to sets declaratively some convenient properties:
|
...references.mdn_p })}. Moreover, the ${el("code", "assign")} provides a way to sets declaratively
|
||||||
|
some convenient properties:
|
||||||
`),
|
`),
|
||||||
el("ul").append(
|
el("ul").append(
|
||||||
el("li").append(...T`
|
el("li").append(...T`
|
||||||
|
@ -29,7 +29,7 @@ const references= {
|
|||||||
},
|
},
|
||||||
/** Custom Element lifecycle callbacks */
|
/** Custom Element lifecycle callbacks */
|
||||||
mdn_customElement: {
|
mdn_customElement: {
|
||||||
href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks"
|
href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks" // editorconfig-checker-disable-line
|
||||||
},
|
},
|
||||||
/** MutationObserver */
|
/** MutationObserver */
|
||||||
mdn_mutation: {
|
mdn_mutation: {
|
||||||
@ -105,17 +105,20 @@ export function page({ pkg, info }){
|
|||||||
`),
|
`),
|
||||||
el("p").append(...T`
|
el("p").append(...T`
|
||||||
The library provide three additional live-cycle events corresponding to how they are named in a case of
|
The library provide three additional live-cycle events corresponding to how they are named in a case of
|
||||||
custom elements: ${el("code", "on.connected")}, ${el("code", "on.disconnected")} and ${el("code", "on.attributeChanged")}.
|
custom elements: ${el("code", "on.connected")}, ${el("code", "on.disconnected")} and ${el("code",
|
||||||
|
"on.attributeChanged")}.
|
||||||
`),
|
`),
|
||||||
el(example, { src: fileURL("./components/examples/events/live-cycle.js"), page_id }),
|
el(example, { src: fileURL("./components/examples/events/live-cycle.js"), page_id }),
|
||||||
el("p").append(...T`
|
el("p").append(...T`
|
||||||
For Custom elements, we will later introduce a way to replace ${el("code", "*Callback")} syntax with
|
For Custom elements, we will later introduce a way to replace ${el("code", "*Callback")} syntax with
|
||||||
${el("code", "dde:*")} events. The ${el("code", "on.*")} functions then listen to the appropriate
|
${el("code", "dde:*")} events. The ${el("code", "on.*")} functions then listen to the appropriate
|
||||||
Custom Elements events (see ${el("a", { textContent: t`Custom element lifecycle callbacks | MDN`, ...references.mdn_customElement })}).
|
Custom Elements events (see ${el("a", { textContent: t`Custom element lifecycle callbacks | MDN`,
|
||||||
|
...references.mdn_customElement })}).
|
||||||
`),
|
`),
|
||||||
el("p").append(...T`
|
el("p").append(...T`
|
||||||
But, in case of regular elemnets the ${el("a", references.mdn_mutation).append(el("code", "MutationObserver"), " | MDN")}
|
But, in case of regular elemnets the ${el("a", references.mdn_mutation).append(el("code",
|
||||||
is internaly used to track these events. Therefore, there are some drawbacks:
|
"MutationObserver"), " | MDN")} is internaly used to track these events. Therefore, there are some
|
||||||
|
drawbacks:
|
||||||
`),
|
`),
|
||||||
el("ul").append(
|
el("ul").append(
|
||||||
el("li").append(...T`
|
el("li").append(...T`
|
||||||
@ -136,7 +139,8 @@ export function page({ pkg, info }){
|
|||||||
native behaviour re-(dis)connecting element, use:
|
native behaviour re-(dis)connecting element, use:
|
||||||
`),
|
`),
|
||||||
el("ul").append(
|
el("ul").append(
|
||||||
el("li").append(...T`custom ${el("code", "MutationObserver")} or logic in (dis)${el("code", "connectedCallback")} or…`),
|
el("li").append(...T`custom ${el("code", "MutationObserver")} or logic in (dis)${el("code",
|
||||||
|
"connectedCallback")} or…`),
|
||||||
el("li").append(...T`re-add ${el("code", "on.connected")} or ${el("code", "on.disconnected")} listeners.`)
|
el("li").append(...T`re-add ${el("code", "on.connected")} or ${el("code", "on.disconnected")} listeners.`)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ const references= {
|
|||||||
/** observedAttributes on MDN */
|
/** observedAttributes on MDN */
|
||||||
mdn_observedAttributes: {
|
mdn_observedAttributes: {
|
||||||
title: t`MDN documentation page for observedAttributes`,
|
title: t`MDN documentation page for observedAttributes`,
|
||||||
href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#responding_to_attribute_changes",
|
href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#responding_to_attribute_changes", // editorconfig-checker-disable-line
|
||||||
},
|
},
|
||||||
/** Custom Elements on MDN */
|
/** Custom Elements on MDN */
|
||||||
mdn_custom_elements: {
|
mdn_custom_elements: {
|
||||||
@ -55,10 +55,10 @@ export function page({ pkg, info }){
|
|||||||
return el(simplePage, { info, pkg }).append(
|
return el(simplePage, { info, pkg }).append(
|
||||||
el("h2", t`Using web components in combinantion with DDE`),
|
el("h2", t`Using web components in combinantion with DDE`),
|
||||||
el("p").append(...T`
|
el("p").append(...T`
|
||||||
The DDE library allows for use within ${el("a", references.mdn_web_components).append( el("strong", t`Web Components`) )}
|
The DDE library allows for use within ${el("a", references.mdn_web_components).append( el("strong",
|
||||||
for dom-tree generation. However, in order to be able to use signals (possibly mapping to registered
|
t`Web Components`) )} for dom-tree generation. However, in order to be able to use signals (possibly
|
||||||
${el("a", references.mdn_observedAttributes).append( el("code", "observedAttributes") )}) and additional
|
mapping to registered ${el("a", references.mdn_observedAttributes).append( el("code", "observedAttributes")
|
||||||
functionality is (unfortunately) required to use helpers provided by the library.
|
)}) and additional functionality is (unfortunately) required to use helpers provided by the library.
|
||||||
`),
|
`),
|
||||||
el(code, { src: fileURL("./components/examples/customElement/intro.js"), page_id }),
|
el(code, { src: fileURL("./components/examples/customElement/intro.js"), page_id }),
|
||||||
|
|
||||||
@ -82,8 +82,8 @@ export function page({ pkg, info }){
|
|||||||
`),
|
`),
|
||||||
el("p").append(...T`
|
el("p").append(...T`
|
||||||
Also see the Life Cycle Events sections, very similarly we would like to use
|
Also see the Life Cycle Events sections, very similarly we would like to use
|
||||||
${el("a", { textContent: t`DDE events`, href: "./p03-events.html", title: t`See events part of the library documentation` })}.
|
${el("a", { textContent: t`DDE events`, href: "./p03-events.html", title: t`See events part of the library
|
||||||
To do it, the library provides function ${el("code", "customElementWithDDE")}…
|
documentation` })}. To do it, the library provides function ${el("code", "customElementWithDDE")}…
|
||||||
`),
|
`),
|
||||||
el(example, { src: fileURL("./components/examples/customElement/customElementWithDDE.js"), page_id }),
|
el(example, { src: fileURL("./components/examples/customElement/customElementWithDDE.js"), page_id }),
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ export function thirdParty(){
|
|||||||
});
|
});
|
||||||
// Array.from((new URL(location)).searchParams.entries())
|
// Array.from((new URL(location)).searchParams.entries())
|
||||||
// .forEach(([ key, value ])=> S.action(store, "set", key, value));
|
// .forEach(([ key, value ])=> S.action(store, "set", key, value));
|
||||||
// S.on(store, data=> history.replaceState("", "", "?"+(new URLSearchParams(JSON.parse(JSON.stringify(data)))).toString()));
|
// S.on(store, data=> history.replaceState("", "",
|
||||||
|
// "?"+(new URLSearchParams(JSON.parse(JSON.stringify(data)))).toString()));
|
||||||
useStore(store_adapter, {
|
useStore(store_adapter, {
|
||||||
onread(data){
|
onread(data){
|
||||||
Array.from(data.entries())
|
Array.from(data.entries())
|
||||||
|
@ -15,6 +15,7 @@ export function fullNameComponent(){
|
|||||||
on.disconnected(()=> console.log(fullNameComponent))
|
on.disconnected(()=> console.log(fullNameComponent))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const style= { height: "80px", display: "block", fill: "currentColor" };
|
||||||
const elSVG= elNS("http://www.w3.org/2000/svg");
|
const elSVG= elNS("http://www.w3.org/2000/svg");
|
||||||
return el("div", { className }).append(
|
return el("div", { className }).append(
|
||||||
el("h2", "Simple form:"),
|
el("h2", "Simple form:"),
|
||||||
@ -29,7 +30,7 @@ export function fullNameComponent(){
|
|||||||
": ",
|
": ",
|
||||||
el("#text", full_name)
|
el("#text", full_name)
|
||||||
),
|
),
|
||||||
elSVG("svg", { viewBox: "0 0 240 80", style: { height: "80px", display: "block" } }).append(
|
elSVG("svg", { viewBox: "0 0 240 80", style }).append(
|
||||||
//elSVG("style", { })
|
//elSVG("style", { })
|
||||||
elSVG("text", { x: 20, y: 35, textContent: "Text" }),
|
elSVG("text", { x: 20, y: 35, textContent: "Text" }),
|
||||||
)
|
)
|
||||||
|
@ -17,21 +17,24 @@ const className= style.host(todosComponent).css`
|
|||||||
/** @param {{ todos: string[] }} */
|
/** @param {{ todos: string[] }} */
|
||||||
export function todosComponent({ todos= [ "Task A" ] }= {}){
|
export function todosComponent({ todos= [ "Task A" ] }= {}){
|
||||||
let key= 0;
|
let key= 0;
|
||||||
const todosO= S(new Map(), {
|
const todosO= S( /** @type {Map<number, ddeSignal<string>>} */ (new Map()), {
|
||||||
|
/** @param {string} v */
|
||||||
add(v){ this.value.set(key++, S(v)); },
|
add(v){ this.value.set(key++, S(v)); },
|
||||||
|
/** @param {number} key */
|
||||||
remove(key){ S.clear(this.value.get(key)); this.value.delete(key); }
|
remove(key){ S.clear(this.value.get(key)); this.value.delete(key); }
|
||||||
});
|
});
|
||||||
todos.forEach(text=> S.action(todosO, "add", text));
|
todos.forEach(text=> S.action(todosO, "add", text));
|
||||||
|
|
||||||
const name= "todoName";
|
const name= "todoName";
|
||||||
const onsubmitAdd= on("submit", event=> {
|
const onsubmitAdd= on("submit", event=> {
|
||||||
const el= event.target.elements[name];
|
const el_form= /** @type {HTMLFormElement} */ (event.target);
|
||||||
|
const el= /** @type {HTMLInputElement} */ (el_form.elements[name]);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
S.action(todosO, "add", el.value);
|
S.action(todosO, "add", el.value);
|
||||||
el.value= "";
|
el.value= "";
|
||||||
});
|
});
|
||||||
const onremove= on("remove", event=>
|
const onremove= on("remove", /** @param {CustomEvent<number>} event */
|
||||||
S.action(todosO, "remove", event.detail));
|
event=> S.action(todosO, "remove", event.detail));
|
||||||
|
|
||||||
return el("div", { className }).append(
|
return el("div", { className }).append(
|
||||||
el("div").append(
|
el("div").append(
|
||||||
@ -60,19 +63,24 @@ export function todosComponent({ todos= [ "Task A" ] }= {}){
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* @param {{ textContent: ddeSignal<string>, value: ddeSignal<number> }} attrs
|
||||||
* @dispatchs {number} remove
|
* @dispatchs {number} remove
|
||||||
* */
|
* */
|
||||||
function todoComponent({ textContent, value }){
|
function todoComponent({ textContent, value }){
|
||||||
const { host }= scope;
|
const { host }= scope;
|
||||||
|
const dispatchRemove= /** @type {(data: number) => void} */
|
||||||
|
(dispatchEvent("remove", null, host));
|
||||||
const onclick= on("click", event=> {
|
const onclick= on("click", event=> {
|
||||||
const value= Number(event.target.value);
|
const el= /** @type {HTMLButtonElement} */ (event.target);
|
||||||
|
const value= Number(el.value);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
dispatchEvent("remove")(host(), value);
|
dispatchRemove(value);
|
||||||
});
|
});
|
||||||
const is_editable= S(false);
|
const is_editable= S(false);
|
||||||
const onedited= on("change", ev=> {
|
const onedited= on("change", ev=> {
|
||||||
textContent(ev.target.value);
|
const el= /** @type {HTMLInputElement} */ (ev.target);
|
||||||
|
textContent(el.value);
|
||||||
is_editable(false);
|
is_editable(false);
|
||||||
});
|
});
|
||||||
return el("li").append(
|
return el("li").append(
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { style, el, S } from './exports.js';
|
import { style, el, S } from './exports.js';
|
||||||
|
style.css`
|
||||||
|
:root{
|
||||||
|
color-scheme: dark light;
|
||||||
|
}
|
||||||
|
`;
|
||||||
document.head.append(style.element);
|
document.head.append(style.element);
|
||||||
import { fullNameComponent } from './components/fullNameComponent.js';
|
import { fullNameComponent } from './components/fullNameComponent.js';
|
||||||
import { todosComponent } from './components/todosComponent.js';
|
import { todosComponent } from './components/todosComponent.js';
|
||||||
|
69
index.d.ts
vendored
69
index.d.ts
vendored
@ -15,9 +15,12 @@ type AttrsModified= {
|
|||||||
/**
|
/**
|
||||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||||
*/
|
*/
|
||||||
style: string | Partial<CSSStyleDeclaration> | ddeSignal<string> | Partial<{ [K in keyof CSSStyleDeclaration]: ddeSignal<CSSStyleDeclaration[K]> }>
|
style: string | Partial<CSSStyleDeclaration> | ddeSignal<string>
|
||||||
|
| Partial<{ [K in keyof CSSStyleDeclaration]: ddeSignal<CSSStyleDeclaration[K]> }>
|
||||||
/**
|
/**
|
||||||
* 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.
|
* 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|ddeSignal<-1|0|1|boolean>>,
|
classList: Record<string,-1|0|1|boolean|ddeSignal<-1|0|1|boolean>>,
|
||||||
/**
|
/**
|
||||||
@ -28,20 +31,32 @@ type AttrsModified= {
|
|||||||
* Sets `aria-*` simiraly to `dataset`
|
* Sets `aria-*` simiraly to `dataset`
|
||||||
* */
|
* */
|
||||||
ariaset: Record<string,string|ddeSignal<string>>,
|
ariaset: Record<string,string|ddeSignal<string>>,
|
||||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, string|ddeSignal<string>> & Record<`.${string}`, any>
|
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, string|ddeSignal<string>>
|
||||||
|
& Record<`.${string}`, any>
|
||||||
type _fromElsInterfaces<EL extends SupportedElement>= Omit<EL, keyof AttrsModified>;
|
type _fromElsInterfaces<EL extends SupportedElement>= Omit<EL, keyof AttrsModified>;
|
||||||
/**
|
/**
|
||||||
* Just element attributtes
|
* Just element attributtes
|
||||||
*
|
*
|
||||||
* In most cases, you can use native propertie such as [MDN WEB/API/Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) and so on (e.g. [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text)).
|
* In most cases, you can use native propertie such as
|
||||||
|
* [MDN WEB/API/Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) and so on
|
||||||
|
* (e.g. [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text)).
|
||||||
*
|
*
|
||||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
type ElementAttributes<T extends SupportedElement>= Partial<{ [K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] | ddeSignal<_fromElsInterfaces<T>[K]> } & AttrsModified> & Record<string, any>;
|
type ElementAttributes<T extends SupportedElement>= Partial<{
|
||||||
export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El
|
[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] | ddeSignal<_fromElsInterfaces<T>[K]>
|
||||||
|
} & AttrsModified> & Record<string, any>;
|
||||||
|
export function classListDeclarative<El extends SupportedElement>(
|
||||||
|
element: El,
|
||||||
|
classList: AttrsModified["classList"]
|
||||||
|
): El
|
||||||
export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El
|
export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El
|
||||||
export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]
|
export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(
|
||||||
|
element: El,
|
||||||
|
attr: ATT,
|
||||||
|
value: ElementAttributes<El>[ATT]
|
||||||
|
): ElementAttributes<El>[ATT]
|
||||||
|
|
||||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap;
|
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||||
type textContent= string | ddeSignal<string>;
|
type textContent= string | ddeSignal<string>;
|
||||||
@ -68,7 +83,9 @@ export function el<
|
|||||||
component: C,
|
component: C,
|
||||||
attrs?: Parameters<C>[0] | textContent,
|
attrs?: Parameters<C>[0] | textContent,
|
||||||
...addons: ddeElementAddon<ReturnType<C>>[]
|
...addons: ddeElementAddon<ReturnType<C>>[]
|
||||||
): ReturnType<C> extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? ReturnType<C> : ( ReturnType<C> extends ddeDocumentFragment ? ReturnType<C> : ddeHTMLElement )
|
): ReturnType<C> extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap]
|
||||||
|
? ReturnType<C>
|
||||||
|
: ( ReturnType<C> extends ddeDocumentFragment ? ReturnType<C> : ddeHTMLElement )
|
||||||
export { el as createElement }
|
export { el as createElement }
|
||||||
|
|
||||||
export function elNS(
|
export function elNS(
|
||||||
@ -88,7 +105,9 @@ export function elNS(
|
|||||||
EL extends ( TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement ),
|
EL extends ( TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement ),
|
||||||
>(
|
>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | textContent | Partial<{ [key in keyof EL]: EL[key] | ddeSignal<EL[key]> | string | number | boolean }>,
|
attrs?: string | textContent | Partial<{
|
||||||
|
[key in keyof EL]: EL[key] | ddeSignal<EL[key]> | string | number | boolean
|
||||||
|
}>,
|
||||||
...addons: ddeElementAddon<EL>[]
|
...addons: ddeElementAddon<EL>[]
|
||||||
)=> ddeMathMLElement
|
)=> ddeMathMLElement
|
||||||
export function elNS(
|
export function elNS(
|
||||||
@ -106,18 +125,27 @@ export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
|||||||
* */
|
* */
|
||||||
type simulateSlotsMapper= (body: HTMLSlotElement, el: HTMLElement)=> void;
|
type simulateSlotsMapper= (body: HTMLSlotElement, el: HTMLElement)=> void;
|
||||||
/** Simulate slots for ddeComponents */
|
/** Simulate slots for ddeComponents */
|
||||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL, mapper?: simulateSlotsMapper): EL
|
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(
|
||||||
|
root: EL,
|
||||||
|
mapper?: simulateSlotsMapper
|
||||||
|
): EL
|
||||||
/**
|
/**
|
||||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||||
* @param el Custom Element root element
|
* @param el Custom Element root element
|
||||||
* @param body Body of the custom element
|
* @param body Body of the custom element
|
||||||
* */
|
* */
|
||||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL, mapper?: simulateSlotsMapper): EL
|
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(
|
||||||
|
el: HTMLElement,
|
||||||
|
body: EL, mapper?: simulateSlotsMapper
|
||||||
|
): EL
|
||||||
|
|
||||||
export function dispatchEvent(name: keyof DocumentEventMap | string, options?: EventInit):
|
export function dispatchEvent(name: keyof DocumentEventMap | string, options?: EventInit):
|
||||||
(element: SupportedElement, data?: any)=> void;
|
(element: SupportedElement, data?: any)=> void;
|
||||||
export function dispatchEvent(name: keyof DocumentEventMap | string, options: EventInit | null, element: SupportedElement | (()=> SupportedElement)):
|
export function dispatchEvent(
|
||||||
(data?: any)=> void;
|
name: keyof DocumentEventMap | string,
|
||||||
|
options: EventInit | null,
|
||||||
|
element: SupportedElement | (()=> SupportedElement)
|
||||||
|
): (data?: any)=> void;
|
||||||
interface On{
|
interface On{
|
||||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||||
<
|
<
|
||||||
@ -135,7 +163,7 @@ interface On{
|
|||||||
listener: (this: El, ev: Event | CustomEvent ) => any,
|
listener: (this: El, ev: Event | CustomEvent ) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */// editorconfig-checker-disable-line
|
||||||
connected<
|
connected<
|
||||||
EE extends ddeElementAddon<SupportedElement>,
|
EE extends ddeElementAddon<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||||
@ -143,7 +171,7 @@ interface On{
|
|||||||
listener: (this: El, event: CustomEvent<El>) => any,
|
listener: (this: El, event: CustomEvent<El>) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */// editorconfig-checker-disable-line
|
||||||
disconnected<
|
disconnected<
|
||||||
EE extends ddeElementAddon<SupportedElement>,
|
EE extends ddeElementAddon<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||||
@ -151,7 +179,7 @@ interface On{
|
|||||||
listener: (this: El, event: CustomEvent<void>) => any,
|
listener: (this: El, event: CustomEvent<void>) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
/** Listens to the element attribute changes. In case of custom elements uses [`attributeChangedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
/** Listens to the element attribute changes. In case of custom elements uses [`attributeChangedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */// editorconfig-checker-disable-line
|
||||||
attributeChanged<
|
attributeChanged<
|
||||||
EE extends ddeElementAddon<SupportedElement>,
|
EE extends ddeElementAddon<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||||
@ -162,7 +190,12 @@ interface On{
|
|||||||
}
|
}
|
||||||
export const on: On;
|
export const on: On;
|
||||||
|
|
||||||
type Scope= { scope: Node | Function | Object, host: ddeElementAddon<any>, custom_element: false | HTMLElement, prevent: boolean }
|
type Scope= {
|
||||||
|
scope: Node | Function | Object,
|
||||||
|
host: ddeElementAddon<any>,
|
||||||
|
custom_element: false | HTMLElement,
|
||||||
|
prevent: boolean
|
||||||
|
};
|
||||||
/** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */
|
/** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */
|
||||||
export const scope: {
|
export const scope: {
|
||||||
current: Scope,
|
current: Scope,
|
||||||
@ -350,6 +383,7 @@ declare global{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// editorconfig-checker-disable
|
||||||
interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend<ddeHTMLAnchorElement>; }
|
interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend<ddeHTMLAnchorElement>; }
|
||||||
interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend<ddeHTMLAreaElement>; }
|
interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend<ddeHTMLAreaElement>; }
|
||||||
interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend<ddeHTMLAudioElement>; }
|
interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend<ddeHTMLAudioElement>; }
|
||||||
@ -477,3 +511,4 @@ interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend<ddeSVGTi
|
|||||||
interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend<ddeSVGTSpanElement>; }
|
interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend<ddeSVGTSpanElement>; }
|
||||||
interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend<ddeSVGUseElement>; }
|
interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend<ddeSVGUseElement>; }
|
||||||
interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend<ddeSVGViewElement>; }
|
interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend<ddeSVGViewElement>; }
|
||||||
|
// editorconfig-checker-enable
|
||||||
|
19
package-lock.json
generated
19
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@size-limit/preset-small-lib": "~11.0",
|
"@size-limit/preset-small-lib": "~11.0",
|
||||||
"dts-bundler": "~0.1",
|
"dts-bundler": "~0.1",
|
||||||
|
"editorconfig-checker": "^6.0.0",
|
||||||
"esbuild": "~0.24",
|
"esbuild": "~0.24",
|
||||||
"jsdom": "~25.0",
|
"jsdom": "~25.0",
|
||||||
"jshint": "~2.13",
|
"jshint": "~2.13",
|
||||||
@ -1424,6 +1425,24 @@
|
|||||||
"typescript": "^2.4.0"
|
"typescript": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/editorconfig-checker": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/editorconfig-checker/-/editorconfig-checker-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-uyTOwLJzR/k7ugiu7ITjCzkLKBhXeirQZ8hGlUkt1u/hq2Qu1E8EslgFZDN+lxZoQc97eiI87sUFgVILK4P+YQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"ec": "dist/index.js",
|
||||||
|
"editorconfig-checker": "dist/index.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.11.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "buymeacoffee",
|
||||||
|
"url": "https://www.buymeacoffee.com/mstruebing"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
@ -83,9 +83,7 @@
|
|||||||
"modifyEsbuildConfig": {
|
"modifyEsbuildConfig": {
|
||||||
"platform": "browser"
|
"platform": "browser"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {},
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"dom",
|
"dom",
|
||||||
"javascript",
|
"javascript",
|
||||||
@ -95,6 +93,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@size-limit/preset-small-lib": "~11.0",
|
"@size-limit/preset-small-lib": "~11.0",
|
||||||
"dts-bundler": "~0.1",
|
"dts-bundler": "~0.1",
|
||||||
|
"editorconfig-checker": "~6.0",
|
||||||
"esbuild": "~0.24",
|
"esbuild": "~0.24",
|
||||||
"jsdom": "~25.0",
|
"jsdom": "~25.0",
|
||||||
"jshint": "~2.13",
|
"jshint": "~2.13",
|
||||||
|
@ -15,7 +15,7 @@ function setDeleteAttr(obj, prop, val){
|
|||||||
Options:
|
Options:
|
||||||
1. Leave it, as it is native behaviour
|
1. Leave it, as it is native behaviour
|
||||||
2. Sets as empty string and removes the corresponding attribute when also has empty string
|
2. Sets as empty string and removes the corresponding attribute when also has empty string
|
||||||
*3. Sets as undefined and removes the corresponding attribute when "undefined" string discovered
|
3. (*) Sets as undefined and removes the corresponding attribute when "undefined" string discovered
|
||||||
4. Point 2. with checks for coincidence (e.g. use special string)
|
4. Point 2. with checks for coincidence (e.g. use special string)
|
||||||
*/
|
*/
|
||||||
Reflect.set(obj, prop, val);
|
Reflect.set(obj, prop, val);
|
||||||
|
27
src/dom.js
27
src/dom.js
@ -25,9 +25,11 @@ export const scope= {
|
|||||||
return scopes.pop();
|
return scopes.pop();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// following chainableAppend implementation is OK as the ElementPrototype.append description already is { writable: true, enumerable: true, configurable: true }
|
// following chainableAppend implementation is OK as the ElementPrototype.append description already is { writable: true, enumerable: true, configurable: true } // editorconfig-checker-disable-line
|
||||||
function append(...els){ this.appendOriginal(...els); return this; }
|
function append(...els){ this.appendOriginal(...els); return this; }
|
||||||
export function chainableAppend(el){ if(el.append===append) return el; el.appendOriginal= el.append; el.append= append; return el; }
|
export function chainableAppend(el){
|
||||||
|
if(el.append===append) return el; el.appendOriginal= el.append; el.append= append; return el;
|
||||||
|
}
|
||||||
let namespace;
|
let namespace;
|
||||||
export function createElement(tag, attributes, ...addons){
|
export function createElement(tag, attributes, ...addons){
|
||||||
/* jshint maxcomplexity: 15 */
|
/* jshint maxcomplexity: 15 */
|
||||||
@ -40,7 +42,9 @@ export function createElement(tag, attributes, ...addons){
|
|||||||
switch(true){
|
switch(true){
|
||||||
case typeof tag==="function": {
|
case typeof tag==="function": {
|
||||||
scoped= 1;
|
scoped= 1;
|
||||||
scope.push({ scope: tag, host: (...c)=> c.length ? (scoped===1 ? addons.unshift(...c) : c.forEach(c=> c(el_host)), undefined) : el_host });
|
const host= (...c)=> !c.length ? el_host :
|
||||||
|
(scoped===1 ? addons.unshift(...c) : c.forEach(c=> c(el_host)), undefined);
|
||||||
|
scope.push({ scope: tag, host });
|
||||||
el= tag(attributes || undefined);
|
el= tag(attributes || undefined);
|
||||||
const is_fragment= el instanceof env.F;
|
const is_fragment= el instanceof env.F;
|
||||||
if(el.nodeName==="#comment") break;
|
if(el.nodeName==="#comment") break;
|
||||||
@ -108,7 +112,9 @@ export function simulateSlots(element, root, mapper){
|
|||||||
}
|
}
|
||||||
function simulateSlotReplace(slot, element, mapper){
|
function simulateSlotReplace(slot, element, mapper){
|
||||||
if(mapper) mapper(slot, element);
|
if(mapper) mapper(slot, element);
|
||||||
try{ slot.replaceWith(assign(element, { className: [ element.className, slot.className ], dataset: { ...slot.dataset } })); }
|
try{ slot.replaceWith(assign(element, {
|
||||||
|
className: [ element.className, slot.className ],
|
||||||
|
dataset: { ...slot.dataset } })); }
|
||||||
catch(_){ slot.replaceWith(element); }
|
catch(_){ slot.replaceWith(element); }
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -216,7 +222,9 @@ function getPropDescriptor(p, key){
|
|||||||
return des;
|
return des;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @template {Record<any, any>} T @param {object} s @param {T} obj @param {(param: [ keyof T, T[keyof T] ])=> void} cb */
|
/**
|
||||||
|
* @template {Record<any, any>} T @param {object} s @param {T} obj @param {(param: [ keyof T, T[keyof T] ])=> void} cb
|
||||||
|
* */
|
||||||
function forEachEntries(s, obj, cb){
|
function forEachEntries(s, obj, cb){
|
||||||
if(typeof obj !== "object" || obj===null) return;
|
if(typeof obj !== "object" || obj===null) return;
|
||||||
return Object.entries(obj).forEach(function process([ key, val ]){
|
return Object.entries(obj).forEach(function process([ key, val ]){
|
||||||
@ -227,6 +235,9 @@ function forEachEntries(s, obj, cb){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function attrArrToStr(attr){ return Array.isArray(attr) ? attr.filter(Boolean).join(" ") : attr; }
|
function attrArrToStr(attr){ return Array.isArray(attr) ? attr.filter(Boolean).join(" ") : attr; }
|
||||||
function setRemove(obj, prop, key, val){ return obj[ (isUndef(val) ? "remove" : "set") + prop ](key, attrArrToStr(val)); }
|
function setRemove(obj, prop, key, val){
|
||||||
function setRemoveNS(obj, prop, key, val, ns= null){ return obj[ (isUndef(val) ? "remove" : "set") + prop + "NS" ](ns, key, attrArrToStr(val)); }
|
return obj[ (isUndef(val) ? "remove" : "set") + prop ](key, attrArrToStr(val)); }
|
||||||
function setDelete(obj, key, val){ Reflect.set(obj, key, val); if(!isUndef(val)) return; return Reflect.deleteProperty(obj, key); }
|
function setRemoveNS(obj, prop, key, val, ns= null){
|
||||||
|
return obj[ (isUndef(val) ? "remove" : "set") + prop + "NS" ](ns, key, attrArrToStr(val)); }
|
||||||
|
function setDelete(obj, key, val){
|
||||||
|
Reflect.set(obj, key, val); if(!isUndef(val)) return; return Reflect.deleteProperty(obj, key); }
|
||||||
|
Loading…
Reference in New Issue
Block a user