mirror of
https://github.com/jaandrle/deka-dom-el
synced 2025-04-01 11:45:53 +02:00
⚡ dde and docs improvements (#27)
* ⚡ 🎉 * ⚡ wip * 🔤 * ⚡ wip * ⚡ wip * ⚡ Refatc signals to .get/.set syntax #26 * 🐛 Better types for on* * 🔤 * 🔤 * 🐛 coumputed signal * 🔤 ⚡ Docs UI/UX * ⚡ 🔤 UI enhancements * ⚡ (bs) (un)min * 🔤 adds debugging * 🔤 ssr * 🔤 * ⚡ bs/lint * 🔤 * 🔤 UI * 🔤 updates texts * 🔤UI * ⚡ dispatch * 🔤 events * 🔤 elements * 🔤 intro * 🐛 fixes completitions for el with components * 🐛 wrong file(s) in git * 🔤 logo * 🐛 🔤 types 3ps * 🔤 ui/ux * 🔤 * 🔤 * 🔤 scopes * 🔤 * 🔤 ui/ux * 🔤 * ⚡ issignal * 🔤 improvemens * ⚡ irelands * 🔤 UI/UX/wording * 🐛 npx-hint [Scrollable region must have keyboard access | Axe Rules | Deque University | Deque Systems](https://dequeuniversity.com/rules/axe/4.10/scrollable-region-focusable?application=axeAPI) * 🔤 logos * ⚡ better? dts builds * Update README.md
This commit is contained in:
parent
dba4e93b88
commit
4366027658
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
dist/docs/
|
||||
dist/.*
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
166
README.md
166
README.md
@ -2,94 +2,120 @@
|
||||
| [source code on GitHub](https://github.com/jaandrle/deka-dom-el)
|
||||
| [*mirrored* on Gitea](https://gitea.jaandrle.cz/jaandrle/deka-dom-el)
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/assets/logo.svg" alt="Deka DOM Elements Logo" width="180" height="180">
|
||||
</p>
|
||||
|
||||
# Deka DOM Elements
|
||||
|
||||
***Vanilla for flavouring — a full-fledged feast for large projects***
|
||||
|
||||
*…use simple DOM API by default and library tools and logic when you need them*
|
||||
|
||||
```javascript
|
||||
// 🌟 Reactive component with clear separation of concerns
|
||||
document.body.append(
|
||||
el(HelloWorldComponent, { initial: "🚀" })
|
||||
el(EmojiCounter, { initial: "🚀" })
|
||||
);
|
||||
/** @typedef {"🎉" | "🚀"} Emoji */
|
||||
/** @param {{ initial: Emoji }} attrs */
|
||||
function HelloWorldComponent({ initial }){
|
||||
const clicks= S(0);
|
||||
const emoji= S(initial);
|
||||
|
||||
function EmojiCounter({ initial }) {
|
||||
// ✨ State - Define reactive data
|
||||
const count = S(0);
|
||||
const emoji = S(initial);
|
||||
|
||||
/** @param {HTMLOptionElement} el */
|
||||
const isSelected= el=> (el.selected= el.value===initial);
|
||||
// @ts-expect-error 2339: The <select> has only two options with {@link Emoji}
|
||||
const onChange= on("change", event=> emoji(event.target.value));
|
||||
|
||||
|
||||
// 🔄 View - UI updates automatically when signals change
|
||||
return el().append(
|
||||
el("p", {
|
||||
textContent: S(() => `Hello World ${emoji().repeat(clicks())}`),
|
||||
className: "example",
|
||||
ariaLive: "polite", //OR ariaset: { live: "polite" },
|
||||
dataset: { example: "Example" }, //OR dataExample: "Example",
|
||||
}),
|
||||
el("button",
|
||||
{ textContent: "Fire", type: "button" },
|
||||
on("click", ()=> clicks(clicks() + 1)),
|
||||
on("keyup", ()=> clicks(clicks() - 2)),
|
||||
),
|
||||
el("select", null, onChange).append(
|
||||
el(OptionComponent, "🎉", isSelected),//OR { textContent: "🎉" }
|
||||
el(OptionComponent, "🚀", isSelected),//OR { textContent: "🚀" }
|
||||
)
|
||||
el("p", {
|
||||
className: "output",
|
||||
textContent: S(() =>
|
||||
`Hello World ${emoji.get().repeat(clicks.get())}`),
|
||||
}),
|
||||
|
||||
// 🎮 Controls - Update state on events
|
||||
el("button", { textContent: "Add Emoji" },
|
||||
on("click", () => count.set(count.get() + 1))
|
||||
),
|
||||
|
||||
el("select", null, on("change", e => emoji.set(e.target.value)))
|
||||
.append(
|
||||
el(Option, "🎉", isSelected),
|
||||
el(Option, "🚀", isSelected),
|
||||
el(Option, "💖", isSelected),
|
||||
)
|
||||
);
|
||||
}
|
||||
function OptionComponent({ textContent }){
|
||||
return el("option", { value: textContent, textContent })
|
||||
function Option({ textContent }){
|
||||
return el("option", { value: textContent, textContent });
|
||||
}
|
||||
```
|
||||
# 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).
|
||||
|
||||
## 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)
|
||||
- [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)
|
||||
- [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)
|
||||
Creating reactive elements, components, and Web Components using the native
|
||||
[IDL](https://developer.mozilla.org/en-US/docs/Glossary/IDL)/JavaScript DOM API enhanced with
|
||||
[**signals/observables**](#understanding-signals).
|
||||
|
||||
## Why an another one?
|
||||
This library falls somewhere between van/hyperscript and [solid-js](https://github.com/solidjs/solid) in terms of size,
|
||||
complexity, and usability.
|
||||
## Features at a Glance
|
||||
|
||||
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
|
||||
to the capability of writing complete declarative reactive UI templates.
|
||||
- ✅ **No build step required** — use directly in browsers or Node.js
|
||||
- ☑️ **Lightweight** — ~10-15kB minified (original goal 10kB) with zero/minimal dependencies
|
||||
- ✅ **Declarative & functional approach** for clean, maintainable code
|
||||
- ✅ **Optional signals** with support for custom reactive implementations
|
||||
- ✅ **Server-side rendering** support via [jsdom](https://github.com/jsdom/jsdom)
|
||||
- 🔄 **TypeScript support** (work in progress)
|
||||
- 🔄 **Enhanced Web Components** support (work in progress)
|
||||
|
||||
As a result, any “internal” function (`assign`, `classListDeclarative`, `on`, `dispatchEvent`, …, `S`, …)
|
||||
can be used independently, although they are primarily designed for use in combination. This can also,
|
||||
hopefully, help in integrating the library into existing projects.
|
||||
## Why Another Library?
|
||||
|
||||
To balance these requirements, numerous compromises have been made. To summarize:
|
||||
- [ ] Library size: 10–15kB minified (the original goal was a maximum of 10kB)
|
||||
- [x] Optional use of *signals* with the ability to register *your own signals/observables implementation*
|
||||
- [x] *No build step required*
|
||||
- [x] Preference for a *declarative/functional* approach
|
||||
- [x] Focus on zero/minimal dependencies
|
||||
- [ ] Support for/enhancement of custom elements (web components)
|
||||
- [x] Support for SSR ([jsdom](https://github.com/jsdom/jsdom))
|
||||
- [ ] WIP providing types
|
||||
This library bridges the gap between minimal solutions like van/hyperscript and more comprehensive frameworks like
|
||||
[solid-js](https://github.com/solidjs/solid), offering a balanced trade-off between size, complexity, and usability.
|
||||
|
||||
## First steps
|
||||
- [**Guide**](https://jaandrle.github.io/deka-dom-el)
|
||||
- Documentation
|
||||
- Installation
|
||||
- npm
|
||||
- [dist/](dist/) (`https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/`…)
|
||||
Following functional programming principles, Deka DOM Elements starts with pure JavaScript (DOM API) and gradually adds
|
||||
auxiliary functions. These range from minor improvements to advanced features for building complete declarative
|
||||
reactive UI templates.
|
||||
|
||||
## Signals
|
||||
- [Signals — whats going on behind the scenes | by Ryan Hoffnan | ITNEXT](https://itnext.io/
|
||||
signals-whats-going-on-behind-the-scenes-ec858589ea63)
|
||||
- [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)
|
||||
A key advantage: any internal function (`assign`, `classListDeclarative`, `on`, `dispatchEvent`, `S`, etc.) can be used
|
||||
independently while also working seamlessly together. This modular approach makes it easier to integrate the library
|
||||
into existing projects.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
#### npm
|
||||
```bash
|
||||
# TBD
|
||||
# npm install deka-dom-el
|
||||
```
|
||||
|
||||
#### Direct Script
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/dde-with-signals.min.js"></script>
|
||||
<script type="module">
|
||||
const { el, S } = dde;
|
||||
</script>
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
- [**Interactive Guide**](https://jaandrle.github.io/deka-dom-el): WIP
|
||||
- [Examples](./examples/): TBD/WIP
|
||||
|
||||
## Understanding Signals
|
||||
|
||||
Signals are the reactive backbone of Deka DOM Elements:
|
||||
|
||||
- [Signals — what's going on behind the scenes](https://itnext.io/signals-whats-going-on-behind-the-scenes-ec858589ea63)
|
||||
- [The Evolution of Signals in JavaScript](https://dev.to/this-is-learning/the-evolution-of-signals-in-javascript-8ob)
|
||||
- [TC39 Signals Proposal](https://github.com/tc39/proposal-signals) (future standard)
|
||||
- [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern) (underlying concept)
|
||||
|
||||
## Inspiration and Alternatives
|
||||
|
||||
- [vanjs-org/van](https://github.com/vanjs-org/van) - World's smallest reactive UI framework
|
||||
- [adamhaile/S](https://github.com/adamhaile/S) - Simple, clean, fast reactive programming
|
||||
- [hyperhype/hyperscript](https://github.com/hyperhype/hyperscript) - Create HyperText with JavaScript
|
||||
- [potch/signals](https://github.com/potch/signals) - A small reactive signals library
|
||||
- [jaandrle/dollar_dom_component](https://github.com/jaandrle/dollar_dom_component) -
|
||||
Functional DOM components without JSX/virtual DOM
|
||||
|
96
bs/build.js
96
bs/build.js
@ -1,71 +1,37 @@
|
||||
#!/usr/bin/env -S npx nodejsscript
|
||||
import { bundle as bundleDTS } from "dts-bundler";
|
||||
import { build } from "./dev/.build.js"
|
||||
const files= [ "index", "index-with-signals" ];
|
||||
const filesOut= (file, mark= "esm")=> "dist/"+file.replace("index", mark);
|
||||
const css= echo.css`
|
||||
.info{ color: gray; }
|
||||
`;
|
||||
|
||||
$.api("", true)
|
||||
.option("--minify", "Level of minification [ no, full, partial (default) ]")
|
||||
.action(async function main({ minify= "partial" }){
|
||||
for(const file_root of files){
|
||||
const file= file_root+".js";
|
||||
echo("Processing: "+ file);
|
||||
const out= filesOut(file);
|
||||
const esbuild_output= s.$().run([
|
||||
"npx esbuild '::file::'",
|
||||
"--platform=neutral",
|
||||
"--bundle",
|
||||
minifyOption(minify),
|
||||
"--legal-comments=inline",
|
||||
"--packages=external",
|
||||
"--outfile='::out::'"
|
||||
].filter(Boolean).join(" "), { file, out });
|
||||
if(esbuild_output.code)
|
||||
return $.exit(esbuild_output.code, echo(esbuild_output.stderr));
|
||||
echoVariant(esbuild_output.stderr.split("\n")[1].trim()+ " (esbuild)");
|
||||
pipe(
|
||||
f=> f.replace(/^ +/gm, m=> "\t".repeat(m.length/2)),
|
||||
f=> s.echo(f).to(out)
|
||||
)(s.cat(out));
|
||||
|
||||
const file_dts= file_root+".d.ts";
|
||||
const file_dts_out= filesOut(file_dts);
|
||||
echoVariant(file_dts_out);
|
||||
s.echo(bundleDTS(file_dts)).to(file_dts_out);
|
||||
|
||||
await toDDE(out, file_root);
|
||||
}
|
||||
$.exit(0);
|
||||
|
||||
async function toDDE(file, file_root){
|
||||
const name= "dde";
|
||||
const out= filesOut(file_root+".js", name);
|
||||
echoVariant(`${out} (${file} → globalThis.${name})`)
|
||||
|
||||
let content= s.cat(file).toString().split(/export ?{/);
|
||||
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");
|
||||
s.echo([
|
||||
`//deka-dom-el library is available via global namespace \`${name}\``,
|
||||
"(()=> {",
|
||||
content.join(""),
|
||||
"})();"
|
||||
].join("\n")).to(out);
|
||||
}
|
||||
$.api("")
|
||||
.command("main", "Build main files", { default: true })
|
||||
.action(async function main(){
|
||||
const regular = await build({
|
||||
files,
|
||||
filesOut,
|
||||
minify: "no",
|
||||
});
|
||||
const min = await build({
|
||||
files,
|
||||
filesOut(file, mark= "esm"){
|
||||
const out= filesOut(file, mark);
|
||||
const idx= out.lastIndexOf(".");
|
||||
return out.slice(0, idx)+".min"+out.slice(idx);
|
||||
},
|
||||
minify: "full",
|
||||
});
|
||||
return $.exit(regular + min);
|
||||
})
|
||||
.command("signals", "Build only signals (for example for analysis)")
|
||||
.action(async function signals(){
|
||||
const regular = await build({
|
||||
files: [ "signals" ],
|
||||
filesOut(file){ return "dist/."+file; },
|
||||
minify: "no",
|
||||
dde: false,
|
||||
});
|
||||
return $.exit(regular);
|
||||
})
|
||||
.parse();
|
||||
|
||||
/** @param {"no"|"full"|"partial"} level */
|
||||
function minifyOption(level= "partial"){
|
||||
if("no"===level) return undefined;
|
||||
if("full"===level) return "--minify";
|
||||
return "--minify-syntax --minify-identifiers";
|
||||
}
|
||||
function echoVariant(name){
|
||||
return echo("%c✓ "+name, css.info+css);
|
||||
}
|
||||
|
||||
function filesOut(file, mark= "esm"){ return "dist/"+file.replace("index", mark); }
|
||||
|
108
bs/dev/.build.js
Normal file
108
bs/dev/.build.js
Normal file
@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env -S npx nodejsscript
|
||||
import { bundle, bundle as bundleDTS } from "dts-bundler";
|
||||
const css= echo.css`
|
||||
.info{ color: gray; }
|
||||
`;
|
||||
|
||||
export async function build({ files, filesOut, minify= "partial", dde= true }){
|
||||
for(const file_root of files){
|
||||
const file= file_root+".js";
|
||||
echo(`Processing ${file} (minified: ${minify})`);
|
||||
const out= filesOut(file);
|
||||
const esbuild_output= buildEsbuild({ file, out, minify });
|
||||
echoVariant(esbuild_output.stderr.split("\n")[1].trim()+ " (esbuild)");
|
||||
|
||||
const file_dts= file_root+".d.ts";
|
||||
const file_dts_out= filesOut(file_dts);
|
||||
echoVariant(file_dts_out, true);
|
||||
buildDts({
|
||||
bundle: out,
|
||||
entry: file_dts,
|
||||
});
|
||||
echoVariant(file_dts_out);
|
||||
|
||||
if(dde) toDDE(file, file_root);
|
||||
}
|
||||
return 0;
|
||||
|
||||
async function toDDE(file, file_root){
|
||||
const name= "dde";
|
||||
const out= filesOut(file_root+".js", name);
|
||||
|
||||
const params= [
|
||||
"--format=iife",
|
||||
"--global-name="+name,
|
||||
];
|
||||
const dde_output= buildEsbuild({ file, out, minify, params });
|
||||
echoVariant(`${out} (${file} → globalThis.${name})`)
|
||||
|
||||
const file_dts= file_root+".d.ts";
|
||||
const file_dts_out= filesOut(file_dts, name);
|
||||
echoVariant(file_dts_out, true);
|
||||
buildDts({
|
||||
name,
|
||||
bundle: out,
|
||||
entry: file_dts,
|
||||
})
|
||||
echoVariant(file_dts_out);
|
||||
|
||||
return dde_output;
|
||||
}
|
||||
}
|
||||
export function buildDts({ bundle, entry, name }){
|
||||
const out= bundle.slice(0, bundle.lastIndexOf("."))+".d.ts";
|
||||
const dts_b_g_output= s.run([
|
||||
"npx dts-bundle-generator",
|
||||
"--silent",
|
||||
"-o ::out::",
|
||||
!name ? false : ("--umd-module-name "+name),
|
||||
"--inline-declare-global",
|
||||
"::entry::"
|
||||
].filter(Boolean).join(" "), { out, entry });
|
||||
return dts_b_g_output;
|
||||
}
|
||||
class ErrorEsbuild extends Error{
|
||||
constructor({ code, stderr }){
|
||||
super(stderr);
|
||||
this.code= code;
|
||||
this.stderr= stderr;
|
||||
}
|
||||
}
|
||||
function buildEsbuild({ file, out, minify= "partial", params= [] }){
|
||||
try {
|
||||
return esbuild({ file, out, minify, params });
|
||||
} catch(e){
|
||||
if(e instanceof ErrorEsbuild)
|
||||
return $.exit(e.code, echo(e.stderr));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
export function esbuild({ file, out, minify= "partial", params= [] }){
|
||||
const esbuild_output= s.$().run([
|
||||
"npx esbuild '::file::'",
|
||||
"--platform=neutral",
|
||||
"--bundle",
|
||||
minifyOption(minify),
|
||||
"--legal-comments=inline",
|
||||
"--packages=external",
|
||||
...params,
|
||||
"--outfile='::out::'"
|
||||
].filter(Boolean).join(" "), { file, out });
|
||||
if(esbuild_output.code)
|
||||
throw new ErrorEsbuild(esbuild_output);
|
||||
pipe(
|
||||
f=> f.replace(/^ +/gm, m=> "\t".repeat(m.length/2)),
|
||||
f=> s.echo(f).to(out)
|
||||
)(s.cat(out));
|
||||
return esbuild_output;
|
||||
}
|
||||
/** @param {"no"|"full"|"partial"} level */
|
||||
function minifyOption(level= "partial"){
|
||||
if("no"===level) return undefined;
|
||||
if("full"===level) return "--minify";
|
||||
return "--minify-syntax --minify-identifiers";
|
||||
}
|
||||
function echoVariant(name, todo= false){
|
||||
if(todo) return echo.use("-R", "~ "+name);
|
||||
return echo("%c✓ "+name, css.info);
|
||||
}
|
14
bs/docs.js
14
bs/docs.js
@ -4,7 +4,7 @@ echo("Building static documentation files…");
|
||||
echo("Preparing…");
|
||||
import { path_target, pages as pages_registered, styles, dispatchEvent, t } from "../docs/ssr.js";
|
||||
import { createHTMl } from "./docs/jsdom.js";
|
||||
import { register } from "../jsdom.js";
|
||||
import { register, queue } from "../jsdom.js";
|
||||
const pkg= s.cat("package.json").xargs(JSON.parse);
|
||||
|
||||
if(s.test("-d", path_target.root)){
|
||||
@ -14,6 +14,10 @@ if(s.test("-d", path_target.root)){
|
||||
echo("Creating directory…");
|
||||
s.mkdir("-p", path_target.root);
|
||||
}
|
||||
|
||||
// Create assets directory in target
|
||||
echo("Creating assets directory…");
|
||||
s.mkdir("-p", path_target.root+"assets");
|
||||
echo("Collecting list of pages…");
|
||||
const pages= s.ls($.xdg.main`../docs/*.html.js`).map(addPage);
|
||||
for(const { id, info } of pages){
|
||||
@ -27,12 +31,20 @@ for(const { id, info } of pages){
|
||||
serverDOM.document.body.append(
|
||||
el(page, { pkg, info }),
|
||||
);
|
||||
await queue();
|
||||
|
||||
echo.use("-R", `Writing ${id}.html…`);
|
||||
dispatchEvent("oneachrender", document);
|
||||
s.echo(serverDOM.serialize()).to(path_target.root+id+".html");
|
||||
}
|
||||
s.echo(styles.content).to(path_target.css+styles.name);
|
||||
|
||||
// Copy assets
|
||||
echo("Copying assets…");
|
||||
if(s.test("-d", "docs/assets")) {
|
||||
s.cp("-r", "docs/assets/*", path_target.assets);
|
||||
}
|
||||
|
||||
dispatchEvent("onssrend");
|
||||
echo("Done");
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { JSDOM } from "jsdom";
|
||||
const html_default= "<!doctype html><html><head><meta charset=\"utf-8\"></head><body></body></html>";
|
||||
const html_default= "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"></head><body></body></html>";
|
||||
let keys= [];
|
||||
let dom= null;
|
||||
import { relative } from 'node:path';
|
||||
|
785
dist/dde-with-signals.d.ts
vendored
Normal file
785
dist/dde-with-signals.d.ts
vendored
Normal file
@ -0,0 +1,785 @@
|
||||
// Generated by dts-bundle-generator v9.5.1
|
||||
|
||||
export interface Signal<V, A> {
|
||||
/** The current value of the signal */
|
||||
get(): V;
|
||||
/** Set new value of the signal */
|
||||
set(value: V): V;
|
||||
toJSON(): V;
|
||||
valueOf(): V;
|
||||
}
|
||||
export type Action<V> = (this: {
|
||||
value: V;
|
||||
stopPropagation(): void;
|
||||
}, ...a: any[]) => typeof signal._ | void;
|
||||
//type SymbolSignal= Symbol;
|
||||
export type SymbolOnclear = symbol;
|
||||
export type Actions<V> = Record<string | SymbolOnclear, Action<V>>;
|
||||
export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & {
|
||||
first_time?: boolean;
|
||||
};
|
||||
export interface signal {
|
||||
_: Symbol;
|
||||
/**
|
||||
* Computations signal. This creates a signal which is computed from other signals.
|
||||
* */
|
||||
<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>;
|
||||
/**
|
||||
* Simple example:
|
||||
* ```js
|
||||
* const hello= S("Hello Signal");
|
||||
* ```
|
||||
* …simple todo signal:
|
||||
* ```js
|
||||
* const todos= S([], {
|
||||
* add(v){ this.value.push(S(v)); },
|
||||
* remove(i){ this.value.splice(i, 1); },
|
||||
* [S.symbols.onclear](){ S.clear(...this.value); },
|
||||
* });
|
||||
* ```
|
||||
* …computed signal:
|
||||
* ```js
|
||||
* const name= S("Jan");
|
||||
* const surname= S("Andrle");
|
||||
* const fullname= S(()=> name.get()+" "+surname.get());
|
||||
* ```
|
||||
* @param value Initial signal value. Or function computing value from other signals.
|
||||
* @param actions Use to define actions on the signal. Such as add item to the array.
|
||||
* There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared
|
||||
* by `S.clear`.
|
||||
* */
|
||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void;
|
||||
clear(...signals: Signal<any, any>[]): void;
|
||||
on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void;
|
||||
symbols: {
|
||||
//signal: SymbolSignal;
|
||||
onclear: SymbolOnclear;
|
||||
};
|
||||
/**
|
||||
* Reactive element, which is rendered based on the given signal.
|
||||
* ```js
|
||||
* S.el(signal, value=> value ? el("b", "True") : el("i", "False"));
|
||||
* S.el(listS, list=> list.map(li=> el("li", li)));
|
||||
* ```
|
||||
* */
|
||||
el<S extends any>(signal: Signal<S, any>, el: (v: S) => Element | Element[] | DocumentFragment): DocumentFragment;
|
||||
observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>;
|
||||
}
|
||||
export const signal: signal;
|
||||
export const S: signal;
|
||||
declare global {
|
||||
type ddeSignal<T, A = {}> = Signal<T, A>;
|
||||
type ddeAction<V> = Action<V>;
|
||||
type ddeActions<V> = Actions<V>;
|
||||
}
|
||||
export type CustomElementTagNameMap = {
|
||||
"#text": Text;
|
||||
"#comment": Comment;
|
||||
};
|
||||
export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
||||
declare global {
|
||||
type ddeComponentAttributes = Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El) => any;
|
||||
type ddeString = string | Signal<string, {}>;
|
||||
type ddeStringable = ddeString | number | Signal<number, {}>;
|
||||
}
|
||||
export type PascalCase = `${Capitalize<string>}${string}`;
|
||||
export type AttrsModified = {
|
||||
/**
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString | Partial<{
|
||||
[K in keyof CSSStyleDeclaration]: Signal<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.
|
||||
*/
|
||||
classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>;
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap)
|
||||
* */
|
||||
dataset: Record<string, ddeStringable>;
|
||||
/**
|
||||
* Sets `aria-*` simiraly to `dataset`
|
||||
* */
|
||||
ariaset: Record<string, ddeString>;
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>;
|
||||
export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>;
|
||||
export type IsReadonly<T, K extends keyof T> = T extends {
|
||||
readonly [P in K]: T[K];
|
||||
} ? true : false;
|
||||
/**
|
||||
* 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)).
|
||||
*
|
||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||
* @private
|
||||
*/
|
||||
export type ElementAttributes<T extends SupportedElement> = Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable);
|
||||
} & 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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT];
|
||||
export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(attrs: {
|
||||
type: "component" | "reactive" | "later";
|
||||
name?: string;
|
||||
host?: "this" | "parentElement";
|
||||
}, is_open?: boolean): Comment;
|
||||
}
|
||||
export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<A extends {
|
||||
textContent: ddeStringable;
|
||||
}, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement;
|
||||
export function el(tag_name?: "<>"): ddeDocumentFragment;
|
||||
export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement;
|
||||
export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement;
|
||||
export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean;
|
||||
}>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement;
|
||||
export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement;
|
||||
export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
||||
/** Simulate slots for ddeComponents */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL;
|
||||
/**
|
||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||
* @param el Custom Element root element
|
||||
* @param body Body of the custom element
|
||||
* */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, element: SupportedElement): (data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, element: SupportedElement | (() => SupportedElement)): (data?: any) => void;
|
||||
export interface On {
|
||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||
<Event extends keyof DocumentEventMap, EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: Event, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any, options?: AddEventListenerOptions): EE;
|
||||
<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
connected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<El>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
disconnected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
attributeChanged<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<[
|
||||
string,
|
||||
string
|
||||
]>) => any, options?: AddEventListenerOptions): EE;
|
||||
}
|
||||
export const on: On;
|
||||
export 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}) */
|
||||
export const scope: {
|
||||
current: Scope;
|
||||
/** Stops all automatizations. E. g. signals used as attributes in current scope
|
||||
* registers removing these listeners (and clean signal if no other listeners are detected)
|
||||
* on `disconnected` event. */
|
||||
preventDefault<T extends boolean>(prevent: T): T;
|
||||
/**
|
||||
* This represents reference to the current host element — `scope.host()`.
|
||||
* It can be also used to register Addon(s) (functions to be called when component is initized)
|
||||
* — `scope.host(on.connected(console.log))`.
|
||||
* */
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||
state: Scope[];
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>;
|
||||
/** Removes last/current child scope. */
|
||||
pop(): ReturnType<Array<Scope>["pop"]>;
|
||||
};
|
||||
export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL;
|
||||
export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>;
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
/* TypeScript MEH */
|
||||
declare global {
|
||||
type ddeAppend<el> = (...nodes: (Node | string)[]) => el;
|
||||
interface ddeDocumentFragment extends DocumentFragment {
|
||||
append: ddeAppend<ddeDocumentFragment>;
|
||||
}
|
||||
interface ddeHTMLElement extends HTMLElement {
|
||||
append: ddeAppend<ddeHTMLElement>;
|
||||
}
|
||||
interface ddeSVGElement extends SVGElement {
|
||||
append: ddeAppend<ddeSVGElement>;
|
||||
}
|
||||
interface ddeMathMLElement extends MathMLElement {
|
||||
append: ddeAppend<ddeMathMLElement>;
|
||||
}
|
||||
interface ddeHTMLElementTagNameMap {
|
||||
"a": ddeHTMLAnchorElement;
|
||||
"area": ddeHTMLAreaElement;
|
||||
"audio": ddeHTMLAudioElement;
|
||||
"base": ddeHTMLBaseElement;
|
||||
"blockquote": ddeHTMLQuoteElement;
|
||||
"body": ddeHTMLBodyElement;
|
||||
"br": ddeHTMLBRElement;
|
||||
"button": ddeHTMLButtonElement;
|
||||
"canvas": ddeHTMLCanvasElement;
|
||||
"caption": ddeHTMLTableCaptionElement;
|
||||
"col": ddeHTMLTableColElement;
|
||||
"colgroup": ddeHTMLTableColElement;
|
||||
"data": ddeHTMLDataElement;
|
||||
"datalist": ddeHTMLDataListElement;
|
||||
"del": ddeHTMLModElement;
|
||||
"details": ddeHTMLDetailsElement;
|
||||
"dialog": ddeHTMLDialogElement;
|
||||
"div": ddeHTMLDivElement;
|
||||
"dl": ddeHTMLDListElement;
|
||||
"embed": ddeHTMLEmbedElement;
|
||||
"fieldset": ddeHTMLFieldSetElement;
|
||||
"form": ddeHTMLFormElement;
|
||||
"h1": ddeHTMLHeadingElement;
|
||||
"h2": ddeHTMLHeadingElement;
|
||||
"h3": ddeHTMLHeadingElement;
|
||||
"h4": ddeHTMLHeadingElement;
|
||||
"h5": ddeHTMLHeadingElement;
|
||||
"h6": ddeHTMLHeadingElement;
|
||||
"head": ddeHTMLHeadElement;
|
||||
"hr": ddeHTMLHRElement;
|
||||
"html": ddeHTMLHtmlElement;
|
||||
"iframe": ddeHTMLIFrameElement;
|
||||
"img": ddeHTMLImageElement;
|
||||
"input": ddeHTMLInputElement;
|
||||
"ins": ddeHTMLModElement;
|
||||
"label": ddeHTMLLabelElement;
|
||||
"legend": ddeHTMLLegendElement;
|
||||
"li": ddeHTMLLIElement;
|
||||
"link": ddeHTMLLinkElement;
|
||||
"map": ddeHTMLMapElement;
|
||||
"menu": ddeHTMLMenuElement;
|
||||
"meta": ddeHTMLMetaElement;
|
||||
"meter": ddeHTMLMeterElement;
|
||||
"object": ddeHTMLObjectElement;
|
||||
"ol": ddeHTMLOListElement;
|
||||
"optgroup": ddeHTMLOptGroupElement;
|
||||
"option": ddeHTMLOptionElement;
|
||||
"output": ddeHTMLOutputElement;
|
||||
"p": ddeHTMLParagraphElement;
|
||||
"picture": ddeHTMLPictureElement;
|
||||
"pre": ddeHTMLPreElement;
|
||||
"progress": ddeHTMLProgressElement;
|
||||
"q": ddeHTMLQuoteElement;
|
||||
"script": ddeHTMLScriptElement;
|
||||
"select": ddeHTMLSelectElement;
|
||||
"slot": ddeHTMLSlotElement;
|
||||
"source": ddeHTMLSourceElement;
|
||||
"span": ddeHTMLSpanElement;
|
||||
"style": ddeHTMLStyleElement;
|
||||
"table": ddeHTMLTableElement;
|
||||
"tbody": ddeHTMLTableSectionElement;
|
||||
"td": ddeHTMLTableCellElement;
|
||||
"template": ddeHTMLTemplateElement;
|
||||
"textarea": ddeHTMLTextAreaElement;
|
||||
"tfoot": ddeHTMLTableSectionElement;
|
||||
"th": ddeHTMLTableCellElement;
|
||||
"thead": ddeHTMLTableSectionElement;
|
||||
"time": ddeHTMLTimeElement;
|
||||
"title": ddeHTMLTitleElement;
|
||||
"tr": ddeHTMLTableRowElement;
|
||||
"track": ddeHTMLTrackElement;
|
||||
"ul": ddeHTMLUListElement;
|
||||
"video": ddeHTMLVideoElement;
|
||||
}
|
||||
interface ddeSVGElementTagNameMap {
|
||||
"a": ddeSVGAElement;
|
||||
"animate": ddeSVGAnimateElement;
|
||||
"animateMotion": ddeSVGAnimateMotionElement;
|
||||
"animateTransform": ddeSVGAnimateTransformElement;
|
||||
"circle": ddeSVGCircleElement;
|
||||
"clipPath": ddeSVGClipPathElement;
|
||||
"defs": ddeSVGDefsElement;
|
||||
"desc": ddeSVGDescElement;
|
||||
"ellipse": ddeSVGEllipseElement;
|
||||
"feBlend": ddeSVGFEBlendElement;
|
||||
"feColorMatrix": ddeSVGFEColorMatrixElement;
|
||||
"feComponentTransfer": ddeSVGFEComponentTransferElement;
|
||||
"feComposite": ddeSVGFECompositeElement;
|
||||
"feConvolveMatrix": ddeSVGFEConvolveMatrixElement;
|
||||
"feDiffuseLighting": ddeSVGFEDiffuseLightingElement;
|
||||
"feDisplacementMap": ddeSVGFEDisplacementMapElement;
|
||||
"feDistantLight": ddeSVGFEDistantLightElement;
|
||||
"feDropShadow": ddeSVGFEDropShadowElement;
|
||||
"feFlood": ddeSVGFEFloodElement;
|
||||
"feFuncA": ddeSVGFEFuncAElement;
|
||||
"feFuncB": ddeSVGFEFuncBElement;
|
||||
"feFuncG": ddeSVGFEFuncGElement;
|
||||
"feFuncR": ddeSVGFEFuncRElement;
|
||||
"feGaussianBlur": ddeSVGFEGaussianBlurElement;
|
||||
"feImage": ddeSVGFEImageElement;
|
||||
"feMerge": ddeSVGFEMergeElement;
|
||||
"feMergeNode": ddeSVGFEMergeNodeElement;
|
||||
"feMorphology": ddeSVGFEMorphologyElement;
|
||||
"feOffset": ddeSVGFEOffsetElement;
|
||||
"fePointLight": ddeSVGFEPointLightElement;
|
||||
"feSpecularLighting": ddeSVGFESpecularLightingElement;
|
||||
"feSpotLight": ddeSVGFESpotLightElement;
|
||||
"feTile": ddeSVGFETileElement;
|
||||
"feTurbulence": ddeSVGFETurbulenceElement;
|
||||
"filter": ddeSVGFilterElement;
|
||||
"foreignObject": ddeSVGForeignObjectElement;
|
||||
"g": ddeSVGGElement;
|
||||
"image": ddeSVGImageElement;
|
||||
"line": ddeSVGLineElement;
|
||||
"linearGradient": ddeSVGLinearGradientElement;
|
||||
"marker": ddeSVGMarkerElement;
|
||||
"mask": ddeSVGMaskElement;
|
||||
"metadata": ddeSVGMetadataElement;
|
||||
"mpath": ddeSVGMPathElement;
|
||||
"path": ddeSVGPathElement;
|
||||
"pattern": ddeSVGPatternElement;
|
||||
"polygon": ddeSVGPolygonElement;
|
||||
"polyline": ddeSVGPolylineElement;
|
||||
"radialGradient": ddeSVGRadialGradientElement;
|
||||
"rect": ddeSVGRectElement;
|
||||
"script": ddeSVGScriptElement;
|
||||
"set": ddeSVGSetElement;
|
||||
"stop": ddeSVGStopElement;
|
||||
"style": ddeSVGStyleElement;
|
||||
"svg": ddeSVGSVGElement;
|
||||
"switch": ddeSVGSwitchElement;
|
||||
"symbol": ddeSVGSymbolElement;
|
||||
"text": ddeSVGTextElement;
|
||||
"textPath": ddeSVGTextPathElement;
|
||||
"title": ddeSVGTitleElement;
|
||||
"tspan": ddeSVGTSpanElement;
|
||||
"use": ddeSVGUseElement;
|
||||
"view": ddeSVGViewElement;
|
||||
}
|
||||
}
|
||||
// editorconfig-checker-disable
|
||||
export interface ddeHTMLAnchorElement extends HTMLAnchorElement {
|
||||
append: ddeAppend<ddeHTMLAnchorElement>;
|
||||
}
|
||||
export interface ddeHTMLAreaElement extends HTMLAreaElement {
|
||||
append: ddeAppend<ddeHTMLAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLAudioElement extends HTMLAudioElement {
|
||||
append: ddeAppend<ddeHTMLAudioElement>;
|
||||
}
|
||||
export interface ddeHTMLBaseElement extends HTMLBaseElement {
|
||||
append: ddeAppend<ddeHTMLBaseElement>;
|
||||
}
|
||||
export interface ddeHTMLQuoteElement extends HTMLQuoteElement {
|
||||
append: ddeAppend<ddeHTMLQuoteElement>;
|
||||
}
|
||||
export interface ddeHTMLBodyElement extends HTMLBodyElement {
|
||||
append: ddeAppend<ddeHTMLBodyElement>;
|
||||
}
|
||||
export interface ddeHTMLBRElement extends HTMLBRElement {
|
||||
append: ddeAppend<ddeHTMLBRElement>;
|
||||
}
|
||||
export interface ddeHTMLButtonElement extends HTMLButtonElement {
|
||||
append: ddeAppend<ddeHTMLButtonElement>;
|
||||
}
|
||||
export interface ddeHTMLCanvasElement extends HTMLCanvasElement {
|
||||
append: ddeAppend<ddeHTMLCanvasElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement {
|
||||
append: ddeAppend<ddeHTMLTableCaptionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLDataElement extends HTMLDataElement {
|
||||
append: ddeAppend<ddeHTMLDataElement>;
|
||||
}
|
||||
export interface ddeHTMLDataListElement extends HTMLDataListElement {
|
||||
append: ddeAppend<ddeHTMLDataListElement>;
|
||||
}
|
||||
export interface ddeHTMLModElement extends HTMLModElement {
|
||||
append: ddeAppend<ddeHTMLModElement>;
|
||||
}
|
||||
export interface ddeHTMLDetailsElement extends HTMLDetailsElement {
|
||||
append: ddeAppend<ddeHTMLDetailsElement>;
|
||||
}
|
||||
export interface ddeHTMLDialogElement extends HTMLDialogElement {
|
||||
append: ddeAppend<ddeHTMLDialogElement>;
|
||||
}
|
||||
export interface ddeHTMLDivElement extends HTMLDivElement {
|
||||
append: ddeAppend<ddeHTMLDivElement>;
|
||||
}
|
||||
export interface ddeHTMLDListElement extends HTMLDListElement {
|
||||
append: ddeAppend<ddeHTMLDListElement>;
|
||||
}
|
||||
export interface ddeHTMLEmbedElement extends HTMLEmbedElement {
|
||||
append: ddeAppend<ddeHTMLEmbedElement>;
|
||||
}
|
||||
export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement {
|
||||
append: ddeAppend<ddeHTMLFieldSetElement>;
|
||||
}
|
||||
export interface ddeHTMLFormElement extends HTMLFormElement {
|
||||
append: ddeAppend<ddeHTMLFormElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadingElement extends HTMLHeadingElement {
|
||||
append: ddeAppend<ddeHTMLHeadingElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadElement extends HTMLHeadElement {
|
||||
append: ddeAppend<ddeHTMLHeadElement>;
|
||||
}
|
||||
export interface ddeHTMLHRElement extends HTMLHRElement {
|
||||
append: ddeAppend<ddeHTMLHRElement>;
|
||||
}
|
||||
export interface ddeHTMLHtmlElement extends HTMLHtmlElement {
|
||||
append: ddeAppend<ddeHTMLHtmlElement>;
|
||||
}
|
||||
export interface ddeHTMLIFrameElement extends HTMLIFrameElement {
|
||||
append: ddeAppend<ddeHTMLIFrameElement>;
|
||||
}
|
||||
export interface ddeHTMLImageElement extends HTMLImageElement {
|
||||
append: ddeAppend<ddeHTMLImageElement>;
|
||||
}
|
||||
export interface ddeHTMLInputElement extends HTMLInputElement {
|
||||
append: ddeAppend<ddeHTMLInputElement>;
|
||||
}
|
||||
export interface ddeHTMLLabelElement extends HTMLLabelElement {
|
||||
append: ddeAppend<ddeHTMLLabelElement>;
|
||||
}
|
||||
export interface ddeHTMLLegendElement extends HTMLLegendElement {
|
||||
append: ddeAppend<ddeHTMLLegendElement>;
|
||||
}
|
||||
export interface ddeHTMLLIElement extends HTMLLIElement {
|
||||
append: ddeAppend<ddeHTMLLIElement>;
|
||||
}
|
||||
export interface ddeHTMLLinkElement extends HTMLLinkElement {
|
||||
append: ddeAppend<ddeHTMLLinkElement>;
|
||||
}
|
||||
export interface ddeHTMLMapElement extends HTMLMapElement {
|
||||
append: ddeAppend<ddeHTMLMapElement>;
|
||||
}
|
||||
export interface ddeHTMLMenuElement extends HTMLMenuElement {
|
||||
append: ddeAppend<ddeHTMLMenuElement>;
|
||||
}
|
||||
export interface ddeHTMLMetaElement extends HTMLMetaElement {
|
||||
append: ddeAppend<ddeHTMLMetaElement>;
|
||||
}
|
||||
export interface ddeHTMLMeterElement extends HTMLMeterElement {
|
||||
append: ddeAppend<ddeHTMLMeterElement>;
|
||||
}
|
||||
export interface ddeHTMLObjectElement extends HTMLObjectElement {
|
||||
append: ddeAppend<ddeHTMLObjectElement>;
|
||||
}
|
||||
export interface ddeHTMLOListElement extends HTMLOListElement {
|
||||
append: ddeAppend<ddeHTMLOListElement>;
|
||||
}
|
||||
export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement {
|
||||
append: ddeAppend<ddeHTMLOptGroupElement>;
|
||||
}
|
||||
export interface ddeHTMLOptionElement extends HTMLOptionElement {
|
||||
append: ddeAppend<ddeHTMLOptionElement>;
|
||||
}
|
||||
export interface ddeHTMLOutputElement extends HTMLOutputElement {
|
||||
append: ddeAppend<ddeHTMLOutputElement>;
|
||||
}
|
||||
export interface ddeHTMLParagraphElement extends HTMLParagraphElement {
|
||||
append: ddeAppend<ddeHTMLParagraphElement>;
|
||||
}
|
||||
export interface ddeHTMLPictureElement extends HTMLPictureElement {
|
||||
append: ddeAppend<ddeHTMLPictureElement>;
|
||||
}
|
||||
export interface ddeHTMLPreElement extends HTMLPreElement {
|
||||
append: ddeAppend<ddeHTMLPreElement>;
|
||||
}
|
||||
export interface ddeHTMLProgressElement extends HTMLProgressElement {
|
||||
append: ddeAppend<ddeHTMLProgressElement>;
|
||||
}
|
||||
export interface ddeHTMLScriptElement extends HTMLScriptElement {
|
||||
append: ddeAppend<ddeHTMLScriptElement>;
|
||||
}
|
||||
export interface ddeHTMLSelectElement extends HTMLSelectElement {
|
||||
append: ddeAppend<ddeHTMLSelectElement>;
|
||||
}
|
||||
export interface ddeHTMLSlotElement extends HTMLSlotElement {
|
||||
append: ddeAppend<ddeHTMLSlotElement>;
|
||||
}
|
||||
export interface ddeHTMLSourceElement extends HTMLSourceElement {
|
||||
append: ddeAppend<ddeHTMLSourceElement>;
|
||||
}
|
||||
export interface ddeHTMLSpanElement extends HTMLSpanElement {
|
||||
append: ddeAppend<ddeHTMLSpanElement>;
|
||||
}
|
||||
export interface ddeHTMLStyleElement extends HTMLStyleElement {
|
||||
append: ddeAppend<ddeHTMLStyleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableElement extends HTMLTableElement {
|
||||
append: ddeAppend<ddeHTMLTableElement>;
|
||||
}
|
||||
export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement {
|
||||
append: ddeAppend<ddeHTMLTableSectionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTemplateElement extends HTMLTemplateElement {
|
||||
append: ddeAppend<ddeHTMLTemplateElement>;
|
||||
}
|
||||
export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement {
|
||||
append: ddeAppend<ddeHTMLTextAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTimeElement extends HTMLTimeElement {
|
||||
append: ddeAppend<ddeHTMLTimeElement>;
|
||||
}
|
||||
export interface ddeHTMLTitleElement extends HTMLTitleElement {
|
||||
append: ddeAppend<ddeHTMLTitleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableRowElement extends HTMLTableRowElement {
|
||||
append: ddeAppend<ddeHTMLTableRowElement>;
|
||||
}
|
||||
export interface ddeHTMLTrackElement extends HTMLTrackElement {
|
||||
append: ddeAppend<ddeHTMLTrackElement>;
|
||||
}
|
||||
export interface ddeHTMLUListElement extends HTMLUListElement {
|
||||
append: ddeAppend<ddeHTMLUListElement>;
|
||||
}
|
||||
export interface ddeHTMLVideoElement extends HTMLVideoElement {
|
||||
append: ddeAppend<ddeHTMLVideoElement>;
|
||||
}
|
||||
export interface ddeSVGAElement extends SVGAElement {
|
||||
append: ddeAppend<ddeSVGAElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateElement extends SVGAnimateElement {
|
||||
append: ddeAppend<ddeSVGAnimateElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement {
|
||||
append: ddeAppend<ddeSVGAnimateMotionElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement {
|
||||
append: ddeAppend<ddeSVGAnimateTransformElement>;
|
||||
}
|
||||
export interface ddeSVGCircleElement extends SVGCircleElement {
|
||||
append: ddeAppend<ddeSVGCircleElement>;
|
||||
}
|
||||
export interface ddeSVGClipPathElement extends SVGClipPathElement {
|
||||
append: ddeAppend<ddeSVGClipPathElement>;
|
||||
}
|
||||
export interface ddeSVGDefsElement extends SVGDefsElement {
|
||||
append: ddeAppend<ddeSVGDefsElement>;
|
||||
}
|
||||
export interface ddeSVGDescElement extends SVGDescElement {
|
||||
append: ddeAppend<ddeSVGDescElement>;
|
||||
}
|
||||
export interface ddeSVGEllipseElement extends SVGEllipseElement {
|
||||
append: ddeAppend<ddeSVGEllipseElement>;
|
||||
}
|
||||
export interface ddeSVGFEBlendElement extends SVGFEBlendElement {
|
||||
append: ddeAppend<ddeSVGFEBlendElement>;
|
||||
}
|
||||
export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEColorMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement {
|
||||
append: ddeAppend<ddeSVGFEComponentTransferElement>;
|
||||
}
|
||||
export interface ddeSVGFECompositeElement extends SVGFECompositeElement {
|
||||
append: ddeAppend<ddeSVGFECompositeElement>;
|
||||
}
|
||||
export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEConvolveMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement {
|
||||
append: ddeAppend<ddeSVGFEDiffuseLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement {
|
||||
append: ddeAppend<ddeSVGFEDisplacementMapElement>;
|
||||
}
|
||||
export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement {
|
||||
append: ddeAppend<ddeSVGFEDistantLightElement>;
|
||||
}
|
||||
export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement {
|
||||
append: ddeAppend<ddeSVGFEDropShadowElement>;
|
||||
}
|
||||
export interface ddeSVGFEFloodElement extends SVGFEFloodElement {
|
||||
append: ddeAppend<ddeSVGFEFloodElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement {
|
||||
append: ddeAppend<ddeSVGFEFuncAElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement {
|
||||
append: ddeAppend<ddeSVGFEFuncBElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement {
|
||||
append: ddeAppend<ddeSVGFEFuncGElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement {
|
||||
append: ddeAppend<ddeSVGFEFuncRElement>;
|
||||
}
|
||||
export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement {
|
||||
append: ddeAppend<ddeSVGFEGaussianBlurElement>;
|
||||
}
|
||||
export interface ddeSVGFEImageElement extends SVGFEImageElement {
|
||||
append: ddeAppend<ddeSVGFEImageElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeElement extends SVGFEMergeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeNodeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement {
|
||||
append: ddeAppend<ddeSVGFEMorphologyElement>;
|
||||
}
|
||||
export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement {
|
||||
append: ddeAppend<ddeSVGFEOffsetElement>;
|
||||
}
|
||||
export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement {
|
||||
append: ddeAppend<ddeSVGFEPointLightElement>;
|
||||
}
|
||||
export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement {
|
||||
append: ddeAppend<ddeSVGFESpecularLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement {
|
||||
append: ddeAppend<ddeSVGFESpotLightElement>;
|
||||
}
|
||||
export interface ddeSVGFETileElement extends SVGFETileElement {
|
||||
append: ddeAppend<ddeSVGFETileElement>;
|
||||
}
|
||||
export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement {
|
||||
append: ddeAppend<ddeSVGFETurbulenceElement>;
|
||||
}
|
||||
export interface ddeSVGFilterElement extends SVGFilterElement {
|
||||
append: ddeAppend<ddeSVGFilterElement>;
|
||||
}
|
||||
export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement {
|
||||
append: ddeAppend<ddeSVGForeignObjectElement>;
|
||||
}
|
||||
export interface ddeSVGGElement extends SVGGElement {
|
||||
append: ddeAppend<ddeSVGGElement>;
|
||||
}
|
||||
export interface ddeSVGImageElement extends SVGImageElement {
|
||||
append: ddeAppend<ddeSVGImageElement>;
|
||||
}
|
||||
export interface ddeSVGLineElement extends SVGLineElement {
|
||||
append: ddeAppend<ddeSVGLineElement>;
|
||||
}
|
||||
export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement {
|
||||
append: ddeAppend<ddeSVGLinearGradientElement>;
|
||||
}
|
||||
export interface ddeSVGMarkerElement extends SVGMarkerElement {
|
||||
append: ddeAppend<ddeSVGMarkerElement>;
|
||||
}
|
||||
export interface ddeSVGMaskElement extends SVGMaskElement {
|
||||
append: ddeAppend<ddeSVGMaskElement>;
|
||||
}
|
||||
export interface ddeSVGMetadataElement extends SVGMetadataElement {
|
||||
append: ddeAppend<ddeSVGMetadataElement>;
|
||||
}
|
||||
export interface ddeSVGMPathElement extends SVGMPathElement {
|
||||
append: ddeAppend<ddeSVGMPathElement>;
|
||||
}
|
||||
export interface ddeSVGPathElement extends SVGPathElement {
|
||||
append: ddeAppend<ddeSVGPathElement>;
|
||||
}
|
||||
export interface ddeSVGPatternElement extends SVGPatternElement {
|
||||
append: ddeAppend<ddeSVGPatternElement>;
|
||||
}
|
||||
export interface ddeSVGPolygonElement extends SVGPolygonElement {
|
||||
append: ddeAppend<ddeSVGPolygonElement>;
|
||||
}
|
||||
export interface ddeSVGPolylineElement extends SVGPolylineElement {
|
||||
append: ddeAppend<ddeSVGPolylineElement>;
|
||||
}
|
||||
export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement {
|
||||
append: ddeAppend<ddeSVGRadialGradientElement>;
|
||||
}
|
||||
export interface ddeSVGRectElement extends SVGRectElement {
|
||||
append: ddeAppend<ddeSVGRectElement>;
|
||||
}
|
||||
export interface ddeSVGScriptElement extends SVGScriptElement {
|
||||
append: ddeAppend<ddeSVGScriptElement>;
|
||||
}
|
||||
export interface ddeSVGSetElement extends SVGSetElement {
|
||||
append: ddeAppend<ddeSVGSetElement>;
|
||||
}
|
||||
export interface ddeSVGStopElement extends SVGStopElement {
|
||||
append: ddeAppend<ddeSVGStopElement>;
|
||||
}
|
||||
export interface ddeSVGStyleElement extends SVGStyleElement {
|
||||
append: ddeAppend<ddeSVGStyleElement>;
|
||||
}
|
||||
export interface ddeSVGSVGElement extends SVGSVGElement {
|
||||
append: ddeAppend<ddeSVGSVGElement>;
|
||||
}
|
||||
export interface ddeSVGSwitchElement extends SVGSwitchElement {
|
||||
append: ddeAppend<ddeSVGSwitchElement>;
|
||||
}
|
||||
export interface ddeSVGSymbolElement extends SVGSymbolElement {
|
||||
append: ddeAppend<ddeSVGSymbolElement>;
|
||||
}
|
||||
export interface ddeSVGTextElement extends SVGTextElement {
|
||||
append: ddeAppend<ddeSVGTextElement>;
|
||||
}
|
||||
export interface ddeSVGTextPathElement extends SVGTextPathElement {
|
||||
append: ddeAppend<ddeSVGTextPathElement>;
|
||||
}
|
||||
export interface ddeSVGTitleElement extends SVGTitleElement {
|
||||
append: ddeAppend<ddeSVGTitleElement>;
|
||||
}
|
||||
export interface ddeSVGTSpanElement extends SVGTSpanElement {
|
||||
append: ddeAppend<ddeSVGTSpanElement>;
|
||||
}
|
||||
export interface ddeSVGUseElement extends SVGUseElement {
|
||||
append: ddeAppend<ddeSVGUseElement>;
|
||||
}
|
||||
export interface ddeSVGViewElement extends SVGViewElement {
|
||||
append: ddeAppend<ddeSVGViewElement>;
|
||||
}
|
||||
|
||||
export {
|
||||
dispatchEvent$1 as dispatchEvent,
|
||||
el as createElement,
|
||||
elNS as createElementNS,
|
||||
};
|
||||
|
||||
export as namespace dde;
|
||||
|
||||
export {};
|
1645
dist/dde-with-signals.js
vendored
1645
dist/dde-with-signals.js
vendored
File diff suppressed because it is too large
Load Diff
785
dist/dde-with-signals.min.d.ts
vendored
Normal file
785
dist/dde-with-signals.min.d.ts
vendored
Normal file
@ -0,0 +1,785 @@
|
||||
// Generated by dts-bundle-generator v9.5.1
|
||||
|
||||
export interface Signal<V, A> {
|
||||
/** The current value of the signal */
|
||||
get(): V;
|
||||
/** Set new value of the signal */
|
||||
set(value: V): V;
|
||||
toJSON(): V;
|
||||
valueOf(): V;
|
||||
}
|
||||
export type Action<V> = (this: {
|
||||
value: V;
|
||||
stopPropagation(): void;
|
||||
}, ...a: any[]) => typeof signal._ | void;
|
||||
//type SymbolSignal= Symbol;
|
||||
export type SymbolOnclear = symbol;
|
||||
export type Actions<V> = Record<string | SymbolOnclear, Action<V>>;
|
||||
export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & {
|
||||
first_time?: boolean;
|
||||
};
|
||||
export interface signal {
|
||||
_: Symbol;
|
||||
/**
|
||||
* Computations signal. This creates a signal which is computed from other signals.
|
||||
* */
|
||||
<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>;
|
||||
/**
|
||||
* Simple example:
|
||||
* ```js
|
||||
* const hello= S("Hello Signal");
|
||||
* ```
|
||||
* …simple todo signal:
|
||||
* ```js
|
||||
* const todos= S([], {
|
||||
* add(v){ this.value.push(S(v)); },
|
||||
* remove(i){ this.value.splice(i, 1); },
|
||||
* [S.symbols.onclear](){ S.clear(...this.value); },
|
||||
* });
|
||||
* ```
|
||||
* …computed signal:
|
||||
* ```js
|
||||
* const name= S("Jan");
|
||||
* const surname= S("Andrle");
|
||||
* const fullname= S(()=> name.get()+" "+surname.get());
|
||||
* ```
|
||||
* @param value Initial signal value. Or function computing value from other signals.
|
||||
* @param actions Use to define actions on the signal. Such as add item to the array.
|
||||
* There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared
|
||||
* by `S.clear`.
|
||||
* */
|
||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void;
|
||||
clear(...signals: Signal<any, any>[]): void;
|
||||
on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void;
|
||||
symbols: {
|
||||
//signal: SymbolSignal;
|
||||
onclear: SymbolOnclear;
|
||||
};
|
||||
/**
|
||||
* Reactive element, which is rendered based on the given signal.
|
||||
* ```js
|
||||
* S.el(signal, value=> value ? el("b", "True") : el("i", "False"));
|
||||
* S.el(listS, list=> list.map(li=> el("li", li)));
|
||||
* ```
|
||||
* */
|
||||
el<S extends any>(signal: Signal<S, any>, el: (v: S) => Element | Element[] | DocumentFragment): DocumentFragment;
|
||||
observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>;
|
||||
}
|
||||
export const signal: signal;
|
||||
export const S: signal;
|
||||
declare global {
|
||||
type ddeSignal<T, A = {}> = Signal<T, A>;
|
||||
type ddeAction<V> = Action<V>;
|
||||
type ddeActions<V> = Actions<V>;
|
||||
}
|
||||
export type CustomElementTagNameMap = {
|
||||
"#text": Text;
|
||||
"#comment": Comment;
|
||||
};
|
||||
export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
||||
declare global {
|
||||
type ddeComponentAttributes = Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El) => any;
|
||||
type ddeString = string | Signal<string, {}>;
|
||||
type ddeStringable = ddeString | number | Signal<number, {}>;
|
||||
}
|
||||
export type PascalCase = `${Capitalize<string>}${string}`;
|
||||
export type AttrsModified = {
|
||||
/**
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString | Partial<{
|
||||
[K in keyof CSSStyleDeclaration]: Signal<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.
|
||||
*/
|
||||
classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>;
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap)
|
||||
* */
|
||||
dataset: Record<string, ddeStringable>;
|
||||
/**
|
||||
* Sets `aria-*` simiraly to `dataset`
|
||||
* */
|
||||
ariaset: Record<string, ddeString>;
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>;
|
||||
export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>;
|
||||
export type IsReadonly<T, K extends keyof T> = T extends {
|
||||
readonly [P in K]: T[K];
|
||||
} ? true : false;
|
||||
/**
|
||||
* 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)).
|
||||
*
|
||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||
* @private
|
||||
*/
|
||||
export type ElementAttributes<T extends SupportedElement> = Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable);
|
||||
} & 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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT];
|
||||
export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(attrs: {
|
||||
type: "component" | "reactive" | "later";
|
||||
name?: string;
|
||||
host?: "this" | "parentElement";
|
||||
}, is_open?: boolean): Comment;
|
||||
}
|
||||
export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<A extends {
|
||||
textContent: ddeStringable;
|
||||
}, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement;
|
||||
export function el(tag_name?: "<>"): ddeDocumentFragment;
|
||||
export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement;
|
||||
export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement;
|
||||
export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean;
|
||||
}>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement;
|
||||
export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement;
|
||||
export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
||||
/** Simulate slots for ddeComponents */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL;
|
||||
/**
|
||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||
* @param el Custom Element root element
|
||||
* @param body Body of the custom element
|
||||
* */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, element: SupportedElement): (data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, element: SupportedElement | (() => SupportedElement)): (data?: any) => void;
|
||||
export interface On {
|
||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||
<Event extends keyof DocumentEventMap, EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: Event, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any, options?: AddEventListenerOptions): EE;
|
||||
<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
connected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<El>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
disconnected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
attributeChanged<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<[
|
||||
string,
|
||||
string
|
||||
]>) => any, options?: AddEventListenerOptions): EE;
|
||||
}
|
||||
export const on: On;
|
||||
export 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}) */
|
||||
export const scope: {
|
||||
current: Scope;
|
||||
/** Stops all automatizations. E. g. signals used as attributes in current scope
|
||||
* registers removing these listeners (and clean signal if no other listeners are detected)
|
||||
* on `disconnected` event. */
|
||||
preventDefault<T extends boolean>(prevent: T): T;
|
||||
/**
|
||||
* This represents reference to the current host element — `scope.host()`.
|
||||
* It can be also used to register Addon(s) (functions to be called when component is initized)
|
||||
* — `scope.host(on.connected(console.log))`.
|
||||
* */
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||
state: Scope[];
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>;
|
||||
/** Removes last/current child scope. */
|
||||
pop(): ReturnType<Array<Scope>["pop"]>;
|
||||
};
|
||||
export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL;
|
||||
export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>;
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
/* TypeScript MEH */
|
||||
declare global {
|
||||
type ddeAppend<el> = (...nodes: (Node | string)[]) => el;
|
||||
interface ddeDocumentFragment extends DocumentFragment {
|
||||
append: ddeAppend<ddeDocumentFragment>;
|
||||
}
|
||||
interface ddeHTMLElement extends HTMLElement {
|
||||
append: ddeAppend<ddeHTMLElement>;
|
||||
}
|
||||
interface ddeSVGElement extends SVGElement {
|
||||
append: ddeAppend<ddeSVGElement>;
|
||||
}
|
||||
interface ddeMathMLElement extends MathMLElement {
|
||||
append: ddeAppend<ddeMathMLElement>;
|
||||
}
|
||||
interface ddeHTMLElementTagNameMap {
|
||||
"a": ddeHTMLAnchorElement;
|
||||
"area": ddeHTMLAreaElement;
|
||||
"audio": ddeHTMLAudioElement;
|
||||
"base": ddeHTMLBaseElement;
|
||||
"blockquote": ddeHTMLQuoteElement;
|
||||
"body": ddeHTMLBodyElement;
|
||||
"br": ddeHTMLBRElement;
|
||||
"button": ddeHTMLButtonElement;
|
||||
"canvas": ddeHTMLCanvasElement;
|
||||
"caption": ddeHTMLTableCaptionElement;
|
||||
"col": ddeHTMLTableColElement;
|
||||
"colgroup": ddeHTMLTableColElement;
|
||||
"data": ddeHTMLDataElement;
|
||||
"datalist": ddeHTMLDataListElement;
|
||||
"del": ddeHTMLModElement;
|
||||
"details": ddeHTMLDetailsElement;
|
||||
"dialog": ddeHTMLDialogElement;
|
||||
"div": ddeHTMLDivElement;
|
||||
"dl": ddeHTMLDListElement;
|
||||
"embed": ddeHTMLEmbedElement;
|
||||
"fieldset": ddeHTMLFieldSetElement;
|
||||
"form": ddeHTMLFormElement;
|
||||
"h1": ddeHTMLHeadingElement;
|
||||
"h2": ddeHTMLHeadingElement;
|
||||
"h3": ddeHTMLHeadingElement;
|
||||
"h4": ddeHTMLHeadingElement;
|
||||
"h5": ddeHTMLHeadingElement;
|
||||
"h6": ddeHTMLHeadingElement;
|
||||
"head": ddeHTMLHeadElement;
|
||||
"hr": ddeHTMLHRElement;
|
||||
"html": ddeHTMLHtmlElement;
|
||||
"iframe": ddeHTMLIFrameElement;
|
||||
"img": ddeHTMLImageElement;
|
||||
"input": ddeHTMLInputElement;
|
||||
"ins": ddeHTMLModElement;
|
||||
"label": ddeHTMLLabelElement;
|
||||
"legend": ddeHTMLLegendElement;
|
||||
"li": ddeHTMLLIElement;
|
||||
"link": ddeHTMLLinkElement;
|
||||
"map": ddeHTMLMapElement;
|
||||
"menu": ddeHTMLMenuElement;
|
||||
"meta": ddeHTMLMetaElement;
|
||||
"meter": ddeHTMLMeterElement;
|
||||
"object": ddeHTMLObjectElement;
|
||||
"ol": ddeHTMLOListElement;
|
||||
"optgroup": ddeHTMLOptGroupElement;
|
||||
"option": ddeHTMLOptionElement;
|
||||
"output": ddeHTMLOutputElement;
|
||||
"p": ddeHTMLParagraphElement;
|
||||
"picture": ddeHTMLPictureElement;
|
||||
"pre": ddeHTMLPreElement;
|
||||
"progress": ddeHTMLProgressElement;
|
||||
"q": ddeHTMLQuoteElement;
|
||||
"script": ddeHTMLScriptElement;
|
||||
"select": ddeHTMLSelectElement;
|
||||
"slot": ddeHTMLSlotElement;
|
||||
"source": ddeHTMLSourceElement;
|
||||
"span": ddeHTMLSpanElement;
|
||||
"style": ddeHTMLStyleElement;
|
||||
"table": ddeHTMLTableElement;
|
||||
"tbody": ddeHTMLTableSectionElement;
|
||||
"td": ddeHTMLTableCellElement;
|
||||
"template": ddeHTMLTemplateElement;
|
||||
"textarea": ddeHTMLTextAreaElement;
|
||||
"tfoot": ddeHTMLTableSectionElement;
|
||||
"th": ddeHTMLTableCellElement;
|
||||
"thead": ddeHTMLTableSectionElement;
|
||||
"time": ddeHTMLTimeElement;
|
||||
"title": ddeHTMLTitleElement;
|
||||
"tr": ddeHTMLTableRowElement;
|
||||
"track": ddeHTMLTrackElement;
|
||||
"ul": ddeHTMLUListElement;
|
||||
"video": ddeHTMLVideoElement;
|
||||
}
|
||||
interface ddeSVGElementTagNameMap {
|
||||
"a": ddeSVGAElement;
|
||||
"animate": ddeSVGAnimateElement;
|
||||
"animateMotion": ddeSVGAnimateMotionElement;
|
||||
"animateTransform": ddeSVGAnimateTransformElement;
|
||||
"circle": ddeSVGCircleElement;
|
||||
"clipPath": ddeSVGClipPathElement;
|
||||
"defs": ddeSVGDefsElement;
|
||||
"desc": ddeSVGDescElement;
|
||||
"ellipse": ddeSVGEllipseElement;
|
||||
"feBlend": ddeSVGFEBlendElement;
|
||||
"feColorMatrix": ddeSVGFEColorMatrixElement;
|
||||
"feComponentTransfer": ddeSVGFEComponentTransferElement;
|
||||
"feComposite": ddeSVGFECompositeElement;
|
||||
"feConvolveMatrix": ddeSVGFEConvolveMatrixElement;
|
||||
"feDiffuseLighting": ddeSVGFEDiffuseLightingElement;
|
||||
"feDisplacementMap": ddeSVGFEDisplacementMapElement;
|
||||
"feDistantLight": ddeSVGFEDistantLightElement;
|
||||
"feDropShadow": ddeSVGFEDropShadowElement;
|
||||
"feFlood": ddeSVGFEFloodElement;
|
||||
"feFuncA": ddeSVGFEFuncAElement;
|
||||
"feFuncB": ddeSVGFEFuncBElement;
|
||||
"feFuncG": ddeSVGFEFuncGElement;
|
||||
"feFuncR": ddeSVGFEFuncRElement;
|
||||
"feGaussianBlur": ddeSVGFEGaussianBlurElement;
|
||||
"feImage": ddeSVGFEImageElement;
|
||||
"feMerge": ddeSVGFEMergeElement;
|
||||
"feMergeNode": ddeSVGFEMergeNodeElement;
|
||||
"feMorphology": ddeSVGFEMorphologyElement;
|
||||
"feOffset": ddeSVGFEOffsetElement;
|
||||
"fePointLight": ddeSVGFEPointLightElement;
|
||||
"feSpecularLighting": ddeSVGFESpecularLightingElement;
|
||||
"feSpotLight": ddeSVGFESpotLightElement;
|
||||
"feTile": ddeSVGFETileElement;
|
||||
"feTurbulence": ddeSVGFETurbulenceElement;
|
||||
"filter": ddeSVGFilterElement;
|
||||
"foreignObject": ddeSVGForeignObjectElement;
|
||||
"g": ddeSVGGElement;
|
||||
"image": ddeSVGImageElement;
|
||||
"line": ddeSVGLineElement;
|
||||
"linearGradient": ddeSVGLinearGradientElement;
|
||||
"marker": ddeSVGMarkerElement;
|
||||
"mask": ddeSVGMaskElement;
|
||||
"metadata": ddeSVGMetadataElement;
|
||||
"mpath": ddeSVGMPathElement;
|
||||
"path": ddeSVGPathElement;
|
||||
"pattern": ddeSVGPatternElement;
|
||||
"polygon": ddeSVGPolygonElement;
|
||||
"polyline": ddeSVGPolylineElement;
|
||||
"radialGradient": ddeSVGRadialGradientElement;
|
||||
"rect": ddeSVGRectElement;
|
||||
"script": ddeSVGScriptElement;
|
||||
"set": ddeSVGSetElement;
|
||||
"stop": ddeSVGStopElement;
|
||||
"style": ddeSVGStyleElement;
|
||||
"svg": ddeSVGSVGElement;
|
||||
"switch": ddeSVGSwitchElement;
|
||||
"symbol": ddeSVGSymbolElement;
|
||||
"text": ddeSVGTextElement;
|
||||
"textPath": ddeSVGTextPathElement;
|
||||
"title": ddeSVGTitleElement;
|
||||
"tspan": ddeSVGTSpanElement;
|
||||
"use": ddeSVGUseElement;
|
||||
"view": ddeSVGViewElement;
|
||||
}
|
||||
}
|
||||
// editorconfig-checker-disable
|
||||
export interface ddeHTMLAnchorElement extends HTMLAnchorElement {
|
||||
append: ddeAppend<ddeHTMLAnchorElement>;
|
||||
}
|
||||
export interface ddeHTMLAreaElement extends HTMLAreaElement {
|
||||
append: ddeAppend<ddeHTMLAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLAudioElement extends HTMLAudioElement {
|
||||
append: ddeAppend<ddeHTMLAudioElement>;
|
||||
}
|
||||
export interface ddeHTMLBaseElement extends HTMLBaseElement {
|
||||
append: ddeAppend<ddeHTMLBaseElement>;
|
||||
}
|
||||
export interface ddeHTMLQuoteElement extends HTMLQuoteElement {
|
||||
append: ddeAppend<ddeHTMLQuoteElement>;
|
||||
}
|
||||
export interface ddeHTMLBodyElement extends HTMLBodyElement {
|
||||
append: ddeAppend<ddeHTMLBodyElement>;
|
||||
}
|
||||
export interface ddeHTMLBRElement extends HTMLBRElement {
|
||||
append: ddeAppend<ddeHTMLBRElement>;
|
||||
}
|
||||
export interface ddeHTMLButtonElement extends HTMLButtonElement {
|
||||
append: ddeAppend<ddeHTMLButtonElement>;
|
||||
}
|
||||
export interface ddeHTMLCanvasElement extends HTMLCanvasElement {
|
||||
append: ddeAppend<ddeHTMLCanvasElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement {
|
||||
append: ddeAppend<ddeHTMLTableCaptionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLDataElement extends HTMLDataElement {
|
||||
append: ddeAppend<ddeHTMLDataElement>;
|
||||
}
|
||||
export interface ddeHTMLDataListElement extends HTMLDataListElement {
|
||||
append: ddeAppend<ddeHTMLDataListElement>;
|
||||
}
|
||||
export interface ddeHTMLModElement extends HTMLModElement {
|
||||
append: ddeAppend<ddeHTMLModElement>;
|
||||
}
|
||||
export interface ddeHTMLDetailsElement extends HTMLDetailsElement {
|
||||
append: ddeAppend<ddeHTMLDetailsElement>;
|
||||
}
|
||||
export interface ddeHTMLDialogElement extends HTMLDialogElement {
|
||||
append: ddeAppend<ddeHTMLDialogElement>;
|
||||
}
|
||||
export interface ddeHTMLDivElement extends HTMLDivElement {
|
||||
append: ddeAppend<ddeHTMLDivElement>;
|
||||
}
|
||||
export interface ddeHTMLDListElement extends HTMLDListElement {
|
||||
append: ddeAppend<ddeHTMLDListElement>;
|
||||
}
|
||||
export interface ddeHTMLEmbedElement extends HTMLEmbedElement {
|
||||
append: ddeAppend<ddeHTMLEmbedElement>;
|
||||
}
|
||||
export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement {
|
||||
append: ddeAppend<ddeHTMLFieldSetElement>;
|
||||
}
|
||||
export interface ddeHTMLFormElement extends HTMLFormElement {
|
||||
append: ddeAppend<ddeHTMLFormElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadingElement extends HTMLHeadingElement {
|
||||
append: ddeAppend<ddeHTMLHeadingElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadElement extends HTMLHeadElement {
|
||||
append: ddeAppend<ddeHTMLHeadElement>;
|
||||
}
|
||||
export interface ddeHTMLHRElement extends HTMLHRElement {
|
||||
append: ddeAppend<ddeHTMLHRElement>;
|
||||
}
|
||||
export interface ddeHTMLHtmlElement extends HTMLHtmlElement {
|
||||
append: ddeAppend<ddeHTMLHtmlElement>;
|
||||
}
|
||||
export interface ddeHTMLIFrameElement extends HTMLIFrameElement {
|
||||
append: ddeAppend<ddeHTMLIFrameElement>;
|
||||
}
|
||||
export interface ddeHTMLImageElement extends HTMLImageElement {
|
||||
append: ddeAppend<ddeHTMLImageElement>;
|
||||
}
|
||||
export interface ddeHTMLInputElement extends HTMLInputElement {
|
||||
append: ddeAppend<ddeHTMLInputElement>;
|
||||
}
|
||||
export interface ddeHTMLLabelElement extends HTMLLabelElement {
|
||||
append: ddeAppend<ddeHTMLLabelElement>;
|
||||
}
|
||||
export interface ddeHTMLLegendElement extends HTMLLegendElement {
|
||||
append: ddeAppend<ddeHTMLLegendElement>;
|
||||
}
|
||||
export interface ddeHTMLLIElement extends HTMLLIElement {
|
||||
append: ddeAppend<ddeHTMLLIElement>;
|
||||
}
|
||||
export interface ddeHTMLLinkElement extends HTMLLinkElement {
|
||||
append: ddeAppend<ddeHTMLLinkElement>;
|
||||
}
|
||||
export interface ddeHTMLMapElement extends HTMLMapElement {
|
||||
append: ddeAppend<ddeHTMLMapElement>;
|
||||
}
|
||||
export interface ddeHTMLMenuElement extends HTMLMenuElement {
|
||||
append: ddeAppend<ddeHTMLMenuElement>;
|
||||
}
|
||||
export interface ddeHTMLMetaElement extends HTMLMetaElement {
|
||||
append: ddeAppend<ddeHTMLMetaElement>;
|
||||
}
|
||||
export interface ddeHTMLMeterElement extends HTMLMeterElement {
|
||||
append: ddeAppend<ddeHTMLMeterElement>;
|
||||
}
|
||||
export interface ddeHTMLObjectElement extends HTMLObjectElement {
|
||||
append: ddeAppend<ddeHTMLObjectElement>;
|
||||
}
|
||||
export interface ddeHTMLOListElement extends HTMLOListElement {
|
||||
append: ddeAppend<ddeHTMLOListElement>;
|
||||
}
|
||||
export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement {
|
||||
append: ddeAppend<ddeHTMLOptGroupElement>;
|
||||
}
|
||||
export interface ddeHTMLOptionElement extends HTMLOptionElement {
|
||||
append: ddeAppend<ddeHTMLOptionElement>;
|
||||
}
|
||||
export interface ddeHTMLOutputElement extends HTMLOutputElement {
|
||||
append: ddeAppend<ddeHTMLOutputElement>;
|
||||
}
|
||||
export interface ddeHTMLParagraphElement extends HTMLParagraphElement {
|
||||
append: ddeAppend<ddeHTMLParagraphElement>;
|
||||
}
|
||||
export interface ddeHTMLPictureElement extends HTMLPictureElement {
|
||||
append: ddeAppend<ddeHTMLPictureElement>;
|
||||
}
|
||||
export interface ddeHTMLPreElement extends HTMLPreElement {
|
||||
append: ddeAppend<ddeHTMLPreElement>;
|
||||
}
|
||||
export interface ddeHTMLProgressElement extends HTMLProgressElement {
|
||||
append: ddeAppend<ddeHTMLProgressElement>;
|
||||
}
|
||||
export interface ddeHTMLScriptElement extends HTMLScriptElement {
|
||||
append: ddeAppend<ddeHTMLScriptElement>;
|
||||
}
|
||||
export interface ddeHTMLSelectElement extends HTMLSelectElement {
|
||||
append: ddeAppend<ddeHTMLSelectElement>;
|
||||
}
|
||||
export interface ddeHTMLSlotElement extends HTMLSlotElement {
|
||||
append: ddeAppend<ddeHTMLSlotElement>;
|
||||
}
|
||||
export interface ddeHTMLSourceElement extends HTMLSourceElement {
|
||||
append: ddeAppend<ddeHTMLSourceElement>;
|
||||
}
|
||||
export interface ddeHTMLSpanElement extends HTMLSpanElement {
|
||||
append: ddeAppend<ddeHTMLSpanElement>;
|
||||
}
|
||||
export interface ddeHTMLStyleElement extends HTMLStyleElement {
|
||||
append: ddeAppend<ddeHTMLStyleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableElement extends HTMLTableElement {
|
||||
append: ddeAppend<ddeHTMLTableElement>;
|
||||
}
|
||||
export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement {
|
||||
append: ddeAppend<ddeHTMLTableSectionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTemplateElement extends HTMLTemplateElement {
|
||||
append: ddeAppend<ddeHTMLTemplateElement>;
|
||||
}
|
||||
export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement {
|
||||
append: ddeAppend<ddeHTMLTextAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTimeElement extends HTMLTimeElement {
|
||||
append: ddeAppend<ddeHTMLTimeElement>;
|
||||
}
|
||||
export interface ddeHTMLTitleElement extends HTMLTitleElement {
|
||||
append: ddeAppend<ddeHTMLTitleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableRowElement extends HTMLTableRowElement {
|
||||
append: ddeAppend<ddeHTMLTableRowElement>;
|
||||
}
|
||||
export interface ddeHTMLTrackElement extends HTMLTrackElement {
|
||||
append: ddeAppend<ddeHTMLTrackElement>;
|
||||
}
|
||||
export interface ddeHTMLUListElement extends HTMLUListElement {
|
||||
append: ddeAppend<ddeHTMLUListElement>;
|
||||
}
|
||||
export interface ddeHTMLVideoElement extends HTMLVideoElement {
|
||||
append: ddeAppend<ddeHTMLVideoElement>;
|
||||
}
|
||||
export interface ddeSVGAElement extends SVGAElement {
|
||||
append: ddeAppend<ddeSVGAElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateElement extends SVGAnimateElement {
|
||||
append: ddeAppend<ddeSVGAnimateElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement {
|
||||
append: ddeAppend<ddeSVGAnimateMotionElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement {
|
||||
append: ddeAppend<ddeSVGAnimateTransformElement>;
|
||||
}
|
||||
export interface ddeSVGCircleElement extends SVGCircleElement {
|
||||
append: ddeAppend<ddeSVGCircleElement>;
|
||||
}
|
||||
export interface ddeSVGClipPathElement extends SVGClipPathElement {
|
||||
append: ddeAppend<ddeSVGClipPathElement>;
|
||||
}
|
||||
export interface ddeSVGDefsElement extends SVGDefsElement {
|
||||
append: ddeAppend<ddeSVGDefsElement>;
|
||||
}
|
||||
export interface ddeSVGDescElement extends SVGDescElement {
|
||||
append: ddeAppend<ddeSVGDescElement>;
|
||||
}
|
||||
export interface ddeSVGEllipseElement extends SVGEllipseElement {
|
||||
append: ddeAppend<ddeSVGEllipseElement>;
|
||||
}
|
||||
export interface ddeSVGFEBlendElement extends SVGFEBlendElement {
|
||||
append: ddeAppend<ddeSVGFEBlendElement>;
|
||||
}
|
||||
export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEColorMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement {
|
||||
append: ddeAppend<ddeSVGFEComponentTransferElement>;
|
||||
}
|
||||
export interface ddeSVGFECompositeElement extends SVGFECompositeElement {
|
||||
append: ddeAppend<ddeSVGFECompositeElement>;
|
||||
}
|
||||
export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEConvolveMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement {
|
||||
append: ddeAppend<ddeSVGFEDiffuseLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement {
|
||||
append: ddeAppend<ddeSVGFEDisplacementMapElement>;
|
||||
}
|
||||
export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement {
|
||||
append: ddeAppend<ddeSVGFEDistantLightElement>;
|
||||
}
|
||||
export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement {
|
||||
append: ddeAppend<ddeSVGFEDropShadowElement>;
|
||||
}
|
||||
export interface ddeSVGFEFloodElement extends SVGFEFloodElement {
|
||||
append: ddeAppend<ddeSVGFEFloodElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement {
|
||||
append: ddeAppend<ddeSVGFEFuncAElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement {
|
||||
append: ddeAppend<ddeSVGFEFuncBElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement {
|
||||
append: ddeAppend<ddeSVGFEFuncGElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement {
|
||||
append: ddeAppend<ddeSVGFEFuncRElement>;
|
||||
}
|
||||
export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement {
|
||||
append: ddeAppend<ddeSVGFEGaussianBlurElement>;
|
||||
}
|
||||
export interface ddeSVGFEImageElement extends SVGFEImageElement {
|
||||
append: ddeAppend<ddeSVGFEImageElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeElement extends SVGFEMergeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeNodeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement {
|
||||
append: ddeAppend<ddeSVGFEMorphologyElement>;
|
||||
}
|
||||
export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement {
|
||||
append: ddeAppend<ddeSVGFEOffsetElement>;
|
||||
}
|
||||
export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement {
|
||||
append: ddeAppend<ddeSVGFEPointLightElement>;
|
||||
}
|
||||
export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement {
|
||||
append: ddeAppend<ddeSVGFESpecularLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement {
|
||||
append: ddeAppend<ddeSVGFESpotLightElement>;
|
||||
}
|
||||
export interface ddeSVGFETileElement extends SVGFETileElement {
|
||||
append: ddeAppend<ddeSVGFETileElement>;
|
||||
}
|
||||
export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement {
|
||||
append: ddeAppend<ddeSVGFETurbulenceElement>;
|
||||
}
|
||||
export interface ddeSVGFilterElement extends SVGFilterElement {
|
||||
append: ddeAppend<ddeSVGFilterElement>;
|
||||
}
|
||||
export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement {
|
||||
append: ddeAppend<ddeSVGForeignObjectElement>;
|
||||
}
|
||||
export interface ddeSVGGElement extends SVGGElement {
|
||||
append: ddeAppend<ddeSVGGElement>;
|
||||
}
|
||||
export interface ddeSVGImageElement extends SVGImageElement {
|
||||
append: ddeAppend<ddeSVGImageElement>;
|
||||
}
|
||||
export interface ddeSVGLineElement extends SVGLineElement {
|
||||
append: ddeAppend<ddeSVGLineElement>;
|
||||
}
|
||||
export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement {
|
||||
append: ddeAppend<ddeSVGLinearGradientElement>;
|
||||
}
|
||||
export interface ddeSVGMarkerElement extends SVGMarkerElement {
|
||||
append: ddeAppend<ddeSVGMarkerElement>;
|
||||
}
|
||||
export interface ddeSVGMaskElement extends SVGMaskElement {
|
||||
append: ddeAppend<ddeSVGMaskElement>;
|
||||
}
|
||||
export interface ddeSVGMetadataElement extends SVGMetadataElement {
|
||||
append: ddeAppend<ddeSVGMetadataElement>;
|
||||
}
|
||||
export interface ddeSVGMPathElement extends SVGMPathElement {
|
||||
append: ddeAppend<ddeSVGMPathElement>;
|
||||
}
|
||||
export interface ddeSVGPathElement extends SVGPathElement {
|
||||
append: ddeAppend<ddeSVGPathElement>;
|
||||
}
|
||||
export interface ddeSVGPatternElement extends SVGPatternElement {
|
||||
append: ddeAppend<ddeSVGPatternElement>;
|
||||
}
|
||||
export interface ddeSVGPolygonElement extends SVGPolygonElement {
|
||||
append: ddeAppend<ddeSVGPolygonElement>;
|
||||
}
|
||||
export interface ddeSVGPolylineElement extends SVGPolylineElement {
|
||||
append: ddeAppend<ddeSVGPolylineElement>;
|
||||
}
|
||||
export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement {
|
||||
append: ddeAppend<ddeSVGRadialGradientElement>;
|
||||
}
|
||||
export interface ddeSVGRectElement extends SVGRectElement {
|
||||
append: ddeAppend<ddeSVGRectElement>;
|
||||
}
|
||||
export interface ddeSVGScriptElement extends SVGScriptElement {
|
||||
append: ddeAppend<ddeSVGScriptElement>;
|
||||
}
|
||||
export interface ddeSVGSetElement extends SVGSetElement {
|
||||
append: ddeAppend<ddeSVGSetElement>;
|
||||
}
|
||||
export interface ddeSVGStopElement extends SVGStopElement {
|
||||
append: ddeAppend<ddeSVGStopElement>;
|
||||
}
|
||||
export interface ddeSVGStyleElement extends SVGStyleElement {
|
||||
append: ddeAppend<ddeSVGStyleElement>;
|
||||
}
|
||||
export interface ddeSVGSVGElement extends SVGSVGElement {
|
||||
append: ddeAppend<ddeSVGSVGElement>;
|
||||
}
|
||||
export interface ddeSVGSwitchElement extends SVGSwitchElement {
|
||||
append: ddeAppend<ddeSVGSwitchElement>;
|
||||
}
|
||||
export interface ddeSVGSymbolElement extends SVGSymbolElement {
|
||||
append: ddeAppend<ddeSVGSymbolElement>;
|
||||
}
|
||||
export interface ddeSVGTextElement extends SVGTextElement {
|
||||
append: ddeAppend<ddeSVGTextElement>;
|
||||
}
|
||||
export interface ddeSVGTextPathElement extends SVGTextPathElement {
|
||||
append: ddeAppend<ddeSVGTextPathElement>;
|
||||
}
|
||||
export interface ddeSVGTitleElement extends SVGTitleElement {
|
||||
append: ddeAppend<ddeSVGTitleElement>;
|
||||
}
|
||||
export interface ddeSVGTSpanElement extends SVGTSpanElement {
|
||||
append: ddeAppend<ddeSVGTSpanElement>;
|
||||
}
|
||||
export interface ddeSVGUseElement extends SVGUseElement {
|
||||
append: ddeAppend<ddeSVGUseElement>;
|
||||
}
|
||||
export interface ddeSVGViewElement extends SVGViewElement {
|
||||
append: ddeAppend<ddeSVGViewElement>;
|
||||
}
|
||||
|
||||
export {
|
||||
dispatchEvent$1 as dispatchEvent,
|
||||
el as createElement,
|
||||
elNS as createElementNS,
|
||||
};
|
||||
|
||||
export as namespace dde;
|
||||
|
||||
export {};
|
4
dist/dde-with-signals.min.js
vendored
Normal file
4
dist/dde-with-signals.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
784
dist/dde.d.ts
vendored
Normal file
784
dist/dde.d.ts
vendored
Normal file
@ -0,0 +1,784 @@
|
||||
// Generated by dts-bundle-generator v9.5.1
|
||||
|
||||
export interface Signal<V, A> {
|
||||
/** The current value of the signal */
|
||||
get(): V;
|
||||
/** Set new value of the signal */
|
||||
set(value: V): V;
|
||||
toJSON(): V;
|
||||
valueOf(): V;
|
||||
}
|
||||
export type Action<V> = (this: {
|
||||
value: V;
|
||||
stopPropagation(): void;
|
||||
}, ...a: any[]) => typeof signal._ | void;
|
||||
//type SymbolSignal= Symbol;
|
||||
export type SymbolOnclear = symbol;
|
||||
export type Actions<V> = Record<string | SymbolOnclear, Action<V>>;
|
||||
export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & {
|
||||
first_time?: boolean;
|
||||
};
|
||||
export interface signal {
|
||||
_: Symbol;
|
||||
/**
|
||||
* Computations signal. This creates a signal which is computed from other signals.
|
||||
* */
|
||||
<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>;
|
||||
/**
|
||||
* Simple example:
|
||||
* ```js
|
||||
* const hello= S("Hello Signal");
|
||||
* ```
|
||||
* …simple todo signal:
|
||||
* ```js
|
||||
* const todos= S([], {
|
||||
* add(v){ this.value.push(S(v)); },
|
||||
* remove(i){ this.value.splice(i, 1); },
|
||||
* [S.symbols.onclear](){ S.clear(...this.value); },
|
||||
* });
|
||||
* ```
|
||||
* …computed signal:
|
||||
* ```js
|
||||
* const name= S("Jan");
|
||||
* const surname= S("Andrle");
|
||||
* const fullname= S(()=> name.get()+" "+surname.get());
|
||||
* ```
|
||||
* @param value Initial signal value. Or function computing value from other signals.
|
||||
* @param actions Use to define actions on the signal. Such as add item to the array.
|
||||
* There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared
|
||||
* by `S.clear`.
|
||||
* */
|
||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void;
|
||||
clear(...signals: Signal<any, any>[]): void;
|
||||
on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void;
|
||||
symbols: {
|
||||
//signal: SymbolSignal;
|
||||
onclear: SymbolOnclear;
|
||||
};
|
||||
/**
|
||||
* Reactive element, which is rendered based on the given signal.
|
||||
* ```js
|
||||
* S.el(signal, value=> value ? el("b", "True") : el("i", "False"));
|
||||
* S.el(listS, list=> list.map(li=> el("li", li)));
|
||||
* ```
|
||||
* */
|
||||
el<S extends any>(signal: Signal<S, any>, el: (v: S) => Element | Element[] | DocumentFragment): DocumentFragment;
|
||||
observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>;
|
||||
}
|
||||
declare const signal: signal;
|
||||
declare global {
|
||||
type ddeSignal<T, A = {}> = Signal<T, A>;
|
||||
type ddeAction<V> = Action<V>;
|
||||
type ddeActions<V> = Actions<V>;
|
||||
}
|
||||
export type CustomElementTagNameMap = {
|
||||
"#text": Text;
|
||||
"#comment": Comment;
|
||||
};
|
||||
export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
||||
declare global {
|
||||
type ddeComponentAttributes = Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El) => any;
|
||||
type ddeString = string | Signal<string, {}>;
|
||||
type ddeStringable = ddeString | number | Signal<number, {}>;
|
||||
}
|
||||
export type PascalCase = `${Capitalize<string>}${string}`;
|
||||
export type AttrsModified = {
|
||||
/**
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString | Partial<{
|
||||
[K in keyof CSSStyleDeclaration]: Signal<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.
|
||||
*/
|
||||
classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>;
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap)
|
||||
* */
|
||||
dataset: Record<string, ddeStringable>;
|
||||
/**
|
||||
* Sets `aria-*` simiraly to `dataset`
|
||||
* */
|
||||
ariaset: Record<string, ddeString>;
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>;
|
||||
export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>;
|
||||
export type IsReadonly<T, K extends keyof T> = T extends {
|
||||
readonly [P in K]: T[K];
|
||||
} ? true : false;
|
||||
/**
|
||||
* 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)).
|
||||
*
|
||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||
* @private
|
||||
*/
|
||||
export type ElementAttributes<T extends SupportedElement> = Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable);
|
||||
} & 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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT];
|
||||
export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(attrs: {
|
||||
type: "component" | "reactive" | "later";
|
||||
name?: string;
|
||||
host?: "this" | "parentElement";
|
||||
}, is_open?: boolean): Comment;
|
||||
}
|
||||
export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<A extends {
|
||||
textContent: ddeStringable;
|
||||
}, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement;
|
||||
export function el(tag_name?: "<>"): ddeDocumentFragment;
|
||||
export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement;
|
||||
export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement;
|
||||
export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean;
|
||||
}>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement;
|
||||
export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement;
|
||||
export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
||||
/** Simulate slots for ddeComponents */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL;
|
||||
/**
|
||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||
* @param el Custom Element root element
|
||||
* @param body Body of the custom element
|
||||
* */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, element: SupportedElement): (data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, element: SupportedElement | (() => SupportedElement)): (data?: any) => void;
|
||||
export interface On {
|
||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||
<Event extends keyof DocumentEventMap, EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: Event, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any, options?: AddEventListenerOptions): EE;
|
||||
<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
connected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<El>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
disconnected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
attributeChanged<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<[
|
||||
string,
|
||||
string
|
||||
]>) => any, options?: AddEventListenerOptions): EE;
|
||||
}
|
||||
export const on: On;
|
||||
export 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}) */
|
||||
export const scope: {
|
||||
current: Scope;
|
||||
/** Stops all automatizations. E. g. signals used as attributes in current scope
|
||||
* registers removing these listeners (and clean signal if no other listeners are detected)
|
||||
* on `disconnected` event. */
|
||||
preventDefault<T extends boolean>(prevent: T): T;
|
||||
/**
|
||||
* This represents reference to the current host element — `scope.host()`.
|
||||
* It can be also used to register Addon(s) (functions to be called when component is initized)
|
||||
* — `scope.host(on.connected(console.log))`.
|
||||
* */
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||
state: Scope[];
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>;
|
||||
/** Removes last/current child scope. */
|
||||
pop(): ReturnType<Array<Scope>["pop"]>;
|
||||
};
|
||||
export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL;
|
||||
export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>;
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
/* TypeScript MEH */
|
||||
declare global {
|
||||
type ddeAppend<el> = (...nodes: (Node | string)[]) => el;
|
||||
interface ddeDocumentFragment extends DocumentFragment {
|
||||
append: ddeAppend<ddeDocumentFragment>;
|
||||
}
|
||||
interface ddeHTMLElement extends HTMLElement {
|
||||
append: ddeAppend<ddeHTMLElement>;
|
||||
}
|
||||
interface ddeSVGElement extends SVGElement {
|
||||
append: ddeAppend<ddeSVGElement>;
|
||||
}
|
||||
interface ddeMathMLElement extends MathMLElement {
|
||||
append: ddeAppend<ddeMathMLElement>;
|
||||
}
|
||||
interface ddeHTMLElementTagNameMap {
|
||||
"a": ddeHTMLAnchorElement;
|
||||
"area": ddeHTMLAreaElement;
|
||||
"audio": ddeHTMLAudioElement;
|
||||
"base": ddeHTMLBaseElement;
|
||||
"blockquote": ddeHTMLQuoteElement;
|
||||
"body": ddeHTMLBodyElement;
|
||||
"br": ddeHTMLBRElement;
|
||||
"button": ddeHTMLButtonElement;
|
||||
"canvas": ddeHTMLCanvasElement;
|
||||
"caption": ddeHTMLTableCaptionElement;
|
||||
"col": ddeHTMLTableColElement;
|
||||
"colgroup": ddeHTMLTableColElement;
|
||||
"data": ddeHTMLDataElement;
|
||||
"datalist": ddeHTMLDataListElement;
|
||||
"del": ddeHTMLModElement;
|
||||
"details": ddeHTMLDetailsElement;
|
||||
"dialog": ddeHTMLDialogElement;
|
||||
"div": ddeHTMLDivElement;
|
||||
"dl": ddeHTMLDListElement;
|
||||
"embed": ddeHTMLEmbedElement;
|
||||
"fieldset": ddeHTMLFieldSetElement;
|
||||
"form": ddeHTMLFormElement;
|
||||
"h1": ddeHTMLHeadingElement;
|
||||
"h2": ddeHTMLHeadingElement;
|
||||
"h3": ddeHTMLHeadingElement;
|
||||
"h4": ddeHTMLHeadingElement;
|
||||
"h5": ddeHTMLHeadingElement;
|
||||
"h6": ddeHTMLHeadingElement;
|
||||
"head": ddeHTMLHeadElement;
|
||||
"hr": ddeHTMLHRElement;
|
||||
"html": ddeHTMLHtmlElement;
|
||||
"iframe": ddeHTMLIFrameElement;
|
||||
"img": ddeHTMLImageElement;
|
||||
"input": ddeHTMLInputElement;
|
||||
"ins": ddeHTMLModElement;
|
||||
"label": ddeHTMLLabelElement;
|
||||
"legend": ddeHTMLLegendElement;
|
||||
"li": ddeHTMLLIElement;
|
||||
"link": ddeHTMLLinkElement;
|
||||
"map": ddeHTMLMapElement;
|
||||
"menu": ddeHTMLMenuElement;
|
||||
"meta": ddeHTMLMetaElement;
|
||||
"meter": ddeHTMLMeterElement;
|
||||
"object": ddeHTMLObjectElement;
|
||||
"ol": ddeHTMLOListElement;
|
||||
"optgroup": ddeHTMLOptGroupElement;
|
||||
"option": ddeHTMLOptionElement;
|
||||
"output": ddeHTMLOutputElement;
|
||||
"p": ddeHTMLParagraphElement;
|
||||
"picture": ddeHTMLPictureElement;
|
||||
"pre": ddeHTMLPreElement;
|
||||
"progress": ddeHTMLProgressElement;
|
||||
"q": ddeHTMLQuoteElement;
|
||||
"script": ddeHTMLScriptElement;
|
||||
"select": ddeHTMLSelectElement;
|
||||
"slot": ddeHTMLSlotElement;
|
||||
"source": ddeHTMLSourceElement;
|
||||
"span": ddeHTMLSpanElement;
|
||||
"style": ddeHTMLStyleElement;
|
||||
"table": ddeHTMLTableElement;
|
||||
"tbody": ddeHTMLTableSectionElement;
|
||||
"td": ddeHTMLTableCellElement;
|
||||
"template": ddeHTMLTemplateElement;
|
||||
"textarea": ddeHTMLTextAreaElement;
|
||||
"tfoot": ddeHTMLTableSectionElement;
|
||||
"th": ddeHTMLTableCellElement;
|
||||
"thead": ddeHTMLTableSectionElement;
|
||||
"time": ddeHTMLTimeElement;
|
||||
"title": ddeHTMLTitleElement;
|
||||
"tr": ddeHTMLTableRowElement;
|
||||
"track": ddeHTMLTrackElement;
|
||||
"ul": ddeHTMLUListElement;
|
||||
"video": ddeHTMLVideoElement;
|
||||
}
|
||||
interface ddeSVGElementTagNameMap {
|
||||
"a": ddeSVGAElement;
|
||||
"animate": ddeSVGAnimateElement;
|
||||
"animateMotion": ddeSVGAnimateMotionElement;
|
||||
"animateTransform": ddeSVGAnimateTransformElement;
|
||||
"circle": ddeSVGCircleElement;
|
||||
"clipPath": ddeSVGClipPathElement;
|
||||
"defs": ddeSVGDefsElement;
|
||||
"desc": ddeSVGDescElement;
|
||||
"ellipse": ddeSVGEllipseElement;
|
||||
"feBlend": ddeSVGFEBlendElement;
|
||||
"feColorMatrix": ddeSVGFEColorMatrixElement;
|
||||
"feComponentTransfer": ddeSVGFEComponentTransferElement;
|
||||
"feComposite": ddeSVGFECompositeElement;
|
||||
"feConvolveMatrix": ddeSVGFEConvolveMatrixElement;
|
||||
"feDiffuseLighting": ddeSVGFEDiffuseLightingElement;
|
||||
"feDisplacementMap": ddeSVGFEDisplacementMapElement;
|
||||
"feDistantLight": ddeSVGFEDistantLightElement;
|
||||
"feDropShadow": ddeSVGFEDropShadowElement;
|
||||
"feFlood": ddeSVGFEFloodElement;
|
||||
"feFuncA": ddeSVGFEFuncAElement;
|
||||
"feFuncB": ddeSVGFEFuncBElement;
|
||||
"feFuncG": ddeSVGFEFuncGElement;
|
||||
"feFuncR": ddeSVGFEFuncRElement;
|
||||
"feGaussianBlur": ddeSVGFEGaussianBlurElement;
|
||||
"feImage": ddeSVGFEImageElement;
|
||||
"feMerge": ddeSVGFEMergeElement;
|
||||
"feMergeNode": ddeSVGFEMergeNodeElement;
|
||||
"feMorphology": ddeSVGFEMorphologyElement;
|
||||
"feOffset": ddeSVGFEOffsetElement;
|
||||
"fePointLight": ddeSVGFEPointLightElement;
|
||||
"feSpecularLighting": ddeSVGFESpecularLightingElement;
|
||||
"feSpotLight": ddeSVGFESpotLightElement;
|
||||
"feTile": ddeSVGFETileElement;
|
||||
"feTurbulence": ddeSVGFETurbulenceElement;
|
||||
"filter": ddeSVGFilterElement;
|
||||
"foreignObject": ddeSVGForeignObjectElement;
|
||||
"g": ddeSVGGElement;
|
||||
"image": ddeSVGImageElement;
|
||||
"line": ddeSVGLineElement;
|
||||
"linearGradient": ddeSVGLinearGradientElement;
|
||||
"marker": ddeSVGMarkerElement;
|
||||
"mask": ddeSVGMaskElement;
|
||||
"metadata": ddeSVGMetadataElement;
|
||||
"mpath": ddeSVGMPathElement;
|
||||
"path": ddeSVGPathElement;
|
||||
"pattern": ddeSVGPatternElement;
|
||||
"polygon": ddeSVGPolygonElement;
|
||||
"polyline": ddeSVGPolylineElement;
|
||||
"radialGradient": ddeSVGRadialGradientElement;
|
||||
"rect": ddeSVGRectElement;
|
||||
"script": ddeSVGScriptElement;
|
||||
"set": ddeSVGSetElement;
|
||||
"stop": ddeSVGStopElement;
|
||||
"style": ddeSVGStyleElement;
|
||||
"svg": ddeSVGSVGElement;
|
||||
"switch": ddeSVGSwitchElement;
|
||||
"symbol": ddeSVGSymbolElement;
|
||||
"text": ddeSVGTextElement;
|
||||
"textPath": ddeSVGTextPathElement;
|
||||
"title": ddeSVGTitleElement;
|
||||
"tspan": ddeSVGTSpanElement;
|
||||
"use": ddeSVGUseElement;
|
||||
"view": ddeSVGViewElement;
|
||||
}
|
||||
}
|
||||
// editorconfig-checker-disable
|
||||
export interface ddeHTMLAnchorElement extends HTMLAnchorElement {
|
||||
append: ddeAppend<ddeHTMLAnchorElement>;
|
||||
}
|
||||
export interface ddeHTMLAreaElement extends HTMLAreaElement {
|
||||
append: ddeAppend<ddeHTMLAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLAudioElement extends HTMLAudioElement {
|
||||
append: ddeAppend<ddeHTMLAudioElement>;
|
||||
}
|
||||
export interface ddeHTMLBaseElement extends HTMLBaseElement {
|
||||
append: ddeAppend<ddeHTMLBaseElement>;
|
||||
}
|
||||
export interface ddeHTMLQuoteElement extends HTMLQuoteElement {
|
||||
append: ddeAppend<ddeHTMLQuoteElement>;
|
||||
}
|
||||
export interface ddeHTMLBodyElement extends HTMLBodyElement {
|
||||
append: ddeAppend<ddeHTMLBodyElement>;
|
||||
}
|
||||
export interface ddeHTMLBRElement extends HTMLBRElement {
|
||||
append: ddeAppend<ddeHTMLBRElement>;
|
||||
}
|
||||
export interface ddeHTMLButtonElement extends HTMLButtonElement {
|
||||
append: ddeAppend<ddeHTMLButtonElement>;
|
||||
}
|
||||
export interface ddeHTMLCanvasElement extends HTMLCanvasElement {
|
||||
append: ddeAppend<ddeHTMLCanvasElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement {
|
||||
append: ddeAppend<ddeHTMLTableCaptionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLDataElement extends HTMLDataElement {
|
||||
append: ddeAppend<ddeHTMLDataElement>;
|
||||
}
|
||||
export interface ddeHTMLDataListElement extends HTMLDataListElement {
|
||||
append: ddeAppend<ddeHTMLDataListElement>;
|
||||
}
|
||||
export interface ddeHTMLModElement extends HTMLModElement {
|
||||
append: ddeAppend<ddeHTMLModElement>;
|
||||
}
|
||||
export interface ddeHTMLDetailsElement extends HTMLDetailsElement {
|
||||
append: ddeAppend<ddeHTMLDetailsElement>;
|
||||
}
|
||||
export interface ddeHTMLDialogElement extends HTMLDialogElement {
|
||||
append: ddeAppend<ddeHTMLDialogElement>;
|
||||
}
|
||||
export interface ddeHTMLDivElement extends HTMLDivElement {
|
||||
append: ddeAppend<ddeHTMLDivElement>;
|
||||
}
|
||||
export interface ddeHTMLDListElement extends HTMLDListElement {
|
||||
append: ddeAppend<ddeHTMLDListElement>;
|
||||
}
|
||||
export interface ddeHTMLEmbedElement extends HTMLEmbedElement {
|
||||
append: ddeAppend<ddeHTMLEmbedElement>;
|
||||
}
|
||||
export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement {
|
||||
append: ddeAppend<ddeHTMLFieldSetElement>;
|
||||
}
|
||||
export interface ddeHTMLFormElement extends HTMLFormElement {
|
||||
append: ddeAppend<ddeHTMLFormElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadingElement extends HTMLHeadingElement {
|
||||
append: ddeAppend<ddeHTMLHeadingElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadElement extends HTMLHeadElement {
|
||||
append: ddeAppend<ddeHTMLHeadElement>;
|
||||
}
|
||||
export interface ddeHTMLHRElement extends HTMLHRElement {
|
||||
append: ddeAppend<ddeHTMLHRElement>;
|
||||
}
|
||||
export interface ddeHTMLHtmlElement extends HTMLHtmlElement {
|
||||
append: ddeAppend<ddeHTMLHtmlElement>;
|
||||
}
|
||||
export interface ddeHTMLIFrameElement extends HTMLIFrameElement {
|
||||
append: ddeAppend<ddeHTMLIFrameElement>;
|
||||
}
|
||||
export interface ddeHTMLImageElement extends HTMLImageElement {
|
||||
append: ddeAppend<ddeHTMLImageElement>;
|
||||
}
|
||||
export interface ddeHTMLInputElement extends HTMLInputElement {
|
||||
append: ddeAppend<ddeHTMLInputElement>;
|
||||
}
|
||||
export interface ddeHTMLLabelElement extends HTMLLabelElement {
|
||||
append: ddeAppend<ddeHTMLLabelElement>;
|
||||
}
|
||||
export interface ddeHTMLLegendElement extends HTMLLegendElement {
|
||||
append: ddeAppend<ddeHTMLLegendElement>;
|
||||
}
|
||||
export interface ddeHTMLLIElement extends HTMLLIElement {
|
||||
append: ddeAppend<ddeHTMLLIElement>;
|
||||
}
|
||||
export interface ddeHTMLLinkElement extends HTMLLinkElement {
|
||||
append: ddeAppend<ddeHTMLLinkElement>;
|
||||
}
|
||||
export interface ddeHTMLMapElement extends HTMLMapElement {
|
||||
append: ddeAppend<ddeHTMLMapElement>;
|
||||
}
|
||||
export interface ddeHTMLMenuElement extends HTMLMenuElement {
|
||||
append: ddeAppend<ddeHTMLMenuElement>;
|
||||
}
|
||||
export interface ddeHTMLMetaElement extends HTMLMetaElement {
|
||||
append: ddeAppend<ddeHTMLMetaElement>;
|
||||
}
|
||||
export interface ddeHTMLMeterElement extends HTMLMeterElement {
|
||||
append: ddeAppend<ddeHTMLMeterElement>;
|
||||
}
|
||||
export interface ddeHTMLObjectElement extends HTMLObjectElement {
|
||||
append: ddeAppend<ddeHTMLObjectElement>;
|
||||
}
|
||||
export interface ddeHTMLOListElement extends HTMLOListElement {
|
||||
append: ddeAppend<ddeHTMLOListElement>;
|
||||
}
|
||||
export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement {
|
||||
append: ddeAppend<ddeHTMLOptGroupElement>;
|
||||
}
|
||||
export interface ddeHTMLOptionElement extends HTMLOptionElement {
|
||||
append: ddeAppend<ddeHTMLOptionElement>;
|
||||
}
|
||||
export interface ddeHTMLOutputElement extends HTMLOutputElement {
|
||||
append: ddeAppend<ddeHTMLOutputElement>;
|
||||
}
|
||||
export interface ddeHTMLParagraphElement extends HTMLParagraphElement {
|
||||
append: ddeAppend<ddeHTMLParagraphElement>;
|
||||
}
|
||||
export interface ddeHTMLPictureElement extends HTMLPictureElement {
|
||||
append: ddeAppend<ddeHTMLPictureElement>;
|
||||
}
|
||||
export interface ddeHTMLPreElement extends HTMLPreElement {
|
||||
append: ddeAppend<ddeHTMLPreElement>;
|
||||
}
|
||||
export interface ddeHTMLProgressElement extends HTMLProgressElement {
|
||||
append: ddeAppend<ddeHTMLProgressElement>;
|
||||
}
|
||||
export interface ddeHTMLScriptElement extends HTMLScriptElement {
|
||||
append: ddeAppend<ddeHTMLScriptElement>;
|
||||
}
|
||||
export interface ddeHTMLSelectElement extends HTMLSelectElement {
|
||||
append: ddeAppend<ddeHTMLSelectElement>;
|
||||
}
|
||||
export interface ddeHTMLSlotElement extends HTMLSlotElement {
|
||||
append: ddeAppend<ddeHTMLSlotElement>;
|
||||
}
|
||||
export interface ddeHTMLSourceElement extends HTMLSourceElement {
|
||||
append: ddeAppend<ddeHTMLSourceElement>;
|
||||
}
|
||||
export interface ddeHTMLSpanElement extends HTMLSpanElement {
|
||||
append: ddeAppend<ddeHTMLSpanElement>;
|
||||
}
|
||||
export interface ddeHTMLStyleElement extends HTMLStyleElement {
|
||||
append: ddeAppend<ddeHTMLStyleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableElement extends HTMLTableElement {
|
||||
append: ddeAppend<ddeHTMLTableElement>;
|
||||
}
|
||||
export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement {
|
||||
append: ddeAppend<ddeHTMLTableSectionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTemplateElement extends HTMLTemplateElement {
|
||||
append: ddeAppend<ddeHTMLTemplateElement>;
|
||||
}
|
||||
export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement {
|
||||
append: ddeAppend<ddeHTMLTextAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTimeElement extends HTMLTimeElement {
|
||||
append: ddeAppend<ddeHTMLTimeElement>;
|
||||
}
|
||||
export interface ddeHTMLTitleElement extends HTMLTitleElement {
|
||||
append: ddeAppend<ddeHTMLTitleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableRowElement extends HTMLTableRowElement {
|
||||
append: ddeAppend<ddeHTMLTableRowElement>;
|
||||
}
|
||||
export interface ddeHTMLTrackElement extends HTMLTrackElement {
|
||||
append: ddeAppend<ddeHTMLTrackElement>;
|
||||
}
|
||||
export interface ddeHTMLUListElement extends HTMLUListElement {
|
||||
append: ddeAppend<ddeHTMLUListElement>;
|
||||
}
|
||||
export interface ddeHTMLVideoElement extends HTMLVideoElement {
|
||||
append: ddeAppend<ddeHTMLVideoElement>;
|
||||
}
|
||||
export interface ddeSVGAElement extends SVGAElement {
|
||||
append: ddeAppend<ddeSVGAElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateElement extends SVGAnimateElement {
|
||||
append: ddeAppend<ddeSVGAnimateElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement {
|
||||
append: ddeAppend<ddeSVGAnimateMotionElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement {
|
||||
append: ddeAppend<ddeSVGAnimateTransformElement>;
|
||||
}
|
||||
export interface ddeSVGCircleElement extends SVGCircleElement {
|
||||
append: ddeAppend<ddeSVGCircleElement>;
|
||||
}
|
||||
export interface ddeSVGClipPathElement extends SVGClipPathElement {
|
||||
append: ddeAppend<ddeSVGClipPathElement>;
|
||||
}
|
||||
export interface ddeSVGDefsElement extends SVGDefsElement {
|
||||
append: ddeAppend<ddeSVGDefsElement>;
|
||||
}
|
||||
export interface ddeSVGDescElement extends SVGDescElement {
|
||||
append: ddeAppend<ddeSVGDescElement>;
|
||||
}
|
||||
export interface ddeSVGEllipseElement extends SVGEllipseElement {
|
||||
append: ddeAppend<ddeSVGEllipseElement>;
|
||||
}
|
||||
export interface ddeSVGFEBlendElement extends SVGFEBlendElement {
|
||||
append: ddeAppend<ddeSVGFEBlendElement>;
|
||||
}
|
||||
export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEColorMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement {
|
||||
append: ddeAppend<ddeSVGFEComponentTransferElement>;
|
||||
}
|
||||
export interface ddeSVGFECompositeElement extends SVGFECompositeElement {
|
||||
append: ddeAppend<ddeSVGFECompositeElement>;
|
||||
}
|
||||
export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEConvolveMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement {
|
||||
append: ddeAppend<ddeSVGFEDiffuseLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement {
|
||||
append: ddeAppend<ddeSVGFEDisplacementMapElement>;
|
||||
}
|
||||
export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement {
|
||||
append: ddeAppend<ddeSVGFEDistantLightElement>;
|
||||
}
|
||||
export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement {
|
||||
append: ddeAppend<ddeSVGFEDropShadowElement>;
|
||||
}
|
||||
export interface ddeSVGFEFloodElement extends SVGFEFloodElement {
|
||||
append: ddeAppend<ddeSVGFEFloodElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement {
|
||||
append: ddeAppend<ddeSVGFEFuncAElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement {
|
||||
append: ddeAppend<ddeSVGFEFuncBElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement {
|
||||
append: ddeAppend<ddeSVGFEFuncGElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement {
|
||||
append: ddeAppend<ddeSVGFEFuncRElement>;
|
||||
}
|
||||
export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement {
|
||||
append: ddeAppend<ddeSVGFEGaussianBlurElement>;
|
||||
}
|
||||
export interface ddeSVGFEImageElement extends SVGFEImageElement {
|
||||
append: ddeAppend<ddeSVGFEImageElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeElement extends SVGFEMergeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeNodeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement {
|
||||
append: ddeAppend<ddeSVGFEMorphologyElement>;
|
||||
}
|
||||
export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement {
|
||||
append: ddeAppend<ddeSVGFEOffsetElement>;
|
||||
}
|
||||
export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement {
|
||||
append: ddeAppend<ddeSVGFEPointLightElement>;
|
||||
}
|
||||
export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement {
|
||||
append: ddeAppend<ddeSVGFESpecularLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement {
|
||||
append: ddeAppend<ddeSVGFESpotLightElement>;
|
||||
}
|
||||
export interface ddeSVGFETileElement extends SVGFETileElement {
|
||||
append: ddeAppend<ddeSVGFETileElement>;
|
||||
}
|
||||
export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement {
|
||||
append: ddeAppend<ddeSVGFETurbulenceElement>;
|
||||
}
|
||||
export interface ddeSVGFilterElement extends SVGFilterElement {
|
||||
append: ddeAppend<ddeSVGFilterElement>;
|
||||
}
|
||||
export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement {
|
||||
append: ddeAppend<ddeSVGForeignObjectElement>;
|
||||
}
|
||||
export interface ddeSVGGElement extends SVGGElement {
|
||||
append: ddeAppend<ddeSVGGElement>;
|
||||
}
|
||||
export interface ddeSVGImageElement extends SVGImageElement {
|
||||
append: ddeAppend<ddeSVGImageElement>;
|
||||
}
|
||||
export interface ddeSVGLineElement extends SVGLineElement {
|
||||
append: ddeAppend<ddeSVGLineElement>;
|
||||
}
|
||||
export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement {
|
||||
append: ddeAppend<ddeSVGLinearGradientElement>;
|
||||
}
|
||||
export interface ddeSVGMarkerElement extends SVGMarkerElement {
|
||||
append: ddeAppend<ddeSVGMarkerElement>;
|
||||
}
|
||||
export interface ddeSVGMaskElement extends SVGMaskElement {
|
||||
append: ddeAppend<ddeSVGMaskElement>;
|
||||
}
|
||||
export interface ddeSVGMetadataElement extends SVGMetadataElement {
|
||||
append: ddeAppend<ddeSVGMetadataElement>;
|
||||
}
|
||||
export interface ddeSVGMPathElement extends SVGMPathElement {
|
||||
append: ddeAppend<ddeSVGMPathElement>;
|
||||
}
|
||||
export interface ddeSVGPathElement extends SVGPathElement {
|
||||
append: ddeAppend<ddeSVGPathElement>;
|
||||
}
|
||||
export interface ddeSVGPatternElement extends SVGPatternElement {
|
||||
append: ddeAppend<ddeSVGPatternElement>;
|
||||
}
|
||||
export interface ddeSVGPolygonElement extends SVGPolygonElement {
|
||||
append: ddeAppend<ddeSVGPolygonElement>;
|
||||
}
|
||||
export interface ddeSVGPolylineElement extends SVGPolylineElement {
|
||||
append: ddeAppend<ddeSVGPolylineElement>;
|
||||
}
|
||||
export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement {
|
||||
append: ddeAppend<ddeSVGRadialGradientElement>;
|
||||
}
|
||||
export interface ddeSVGRectElement extends SVGRectElement {
|
||||
append: ddeAppend<ddeSVGRectElement>;
|
||||
}
|
||||
export interface ddeSVGScriptElement extends SVGScriptElement {
|
||||
append: ddeAppend<ddeSVGScriptElement>;
|
||||
}
|
||||
export interface ddeSVGSetElement extends SVGSetElement {
|
||||
append: ddeAppend<ddeSVGSetElement>;
|
||||
}
|
||||
export interface ddeSVGStopElement extends SVGStopElement {
|
||||
append: ddeAppend<ddeSVGStopElement>;
|
||||
}
|
||||
export interface ddeSVGStyleElement extends SVGStyleElement {
|
||||
append: ddeAppend<ddeSVGStyleElement>;
|
||||
}
|
||||
export interface ddeSVGSVGElement extends SVGSVGElement {
|
||||
append: ddeAppend<ddeSVGSVGElement>;
|
||||
}
|
||||
export interface ddeSVGSwitchElement extends SVGSwitchElement {
|
||||
append: ddeAppend<ddeSVGSwitchElement>;
|
||||
}
|
||||
export interface ddeSVGSymbolElement extends SVGSymbolElement {
|
||||
append: ddeAppend<ddeSVGSymbolElement>;
|
||||
}
|
||||
export interface ddeSVGTextElement extends SVGTextElement {
|
||||
append: ddeAppend<ddeSVGTextElement>;
|
||||
}
|
||||
export interface ddeSVGTextPathElement extends SVGTextPathElement {
|
||||
append: ddeAppend<ddeSVGTextPathElement>;
|
||||
}
|
||||
export interface ddeSVGTitleElement extends SVGTitleElement {
|
||||
append: ddeAppend<ddeSVGTitleElement>;
|
||||
}
|
||||
export interface ddeSVGTSpanElement extends SVGTSpanElement {
|
||||
append: ddeAppend<ddeSVGTSpanElement>;
|
||||
}
|
||||
export interface ddeSVGUseElement extends SVGUseElement {
|
||||
append: ddeAppend<ddeSVGUseElement>;
|
||||
}
|
||||
export interface ddeSVGViewElement extends SVGViewElement {
|
||||
append: ddeAppend<ddeSVGViewElement>;
|
||||
}
|
||||
|
||||
export {
|
||||
dispatchEvent$1 as dispatchEvent,
|
||||
el as createElement,
|
||||
elNS as createElementNS,
|
||||
};
|
||||
|
||||
export as namespace dde;
|
||||
|
||||
export {};
|
1104
dist/dde.js
vendored
1104
dist/dde.js
vendored
File diff suppressed because it is too large
Load Diff
784
dist/dde.min.d.ts
vendored
Normal file
784
dist/dde.min.d.ts
vendored
Normal file
@ -0,0 +1,784 @@
|
||||
// Generated by dts-bundle-generator v9.5.1
|
||||
|
||||
export interface Signal<V, A> {
|
||||
/** The current value of the signal */
|
||||
get(): V;
|
||||
/** Set new value of the signal */
|
||||
set(value: V): V;
|
||||
toJSON(): V;
|
||||
valueOf(): V;
|
||||
}
|
||||
export type Action<V> = (this: {
|
||||
value: V;
|
||||
stopPropagation(): void;
|
||||
}, ...a: any[]) => typeof signal._ | void;
|
||||
//type SymbolSignal= Symbol;
|
||||
export type SymbolOnclear = symbol;
|
||||
export type Actions<V> = Record<string | SymbolOnclear, Action<V>>;
|
||||
export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & {
|
||||
first_time?: boolean;
|
||||
};
|
||||
export interface signal {
|
||||
_: Symbol;
|
||||
/**
|
||||
* Computations signal. This creates a signal which is computed from other signals.
|
||||
* */
|
||||
<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>;
|
||||
/**
|
||||
* Simple example:
|
||||
* ```js
|
||||
* const hello= S("Hello Signal");
|
||||
* ```
|
||||
* …simple todo signal:
|
||||
* ```js
|
||||
* const todos= S([], {
|
||||
* add(v){ this.value.push(S(v)); },
|
||||
* remove(i){ this.value.splice(i, 1); },
|
||||
* [S.symbols.onclear](){ S.clear(...this.value); },
|
||||
* });
|
||||
* ```
|
||||
* …computed signal:
|
||||
* ```js
|
||||
* const name= S("Jan");
|
||||
* const surname= S("Andrle");
|
||||
* const fullname= S(()=> name.get()+" "+surname.get());
|
||||
* ```
|
||||
* @param value Initial signal value. Or function computing value from other signals.
|
||||
* @param actions Use to define actions on the signal. Such as add item to the array.
|
||||
* There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared
|
||||
* by `S.clear`.
|
||||
* */
|
||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void;
|
||||
clear(...signals: Signal<any, any>[]): void;
|
||||
on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void;
|
||||
symbols: {
|
||||
//signal: SymbolSignal;
|
||||
onclear: SymbolOnclear;
|
||||
};
|
||||
/**
|
||||
* Reactive element, which is rendered based on the given signal.
|
||||
* ```js
|
||||
* S.el(signal, value=> value ? el("b", "True") : el("i", "False"));
|
||||
* S.el(listS, list=> list.map(li=> el("li", li)));
|
||||
* ```
|
||||
* */
|
||||
el<S extends any>(signal: Signal<S, any>, el: (v: S) => Element | Element[] | DocumentFragment): DocumentFragment;
|
||||
observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>;
|
||||
}
|
||||
declare const signal: signal;
|
||||
declare global {
|
||||
type ddeSignal<T, A = {}> = Signal<T, A>;
|
||||
type ddeAction<V> = Action<V>;
|
||||
type ddeActions<V> = Actions<V>;
|
||||
}
|
||||
export type CustomElementTagNameMap = {
|
||||
"#text": Text;
|
||||
"#comment": Comment;
|
||||
};
|
||||
export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
||||
declare global {
|
||||
type ddeComponentAttributes = Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El) => any;
|
||||
type ddeString = string | Signal<string, {}>;
|
||||
type ddeStringable = ddeString | number | Signal<number, {}>;
|
||||
}
|
||||
export type PascalCase = `${Capitalize<string>}${string}`;
|
||||
export type AttrsModified = {
|
||||
/**
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString | Partial<{
|
||||
[K in keyof CSSStyleDeclaration]: Signal<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.
|
||||
*/
|
||||
classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>;
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap)
|
||||
* */
|
||||
dataset: Record<string, ddeStringable>;
|
||||
/**
|
||||
* Sets `aria-*` simiraly to `dataset`
|
||||
* */
|
||||
ariaset: Record<string, ddeString>;
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>;
|
||||
export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>;
|
||||
export type IsReadonly<T, K extends keyof T> = T extends {
|
||||
readonly [P in K]: T[K];
|
||||
} ? true : false;
|
||||
/**
|
||||
* 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)).
|
||||
*
|
||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||
* @private
|
||||
*/
|
||||
export type ElementAttributes<T extends SupportedElement> = Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable);
|
||||
} & 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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT];
|
||||
export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(attrs: {
|
||||
type: "component" | "reactive" | "later";
|
||||
name?: string;
|
||||
host?: "this" | "parentElement";
|
||||
}, is_open?: boolean): Comment;
|
||||
}
|
||||
export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<A extends {
|
||||
textContent: ddeStringable;
|
||||
}, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement;
|
||||
export function el(tag_name?: "<>"): ddeDocumentFragment;
|
||||
export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement;
|
||||
export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement;
|
||||
export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean;
|
||||
}>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement;
|
||||
export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement;
|
||||
export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
||||
/** Simulate slots for ddeComponents */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL;
|
||||
/**
|
||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||
* @param el Custom Element root element
|
||||
* @param body Body of the custom element
|
||||
* */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, element: SupportedElement): (data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, element: SupportedElement | (() => SupportedElement)): (data?: any) => void;
|
||||
export interface On {
|
||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||
<Event extends keyof DocumentEventMap, EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: Event, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any, options?: AddEventListenerOptions): EE;
|
||||
<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
connected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<El>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
disconnected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
attributeChanged<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<[
|
||||
string,
|
||||
string
|
||||
]>) => any, options?: AddEventListenerOptions): EE;
|
||||
}
|
||||
export const on: On;
|
||||
export 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}) */
|
||||
export const scope: {
|
||||
current: Scope;
|
||||
/** Stops all automatizations. E. g. signals used as attributes in current scope
|
||||
* registers removing these listeners (and clean signal if no other listeners are detected)
|
||||
* on `disconnected` event. */
|
||||
preventDefault<T extends boolean>(prevent: T): T;
|
||||
/**
|
||||
* This represents reference to the current host element — `scope.host()`.
|
||||
* It can be also used to register Addon(s) (functions to be called when component is initized)
|
||||
* — `scope.host(on.connected(console.log))`.
|
||||
* */
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||
state: Scope[];
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>;
|
||||
/** Removes last/current child scope. */
|
||||
pop(): ReturnType<Array<Scope>["pop"]>;
|
||||
};
|
||||
export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL;
|
||||
export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>;
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
/* TypeScript MEH */
|
||||
declare global {
|
||||
type ddeAppend<el> = (...nodes: (Node | string)[]) => el;
|
||||
interface ddeDocumentFragment extends DocumentFragment {
|
||||
append: ddeAppend<ddeDocumentFragment>;
|
||||
}
|
||||
interface ddeHTMLElement extends HTMLElement {
|
||||
append: ddeAppend<ddeHTMLElement>;
|
||||
}
|
||||
interface ddeSVGElement extends SVGElement {
|
||||
append: ddeAppend<ddeSVGElement>;
|
||||
}
|
||||
interface ddeMathMLElement extends MathMLElement {
|
||||
append: ddeAppend<ddeMathMLElement>;
|
||||
}
|
||||
interface ddeHTMLElementTagNameMap {
|
||||
"a": ddeHTMLAnchorElement;
|
||||
"area": ddeHTMLAreaElement;
|
||||
"audio": ddeHTMLAudioElement;
|
||||
"base": ddeHTMLBaseElement;
|
||||
"blockquote": ddeHTMLQuoteElement;
|
||||
"body": ddeHTMLBodyElement;
|
||||
"br": ddeHTMLBRElement;
|
||||
"button": ddeHTMLButtonElement;
|
||||
"canvas": ddeHTMLCanvasElement;
|
||||
"caption": ddeHTMLTableCaptionElement;
|
||||
"col": ddeHTMLTableColElement;
|
||||
"colgroup": ddeHTMLTableColElement;
|
||||
"data": ddeHTMLDataElement;
|
||||
"datalist": ddeHTMLDataListElement;
|
||||
"del": ddeHTMLModElement;
|
||||
"details": ddeHTMLDetailsElement;
|
||||
"dialog": ddeHTMLDialogElement;
|
||||
"div": ddeHTMLDivElement;
|
||||
"dl": ddeHTMLDListElement;
|
||||
"embed": ddeHTMLEmbedElement;
|
||||
"fieldset": ddeHTMLFieldSetElement;
|
||||
"form": ddeHTMLFormElement;
|
||||
"h1": ddeHTMLHeadingElement;
|
||||
"h2": ddeHTMLHeadingElement;
|
||||
"h3": ddeHTMLHeadingElement;
|
||||
"h4": ddeHTMLHeadingElement;
|
||||
"h5": ddeHTMLHeadingElement;
|
||||
"h6": ddeHTMLHeadingElement;
|
||||
"head": ddeHTMLHeadElement;
|
||||
"hr": ddeHTMLHRElement;
|
||||
"html": ddeHTMLHtmlElement;
|
||||
"iframe": ddeHTMLIFrameElement;
|
||||
"img": ddeHTMLImageElement;
|
||||
"input": ddeHTMLInputElement;
|
||||
"ins": ddeHTMLModElement;
|
||||
"label": ddeHTMLLabelElement;
|
||||
"legend": ddeHTMLLegendElement;
|
||||
"li": ddeHTMLLIElement;
|
||||
"link": ddeHTMLLinkElement;
|
||||
"map": ddeHTMLMapElement;
|
||||
"menu": ddeHTMLMenuElement;
|
||||
"meta": ddeHTMLMetaElement;
|
||||
"meter": ddeHTMLMeterElement;
|
||||
"object": ddeHTMLObjectElement;
|
||||
"ol": ddeHTMLOListElement;
|
||||
"optgroup": ddeHTMLOptGroupElement;
|
||||
"option": ddeHTMLOptionElement;
|
||||
"output": ddeHTMLOutputElement;
|
||||
"p": ddeHTMLParagraphElement;
|
||||
"picture": ddeHTMLPictureElement;
|
||||
"pre": ddeHTMLPreElement;
|
||||
"progress": ddeHTMLProgressElement;
|
||||
"q": ddeHTMLQuoteElement;
|
||||
"script": ddeHTMLScriptElement;
|
||||
"select": ddeHTMLSelectElement;
|
||||
"slot": ddeHTMLSlotElement;
|
||||
"source": ddeHTMLSourceElement;
|
||||
"span": ddeHTMLSpanElement;
|
||||
"style": ddeHTMLStyleElement;
|
||||
"table": ddeHTMLTableElement;
|
||||
"tbody": ddeHTMLTableSectionElement;
|
||||
"td": ddeHTMLTableCellElement;
|
||||
"template": ddeHTMLTemplateElement;
|
||||
"textarea": ddeHTMLTextAreaElement;
|
||||
"tfoot": ddeHTMLTableSectionElement;
|
||||
"th": ddeHTMLTableCellElement;
|
||||
"thead": ddeHTMLTableSectionElement;
|
||||
"time": ddeHTMLTimeElement;
|
||||
"title": ddeHTMLTitleElement;
|
||||
"tr": ddeHTMLTableRowElement;
|
||||
"track": ddeHTMLTrackElement;
|
||||
"ul": ddeHTMLUListElement;
|
||||
"video": ddeHTMLVideoElement;
|
||||
}
|
||||
interface ddeSVGElementTagNameMap {
|
||||
"a": ddeSVGAElement;
|
||||
"animate": ddeSVGAnimateElement;
|
||||
"animateMotion": ddeSVGAnimateMotionElement;
|
||||
"animateTransform": ddeSVGAnimateTransformElement;
|
||||
"circle": ddeSVGCircleElement;
|
||||
"clipPath": ddeSVGClipPathElement;
|
||||
"defs": ddeSVGDefsElement;
|
||||
"desc": ddeSVGDescElement;
|
||||
"ellipse": ddeSVGEllipseElement;
|
||||
"feBlend": ddeSVGFEBlendElement;
|
||||
"feColorMatrix": ddeSVGFEColorMatrixElement;
|
||||
"feComponentTransfer": ddeSVGFEComponentTransferElement;
|
||||
"feComposite": ddeSVGFECompositeElement;
|
||||
"feConvolveMatrix": ddeSVGFEConvolveMatrixElement;
|
||||
"feDiffuseLighting": ddeSVGFEDiffuseLightingElement;
|
||||
"feDisplacementMap": ddeSVGFEDisplacementMapElement;
|
||||
"feDistantLight": ddeSVGFEDistantLightElement;
|
||||
"feDropShadow": ddeSVGFEDropShadowElement;
|
||||
"feFlood": ddeSVGFEFloodElement;
|
||||
"feFuncA": ddeSVGFEFuncAElement;
|
||||
"feFuncB": ddeSVGFEFuncBElement;
|
||||
"feFuncG": ddeSVGFEFuncGElement;
|
||||
"feFuncR": ddeSVGFEFuncRElement;
|
||||
"feGaussianBlur": ddeSVGFEGaussianBlurElement;
|
||||
"feImage": ddeSVGFEImageElement;
|
||||
"feMerge": ddeSVGFEMergeElement;
|
||||
"feMergeNode": ddeSVGFEMergeNodeElement;
|
||||
"feMorphology": ddeSVGFEMorphologyElement;
|
||||
"feOffset": ddeSVGFEOffsetElement;
|
||||
"fePointLight": ddeSVGFEPointLightElement;
|
||||
"feSpecularLighting": ddeSVGFESpecularLightingElement;
|
||||
"feSpotLight": ddeSVGFESpotLightElement;
|
||||
"feTile": ddeSVGFETileElement;
|
||||
"feTurbulence": ddeSVGFETurbulenceElement;
|
||||
"filter": ddeSVGFilterElement;
|
||||
"foreignObject": ddeSVGForeignObjectElement;
|
||||
"g": ddeSVGGElement;
|
||||
"image": ddeSVGImageElement;
|
||||
"line": ddeSVGLineElement;
|
||||
"linearGradient": ddeSVGLinearGradientElement;
|
||||
"marker": ddeSVGMarkerElement;
|
||||
"mask": ddeSVGMaskElement;
|
||||
"metadata": ddeSVGMetadataElement;
|
||||
"mpath": ddeSVGMPathElement;
|
||||
"path": ddeSVGPathElement;
|
||||
"pattern": ddeSVGPatternElement;
|
||||
"polygon": ddeSVGPolygonElement;
|
||||
"polyline": ddeSVGPolylineElement;
|
||||
"radialGradient": ddeSVGRadialGradientElement;
|
||||
"rect": ddeSVGRectElement;
|
||||
"script": ddeSVGScriptElement;
|
||||
"set": ddeSVGSetElement;
|
||||
"stop": ddeSVGStopElement;
|
||||
"style": ddeSVGStyleElement;
|
||||
"svg": ddeSVGSVGElement;
|
||||
"switch": ddeSVGSwitchElement;
|
||||
"symbol": ddeSVGSymbolElement;
|
||||
"text": ddeSVGTextElement;
|
||||
"textPath": ddeSVGTextPathElement;
|
||||
"title": ddeSVGTitleElement;
|
||||
"tspan": ddeSVGTSpanElement;
|
||||
"use": ddeSVGUseElement;
|
||||
"view": ddeSVGViewElement;
|
||||
}
|
||||
}
|
||||
// editorconfig-checker-disable
|
||||
export interface ddeHTMLAnchorElement extends HTMLAnchorElement {
|
||||
append: ddeAppend<ddeHTMLAnchorElement>;
|
||||
}
|
||||
export interface ddeHTMLAreaElement extends HTMLAreaElement {
|
||||
append: ddeAppend<ddeHTMLAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLAudioElement extends HTMLAudioElement {
|
||||
append: ddeAppend<ddeHTMLAudioElement>;
|
||||
}
|
||||
export interface ddeHTMLBaseElement extends HTMLBaseElement {
|
||||
append: ddeAppend<ddeHTMLBaseElement>;
|
||||
}
|
||||
export interface ddeHTMLQuoteElement extends HTMLQuoteElement {
|
||||
append: ddeAppend<ddeHTMLQuoteElement>;
|
||||
}
|
||||
export interface ddeHTMLBodyElement extends HTMLBodyElement {
|
||||
append: ddeAppend<ddeHTMLBodyElement>;
|
||||
}
|
||||
export interface ddeHTMLBRElement extends HTMLBRElement {
|
||||
append: ddeAppend<ddeHTMLBRElement>;
|
||||
}
|
||||
export interface ddeHTMLButtonElement extends HTMLButtonElement {
|
||||
append: ddeAppend<ddeHTMLButtonElement>;
|
||||
}
|
||||
export interface ddeHTMLCanvasElement extends HTMLCanvasElement {
|
||||
append: ddeAppend<ddeHTMLCanvasElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement {
|
||||
append: ddeAppend<ddeHTMLTableCaptionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLDataElement extends HTMLDataElement {
|
||||
append: ddeAppend<ddeHTMLDataElement>;
|
||||
}
|
||||
export interface ddeHTMLDataListElement extends HTMLDataListElement {
|
||||
append: ddeAppend<ddeHTMLDataListElement>;
|
||||
}
|
||||
export interface ddeHTMLModElement extends HTMLModElement {
|
||||
append: ddeAppend<ddeHTMLModElement>;
|
||||
}
|
||||
export interface ddeHTMLDetailsElement extends HTMLDetailsElement {
|
||||
append: ddeAppend<ddeHTMLDetailsElement>;
|
||||
}
|
||||
export interface ddeHTMLDialogElement extends HTMLDialogElement {
|
||||
append: ddeAppend<ddeHTMLDialogElement>;
|
||||
}
|
||||
export interface ddeHTMLDivElement extends HTMLDivElement {
|
||||
append: ddeAppend<ddeHTMLDivElement>;
|
||||
}
|
||||
export interface ddeHTMLDListElement extends HTMLDListElement {
|
||||
append: ddeAppend<ddeHTMLDListElement>;
|
||||
}
|
||||
export interface ddeHTMLEmbedElement extends HTMLEmbedElement {
|
||||
append: ddeAppend<ddeHTMLEmbedElement>;
|
||||
}
|
||||
export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement {
|
||||
append: ddeAppend<ddeHTMLFieldSetElement>;
|
||||
}
|
||||
export interface ddeHTMLFormElement extends HTMLFormElement {
|
||||
append: ddeAppend<ddeHTMLFormElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadingElement extends HTMLHeadingElement {
|
||||
append: ddeAppend<ddeHTMLHeadingElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadElement extends HTMLHeadElement {
|
||||
append: ddeAppend<ddeHTMLHeadElement>;
|
||||
}
|
||||
export interface ddeHTMLHRElement extends HTMLHRElement {
|
||||
append: ddeAppend<ddeHTMLHRElement>;
|
||||
}
|
||||
export interface ddeHTMLHtmlElement extends HTMLHtmlElement {
|
||||
append: ddeAppend<ddeHTMLHtmlElement>;
|
||||
}
|
||||
export interface ddeHTMLIFrameElement extends HTMLIFrameElement {
|
||||
append: ddeAppend<ddeHTMLIFrameElement>;
|
||||
}
|
||||
export interface ddeHTMLImageElement extends HTMLImageElement {
|
||||
append: ddeAppend<ddeHTMLImageElement>;
|
||||
}
|
||||
export interface ddeHTMLInputElement extends HTMLInputElement {
|
||||
append: ddeAppend<ddeHTMLInputElement>;
|
||||
}
|
||||
export interface ddeHTMLLabelElement extends HTMLLabelElement {
|
||||
append: ddeAppend<ddeHTMLLabelElement>;
|
||||
}
|
||||
export interface ddeHTMLLegendElement extends HTMLLegendElement {
|
||||
append: ddeAppend<ddeHTMLLegendElement>;
|
||||
}
|
||||
export interface ddeHTMLLIElement extends HTMLLIElement {
|
||||
append: ddeAppend<ddeHTMLLIElement>;
|
||||
}
|
||||
export interface ddeHTMLLinkElement extends HTMLLinkElement {
|
||||
append: ddeAppend<ddeHTMLLinkElement>;
|
||||
}
|
||||
export interface ddeHTMLMapElement extends HTMLMapElement {
|
||||
append: ddeAppend<ddeHTMLMapElement>;
|
||||
}
|
||||
export interface ddeHTMLMenuElement extends HTMLMenuElement {
|
||||
append: ddeAppend<ddeHTMLMenuElement>;
|
||||
}
|
||||
export interface ddeHTMLMetaElement extends HTMLMetaElement {
|
||||
append: ddeAppend<ddeHTMLMetaElement>;
|
||||
}
|
||||
export interface ddeHTMLMeterElement extends HTMLMeterElement {
|
||||
append: ddeAppend<ddeHTMLMeterElement>;
|
||||
}
|
||||
export interface ddeHTMLObjectElement extends HTMLObjectElement {
|
||||
append: ddeAppend<ddeHTMLObjectElement>;
|
||||
}
|
||||
export interface ddeHTMLOListElement extends HTMLOListElement {
|
||||
append: ddeAppend<ddeHTMLOListElement>;
|
||||
}
|
||||
export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement {
|
||||
append: ddeAppend<ddeHTMLOptGroupElement>;
|
||||
}
|
||||
export interface ddeHTMLOptionElement extends HTMLOptionElement {
|
||||
append: ddeAppend<ddeHTMLOptionElement>;
|
||||
}
|
||||
export interface ddeHTMLOutputElement extends HTMLOutputElement {
|
||||
append: ddeAppend<ddeHTMLOutputElement>;
|
||||
}
|
||||
export interface ddeHTMLParagraphElement extends HTMLParagraphElement {
|
||||
append: ddeAppend<ddeHTMLParagraphElement>;
|
||||
}
|
||||
export interface ddeHTMLPictureElement extends HTMLPictureElement {
|
||||
append: ddeAppend<ddeHTMLPictureElement>;
|
||||
}
|
||||
export interface ddeHTMLPreElement extends HTMLPreElement {
|
||||
append: ddeAppend<ddeHTMLPreElement>;
|
||||
}
|
||||
export interface ddeHTMLProgressElement extends HTMLProgressElement {
|
||||
append: ddeAppend<ddeHTMLProgressElement>;
|
||||
}
|
||||
export interface ddeHTMLScriptElement extends HTMLScriptElement {
|
||||
append: ddeAppend<ddeHTMLScriptElement>;
|
||||
}
|
||||
export interface ddeHTMLSelectElement extends HTMLSelectElement {
|
||||
append: ddeAppend<ddeHTMLSelectElement>;
|
||||
}
|
||||
export interface ddeHTMLSlotElement extends HTMLSlotElement {
|
||||
append: ddeAppend<ddeHTMLSlotElement>;
|
||||
}
|
||||
export interface ddeHTMLSourceElement extends HTMLSourceElement {
|
||||
append: ddeAppend<ddeHTMLSourceElement>;
|
||||
}
|
||||
export interface ddeHTMLSpanElement extends HTMLSpanElement {
|
||||
append: ddeAppend<ddeHTMLSpanElement>;
|
||||
}
|
||||
export interface ddeHTMLStyleElement extends HTMLStyleElement {
|
||||
append: ddeAppend<ddeHTMLStyleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableElement extends HTMLTableElement {
|
||||
append: ddeAppend<ddeHTMLTableElement>;
|
||||
}
|
||||
export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement {
|
||||
append: ddeAppend<ddeHTMLTableSectionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTemplateElement extends HTMLTemplateElement {
|
||||
append: ddeAppend<ddeHTMLTemplateElement>;
|
||||
}
|
||||
export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement {
|
||||
append: ddeAppend<ddeHTMLTextAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTimeElement extends HTMLTimeElement {
|
||||
append: ddeAppend<ddeHTMLTimeElement>;
|
||||
}
|
||||
export interface ddeHTMLTitleElement extends HTMLTitleElement {
|
||||
append: ddeAppend<ddeHTMLTitleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableRowElement extends HTMLTableRowElement {
|
||||
append: ddeAppend<ddeHTMLTableRowElement>;
|
||||
}
|
||||
export interface ddeHTMLTrackElement extends HTMLTrackElement {
|
||||
append: ddeAppend<ddeHTMLTrackElement>;
|
||||
}
|
||||
export interface ddeHTMLUListElement extends HTMLUListElement {
|
||||
append: ddeAppend<ddeHTMLUListElement>;
|
||||
}
|
||||
export interface ddeHTMLVideoElement extends HTMLVideoElement {
|
||||
append: ddeAppend<ddeHTMLVideoElement>;
|
||||
}
|
||||
export interface ddeSVGAElement extends SVGAElement {
|
||||
append: ddeAppend<ddeSVGAElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateElement extends SVGAnimateElement {
|
||||
append: ddeAppend<ddeSVGAnimateElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement {
|
||||
append: ddeAppend<ddeSVGAnimateMotionElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement {
|
||||
append: ddeAppend<ddeSVGAnimateTransformElement>;
|
||||
}
|
||||
export interface ddeSVGCircleElement extends SVGCircleElement {
|
||||
append: ddeAppend<ddeSVGCircleElement>;
|
||||
}
|
||||
export interface ddeSVGClipPathElement extends SVGClipPathElement {
|
||||
append: ddeAppend<ddeSVGClipPathElement>;
|
||||
}
|
||||
export interface ddeSVGDefsElement extends SVGDefsElement {
|
||||
append: ddeAppend<ddeSVGDefsElement>;
|
||||
}
|
||||
export interface ddeSVGDescElement extends SVGDescElement {
|
||||
append: ddeAppend<ddeSVGDescElement>;
|
||||
}
|
||||
export interface ddeSVGEllipseElement extends SVGEllipseElement {
|
||||
append: ddeAppend<ddeSVGEllipseElement>;
|
||||
}
|
||||
export interface ddeSVGFEBlendElement extends SVGFEBlendElement {
|
||||
append: ddeAppend<ddeSVGFEBlendElement>;
|
||||
}
|
||||
export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEColorMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement {
|
||||
append: ddeAppend<ddeSVGFEComponentTransferElement>;
|
||||
}
|
||||
export interface ddeSVGFECompositeElement extends SVGFECompositeElement {
|
||||
append: ddeAppend<ddeSVGFECompositeElement>;
|
||||
}
|
||||
export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEConvolveMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement {
|
||||
append: ddeAppend<ddeSVGFEDiffuseLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement {
|
||||
append: ddeAppend<ddeSVGFEDisplacementMapElement>;
|
||||
}
|
||||
export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement {
|
||||
append: ddeAppend<ddeSVGFEDistantLightElement>;
|
||||
}
|
||||
export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement {
|
||||
append: ddeAppend<ddeSVGFEDropShadowElement>;
|
||||
}
|
||||
export interface ddeSVGFEFloodElement extends SVGFEFloodElement {
|
||||
append: ddeAppend<ddeSVGFEFloodElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement {
|
||||
append: ddeAppend<ddeSVGFEFuncAElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement {
|
||||
append: ddeAppend<ddeSVGFEFuncBElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement {
|
||||
append: ddeAppend<ddeSVGFEFuncGElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement {
|
||||
append: ddeAppend<ddeSVGFEFuncRElement>;
|
||||
}
|
||||
export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement {
|
||||
append: ddeAppend<ddeSVGFEGaussianBlurElement>;
|
||||
}
|
||||
export interface ddeSVGFEImageElement extends SVGFEImageElement {
|
||||
append: ddeAppend<ddeSVGFEImageElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeElement extends SVGFEMergeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeNodeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement {
|
||||
append: ddeAppend<ddeSVGFEMorphologyElement>;
|
||||
}
|
||||
export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement {
|
||||
append: ddeAppend<ddeSVGFEOffsetElement>;
|
||||
}
|
||||
export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement {
|
||||
append: ddeAppend<ddeSVGFEPointLightElement>;
|
||||
}
|
||||
export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement {
|
||||
append: ddeAppend<ddeSVGFESpecularLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement {
|
||||
append: ddeAppend<ddeSVGFESpotLightElement>;
|
||||
}
|
||||
export interface ddeSVGFETileElement extends SVGFETileElement {
|
||||
append: ddeAppend<ddeSVGFETileElement>;
|
||||
}
|
||||
export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement {
|
||||
append: ddeAppend<ddeSVGFETurbulenceElement>;
|
||||
}
|
||||
export interface ddeSVGFilterElement extends SVGFilterElement {
|
||||
append: ddeAppend<ddeSVGFilterElement>;
|
||||
}
|
||||
export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement {
|
||||
append: ddeAppend<ddeSVGForeignObjectElement>;
|
||||
}
|
||||
export interface ddeSVGGElement extends SVGGElement {
|
||||
append: ddeAppend<ddeSVGGElement>;
|
||||
}
|
||||
export interface ddeSVGImageElement extends SVGImageElement {
|
||||
append: ddeAppend<ddeSVGImageElement>;
|
||||
}
|
||||
export interface ddeSVGLineElement extends SVGLineElement {
|
||||
append: ddeAppend<ddeSVGLineElement>;
|
||||
}
|
||||
export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement {
|
||||
append: ddeAppend<ddeSVGLinearGradientElement>;
|
||||
}
|
||||
export interface ddeSVGMarkerElement extends SVGMarkerElement {
|
||||
append: ddeAppend<ddeSVGMarkerElement>;
|
||||
}
|
||||
export interface ddeSVGMaskElement extends SVGMaskElement {
|
||||
append: ddeAppend<ddeSVGMaskElement>;
|
||||
}
|
||||
export interface ddeSVGMetadataElement extends SVGMetadataElement {
|
||||
append: ddeAppend<ddeSVGMetadataElement>;
|
||||
}
|
||||
export interface ddeSVGMPathElement extends SVGMPathElement {
|
||||
append: ddeAppend<ddeSVGMPathElement>;
|
||||
}
|
||||
export interface ddeSVGPathElement extends SVGPathElement {
|
||||
append: ddeAppend<ddeSVGPathElement>;
|
||||
}
|
||||
export interface ddeSVGPatternElement extends SVGPatternElement {
|
||||
append: ddeAppend<ddeSVGPatternElement>;
|
||||
}
|
||||
export interface ddeSVGPolygonElement extends SVGPolygonElement {
|
||||
append: ddeAppend<ddeSVGPolygonElement>;
|
||||
}
|
||||
export interface ddeSVGPolylineElement extends SVGPolylineElement {
|
||||
append: ddeAppend<ddeSVGPolylineElement>;
|
||||
}
|
||||
export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement {
|
||||
append: ddeAppend<ddeSVGRadialGradientElement>;
|
||||
}
|
||||
export interface ddeSVGRectElement extends SVGRectElement {
|
||||
append: ddeAppend<ddeSVGRectElement>;
|
||||
}
|
||||
export interface ddeSVGScriptElement extends SVGScriptElement {
|
||||
append: ddeAppend<ddeSVGScriptElement>;
|
||||
}
|
||||
export interface ddeSVGSetElement extends SVGSetElement {
|
||||
append: ddeAppend<ddeSVGSetElement>;
|
||||
}
|
||||
export interface ddeSVGStopElement extends SVGStopElement {
|
||||
append: ddeAppend<ddeSVGStopElement>;
|
||||
}
|
||||
export interface ddeSVGStyleElement extends SVGStyleElement {
|
||||
append: ddeAppend<ddeSVGStyleElement>;
|
||||
}
|
||||
export interface ddeSVGSVGElement extends SVGSVGElement {
|
||||
append: ddeAppend<ddeSVGSVGElement>;
|
||||
}
|
||||
export interface ddeSVGSwitchElement extends SVGSwitchElement {
|
||||
append: ddeAppend<ddeSVGSwitchElement>;
|
||||
}
|
||||
export interface ddeSVGSymbolElement extends SVGSymbolElement {
|
||||
append: ddeAppend<ddeSVGSymbolElement>;
|
||||
}
|
||||
export interface ddeSVGTextElement extends SVGTextElement {
|
||||
append: ddeAppend<ddeSVGTextElement>;
|
||||
}
|
||||
export interface ddeSVGTextPathElement extends SVGTextPathElement {
|
||||
append: ddeAppend<ddeSVGTextPathElement>;
|
||||
}
|
||||
export interface ddeSVGTitleElement extends SVGTitleElement {
|
||||
append: ddeAppend<ddeSVGTitleElement>;
|
||||
}
|
||||
export interface ddeSVGTSpanElement extends SVGTSpanElement {
|
||||
append: ddeAppend<ddeSVGTSpanElement>;
|
||||
}
|
||||
export interface ddeSVGUseElement extends SVGUseElement {
|
||||
append: ddeAppend<ddeSVGUseElement>;
|
||||
}
|
||||
export interface ddeSVGViewElement extends SVGViewElement {
|
||||
append: ddeAppend<ddeSVGViewElement>;
|
||||
}
|
||||
|
||||
export {
|
||||
dispatchEvent$1 as dispatchEvent,
|
||||
el as createElement,
|
||||
elNS as createElementNS,
|
||||
};
|
||||
|
||||
export as namespace dde;
|
||||
|
||||
export {};
|
1
dist/dde.min.js
vendored
Normal file
1
dist/dde.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
641
dist/esm-with-signals.d.min.ts
vendored
Normal file
641
dist/esm-with-signals.d.min.ts
vendored
Normal file
@ -0,0 +1,641 @@
|
||||
declare global{ /* ddeSignal */ }
|
||||
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
||||
type SupportedElement=
|
||||
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
||||
| SVGElementTagNameMap[keyof SVGElementTagNameMap]
|
||||
| MathMLElementTagNameMap[keyof MathMLElementTagNameMap]
|
||||
| CustomElementTagNameMap[keyof CustomElementTagNameMap]
|
||||
declare global {
|
||||
type ddeComponentAttributes= Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node>= (element: El)=> any;
|
||||
type ddeString= string | ddeSignal<string>
|
||||
type ddeStringable= ddeString | number | ddeSignal<number>
|
||||
}
|
||||
type PascalCase=
|
||||
`${Capitalize<string>}${string}`;
|
||||
type AttrsModified= {
|
||||
/**
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString
|
||||
| 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.
|
||||
*/
|
||||
classList: Record<string,-1|0|1|boolean|ddeSignal<-1|0|1|boolean>>,
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap)
|
||||
* */
|
||||
dataset: Record<string, ddeStringable>,
|
||||
/**
|
||||
* Sets `aria-*` simiraly to `dataset`
|
||||
* */
|
||||
ariaset: Record<string, ddeString>,
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString>
|
||||
& Record<`.${string}`, any>
|
||||
type _fromElsInterfaces<EL extends SupportedElement>= Omit<EL, keyof AttrsModified>;
|
||||
type IsReadonly<T, K extends keyof T> =
|
||||
T extends { readonly [P in K]: T[K] } ? true : false;
|
||||
/**
|
||||
* 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)).
|
||||
*
|
||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||
* @private
|
||||
*/
|
||||
type ElementAttributes<T extends SupportedElement>= Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]:
|
||||
_fromElsInterfaces<T>[K] extends ((...p: any[])=> any)
|
||||
? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>)=>
|
||||
ddeSignal<ReturnType<_fromElsInterfaces<T>[K]>>)
|
||||
: (IsReadonly<_fromElsInterfaces<T>, K> extends false
|
||||
? _fromElsInterfaces<T>[K] | ddeSignal<_fromElsInterfaces<T>[K]>
|
||||
: ddeStringable)
|
||||
} & 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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(
|
||||
element: El,
|
||||
attr: ATT,
|
||||
value: ElementAttributes<El>[ATT]
|
||||
): ElementAttributes<El>[ATT]
|
||||
|
||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(
|
||||
attrs: { type: "component"|"reactive"|"later", name?: string, host?: "this"|"parentElement" },
|
||||
is_open?: boolean
|
||||
): Comment;
|
||||
}
|
||||
|
||||
export function el<
|
||||
A extends ddeComponentAttributes,
|
||||
EL extends SupportedElement | ddeDocumentFragment
|
||||
>(
|
||||
component: (attr: A, ...rest: any[])=> EL,
|
||||
attrs?: NoInfer<A>,
|
||||
...addons: ddeElementAddon<EL>[]
|
||||
): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap]
|
||||
? EL
|
||||
: ( EL extends ddeDocumentFragment ? EL : ddeHTMLElement )
|
||||
export function el<
|
||||
A extends { textContent: ddeStringable },
|
||||
EL extends SupportedElement | ddeDocumentFragment
|
||||
>(
|
||||
component: (attr: A, ...rest: any[])=> EL,
|
||||
attrs?: NoInfer<A>["textContent"],
|
||||
...addons: ddeElementAddon<EL>[]
|
||||
): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap]
|
||||
? EL
|
||||
: ( EL extends ddeDocumentFragment ? EL : ddeHTMLElement )
|
||||
export function el<
|
||||
TAG extends keyof ExtendedHTMLElementTagNameMap,
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable,
|
||||
...addons: ddeElementAddon<
|
||||
ExtendedHTMLElementTagNameMap[NoInfer<TAG>]
|
||||
>[], // TODO: for now addons must have the same element
|
||||
): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement
|
||||
export function el(
|
||||
tag_name?: "<>",
|
||||
): ddeDocumentFragment
|
||||
export function el(
|
||||
tag_name: string,
|
||||
attrs?: ElementAttributes<HTMLElement> | ddeStringable,
|
||||
...addons: ddeElementAddon<HTMLElement>[]
|
||||
): ddeHTMLElement
|
||||
export { el as createElement }
|
||||
|
||||
export function elNS(
|
||||
namespace: "http://www.w3.org/2000/svg"
|
||||
): <
|
||||
TAG extends keyof SVGElementTagNameMap & string,
|
||||
EL extends ( TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement ),
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable,
|
||||
...addons: ddeElementAddon<NoInfer<EL>>[]
|
||||
)=> TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement
|
||||
export function elNS(
|
||||
namespace: "http://www.w3.org/1998/Math/MathML"
|
||||
): <
|
||||
TAG extends keyof MathMLElementTagNameMap & string,
|
||||
EL extends ( TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement ),
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | ddeSignal<EL[key]> | string | number | boolean
|
||||
}>,
|
||||
...addons: ddeElementAddon<NoInfer<EL>>[]
|
||||
)=> ddeMathMLElement
|
||||
export function elNS(
|
||||
namespace: string
|
||||
): (
|
||||
tag_name: string,
|
||||
attrs?: string | ddeStringable | Record<string, any>,
|
||||
...addons: ddeElementAddon<SupportedElement>[]
|
||||
)=> SupportedElement
|
||||
export { elNS as createElementNS }
|
||||
|
||||
export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
||||
/** Simulate slots for ddeComponents */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(
|
||||
root: EL,
|
||||
): EL
|
||||
/**
|
||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||
* @param el Custom Element root element
|
||||
* @param body Body of the custom element
|
||||
* */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(
|
||||
el: HTMLElement,
|
||||
body: EL,
|
||||
): EL
|
||||
|
||||
export function dispatchEvent(name: keyof DocumentEventMap | string, element: SupportedElement):
|
||||
(data?: any)=> void;
|
||||
export function dispatchEvent(name: keyof DocumentEventMap | string, options?: EventInit):
|
||||
(element: SupportedElement, data?: any)=> void;
|
||||
export function dispatchEvent(
|
||||
name: keyof DocumentEventMap | string,
|
||||
options: EventInit | null,
|
||||
element: SupportedElement | (()=> SupportedElement)
|
||||
): (data?: any)=> void;
|
||||
interface On{
|
||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||
<
|
||||
Event extends keyof DocumentEventMap,
|
||||
EE extends ddeElementAddon<SupportedElement>= ddeElementAddon<HTMLElement>,
|
||||
>(
|
||||
type: Event,
|
||||
listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : EE;
|
||||
<
|
||||
EE extends ddeElementAddon<SupportedElement>= ddeElementAddon<HTMLElement>,
|
||||
>(
|
||||
type: string,
|
||||
listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent ) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : 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 */// editorconfig-checker-disable-line
|
||||
connected<
|
||||
EE extends ddeElementAddon<SupportedElement>,
|
||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||
>(
|
||||
listener: (this: El, event: CustomEvent<El>) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : 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 */// editorconfig-checker-disable-line
|
||||
disconnected<
|
||||
EE extends ddeElementAddon<SupportedElement>,
|
||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||
>(
|
||||
listener: (this: El, event: CustomEvent<void>) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : 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 */// editorconfig-checker-disable-line
|
||||
attributeChanged<
|
||||
EE extends ddeElementAddon<SupportedElement>,
|
||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||
>(
|
||||
listener: (this: El, event: CustomEvent<[ string, string ]>) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : EE;
|
||||
}
|
||||
export const on: On;
|
||||
|
||||
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}) */
|
||||
export const scope: {
|
||||
current: Scope,
|
||||
/** Stops all automatizations. E. g. signals used as attributes in current scope
|
||||
* registers removing these listeners (and clean signal if no other listeners are detected)
|
||||
* on `disconnected` event. */
|
||||
preventDefault<T extends boolean>(prevent: T): T,
|
||||
/**
|
||||
* This represents reference to the current host element — `scope.host()`.
|
||||
* It can be also used to register Addon(s) (functions to be called when component is initized)
|
||||
* — `scope.host(on.connected(console.log))`.
|
||||
* */
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[])=> HTMLElement,
|
||||
|
||||
state: Scope[],
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>,
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>,
|
||||
/** Removes last/current child scope. */
|
||||
pop(): ReturnType<Array<Scope>["pop"]>,
|
||||
};
|
||||
|
||||
export function customElementRender<
|
||||
EL extends HTMLElement,
|
||||
P extends any = Record<string, string | ddeSignal<string>>
|
||||
>(
|
||||
target: ShadowRoot | EL,
|
||||
render: (props: P)=> SupportedElement | DocumentFragment,
|
||||
props?: P | ((el: EL)=> P)
|
||||
): EL
|
||||
export function customElementWithDDE<EL extends (new ()=> HTMLElement)>(custom_element: EL): EL
|
||||
export function lifecyclesToEvents<EL extends (new ()=> HTMLElement)>(custom_element: EL): EL
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>
|
||||
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
|
||||
/* TypeScript MEH */
|
||||
declare global{
|
||||
type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
|
||||
|
||||
interface ddeDocumentFragment extends DocumentFragment{ append: ddeAppend<ddeDocumentFragment>; }
|
||||
interface ddeHTMLElement extends HTMLElement{ append: ddeAppend<ddeHTMLElement>; }
|
||||
interface ddeSVGElement extends SVGElement{ append: ddeAppend<ddeSVGElement>; }
|
||||
interface ddeMathMLElement extends MathMLElement{ append: ddeAppend<ddeMathMLElement>; }
|
||||
|
||||
interface ddeHTMLElementTagNameMap {
|
||||
"a": ddeHTMLAnchorElement;
|
||||
"area": ddeHTMLAreaElement;
|
||||
"audio": ddeHTMLAudioElement;
|
||||
"base": ddeHTMLBaseElement;
|
||||
"blockquote": ddeHTMLQuoteElement;
|
||||
"body": ddeHTMLBodyElement;
|
||||
"br": ddeHTMLBRElement;
|
||||
"button": ddeHTMLButtonElement;
|
||||
"canvas": ddeHTMLCanvasElement;
|
||||
"caption": ddeHTMLTableCaptionElement;
|
||||
"col": ddeHTMLTableColElement;
|
||||
"colgroup": ddeHTMLTableColElement;
|
||||
"data": ddeHTMLDataElement;
|
||||
"datalist": ddeHTMLDataListElement;
|
||||
"del": ddeHTMLModElement;
|
||||
"details": ddeHTMLDetailsElement;
|
||||
"dialog": ddeHTMLDialogElement;
|
||||
"div": ddeHTMLDivElement;
|
||||
"dl": ddeHTMLDListElement;
|
||||
"embed": ddeHTMLEmbedElement;
|
||||
"fieldset": ddeHTMLFieldSetElement;
|
||||
"form": ddeHTMLFormElement;
|
||||
"h1": ddeHTMLHeadingElement;
|
||||
"h2": ddeHTMLHeadingElement;
|
||||
"h3": ddeHTMLHeadingElement;
|
||||
"h4": ddeHTMLHeadingElement;
|
||||
"h5": ddeHTMLHeadingElement;
|
||||
"h6": ddeHTMLHeadingElement;
|
||||
"head": ddeHTMLHeadElement;
|
||||
"hr": ddeHTMLHRElement;
|
||||
"html": ddeHTMLHtmlElement;
|
||||
"iframe": ddeHTMLIFrameElement;
|
||||
"img": ddeHTMLImageElement;
|
||||
"input": ddeHTMLInputElement;
|
||||
"ins": ddeHTMLModElement;
|
||||
"label": ddeHTMLLabelElement;
|
||||
"legend": ddeHTMLLegendElement;
|
||||
"li": ddeHTMLLIElement;
|
||||
"link": ddeHTMLLinkElement;
|
||||
"map": ddeHTMLMapElement;
|
||||
"menu": ddeHTMLMenuElement;
|
||||
"meta": ddeHTMLMetaElement;
|
||||
"meter": ddeHTMLMeterElement;
|
||||
"object": ddeHTMLObjectElement;
|
||||
"ol": ddeHTMLOListElement;
|
||||
"optgroup": ddeHTMLOptGroupElement;
|
||||
"option": ddeHTMLOptionElement;
|
||||
"output": ddeHTMLOutputElement;
|
||||
"p": ddeHTMLParagraphElement;
|
||||
"picture": ddeHTMLPictureElement;
|
||||
"pre": ddeHTMLPreElement;
|
||||
"progress": ddeHTMLProgressElement;
|
||||
"q": ddeHTMLQuoteElement;
|
||||
"script": ddeHTMLScriptElement;
|
||||
"select": ddeHTMLSelectElement;
|
||||
"slot": ddeHTMLSlotElement;
|
||||
"source": ddeHTMLSourceElement;
|
||||
"span": ddeHTMLSpanElement;
|
||||
"style": ddeHTMLStyleElement;
|
||||
"table": ddeHTMLTableElement;
|
||||
"tbody": ddeHTMLTableSectionElement;
|
||||
"td": ddeHTMLTableCellElement;
|
||||
"template": ddeHTMLTemplateElement;
|
||||
"textarea": ddeHTMLTextAreaElement;
|
||||
"tfoot": ddeHTMLTableSectionElement;
|
||||
"th": ddeHTMLTableCellElement;
|
||||
"thead": ddeHTMLTableSectionElement;
|
||||
"time": ddeHTMLTimeElement;
|
||||
"title": ddeHTMLTitleElement;
|
||||
"tr": ddeHTMLTableRowElement;
|
||||
"track": ddeHTMLTrackElement;
|
||||
"ul": ddeHTMLUListElement;
|
||||
"video": ddeHTMLVideoElement;
|
||||
}
|
||||
interface ddeSVGElementTagNameMap {
|
||||
"a": ddeSVGAElement;
|
||||
"animate": ddeSVGAnimateElement;
|
||||
"animateMotion": ddeSVGAnimateMotionElement;
|
||||
"animateTransform": ddeSVGAnimateTransformElement;
|
||||
"circle": ddeSVGCircleElement;
|
||||
"clipPath": ddeSVGClipPathElement;
|
||||
"defs": ddeSVGDefsElement;
|
||||
"desc": ddeSVGDescElement;
|
||||
"ellipse": ddeSVGEllipseElement;
|
||||
"feBlend": ddeSVGFEBlendElement;
|
||||
"feColorMatrix": ddeSVGFEColorMatrixElement;
|
||||
"feComponentTransfer": ddeSVGFEComponentTransferElement;
|
||||
"feComposite": ddeSVGFECompositeElement;
|
||||
"feConvolveMatrix": ddeSVGFEConvolveMatrixElement;
|
||||
"feDiffuseLighting": ddeSVGFEDiffuseLightingElement;
|
||||
"feDisplacementMap": ddeSVGFEDisplacementMapElement;
|
||||
"feDistantLight": ddeSVGFEDistantLightElement;
|
||||
"feDropShadow": ddeSVGFEDropShadowElement;
|
||||
"feFlood": ddeSVGFEFloodElement;
|
||||
"feFuncA": ddeSVGFEFuncAElement;
|
||||
"feFuncB": ddeSVGFEFuncBElement;
|
||||
"feFuncG": ddeSVGFEFuncGElement;
|
||||
"feFuncR": ddeSVGFEFuncRElement;
|
||||
"feGaussianBlur": ddeSVGFEGaussianBlurElement;
|
||||
"feImage": ddeSVGFEImageElement;
|
||||
"feMerge": ddeSVGFEMergeElement;
|
||||
"feMergeNode": ddeSVGFEMergeNodeElement;
|
||||
"feMorphology": ddeSVGFEMorphologyElement;
|
||||
"feOffset": ddeSVGFEOffsetElement;
|
||||
"fePointLight": ddeSVGFEPointLightElement;
|
||||
"feSpecularLighting": ddeSVGFESpecularLightingElement;
|
||||
"feSpotLight": ddeSVGFESpotLightElement;
|
||||
"feTile": ddeSVGFETileElement;
|
||||
"feTurbulence": ddeSVGFETurbulenceElement;
|
||||
"filter": ddeSVGFilterElement;
|
||||
"foreignObject": ddeSVGForeignObjectElement;
|
||||
"g": ddeSVGGElement;
|
||||
"image": ddeSVGImageElement;
|
||||
"line": ddeSVGLineElement;
|
||||
"linearGradient": ddeSVGLinearGradientElement;
|
||||
"marker": ddeSVGMarkerElement;
|
||||
"mask": ddeSVGMaskElement;
|
||||
"metadata": ddeSVGMetadataElement;
|
||||
"mpath": ddeSVGMPathElement;
|
||||
"path": ddeSVGPathElement;
|
||||
"pattern": ddeSVGPatternElement;
|
||||
"polygon": ddeSVGPolygonElement;
|
||||
"polyline": ddeSVGPolylineElement;
|
||||
"radialGradient": ddeSVGRadialGradientElement;
|
||||
"rect": ddeSVGRectElement;
|
||||
"script": ddeSVGScriptElement;
|
||||
"set": ddeSVGSetElement;
|
||||
"stop": ddeSVGStopElement;
|
||||
"style": ddeSVGStyleElement;
|
||||
"svg": ddeSVGSVGElement;
|
||||
"switch": ddeSVGSwitchElement;
|
||||
"symbol": ddeSVGSymbolElement;
|
||||
"text": ddeSVGTextElement;
|
||||
"textPath": ddeSVGTextPathElement;
|
||||
"title": ddeSVGTitleElement;
|
||||
"tspan": ddeSVGTSpanElement;
|
||||
"use": ddeSVGUseElement;
|
||||
"view": ddeSVGViewElement;
|
||||
}
|
||||
}
|
||||
|
||||
// editorconfig-checker-disable
|
||||
interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend<ddeHTMLAnchorElement>; }
|
||||
interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend<ddeHTMLAreaElement>; }
|
||||
interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend<ddeHTMLAudioElement>; }
|
||||
interface ddeHTMLBaseElement extends HTMLBaseElement{ append: ddeAppend<ddeHTMLBaseElement>; }
|
||||
interface ddeHTMLQuoteElement extends HTMLQuoteElement{ append: ddeAppend<ddeHTMLQuoteElement>; }
|
||||
interface ddeHTMLBodyElement extends HTMLBodyElement{ append: ddeAppend<ddeHTMLBodyElement>; }
|
||||
interface ddeHTMLBRElement extends HTMLBRElement{ append: ddeAppend<ddeHTMLBRElement>; }
|
||||
interface ddeHTMLButtonElement extends HTMLButtonElement{ append: ddeAppend<ddeHTMLButtonElement>; }
|
||||
interface ddeHTMLCanvasElement extends HTMLCanvasElement{ append: ddeAppend<ddeHTMLCanvasElement>; }
|
||||
interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement{ append: ddeAppend<ddeHTMLTableCaptionElement>; }
|
||||
interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend<ddeHTMLTableColElement>; }
|
||||
interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend<ddeHTMLTableColElement>; }
|
||||
interface ddeHTMLDataElement extends HTMLDataElement{ append: ddeAppend<ddeHTMLDataElement>; }
|
||||
interface ddeHTMLDataListElement extends HTMLDataListElement{ append: ddeAppend<ddeHTMLDataListElement>; }
|
||||
interface ddeHTMLModElement extends HTMLModElement{ append: ddeAppend<ddeHTMLModElement>; }
|
||||
interface ddeHTMLDetailsElement extends HTMLDetailsElement{ append: ddeAppend<ddeHTMLDetailsElement>; }
|
||||
interface ddeHTMLDialogElement extends HTMLDialogElement{ append: ddeAppend<ddeHTMLDialogElement>; }
|
||||
interface ddeHTMLDivElement extends HTMLDivElement{ append: ddeAppend<ddeHTMLDivElement>; }
|
||||
interface ddeHTMLDListElement extends HTMLDListElement{ append: ddeAppend<ddeHTMLDListElement>; }
|
||||
interface ddeHTMLEmbedElement extends HTMLEmbedElement{ append: ddeAppend<ddeHTMLEmbedElement>; }
|
||||
interface ddeHTMLFieldSetElement extends HTMLFieldSetElement{ append: ddeAppend<ddeHTMLFieldSetElement>; }
|
||||
interface ddeHTMLFormElement extends HTMLFormElement{ append: ddeAppend<ddeHTMLFormElement>; }
|
||||
interface ddeHTMLHeadingElement extends HTMLHeadingElement{ append: ddeAppend<ddeHTMLHeadingElement>; }
|
||||
interface ddeHTMLHeadElement extends HTMLHeadElement{ append: ddeAppend<ddeHTMLHeadElement>; }
|
||||
interface ddeHTMLHRElement extends HTMLHRElement{ append: ddeAppend<ddeHTMLHRElement>; }
|
||||
interface ddeHTMLHtmlElement extends HTMLHtmlElement{ append: ddeAppend<ddeHTMLHtmlElement>; }
|
||||
interface ddeHTMLIFrameElement extends HTMLIFrameElement{ append: ddeAppend<ddeHTMLIFrameElement>; }
|
||||
interface ddeHTMLImageElement extends HTMLImageElement{ append: ddeAppend<ddeHTMLImageElement>; }
|
||||
interface ddeHTMLInputElement extends HTMLInputElement{ append: ddeAppend<ddeHTMLInputElement>; }
|
||||
interface ddeHTMLLabelElement extends HTMLLabelElement{ append: ddeAppend<ddeHTMLLabelElement>; }
|
||||
interface ddeHTMLLegendElement extends HTMLLegendElement{ append: ddeAppend<ddeHTMLLegendElement>; }
|
||||
interface ddeHTMLLIElement extends HTMLLIElement{ append: ddeAppend<ddeHTMLLIElement>; }
|
||||
interface ddeHTMLLinkElement extends HTMLLinkElement{ append: ddeAppend<ddeHTMLLinkElement>; }
|
||||
interface ddeHTMLMapElement extends HTMLMapElement{ append: ddeAppend<ddeHTMLMapElement>; }
|
||||
interface ddeHTMLMenuElement extends HTMLMenuElement{ append: ddeAppend<ddeHTMLMenuElement>; }
|
||||
interface ddeHTMLMetaElement extends HTMLMetaElement{ append: ddeAppend<ddeHTMLMetaElement>; }
|
||||
interface ddeHTMLMeterElement extends HTMLMeterElement{ append: ddeAppend<ddeHTMLMeterElement>; }
|
||||
interface ddeHTMLObjectElement extends HTMLObjectElement{ append: ddeAppend<ddeHTMLObjectElement>; }
|
||||
interface ddeHTMLOListElement extends HTMLOListElement{ append: ddeAppend<ddeHTMLOListElement>; }
|
||||
interface ddeHTMLOptGroupElement extends HTMLOptGroupElement{ append: ddeAppend<ddeHTMLOptGroupElement>; }
|
||||
interface ddeHTMLOptionElement extends HTMLOptionElement{ append: ddeAppend<ddeHTMLOptionElement>; }
|
||||
interface ddeHTMLOutputElement extends HTMLOutputElement{ append: ddeAppend<ddeHTMLOutputElement>; }
|
||||
interface ddeHTMLParagraphElement extends HTMLParagraphElement{ append: ddeAppend<ddeHTMLParagraphElement>; }
|
||||
interface ddeHTMLPictureElement extends HTMLPictureElement{ append: ddeAppend<ddeHTMLPictureElement>; }
|
||||
interface ddeHTMLPreElement extends HTMLPreElement{ append: ddeAppend<ddeHTMLPreElement>; }
|
||||
interface ddeHTMLProgressElement extends HTMLProgressElement{ append: ddeAppend<ddeHTMLProgressElement>; }
|
||||
interface ddeHTMLScriptElement extends HTMLScriptElement{ append: ddeAppend<ddeHTMLScriptElement>; }
|
||||
interface ddeHTMLSelectElement extends HTMLSelectElement{ append: ddeAppend<ddeHTMLSelectElement>; }
|
||||
interface ddeHTMLSlotElement extends HTMLSlotElement{ append: ddeAppend<ddeHTMLSlotElement>; }
|
||||
interface ddeHTMLSourceElement extends HTMLSourceElement{ append: ddeAppend<ddeHTMLSourceElement>; }
|
||||
interface ddeHTMLSpanElement extends HTMLSpanElement{ append: ddeAppend<ddeHTMLSpanElement>; }
|
||||
interface ddeHTMLStyleElement extends HTMLStyleElement{ append: ddeAppend<ddeHTMLStyleElement>; }
|
||||
interface ddeHTMLTableElement extends HTMLTableElement{ append: ddeAppend<ddeHTMLTableElement>; }
|
||||
interface ddeHTMLTableSectionElement extends HTMLTableSectionElement{ append: ddeAppend<ddeHTMLTableSectionElement>; }
|
||||
interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend<ddeHTMLTableCellElement>; }
|
||||
interface ddeHTMLTemplateElement extends HTMLTemplateElement{ append: ddeAppend<ddeHTMLTemplateElement>; }
|
||||
interface ddeHTMLTextAreaElement extends HTMLTextAreaElement{ append: ddeAppend<ddeHTMLTextAreaElement>; }
|
||||
interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend<ddeHTMLTableCellElement>; }
|
||||
interface ddeHTMLTimeElement extends HTMLTimeElement{ append: ddeAppend<ddeHTMLTimeElement>; }
|
||||
interface ddeHTMLTitleElement extends HTMLTitleElement{ append: ddeAppend<ddeHTMLTitleElement>; }
|
||||
interface ddeHTMLTableRowElement extends HTMLTableRowElement{ append: ddeAppend<ddeHTMLTableRowElement>; }
|
||||
interface ddeHTMLTrackElement extends HTMLTrackElement{ append: ddeAppend<ddeHTMLTrackElement>; }
|
||||
interface ddeHTMLUListElement extends HTMLUListElement{ append: ddeAppend<ddeHTMLUListElement>; }
|
||||
interface ddeHTMLVideoElement extends HTMLVideoElement{ append: ddeAppend<ddeHTMLVideoElement>; }
|
||||
interface ddeSVGAElement extends SVGAElement{ append: ddeAppend<ddeSVGAElement>; }
|
||||
interface ddeSVGAnimateElement extends SVGAnimateElement{ append: ddeAppend<ddeSVGAnimateElement>; }
|
||||
interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement{ append: ddeAppend<ddeSVGAnimateMotionElement>; }
|
||||
interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement{ append: ddeAppend<ddeSVGAnimateTransformElement>; }
|
||||
interface ddeSVGCircleElement extends SVGCircleElement{ append: ddeAppend<ddeSVGCircleElement>; }
|
||||
interface ddeSVGClipPathElement extends SVGClipPathElement{ append: ddeAppend<ddeSVGClipPathElement>; }
|
||||
interface ddeSVGDefsElement extends SVGDefsElement{ append: ddeAppend<ddeSVGDefsElement>; }
|
||||
interface ddeSVGDescElement extends SVGDescElement{ append: ddeAppend<ddeSVGDescElement>; }
|
||||
interface ddeSVGEllipseElement extends SVGEllipseElement{ append: ddeAppend<ddeSVGEllipseElement>; }
|
||||
interface ddeSVGFEBlendElement extends SVGFEBlendElement{ append: ddeAppend<ddeSVGFEBlendElement>; }
|
||||
interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement{ append: ddeAppend<ddeSVGFEColorMatrixElement>; }
|
||||
interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement{ append: ddeAppend<ddeSVGFEComponentTransferElement>; }
|
||||
interface ddeSVGFECompositeElement extends SVGFECompositeElement{ append: ddeAppend<ddeSVGFECompositeElement>; }
|
||||
interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement{ append: ddeAppend<ddeSVGFEConvolveMatrixElement>; }
|
||||
interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement{ append: ddeAppend<ddeSVGFEDiffuseLightingElement>; }
|
||||
interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement{ append: ddeAppend<ddeSVGFEDisplacementMapElement>; }
|
||||
interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement{ append: ddeAppend<ddeSVGFEDistantLightElement>; }
|
||||
interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement{ append: ddeAppend<ddeSVGFEDropShadowElement>; }
|
||||
interface ddeSVGFEFloodElement extends SVGFEFloodElement{ append: ddeAppend<ddeSVGFEFloodElement>; }
|
||||
interface ddeSVGFEFuncAElement extends SVGFEFuncAElement{ append: ddeAppend<ddeSVGFEFuncAElement>; }
|
||||
interface ddeSVGFEFuncBElement extends SVGFEFuncBElement{ append: ddeAppend<ddeSVGFEFuncBElement>; }
|
||||
interface ddeSVGFEFuncGElement extends SVGFEFuncGElement{ append: ddeAppend<ddeSVGFEFuncGElement>; }
|
||||
interface ddeSVGFEFuncRElement extends SVGFEFuncRElement{ append: ddeAppend<ddeSVGFEFuncRElement>; }
|
||||
interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement{ append: ddeAppend<ddeSVGFEGaussianBlurElement>; }
|
||||
interface ddeSVGFEImageElement extends SVGFEImageElement{ append: ddeAppend<ddeSVGFEImageElement>; }
|
||||
interface ddeSVGFEMergeElement extends SVGFEMergeElement{ append: ddeAppend<ddeSVGFEMergeElement>; }
|
||||
interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement{ append: ddeAppend<ddeSVGFEMergeNodeElement>; }
|
||||
interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement{ append: ddeAppend<ddeSVGFEMorphologyElement>; }
|
||||
interface ddeSVGFEOffsetElement extends SVGFEOffsetElement{ append: ddeAppend<ddeSVGFEOffsetElement>; }
|
||||
interface ddeSVGFEPointLightElement extends SVGFEPointLightElement{ append: ddeAppend<ddeSVGFEPointLightElement>; }
|
||||
interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement{ append: ddeAppend<ddeSVGFESpecularLightingElement>; }
|
||||
interface ddeSVGFESpotLightElement extends SVGFESpotLightElement{ append: ddeAppend<ddeSVGFESpotLightElement>; }
|
||||
interface ddeSVGFETileElement extends SVGFETileElement{ append: ddeAppend<ddeSVGFETileElement>; }
|
||||
interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement{ append: ddeAppend<ddeSVGFETurbulenceElement>; }
|
||||
interface ddeSVGFilterElement extends SVGFilterElement{ append: ddeAppend<ddeSVGFilterElement>; }
|
||||
interface ddeSVGForeignObjectElement extends SVGForeignObjectElement{ append: ddeAppend<ddeSVGForeignObjectElement>; }
|
||||
interface ddeSVGGElement extends SVGGElement{ append: ddeAppend<ddeSVGGElement>; }
|
||||
interface ddeSVGImageElement extends SVGImageElement{ append: ddeAppend<ddeSVGImageElement>; }
|
||||
interface ddeSVGLineElement extends SVGLineElement{ append: ddeAppend<ddeSVGLineElement>; }
|
||||
interface ddeSVGLinearGradientElement extends SVGLinearGradientElement{ append: ddeAppend<ddeSVGLinearGradientElement>; }
|
||||
interface ddeSVGMarkerElement extends SVGMarkerElement{ append: ddeAppend<ddeSVGMarkerElement>; }
|
||||
interface ddeSVGMaskElement extends SVGMaskElement{ append: ddeAppend<ddeSVGMaskElement>; }
|
||||
interface ddeSVGMetadataElement extends SVGMetadataElement{ append: ddeAppend<ddeSVGMetadataElement>; }
|
||||
interface ddeSVGMPathElement extends SVGMPathElement{ append: ddeAppend<ddeSVGMPathElement>; }
|
||||
interface ddeSVGPathElement extends SVGPathElement{ append: ddeAppend<ddeSVGPathElement>; }
|
||||
interface ddeSVGPatternElement extends SVGPatternElement{ append: ddeAppend<ddeSVGPatternElement>; }
|
||||
interface ddeSVGPolygonElement extends SVGPolygonElement{ append: ddeAppend<ddeSVGPolygonElement>; }
|
||||
interface ddeSVGPolylineElement extends SVGPolylineElement{ append: ddeAppend<ddeSVGPolylineElement>; }
|
||||
interface ddeSVGRadialGradientElement extends SVGRadialGradientElement{ append: ddeAppend<ddeSVGRadialGradientElement>; }
|
||||
interface ddeSVGRectElement extends SVGRectElement{ append: ddeAppend<ddeSVGRectElement>; }
|
||||
interface ddeSVGScriptElement extends SVGScriptElement{ append: ddeAppend<ddeSVGScriptElement>; }
|
||||
interface ddeSVGSetElement extends SVGSetElement{ append: ddeAppend<ddeSVGSetElement>; }
|
||||
interface ddeSVGStopElement extends SVGStopElement{ append: ddeAppend<ddeSVGStopElement>; }
|
||||
interface ddeSVGStyleElement extends SVGStyleElement{ append: ddeAppend<ddeSVGStyleElement>; }
|
||||
interface ddeSVGSVGElement extends SVGSVGElement{ append: ddeAppend<ddeSVGSVGElement>; }
|
||||
interface ddeSVGSwitchElement extends SVGSwitchElement{ append: ddeAppend<ddeSVGSwitchElement>; }
|
||||
interface ddeSVGSymbolElement extends SVGSymbolElement{ append: ddeAppend<ddeSVGSymbolElement>; }
|
||||
interface ddeSVGTextElement extends SVGTextElement{ append: ddeAppend<ddeSVGTextElement>; }
|
||||
interface ddeSVGTextPathElement extends SVGTextPathElement{ append: ddeAppend<ddeSVGTextPathElement>; }
|
||||
interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend<ddeSVGTitleElement>; }
|
||||
interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend<ddeSVGTSpanElement>; }
|
||||
interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend<ddeSVGUseElement>; }
|
||||
interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend<ddeSVGViewElement>; }
|
||||
// editorconfig-checker-enable
|
||||
export interface Signal<V, A> {
|
||||
/** The current value of the signal */
|
||||
get(): V;
|
||||
/** Set new value of the signal */
|
||||
set(value: V): V;
|
||||
toJSON(): V;
|
||||
valueOf(): V;
|
||||
}
|
||||
type Action<V>= (this: { value: V, stopPropagation(): void }, ...a: any[])=> typeof signal._ | void;
|
||||
//type SymbolSignal= Symbol;
|
||||
type SymbolOnclear= symbol;
|
||||
type Actions<V>= Record<string | SymbolOnclear, Action<V>>;
|
||||
type OnListenerOptions= Pick<AddEventListenerOptions, "signal"> & { first_time?: boolean };
|
||||
interface signal{
|
||||
_: Symbol
|
||||
/**
|
||||
* Computations signal. This creates a signal which is computed from other signals.
|
||||
* */
|
||||
<V extends ()=> any>(computation: V): Signal<ReturnType<V>, {}>
|
||||
/**
|
||||
* Simple example:
|
||||
* ```js
|
||||
* const hello= S("Hello Signal");
|
||||
* ```
|
||||
* …simple todo signal:
|
||||
* ```js
|
||||
* const todos= S([], {
|
||||
* add(v){ this.value.push(S(v)); },
|
||||
* remove(i){ this.value.splice(i, 1); },
|
||||
* [S.symbols.onclear](){ S.clear(...this.value); },
|
||||
* });
|
||||
* ```
|
||||
* …computed signal:
|
||||
* ```js
|
||||
* const name= S("Jan");
|
||||
* const surname= S("Andrle");
|
||||
* const fullname= S(()=> name.get()+" "+surname.get());
|
||||
* ```
|
||||
* @param value Initial signal value. Or function computing value from other signals.
|
||||
* @param actions Use to define actions on the signal. Such as add item to the array.
|
||||
* There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared
|
||||
* by `S.clear`.
|
||||
* */
|
||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(
|
||||
signal: S,
|
||||
name: N,
|
||||
...params: A[N] extends (...args: infer P)=> any ? P : never
|
||||
): void;
|
||||
clear(...signals: Signal<any, any>[]): void;
|
||||
on<T>(signal: Signal<T, any>, onchange: (a: T)=> void, options?: OnListenerOptions): void;
|
||||
symbols: {
|
||||
//signal: SymbolSignal;
|
||||
onclear: SymbolOnclear;
|
||||
}
|
||||
/**
|
||||
* Reactive element, which is rendered based on the given signal.
|
||||
* ```js
|
||||
* S.el(signal, value=> value ? el("b", "True") : el("i", "False"));
|
||||
* S.el(listS, list=> list.map(li=> el("li", li)));
|
||||
* ```
|
||||
* */
|
||||
el<S extends any>(signal: Signal<S, any>, el: (v: S)=> Element | Element[] | DocumentFragment): DocumentFragment;
|
||||
|
||||
observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>;
|
||||
}
|
||||
export const signal: signal;
|
||||
export const S: signal;
|
||||
declare global {
|
||||
type ddeSignal<T, A= {}>= Signal<T, A>;
|
||||
type ddeAction<V>= Action<V>
|
||||
type ddeActions<V>= Actions<V>
|
||||
}
|
970
dist/esm-with-signals.d.ts
vendored
970
dist/esm-with-signals.d.ts
vendored
File diff suppressed because it is too large
Load Diff
1320
dist/esm-with-signals.js
vendored
1320
dist/esm-with-signals.js
vendored
File diff suppressed because it is too large
Load Diff
783
dist/esm-with-signals.min.d.ts
vendored
Normal file
783
dist/esm-with-signals.min.d.ts
vendored
Normal file
@ -0,0 +1,783 @@
|
||||
// Generated by dts-bundle-generator v9.5.1
|
||||
|
||||
export interface Signal<V, A> {
|
||||
/** The current value of the signal */
|
||||
get(): V;
|
||||
/** Set new value of the signal */
|
||||
set(value: V): V;
|
||||
toJSON(): V;
|
||||
valueOf(): V;
|
||||
}
|
||||
export type Action<V> = (this: {
|
||||
value: V;
|
||||
stopPropagation(): void;
|
||||
}, ...a: any[]) => typeof signal._ | void;
|
||||
//type SymbolSignal= Symbol;
|
||||
export type SymbolOnclear = symbol;
|
||||
export type Actions<V> = Record<string | SymbolOnclear, Action<V>>;
|
||||
export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & {
|
||||
first_time?: boolean;
|
||||
};
|
||||
export interface signal {
|
||||
_: Symbol;
|
||||
/**
|
||||
* Computations signal. This creates a signal which is computed from other signals.
|
||||
* */
|
||||
<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>;
|
||||
/**
|
||||
* Simple example:
|
||||
* ```js
|
||||
* const hello= S("Hello Signal");
|
||||
* ```
|
||||
* …simple todo signal:
|
||||
* ```js
|
||||
* const todos= S([], {
|
||||
* add(v){ this.value.push(S(v)); },
|
||||
* remove(i){ this.value.splice(i, 1); },
|
||||
* [S.symbols.onclear](){ S.clear(...this.value); },
|
||||
* });
|
||||
* ```
|
||||
* …computed signal:
|
||||
* ```js
|
||||
* const name= S("Jan");
|
||||
* const surname= S("Andrle");
|
||||
* const fullname= S(()=> name.get()+" "+surname.get());
|
||||
* ```
|
||||
* @param value Initial signal value. Or function computing value from other signals.
|
||||
* @param actions Use to define actions on the signal. Such as add item to the array.
|
||||
* There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared
|
||||
* by `S.clear`.
|
||||
* */
|
||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void;
|
||||
clear(...signals: Signal<any, any>[]): void;
|
||||
on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void;
|
||||
symbols: {
|
||||
//signal: SymbolSignal;
|
||||
onclear: SymbolOnclear;
|
||||
};
|
||||
/**
|
||||
* Reactive element, which is rendered based on the given signal.
|
||||
* ```js
|
||||
* S.el(signal, value=> value ? el("b", "True") : el("i", "False"));
|
||||
* S.el(listS, list=> list.map(li=> el("li", li)));
|
||||
* ```
|
||||
* */
|
||||
el<S extends any>(signal: Signal<S, any>, el: (v: S) => Element | Element[] | DocumentFragment): DocumentFragment;
|
||||
observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>;
|
||||
}
|
||||
export const signal: signal;
|
||||
export const S: signal;
|
||||
declare global {
|
||||
type ddeSignal<T, A = {}> = Signal<T, A>;
|
||||
type ddeAction<V> = Action<V>;
|
||||
type ddeActions<V> = Actions<V>;
|
||||
}
|
||||
export type CustomElementTagNameMap = {
|
||||
"#text": Text;
|
||||
"#comment": Comment;
|
||||
};
|
||||
export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
||||
declare global {
|
||||
type ddeComponentAttributes = Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El) => any;
|
||||
type ddeString = string | Signal<string, {}>;
|
||||
type ddeStringable = ddeString | number | Signal<number, {}>;
|
||||
}
|
||||
export type PascalCase = `${Capitalize<string>}${string}`;
|
||||
export type AttrsModified = {
|
||||
/**
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString | Partial<{
|
||||
[K in keyof CSSStyleDeclaration]: Signal<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.
|
||||
*/
|
||||
classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>;
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap)
|
||||
* */
|
||||
dataset: Record<string, ddeStringable>;
|
||||
/**
|
||||
* Sets `aria-*` simiraly to `dataset`
|
||||
* */
|
||||
ariaset: Record<string, ddeString>;
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>;
|
||||
export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>;
|
||||
export type IsReadonly<T, K extends keyof T> = T extends {
|
||||
readonly [P in K]: T[K];
|
||||
} ? true : false;
|
||||
/**
|
||||
* 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)).
|
||||
*
|
||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||
* @private
|
||||
*/
|
||||
export type ElementAttributes<T extends SupportedElement> = Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable);
|
||||
} & 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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT];
|
||||
export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(attrs: {
|
||||
type: "component" | "reactive" | "later";
|
||||
name?: string;
|
||||
host?: "this" | "parentElement";
|
||||
}, is_open?: boolean): Comment;
|
||||
}
|
||||
export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<A extends {
|
||||
textContent: ddeStringable;
|
||||
}, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement;
|
||||
export function el(tag_name?: "<>"): ddeDocumentFragment;
|
||||
export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement;
|
||||
export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement;
|
||||
export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean;
|
||||
}>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement;
|
||||
export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement;
|
||||
export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
||||
/** Simulate slots for ddeComponents */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL;
|
||||
/**
|
||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||
* @param el Custom Element root element
|
||||
* @param body Body of the custom element
|
||||
* */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, element: SupportedElement): (data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, element: SupportedElement | (() => SupportedElement)): (data?: any) => void;
|
||||
export interface On {
|
||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||
<Event extends keyof DocumentEventMap, EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: Event, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any, options?: AddEventListenerOptions): EE;
|
||||
<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
connected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<El>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
disconnected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
attributeChanged<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<[
|
||||
string,
|
||||
string
|
||||
]>) => any, options?: AddEventListenerOptions): EE;
|
||||
}
|
||||
export const on: On;
|
||||
export 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}) */
|
||||
export const scope: {
|
||||
current: Scope;
|
||||
/** Stops all automatizations. E. g. signals used as attributes in current scope
|
||||
* registers removing these listeners (and clean signal if no other listeners are detected)
|
||||
* on `disconnected` event. */
|
||||
preventDefault<T extends boolean>(prevent: T): T;
|
||||
/**
|
||||
* This represents reference to the current host element — `scope.host()`.
|
||||
* It can be also used to register Addon(s) (functions to be called when component is initized)
|
||||
* — `scope.host(on.connected(console.log))`.
|
||||
* */
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||
state: Scope[];
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>;
|
||||
/** Removes last/current child scope. */
|
||||
pop(): ReturnType<Array<Scope>["pop"]>;
|
||||
};
|
||||
export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL;
|
||||
export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>;
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
/* TypeScript MEH */
|
||||
declare global {
|
||||
type ddeAppend<el> = (...nodes: (Node | string)[]) => el;
|
||||
interface ddeDocumentFragment extends DocumentFragment {
|
||||
append: ddeAppend<ddeDocumentFragment>;
|
||||
}
|
||||
interface ddeHTMLElement extends HTMLElement {
|
||||
append: ddeAppend<ddeHTMLElement>;
|
||||
}
|
||||
interface ddeSVGElement extends SVGElement {
|
||||
append: ddeAppend<ddeSVGElement>;
|
||||
}
|
||||
interface ddeMathMLElement extends MathMLElement {
|
||||
append: ddeAppend<ddeMathMLElement>;
|
||||
}
|
||||
interface ddeHTMLElementTagNameMap {
|
||||
"a": ddeHTMLAnchorElement;
|
||||
"area": ddeHTMLAreaElement;
|
||||
"audio": ddeHTMLAudioElement;
|
||||
"base": ddeHTMLBaseElement;
|
||||
"blockquote": ddeHTMLQuoteElement;
|
||||
"body": ddeHTMLBodyElement;
|
||||
"br": ddeHTMLBRElement;
|
||||
"button": ddeHTMLButtonElement;
|
||||
"canvas": ddeHTMLCanvasElement;
|
||||
"caption": ddeHTMLTableCaptionElement;
|
||||
"col": ddeHTMLTableColElement;
|
||||
"colgroup": ddeHTMLTableColElement;
|
||||
"data": ddeHTMLDataElement;
|
||||
"datalist": ddeHTMLDataListElement;
|
||||
"del": ddeHTMLModElement;
|
||||
"details": ddeHTMLDetailsElement;
|
||||
"dialog": ddeHTMLDialogElement;
|
||||
"div": ddeHTMLDivElement;
|
||||
"dl": ddeHTMLDListElement;
|
||||
"embed": ddeHTMLEmbedElement;
|
||||
"fieldset": ddeHTMLFieldSetElement;
|
||||
"form": ddeHTMLFormElement;
|
||||
"h1": ddeHTMLHeadingElement;
|
||||
"h2": ddeHTMLHeadingElement;
|
||||
"h3": ddeHTMLHeadingElement;
|
||||
"h4": ddeHTMLHeadingElement;
|
||||
"h5": ddeHTMLHeadingElement;
|
||||
"h6": ddeHTMLHeadingElement;
|
||||
"head": ddeHTMLHeadElement;
|
||||
"hr": ddeHTMLHRElement;
|
||||
"html": ddeHTMLHtmlElement;
|
||||
"iframe": ddeHTMLIFrameElement;
|
||||
"img": ddeHTMLImageElement;
|
||||
"input": ddeHTMLInputElement;
|
||||
"ins": ddeHTMLModElement;
|
||||
"label": ddeHTMLLabelElement;
|
||||
"legend": ddeHTMLLegendElement;
|
||||
"li": ddeHTMLLIElement;
|
||||
"link": ddeHTMLLinkElement;
|
||||
"map": ddeHTMLMapElement;
|
||||
"menu": ddeHTMLMenuElement;
|
||||
"meta": ddeHTMLMetaElement;
|
||||
"meter": ddeHTMLMeterElement;
|
||||
"object": ddeHTMLObjectElement;
|
||||
"ol": ddeHTMLOListElement;
|
||||
"optgroup": ddeHTMLOptGroupElement;
|
||||
"option": ddeHTMLOptionElement;
|
||||
"output": ddeHTMLOutputElement;
|
||||
"p": ddeHTMLParagraphElement;
|
||||
"picture": ddeHTMLPictureElement;
|
||||
"pre": ddeHTMLPreElement;
|
||||
"progress": ddeHTMLProgressElement;
|
||||
"q": ddeHTMLQuoteElement;
|
||||
"script": ddeHTMLScriptElement;
|
||||
"select": ddeHTMLSelectElement;
|
||||
"slot": ddeHTMLSlotElement;
|
||||
"source": ddeHTMLSourceElement;
|
||||
"span": ddeHTMLSpanElement;
|
||||
"style": ddeHTMLStyleElement;
|
||||
"table": ddeHTMLTableElement;
|
||||
"tbody": ddeHTMLTableSectionElement;
|
||||
"td": ddeHTMLTableCellElement;
|
||||
"template": ddeHTMLTemplateElement;
|
||||
"textarea": ddeHTMLTextAreaElement;
|
||||
"tfoot": ddeHTMLTableSectionElement;
|
||||
"th": ddeHTMLTableCellElement;
|
||||
"thead": ddeHTMLTableSectionElement;
|
||||
"time": ddeHTMLTimeElement;
|
||||
"title": ddeHTMLTitleElement;
|
||||
"tr": ddeHTMLTableRowElement;
|
||||
"track": ddeHTMLTrackElement;
|
||||
"ul": ddeHTMLUListElement;
|
||||
"video": ddeHTMLVideoElement;
|
||||
}
|
||||
interface ddeSVGElementTagNameMap {
|
||||
"a": ddeSVGAElement;
|
||||
"animate": ddeSVGAnimateElement;
|
||||
"animateMotion": ddeSVGAnimateMotionElement;
|
||||
"animateTransform": ddeSVGAnimateTransformElement;
|
||||
"circle": ddeSVGCircleElement;
|
||||
"clipPath": ddeSVGClipPathElement;
|
||||
"defs": ddeSVGDefsElement;
|
||||
"desc": ddeSVGDescElement;
|
||||
"ellipse": ddeSVGEllipseElement;
|
||||
"feBlend": ddeSVGFEBlendElement;
|
||||
"feColorMatrix": ddeSVGFEColorMatrixElement;
|
||||
"feComponentTransfer": ddeSVGFEComponentTransferElement;
|
||||
"feComposite": ddeSVGFECompositeElement;
|
||||
"feConvolveMatrix": ddeSVGFEConvolveMatrixElement;
|
||||
"feDiffuseLighting": ddeSVGFEDiffuseLightingElement;
|
||||
"feDisplacementMap": ddeSVGFEDisplacementMapElement;
|
||||
"feDistantLight": ddeSVGFEDistantLightElement;
|
||||
"feDropShadow": ddeSVGFEDropShadowElement;
|
||||
"feFlood": ddeSVGFEFloodElement;
|
||||
"feFuncA": ddeSVGFEFuncAElement;
|
||||
"feFuncB": ddeSVGFEFuncBElement;
|
||||
"feFuncG": ddeSVGFEFuncGElement;
|
||||
"feFuncR": ddeSVGFEFuncRElement;
|
||||
"feGaussianBlur": ddeSVGFEGaussianBlurElement;
|
||||
"feImage": ddeSVGFEImageElement;
|
||||
"feMerge": ddeSVGFEMergeElement;
|
||||
"feMergeNode": ddeSVGFEMergeNodeElement;
|
||||
"feMorphology": ddeSVGFEMorphologyElement;
|
||||
"feOffset": ddeSVGFEOffsetElement;
|
||||
"fePointLight": ddeSVGFEPointLightElement;
|
||||
"feSpecularLighting": ddeSVGFESpecularLightingElement;
|
||||
"feSpotLight": ddeSVGFESpotLightElement;
|
||||
"feTile": ddeSVGFETileElement;
|
||||
"feTurbulence": ddeSVGFETurbulenceElement;
|
||||
"filter": ddeSVGFilterElement;
|
||||
"foreignObject": ddeSVGForeignObjectElement;
|
||||
"g": ddeSVGGElement;
|
||||
"image": ddeSVGImageElement;
|
||||
"line": ddeSVGLineElement;
|
||||
"linearGradient": ddeSVGLinearGradientElement;
|
||||
"marker": ddeSVGMarkerElement;
|
||||
"mask": ddeSVGMaskElement;
|
||||
"metadata": ddeSVGMetadataElement;
|
||||
"mpath": ddeSVGMPathElement;
|
||||
"path": ddeSVGPathElement;
|
||||
"pattern": ddeSVGPatternElement;
|
||||
"polygon": ddeSVGPolygonElement;
|
||||
"polyline": ddeSVGPolylineElement;
|
||||
"radialGradient": ddeSVGRadialGradientElement;
|
||||
"rect": ddeSVGRectElement;
|
||||
"script": ddeSVGScriptElement;
|
||||
"set": ddeSVGSetElement;
|
||||
"stop": ddeSVGStopElement;
|
||||
"style": ddeSVGStyleElement;
|
||||
"svg": ddeSVGSVGElement;
|
||||
"switch": ddeSVGSwitchElement;
|
||||
"symbol": ddeSVGSymbolElement;
|
||||
"text": ddeSVGTextElement;
|
||||
"textPath": ddeSVGTextPathElement;
|
||||
"title": ddeSVGTitleElement;
|
||||
"tspan": ddeSVGTSpanElement;
|
||||
"use": ddeSVGUseElement;
|
||||
"view": ddeSVGViewElement;
|
||||
}
|
||||
}
|
||||
// editorconfig-checker-disable
|
||||
export interface ddeHTMLAnchorElement extends HTMLAnchorElement {
|
||||
append: ddeAppend<ddeHTMLAnchorElement>;
|
||||
}
|
||||
export interface ddeHTMLAreaElement extends HTMLAreaElement {
|
||||
append: ddeAppend<ddeHTMLAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLAudioElement extends HTMLAudioElement {
|
||||
append: ddeAppend<ddeHTMLAudioElement>;
|
||||
}
|
||||
export interface ddeHTMLBaseElement extends HTMLBaseElement {
|
||||
append: ddeAppend<ddeHTMLBaseElement>;
|
||||
}
|
||||
export interface ddeHTMLQuoteElement extends HTMLQuoteElement {
|
||||
append: ddeAppend<ddeHTMLQuoteElement>;
|
||||
}
|
||||
export interface ddeHTMLBodyElement extends HTMLBodyElement {
|
||||
append: ddeAppend<ddeHTMLBodyElement>;
|
||||
}
|
||||
export interface ddeHTMLBRElement extends HTMLBRElement {
|
||||
append: ddeAppend<ddeHTMLBRElement>;
|
||||
}
|
||||
export interface ddeHTMLButtonElement extends HTMLButtonElement {
|
||||
append: ddeAppend<ddeHTMLButtonElement>;
|
||||
}
|
||||
export interface ddeHTMLCanvasElement extends HTMLCanvasElement {
|
||||
append: ddeAppend<ddeHTMLCanvasElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement {
|
||||
append: ddeAppend<ddeHTMLTableCaptionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLDataElement extends HTMLDataElement {
|
||||
append: ddeAppend<ddeHTMLDataElement>;
|
||||
}
|
||||
export interface ddeHTMLDataListElement extends HTMLDataListElement {
|
||||
append: ddeAppend<ddeHTMLDataListElement>;
|
||||
}
|
||||
export interface ddeHTMLModElement extends HTMLModElement {
|
||||
append: ddeAppend<ddeHTMLModElement>;
|
||||
}
|
||||
export interface ddeHTMLDetailsElement extends HTMLDetailsElement {
|
||||
append: ddeAppend<ddeHTMLDetailsElement>;
|
||||
}
|
||||
export interface ddeHTMLDialogElement extends HTMLDialogElement {
|
||||
append: ddeAppend<ddeHTMLDialogElement>;
|
||||
}
|
||||
export interface ddeHTMLDivElement extends HTMLDivElement {
|
||||
append: ddeAppend<ddeHTMLDivElement>;
|
||||
}
|
||||
export interface ddeHTMLDListElement extends HTMLDListElement {
|
||||
append: ddeAppend<ddeHTMLDListElement>;
|
||||
}
|
||||
export interface ddeHTMLEmbedElement extends HTMLEmbedElement {
|
||||
append: ddeAppend<ddeHTMLEmbedElement>;
|
||||
}
|
||||
export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement {
|
||||
append: ddeAppend<ddeHTMLFieldSetElement>;
|
||||
}
|
||||
export interface ddeHTMLFormElement extends HTMLFormElement {
|
||||
append: ddeAppend<ddeHTMLFormElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadingElement extends HTMLHeadingElement {
|
||||
append: ddeAppend<ddeHTMLHeadingElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadElement extends HTMLHeadElement {
|
||||
append: ddeAppend<ddeHTMLHeadElement>;
|
||||
}
|
||||
export interface ddeHTMLHRElement extends HTMLHRElement {
|
||||
append: ddeAppend<ddeHTMLHRElement>;
|
||||
}
|
||||
export interface ddeHTMLHtmlElement extends HTMLHtmlElement {
|
||||
append: ddeAppend<ddeHTMLHtmlElement>;
|
||||
}
|
||||
export interface ddeHTMLIFrameElement extends HTMLIFrameElement {
|
||||
append: ddeAppend<ddeHTMLIFrameElement>;
|
||||
}
|
||||
export interface ddeHTMLImageElement extends HTMLImageElement {
|
||||
append: ddeAppend<ddeHTMLImageElement>;
|
||||
}
|
||||
export interface ddeHTMLInputElement extends HTMLInputElement {
|
||||
append: ddeAppend<ddeHTMLInputElement>;
|
||||
}
|
||||
export interface ddeHTMLLabelElement extends HTMLLabelElement {
|
||||
append: ddeAppend<ddeHTMLLabelElement>;
|
||||
}
|
||||
export interface ddeHTMLLegendElement extends HTMLLegendElement {
|
||||
append: ddeAppend<ddeHTMLLegendElement>;
|
||||
}
|
||||
export interface ddeHTMLLIElement extends HTMLLIElement {
|
||||
append: ddeAppend<ddeHTMLLIElement>;
|
||||
}
|
||||
export interface ddeHTMLLinkElement extends HTMLLinkElement {
|
||||
append: ddeAppend<ddeHTMLLinkElement>;
|
||||
}
|
||||
export interface ddeHTMLMapElement extends HTMLMapElement {
|
||||
append: ddeAppend<ddeHTMLMapElement>;
|
||||
}
|
||||
export interface ddeHTMLMenuElement extends HTMLMenuElement {
|
||||
append: ddeAppend<ddeHTMLMenuElement>;
|
||||
}
|
||||
export interface ddeHTMLMetaElement extends HTMLMetaElement {
|
||||
append: ddeAppend<ddeHTMLMetaElement>;
|
||||
}
|
||||
export interface ddeHTMLMeterElement extends HTMLMeterElement {
|
||||
append: ddeAppend<ddeHTMLMeterElement>;
|
||||
}
|
||||
export interface ddeHTMLObjectElement extends HTMLObjectElement {
|
||||
append: ddeAppend<ddeHTMLObjectElement>;
|
||||
}
|
||||
export interface ddeHTMLOListElement extends HTMLOListElement {
|
||||
append: ddeAppend<ddeHTMLOListElement>;
|
||||
}
|
||||
export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement {
|
||||
append: ddeAppend<ddeHTMLOptGroupElement>;
|
||||
}
|
||||
export interface ddeHTMLOptionElement extends HTMLOptionElement {
|
||||
append: ddeAppend<ddeHTMLOptionElement>;
|
||||
}
|
||||
export interface ddeHTMLOutputElement extends HTMLOutputElement {
|
||||
append: ddeAppend<ddeHTMLOutputElement>;
|
||||
}
|
||||
export interface ddeHTMLParagraphElement extends HTMLParagraphElement {
|
||||
append: ddeAppend<ddeHTMLParagraphElement>;
|
||||
}
|
||||
export interface ddeHTMLPictureElement extends HTMLPictureElement {
|
||||
append: ddeAppend<ddeHTMLPictureElement>;
|
||||
}
|
||||
export interface ddeHTMLPreElement extends HTMLPreElement {
|
||||
append: ddeAppend<ddeHTMLPreElement>;
|
||||
}
|
||||
export interface ddeHTMLProgressElement extends HTMLProgressElement {
|
||||
append: ddeAppend<ddeHTMLProgressElement>;
|
||||
}
|
||||
export interface ddeHTMLScriptElement extends HTMLScriptElement {
|
||||
append: ddeAppend<ddeHTMLScriptElement>;
|
||||
}
|
||||
export interface ddeHTMLSelectElement extends HTMLSelectElement {
|
||||
append: ddeAppend<ddeHTMLSelectElement>;
|
||||
}
|
||||
export interface ddeHTMLSlotElement extends HTMLSlotElement {
|
||||
append: ddeAppend<ddeHTMLSlotElement>;
|
||||
}
|
||||
export interface ddeHTMLSourceElement extends HTMLSourceElement {
|
||||
append: ddeAppend<ddeHTMLSourceElement>;
|
||||
}
|
||||
export interface ddeHTMLSpanElement extends HTMLSpanElement {
|
||||
append: ddeAppend<ddeHTMLSpanElement>;
|
||||
}
|
||||
export interface ddeHTMLStyleElement extends HTMLStyleElement {
|
||||
append: ddeAppend<ddeHTMLStyleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableElement extends HTMLTableElement {
|
||||
append: ddeAppend<ddeHTMLTableElement>;
|
||||
}
|
||||
export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement {
|
||||
append: ddeAppend<ddeHTMLTableSectionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTemplateElement extends HTMLTemplateElement {
|
||||
append: ddeAppend<ddeHTMLTemplateElement>;
|
||||
}
|
||||
export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement {
|
||||
append: ddeAppend<ddeHTMLTextAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTimeElement extends HTMLTimeElement {
|
||||
append: ddeAppend<ddeHTMLTimeElement>;
|
||||
}
|
||||
export interface ddeHTMLTitleElement extends HTMLTitleElement {
|
||||
append: ddeAppend<ddeHTMLTitleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableRowElement extends HTMLTableRowElement {
|
||||
append: ddeAppend<ddeHTMLTableRowElement>;
|
||||
}
|
||||
export interface ddeHTMLTrackElement extends HTMLTrackElement {
|
||||
append: ddeAppend<ddeHTMLTrackElement>;
|
||||
}
|
||||
export interface ddeHTMLUListElement extends HTMLUListElement {
|
||||
append: ddeAppend<ddeHTMLUListElement>;
|
||||
}
|
||||
export interface ddeHTMLVideoElement extends HTMLVideoElement {
|
||||
append: ddeAppend<ddeHTMLVideoElement>;
|
||||
}
|
||||
export interface ddeSVGAElement extends SVGAElement {
|
||||
append: ddeAppend<ddeSVGAElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateElement extends SVGAnimateElement {
|
||||
append: ddeAppend<ddeSVGAnimateElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement {
|
||||
append: ddeAppend<ddeSVGAnimateMotionElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement {
|
||||
append: ddeAppend<ddeSVGAnimateTransformElement>;
|
||||
}
|
||||
export interface ddeSVGCircleElement extends SVGCircleElement {
|
||||
append: ddeAppend<ddeSVGCircleElement>;
|
||||
}
|
||||
export interface ddeSVGClipPathElement extends SVGClipPathElement {
|
||||
append: ddeAppend<ddeSVGClipPathElement>;
|
||||
}
|
||||
export interface ddeSVGDefsElement extends SVGDefsElement {
|
||||
append: ddeAppend<ddeSVGDefsElement>;
|
||||
}
|
||||
export interface ddeSVGDescElement extends SVGDescElement {
|
||||
append: ddeAppend<ddeSVGDescElement>;
|
||||
}
|
||||
export interface ddeSVGEllipseElement extends SVGEllipseElement {
|
||||
append: ddeAppend<ddeSVGEllipseElement>;
|
||||
}
|
||||
export interface ddeSVGFEBlendElement extends SVGFEBlendElement {
|
||||
append: ddeAppend<ddeSVGFEBlendElement>;
|
||||
}
|
||||
export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEColorMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement {
|
||||
append: ddeAppend<ddeSVGFEComponentTransferElement>;
|
||||
}
|
||||
export interface ddeSVGFECompositeElement extends SVGFECompositeElement {
|
||||
append: ddeAppend<ddeSVGFECompositeElement>;
|
||||
}
|
||||
export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEConvolveMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement {
|
||||
append: ddeAppend<ddeSVGFEDiffuseLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement {
|
||||
append: ddeAppend<ddeSVGFEDisplacementMapElement>;
|
||||
}
|
||||
export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement {
|
||||
append: ddeAppend<ddeSVGFEDistantLightElement>;
|
||||
}
|
||||
export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement {
|
||||
append: ddeAppend<ddeSVGFEDropShadowElement>;
|
||||
}
|
||||
export interface ddeSVGFEFloodElement extends SVGFEFloodElement {
|
||||
append: ddeAppend<ddeSVGFEFloodElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement {
|
||||
append: ddeAppend<ddeSVGFEFuncAElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement {
|
||||
append: ddeAppend<ddeSVGFEFuncBElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement {
|
||||
append: ddeAppend<ddeSVGFEFuncGElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement {
|
||||
append: ddeAppend<ddeSVGFEFuncRElement>;
|
||||
}
|
||||
export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement {
|
||||
append: ddeAppend<ddeSVGFEGaussianBlurElement>;
|
||||
}
|
||||
export interface ddeSVGFEImageElement extends SVGFEImageElement {
|
||||
append: ddeAppend<ddeSVGFEImageElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeElement extends SVGFEMergeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeNodeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement {
|
||||
append: ddeAppend<ddeSVGFEMorphologyElement>;
|
||||
}
|
||||
export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement {
|
||||
append: ddeAppend<ddeSVGFEOffsetElement>;
|
||||
}
|
||||
export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement {
|
||||
append: ddeAppend<ddeSVGFEPointLightElement>;
|
||||
}
|
||||
export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement {
|
||||
append: ddeAppend<ddeSVGFESpecularLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement {
|
||||
append: ddeAppend<ddeSVGFESpotLightElement>;
|
||||
}
|
||||
export interface ddeSVGFETileElement extends SVGFETileElement {
|
||||
append: ddeAppend<ddeSVGFETileElement>;
|
||||
}
|
||||
export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement {
|
||||
append: ddeAppend<ddeSVGFETurbulenceElement>;
|
||||
}
|
||||
export interface ddeSVGFilterElement extends SVGFilterElement {
|
||||
append: ddeAppend<ddeSVGFilterElement>;
|
||||
}
|
||||
export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement {
|
||||
append: ddeAppend<ddeSVGForeignObjectElement>;
|
||||
}
|
||||
export interface ddeSVGGElement extends SVGGElement {
|
||||
append: ddeAppend<ddeSVGGElement>;
|
||||
}
|
||||
export interface ddeSVGImageElement extends SVGImageElement {
|
||||
append: ddeAppend<ddeSVGImageElement>;
|
||||
}
|
||||
export interface ddeSVGLineElement extends SVGLineElement {
|
||||
append: ddeAppend<ddeSVGLineElement>;
|
||||
}
|
||||
export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement {
|
||||
append: ddeAppend<ddeSVGLinearGradientElement>;
|
||||
}
|
||||
export interface ddeSVGMarkerElement extends SVGMarkerElement {
|
||||
append: ddeAppend<ddeSVGMarkerElement>;
|
||||
}
|
||||
export interface ddeSVGMaskElement extends SVGMaskElement {
|
||||
append: ddeAppend<ddeSVGMaskElement>;
|
||||
}
|
||||
export interface ddeSVGMetadataElement extends SVGMetadataElement {
|
||||
append: ddeAppend<ddeSVGMetadataElement>;
|
||||
}
|
||||
export interface ddeSVGMPathElement extends SVGMPathElement {
|
||||
append: ddeAppend<ddeSVGMPathElement>;
|
||||
}
|
||||
export interface ddeSVGPathElement extends SVGPathElement {
|
||||
append: ddeAppend<ddeSVGPathElement>;
|
||||
}
|
||||
export interface ddeSVGPatternElement extends SVGPatternElement {
|
||||
append: ddeAppend<ddeSVGPatternElement>;
|
||||
}
|
||||
export interface ddeSVGPolygonElement extends SVGPolygonElement {
|
||||
append: ddeAppend<ddeSVGPolygonElement>;
|
||||
}
|
||||
export interface ddeSVGPolylineElement extends SVGPolylineElement {
|
||||
append: ddeAppend<ddeSVGPolylineElement>;
|
||||
}
|
||||
export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement {
|
||||
append: ddeAppend<ddeSVGRadialGradientElement>;
|
||||
}
|
||||
export interface ddeSVGRectElement extends SVGRectElement {
|
||||
append: ddeAppend<ddeSVGRectElement>;
|
||||
}
|
||||
export interface ddeSVGScriptElement extends SVGScriptElement {
|
||||
append: ddeAppend<ddeSVGScriptElement>;
|
||||
}
|
||||
export interface ddeSVGSetElement extends SVGSetElement {
|
||||
append: ddeAppend<ddeSVGSetElement>;
|
||||
}
|
||||
export interface ddeSVGStopElement extends SVGStopElement {
|
||||
append: ddeAppend<ddeSVGStopElement>;
|
||||
}
|
||||
export interface ddeSVGStyleElement extends SVGStyleElement {
|
||||
append: ddeAppend<ddeSVGStyleElement>;
|
||||
}
|
||||
export interface ddeSVGSVGElement extends SVGSVGElement {
|
||||
append: ddeAppend<ddeSVGSVGElement>;
|
||||
}
|
||||
export interface ddeSVGSwitchElement extends SVGSwitchElement {
|
||||
append: ddeAppend<ddeSVGSwitchElement>;
|
||||
}
|
||||
export interface ddeSVGSymbolElement extends SVGSymbolElement {
|
||||
append: ddeAppend<ddeSVGSymbolElement>;
|
||||
}
|
||||
export interface ddeSVGTextElement extends SVGTextElement {
|
||||
append: ddeAppend<ddeSVGTextElement>;
|
||||
}
|
||||
export interface ddeSVGTextPathElement extends SVGTextPathElement {
|
||||
append: ddeAppend<ddeSVGTextPathElement>;
|
||||
}
|
||||
export interface ddeSVGTitleElement extends SVGTitleElement {
|
||||
append: ddeAppend<ddeSVGTitleElement>;
|
||||
}
|
||||
export interface ddeSVGTSpanElement extends SVGTSpanElement {
|
||||
append: ddeAppend<ddeSVGTSpanElement>;
|
||||
}
|
||||
export interface ddeSVGUseElement extends SVGUseElement {
|
||||
append: ddeAppend<ddeSVGUseElement>;
|
||||
}
|
||||
export interface ddeSVGViewElement extends SVGViewElement {
|
||||
append: ddeAppend<ddeSVGViewElement>;
|
||||
}
|
||||
|
||||
export {
|
||||
dispatchEvent$1 as dispatchEvent,
|
||||
el as createElement,
|
||||
elNS as createElementNS,
|
||||
};
|
||||
|
||||
export {};
|
4
dist/esm-with-signals.min.js
vendored
Normal file
4
dist/esm-with-signals.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
568
dist/esm.d.min.ts
vendored
Normal file
568
dist/esm.d.min.ts
vendored
Normal file
@ -0,0 +1,568 @@
|
||||
declare global{ /* ddeSignal */ }
|
||||
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
||||
type SupportedElement=
|
||||
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
||||
| SVGElementTagNameMap[keyof SVGElementTagNameMap]
|
||||
| MathMLElementTagNameMap[keyof MathMLElementTagNameMap]
|
||||
| CustomElementTagNameMap[keyof CustomElementTagNameMap]
|
||||
declare global {
|
||||
type ddeComponentAttributes= Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node>= (element: El)=> any;
|
||||
type ddeString= string | ddeSignal<string>
|
||||
type ddeStringable= ddeString | number | ddeSignal<number>
|
||||
}
|
||||
type PascalCase=
|
||||
`${Capitalize<string>}${string}`;
|
||||
type AttrsModified= {
|
||||
/**
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString
|
||||
| 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.
|
||||
*/
|
||||
classList: Record<string,-1|0|1|boolean|ddeSignal<-1|0|1|boolean>>,
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap)
|
||||
* */
|
||||
dataset: Record<string, ddeStringable>,
|
||||
/**
|
||||
* Sets `aria-*` simiraly to `dataset`
|
||||
* */
|
||||
ariaset: Record<string, ddeString>,
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString>
|
||||
& Record<`.${string}`, any>
|
||||
type _fromElsInterfaces<EL extends SupportedElement>= Omit<EL, keyof AttrsModified>;
|
||||
type IsReadonly<T, K extends keyof T> =
|
||||
T extends { readonly [P in K]: T[K] } ? true : false;
|
||||
/**
|
||||
* 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)).
|
||||
*
|
||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||
* @private
|
||||
*/
|
||||
type ElementAttributes<T extends SupportedElement>= Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]:
|
||||
_fromElsInterfaces<T>[K] extends ((...p: any[])=> any)
|
||||
? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>)=>
|
||||
ddeSignal<ReturnType<_fromElsInterfaces<T>[K]>>)
|
||||
: (IsReadonly<_fromElsInterfaces<T>, K> extends false
|
||||
? _fromElsInterfaces<T>[K] | ddeSignal<_fromElsInterfaces<T>[K]>
|
||||
: ddeStringable)
|
||||
} & 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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(
|
||||
element: El,
|
||||
attr: ATT,
|
||||
value: ElementAttributes<El>[ATT]
|
||||
): ElementAttributes<El>[ATT]
|
||||
|
||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(
|
||||
attrs: { type: "component"|"reactive"|"later", name?: string, host?: "this"|"parentElement" },
|
||||
is_open?: boolean
|
||||
): Comment;
|
||||
}
|
||||
|
||||
export function el<
|
||||
A extends ddeComponentAttributes,
|
||||
EL extends SupportedElement | ddeDocumentFragment
|
||||
>(
|
||||
component: (attr: A, ...rest: any[])=> EL,
|
||||
attrs?: NoInfer<A>,
|
||||
...addons: ddeElementAddon<EL>[]
|
||||
): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap]
|
||||
? EL
|
||||
: ( EL extends ddeDocumentFragment ? EL : ddeHTMLElement )
|
||||
export function el<
|
||||
A extends { textContent: ddeStringable },
|
||||
EL extends SupportedElement | ddeDocumentFragment
|
||||
>(
|
||||
component: (attr: A, ...rest: any[])=> EL,
|
||||
attrs?: NoInfer<A>["textContent"],
|
||||
...addons: ddeElementAddon<EL>[]
|
||||
): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap]
|
||||
? EL
|
||||
: ( EL extends ddeDocumentFragment ? EL : ddeHTMLElement )
|
||||
export function el<
|
||||
TAG extends keyof ExtendedHTMLElementTagNameMap,
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable,
|
||||
...addons: ddeElementAddon<
|
||||
ExtendedHTMLElementTagNameMap[NoInfer<TAG>]
|
||||
>[], // TODO: for now addons must have the same element
|
||||
): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement
|
||||
export function el(
|
||||
tag_name?: "<>",
|
||||
): ddeDocumentFragment
|
||||
export function el(
|
||||
tag_name: string,
|
||||
attrs?: ElementAttributes<HTMLElement> | ddeStringable,
|
||||
...addons: ddeElementAddon<HTMLElement>[]
|
||||
): ddeHTMLElement
|
||||
export { el as createElement }
|
||||
|
||||
export function elNS(
|
||||
namespace: "http://www.w3.org/2000/svg"
|
||||
): <
|
||||
TAG extends keyof SVGElementTagNameMap & string,
|
||||
EL extends ( TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement ),
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable,
|
||||
...addons: ddeElementAddon<NoInfer<EL>>[]
|
||||
)=> TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement
|
||||
export function elNS(
|
||||
namespace: "http://www.w3.org/1998/Math/MathML"
|
||||
): <
|
||||
TAG extends keyof MathMLElementTagNameMap & string,
|
||||
EL extends ( TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement ),
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | ddeSignal<EL[key]> | string | number | boolean
|
||||
}>,
|
||||
...addons: ddeElementAddon<NoInfer<EL>>[]
|
||||
)=> ddeMathMLElement
|
||||
export function elNS(
|
||||
namespace: string
|
||||
): (
|
||||
tag_name: string,
|
||||
attrs?: string | ddeStringable | Record<string, any>,
|
||||
...addons: ddeElementAddon<SupportedElement>[]
|
||||
)=> SupportedElement
|
||||
export { elNS as createElementNS }
|
||||
|
||||
export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
||||
/** Simulate slots for ddeComponents */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(
|
||||
root: EL,
|
||||
): EL
|
||||
/**
|
||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||
* @param el Custom Element root element
|
||||
* @param body Body of the custom element
|
||||
* */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(
|
||||
el: HTMLElement,
|
||||
body: EL,
|
||||
): EL
|
||||
|
||||
export function dispatchEvent(name: keyof DocumentEventMap | string, element: SupportedElement):
|
||||
(data?: any)=> void;
|
||||
export function dispatchEvent(name: keyof DocumentEventMap | string, options?: EventInit):
|
||||
(element: SupportedElement, data?: any)=> void;
|
||||
export function dispatchEvent(
|
||||
name: keyof DocumentEventMap | string,
|
||||
options: EventInit | null,
|
||||
element: SupportedElement | (()=> SupportedElement)
|
||||
): (data?: any)=> void;
|
||||
interface On{
|
||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||
<
|
||||
Event extends keyof DocumentEventMap,
|
||||
EE extends ddeElementAddon<SupportedElement>= ddeElementAddon<HTMLElement>,
|
||||
>(
|
||||
type: Event,
|
||||
listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : EE;
|
||||
<
|
||||
EE extends ddeElementAddon<SupportedElement>= ddeElementAddon<HTMLElement>,
|
||||
>(
|
||||
type: string,
|
||||
listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent ) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : 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 */// editorconfig-checker-disable-line
|
||||
connected<
|
||||
EE extends ddeElementAddon<SupportedElement>,
|
||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||
>(
|
||||
listener: (this: El, event: CustomEvent<El>) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : 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 */// editorconfig-checker-disable-line
|
||||
disconnected<
|
||||
EE extends ddeElementAddon<SupportedElement>,
|
||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||
>(
|
||||
listener: (this: El, event: CustomEvent<void>) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : 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 */// editorconfig-checker-disable-line
|
||||
attributeChanged<
|
||||
EE extends ddeElementAddon<SupportedElement>,
|
||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||
>(
|
||||
listener: (this: El, event: CustomEvent<[ string, string ]>) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : EE;
|
||||
}
|
||||
export const on: On;
|
||||
|
||||
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}) */
|
||||
export const scope: {
|
||||
current: Scope,
|
||||
/** Stops all automatizations. E. g. signals used as attributes in current scope
|
||||
* registers removing these listeners (and clean signal if no other listeners are detected)
|
||||
* on `disconnected` event. */
|
||||
preventDefault<T extends boolean>(prevent: T): T,
|
||||
/**
|
||||
* This represents reference to the current host element — `scope.host()`.
|
||||
* It can be also used to register Addon(s) (functions to be called when component is initized)
|
||||
* — `scope.host(on.connected(console.log))`.
|
||||
* */
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[])=> HTMLElement,
|
||||
|
||||
state: Scope[],
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>,
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>,
|
||||
/** Removes last/current child scope. */
|
||||
pop(): ReturnType<Array<Scope>["pop"]>,
|
||||
};
|
||||
|
||||
export function customElementRender<
|
||||
EL extends HTMLElement,
|
||||
P extends any = Record<string, string | ddeSignal<string>>
|
||||
>(
|
||||
target: ShadowRoot | EL,
|
||||
render: (props: P)=> SupportedElement | DocumentFragment,
|
||||
props?: P | ((el: EL)=> P)
|
||||
): EL
|
||||
export function customElementWithDDE<EL extends (new ()=> HTMLElement)>(custom_element: EL): EL
|
||||
export function lifecyclesToEvents<EL extends (new ()=> HTMLElement)>(custom_element: EL): EL
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>
|
||||
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
|
||||
/* TypeScript MEH */
|
||||
declare global{
|
||||
type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
|
||||
|
||||
interface ddeDocumentFragment extends DocumentFragment{ append: ddeAppend<ddeDocumentFragment>; }
|
||||
interface ddeHTMLElement extends HTMLElement{ append: ddeAppend<ddeHTMLElement>; }
|
||||
interface ddeSVGElement extends SVGElement{ append: ddeAppend<ddeSVGElement>; }
|
||||
interface ddeMathMLElement extends MathMLElement{ append: ddeAppend<ddeMathMLElement>; }
|
||||
|
||||
interface ddeHTMLElementTagNameMap {
|
||||
"a": ddeHTMLAnchorElement;
|
||||
"area": ddeHTMLAreaElement;
|
||||
"audio": ddeHTMLAudioElement;
|
||||
"base": ddeHTMLBaseElement;
|
||||
"blockquote": ddeHTMLQuoteElement;
|
||||
"body": ddeHTMLBodyElement;
|
||||
"br": ddeHTMLBRElement;
|
||||
"button": ddeHTMLButtonElement;
|
||||
"canvas": ddeHTMLCanvasElement;
|
||||
"caption": ddeHTMLTableCaptionElement;
|
||||
"col": ddeHTMLTableColElement;
|
||||
"colgroup": ddeHTMLTableColElement;
|
||||
"data": ddeHTMLDataElement;
|
||||
"datalist": ddeHTMLDataListElement;
|
||||
"del": ddeHTMLModElement;
|
||||
"details": ddeHTMLDetailsElement;
|
||||
"dialog": ddeHTMLDialogElement;
|
||||
"div": ddeHTMLDivElement;
|
||||
"dl": ddeHTMLDListElement;
|
||||
"embed": ddeHTMLEmbedElement;
|
||||
"fieldset": ddeHTMLFieldSetElement;
|
||||
"form": ddeHTMLFormElement;
|
||||
"h1": ddeHTMLHeadingElement;
|
||||
"h2": ddeHTMLHeadingElement;
|
||||
"h3": ddeHTMLHeadingElement;
|
||||
"h4": ddeHTMLHeadingElement;
|
||||
"h5": ddeHTMLHeadingElement;
|
||||
"h6": ddeHTMLHeadingElement;
|
||||
"head": ddeHTMLHeadElement;
|
||||
"hr": ddeHTMLHRElement;
|
||||
"html": ddeHTMLHtmlElement;
|
||||
"iframe": ddeHTMLIFrameElement;
|
||||
"img": ddeHTMLImageElement;
|
||||
"input": ddeHTMLInputElement;
|
||||
"ins": ddeHTMLModElement;
|
||||
"label": ddeHTMLLabelElement;
|
||||
"legend": ddeHTMLLegendElement;
|
||||
"li": ddeHTMLLIElement;
|
||||
"link": ddeHTMLLinkElement;
|
||||
"map": ddeHTMLMapElement;
|
||||
"menu": ddeHTMLMenuElement;
|
||||
"meta": ddeHTMLMetaElement;
|
||||
"meter": ddeHTMLMeterElement;
|
||||
"object": ddeHTMLObjectElement;
|
||||
"ol": ddeHTMLOListElement;
|
||||
"optgroup": ddeHTMLOptGroupElement;
|
||||
"option": ddeHTMLOptionElement;
|
||||
"output": ddeHTMLOutputElement;
|
||||
"p": ddeHTMLParagraphElement;
|
||||
"picture": ddeHTMLPictureElement;
|
||||
"pre": ddeHTMLPreElement;
|
||||
"progress": ddeHTMLProgressElement;
|
||||
"q": ddeHTMLQuoteElement;
|
||||
"script": ddeHTMLScriptElement;
|
||||
"select": ddeHTMLSelectElement;
|
||||
"slot": ddeHTMLSlotElement;
|
||||
"source": ddeHTMLSourceElement;
|
||||
"span": ddeHTMLSpanElement;
|
||||
"style": ddeHTMLStyleElement;
|
||||
"table": ddeHTMLTableElement;
|
||||
"tbody": ddeHTMLTableSectionElement;
|
||||
"td": ddeHTMLTableCellElement;
|
||||
"template": ddeHTMLTemplateElement;
|
||||
"textarea": ddeHTMLTextAreaElement;
|
||||
"tfoot": ddeHTMLTableSectionElement;
|
||||
"th": ddeHTMLTableCellElement;
|
||||
"thead": ddeHTMLTableSectionElement;
|
||||
"time": ddeHTMLTimeElement;
|
||||
"title": ddeHTMLTitleElement;
|
||||
"tr": ddeHTMLTableRowElement;
|
||||
"track": ddeHTMLTrackElement;
|
||||
"ul": ddeHTMLUListElement;
|
||||
"video": ddeHTMLVideoElement;
|
||||
}
|
||||
interface ddeSVGElementTagNameMap {
|
||||
"a": ddeSVGAElement;
|
||||
"animate": ddeSVGAnimateElement;
|
||||
"animateMotion": ddeSVGAnimateMotionElement;
|
||||
"animateTransform": ddeSVGAnimateTransformElement;
|
||||
"circle": ddeSVGCircleElement;
|
||||
"clipPath": ddeSVGClipPathElement;
|
||||
"defs": ddeSVGDefsElement;
|
||||
"desc": ddeSVGDescElement;
|
||||
"ellipse": ddeSVGEllipseElement;
|
||||
"feBlend": ddeSVGFEBlendElement;
|
||||
"feColorMatrix": ddeSVGFEColorMatrixElement;
|
||||
"feComponentTransfer": ddeSVGFEComponentTransferElement;
|
||||
"feComposite": ddeSVGFECompositeElement;
|
||||
"feConvolveMatrix": ddeSVGFEConvolveMatrixElement;
|
||||
"feDiffuseLighting": ddeSVGFEDiffuseLightingElement;
|
||||
"feDisplacementMap": ddeSVGFEDisplacementMapElement;
|
||||
"feDistantLight": ddeSVGFEDistantLightElement;
|
||||
"feDropShadow": ddeSVGFEDropShadowElement;
|
||||
"feFlood": ddeSVGFEFloodElement;
|
||||
"feFuncA": ddeSVGFEFuncAElement;
|
||||
"feFuncB": ddeSVGFEFuncBElement;
|
||||
"feFuncG": ddeSVGFEFuncGElement;
|
||||
"feFuncR": ddeSVGFEFuncRElement;
|
||||
"feGaussianBlur": ddeSVGFEGaussianBlurElement;
|
||||
"feImage": ddeSVGFEImageElement;
|
||||
"feMerge": ddeSVGFEMergeElement;
|
||||
"feMergeNode": ddeSVGFEMergeNodeElement;
|
||||
"feMorphology": ddeSVGFEMorphologyElement;
|
||||
"feOffset": ddeSVGFEOffsetElement;
|
||||
"fePointLight": ddeSVGFEPointLightElement;
|
||||
"feSpecularLighting": ddeSVGFESpecularLightingElement;
|
||||
"feSpotLight": ddeSVGFESpotLightElement;
|
||||
"feTile": ddeSVGFETileElement;
|
||||
"feTurbulence": ddeSVGFETurbulenceElement;
|
||||
"filter": ddeSVGFilterElement;
|
||||
"foreignObject": ddeSVGForeignObjectElement;
|
||||
"g": ddeSVGGElement;
|
||||
"image": ddeSVGImageElement;
|
||||
"line": ddeSVGLineElement;
|
||||
"linearGradient": ddeSVGLinearGradientElement;
|
||||
"marker": ddeSVGMarkerElement;
|
||||
"mask": ddeSVGMaskElement;
|
||||
"metadata": ddeSVGMetadataElement;
|
||||
"mpath": ddeSVGMPathElement;
|
||||
"path": ddeSVGPathElement;
|
||||
"pattern": ddeSVGPatternElement;
|
||||
"polygon": ddeSVGPolygonElement;
|
||||
"polyline": ddeSVGPolylineElement;
|
||||
"radialGradient": ddeSVGRadialGradientElement;
|
||||
"rect": ddeSVGRectElement;
|
||||
"script": ddeSVGScriptElement;
|
||||
"set": ddeSVGSetElement;
|
||||
"stop": ddeSVGStopElement;
|
||||
"style": ddeSVGStyleElement;
|
||||
"svg": ddeSVGSVGElement;
|
||||
"switch": ddeSVGSwitchElement;
|
||||
"symbol": ddeSVGSymbolElement;
|
||||
"text": ddeSVGTextElement;
|
||||
"textPath": ddeSVGTextPathElement;
|
||||
"title": ddeSVGTitleElement;
|
||||
"tspan": ddeSVGTSpanElement;
|
||||
"use": ddeSVGUseElement;
|
||||
"view": ddeSVGViewElement;
|
||||
}
|
||||
}
|
||||
|
||||
// editorconfig-checker-disable
|
||||
interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend<ddeHTMLAnchorElement>; }
|
||||
interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend<ddeHTMLAreaElement>; }
|
||||
interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend<ddeHTMLAudioElement>; }
|
||||
interface ddeHTMLBaseElement extends HTMLBaseElement{ append: ddeAppend<ddeHTMLBaseElement>; }
|
||||
interface ddeHTMLQuoteElement extends HTMLQuoteElement{ append: ddeAppend<ddeHTMLQuoteElement>; }
|
||||
interface ddeHTMLBodyElement extends HTMLBodyElement{ append: ddeAppend<ddeHTMLBodyElement>; }
|
||||
interface ddeHTMLBRElement extends HTMLBRElement{ append: ddeAppend<ddeHTMLBRElement>; }
|
||||
interface ddeHTMLButtonElement extends HTMLButtonElement{ append: ddeAppend<ddeHTMLButtonElement>; }
|
||||
interface ddeHTMLCanvasElement extends HTMLCanvasElement{ append: ddeAppend<ddeHTMLCanvasElement>; }
|
||||
interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement{ append: ddeAppend<ddeHTMLTableCaptionElement>; }
|
||||
interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend<ddeHTMLTableColElement>; }
|
||||
interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend<ddeHTMLTableColElement>; }
|
||||
interface ddeHTMLDataElement extends HTMLDataElement{ append: ddeAppend<ddeHTMLDataElement>; }
|
||||
interface ddeHTMLDataListElement extends HTMLDataListElement{ append: ddeAppend<ddeHTMLDataListElement>; }
|
||||
interface ddeHTMLModElement extends HTMLModElement{ append: ddeAppend<ddeHTMLModElement>; }
|
||||
interface ddeHTMLDetailsElement extends HTMLDetailsElement{ append: ddeAppend<ddeHTMLDetailsElement>; }
|
||||
interface ddeHTMLDialogElement extends HTMLDialogElement{ append: ddeAppend<ddeHTMLDialogElement>; }
|
||||
interface ddeHTMLDivElement extends HTMLDivElement{ append: ddeAppend<ddeHTMLDivElement>; }
|
||||
interface ddeHTMLDListElement extends HTMLDListElement{ append: ddeAppend<ddeHTMLDListElement>; }
|
||||
interface ddeHTMLEmbedElement extends HTMLEmbedElement{ append: ddeAppend<ddeHTMLEmbedElement>; }
|
||||
interface ddeHTMLFieldSetElement extends HTMLFieldSetElement{ append: ddeAppend<ddeHTMLFieldSetElement>; }
|
||||
interface ddeHTMLFormElement extends HTMLFormElement{ append: ddeAppend<ddeHTMLFormElement>; }
|
||||
interface ddeHTMLHeadingElement extends HTMLHeadingElement{ append: ddeAppend<ddeHTMLHeadingElement>; }
|
||||
interface ddeHTMLHeadElement extends HTMLHeadElement{ append: ddeAppend<ddeHTMLHeadElement>; }
|
||||
interface ddeHTMLHRElement extends HTMLHRElement{ append: ddeAppend<ddeHTMLHRElement>; }
|
||||
interface ddeHTMLHtmlElement extends HTMLHtmlElement{ append: ddeAppend<ddeHTMLHtmlElement>; }
|
||||
interface ddeHTMLIFrameElement extends HTMLIFrameElement{ append: ddeAppend<ddeHTMLIFrameElement>; }
|
||||
interface ddeHTMLImageElement extends HTMLImageElement{ append: ddeAppend<ddeHTMLImageElement>; }
|
||||
interface ddeHTMLInputElement extends HTMLInputElement{ append: ddeAppend<ddeHTMLInputElement>; }
|
||||
interface ddeHTMLLabelElement extends HTMLLabelElement{ append: ddeAppend<ddeHTMLLabelElement>; }
|
||||
interface ddeHTMLLegendElement extends HTMLLegendElement{ append: ddeAppend<ddeHTMLLegendElement>; }
|
||||
interface ddeHTMLLIElement extends HTMLLIElement{ append: ddeAppend<ddeHTMLLIElement>; }
|
||||
interface ddeHTMLLinkElement extends HTMLLinkElement{ append: ddeAppend<ddeHTMLLinkElement>; }
|
||||
interface ddeHTMLMapElement extends HTMLMapElement{ append: ddeAppend<ddeHTMLMapElement>; }
|
||||
interface ddeHTMLMenuElement extends HTMLMenuElement{ append: ddeAppend<ddeHTMLMenuElement>; }
|
||||
interface ddeHTMLMetaElement extends HTMLMetaElement{ append: ddeAppend<ddeHTMLMetaElement>; }
|
||||
interface ddeHTMLMeterElement extends HTMLMeterElement{ append: ddeAppend<ddeHTMLMeterElement>; }
|
||||
interface ddeHTMLObjectElement extends HTMLObjectElement{ append: ddeAppend<ddeHTMLObjectElement>; }
|
||||
interface ddeHTMLOListElement extends HTMLOListElement{ append: ddeAppend<ddeHTMLOListElement>; }
|
||||
interface ddeHTMLOptGroupElement extends HTMLOptGroupElement{ append: ddeAppend<ddeHTMLOptGroupElement>; }
|
||||
interface ddeHTMLOptionElement extends HTMLOptionElement{ append: ddeAppend<ddeHTMLOptionElement>; }
|
||||
interface ddeHTMLOutputElement extends HTMLOutputElement{ append: ddeAppend<ddeHTMLOutputElement>; }
|
||||
interface ddeHTMLParagraphElement extends HTMLParagraphElement{ append: ddeAppend<ddeHTMLParagraphElement>; }
|
||||
interface ddeHTMLPictureElement extends HTMLPictureElement{ append: ddeAppend<ddeHTMLPictureElement>; }
|
||||
interface ddeHTMLPreElement extends HTMLPreElement{ append: ddeAppend<ddeHTMLPreElement>; }
|
||||
interface ddeHTMLProgressElement extends HTMLProgressElement{ append: ddeAppend<ddeHTMLProgressElement>; }
|
||||
interface ddeHTMLScriptElement extends HTMLScriptElement{ append: ddeAppend<ddeHTMLScriptElement>; }
|
||||
interface ddeHTMLSelectElement extends HTMLSelectElement{ append: ddeAppend<ddeHTMLSelectElement>; }
|
||||
interface ddeHTMLSlotElement extends HTMLSlotElement{ append: ddeAppend<ddeHTMLSlotElement>; }
|
||||
interface ddeHTMLSourceElement extends HTMLSourceElement{ append: ddeAppend<ddeHTMLSourceElement>; }
|
||||
interface ddeHTMLSpanElement extends HTMLSpanElement{ append: ddeAppend<ddeHTMLSpanElement>; }
|
||||
interface ddeHTMLStyleElement extends HTMLStyleElement{ append: ddeAppend<ddeHTMLStyleElement>; }
|
||||
interface ddeHTMLTableElement extends HTMLTableElement{ append: ddeAppend<ddeHTMLTableElement>; }
|
||||
interface ddeHTMLTableSectionElement extends HTMLTableSectionElement{ append: ddeAppend<ddeHTMLTableSectionElement>; }
|
||||
interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend<ddeHTMLTableCellElement>; }
|
||||
interface ddeHTMLTemplateElement extends HTMLTemplateElement{ append: ddeAppend<ddeHTMLTemplateElement>; }
|
||||
interface ddeHTMLTextAreaElement extends HTMLTextAreaElement{ append: ddeAppend<ddeHTMLTextAreaElement>; }
|
||||
interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend<ddeHTMLTableCellElement>; }
|
||||
interface ddeHTMLTimeElement extends HTMLTimeElement{ append: ddeAppend<ddeHTMLTimeElement>; }
|
||||
interface ddeHTMLTitleElement extends HTMLTitleElement{ append: ddeAppend<ddeHTMLTitleElement>; }
|
||||
interface ddeHTMLTableRowElement extends HTMLTableRowElement{ append: ddeAppend<ddeHTMLTableRowElement>; }
|
||||
interface ddeHTMLTrackElement extends HTMLTrackElement{ append: ddeAppend<ddeHTMLTrackElement>; }
|
||||
interface ddeHTMLUListElement extends HTMLUListElement{ append: ddeAppend<ddeHTMLUListElement>; }
|
||||
interface ddeHTMLVideoElement extends HTMLVideoElement{ append: ddeAppend<ddeHTMLVideoElement>; }
|
||||
interface ddeSVGAElement extends SVGAElement{ append: ddeAppend<ddeSVGAElement>; }
|
||||
interface ddeSVGAnimateElement extends SVGAnimateElement{ append: ddeAppend<ddeSVGAnimateElement>; }
|
||||
interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement{ append: ddeAppend<ddeSVGAnimateMotionElement>; }
|
||||
interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement{ append: ddeAppend<ddeSVGAnimateTransformElement>; }
|
||||
interface ddeSVGCircleElement extends SVGCircleElement{ append: ddeAppend<ddeSVGCircleElement>; }
|
||||
interface ddeSVGClipPathElement extends SVGClipPathElement{ append: ddeAppend<ddeSVGClipPathElement>; }
|
||||
interface ddeSVGDefsElement extends SVGDefsElement{ append: ddeAppend<ddeSVGDefsElement>; }
|
||||
interface ddeSVGDescElement extends SVGDescElement{ append: ddeAppend<ddeSVGDescElement>; }
|
||||
interface ddeSVGEllipseElement extends SVGEllipseElement{ append: ddeAppend<ddeSVGEllipseElement>; }
|
||||
interface ddeSVGFEBlendElement extends SVGFEBlendElement{ append: ddeAppend<ddeSVGFEBlendElement>; }
|
||||
interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement{ append: ddeAppend<ddeSVGFEColorMatrixElement>; }
|
||||
interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement{ append: ddeAppend<ddeSVGFEComponentTransferElement>; }
|
||||
interface ddeSVGFECompositeElement extends SVGFECompositeElement{ append: ddeAppend<ddeSVGFECompositeElement>; }
|
||||
interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement{ append: ddeAppend<ddeSVGFEConvolveMatrixElement>; }
|
||||
interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement{ append: ddeAppend<ddeSVGFEDiffuseLightingElement>; }
|
||||
interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement{ append: ddeAppend<ddeSVGFEDisplacementMapElement>; }
|
||||
interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement{ append: ddeAppend<ddeSVGFEDistantLightElement>; }
|
||||
interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement{ append: ddeAppend<ddeSVGFEDropShadowElement>; }
|
||||
interface ddeSVGFEFloodElement extends SVGFEFloodElement{ append: ddeAppend<ddeSVGFEFloodElement>; }
|
||||
interface ddeSVGFEFuncAElement extends SVGFEFuncAElement{ append: ddeAppend<ddeSVGFEFuncAElement>; }
|
||||
interface ddeSVGFEFuncBElement extends SVGFEFuncBElement{ append: ddeAppend<ddeSVGFEFuncBElement>; }
|
||||
interface ddeSVGFEFuncGElement extends SVGFEFuncGElement{ append: ddeAppend<ddeSVGFEFuncGElement>; }
|
||||
interface ddeSVGFEFuncRElement extends SVGFEFuncRElement{ append: ddeAppend<ddeSVGFEFuncRElement>; }
|
||||
interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement{ append: ddeAppend<ddeSVGFEGaussianBlurElement>; }
|
||||
interface ddeSVGFEImageElement extends SVGFEImageElement{ append: ddeAppend<ddeSVGFEImageElement>; }
|
||||
interface ddeSVGFEMergeElement extends SVGFEMergeElement{ append: ddeAppend<ddeSVGFEMergeElement>; }
|
||||
interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement{ append: ddeAppend<ddeSVGFEMergeNodeElement>; }
|
||||
interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement{ append: ddeAppend<ddeSVGFEMorphologyElement>; }
|
||||
interface ddeSVGFEOffsetElement extends SVGFEOffsetElement{ append: ddeAppend<ddeSVGFEOffsetElement>; }
|
||||
interface ddeSVGFEPointLightElement extends SVGFEPointLightElement{ append: ddeAppend<ddeSVGFEPointLightElement>; }
|
||||
interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement{ append: ddeAppend<ddeSVGFESpecularLightingElement>; }
|
||||
interface ddeSVGFESpotLightElement extends SVGFESpotLightElement{ append: ddeAppend<ddeSVGFESpotLightElement>; }
|
||||
interface ddeSVGFETileElement extends SVGFETileElement{ append: ddeAppend<ddeSVGFETileElement>; }
|
||||
interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement{ append: ddeAppend<ddeSVGFETurbulenceElement>; }
|
||||
interface ddeSVGFilterElement extends SVGFilterElement{ append: ddeAppend<ddeSVGFilterElement>; }
|
||||
interface ddeSVGForeignObjectElement extends SVGForeignObjectElement{ append: ddeAppend<ddeSVGForeignObjectElement>; }
|
||||
interface ddeSVGGElement extends SVGGElement{ append: ddeAppend<ddeSVGGElement>; }
|
||||
interface ddeSVGImageElement extends SVGImageElement{ append: ddeAppend<ddeSVGImageElement>; }
|
||||
interface ddeSVGLineElement extends SVGLineElement{ append: ddeAppend<ddeSVGLineElement>; }
|
||||
interface ddeSVGLinearGradientElement extends SVGLinearGradientElement{ append: ddeAppend<ddeSVGLinearGradientElement>; }
|
||||
interface ddeSVGMarkerElement extends SVGMarkerElement{ append: ddeAppend<ddeSVGMarkerElement>; }
|
||||
interface ddeSVGMaskElement extends SVGMaskElement{ append: ddeAppend<ddeSVGMaskElement>; }
|
||||
interface ddeSVGMetadataElement extends SVGMetadataElement{ append: ddeAppend<ddeSVGMetadataElement>; }
|
||||
interface ddeSVGMPathElement extends SVGMPathElement{ append: ddeAppend<ddeSVGMPathElement>; }
|
||||
interface ddeSVGPathElement extends SVGPathElement{ append: ddeAppend<ddeSVGPathElement>; }
|
||||
interface ddeSVGPatternElement extends SVGPatternElement{ append: ddeAppend<ddeSVGPatternElement>; }
|
||||
interface ddeSVGPolygonElement extends SVGPolygonElement{ append: ddeAppend<ddeSVGPolygonElement>; }
|
||||
interface ddeSVGPolylineElement extends SVGPolylineElement{ append: ddeAppend<ddeSVGPolylineElement>; }
|
||||
interface ddeSVGRadialGradientElement extends SVGRadialGradientElement{ append: ddeAppend<ddeSVGRadialGradientElement>; }
|
||||
interface ddeSVGRectElement extends SVGRectElement{ append: ddeAppend<ddeSVGRectElement>; }
|
||||
interface ddeSVGScriptElement extends SVGScriptElement{ append: ddeAppend<ddeSVGScriptElement>; }
|
||||
interface ddeSVGSetElement extends SVGSetElement{ append: ddeAppend<ddeSVGSetElement>; }
|
||||
interface ddeSVGStopElement extends SVGStopElement{ append: ddeAppend<ddeSVGStopElement>; }
|
||||
interface ddeSVGStyleElement extends SVGStyleElement{ append: ddeAppend<ddeSVGStyleElement>; }
|
||||
interface ddeSVGSVGElement extends SVGSVGElement{ append: ddeAppend<ddeSVGSVGElement>; }
|
||||
interface ddeSVGSwitchElement extends SVGSwitchElement{ append: ddeAppend<ddeSVGSwitchElement>; }
|
||||
interface ddeSVGSymbolElement extends SVGSymbolElement{ append: ddeAppend<ddeSVGSymbolElement>; }
|
||||
interface ddeSVGTextElement extends SVGTextElement{ append: ddeAppend<ddeSVGTextElement>; }
|
||||
interface ddeSVGTextPathElement extends SVGTextPathElement{ append: ddeAppend<ddeSVGTextPathElement>; }
|
||||
interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend<ddeSVGTitleElement>; }
|
||||
interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend<ddeSVGTSpanElement>; }
|
||||
interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend<ddeSVGUseElement>; }
|
||||
interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend<ddeSVGViewElement>; }
|
||||
// editorconfig-checker-enable
|
905
dist/esm.d.ts
vendored
905
dist/esm.d.ts
vendored
@ -1,46 +1,118 @@
|
||||
declare global{ /* ddeSignal */ }
|
||||
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
||||
type SupportedElement=
|
||||
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
||||
| SVGElementTagNameMap[keyof SVGElementTagNameMap]
|
||||
| MathMLElementTagNameMap[keyof MathMLElementTagNameMap]
|
||||
| CustomElementTagNameMap[keyof CustomElementTagNameMap]
|
||||
declare global {
|
||||
type ddeComponentAttributes= Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node>= (element: El)=> any;
|
||||
type ddeString= string | ddeSignal<string>
|
||||
type ddeStringable= ddeString | number | ddeSignal<number>
|
||||
// Generated by dts-bundle-generator v9.5.1
|
||||
|
||||
export interface Signal<V, A> {
|
||||
/** The current value of the signal */
|
||||
get(): V;
|
||||
/** Set new value of the signal */
|
||||
set(value: V): V;
|
||||
toJSON(): V;
|
||||
valueOf(): V;
|
||||
}
|
||||
type PascalCase=
|
||||
`${Capitalize<string>}${string}`;
|
||||
type AttrsModified= {
|
||||
export type Action<V> = (this: {
|
||||
value: V;
|
||||
stopPropagation(): void;
|
||||
}, ...a: any[]) => typeof signal._ | void;
|
||||
//type SymbolSignal= Symbol;
|
||||
export type SymbolOnclear = symbol;
|
||||
export type Actions<V> = Record<string | SymbolOnclear, Action<V>>;
|
||||
export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & {
|
||||
first_time?: boolean;
|
||||
};
|
||||
export interface signal {
|
||||
_: Symbol;
|
||||
/**
|
||||
* Computations signal. This creates a signal which is computed from other signals.
|
||||
* */
|
||||
<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>;
|
||||
/**
|
||||
* Simple example:
|
||||
* ```js
|
||||
* const hello= S("Hello Signal");
|
||||
* ```
|
||||
* …simple todo signal:
|
||||
* ```js
|
||||
* const todos= S([], {
|
||||
* add(v){ this.value.push(S(v)); },
|
||||
* remove(i){ this.value.splice(i, 1); },
|
||||
* [S.symbols.onclear](){ S.clear(...this.value); },
|
||||
* });
|
||||
* ```
|
||||
* …computed signal:
|
||||
* ```js
|
||||
* const name= S("Jan");
|
||||
* const surname= S("Andrle");
|
||||
* const fullname= S(()=> name.get()+" "+surname.get());
|
||||
* ```
|
||||
* @param value Initial signal value. Or function computing value from other signals.
|
||||
* @param actions Use to define actions on the signal. Such as add item to the array.
|
||||
* There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared
|
||||
* by `S.clear`.
|
||||
* */
|
||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void;
|
||||
clear(...signals: Signal<any, any>[]): void;
|
||||
on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void;
|
||||
symbols: {
|
||||
//signal: SymbolSignal;
|
||||
onclear: SymbolOnclear;
|
||||
};
|
||||
/**
|
||||
* Reactive element, which is rendered based on the given signal.
|
||||
* ```js
|
||||
* S.el(signal, value=> value ? el("b", "True") : el("i", "False"));
|
||||
* S.el(listS, list=> list.map(li=> el("li", li)));
|
||||
* ```
|
||||
* */
|
||||
el<S extends any>(signal: Signal<S, any>, el: (v: S) => Element | Element[] | DocumentFragment): DocumentFragment;
|
||||
observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>;
|
||||
}
|
||||
declare const signal: signal;
|
||||
declare global {
|
||||
type ddeSignal<T, A = {}> = Signal<T, A>;
|
||||
type ddeAction<V> = Action<V>;
|
||||
type ddeActions<V> = Actions<V>;
|
||||
}
|
||||
export type CustomElementTagNameMap = {
|
||||
"#text": Text;
|
||||
"#comment": Comment;
|
||||
};
|
||||
export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
||||
declare global {
|
||||
type ddeComponentAttributes = Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El) => any;
|
||||
type ddeString = string | Signal<string, {}>;
|
||||
type ddeStringable = ddeString | number | Signal<number, {}>;
|
||||
}
|
||||
export type PascalCase = `${Capitalize<string>}${string}`;
|
||||
export type AttrsModified = {
|
||||
/**
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString
|
||||
| Partial<{ [K in keyof CSSStyleDeclaration]: ddeSignal<CSSStyleDeclaration[K]> }>
|
||||
style: Partial<CSSStyleDeclaration> | ddeString | Partial<{
|
||||
[K in keyof CSSStyleDeclaration]: Signal<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.
|
||||
*/
|
||||
classList: Record<string,-1|0|1|boolean|ddeSignal<-1|0|1|boolean>>,
|
||||
classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>;
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap)
|
||||
* */
|
||||
dataset: Record<string, ddeStringable>,
|
||||
dataset: Record<string, ddeStringable>;
|
||||
/**
|
||||
* Sets `aria-*` simiraly to `dataset`
|
||||
* */
|
||||
ariaset: Record<string, ddeString>,
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString>
|
||||
& Record<`.${string}`, any>
|
||||
type _fromElsInterfaces<EL extends SupportedElement>= Omit<EL, keyof AttrsModified>;
|
||||
type IsReadonly<T, K extends keyof T> =
|
||||
T extends { readonly [P in K]: T[K] } ? true : false;
|
||||
ariaset: Record<string, ddeString>;
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>;
|
||||
export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>;
|
||||
export type IsReadonly<T, K extends keyof T> = T extends {
|
||||
readonly [P in K]: T[K];
|
||||
} ? true : false;
|
||||
/**
|
||||
* Just element attributtes
|
||||
*
|
||||
@ -51,199 +123,132 @@ type IsReadonly<T, K extends keyof T> =
|
||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||
* @private
|
||||
*/
|
||||
type ElementAttributes<T extends SupportedElement>= Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]: IsReadonly<_fromElsInterfaces<T>, K> extends false
|
||||
? _fromElsInterfaces<T>[K] | ddeSignal<_fromElsInterfaces<T>[K]>
|
||||
: ddeStringable
|
||||
export type ElementAttributes<T extends SupportedElement> = Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable);
|
||||
} & 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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(
|
||||
element: El,
|
||||
attr: ATT,
|
||||
value: ElementAttributes<El>[ATT]
|
||||
): ElementAttributes<El>[ATT]
|
||||
|
||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export function el<
|
||||
TAG extends keyof ExtendedHTMLElementTagNameMap,
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable,
|
||||
...addons: ddeElementAddon<
|
||||
ExtendedHTMLElementTagNameMap[NoInfer<TAG>]
|
||||
>[], // TODO: for now addons must have the same element
|
||||
): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement
|
||||
export function el(
|
||||
tag_name?: "<>",
|
||||
): ddeDocumentFragment
|
||||
export function el(
|
||||
tag_name: string,
|
||||
attrs?: ElementAttributes<HTMLElement> | ddeStringable,
|
||||
...addons: ddeElementAddon<HTMLElement>[]
|
||||
): ddeHTMLElement
|
||||
|
||||
export function el<
|
||||
C extends (attr: ddeComponentAttributes)=> SupportedElement | ddeDocumentFragment
|
||||
>(
|
||||
component: C,
|
||||
attrs?: Parameters<C>[0] | ddeStringable,
|
||||
...addons: ddeElementAddon<ReturnType<C>>[]
|
||||
): ReturnType<C> extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap]
|
||||
? ReturnType<C>
|
||||
: ( ReturnType<C> extends ddeDocumentFragment ? ReturnType<C> : ddeHTMLElement )
|
||||
export { el as createElement }
|
||||
|
||||
export function elNS(
|
||||
namespace: "http://www.w3.org/2000/svg"
|
||||
): <
|
||||
TAG extends keyof SVGElementTagNameMap & string,
|
||||
EL extends ( TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement ),
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable,
|
||||
...addons: ddeElementAddon<NoInfer<EL>>[]
|
||||
)=> TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement
|
||||
export function elNS(
|
||||
namespace: "http://www.w3.org/1998/Math/MathML"
|
||||
): <
|
||||
TAG extends keyof MathMLElementTagNameMap & string,
|
||||
EL extends ( TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement ),
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | ddeSignal<EL[key]> | string | number | boolean
|
||||
}>,
|
||||
...addons: ddeElementAddon<NoInfer<EL>>[]
|
||||
)=> ddeMathMLElement
|
||||
export function elNS(
|
||||
namespace: string
|
||||
): (
|
||||
tag_name: string,
|
||||
attrs?: string | ddeStringable | Record<string, any>,
|
||||
...addons: ddeElementAddon<SupportedElement>[]
|
||||
)=> SupportedElement
|
||||
export { elNS as createElementNS }
|
||||
|
||||
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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT];
|
||||
export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(attrs: {
|
||||
type: "component" | "reactive" | "later";
|
||||
name?: string;
|
||||
host?: "this" | "parentElement";
|
||||
}, is_open?: boolean): Comment;
|
||||
}
|
||||
export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<A extends {
|
||||
textContent: ddeStringable;
|
||||
}, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement;
|
||||
export function el(tag_name?: "<>"): ddeDocumentFragment;
|
||||
export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement;
|
||||
export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement;
|
||||
export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean;
|
||||
}>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement;
|
||||
export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement;
|
||||
export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
||||
/** Simulate slots for ddeComponents */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(
|
||||
root: EL,
|
||||
): EL
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL;
|
||||
/**
|
||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||
* @param el Custom Element root element
|
||||
* @param body Body of the custom element
|
||||
* */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(
|
||||
el: HTMLElement,
|
||||
body: EL,
|
||||
): EL
|
||||
|
||||
export function dispatchEvent(name: keyof DocumentEventMap | string, options?: EventInit):
|
||||
(element: SupportedElement, data?: any)=> void;
|
||||
export function dispatchEvent(
|
||||
name: keyof DocumentEventMap | string,
|
||||
options: EventInit | null,
|
||||
element: SupportedElement | (()=> SupportedElement)
|
||||
): (data?: any)=> void;
|
||||
interface On{
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, element: SupportedElement): (data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, element: SupportedElement | (() => SupportedElement)): (data?: any) => void;
|
||||
export interface On {
|
||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||
<
|
||||
Event extends keyof DocumentEventMap,
|
||||
EE extends ddeElementAddon<SupportedElement>= ddeElementAddon<HTMLElement>,
|
||||
>(
|
||||
type: Event,
|
||||
listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : EE;
|
||||
<
|
||||
EE extends ddeElementAddon<SupportedElement>= ddeElementAddon<HTMLElement>,
|
||||
>(
|
||||
type: string,
|
||||
listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent ) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : 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 */// editorconfig-checker-disable-line
|
||||
connected<
|
||||
EE extends ddeElementAddon<SupportedElement>,
|
||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||
>(
|
||||
listener: (this: El, event: CustomEvent<El>) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : 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 */// editorconfig-checker-disable-line
|
||||
disconnected<
|
||||
EE extends ddeElementAddon<SupportedElement>,
|
||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||
>(
|
||||
listener: (this: El, event: CustomEvent<void>) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : 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 */// editorconfig-checker-disable-line
|
||||
attributeChanged<
|
||||
EE extends ddeElementAddon<SupportedElement>,
|
||||
El extends ( EE extends ddeElementAddon<infer El> ? El : never )
|
||||
>(
|
||||
listener: (this: El, event: CustomEvent<[ string, string ]>) => any,
|
||||
options?: AddEventListenerOptions
|
||||
) : EE;
|
||||
<Event extends keyof DocumentEventMap, EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: Event, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any, options?: AddEventListenerOptions): EE;
|
||||
<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
connected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<El>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
disconnected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
attributeChanged<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<[
|
||||
string,
|
||||
string
|
||||
]>) => any, options?: AddEventListenerOptions): EE;
|
||||
}
|
||||
export const on: On;
|
||||
|
||||
type Scope= {
|
||||
scope: Node | Function | Object,
|
||||
host: ddeElementAddon<any>,
|
||||
custom_element: false | HTMLElement,
|
||||
prevent: boolean
|
||||
export 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}) */
|
||||
export const scope: {
|
||||
current: Scope,
|
||||
current: Scope;
|
||||
/** Stops all automatizations. E. g. signals used as attributes in current scope
|
||||
* registers removing these listeners (and clean signal if no other listeners are detected)
|
||||
* on `disconnected` event. */
|
||||
preventDefault<T extends boolean>(prevent: T): T,
|
||||
preventDefault<T extends boolean>(prevent: T): T;
|
||||
/**
|
||||
* This represents reference to the current host element — `scope.host()`.
|
||||
* It can be also used to register Addon(s) (functions to be called when component is initized)
|
||||
* — `scope.host(on.connected(console.log))`.
|
||||
* */
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[])=> HTMLElement,
|
||||
|
||||
state: Scope[],
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||
state: Scope[];
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope: Partial<Scope>): ReturnType<Array<Scope>["push"]>,
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>,
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>;
|
||||
/** Removes last/current child scope. */
|
||||
pop(): ReturnType<Array<Scope>["pop"]>,
|
||||
pop(): ReturnType<Array<Scope>["pop"]>;
|
||||
};
|
||||
|
||||
export function customElementRender<
|
||||
EL extends HTMLElement,
|
||||
P extends any = Record<string, string | ddeSignal<string>>
|
||||
>(
|
||||
target: ShadowRoot | EL,
|
||||
render: (props: P)=> SupportedElement | DocumentFragment,
|
||||
props?: P | ((el: EL)=> P)
|
||||
): EL
|
||||
export function customElementWithDDE<EL extends (new ()=> HTMLElement)>(custom_element: EL): EL
|
||||
export function lifecyclesToEvents<EL extends (new ()=> HTMLElement)>(custom_element: EL): EL
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>
|
||||
|
||||
export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL;
|
||||
export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>;
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
/* TypeScript MEH */
|
||||
declare global{
|
||||
type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
|
||||
|
||||
interface ddeDocumentFragment extends DocumentFragment{ append: ddeAppend<ddeDocumentFragment>; }
|
||||
interface ddeHTMLElement extends HTMLElement{ append: ddeAppend<ddeHTMLElement>; }
|
||||
interface ddeSVGElement extends SVGElement{ append: ddeAppend<ddeSVGElement>; }
|
||||
interface ddeMathMLElement extends MathMLElement{ append: ddeAppend<ddeMathMLElement>; }
|
||||
|
||||
declare global {
|
||||
type ddeAppend<el> = (...nodes: (Node | string)[]) => el;
|
||||
interface ddeDocumentFragment extends DocumentFragment {
|
||||
append: ddeAppend<ddeDocumentFragment>;
|
||||
}
|
||||
interface ddeHTMLElement extends HTMLElement {
|
||||
append: ddeAppend<ddeHTMLElement>;
|
||||
}
|
||||
interface ddeSVGElement extends SVGElement {
|
||||
append: ddeAppend<ddeSVGElement>;
|
||||
}
|
||||
interface ddeMathMLElement extends MathMLElement {
|
||||
append: ddeAppend<ddeMathMLElement>;
|
||||
}
|
||||
interface ddeHTMLElementTagNameMap {
|
||||
"a": ddeHTMLAnchorElement;
|
||||
"area": ddeHTMLAreaElement;
|
||||
@ -385,133 +390,393 @@ declare global{
|
||||
"view": ddeSVGViewElement;
|
||||
}
|
||||
}
|
||||
|
||||
// editorconfig-checker-disable
|
||||
interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend<ddeHTMLAnchorElement>; }
|
||||
interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend<ddeHTMLAreaElement>; }
|
||||
interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend<ddeHTMLAudioElement>; }
|
||||
interface ddeHTMLBaseElement extends HTMLBaseElement{ append: ddeAppend<ddeHTMLBaseElement>; }
|
||||
interface ddeHTMLQuoteElement extends HTMLQuoteElement{ append: ddeAppend<ddeHTMLQuoteElement>; }
|
||||
interface ddeHTMLBodyElement extends HTMLBodyElement{ append: ddeAppend<ddeHTMLBodyElement>; }
|
||||
interface ddeHTMLBRElement extends HTMLBRElement{ append: ddeAppend<ddeHTMLBRElement>; }
|
||||
interface ddeHTMLButtonElement extends HTMLButtonElement{ append: ddeAppend<ddeHTMLButtonElement>; }
|
||||
interface ddeHTMLCanvasElement extends HTMLCanvasElement{ append: ddeAppend<ddeHTMLCanvasElement>; }
|
||||
interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement{ append: ddeAppend<ddeHTMLTableCaptionElement>; }
|
||||
interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend<ddeHTMLTableColElement>; }
|
||||
interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend<ddeHTMLTableColElement>; }
|
||||
interface ddeHTMLDataElement extends HTMLDataElement{ append: ddeAppend<ddeHTMLDataElement>; }
|
||||
interface ddeHTMLDataListElement extends HTMLDataListElement{ append: ddeAppend<ddeHTMLDataListElement>; }
|
||||
interface ddeHTMLModElement extends HTMLModElement{ append: ddeAppend<ddeHTMLModElement>; }
|
||||
interface ddeHTMLDetailsElement extends HTMLDetailsElement{ append: ddeAppend<ddeHTMLDetailsElement>; }
|
||||
interface ddeHTMLDialogElement extends HTMLDialogElement{ append: ddeAppend<ddeHTMLDialogElement>; }
|
||||
interface ddeHTMLDivElement extends HTMLDivElement{ append: ddeAppend<ddeHTMLDivElement>; }
|
||||
interface ddeHTMLDListElement extends HTMLDListElement{ append: ddeAppend<ddeHTMLDListElement>; }
|
||||
interface ddeHTMLEmbedElement extends HTMLEmbedElement{ append: ddeAppend<ddeHTMLEmbedElement>; }
|
||||
interface ddeHTMLFieldSetElement extends HTMLFieldSetElement{ append: ddeAppend<ddeHTMLFieldSetElement>; }
|
||||
interface ddeHTMLFormElement extends HTMLFormElement{ append: ddeAppend<ddeHTMLFormElement>; }
|
||||
interface ddeHTMLHeadingElement extends HTMLHeadingElement{ append: ddeAppend<ddeHTMLHeadingElement>; }
|
||||
interface ddeHTMLHeadElement extends HTMLHeadElement{ append: ddeAppend<ddeHTMLHeadElement>; }
|
||||
interface ddeHTMLHRElement extends HTMLHRElement{ append: ddeAppend<ddeHTMLHRElement>; }
|
||||
interface ddeHTMLHtmlElement extends HTMLHtmlElement{ append: ddeAppend<ddeHTMLHtmlElement>; }
|
||||
interface ddeHTMLIFrameElement extends HTMLIFrameElement{ append: ddeAppend<ddeHTMLIFrameElement>; }
|
||||
interface ddeHTMLImageElement extends HTMLImageElement{ append: ddeAppend<ddeHTMLImageElement>; }
|
||||
interface ddeHTMLInputElement extends HTMLInputElement{ append: ddeAppend<ddeHTMLInputElement>; }
|
||||
interface ddeHTMLLabelElement extends HTMLLabelElement{ append: ddeAppend<ddeHTMLLabelElement>; }
|
||||
interface ddeHTMLLegendElement extends HTMLLegendElement{ append: ddeAppend<ddeHTMLLegendElement>; }
|
||||
interface ddeHTMLLIElement extends HTMLLIElement{ append: ddeAppend<ddeHTMLLIElement>; }
|
||||
interface ddeHTMLLinkElement extends HTMLLinkElement{ append: ddeAppend<ddeHTMLLinkElement>; }
|
||||
interface ddeHTMLMapElement extends HTMLMapElement{ append: ddeAppend<ddeHTMLMapElement>; }
|
||||
interface ddeHTMLMenuElement extends HTMLMenuElement{ append: ddeAppend<ddeHTMLMenuElement>; }
|
||||
interface ddeHTMLMetaElement extends HTMLMetaElement{ append: ddeAppend<ddeHTMLMetaElement>; }
|
||||
interface ddeHTMLMeterElement extends HTMLMeterElement{ append: ddeAppend<ddeHTMLMeterElement>; }
|
||||
interface ddeHTMLObjectElement extends HTMLObjectElement{ append: ddeAppend<ddeHTMLObjectElement>; }
|
||||
interface ddeHTMLOListElement extends HTMLOListElement{ append: ddeAppend<ddeHTMLOListElement>; }
|
||||
interface ddeHTMLOptGroupElement extends HTMLOptGroupElement{ append: ddeAppend<ddeHTMLOptGroupElement>; }
|
||||
interface ddeHTMLOptionElement extends HTMLOptionElement{ append: ddeAppend<ddeHTMLOptionElement>; }
|
||||
interface ddeHTMLOutputElement extends HTMLOutputElement{ append: ddeAppend<ddeHTMLOutputElement>; }
|
||||
interface ddeHTMLParagraphElement extends HTMLParagraphElement{ append: ddeAppend<ddeHTMLParagraphElement>; }
|
||||
interface ddeHTMLPictureElement extends HTMLPictureElement{ append: ddeAppend<ddeHTMLPictureElement>; }
|
||||
interface ddeHTMLPreElement extends HTMLPreElement{ append: ddeAppend<ddeHTMLPreElement>; }
|
||||
interface ddeHTMLProgressElement extends HTMLProgressElement{ append: ddeAppend<ddeHTMLProgressElement>; }
|
||||
interface ddeHTMLScriptElement extends HTMLScriptElement{ append: ddeAppend<ddeHTMLScriptElement>; }
|
||||
interface ddeHTMLSelectElement extends HTMLSelectElement{ append: ddeAppend<ddeHTMLSelectElement>; }
|
||||
interface ddeHTMLSlotElement extends HTMLSlotElement{ append: ddeAppend<ddeHTMLSlotElement>; }
|
||||
interface ddeHTMLSourceElement extends HTMLSourceElement{ append: ddeAppend<ddeHTMLSourceElement>; }
|
||||
interface ddeHTMLSpanElement extends HTMLSpanElement{ append: ddeAppend<ddeHTMLSpanElement>; }
|
||||
interface ddeHTMLStyleElement extends HTMLStyleElement{ append: ddeAppend<ddeHTMLStyleElement>; }
|
||||
interface ddeHTMLTableElement extends HTMLTableElement{ append: ddeAppend<ddeHTMLTableElement>; }
|
||||
interface ddeHTMLTableSectionElement extends HTMLTableSectionElement{ append: ddeAppend<ddeHTMLTableSectionElement>; }
|
||||
interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend<ddeHTMLTableCellElement>; }
|
||||
interface ddeHTMLTemplateElement extends HTMLTemplateElement{ append: ddeAppend<ddeHTMLTemplateElement>; }
|
||||
interface ddeHTMLTextAreaElement extends HTMLTextAreaElement{ append: ddeAppend<ddeHTMLTextAreaElement>; }
|
||||
interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend<ddeHTMLTableCellElement>; }
|
||||
interface ddeHTMLTimeElement extends HTMLTimeElement{ append: ddeAppend<ddeHTMLTimeElement>; }
|
||||
interface ddeHTMLTitleElement extends HTMLTitleElement{ append: ddeAppend<ddeHTMLTitleElement>; }
|
||||
interface ddeHTMLTableRowElement extends HTMLTableRowElement{ append: ddeAppend<ddeHTMLTableRowElement>; }
|
||||
interface ddeHTMLTrackElement extends HTMLTrackElement{ append: ddeAppend<ddeHTMLTrackElement>; }
|
||||
interface ddeHTMLUListElement extends HTMLUListElement{ append: ddeAppend<ddeHTMLUListElement>; }
|
||||
interface ddeHTMLVideoElement extends HTMLVideoElement{ append: ddeAppend<ddeHTMLVideoElement>; }
|
||||
interface ddeSVGAElement extends SVGAElement{ append: ddeAppend<ddeSVGAElement>; }
|
||||
interface ddeSVGAnimateElement extends SVGAnimateElement{ append: ddeAppend<ddeSVGAnimateElement>; }
|
||||
interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement{ append: ddeAppend<ddeSVGAnimateMotionElement>; }
|
||||
interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement{ append: ddeAppend<ddeSVGAnimateTransformElement>; }
|
||||
interface ddeSVGCircleElement extends SVGCircleElement{ append: ddeAppend<ddeSVGCircleElement>; }
|
||||
interface ddeSVGClipPathElement extends SVGClipPathElement{ append: ddeAppend<ddeSVGClipPathElement>; }
|
||||
interface ddeSVGDefsElement extends SVGDefsElement{ append: ddeAppend<ddeSVGDefsElement>; }
|
||||
interface ddeSVGDescElement extends SVGDescElement{ append: ddeAppend<ddeSVGDescElement>; }
|
||||
interface ddeSVGEllipseElement extends SVGEllipseElement{ append: ddeAppend<ddeSVGEllipseElement>; }
|
||||
interface ddeSVGFEBlendElement extends SVGFEBlendElement{ append: ddeAppend<ddeSVGFEBlendElement>; }
|
||||
interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement{ append: ddeAppend<ddeSVGFEColorMatrixElement>; }
|
||||
interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement{ append: ddeAppend<ddeSVGFEComponentTransferElement>; }
|
||||
interface ddeSVGFECompositeElement extends SVGFECompositeElement{ append: ddeAppend<ddeSVGFECompositeElement>; }
|
||||
interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement{ append: ddeAppend<ddeSVGFEConvolveMatrixElement>; }
|
||||
interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement{ append: ddeAppend<ddeSVGFEDiffuseLightingElement>; }
|
||||
interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement{ append: ddeAppend<ddeSVGFEDisplacementMapElement>; }
|
||||
interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement{ append: ddeAppend<ddeSVGFEDistantLightElement>; }
|
||||
interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement{ append: ddeAppend<ddeSVGFEDropShadowElement>; }
|
||||
interface ddeSVGFEFloodElement extends SVGFEFloodElement{ append: ddeAppend<ddeSVGFEFloodElement>; }
|
||||
interface ddeSVGFEFuncAElement extends SVGFEFuncAElement{ append: ddeAppend<ddeSVGFEFuncAElement>; }
|
||||
interface ddeSVGFEFuncBElement extends SVGFEFuncBElement{ append: ddeAppend<ddeSVGFEFuncBElement>; }
|
||||
interface ddeSVGFEFuncGElement extends SVGFEFuncGElement{ append: ddeAppend<ddeSVGFEFuncGElement>; }
|
||||
interface ddeSVGFEFuncRElement extends SVGFEFuncRElement{ append: ddeAppend<ddeSVGFEFuncRElement>; }
|
||||
interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement{ append: ddeAppend<ddeSVGFEGaussianBlurElement>; }
|
||||
interface ddeSVGFEImageElement extends SVGFEImageElement{ append: ddeAppend<ddeSVGFEImageElement>; }
|
||||
interface ddeSVGFEMergeElement extends SVGFEMergeElement{ append: ddeAppend<ddeSVGFEMergeElement>; }
|
||||
interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement{ append: ddeAppend<ddeSVGFEMergeNodeElement>; }
|
||||
interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement{ append: ddeAppend<ddeSVGFEMorphologyElement>; }
|
||||
interface ddeSVGFEOffsetElement extends SVGFEOffsetElement{ append: ddeAppend<ddeSVGFEOffsetElement>; }
|
||||
interface ddeSVGFEPointLightElement extends SVGFEPointLightElement{ append: ddeAppend<ddeSVGFEPointLightElement>; }
|
||||
interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement{ append: ddeAppend<ddeSVGFESpecularLightingElement>; }
|
||||
interface ddeSVGFESpotLightElement extends SVGFESpotLightElement{ append: ddeAppend<ddeSVGFESpotLightElement>; }
|
||||
interface ddeSVGFETileElement extends SVGFETileElement{ append: ddeAppend<ddeSVGFETileElement>; }
|
||||
interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement{ append: ddeAppend<ddeSVGFETurbulenceElement>; }
|
||||
interface ddeSVGFilterElement extends SVGFilterElement{ append: ddeAppend<ddeSVGFilterElement>; }
|
||||
interface ddeSVGForeignObjectElement extends SVGForeignObjectElement{ append: ddeAppend<ddeSVGForeignObjectElement>; }
|
||||
interface ddeSVGGElement extends SVGGElement{ append: ddeAppend<ddeSVGGElement>; }
|
||||
interface ddeSVGImageElement extends SVGImageElement{ append: ddeAppend<ddeSVGImageElement>; }
|
||||
interface ddeSVGLineElement extends SVGLineElement{ append: ddeAppend<ddeSVGLineElement>; }
|
||||
interface ddeSVGLinearGradientElement extends SVGLinearGradientElement{ append: ddeAppend<ddeSVGLinearGradientElement>; }
|
||||
interface ddeSVGMarkerElement extends SVGMarkerElement{ append: ddeAppend<ddeSVGMarkerElement>; }
|
||||
interface ddeSVGMaskElement extends SVGMaskElement{ append: ddeAppend<ddeSVGMaskElement>; }
|
||||
interface ddeSVGMetadataElement extends SVGMetadataElement{ append: ddeAppend<ddeSVGMetadataElement>; }
|
||||
interface ddeSVGMPathElement extends SVGMPathElement{ append: ddeAppend<ddeSVGMPathElement>; }
|
||||
interface ddeSVGPathElement extends SVGPathElement{ append: ddeAppend<ddeSVGPathElement>; }
|
||||
interface ddeSVGPatternElement extends SVGPatternElement{ append: ddeAppend<ddeSVGPatternElement>; }
|
||||
interface ddeSVGPolygonElement extends SVGPolygonElement{ append: ddeAppend<ddeSVGPolygonElement>; }
|
||||
interface ddeSVGPolylineElement extends SVGPolylineElement{ append: ddeAppend<ddeSVGPolylineElement>; }
|
||||
interface ddeSVGRadialGradientElement extends SVGRadialGradientElement{ append: ddeAppend<ddeSVGRadialGradientElement>; }
|
||||
interface ddeSVGRectElement extends SVGRectElement{ append: ddeAppend<ddeSVGRectElement>; }
|
||||
interface ddeSVGScriptElement extends SVGScriptElement{ append: ddeAppend<ddeSVGScriptElement>; }
|
||||
interface ddeSVGSetElement extends SVGSetElement{ append: ddeAppend<ddeSVGSetElement>; }
|
||||
interface ddeSVGStopElement extends SVGStopElement{ append: ddeAppend<ddeSVGStopElement>; }
|
||||
interface ddeSVGStyleElement extends SVGStyleElement{ append: ddeAppend<ddeSVGStyleElement>; }
|
||||
interface ddeSVGSVGElement extends SVGSVGElement{ append: ddeAppend<ddeSVGSVGElement>; }
|
||||
interface ddeSVGSwitchElement extends SVGSwitchElement{ append: ddeAppend<ddeSVGSwitchElement>; }
|
||||
interface ddeSVGSymbolElement extends SVGSymbolElement{ append: ddeAppend<ddeSVGSymbolElement>; }
|
||||
interface ddeSVGTextElement extends SVGTextElement{ append: ddeAppend<ddeSVGTextElement>; }
|
||||
interface ddeSVGTextPathElement extends SVGTextPathElement{ append: ddeAppend<ddeSVGTextPathElement>; }
|
||||
interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend<ddeSVGTitleElement>; }
|
||||
interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend<ddeSVGTSpanElement>; }
|
||||
interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend<ddeSVGUseElement>; }
|
||||
interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend<ddeSVGViewElement>; }
|
||||
// editorconfig-checker-enable
|
||||
export interface ddeHTMLAnchorElement extends HTMLAnchorElement {
|
||||
append: ddeAppend<ddeHTMLAnchorElement>;
|
||||
}
|
||||
export interface ddeHTMLAreaElement extends HTMLAreaElement {
|
||||
append: ddeAppend<ddeHTMLAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLAudioElement extends HTMLAudioElement {
|
||||
append: ddeAppend<ddeHTMLAudioElement>;
|
||||
}
|
||||
export interface ddeHTMLBaseElement extends HTMLBaseElement {
|
||||
append: ddeAppend<ddeHTMLBaseElement>;
|
||||
}
|
||||
export interface ddeHTMLQuoteElement extends HTMLQuoteElement {
|
||||
append: ddeAppend<ddeHTMLQuoteElement>;
|
||||
}
|
||||
export interface ddeHTMLBodyElement extends HTMLBodyElement {
|
||||
append: ddeAppend<ddeHTMLBodyElement>;
|
||||
}
|
||||
export interface ddeHTMLBRElement extends HTMLBRElement {
|
||||
append: ddeAppend<ddeHTMLBRElement>;
|
||||
}
|
||||
export interface ddeHTMLButtonElement extends HTMLButtonElement {
|
||||
append: ddeAppend<ddeHTMLButtonElement>;
|
||||
}
|
||||
export interface ddeHTMLCanvasElement extends HTMLCanvasElement {
|
||||
append: ddeAppend<ddeHTMLCanvasElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement {
|
||||
append: ddeAppend<ddeHTMLTableCaptionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLDataElement extends HTMLDataElement {
|
||||
append: ddeAppend<ddeHTMLDataElement>;
|
||||
}
|
||||
export interface ddeHTMLDataListElement extends HTMLDataListElement {
|
||||
append: ddeAppend<ddeHTMLDataListElement>;
|
||||
}
|
||||
export interface ddeHTMLModElement extends HTMLModElement {
|
||||
append: ddeAppend<ddeHTMLModElement>;
|
||||
}
|
||||
export interface ddeHTMLDetailsElement extends HTMLDetailsElement {
|
||||
append: ddeAppend<ddeHTMLDetailsElement>;
|
||||
}
|
||||
export interface ddeHTMLDialogElement extends HTMLDialogElement {
|
||||
append: ddeAppend<ddeHTMLDialogElement>;
|
||||
}
|
||||
export interface ddeHTMLDivElement extends HTMLDivElement {
|
||||
append: ddeAppend<ddeHTMLDivElement>;
|
||||
}
|
||||
export interface ddeHTMLDListElement extends HTMLDListElement {
|
||||
append: ddeAppend<ddeHTMLDListElement>;
|
||||
}
|
||||
export interface ddeHTMLEmbedElement extends HTMLEmbedElement {
|
||||
append: ddeAppend<ddeHTMLEmbedElement>;
|
||||
}
|
||||
export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement {
|
||||
append: ddeAppend<ddeHTMLFieldSetElement>;
|
||||
}
|
||||
export interface ddeHTMLFormElement extends HTMLFormElement {
|
||||
append: ddeAppend<ddeHTMLFormElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadingElement extends HTMLHeadingElement {
|
||||
append: ddeAppend<ddeHTMLHeadingElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadElement extends HTMLHeadElement {
|
||||
append: ddeAppend<ddeHTMLHeadElement>;
|
||||
}
|
||||
export interface ddeHTMLHRElement extends HTMLHRElement {
|
||||
append: ddeAppend<ddeHTMLHRElement>;
|
||||
}
|
||||
export interface ddeHTMLHtmlElement extends HTMLHtmlElement {
|
||||
append: ddeAppend<ddeHTMLHtmlElement>;
|
||||
}
|
||||
export interface ddeHTMLIFrameElement extends HTMLIFrameElement {
|
||||
append: ddeAppend<ddeHTMLIFrameElement>;
|
||||
}
|
||||
export interface ddeHTMLImageElement extends HTMLImageElement {
|
||||
append: ddeAppend<ddeHTMLImageElement>;
|
||||
}
|
||||
export interface ddeHTMLInputElement extends HTMLInputElement {
|
||||
append: ddeAppend<ddeHTMLInputElement>;
|
||||
}
|
||||
export interface ddeHTMLLabelElement extends HTMLLabelElement {
|
||||
append: ddeAppend<ddeHTMLLabelElement>;
|
||||
}
|
||||
export interface ddeHTMLLegendElement extends HTMLLegendElement {
|
||||
append: ddeAppend<ddeHTMLLegendElement>;
|
||||
}
|
||||
export interface ddeHTMLLIElement extends HTMLLIElement {
|
||||
append: ddeAppend<ddeHTMLLIElement>;
|
||||
}
|
||||
export interface ddeHTMLLinkElement extends HTMLLinkElement {
|
||||
append: ddeAppend<ddeHTMLLinkElement>;
|
||||
}
|
||||
export interface ddeHTMLMapElement extends HTMLMapElement {
|
||||
append: ddeAppend<ddeHTMLMapElement>;
|
||||
}
|
||||
export interface ddeHTMLMenuElement extends HTMLMenuElement {
|
||||
append: ddeAppend<ddeHTMLMenuElement>;
|
||||
}
|
||||
export interface ddeHTMLMetaElement extends HTMLMetaElement {
|
||||
append: ddeAppend<ddeHTMLMetaElement>;
|
||||
}
|
||||
export interface ddeHTMLMeterElement extends HTMLMeterElement {
|
||||
append: ddeAppend<ddeHTMLMeterElement>;
|
||||
}
|
||||
export interface ddeHTMLObjectElement extends HTMLObjectElement {
|
||||
append: ddeAppend<ddeHTMLObjectElement>;
|
||||
}
|
||||
export interface ddeHTMLOListElement extends HTMLOListElement {
|
||||
append: ddeAppend<ddeHTMLOListElement>;
|
||||
}
|
||||
export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement {
|
||||
append: ddeAppend<ddeHTMLOptGroupElement>;
|
||||
}
|
||||
export interface ddeHTMLOptionElement extends HTMLOptionElement {
|
||||
append: ddeAppend<ddeHTMLOptionElement>;
|
||||
}
|
||||
export interface ddeHTMLOutputElement extends HTMLOutputElement {
|
||||
append: ddeAppend<ddeHTMLOutputElement>;
|
||||
}
|
||||
export interface ddeHTMLParagraphElement extends HTMLParagraphElement {
|
||||
append: ddeAppend<ddeHTMLParagraphElement>;
|
||||
}
|
||||
export interface ddeHTMLPictureElement extends HTMLPictureElement {
|
||||
append: ddeAppend<ddeHTMLPictureElement>;
|
||||
}
|
||||
export interface ddeHTMLPreElement extends HTMLPreElement {
|
||||
append: ddeAppend<ddeHTMLPreElement>;
|
||||
}
|
||||
export interface ddeHTMLProgressElement extends HTMLProgressElement {
|
||||
append: ddeAppend<ddeHTMLProgressElement>;
|
||||
}
|
||||
export interface ddeHTMLScriptElement extends HTMLScriptElement {
|
||||
append: ddeAppend<ddeHTMLScriptElement>;
|
||||
}
|
||||
export interface ddeHTMLSelectElement extends HTMLSelectElement {
|
||||
append: ddeAppend<ddeHTMLSelectElement>;
|
||||
}
|
||||
export interface ddeHTMLSlotElement extends HTMLSlotElement {
|
||||
append: ddeAppend<ddeHTMLSlotElement>;
|
||||
}
|
||||
export interface ddeHTMLSourceElement extends HTMLSourceElement {
|
||||
append: ddeAppend<ddeHTMLSourceElement>;
|
||||
}
|
||||
export interface ddeHTMLSpanElement extends HTMLSpanElement {
|
||||
append: ddeAppend<ddeHTMLSpanElement>;
|
||||
}
|
||||
export interface ddeHTMLStyleElement extends HTMLStyleElement {
|
||||
append: ddeAppend<ddeHTMLStyleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableElement extends HTMLTableElement {
|
||||
append: ddeAppend<ddeHTMLTableElement>;
|
||||
}
|
||||
export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement {
|
||||
append: ddeAppend<ddeHTMLTableSectionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTemplateElement extends HTMLTemplateElement {
|
||||
append: ddeAppend<ddeHTMLTemplateElement>;
|
||||
}
|
||||
export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement {
|
||||
append: ddeAppend<ddeHTMLTextAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTimeElement extends HTMLTimeElement {
|
||||
append: ddeAppend<ddeHTMLTimeElement>;
|
||||
}
|
||||
export interface ddeHTMLTitleElement extends HTMLTitleElement {
|
||||
append: ddeAppend<ddeHTMLTitleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableRowElement extends HTMLTableRowElement {
|
||||
append: ddeAppend<ddeHTMLTableRowElement>;
|
||||
}
|
||||
export interface ddeHTMLTrackElement extends HTMLTrackElement {
|
||||
append: ddeAppend<ddeHTMLTrackElement>;
|
||||
}
|
||||
export interface ddeHTMLUListElement extends HTMLUListElement {
|
||||
append: ddeAppend<ddeHTMLUListElement>;
|
||||
}
|
||||
export interface ddeHTMLVideoElement extends HTMLVideoElement {
|
||||
append: ddeAppend<ddeHTMLVideoElement>;
|
||||
}
|
||||
export interface ddeSVGAElement extends SVGAElement {
|
||||
append: ddeAppend<ddeSVGAElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateElement extends SVGAnimateElement {
|
||||
append: ddeAppend<ddeSVGAnimateElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement {
|
||||
append: ddeAppend<ddeSVGAnimateMotionElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement {
|
||||
append: ddeAppend<ddeSVGAnimateTransformElement>;
|
||||
}
|
||||
export interface ddeSVGCircleElement extends SVGCircleElement {
|
||||
append: ddeAppend<ddeSVGCircleElement>;
|
||||
}
|
||||
export interface ddeSVGClipPathElement extends SVGClipPathElement {
|
||||
append: ddeAppend<ddeSVGClipPathElement>;
|
||||
}
|
||||
export interface ddeSVGDefsElement extends SVGDefsElement {
|
||||
append: ddeAppend<ddeSVGDefsElement>;
|
||||
}
|
||||
export interface ddeSVGDescElement extends SVGDescElement {
|
||||
append: ddeAppend<ddeSVGDescElement>;
|
||||
}
|
||||
export interface ddeSVGEllipseElement extends SVGEllipseElement {
|
||||
append: ddeAppend<ddeSVGEllipseElement>;
|
||||
}
|
||||
export interface ddeSVGFEBlendElement extends SVGFEBlendElement {
|
||||
append: ddeAppend<ddeSVGFEBlendElement>;
|
||||
}
|
||||
export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEColorMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement {
|
||||
append: ddeAppend<ddeSVGFEComponentTransferElement>;
|
||||
}
|
||||
export interface ddeSVGFECompositeElement extends SVGFECompositeElement {
|
||||
append: ddeAppend<ddeSVGFECompositeElement>;
|
||||
}
|
||||
export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEConvolveMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement {
|
||||
append: ddeAppend<ddeSVGFEDiffuseLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement {
|
||||
append: ddeAppend<ddeSVGFEDisplacementMapElement>;
|
||||
}
|
||||
export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement {
|
||||
append: ddeAppend<ddeSVGFEDistantLightElement>;
|
||||
}
|
||||
export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement {
|
||||
append: ddeAppend<ddeSVGFEDropShadowElement>;
|
||||
}
|
||||
export interface ddeSVGFEFloodElement extends SVGFEFloodElement {
|
||||
append: ddeAppend<ddeSVGFEFloodElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement {
|
||||
append: ddeAppend<ddeSVGFEFuncAElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement {
|
||||
append: ddeAppend<ddeSVGFEFuncBElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement {
|
||||
append: ddeAppend<ddeSVGFEFuncGElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement {
|
||||
append: ddeAppend<ddeSVGFEFuncRElement>;
|
||||
}
|
||||
export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement {
|
||||
append: ddeAppend<ddeSVGFEGaussianBlurElement>;
|
||||
}
|
||||
export interface ddeSVGFEImageElement extends SVGFEImageElement {
|
||||
append: ddeAppend<ddeSVGFEImageElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeElement extends SVGFEMergeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeNodeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement {
|
||||
append: ddeAppend<ddeSVGFEMorphologyElement>;
|
||||
}
|
||||
export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement {
|
||||
append: ddeAppend<ddeSVGFEOffsetElement>;
|
||||
}
|
||||
export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement {
|
||||
append: ddeAppend<ddeSVGFEPointLightElement>;
|
||||
}
|
||||
export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement {
|
||||
append: ddeAppend<ddeSVGFESpecularLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement {
|
||||
append: ddeAppend<ddeSVGFESpotLightElement>;
|
||||
}
|
||||
export interface ddeSVGFETileElement extends SVGFETileElement {
|
||||
append: ddeAppend<ddeSVGFETileElement>;
|
||||
}
|
||||
export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement {
|
||||
append: ddeAppend<ddeSVGFETurbulenceElement>;
|
||||
}
|
||||
export interface ddeSVGFilterElement extends SVGFilterElement {
|
||||
append: ddeAppend<ddeSVGFilterElement>;
|
||||
}
|
||||
export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement {
|
||||
append: ddeAppend<ddeSVGForeignObjectElement>;
|
||||
}
|
||||
export interface ddeSVGGElement extends SVGGElement {
|
||||
append: ddeAppend<ddeSVGGElement>;
|
||||
}
|
||||
export interface ddeSVGImageElement extends SVGImageElement {
|
||||
append: ddeAppend<ddeSVGImageElement>;
|
||||
}
|
||||
export interface ddeSVGLineElement extends SVGLineElement {
|
||||
append: ddeAppend<ddeSVGLineElement>;
|
||||
}
|
||||
export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement {
|
||||
append: ddeAppend<ddeSVGLinearGradientElement>;
|
||||
}
|
||||
export interface ddeSVGMarkerElement extends SVGMarkerElement {
|
||||
append: ddeAppend<ddeSVGMarkerElement>;
|
||||
}
|
||||
export interface ddeSVGMaskElement extends SVGMaskElement {
|
||||
append: ddeAppend<ddeSVGMaskElement>;
|
||||
}
|
||||
export interface ddeSVGMetadataElement extends SVGMetadataElement {
|
||||
append: ddeAppend<ddeSVGMetadataElement>;
|
||||
}
|
||||
export interface ddeSVGMPathElement extends SVGMPathElement {
|
||||
append: ddeAppend<ddeSVGMPathElement>;
|
||||
}
|
||||
export interface ddeSVGPathElement extends SVGPathElement {
|
||||
append: ddeAppend<ddeSVGPathElement>;
|
||||
}
|
||||
export interface ddeSVGPatternElement extends SVGPatternElement {
|
||||
append: ddeAppend<ddeSVGPatternElement>;
|
||||
}
|
||||
export interface ddeSVGPolygonElement extends SVGPolygonElement {
|
||||
append: ddeAppend<ddeSVGPolygonElement>;
|
||||
}
|
||||
export interface ddeSVGPolylineElement extends SVGPolylineElement {
|
||||
append: ddeAppend<ddeSVGPolylineElement>;
|
||||
}
|
||||
export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement {
|
||||
append: ddeAppend<ddeSVGRadialGradientElement>;
|
||||
}
|
||||
export interface ddeSVGRectElement extends SVGRectElement {
|
||||
append: ddeAppend<ddeSVGRectElement>;
|
||||
}
|
||||
export interface ddeSVGScriptElement extends SVGScriptElement {
|
||||
append: ddeAppend<ddeSVGScriptElement>;
|
||||
}
|
||||
export interface ddeSVGSetElement extends SVGSetElement {
|
||||
append: ddeAppend<ddeSVGSetElement>;
|
||||
}
|
||||
export interface ddeSVGStopElement extends SVGStopElement {
|
||||
append: ddeAppend<ddeSVGStopElement>;
|
||||
}
|
||||
export interface ddeSVGStyleElement extends SVGStyleElement {
|
||||
append: ddeAppend<ddeSVGStyleElement>;
|
||||
}
|
||||
export interface ddeSVGSVGElement extends SVGSVGElement {
|
||||
append: ddeAppend<ddeSVGSVGElement>;
|
||||
}
|
||||
export interface ddeSVGSwitchElement extends SVGSwitchElement {
|
||||
append: ddeAppend<ddeSVGSwitchElement>;
|
||||
}
|
||||
export interface ddeSVGSymbolElement extends SVGSymbolElement {
|
||||
append: ddeAppend<ddeSVGSymbolElement>;
|
||||
}
|
||||
export interface ddeSVGTextElement extends SVGTextElement {
|
||||
append: ddeAppend<ddeSVGTextElement>;
|
||||
}
|
||||
export interface ddeSVGTextPathElement extends SVGTextPathElement {
|
||||
append: ddeAppend<ddeSVGTextPathElement>;
|
||||
}
|
||||
export interface ddeSVGTitleElement extends SVGTitleElement {
|
||||
append: ddeAppend<ddeSVGTitleElement>;
|
||||
}
|
||||
export interface ddeSVGTSpanElement extends SVGTSpanElement {
|
||||
append: ddeAppend<ddeSVGTSpanElement>;
|
||||
}
|
||||
export interface ddeSVGUseElement extends SVGUseElement {
|
||||
append: ddeAppend<ddeSVGUseElement>;
|
||||
}
|
||||
export interface ddeSVGViewElement extends SVGViewElement {
|
||||
append: ddeAppend<ddeSVGViewElement>;
|
||||
}
|
||||
|
||||
export {
|
||||
dispatchEvent$1 as dispatchEvent,
|
||||
el as createElement,
|
||||
elNS as createElementNS,
|
||||
};
|
||||
|
||||
export {};
|
||||
|
853
dist/esm.js
vendored
853
dist/esm.js
vendored
@ -1,451 +1,662 @@
|
||||
// src/signals-common.js
|
||||
var C = {
|
||||
isSignal(t) {
|
||||
return !1;
|
||||
},
|
||||
processReactiveAttribute(t, e, r, n) {
|
||||
return r;
|
||||
}
|
||||
};
|
||||
function Z(t, e = !0) {
|
||||
return e ? Object.assign(C, t) : (Object.setPrototypeOf(t, C), t);
|
||||
}
|
||||
function S(t) {
|
||||
return C.isPrototypeOf(t) && t !== C ? t : C;
|
||||
}
|
||||
|
||||
// src/helpers.js
|
||||
function m(t) {
|
||||
return typeof t > "u";
|
||||
function isUndef(value) {
|
||||
return typeof value === "undefined";
|
||||
}
|
||||
function L(t, e) {
|
||||
if (!t || !(t instanceof AbortSignal))
|
||||
return !0;
|
||||
if (!t.aborted)
|
||||
return t.addEventListener("abort", e), function() {
|
||||
t.removeEventListener("abort", e);
|
||||
};
|
||||
function isInstance(obj, cls) {
|
||||
return obj instanceof cls;
|
||||
}
|
||||
function q(t, e) {
|
||||
let { observedAttributes: r = [] } = t.constructor;
|
||||
return r.reduce(function(n, o) {
|
||||
return n[G(o)] = e(t, o), n;
|
||||
function isProtoFrom(obj, cls) {
|
||||
return Object.prototype.isPrototypeOf.call(cls, obj);
|
||||
}
|
||||
function oAssign(...o) {
|
||||
return Object.assign(...o);
|
||||
}
|
||||
function onAbort(signal, listener) {
|
||||
if (!signal || !isInstance(signal, AbortSignal))
|
||||
return true;
|
||||
if (signal.aborted)
|
||||
return;
|
||||
signal.addEventListener("abort", listener);
|
||||
return function cleanUp() {
|
||||
signal.removeEventListener("abort", listener);
|
||||
};
|
||||
}
|
||||
function observedAttributes(instance, observedAttribute) {
|
||||
const { observedAttributes: observedAttributes3 = [] } = instance.constructor;
|
||||
return observedAttributes3.reduce(function(out, name) {
|
||||
out[kebabToCamel(name)] = observedAttribute(instance, name);
|
||||
return out;
|
||||
}, {});
|
||||
}
|
||||
function G(t) {
|
||||
return t.replace(/-./g, (e) => e[1].toUpperCase());
|
||||
function kebabToCamel(name) {
|
||||
return name.replace(/-./g, (x) => x[1].toUpperCase());
|
||||
}
|
||||
|
||||
// src/signals-lib/common.js
|
||||
var signals_global = {
|
||||
/**
|
||||
* Checks if a value is a signal
|
||||
* @param {any} attributes - Value to check
|
||||
* @returns {boolean} Whether the value is a signal
|
||||
*/
|
||||
isSignal(attributes) {
|
||||
return false;
|
||||
},
|
||||
/**
|
||||
* Processes an attribute that might be reactive
|
||||
* @param {Element} obj - Element that owns the attribute
|
||||
* @param {string} key - Attribute name
|
||||
* @param {any} attr - Attribute value
|
||||
* @param {Function} set - Function to set the attribute
|
||||
* @returns {any} Processed attribute value
|
||||
*/
|
||||
processReactiveAttribute(obj, key, attr, set) {
|
||||
return attr;
|
||||
}
|
||||
};
|
||||
function registerReactivity(def, global = true) {
|
||||
if (global) return oAssign(signals_global, def);
|
||||
Object.setPrototypeOf(def, signals_global);
|
||||
return def;
|
||||
}
|
||||
function signals(_this) {
|
||||
return isProtoFrom(_this, signals_global) && _this !== signals_global ? _this : signals_global;
|
||||
}
|
||||
|
||||
// src/dom-common.js
|
||||
var a = {
|
||||
setDeleteAttr: V,
|
||||
var enviroment = {
|
||||
setDeleteAttr,
|
||||
ssr: "",
|
||||
D: globalThis.document,
|
||||
F: globalThis.DocumentFragment,
|
||||
H: globalThis.HTMLElement,
|
||||
S: globalThis.SVGElement,
|
||||
M: globalThis.MutationObserver,
|
||||
q: (t) => t || Promise.resolve()
|
||||
q: (p) => p || Promise.resolve()
|
||||
};
|
||||
function V(t, e, r) {
|
||||
if (Reflect.set(t, e, r), !!m(r)) {
|
||||
if (Reflect.deleteProperty(t, e), t instanceof a.H && t.getAttribute(e) === "undefined")
|
||||
return t.removeAttribute(e);
|
||||
if (Reflect.get(t, e) === "undefined")
|
||||
return Reflect.set(t, e, "");
|
||||
}
|
||||
function setDeleteAttr(obj, prop, val) {
|
||||
Reflect.set(obj, prop, val);
|
||||
if (!isUndef(val)) return;
|
||||
Reflect.deleteProperty(obj, prop);
|
||||
if (isInstance(obj, enviroment.H) && obj.getAttribute(prop) === "undefined")
|
||||
return obj.removeAttribute(prop);
|
||||
if (Reflect.get(obj, prop) === "undefined")
|
||||
return Reflect.set(obj, prop, "");
|
||||
}
|
||||
var x = "__dde_lifecyclesToEvents", v = "dde:connected", w = "dde:disconnected", y = "dde:attributeChanged";
|
||||
var keyLTE = "__dde_lifecyclesToEvents";
|
||||
var evc = "dde:connected";
|
||||
var evd = "dde:disconnected";
|
||||
var eva = "dde:attributeChanged";
|
||||
|
||||
// src/dom.js
|
||||
function dt(t) {
|
||||
return a.q(t);
|
||||
function queue(promise) {
|
||||
return enviroment.q(promise);
|
||||
}
|
||||
var g = [{
|
||||
var scopes = [{
|
||||
get scope() {
|
||||
return a.D.body;
|
||||
return enviroment.D.body;
|
||||
},
|
||||
host: (t) => t ? t(a.D.body) : a.D.body,
|
||||
prevent: !0
|
||||
}], O = {
|
||||
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
|
||||
prevent: true
|
||||
}];
|
||||
var scope = {
|
||||
/**
|
||||
* Gets the current scope
|
||||
* @returns {Object} Current scope context
|
||||
*/
|
||||
get current() {
|
||||
return g[g.length - 1];
|
||||
return scopes[scopes.length - 1];
|
||||
},
|
||||
/**
|
||||
* Gets the host element of the current scope
|
||||
* @returns {Function} Host accessor function
|
||||
*/
|
||||
get host() {
|
||||
return this.current.host;
|
||||
},
|
||||
/**
|
||||
* Prevents default behavior in the current scope
|
||||
* @returns {Object} Current scope context
|
||||
*/
|
||||
preventDefault() {
|
||||
let { current: t } = this;
|
||||
return t.prevent = !0, t;
|
||||
const { current } = this;
|
||||
current.prevent = true;
|
||||
return current;
|
||||
},
|
||||
/**
|
||||
* Gets a copy of the current scope stack
|
||||
* @returns {Array} Copy of scope stack
|
||||
*/
|
||||
get state() {
|
||||
return [...g];
|
||||
return [...scopes];
|
||||
},
|
||||
push(t = {}) {
|
||||
return g.push(Object.assign({}, this.current, { prevent: !1 }, t));
|
||||
/**
|
||||
* Pushes a new scope to the stack
|
||||
* @param {Object} [s={}] - Scope object to push
|
||||
* @returns {number} New length of the scope stack
|
||||
*/
|
||||
push(s = {}) {
|
||||
return scopes.push(oAssign({}, this.current, { prevent: false }, s));
|
||||
},
|
||||
/**
|
||||
* Pushes the root scope to the stack
|
||||
* @returns {number} New length of the scope stack
|
||||
*/
|
||||
pushRoot() {
|
||||
return g.push(g[0]);
|
||||
return scopes.push(scopes[0]);
|
||||
},
|
||||
/**
|
||||
* Pops the current scope from the stack
|
||||
* @returns {Object|undefined} Popped scope or undefined if only one scope remains
|
||||
*/
|
||||
pop() {
|
||||
if (g.length !== 1)
|
||||
return g.pop();
|
||||
if (scopes.length === 1) return;
|
||||
return scopes.pop();
|
||||
}
|
||||
};
|
||||
function k(...t) {
|
||||
return this.appendOriginal(...t), this;
|
||||
function append(...els) {
|
||||
this.appendOriginal(...els);
|
||||
return this;
|
||||
}
|
||||
function J(t) {
|
||||
return t.append === k || (t.appendOriginal = t.append, t.append = k), t;
|
||||
function chainableAppend(el) {
|
||||
if (el.append === append) return el;
|
||||
el.appendOriginal = el.append;
|
||||
el.append = append;
|
||||
return el;
|
||||
}
|
||||
var T;
|
||||
function P(t, e, ...r) {
|
||||
let n = S(this), o = 0, c, d;
|
||||
switch ((Object(e) !== e || n.isSignal(e)) && (e = { textContent: e }), !0) {
|
||||
case typeof t == "function": {
|
||||
o = 1;
|
||||
let f = (...l) => l.length ? (o === 1 ? r.unshift(...l) : l.forEach((E) => E(d)), void 0) : d;
|
||||
O.push({ scope: t, host: f }), c = t(e || void 0);
|
||||
let p = c instanceof a.F;
|
||||
if (c.nodeName === "#comment") break;
|
||||
let b = P.mark({
|
||||
var namespace;
|
||||
function createElement(tag, attributes, ...addons) {
|
||||
const s = signals(this);
|
||||
let scoped = 0;
|
||||
let el, el_host;
|
||||
if (Object(attributes) !== attributes || s.isSignal(attributes))
|
||||
attributes = { textContent: attributes };
|
||||
switch (true) {
|
||||
case typeof tag === "function": {
|
||||
scoped = 1;
|
||||
const host = (...c) => !c.length ? el_host : (scoped === 1 ? addons.unshift(...c) : c.forEach((c2) => c2(el_host)), void 0);
|
||||
scope.push({ scope: tag, host });
|
||||
el = tag(attributes || void 0);
|
||||
const is_fragment = isInstance(el, enviroment.F);
|
||||
if (el.nodeName === "#comment") break;
|
||||
const el_mark = createElement.mark({
|
||||
type: "component",
|
||||
name: t.name,
|
||||
host: p ? "this" : "parentElement"
|
||||
name: tag.name,
|
||||
host: is_fragment ? "this" : "parentElement"
|
||||
});
|
||||
c.prepend(b), p && (d = b);
|
||||
el.prepend(el_mark);
|
||||
if (is_fragment) el_host = el_mark;
|
||||
break;
|
||||
}
|
||||
case t === "#text":
|
||||
c = R.call(this, a.D.createTextNode(""), e);
|
||||
case tag === "#text":
|
||||
el = assign.call(this, enviroment.D.createTextNode(""), attributes);
|
||||
break;
|
||||
case (t === "<>" || !t):
|
||||
c = R.call(this, a.D.createDocumentFragment(), e);
|
||||
case (tag === "<>" || !tag):
|
||||
el = assign.call(this, enviroment.D.createDocumentFragment(), attributes);
|
||||
break;
|
||||
case !!T:
|
||||
c = R.call(this, a.D.createElementNS(T, t), e);
|
||||
case Boolean(namespace):
|
||||
el = assign.call(this, enviroment.D.createElementNS(namespace, tag), attributes);
|
||||
break;
|
||||
case !c:
|
||||
c = R.call(this, a.D.createElement(t), e);
|
||||
case !el:
|
||||
el = assign.call(this, enviroment.D.createElement(tag), attributes);
|
||||
}
|
||||
return J(c), d || (d = c), r.forEach((f) => f(d)), o && O.pop(), o = 2, c;
|
||||
chainableAppend(el);
|
||||
if (!el_host) el_host = el;
|
||||
addons.forEach((c) => c(el_host));
|
||||
if (scoped) scope.pop();
|
||||
scoped = 2;
|
||||
return el;
|
||||
}
|
||||
P.mark = function(t, e = !1) {
|
||||
t = Object.entries(t).map(([o, c]) => o + `="${c}"`).join(" ");
|
||||
let r = e ? "" : "/", n = a.D.createComment(`<dde:mark ${t}${a.ssr}${r}>`);
|
||||
return e && (n.end = a.D.createComment("</dde:mark>")), n;
|
||||
createElement.mark = function(attrs, is_open = false) {
|
||||
attrs = Object.entries(attrs).map(([n, v]) => n + `="${v}"`).join(" ");
|
||||
const end = is_open ? "" : "/";
|
||||
const out = enviroment.D.createComment(`<dde:mark ${attrs}${enviroment.ssr}${end}>`);
|
||||
if (is_open) out.end = enviroment.D.createComment("</dde:mark>");
|
||||
return out;
|
||||
};
|
||||
function pt(t) {
|
||||
let e = this;
|
||||
return function(...n) {
|
||||
T = t;
|
||||
let o = P.call(e, ...n);
|
||||
return T = void 0, o;
|
||||
function createElementNS(ns) {
|
||||
const _this = this;
|
||||
return function createElementNSCurried(...rest) {
|
||||
namespace = ns;
|
||||
const el = createElement.call(_this, ...rest);
|
||||
namespace = void 0;
|
||||
return el;
|
||||
};
|
||||
}
|
||||
function lt(t, e = t) {
|
||||
let r = "\xB9\u2070", n = "\u2713", o = Object.fromEntries(
|
||||
Array.from(e.querySelectorAll("slot")).filter((c) => !c.name.endsWith(r)).map((c) => [c.name += r, c])
|
||||
function simulateSlots(element, root = element) {
|
||||
const mark_e = "\xB9\u2070", mark_s = "\u2713";
|
||||
const slots = Object.fromEntries(
|
||||
Array.from(root.querySelectorAll("slot")).filter((s) => !s.name.endsWith(mark_e)).map((s) => [s.name += mark_e, s])
|
||||
);
|
||||
if (t.append = new Proxy(t.append, {
|
||||
apply(c, d, f) {
|
||||
if (f[0] === e) return c.apply(t, f);
|
||||
for (let p of f) {
|
||||
let b = (p.slot || "") + r;
|
||||
element.append = new Proxy(element.append, {
|
||||
apply(orig, _, els) {
|
||||
if (els[0] === root) return orig.apply(element, els);
|
||||
for (const el of els) {
|
||||
const name = (el.slot || "") + mark_e;
|
||||
try {
|
||||
Q(p, "remove", "slot");
|
||||
} catch {
|
||||
elementAttribute(el, "remove", "slot");
|
||||
} catch (_error) {
|
||||
}
|
||||
let l = o[b];
|
||||
if (!l) return;
|
||||
l.name.startsWith(n) || (l.childNodes.forEach((E) => E.remove()), l.name = n + b), l.append(p);
|
||||
const slot = slots[name];
|
||||
if (!slot) return;
|
||||
if (!slot.name.startsWith(mark_s)) {
|
||||
slot.childNodes.forEach((c) => c.remove());
|
||||
slot.name = mark_s + name;
|
||||
}
|
||||
slot.append(el);
|
||||
}
|
||||
return t.append = c, t;
|
||||
element.append = orig;
|
||||
return element;
|
||||
}
|
||||
}), t !== e) {
|
||||
let c = Array.from(t.childNodes);
|
||||
t.append(...c);
|
||||
});
|
||||
if (element !== root) {
|
||||
const els = Array.from(element.childNodes);
|
||||
element.append(...els);
|
||||
}
|
||||
return e;
|
||||
return root;
|
||||
}
|
||||
var N = /* @__PURE__ */ new WeakMap(), { setDeleteAttr: $ } = a;
|
||||
function R(t, ...e) {
|
||||
if (!e.length) return t;
|
||||
N.set(t, H(t, this));
|
||||
for (let [r, n] of Object.entries(Object.assign({}, ...e)))
|
||||
U.call(this, t, r, n);
|
||||
return N.delete(t), t;
|
||||
var assign_context = /* @__PURE__ */ new WeakMap();
|
||||
var { setDeleteAttr: setDeleteAttr2 } = enviroment;
|
||||
function assign(element, ...attributes) {
|
||||
if (!attributes.length) return element;
|
||||
assign_context.set(element, assignContext(element, this));
|
||||
for (const [key, value] of Object.entries(oAssign({}, ...attributes)))
|
||||
assignAttribute.call(this, element, key, value);
|
||||
assign_context.delete(element);
|
||||
return element;
|
||||
}
|
||||
function U(t, e, r) {
|
||||
let { setRemoveAttr: n, s: o } = H(t, this), c = this;
|
||||
r = o.processReactiveAttribute(
|
||||
t,
|
||||
e,
|
||||
r,
|
||||
(f, p) => U.call(c, t, f, p)
|
||||
function assignAttribute(element, key, value) {
|
||||
const { setRemoveAttr, s } = assignContext(element, this);
|
||||
const _this = this;
|
||||
value = s.processReactiveAttribute(
|
||||
element,
|
||||
key,
|
||||
value,
|
||||
(key2, value2) => assignAttribute.call(_this, element, key2, value2)
|
||||
);
|
||||
let [d] = e;
|
||||
if (d === "=") return n(e.slice(1), r);
|
||||
if (d === ".") return F(t, e.slice(1), r);
|
||||
if (/(aria|data)([A-Z])/.test(e))
|
||||
return e = e.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(), n(e, r);
|
||||
switch (e === "className" && (e = "class"), e) {
|
||||
const [k] = key;
|
||||
if ("=" === k) return setRemoveAttr(key.slice(1), value);
|
||||
if ("." === k) return setDelete(element, key.slice(1), value);
|
||||
if (/(aria|data)([A-Z])/.test(key)) {
|
||||
key = key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
||||
return setRemoveAttr(key, value);
|
||||
}
|
||||
if ("className" === key) key = "class";
|
||||
switch (key) {
|
||||
case "xlink:href":
|
||||
return n(e, r, "http://www.w3.org/1999/xlink");
|
||||
return setRemoveAttr(key, value, "http://www.w3.org/1999/xlink");
|
||||
case "textContent":
|
||||
return $(t, e, r);
|
||||
return setDeleteAttr2(element, key, value);
|
||||
case "style":
|
||||
if (typeof r != "object") break;
|
||||
if (typeof value !== "object") break;
|
||||
/* falls through */
|
||||
case "dataset":
|
||||
return M(o, e, t, r, F.bind(null, t[e]));
|
||||
return forEachEntries(s, key, element, value, setDelete.bind(null, element[key]));
|
||||
case "ariaset":
|
||||
return M(o, e, t, r, (f, p) => n("aria-" + f, p));
|
||||
return forEachEntries(s, key, element, value, (key2, val) => setRemoveAttr("aria-" + key2, val));
|
||||
case "classList":
|
||||
return K.call(c, t, r);
|
||||
return classListDeclarative.call(_this, element, value);
|
||||
}
|
||||
return X(t, e) ? $(t, e, r) : n(e, r);
|
||||
return isPropSetter(element, key) ? setDeleteAttr2(element, key, value) : setRemoveAttr(key, value);
|
||||
}
|
||||
function H(t, e) {
|
||||
if (N.has(t)) return N.get(t);
|
||||
let n = (t instanceof a.S ? tt : Y).bind(null, t, "Attribute"), o = S(e);
|
||||
return { setRemoveAttr: n, s: o };
|
||||
function assignContext(element, _this) {
|
||||
if (assign_context.has(element)) return assign_context.get(element);
|
||||
const is_svg = isInstance(element, enviroment.S);
|
||||
const setRemoveAttr = (is_svg ? setRemoveNS : setRemove).bind(null, element, "Attribute");
|
||||
const s = signals(_this);
|
||||
return { setRemoveAttr, s };
|
||||
}
|
||||
function K(t, e) {
|
||||
let r = S(this);
|
||||
return M(
|
||||
r,
|
||||
function classListDeclarative(element, toggle) {
|
||||
const s = signals(this);
|
||||
forEachEntries(
|
||||
s,
|
||||
"classList",
|
||||
t,
|
||||
e,
|
||||
(n, o) => t.classList.toggle(n, o === -1 ? void 0 : !!o)
|
||||
), t;
|
||||
element,
|
||||
toggle,
|
||||
(class_name, val) => element.classList.toggle(class_name, val === -1 ? void 0 : Boolean(val))
|
||||
);
|
||||
return element;
|
||||
}
|
||||
function Q(t, e, r, n) {
|
||||
return t instanceof a.H ? t[e + "Attribute"](r, n) : t[e + "AttributeNS"](null, r, n);
|
||||
function elementAttribute(element, op, key, value) {
|
||||
if (isInstance(element, enviroment.H))
|
||||
return element[op + "Attribute"](key, value);
|
||||
return element[op + "AttributeNS"](null, key, value);
|
||||
}
|
||||
function X(t, e) {
|
||||
if (!(e in t)) return !1;
|
||||
let r = z(t, e);
|
||||
return !m(r.set);
|
||||
function isPropSetter(el, key) {
|
||||
if (!(key in el)) return false;
|
||||
const des = getPropDescriptor(el, key);
|
||||
return !isUndef(des.set);
|
||||
}
|
||||
function z(t, e) {
|
||||
if (t = Object.getPrototypeOf(t), !t) return {};
|
||||
let r = Object.getOwnPropertyDescriptor(t, e);
|
||||
return r || z(t, e);
|
||||
function getPropDescriptor(p, key) {
|
||||
p = Object.getPrototypeOf(p);
|
||||
if (!p) return {};
|
||||
const des = Object.getOwnPropertyDescriptor(p, key);
|
||||
if (!des) return getPropDescriptor(p, key);
|
||||
return des;
|
||||
}
|
||||
function M(t, e, r, n, o) {
|
||||
let c = String;
|
||||
if (!(typeof n != "object" || n === null))
|
||||
return Object.entries(n).forEach(function([f, p]) {
|
||||
f && (f = new c(f), f.target = e, p = t.processReactiveAttribute(r, f, p, o), o(f, p));
|
||||
});
|
||||
function forEachEntries(s, target, element, obj, cb) {
|
||||
const S = String;
|
||||
if (typeof obj !== "object" || obj === null) return;
|
||||
return Object.entries(obj).forEach(function process([key, val]) {
|
||||
if (!key) return;
|
||||
key = new S(key);
|
||||
key.target = target;
|
||||
val = s.processReactiveAttribute(element, key, val, cb);
|
||||
cb(key, val);
|
||||
});
|
||||
}
|
||||
function Y(t, e, r, n) {
|
||||
return t[(m(n) ? "remove" : "set") + e](r, n);
|
||||
function setRemove(obj, prop, key, val) {
|
||||
return obj[(isUndef(val) ? "remove" : "set") + prop](key, val);
|
||||
}
|
||||
function tt(t, e, r, n, o = null) {
|
||||
return t[(m(n) ? "remove" : "set") + e + "NS"](o, r, n);
|
||||
function setRemoveNS(obj, prop, key, val, ns = null) {
|
||||
return obj[(isUndef(val) ? "remove" : "set") + prop + "NS"](ns, key, val);
|
||||
}
|
||||
function F(t, e, r) {
|
||||
if (Reflect.set(t, e, r), !!m(r))
|
||||
return Reflect.deleteProperty(t, e);
|
||||
function setDelete(obj, key, val) {
|
||||
Reflect.set(obj, key, val);
|
||||
if (!isUndef(val)) return;
|
||||
return Reflect.deleteProperty(obj, key);
|
||||
}
|
||||
|
||||
// src/events-observer.js
|
||||
var _ = a.M ? et() : new Proxy({}, {
|
||||
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
|
||||
get() {
|
||||
return () => {
|
||||
};
|
||||
}
|
||||
});
|
||||
function et() {
|
||||
let t = /* @__PURE__ */ new Map(), e = !1, r = (s) => function(u) {
|
||||
for (let i of u)
|
||||
if (i.type === "childList") {
|
||||
if (l(i.addedNodes, !0)) {
|
||||
s();
|
||||
continue;
|
||||
}
|
||||
E(i.removedNodes, !0) && s();
|
||||
function connectionsChangesObserverConstructor() {
|
||||
const store = /* @__PURE__ */ new Map();
|
||||
let is_observing = false;
|
||||
const observerListener = (stop2) => function(mutations) {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type !== "childList") continue;
|
||||
if (observerAdded(mutation.addedNodes, true)) {
|
||||
stop2();
|
||||
continue;
|
||||
}
|
||||
}, n = new a.M(r(f));
|
||||
return {
|
||||
observe(s) {
|
||||
let u = new a.M(r(() => {
|
||||
}));
|
||||
return u.observe(s, { childList: !0, subtree: !0 }), () => u.disconnect();
|
||||
},
|
||||
onConnected(s, u) {
|
||||
d();
|
||||
let i = c(s);
|
||||
i.connected.has(u) || (i.connected.add(u), i.length_c += 1);
|
||||
},
|
||||
offConnected(s, u) {
|
||||
if (!t.has(s)) return;
|
||||
let i = t.get(s);
|
||||
i.connected.has(u) && (i.connected.delete(u), i.length_c -= 1, o(s, i));
|
||||
},
|
||||
onDisconnected(s, u) {
|
||||
d();
|
||||
let i = c(s);
|
||||
i.disconnected.has(u) || (i.disconnected.add(u), i.length_d += 1);
|
||||
},
|
||||
offDisconnected(s, u) {
|
||||
if (!t.has(s)) return;
|
||||
let i = t.get(s);
|
||||
i.disconnected.has(u) && (i.disconnected.delete(u), i.length_d -= 1, o(s, i));
|
||||
if (observerRemoved(mutation.removedNodes, true))
|
||||
stop2();
|
||||
}
|
||||
};
|
||||
function o(s, u) {
|
||||
u.length_c || u.length_d || (t.delete(s), f());
|
||||
const observer = new enviroment.M(observerListener(stop));
|
||||
return {
|
||||
/**
|
||||
* Creates an observer for a specific element
|
||||
* @param {Element} element - Element to observe
|
||||
* @returns {Function} Cleanup function
|
||||
*/
|
||||
observe(element) {
|
||||
const o = new enviroment.M(observerListener(() => {
|
||||
}));
|
||||
o.observe(element, { childList: true, subtree: true });
|
||||
return () => o.disconnect();
|
||||
},
|
||||
/**
|
||||
* Register a connection listener for an element
|
||||
* @param {Element} element - Element to watch
|
||||
* @param {Function} listener - Callback for connection event
|
||||
*/
|
||||
onConnected(element, listener) {
|
||||
start();
|
||||
const listeners = getElementStore(element);
|
||||
if (listeners.connected.has(listener)) return;
|
||||
listeners.connected.add(listener);
|
||||
listeners.length_c += 1;
|
||||
},
|
||||
/**
|
||||
* Unregister a connection listener
|
||||
* @param {Element} element - Element being watched
|
||||
* @param {Function} listener - Callback to remove
|
||||
*/
|
||||
offConnected(element, listener) {
|
||||
if (!store.has(element)) return;
|
||||
const ls = store.get(element);
|
||||
if (!ls.connected.has(listener)) return;
|
||||
ls.connected.delete(listener);
|
||||
ls.length_c -= 1;
|
||||
cleanWhenOff(element, ls);
|
||||
},
|
||||
/**
|
||||
* Register a disconnection listener for an element
|
||||
* @param {Element} element - Element to watch
|
||||
* @param {Function} listener - Callback for disconnection event
|
||||
*/
|
||||
onDisconnected(element, listener) {
|
||||
start();
|
||||
const listeners = getElementStore(element);
|
||||
if (listeners.disconnected.has(listener)) return;
|
||||
listeners.disconnected.add(listener);
|
||||
listeners.length_d += 1;
|
||||
},
|
||||
/**
|
||||
* Unregister a disconnection listener
|
||||
* @param {Element} element - Element being watched
|
||||
* @param {Function} listener - Callback to remove
|
||||
*/
|
||||
offDisconnected(element, listener) {
|
||||
if (!store.has(element)) return;
|
||||
const ls = store.get(element);
|
||||
ls.disconnected.delete(listener);
|
||||
ls.length_d -= 1;
|
||||
cleanWhenOff(element, ls);
|
||||
}
|
||||
};
|
||||
function cleanWhenOff(element, ls) {
|
||||
if (ls.length_c || ls.length_d)
|
||||
return;
|
||||
store.delete(element);
|
||||
stop();
|
||||
}
|
||||
function c(s) {
|
||||
if (t.has(s)) return t.get(s);
|
||||
let u = {
|
||||
function getElementStore(element) {
|
||||
if (store.has(element)) return store.get(element);
|
||||
const out = {
|
||||
connected: /* @__PURE__ */ new WeakSet(),
|
||||
length_c: 0,
|
||||
disconnected: /* @__PURE__ */ new WeakSet(),
|
||||
length_d: 0
|
||||
};
|
||||
return t.set(s, u), u;
|
||||
store.set(element, out);
|
||||
return out;
|
||||
}
|
||||
function d() {
|
||||
e || (e = !0, n.observe(a.D.body, { childList: !0, subtree: !0 }));
|
||||
function start() {
|
||||
if (is_observing) return;
|
||||
is_observing = true;
|
||||
observer.observe(enviroment.D.body, { childList: true, subtree: true });
|
||||
}
|
||||
function f() {
|
||||
!e || t.size || (e = !1, n.disconnect());
|
||||
function stop() {
|
||||
if (!is_observing || store.size) return;
|
||||
is_observing = false;
|
||||
observer.disconnect();
|
||||
}
|
||||
function p() {
|
||||
return new Promise(function(s) {
|
||||
(requestIdleCallback || requestAnimationFrame)(s);
|
||||
function requestIdle() {
|
||||
return new Promise(function(resolve) {
|
||||
(requestIdleCallback || requestAnimationFrame)(resolve);
|
||||
});
|
||||
}
|
||||
async function b(s) {
|
||||
t.size > 30 && await p();
|
||||
let u = [];
|
||||
if (!(s instanceof Node)) return u;
|
||||
for (let i of t.keys())
|
||||
i === s || !(i instanceof Node) || s.contains(i) && u.push(i);
|
||||
return u;
|
||||
}
|
||||
function l(s, u) {
|
||||
let i = !1;
|
||||
for (let h of s) {
|
||||
if (u && b(h).then(l), !t.has(h)) continue;
|
||||
let A = t.get(h);
|
||||
A.length_c && (h.dispatchEvent(new Event(v)), A.connected = /* @__PURE__ */ new WeakSet(), A.length_c = 0, A.length_d || t.delete(h), i = !0);
|
||||
async function collectChildren(element) {
|
||||
if (store.size > 30)
|
||||
await requestIdle();
|
||||
const out = [];
|
||||
if (!isInstance(element, Node)) return out;
|
||||
for (const el of store.keys()) {
|
||||
if (el === element || !isInstance(el, Node)) continue;
|
||||
if (element.contains(el))
|
||||
out.push(el);
|
||||
}
|
||||
return i;
|
||||
return out;
|
||||
}
|
||||
function E(s, u) {
|
||||
let i = !1;
|
||||
for (let h of s)
|
||||
u && b(h).then(E), !(!t.has(h) || !t.get(h).length_d) && ((globalThis.queueMicrotask || setTimeout)(I(h)), i = !0);
|
||||
return i;
|
||||
function observerAdded(addedNodes, is_root) {
|
||||
let out = false;
|
||||
for (const element of addedNodes) {
|
||||
if (is_root) collectChildren(element).then(observerAdded);
|
||||
if (!store.has(element)) continue;
|
||||
const ls = store.get(element);
|
||||
if (!ls.length_c) continue;
|
||||
element.dispatchEvent(new Event(evc));
|
||||
ls.connected = /* @__PURE__ */ new WeakSet();
|
||||
ls.length_c = 0;
|
||||
if (!ls.length_d) store.delete(element);
|
||||
out = true;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
function I(s) {
|
||||
function observerRemoved(removedNodes, is_root) {
|
||||
let out = false;
|
||||
for (const element of removedNodes) {
|
||||
if (is_root) collectChildren(element).then(observerRemoved);
|
||||
if (!store.has(element)) continue;
|
||||
const ls = store.get(element);
|
||||
if (!ls.length_d) continue;
|
||||
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
|
||||
out = true;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
function dispatchRemove(element) {
|
||||
return () => {
|
||||
s.isConnected || (s.dispatchEvent(new Event(w)), t.delete(s));
|
||||
if (element.isConnected) return;
|
||||
element.dispatchEvent(new Event(evd));
|
||||
store.delete(element);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// src/customElement.js
|
||||
function wt(t, e, r = rt) {
|
||||
let n = t.host || t;
|
||||
O.push({
|
||||
scope: n,
|
||||
host: (...d) => d.length ? d.forEach((f) => f(n)) : n
|
||||
}), typeof r == "function" && (r = r.call(n, n));
|
||||
let o = n[x];
|
||||
o || nt(n);
|
||||
let c = e.call(n, r);
|
||||
return o || n.dispatchEvent(new Event(v)), t.nodeType === 11 && typeof t.mode == "string" && n.addEventListener(w, _.observe(t), { once: !0 }), O.pop(), t.append(c);
|
||||
function customElementRender(target, render, props = observedAttributes2) {
|
||||
const custom_element = target.host || target;
|
||||
scope.push({
|
||||
scope: custom_element,
|
||||
host: (...c) => c.length ? c.forEach((c2) => c2(custom_element)) : custom_element
|
||||
});
|
||||
if (typeof props === "function") props = props.call(custom_element, custom_element);
|
||||
const is_lte = custom_element[keyLTE];
|
||||
if (!is_lte) lifecyclesToEvents(custom_element);
|
||||
const out = render.call(custom_element, props);
|
||||
if (!is_lte) custom_element.dispatchEvent(new Event(evc));
|
||||
if (target.nodeType === 11 && typeof target.mode === "string")
|
||||
custom_element.addEventListener(evd, c_ch_o.observe(target), { once: true });
|
||||
scope.pop();
|
||||
return target.append(out);
|
||||
}
|
||||
function nt(t) {
|
||||
return j(t.prototype, "connectedCallback", function(e, r, n) {
|
||||
e.apply(r, n), r.dispatchEvent(new Event(v));
|
||||
}), j(t.prototype, "disconnectedCallback", function(e, r, n) {
|
||||
e.apply(r, n), (globalThis.queueMicrotask || setTimeout)(
|
||||
() => !r.isConnected && r.dispatchEvent(new Event(w))
|
||||
function lifecyclesToEvents(class_declaration) {
|
||||
wrapMethod(class_declaration.prototype, "connectedCallback", function(target, thisArg, detail) {
|
||||
target.apply(thisArg, detail);
|
||||
thisArg.dispatchEvent(new Event(evc));
|
||||
});
|
||||
wrapMethod(class_declaration.prototype, "disconnectedCallback", function(target, thisArg, detail) {
|
||||
target.apply(thisArg, detail);
|
||||
(globalThis.queueMicrotask || setTimeout)(
|
||||
() => !thisArg.isConnected && thisArg.dispatchEvent(new Event(evd))
|
||||
);
|
||||
}), j(t.prototype, "attributeChangedCallback", function(e, r, n) {
|
||||
let [o, , c] = n;
|
||||
r.dispatchEvent(new CustomEvent(y, {
|
||||
detail: [o, c]
|
||||
})), e.apply(r, n);
|
||||
}), t.prototype[x] = !0, t;
|
||||
});
|
||||
wrapMethod(class_declaration.prototype, "attributeChangedCallback", function(target, thisArg, detail) {
|
||||
const [attribute, , value] = detail;
|
||||
thisArg.dispatchEvent(new CustomEvent(eva, {
|
||||
detail: [attribute, value]
|
||||
}));
|
||||
target.apply(thisArg, detail);
|
||||
});
|
||||
class_declaration.prototype[keyLTE] = true;
|
||||
return class_declaration;
|
||||
}
|
||||
function j(t, e, r) {
|
||||
t[e] = new Proxy(t[e] || (() => {
|
||||
}), { apply: r });
|
||||
function wrapMethod(obj, method, apply) {
|
||||
obj[method] = new Proxy(obj[method] || (() => {
|
||||
}), { apply });
|
||||
}
|
||||
function rt(t) {
|
||||
return q(t, (e, r) => e.getAttribute(r));
|
||||
function observedAttributes2(instance) {
|
||||
return observedAttributes(instance, (i, n) => i.getAttribute(n));
|
||||
}
|
||||
|
||||
// src/events.js
|
||||
function yt(t, e, r) {
|
||||
return e || (e = {}), function(o, ...c) {
|
||||
r && (c.unshift(o), o = typeof r == "function" ? r() : r);
|
||||
let d = c.length ? new CustomEvent(t, Object.assign({ detail: c[0] }, e)) : new Event(t, e);
|
||||
return o.dispatchEvent(d);
|
||||
function dispatchEvent(name, options, host) {
|
||||
if (typeof options === "function") {
|
||||
host = options;
|
||||
options = null;
|
||||
}
|
||||
if (!options) options = {};
|
||||
return function dispatch(element, ...d) {
|
||||
if (host) {
|
||||
d.unshift(element);
|
||||
element = typeof host === "function" ? host() : host;
|
||||
}
|
||||
const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options);
|
||||
return element.dispatchEvent(event);
|
||||
};
|
||||
}
|
||||
function D(t, e, r) {
|
||||
return function(o) {
|
||||
return o.addEventListener(t, e, r), o;
|
||||
function on(event, listener, options) {
|
||||
return function registerElement(element) {
|
||||
element.addEventListener(event, listener, options);
|
||||
return element;
|
||||
};
|
||||
}
|
||||
var B = (t) => Object.assign({}, typeof t == "object" ? t : null, { once: !0 });
|
||||
D.connected = function(t, e) {
|
||||
return e = B(e), function(n) {
|
||||
return n.addEventListener(v, t, e), n[x] ? n : n.isConnected ? (n.dispatchEvent(new Event(v)), n) : (L(e.signal, () => _.offConnected(n, t)) && _.onConnected(n, t), n);
|
||||
var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true });
|
||||
on.connected = function(listener, options) {
|
||||
options = lifeOptions(options);
|
||||
return function registerElement(element) {
|
||||
element.addEventListener(evc, listener, options);
|
||||
if (element[keyLTE]) return element;
|
||||
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
|
||||
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
|
||||
if (c) c_ch_o.onConnected(element, listener);
|
||||
return element;
|
||||
};
|
||||
};
|
||||
D.disconnected = function(t, e) {
|
||||
return e = B(e), function(n) {
|
||||
return n.addEventListener(w, t, e), n[x] || L(e.signal, () => _.offDisconnected(n, t)) && _.onDisconnected(n, t), n;
|
||||
on.disconnected = function(listener, options) {
|
||||
options = lifeOptions(options);
|
||||
return function registerElement(element) {
|
||||
element.addEventListener(evd, listener, options);
|
||||
if (element[keyLTE]) return element;
|
||||
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
|
||||
if (c) c_ch_o.onDisconnected(element, listener);
|
||||
return element;
|
||||
};
|
||||
};
|
||||
var W = /* @__PURE__ */ new WeakMap();
|
||||
D.disconnectedAsAbort = function(t) {
|
||||
if (W.has(t)) return W.get(t);
|
||||
let e = new AbortController();
|
||||
return W.set(t, e), t(D.disconnected(() => e.abort())), e;
|
||||
var store_abort = /* @__PURE__ */ new WeakMap();
|
||||
on.disconnectedAsAbort = function(host) {
|
||||
if (store_abort.has(host)) return store_abort.get(host);
|
||||
const a = new AbortController();
|
||||
store_abort.set(host, a);
|
||||
host(on.disconnected(() => a.abort()));
|
||||
return a.signal;
|
||||
};
|
||||
var ot = /* @__PURE__ */ new WeakSet();
|
||||
D.attributeChanged = function(t, e) {
|
||||
return typeof e != "object" && (e = {}), function(n) {
|
||||
if (n.addEventListener(y, t, e), n[x] || ot.has(n) || !a.M) return n;
|
||||
let o = new a.M(function(d) {
|
||||
for (let { attributeName: f, target: p } of d)
|
||||
p.dispatchEvent(
|
||||
new CustomEvent(y, { detail: [f, p.getAttribute(f)] })
|
||||
var els_attribute_store = /* @__PURE__ */ new WeakSet();
|
||||
on.attributeChanged = function(listener, options) {
|
||||
if (typeof options !== "object")
|
||||
options = {};
|
||||
return function registerElement(element) {
|
||||
element.addEventListener(eva, listener, options);
|
||||
if (element[keyLTE] || els_attribute_store.has(element))
|
||||
return element;
|
||||
if (!enviroment.M) return element;
|
||||
const observer = new enviroment.M(function(mutations) {
|
||||
for (const { attributeName, target } of mutations)
|
||||
target.dispatchEvent(
|
||||
new CustomEvent(eva, { detail: [attributeName, target.getAttribute(attributeName)] })
|
||||
);
|
||||
});
|
||||
return L(e.signal, () => o.disconnect()) && o.observe(n, { attributes: !0 }), n;
|
||||
const c = onAbort(options.signal, () => observer.disconnect());
|
||||
if (c) observer.observe(element, { attributes: true });
|
||||
return element;
|
||||
};
|
||||
};
|
||||
export {
|
||||
R as assign,
|
||||
U as assignAttribute,
|
||||
J as chainableAppend,
|
||||
K as classListDeclarative,
|
||||
P as createElement,
|
||||
pt as createElementNS,
|
||||
wt as customElementRender,
|
||||
nt as customElementWithDDE,
|
||||
yt as dispatchEvent,
|
||||
P as el,
|
||||
pt as elNS,
|
||||
Q as elementAttribute,
|
||||
nt as lifecyclesToEvents,
|
||||
rt as observedAttributes,
|
||||
D as on,
|
||||
dt as queue,
|
||||
Z as registerReactivity,
|
||||
O as scope,
|
||||
lt as simulateSlots
|
||||
assign,
|
||||
assignAttribute,
|
||||
chainableAppend,
|
||||
classListDeclarative,
|
||||
createElement,
|
||||
createElementNS,
|
||||
customElementRender,
|
||||
lifecyclesToEvents as customElementWithDDE,
|
||||
dispatchEvent,
|
||||
createElement as el,
|
||||
createElementNS as elNS,
|
||||
elementAttribute,
|
||||
lifecyclesToEvents,
|
||||
observedAttributes2 as observedAttributes,
|
||||
on,
|
||||
queue,
|
||||
registerReactivity,
|
||||
scope,
|
||||
simulateSlots
|
||||
};
|
||||
|
782
dist/esm.min.d.ts
vendored
Normal file
782
dist/esm.min.d.ts
vendored
Normal file
@ -0,0 +1,782 @@
|
||||
// Generated by dts-bundle-generator v9.5.1
|
||||
|
||||
export interface Signal<V, A> {
|
||||
/** The current value of the signal */
|
||||
get(): V;
|
||||
/** Set new value of the signal */
|
||||
set(value: V): V;
|
||||
toJSON(): V;
|
||||
valueOf(): V;
|
||||
}
|
||||
export type Action<V> = (this: {
|
||||
value: V;
|
||||
stopPropagation(): void;
|
||||
}, ...a: any[]) => typeof signal._ | void;
|
||||
//type SymbolSignal= Symbol;
|
||||
export type SymbolOnclear = symbol;
|
||||
export type Actions<V> = Record<string | SymbolOnclear, Action<V>>;
|
||||
export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & {
|
||||
first_time?: boolean;
|
||||
};
|
||||
export interface signal {
|
||||
_: Symbol;
|
||||
/**
|
||||
* Computations signal. This creates a signal which is computed from other signals.
|
||||
* */
|
||||
<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>;
|
||||
/**
|
||||
* Simple example:
|
||||
* ```js
|
||||
* const hello= S("Hello Signal");
|
||||
* ```
|
||||
* …simple todo signal:
|
||||
* ```js
|
||||
* const todos= S([], {
|
||||
* add(v){ this.value.push(S(v)); },
|
||||
* remove(i){ this.value.splice(i, 1); },
|
||||
* [S.symbols.onclear](){ S.clear(...this.value); },
|
||||
* });
|
||||
* ```
|
||||
* …computed signal:
|
||||
* ```js
|
||||
* const name= S("Jan");
|
||||
* const surname= S("Andrle");
|
||||
* const fullname= S(()=> name.get()+" "+surname.get());
|
||||
* ```
|
||||
* @param value Initial signal value. Or function computing value from other signals.
|
||||
* @param actions Use to define actions on the signal. Such as add item to the array.
|
||||
* There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared
|
||||
* by `S.clear`.
|
||||
* */
|
||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void;
|
||||
clear(...signals: Signal<any, any>[]): void;
|
||||
on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void;
|
||||
symbols: {
|
||||
//signal: SymbolSignal;
|
||||
onclear: SymbolOnclear;
|
||||
};
|
||||
/**
|
||||
* Reactive element, which is rendered based on the given signal.
|
||||
* ```js
|
||||
* S.el(signal, value=> value ? el("b", "True") : el("i", "False"));
|
||||
* S.el(listS, list=> list.map(li=> el("li", li)));
|
||||
* ```
|
||||
* */
|
||||
el<S extends any>(signal: Signal<S, any>, el: (v: S) => Element | Element[] | DocumentFragment): DocumentFragment;
|
||||
observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>;
|
||||
}
|
||||
declare const signal: signal;
|
||||
declare global {
|
||||
type ddeSignal<T, A = {}> = Signal<T, A>;
|
||||
type ddeAction<V> = Action<V>;
|
||||
type ddeActions<V> = Actions<V>;
|
||||
}
|
||||
export type CustomElementTagNameMap = {
|
||||
"#text": Text;
|
||||
"#comment": Comment;
|
||||
};
|
||||
export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
||||
declare global {
|
||||
type ddeComponentAttributes = Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El) => any;
|
||||
type ddeString = string | Signal<string, {}>;
|
||||
type ddeStringable = ddeString | number | Signal<number, {}>;
|
||||
}
|
||||
export type PascalCase = `${Capitalize<string>}${string}`;
|
||||
export type AttrsModified = {
|
||||
/**
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString | Partial<{
|
||||
[K in keyof CSSStyleDeclaration]: Signal<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.
|
||||
*/
|
||||
classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>;
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
*
|
||||
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap)
|
||||
* */
|
||||
dataset: Record<string, ddeStringable>;
|
||||
/**
|
||||
* Sets `aria-*` simiraly to `dataset`
|
||||
* */
|
||||
ariaset: Record<string, ddeString>;
|
||||
} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>;
|
||||
export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>;
|
||||
export type IsReadonly<T, K extends keyof T> = T extends {
|
||||
readonly [P in K]: T[K];
|
||||
} ? true : false;
|
||||
/**
|
||||
* 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)).
|
||||
*
|
||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||
* @private
|
||||
*/
|
||||
export type ElementAttributes<T extends SupportedElement> = Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable);
|
||||
} & 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 assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT];
|
||||
export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(attrs: {
|
||||
type: "component" | "reactive" | "later";
|
||||
name?: string;
|
||||
host?: "this" | "parentElement";
|
||||
}, is_open?: boolean): Comment;
|
||||
}
|
||||
export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<A extends {
|
||||
textContent: ddeStringable;
|
||||
}, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement);
|
||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement;
|
||||
export function el(tag_name?: "<>"): ddeDocumentFragment;
|
||||
export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement;
|
||||
export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement;
|
||||
export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean;
|
||||
}>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement;
|
||||
export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement;
|
||||
export function chainableAppend<EL extends SupportedElement>(el: EL): EL;
|
||||
/** Simulate slots for ddeComponents */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL;
|
||||
/**
|
||||
* Simulate slots in Custom Elements without using `shadowRoot`.
|
||||
* @param el Custom Element root element
|
||||
* @param body Body of the custom element
|
||||
* */
|
||||
export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, element: SupportedElement): (data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void;
|
||||
declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, element: SupportedElement | (() => SupportedElement)): (data?: any) => void;
|
||||
export interface On {
|
||||
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||
<Event extends keyof DocumentEventMap, EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: Event, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: DocumentEventMap[Event]) => any, options?: AddEventListenerOptions): EE;
|
||||
<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
connected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<El>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
disconnected<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): 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 */ // editorconfig-checker-disable-line
|
||||
attributeChanged<EE extends ddeElementAddon<SupportedElement>, El extends (EE extends ddeElementAddon<infer El> ? El : never)>(listener: (this: El, event: CustomEvent<[
|
||||
string,
|
||||
string
|
||||
]>) => any, options?: AddEventListenerOptions): EE;
|
||||
}
|
||||
export const on: On;
|
||||
export 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}) */
|
||||
export const scope: {
|
||||
current: Scope;
|
||||
/** Stops all automatizations. E. g. signals used as attributes in current scope
|
||||
* registers removing these listeners (and clean signal if no other listeners are detected)
|
||||
* on `disconnected` event. */
|
||||
preventDefault<T extends boolean>(prevent: T): T;
|
||||
/**
|
||||
* This represents reference to the current host element — `scope.host()`.
|
||||
* It can be also used to register Addon(s) (functions to be called when component is initized)
|
||||
* — `scope.host(on.connected(console.log))`.
|
||||
* */
|
||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||
state: Scope[];
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>;
|
||||
/** Removes last/current child scope. */
|
||||
pop(): ReturnType<Array<Scope>["pop"]>;
|
||||
};
|
||||
export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL;
|
||||
export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL;
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>;
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
/* TypeScript MEH */
|
||||
declare global {
|
||||
type ddeAppend<el> = (...nodes: (Node | string)[]) => el;
|
||||
interface ddeDocumentFragment extends DocumentFragment {
|
||||
append: ddeAppend<ddeDocumentFragment>;
|
||||
}
|
||||
interface ddeHTMLElement extends HTMLElement {
|
||||
append: ddeAppend<ddeHTMLElement>;
|
||||
}
|
||||
interface ddeSVGElement extends SVGElement {
|
||||
append: ddeAppend<ddeSVGElement>;
|
||||
}
|
||||
interface ddeMathMLElement extends MathMLElement {
|
||||
append: ddeAppend<ddeMathMLElement>;
|
||||
}
|
||||
interface ddeHTMLElementTagNameMap {
|
||||
"a": ddeHTMLAnchorElement;
|
||||
"area": ddeHTMLAreaElement;
|
||||
"audio": ddeHTMLAudioElement;
|
||||
"base": ddeHTMLBaseElement;
|
||||
"blockquote": ddeHTMLQuoteElement;
|
||||
"body": ddeHTMLBodyElement;
|
||||
"br": ddeHTMLBRElement;
|
||||
"button": ddeHTMLButtonElement;
|
||||
"canvas": ddeHTMLCanvasElement;
|
||||
"caption": ddeHTMLTableCaptionElement;
|
||||
"col": ddeHTMLTableColElement;
|
||||
"colgroup": ddeHTMLTableColElement;
|
||||
"data": ddeHTMLDataElement;
|
||||
"datalist": ddeHTMLDataListElement;
|
||||
"del": ddeHTMLModElement;
|
||||
"details": ddeHTMLDetailsElement;
|
||||
"dialog": ddeHTMLDialogElement;
|
||||
"div": ddeHTMLDivElement;
|
||||
"dl": ddeHTMLDListElement;
|
||||
"embed": ddeHTMLEmbedElement;
|
||||
"fieldset": ddeHTMLFieldSetElement;
|
||||
"form": ddeHTMLFormElement;
|
||||
"h1": ddeHTMLHeadingElement;
|
||||
"h2": ddeHTMLHeadingElement;
|
||||
"h3": ddeHTMLHeadingElement;
|
||||
"h4": ddeHTMLHeadingElement;
|
||||
"h5": ddeHTMLHeadingElement;
|
||||
"h6": ddeHTMLHeadingElement;
|
||||
"head": ddeHTMLHeadElement;
|
||||
"hr": ddeHTMLHRElement;
|
||||
"html": ddeHTMLHtmlElement;
|
||||
"iframe": ddeHTMLIFrameElement;
|
||||
"img": ddeHTMLImageElement;
|
||||
"input": ddeHTMLInputElement;
|
||||
"ins": ddeHTMLModElement;
|
||||
"label": ddeHTMLLabelElement;
|
||||
"legend": ddeHTMLLegendElement;
|
||||
"li": ddeHTMLLIElement;
|
||||
"link": ddeHTMLLinkElement;
|
||||
"map": ddeHTMLMapElement;
|
||||
"menu": ddeHTMLMenuElement;
|
||||
"meta": ddeHTMLMetaElement;
|
||||
"meter": ddeHTMLMeterElement;
|
||||
"object": ddeHTMLObjectElement;
|
||||
"ol": ddeHTMLOListElement;
|
||||
"optgroup": ddeHTMLOptGroupElement;
|
||||
"option": ddeHTMLOptionElement;
|
||||
"output": ddeHTMLOutputElement;
|
||||
"p": ddeHTMLParagraphElement;
|
||||
"picture": ddeHTMLPictureElement;
|
||||
"pre": ddeHTMLPreElement;
|
||||
"progress": ddeHTMLProgressElement;
|
||||
"q": ddeHTMLQuoteElement;
|
||||
"script": ddeHTMLScriptElement;
|
||||
"select": ddeHTMLSelectElement;
|
||||
"slot": ddeHTMLSlotElement;
|
||||
"source": ddeHTMLSourceElement;
|
||||
"span": ddeHTMLSpanElement;
|
||||
"style": ddeHTMLStyleElement;
|
||||
"table": ddeHTMLTableElement;
|
||||
"tbody": ddeHTMLTableSectionElement;
|
||||
"td": ddeHTMLTableCellElement;
|
||||
"template": ddeHTMLTemplateElement;
|
||||
"textarea": ddeHTMLTextAreaElement;
|
||||
"tfoot": ddeHTMLTableSectionElement;
|
||||
"th": ddeHTMLTableCellElement;
|
||||
"thead": ddeHTMLTableSectionElement;
|
||||
"time": ddeHTMLTimeElement;
|
||||
"title": ddeHTMLTitleElement;
|
||||
"tr": ddeHTMLTableRowElement;
|
||||
"track": ddeHTMLTrackElement;
|
||||
"ul": ddeHTMLUListElement;
|
||||
"video": ddeHTMLVideoElement;
|
||||
}
|
||||
interface ddeSVGElementTagNameMap {
|
||||
"a": ddeSVGAElement;
|
||||
"animate": ddeSVGAnimateElement;
|
||||
"animateMotion": ddeSVGAnimateMotionElement;
|
||||
"animateTransform": ddeSVGAnimateTransformElement;
|
||||
"circle": ddeSVGCircleElement;
|
||||
"clipPath": ddeSVGClipPathElement;
|
||||
"defs": ddeSVGDefsElement;
|
||||
"desc": ddeSVGDescElement;
|
||||
"ellipse": ddeSVGEllipseElement;
|
||||
"feBlend": ddeSVGFEBlendElement;
|
||||
"feColorMatrix": ddeSVGFEColorMatrixElement;
|
||||
"feComponentTransfer": ddeSVGFEComponentTransferElement;
|
||||
"feComposite": ddeSVGFECompositeElement;
|
||||
"feConvolveMatrix": ddeSVGFEConvolveMatrixElement;
|
||||
"feDiffuseLighting": ddeSVGFEDiffuseLightingElement;
|
||||
"feDisplacementMap": ddeSVGFEDisplacementMapElement;
|
||||
"feDistantLight": ddeSVGFEDistantLightElement;
|
||||
"feDropShadow": ddeSVGFEDropShadowElement;
|
||||
"feFlood": ddeSVGFEFloodElement;
|
||||
"feFuncA": ddeSVGFEFuncAElement;
|
||||
"feFuncB": ddeSVGFEFuncBElement;
|
||||
"feFuncG": ddeSVGFEFuncGElement;
|
||||
"feFuncR": ddeSVGFEFuncRElement;
|
||||
"feGaussianBlur": ddeSVGFEGaussianBlurElement;
|
||||
"feImage": ddeSVGFEImageElement;
|
||||
"feMerge": ddeSVGFEMergeElement;
|
||||
"feMergeNode": ddeSVGFEMergeNodeElement;
|
||||
"feMorphology": ddeSVGFEMorphologyElement;
|
||||
"feOffset": ddeSVGFEOffsetElement;
|
||||
"fePointLight": ddeSVGFEPointLightElement;
|
||||
"feSpecularLighting": ddeSVGFESpecularLightingElement;
|
||||
"feSpotLight": ddeSVGFESpotLightElement;
|
||||
"feTile": ddeSVGFETileElement;
|
||||
"feTurbulence": ddeSVGFETurbulenceElement;
|
||||
"filter": ddeSVGFilterElement;
|
||||
"foreignObject": ddeSVGForeignObjectElement;
|
||||
"g": ddeSVGGElement;
|
||||
"image": ddeSVGImageElement;
|
||||
"line": ddeSVGLineElement;
|
||||
"linearGradient": ddeSVGLinearGradientElement;
|
||||
"marker": ddeSVGMarkerElement;
|
||||
"mask": ddeSVGMaskElement;
|
||||
"metadata": ddeSVGMetadataElement;
|
||||
"mpath": ddeSVGMPathElement;
|
||||
"path": ddeSVGPathElement;
|
||||
"pattern": ddeSVGPatternElement;
|
||||
"polygon": ddeSVGPolygonElement;
|
||||
"polyline": ddeSVGPolylineElement;
|
||||
"radialGradient": ddeSVGRadialGradientElement;
|
||||
"rect": ddeSVGRectElement;
|
||||
"script": ddeSVGScriptElement;
|
||||
"set": ddeSVGSetElement;
|
||||
"stop": ddeSVGStopElement;
|
||||
"style": ddeSVGStyleElement;
|
||||
"svg": ddeSVGSVGElement;
|
||||
"switch": ddeSVGSwitchElement;
|
||||
"symbol": ddeSVGSymbolElement;
|
||||
"text": ddeSVGTextElement;
|
||||
"textPath": ddeSVGTextPathElement;
|
||||
"title": ddeSVGTitleElement;
|
||||
"tspan": ddeSVGTSpanElement;
|
||||
"use": ddeSVGUseElement;
|
||||
"view": ddeSVGViewElement;
|
||||
}
|
||||
}
|
||||
// editorconfig-checker-disable
|
||||
export interface ddeHTMLAnchorElement extends HTMLAnchorElement {
|
||||
append: ddeAppend<ddeHTMLAnchorElement>;
|
||||
}
|
||||
export interface ddeHTMLAreaElement extends HTMLAreaElement {
|
||||
append: ddeAppend<ddeHTMLAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLAudioElement extends HTMLAudioElement {
|
||||
append: ddeAppend<ddeHTMLAudioElement>;
|
||||
}
|
||||
export interface ddeHTMLBaseElement extends HTMLBaseElement {
|
||||
append: ddeAppend<ddeHTMLBaseElement>;
|
||||
}
|
||||
export interface ddeHTMLQuoteElement extends HTMLQuoteElement {
|
||||
append: ddeAppend<ddeHTMLQuoteElement>;
|
||||
}
|
||||
export interface ddeHTMLBodyElement extends HTMLBodyElement {
|
||||
append: ddeAppend<ddeHTMLBodyElement>;
|
||||
}
|
||||
export interface ddeHTMLBRElement extends HTMLBRElement {
|
||||
append: ddeAppend<ddeHTMLBRElement>;
|
||||
}
|
||||
export interface ddeHTMLButtonElement extends HTMLButtonElement {
|
||||
append: ddeAppend<ddeHTMLButtonElement>;
|
||||
}
|
||||
export interface ddeHTMLCanvasElement extends HTMLCanvasElement {
|
||||
append: ddeAppend<ddeHTMLCanvasElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement {
|
||||
append: ddeAppend<ddeHTMLTableCaptionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLTableColElement extends HTMLTableColElement {
|
||||
append: ddeAppend<ddeHTMLTableColElement>;
|
||||
}
|
||||
export interface ddeHTMLDataElement extends HTMLDataElement {
|
||||
append: ddeAppend<ddeHTMLDataElement>;
|
||||
}
|
||||
export interface ddeHTMLDataListElement extends HTMLDataListElement {
|
||||
append: ddeAppend<ddeHTMLDataListElement>;
|
||||
}
|
||||
export interface ddeHTMLModElement extends HTMLModElement {
|
||||
append: ddeAppend<ddeHTMLModElement>;
|
||||
}
|
||||
export interface ddeHTMLDetailsElement extends HTMLDetailsElement {
|
||||
append: ddeAppend<ddeHTMLDetailsElement>;
|
||||
}
|
||||
export interface ddeHTMLDialogElement extends HTMLDialogElement {
|
||||
append: ddeAppend<ddeHTMLDialogElement>;
|
||||
}
|
||||
export interface ddeHTMLDivElement extends HTMLDivElement {
|
||||
append: ddeAppend<ddeHTMLDivElement>;
|
||||
}
|
||||
export interface ddeHTMLDListElement extends HTMLDListElement {
|
||||
append: ddeAppend<ddeHTMLDListElement>;
|
||||
}
|
||||
export interface ddeHTMLEmbedElement extends HTMLEmbedElement {
|
||||
append: ddeAppend<ddeHTMLEmbedElement>;
|
||||
}
|
||||
export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement {
|
||||
append: ddeAppend<ddeHTMLFieldSetElement>;
|
||||
}
|
||||
export interface ddeHTMLFormElement extends HTMLFormElement {
|
||||
append: ddeAppend<ddeHTMLFormElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadingElement extends HTMLHeadingElement {
|
||||
append: ddeAppend<ddeHTMLHeadingElement>;
|
||||
}
|
||||
export interface ddeHTMLHeadElement extends HTMLHeadElement {
|
||||
append: ddeAppend<ddeHTMLHeadElement>;
|
||||
}
|
||||
export interface ddeHTMLHRElement extends HTMLHRElement {
|
||||
append: ddeAppend<ddeHTMLHRElement>;
|
||||
}
|
||||
export interface ddeHTMLHtmlElement extends HTMLHtmlElement {
|
||||
append: ddeAppend<ddeHTMLHtmlElement>;
|
||||
}
|
||||
export interface ddeHTMLIFrameElement extends HTMLIFrameElement {
|
||||
append: ddeAppend<ddeHTMLIFrameElement>;
|
||||
}
|
||||
export interface ddeHTMLImageElement extends HTMLImageElement {
|
||||
append: ddeAppend<ddeHTMLImageElement>;
|
||||
}
|
||||
export interface ddeHTMLInputElement extends HTMLInputElement {
|
||||
append: ddeAppend<ddeHTMLInputElement>;
|
||||
}
|
||||
export interface ddeHTMLLabelElement extends HTMLLabelElement {
|
||||
append: ddeAppend<ddeHTMLLabelElement>;
|
||||
}
|
||||
export interface ddeHTMLLegendElement extends HTMLLegendElement {
|
||||
append: ddeAppend<ddeHTMLLegendElement>;
|
||||
}
|
||||
export interface ddeHTMLLIElement extends HTMLLIElement {
|
||||
append: ddeAppend<ddeHTMLLIElement>;
|
||||
}
|
||||
export interface ddeHTMLLinkElement extends HTMLLinkElement {
|
||||
append: ddeAppend<ddeHTMLLinkElement>;
|
||||
}
|
||||
export interface ddeHTMLMapElement extends HTMLMapElement {
|
||||
append: ddeAppend<ddeHTMLMapElement>;
|
||||
}
|
||||
export interface ddeHTMLMenuElement extends HTMLMenuElement {
|
||||
append: ddeAppend<ddeHTMLMenuElement>;
|
||||
}
|
||||
export interface ddeHTMLMetaElement extends HTMLMetaElement {
|
||||
append: ddeAppend<ddeHTMLMetaElement>;
|
||||
}
|
||||
export interface ddeHTMLMeterElement extends HTMLMeterElement {
|
||||
append: ddeAppend<ddeHTMLMeterElement>;
|
||||
}
|
||||
export interface ddeHTMLObjectElement extends HTMLObjectElement {
|
||||
append: ddeAppend<ddeHTMLObjectElement>;
|
||||
}
|
||||
export interface ddeHTMLOListElement extends HTMLOListElement {
|
||||
append: ddeAppend<ddeHTMLOListElement>;
|
||||
}
|
||||
export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement {
|
||||
append: ddeAppend<ddeHTMLOptGroupElement>;
|
||||
}
|
||||
export interface ddeHTMLOptionElement extends HTMLOptionElement {
|
||||
append: ddeAppend<ddeHTMLOptionElement>;
|
||||
}
|
||||
export interface ddeHTMLOutputElement extends HTMLOutputElement {
|
||||
append: ddeAppend<ddeHTMLOutputElement>;
|
||||
}
|
||||
export interface ddeHTMLParagraphElement extends HTMLParagraphElement {
|
||||
append: ddeAppend<ddeHTMLParagraphElement>;
|
||||
}
|
||||
export interface ddeHTMLPictureElement extends HTMLPictureElement {
|
||||
append: ddeAppend<ddeHTMLPictureElement>;
|
||||
}
|
||||
export interface ddeHTMLPreElement extends HTMLPreElement {
|
||||
append: ddeAppend<ddeHTMLPreElement>;
|
||||
}
|
||||
export interface ddeHTMLProgressElement extends HTMLProgressElement {
|
||||
append: ddeAppend<ddeHTMLProgressElement>;
|
||||
}
|
||||
export interface ddeHTMLScriptElement extends HTMLScriptElement {
|
||||
append: ddeAppend<ddeHTMLScriptElement>;
|
||||
}
|
||||
export interface ddeHTMLSelectElement extends HTMLSelectElement {
|
||||
append: ddeAppend<ddeHTMLSelectElement>;
|
||||
}
|
||||
export interface ddeHTMLSlotElement extends HTMLSlotElement {
|
||||
append: ddeAppend<ddeHTMLSlotElement>;
|
||||
}
|
||||
export interface ddeHTMLSourceElement extends HTMLSourceElement {
|
||||
append: ddeAppend<ddeHTMLSourceElement>;
|
||||
}
|
||||
export interface ddeHTMLSpanElement extends HTMLSpanElement {
|
||||
append: ddeAppend<ddeHTMLSpanElement>;
|
||||
}
|
||||
export interface ddeHTMLStyleElement extends HTMLStyleElement {
|
||||
append: ddeAppend<ddeHTMLStyleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableElement extends HTMLTableElement {
|
||||
append: ddeAppend<ddeHTMLTableElement>;
|
||||
}
|
||||
export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement {
|
||||
append: ddeAppend<ddeHTMLTableSectionElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTemplateElement extends HTMLTemplateElement {
|
||||
append: ddeAppend<ddeHTMLTemplateElement>;
|
||||
}
|
||||
export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement {
|
||||
append: ddeAppend<ddeHTMLTextAreaElement>;
|
||||
}
|
||||
export interface ddeHTMLTableCellElement extends HTMLTableCellElement {
|
||||
append: ddeAppend<ddeHTMLTableCellElement>;
|
||||
}
|
||||
export interface ddeHTMLTimeElement extends HTMLTimeElement {
|
||||
append: ddeAppend<ddeHTMLTimeElement>;
|
||||
}
|
||||
export interface ddeHTMLTitleElement extends HTMLTitleElement {
|
||||
append: ddeAppend<ddeHTMLTitleElement>;
|
||||
}
|
||||
export interface ddeHTMLTableRowElement extends HTMLTableRowElement {
|
||||
append: ddeAppend<ddeHTMLTableRowElement>;
|
||||
}
|
||||
export interface ddeHTMLTrackElement extends HTMLTrackElement {
|
||||
append: ddeAppend<ddeHTMLTrackElement>;
|
||||
}
|
||||
export interface ddeHTMLUListElement extends HTMLUListElement {
|
||||
append: ddeAppend<ddeHTMLUListElement>;
|
||||
}
|
||||
export interface ddeHTMLVideoElement extends HTMLVideoElement {
|
||||
append: ddeAppend<ddeHTMLVideoElement>;
|
||||
}
|
||||
export interface ddeSVGAElement extends SVGAElement {
|
||||
append: ddeAppend<ddeSVGAElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateElement extends SVGAnimateElement {
|
||||
append: ddeAppend<ddeSVGAnimateElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement {
|
||||
append: ddeAppend<ddeSVGAnimateMotionElement>;
|
||||
}
|
||||
export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement {
|
||||
append: ddeAppend<ddeSVGAnimateTransformElement>;
|
||||
}
|
||||
export interface ddeSVGCircleElement extends SVGCircleElement {
|
||||
append: ddeAppend<ddeSVGCircleElement>;
|
||||
}
|
||||
export interface ddeSVGClipPathElement extends SVGClipPathElement {
|
||||
append: ddeAppend<ddeSVGClipPathElement>;
|
||||
}
|
||||
export interface ddeSVGDefsElement extends SVGDefsElement {
|
||||
append: ddeAppend<ddeSVGDefsElement>;
|
||||
}
|
||||
export interface ddeSVGDescElement extends SVGDescElement {
|
||||
append: ddeAppend<ddeSVGDescElement>;
|
||||
}
|
||||
export interface ddeSVGEllipseElement extends SVGEllipseElement {
|
||||
append: ddeAppend<ddeSVGEllipseElement>;
|
||||
}
|
||||
export interface ddeSVGFEBlendElement extends SVGFEBlendElement {
|
||||
append: ddeAppend<ddeSVGFEBlendElement>;
|
||||
}
|
||||
export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEColorMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement {
|
||||
append: ddeAppend<ddeSVGFEComponentTransferElement>;
|
||||
}
|
||||
export interface ddeSVGFECompositeElement extends SVGFECompositeElement {
|
||||
append: ddeAppend<ddeSVGFECompositeElement>;
|
||||
}
|
||||
export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement {
|
||||
append: ddeAppend<ddeSVGFEConvolveMatrixElement>;
|
||||
}
|
||||
export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement {
|
||||
append: ddeAppend<ddeSVGFEDiffuseLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement {
|
||||
append: ddeAppend<ddeSVGFEDisplacementMapElement>;
|
||||
}
|
||||
export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement {
|
||||
append: ddeAppend<ddeSVGFEDistantLightElement>;
|
||||
}
|
||||
export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement {
|
||||
append: ddeAppend<ddeSVGFEDropShadowElement>;
|
||||
}
|
||||
export interface ddeSVGFEFloodElement extends SVGFEFloodElement {
|
||||
append: ddeAppend<ddeSVGFEFloodElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement {
|
||||
append: ddeAppend<ddeSVGFEFuncAElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement {
|
||||
append: ddeAppend<ddeSVGFEFuncBElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement {
|
||||
append: ddeAppend<ddeSVGFEFuncGElement>;
|
||||
}
|
||||
export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement {
|
||||
append: ddeAppend<ddeSVGFEFuncRElement>;
|
||||
}
|
||||
export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement {
|
||||
append: ddeAppend<ddeSVGFEGaussianBlurElement>;
|
||||
}
|
||||
export interface ddeSVGFEImageElement extends SVGFEImageElement {
|
||||
append: ddeAppend<ddeSVGFEImageElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeElement extends SVGFEMergeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement {
|
||||
append: ddeAppend<ddeSVGFEMergeNodeElement>;
|
||||
}
|
||||
export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement {
|
||||
append: ddeAppend<ddeSVGFEMorphologyElement>;
|
||||
}
|
||||
export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement {
|
||||
append: ddeAppend<ddeSVGFEOffsetElement>;
|
||||
}
|
||||
export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement {
|
||||
append: ddeAppend<ddeSVGFEPointLightElement>;
|
||||
}
|
||||
export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement {
|
||||
append: ddeAppend<ddeSVGFESpecularLightingElement>;
|
||||
}
|
||||
export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement {
|
||||
append: ddeAppend<ddeSVGFESpotLightElement>;
|
||||
}
|
||||
export interface ddeSVGFETileElement extends SVGFETileElement {
|
||||
append: ddeAppend<ddeSVGFETileElement>;
|
||||
}
|
||||
export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement {
|
||||
append: ddeAppend<ddeSVGFETurbulenceElement>;
|
||||
}
|
||||
export interface ddeSVGFilterElement extends SVGFilterElement {
|
||||
append: ddeAppend<ddeSVGFilterElement>;
|
||||
}
|
||||
export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement {
|
||||
append: ddeAppend<ddeSVGForeignObjectElement>;
|
||||
}
|
||||
export interface ddeSVGGElement extends SVGGElement {
|
||||
append: ddeAppend<ddeSVGGElement>;
|
||||
}
|
||||
export interface ddeSVGImageElement extends SVGImageElement {
|
||||
append: ddeAppend<ddeSVGImageElement>;
|
||||
}
|
||||
export interface ddeSVGLineElement extends SVGLineElement {
|
||||
append: ddeAppend<ddeSVGLineElement>;
|
||||
}
|
||||
export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement {
|
||||
append: ddeAppend<ddeSVGLinearGradientElement>;
|
||||
}
|
||||
export interface ddeSVGMarkerElement extends SVGMarkerElement {
|
||||
append: ddeAppend<ddeSVGMarkerElement>;
|
||||
}
|
||||
export interface ddeSVGMaskElement extends SVGMaskElement {
|
||||
append: ddeAppend<ddeSVGMaskElement>;
|
||||
}
|
||||
export interface ddeSVGMetadataElement extends SVGMetadataElement {
|
||||
append: ddeAppend<ddeSVGMetadataElement>;
|
||||
}
|
||||
export interface ddeSVGMPathElement extends SVGMPathElement {
|
||||
append: ddeAppend<ddeSVGMPathElement>;
|
||||
}
|
||||
export interface ddeSVGPathElement extends SVGPathElement {
|
||||
append: ddeAppend<ddeSVGPathElement>;
|
||||
}
|
||||
export interface ddeSVGPatternElement extends SVGPatternElement {
|
||||
append: ddeAppend<ddeSVGPatternElement>;
|
||||
}
|
||||
export interface ddeSVGPolygonElement extends SVGPolygonElement {
|
||||
append: ddeAppend<ddeSVGPolygonElement>;
|
||||
}
|
||||
export interface ddeSVGPolylineElement extends SVGPolylineElement {
|
||||
append: ddeAppend<ddeSVGPolylineElement>;
|
||||
}
|
||||
export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement {
|
||||
append: ddeAppend<ddeSVGRadialGradientElement>;
|
||||
}
|
||||
export interface ddeSVGRectElement extends SVGRectElement {
|
||||
append: ddeAppend<ddeSVGRectElement>;
|
||||
}
|
||||
export interface ddeSVGScriptElement extends SVGScriptElement {
|
||||
append: ddeAppend<ddeSVGScriptElement>;
|
||||
}
|
||||
export interface ddeSVGSetElement extends SVGSetElement {
|
||||
append: ddeAppend<ddeSVGSetElement>;
|
||||
}
|
||||
export interface ddeSVGStopElement extends SVGStopElement {
|
||||
append: ddeAppend<ddeSVGStopElement>;
|
||||
}
|
||||
export interface ddeSVGStyleElement extends SVGStyleElement {
|
||||
append: ddeAppend<ddeSVGStyleElement>;
|
||||
}
|
||||
export interface ddeSVGSVGElement extends SVGSVGElement {
|
||||
append: ddeAppend<ddeSVGSVGElement>;
|
||||
}
|
||||
export interface ddeSVGSwitchElement extends SVGSwitchElement {
|
||||
append: ddeAppend<ddeSVGSwitchElement>;
|
||||
}
|
||||
export interface ddeSVGSymbolElement extends SVGSymbolElement {
|
||||
append: ddeAppend<ddeSVGSymbolElement>;
|
||||
}
|
||||
export interface ddeSVGTextElement extends SVGTextElement {
|
||||
append: ddeAppend<ddeSVGTextElement>;
|
||||
}
|
||||
export interface ddeSVGTextPathElement extends SVGTextPathElement {
|
||||
append: ddeAppend<ddeSVGTextPathElement>;
|
||||
}
|
||||
export interface ddeSVGTitleElement extends SVGTitleElement {
|
||||
append: ddeAppend<ddeSVGTitleElement>;
|
||||
}
|
||||
export interface ddeSVGTSpanElement extends SVGTSpanElement {
|
||||
append: ddeAppend<ddeSVGTSpanElement>;
|
||||
}
|
||||
export interface ddeSVGUseElement extends SVGUseElement {
|
||||
append: ddeAppend<ddeSVGUseElement>;
|
||||
}
|
||||
export interface ddeSVGViewElement extends SVGViewElement {
|
||||
append: ddeAppend<ddeSVGViewElement>;
|
||||
}
|
||||
|
||||
export {
|
||||
dispatchEvent$1 as dispatchEvent,
|
||||
el as createElement,
|
||||
elNS as createElementNS,
|
||||
};
|
||||
|
||||
export {};
|
1
dist/esm.min.js
vendored
Normal file
1
dist/esm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
60
docs/assets/favicon.svg
Normal file
60
docs/assets/favicon.svg
Normal file
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
sodipodi:docname="favicon.svg"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs2" /><sodipodi:namedview
|
||||
id="namedview2"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="9.3249707"
|
||||
inkscape:cx="38.230683"
|
||||
inkscape:cy="28.150223"
|
||||
inkscape:window-width="1278"
|
||||
inkscape:window-height="1023"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2" /><rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="64"
|
||||
height="64"
|
||||
rx="10"
|
||||
fill="#2b2b2b"
|
||||
id="rect1" /><g
|
||||
transform="matrix(0.98009485,0,0,1.1964871,0.58334513,-7.2134367)"
|
||||
id="g2"
|
||||
style="stroke:#666666"><g
|
||||
id="g3"
|
||||
transform="matrix(1.0027126,0,0,0.88864615,3.8540039,4.3371297)"
|
||||
style="stroke:#666666"><path
|
||||
d="M 8.880742,11.550781 2.9817709,32 8.880742,52.449219"
|
||||
stroke="#ff5252"
|
||||
stroke-width="4.25375"
|
||||
fill="none"
|
||||
id="path1"
|
||||
style="stroke:#666666" /><path
|
||||
d="M 47.330923,11.568743 53.261141,32 47.330923,52.431257"
|
||||
stroke="#ff5252"
|
||||
stroke-width="4.26309"
|
||||
fill="none"
|
||||
id="path2"
|
||||
style="stroke:#666666" /></g></g><path
|
||||
d="m 11.726038,32.656946 q 0,-2.685867 0.823088,-4.721927 0.823088,-2.036061 2.166022,-3.404987 1.342933,-1.360261 3.07575,-2.053387 1.732818,-0.693128 3.552275,-0.693128 4.505325,0 6.844629,2.659875 2.339303,2.668539 2.339303,7.780349 0,0.519846 -0.01733,1.083011 -0.02599,0.563166 -0.06931,0.90973 H 17.227733 q 0,1.992739 1.646176,3.145062 1.646176,1.14366 4.245402,1.14366 1.602856,0 3.058423,-0.346564 1.446902,-0.346563 2.443272,-0.693127 l 0.736447,4.548646 q -1.386253,0.476525 -2.945789,0.797097 -1.559536,0.329235 -3.508954,0.329235 -2.599226,0 -4.652615,-0.675799 -2.062053,-0.667135 -3.508955,-1.984075 -1.455566,-1.325605 -2.235335,-3.275025 -0.779767,-1.94942 -0.779767,-4.548646 m 13.645936,-2.1227 q 0,-0.823088 -0.216602,-1.585528 -0.216602,-0.753776 -0.693127,-1.360263 -0.476525,-0.606485 -1.212973,-0.979042 -0.736447,-0.363891 -1.819457,-0.363891 -1.039691,0 -1.793467,0.346563 -0.762439,0.346564 -1.264955,0.95305 -0.493854,0.606485 -0.771105,1.386253 -0.285915,0.77977 -0.372555,1.602856 z m 26.901988,11.263311 q -0.129961,0.08664 -0.589158,0.303244 -0.450533,0.216602 -1.18698,0.459196 -0.736448,0.23393 -1.793466,0.407211 -1.065682,0.173282 -2.408616,0.173282 -3.682236,0 -5.371734,-2.192014 -1.689496,-2.18335 -1.689496,-6.385432 V 17.278193 H 33.602856 V 12.85951 h 10.960069 v 22.093419 q 0,2.079381 0.823089,2.815829 0.823088,0.736447 2.07938,0.736447 1.602856,0 2.685867,-0.433204 1.08301,-0.433205 1.429574,-0.563166 z"
|
||||
id="path1-1"
|
||||
style="fill:#ff5252;stroke-width:0.866409" /></svg>
|
After Width: | Height: | Size: 3.3 KiB |
71
docs/assets/logo.svg
Normal file
71
docs/assets/logo.svg
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="256"
|
||||
height="256"
|
||||
viewBox="0 0 256 256"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs4"><linearGradient
|
||||
id="bgGradient"
|
||||
x1="18"
|
||||
y1="18"
|
||||
x2="238"
|
||||
y2="238"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.1363636,0,0,1.1363636,-17.454544,-17.454544)"><stop
|
||||
offset="0"
|
||||
stop-color="#3b3b3b"
|
||||
id="stop1" /><stop
|
||||
offset="1"
|
||||
stop-color="#2b2b2b"
|
||||
id="stop2" /></linearGradient><filter
|
||||
id="glow"
|
||||
x="-0.089563958"
|
||||
y="-0.082460006"
|
||||
width="1.1791279"
|
||||
height="1.16492"><feGaussianBlur
|
||||
stdDeviation="4"
|
||||
result="blur"
|
||||
id="feGaussianBlur4"
|
||||
in="SourceGraphic" /><feComposite
|
||||
in="SourceGraphic"
|
||||
in2="blur"
|
||||
operator="over"
|
||||
id="feComposite4"
|
||||
result="composite-0" /></filter></defs><rect
|
||||
x="3"
|
||||
y="3"
|
||||
width="250"
|
||||
height="250"
|
||||
fill="url(#bgGradient)"
|
||||
id="rect4"
|
||||
style="fill:url(#bgGradient);stroke-width:1.13636"
|
||||
ry="50" /><g
|
||||
id="g2"
|
||||
transform="translate(-3.5569814,-1.5165883)"><g
|
||||
id="g1"
|
||||
transform="matrix(1.5900346,0,0,1.5900346,-121.12651,-66.626074)"><g
|
||||
opacity="0.25"
|
||||
fill="#ffffff"
|
||||
filter="url(#glow)"
|
||||
id="g5"
|
||||
transform="matrix(0.55415879,0,0,0.56134669,110.90661,51.505106)"><path
|
||||
d="m 80,60 -30,68 30,68"
|
||||
stroke="#ffffff"
|
||||
stroke-width="8"
|
||||
fill="none"
|
||||
id="path4" /><path
|
||||
d="m 176,60 30,68 -30,68"
|
||||
stroke="#ffffff"
|
||||
stroke-width="8"
|
||||
fill="none"
|
||||
id="path5" /></g><path
|
||||
d="m 152.28246,124.58038 q 0,-4.06854 1.24681,-7.15275 1.24681,-3.08421 3.28107,-5.15785 2.03427,-2.06051 4.65913,-3.11046 2.62486,-1.04994 5.38096,-1.04994 6.82464,0 10.3682,4.02916 3.54356,4.04228 3.54356,11.78562 0,0.78746 -0.0263,1.64054 -0.0394,0.85308 -0.10499,1.37805 h -20.01456 q 0,3.01859 2.49362,4.76412 2.49362,1.73241 6.43091,1.73241 2.42799,0 4.63287,-0.52497 2.19176,-0.52497 3.70106,-1.04995 l 1.11556,6.89026 q -2.09989,0.72184 -4.46226,1.20744 -2.36237,0.49872 -5.31534,0.49872 -3.93729,0 -7.04775,-1.02369 -3.12359,-1.01058 -5.31534,-3.00547 -2.20489,-2.00802 -3.38607,-4.96098 -1.18114,-2.95297 -1.18114,-6.89026 m 20.67077,-3.21546 q 0,-1.2468 -0.3281,-2.40174 -0.32811,-1.14182 -1.04995,-2.06052 -0.72183,-0.9187 -1.8374,-1.48304 -1.11557,-0.55123 -2.7561,-0.55123 -1.57492,0 -2.71673,0.52498 -1.15494,0.52497 -1.91615,1.44367 -0.74809,0.9187 -1.16806,2.09989 -0.43311,1.18119 -0.56435,2.42799 z m 40.75096,17.06159 q -0.19687,0.13125 -0.89245,0.45936 -0.68247,0.3281 -1.79803,0.69558 -1.11557,0.35436 -2.71673,0.61685 -1.61429,0.26248 -3.64856,0.26248 -5.57783,0 -8.13707,-3.32045 -2.55923,-3.30732 -2.55923,-9.67261 v -26.18298 h -8.5308 v -6.693389 h 16.60224 v 33.466969 q 0,3.14983 1.24681,4.26539 1.24681,1.11557 3.14983,1.11557 2.428,0 4.06853,-0.65621 1.64054,-0.65622 2.16551,-0.85308 z"
|
||||
id="path1-3"
|
||||
style="fill:#ff5252;stroke-width:1.31243" /></g><path
|
||||
d="m 27.256467,130.12148 q 0,6.64555 2.489444,10.86495 2.468347,4.21939 7.953563,4.21939 1.582274,0 2.953578,-0.10548 1.371303,-0.10549 2.848092,-0.31646 v -27.00413 q -1.476789,-0.84388 -3.375517,-1.4346 -1.898728,-0.56962 -4.008427,-0.56962 -4.641336,0 -6.751034,3.69197 -2.109699,3.69198 -2.109699,10.65398 m 29.219322,23.62862 q -3.586487,1.16034 -8.755248,1.89873 -5.168761,0.7384 -10.126552,0.7384 -11.603341,0 -17.55269,-6.85651 -5.970447,-6.85652 -5.970447,-18.77632 0,-12.13076 5.021083,-19.15606 4.999985,-7.0042 14.810082,-7.0042 2.637123,0 5.168761,0.56962 2.531638,0.59072 4.430366,1.64557 V 84.235539 l 12.974645,-2.215183 z m 23.523136,-23.62862 q 0,6.64555 2.489444,10.86495 2.468344,4.21939 7.953559,4.21939 1.582268,0 2.953578,-0.10548 1.3713,-0.10549 2.84809,-0.31646 v -27.00413 q -1.47679,-0.84388 -3.37552,-1.4346 -1.89873,-0.56962 -4.008423,-0.56962 -4.64133,0 -6.75103,3.69197 -2.109698,3.69198 -2.109698,10.65398 m 29.219315,23.62862 q -3.58648,1.16034 -8.75524,1.89873 -5.168774,0.7384 -10.126562,0.7384 -11.603332,0 -17.552681,-6.85651 -5.970446,-6.85652 -5.970446,-18.77632 0,-12.13076 4.999984,-19.15606 5.021082,-7.0042 14.831178,-7.0042 2.63712,0 5.168753,0.56962 2.53164,0.59072 4.43037,1.64557 V 84.235539 l 12.974644,-2.215183 z"
|
||||
id="path1"
|
||||
style="fill:#ff5252;stroke-width:2.1097;fill-opacity:0.66479665" /></g></svg>
|
After Width: | Height: | Size: 4.6 KiB |
@ -1,28 +1,179 @@
|
||||
import { registerClientFile, styles } from "../ssr.js";
|
||||
const host= "."+code.name;
|
||||
styles.css`
|
||||
${host}{
|
||||
--shiki-color-text: #e9eded;
|
||||
--shiki-color-background: #212121;
|
||||
/* Code block styling */
|
||||
${host} {
|
||||
/* Theme for dark mode - matches Flems/CodeMirror dark theme */
|
||||
--shiki-color-text: #f8f8f2;
|
||||
--shiki-color-background: var(--code-bg);
|
||||
--shiki-token-constant: #82b1ff;
|
||||
--shiki-token-string: #c3e88d;
|
||||
--shiki-token-comment: #546e7a;
|
||||
--shiki-token-keyword: #c792ea;
|
||||
--shiki-token-parameter: #AA0000;
|
||||
--shiki-token-parameter: #fd971f;
|
||||
--shiki-token-function: #80cbae;
|
||||
--shiki-token-string-expression: #c3e88d;
|
||||
--shiki-token-punctuation: var(--code);
|
||||
--shiki-token-link: #EE0000;
|
||||
--shiki-token-punctuation: #89ddff;
|
||||
--shiki-token-link: #82aaff;
|
||||
--shiki-token-variable: #f8f8f2;
|
||||
--shiki-token-number: #f78c6c;
|
||||
--shiki-token-boolean: #82b1ff;
|
||||
--shiki-token-tag: #f07178;
|
||||
--shiki-token-attribute: #ffcb6b;
|
||||
--shiki-token-property: #82b1ff;
|
||||
--shiki-token-operator: #89ddff;
|
||||
--shiki-token-regex: #c3e88d;
|
||||
--shiki-token-class: #ffcb6b;
|
||||
|
||||
/* Basic styling */
|
||||
white-space: pre;
|
||||
tab-size: 2; /* TODO: allow custom tab size?! */
|
||||
overflow: scroll;
|
||||
tab-size: 2;
|
||||
overflow: auto;
|
||||
border-radius: var(--border-radius);
|
||||
font-family: var(--font-mono);
|
||||
font-size: .85rem;
|
||||
line-height: 1.5;
|
||||
position: relative;
|
||||
margin-block: 1rem;
|
||||
max-width: 100%;
|
||||
}
|
||||
${host}[data-js=todo]{
|
||||
|
||||
/* Light mode overrides to match GitHub-like theme */
|
||||
@media (prefers-color-scheme: light) {
|
||||
${host} {
|
||||
--shiki-color-text: #24292e;
|
||||
--shiki-color-background: var(--code-bg);
|
||||
--shiki-token-constant: #005cc5;
|
||||
--shiki-token-string: #22863a;
|
||||
--shiki-token-comment: #6a737d;
|
||||
--shiki-token-keyword: #d73a49;
|
||||
--shiki-token-parameter: #e36209;
|
||||
--shiki-token-function: #6f42c1;
|
||||
--shiki-token-string-expression: #22863a;
|
||||
--shiki-token-punctuation: #24292e;
|
||||
--shiki-token-link: #0366d6;
|
||||
--shiki-token-variable: #24292e;
|
||||
--shiki-token-number: #005cc5;
|
||||
--shiki-token-boolean: #005cc5;
|
||||
--shiki-token-tag: #22863a;
|
||||
--shiki-token-attribute: #005cc5;
|
||||
--shiki-token-property: #005cc5;
|
||||
--shiki-token-operator: #d73a49;
|
||||
--shiki-token-regex: #032f62;
|
||||
--shiki-token-class: #6f42c1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Support for theme toggles */
|
||||
html[data-theme="light"] ${host} {
|
||||
--shiki-color-text: #24292e;
|
||||
--shiki-color-background: var(--code-bg);
|
||||
--shiki-token-constant: #005cc5;
|
||||
--shiki-token-string: #22863a;
|
||||
--shiki-token-comment: #6a737d;
|
||||
--shiki-token-keyword: #d73a49;
|
||||
--shiki-token-parameter: #e36209;
|
||||
--shiki-token-function: #6f42c1;
|
||||
--shiki-token-string-expression: #22863a;
|
||||
--shiki-token-punctuation: #24292e;
|
||||
--shiki-token-link: #0366d6;
|
||||
--shiki-token-variable: #24292e;
|
||||
--shiki-token-number: #005cc5;
|
||||
--shiki-token-boolean: #005cc5;
|
||||
--shiki-token-tag: #22863a;
|
||||
--shiki-token-attribute: #005cc5;
|
||||
--shiki-token-property: #005cc5;
|
||||
--shiki-token-operator: #d73a49;
|
||||
--shiki-token-regex: #032f62;
|
||||
--shiki-token-class: #6f42c1;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] ${host} {
|
||||
--shiki-color-text: #f8f8f2;
|
||||
--shiki-color-background: var(--code-bg);
|
||||
--shiki-token-constant: #82b1ff;
|
||||
--shiki-token-string: #c3e88d;
|
||||
--shiki-token-comment: #546e7a;
|
||||
--shiki-token-keyword: #c792ea;
|
||||
--shiki-token-parameter: #fd971f;
|
||||
--shiki-token-function: #80cbae;
|
||||
--shiki-token-string-expression: #c3e88d;
|
||||
--shiki-token-punctuation: #89ddff;
|
||||
--shiki-token-link: #82aaff;
|
||||
--shiki-token-variable: #f8f8f2;
|
||||
--shiki-token-number: #f78c6c;
|
||||
--shiki-token-boolean: #82b1ff;
|
||||
--shiki-token-tag: #f07178;
|
||||
--shiki-token-attribute: #ffcb6b;
|
||||
--shiki-token-property: #82b1ff;
|
||||
--shiki-token-operator: #89ddff;
|
||||
--shiki-token-regex: #c3e88d;
|
||||
--shiki-token-class: #ffcb6b;
|
||||
}
|
||||
|
||||
/* Code block with syntax highlighting waiting for JS */
|
||||
${host}[data-js=todo] {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--standard-border-radius);
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 18.4px; /* to fix shift when → dataJS=done */
|
||||
padding: 1rem 1.4rem;
|
||||
border-radius: var(--border-radius);
|
||||
padding: 1rem;
|
||||
background-color: var(--code-bg);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Add a subtle loading indicator */
|
||||
${host}[data-js=todo]::before {
|
||||
content: "Loading syntax highlighting...";
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-light);
|
||||
background-color: var(--bg);
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: var(--border-radius);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* All code blocks should have consistent font and sizing */
|
||||
${host} code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: inherit;
|
||||
line-height: 1.5;
|
||||
padding: 0;
|
||||
}
|
||||
${host} pre {
|
||||
margin-block: 0;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
/* Ensure line numbers (if added) are styled appropriately */
|
||||
${host} .line-number {
|
||||
user-select: none;
|
||||
opacity: 0.5;
|
||||
margin-right: 1rem;
|
||||
min-width: 1.5rem;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* If there's a copy button, style it */
|
||||
${host} .copy-button {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
background-color: var(--bg);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
${host}:hover .copy-button {
|
||||
opacity: 1;
|
||||
}
|
||||
`;
|
||||
import { el } from "deka-dom-el";
|
||||
@ -43,8 +194,8 @@ export function code({ id, src, content, language= "js", className= host.slice(1
|
||||
registerClientPart(page_id);
|
||||
dataJS= "todo";
|
||||
}
|
||||
return el("div", { id, className, dataJS }).append(
|
||||
el("code", { className: "language-"+language, textContent: content })
|
||||
return el("div", { id, className, dataJS, tabIndex: 0 }).append(
|
||||
el("code", { className: "language-"+language, textContent: content.trim() })
|
||||
);
|
||||
}
|
||||
let is_registered= {};
|
||||
@ -52,12 +203,45 @@ let is_registered= {};
|
||||
function registerClientPart(page_id){
|
||||
if(is_registered[page_id]) return;
|
||||
|
||||
// Add Shiki with a more reliable loading method
|
||||
document.head.append(
|
||||
el("script", { src: "https://cdn.jsdelivr.net/npm/shiki@0.9", defer: true }),
|
||||
// Use a newer version of Shiki with better performance
|
||||
el("script", { src: "https://cdn.jsdelivr.net/npm/shiki@0.14.3/dist/index.unpkg.iife.js", defer: true }),
|
||||
// Make sure we can match Flems styling in dark/light mode
|
||||
el("style", `
|
||||
/* Ensure CodeMirror and Shiki use the same font */
|
||||
.CodeMirror *, .shiki * {
|
||||
font-family: var(--font-mono) !important;
|
||||
}
|
||||
|
||||
/* Style Shiki's output to match our theme */
|
||||
.shiki {
|
||||
background-color: var(--shiki-color-background) !important;
|
||||
color: var(--shiki-color-text) !important;
|
||||
padding: 1rem;
|
||||
border-radius: var(--border-radius);
|
||||
tab-size: 2;
|
||||
}
|
||||
|
||||
/* Ensure Shiki code tokens use our CSS variables */
|
||||
.shiki .keyword { color: var(--shiki-token-keyword) !important; }
|
||||
.shiki .constant { color: var(--shiki-token-constant) !important; }
|
||||
.shiki .string { color: var(--shiki-token-string) !important; }
|
||||
.shiki .comment { color: var(--shiki-token-comment) !important; }
|
||||
.shiki .function { color: var(--shiki-token-function) !important; }
|
||||
.shiki .operator, .shiki .punctuation { color: var(--shiki-token-punctuation) !important; }
|
||||
.shiki .parameter { color: var(--shiki-token-parameter) !important; }
|
||||
.shiki .variable { color: var(--shiki-token-variable) !important; }
|
||||
.shiki .property { color: var(--shiki-token-property) !important; }
|
||||
`),
|
||||
);
|
||||
|
||||
registerClientFile(
|
||||
new URL("./code.js.js", import.meta.url),
|
||||
el("script", { type: "module" })
|
||||
{
|
||||
head: el("script", { type: "module" }),
|
||||
}
|
||||
);
|
||||
|
||||
is_registered[page_id]= true;
|
||||
}
|
||||
|
@ -1,12 +1,61 @@
|
||||
const highlighter= await globalThis.shiki.getHighlighter({
|
||||
theme: "css-variables",
|
||||
langs: ["js", "ts", "css", "html", "shell"],
|
||||
});
|
||||
const codeBlocks= document.querySelectorAll('code[class*="language-"]');
|
||||
try {
|
||||
// Initialize Shiki with our custom theme
|
||||
const highlighter = await globalThis.shiki.getHighlighter({
|
||||
theme: "css-variables",
|
||||
langs: ["javascript", "typescript", "css", "html", "shell"],
|
||||
});
|
||||
|
||||
codeBlocks.forEach((block)=> {
|
||||
const lang= block.className.replace("language-", "");
|
||||
block.parentElement.dataset.js= "done";
|
||||
const html= highlighter.codeToHtml(block.textContent, { lang });
|
||||
block.innerHTML= html;
|
||||
});
|
||||
// Find all code blocks that need highlighting
|
||||
const codeBlocks = document.querySelectorAll('div[data-js="todo"] code[class*="language-"]');
|
||||
|
||||
// Process each code block
|
||||
codeBlocks.forEach((block) => {
|
||||
try {
|
||||
// Get the language from the class
|
||||
const langClass = block.className.match(/language-(\w+)/);
|
||||
|
||||
// Map the language to Shiki format
|
||||
let lang = langClass ? langClass[1] : 'javascript';
|
||||
if (lang === 'js') lang = 'javascript';
|
||||
if (lang === 'ts') lang = 'typescript';
|
||||
|
||||
// Mark the container as processed
|
||||
block.parentElement.dataset.js = "done";
|
||||
|
||||
// Highlight the code
|
||||
const code = block.textContent;
|
||||
const html = highlighter.codeToHtml(code, { lang });
|
||||
|
||||
// Insert the highlighted HTML
|
||||
block.innerHTML = html;
|
||||
|
||||
// Add copy button functionality
|
||||
const copyBtn = document.createElement('button');
|
||||
copyBtn.className = 'copy-button';
|
||||
copyBtn.textContent = 'Copy';
|
||||
copyBtn.setAttribute('aria-label', 'Copy code to clipboard');
|
||||
copyBtn.addEventListener('click', () => {
|
||||
navigator.clipboard.writeText(code).then(() => {
|
||||
copyBtn.textContent = 'Copied!';
|
||||
setTimeout(() => {
|
||||
copyBtn.textContent = 'Copy';
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
// Add the copy button to the code block container
|
||||
block.parentElement.appendChild(copyBtn);
|
||||
} catch (err) {
|
||||
console.error('Error highlighting code block:', err);
|
||||
// Make sure we don't leave the block in a pending state
|
||||
block.parentElement.dataset.js = "error";
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to initialize Shiki:', err);
|
||||
|
||||
// Fallback: at least mark blocks as processed so they don't show loading indicator
|
||||
document.querySelectorAll('div[data-js="todo"]').forEach(block => {
|
||||
block.dataset.js = "error";
|
||||
});
|
||||
}
|
||||
|
@ -1,16 +1,100 @@
|
||||
import { styles } from "../ssr.js";
|
||||
const host= "."+example.name;
|
||||
styles.css`
|
||||
${host}{
|
||||
${host} {
|
||||
grid-column: full-main;
|
||||
width: 100%;
|
||||
max-width: calc(9/5 * var(--body-max-width));
|
||||
height: calc(3/5 * var(--body-max-width));
|
||||
margin-inline: auto;
|
||||
width: calc(100% - .75em);
|
||||
height: calc(4/6 * var(--body-max-width));
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: var(--shadow);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
${host} .runtime {
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
/* CodeMirror styling to match our theme */
|
||||
.CodeMirror {
|
||||
height: 100% !important;
|
||||
font-family: var(--font-mono) !important;
|
||||
font-size: .85rem !important;
|
||||
line-height: 1.5 !important;
|
||||
}
|
||||
|
||||
/* Dark mode styles for CodeMirror */
|
||||
.CodeMirror, .CodeMirror-gutters {
|
||||
background: #212121 !important;
|
||||
border: 1px solid white;
|
||||
background: var(--code-bg) !important;
|
||||
color: var(--text) !important;
|
||||
}
|
||||
|
||||
/* Light mode adjustments for CodeMirror - using CSS variables */
|
||||
@media (prefers-color-scheme: light) {
|
||||
/* Core syntax elements */
|
||||
.cm-s-material .cm-keyword { color: var(--shiki-token-keyword, #d73a49) !important; }
|
||||
.cm-s-material .cm-atom { color: var(--shiki-token-constant, #005cc5) !important; }
|
||||
.cm-s-material .cm-number { color: var(--shiki-token-number, #005cc5) !important; }
|
||||
.cm-s-material .cm-def { color: var(--shiki-token-function, #6f42c1) !important; }
|
||||
.cm-s-material .cm-variable { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
.cm-s-material .cm-variable-2 { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
.cm-s-material .cm-variable-3 { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
.cm-s-material .cm-property { color: var(--shiki-token-property, #005cc5) !important; }
|
||||
.cm-s-material .cm-operator { color: var(--shiki-token-operator, #d73a49) !important; }
|
||||
.cm-s-material .cm-comment { color: var(--shiki-token-comment, #6a737d) !important; }
|
||||
.cm-s-material .cm-string { color: var(--shiki-token-string, #22863a) !important; }
|
||||
.cm-s-material .cm-string-2 { color: var(--shiki-token-string, #22863a) !important; }
|
||||
.cm-s-material .cm-tag { color: var(--shiki-token-tag, #22863a) !important; }
|
||||
.cm-s-material .cm-attribute { color: var(--shiki-token-attribute, #005cc5) !important; }
|
||||
.cm-s-material .cm-bracket { color: var(--shiki-token-punctuation, #24292e) !important; }
|
||||
.cm-s-material .cm-punctuation { color: var(--shiki-token-punctuation, #24292e) !important; }
|
||||
.cm-s-material .cm-link { color: var(--shiki-token-link, #0366d6) !important; }
|
||||
.cm-s-material .cm-error { color: #f44336 !important; }
|
||||
}
|
||||
|
||||
/* Handle theme toggle */
|
||||
html[data-theme="light"] .CodeMirror {
|
||||
background: #f5f7fa !important;
|
||||
}
|
||||
|
||||
html[data-theme="light"] .CodeMirror-gutters {
|
||||
background: #f5f7fa !important;
|
||||
border-right: 1px solid #e5e7eb !important;
|
||||
}
|
||||
|
||||
/* Also apply the same styles to CodeMirror with data-theme */
|
||||
html[data-theme="light"] .cm-s-material .cm-keyword { color: var(--shiki-token-keyword, #d73a49) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-atom { color: var(--shiki-token-constant, #005cc5) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-number { color: var(--shiki-token-number, #005cc5) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-def { color: var(--shiki-token-function, #6f42c1) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-variable { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-variable-2 { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-variable-3 { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-property { color: var(--shiki-token-property, #005cc5) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-operator { color: var(--shiki-token-operator, #d73a49) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-comment { color: var(--shiki-token-comment, #6a737d) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-string { color: var(--shiki-token-string, #22863a) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-string-2 { color: var(--shiki-token-string, #22863a) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-tag { color: var(--shiki-token-tag, #22863a) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-attribute { color: var(--shiki-token-attribute, #005cc5) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-bracket { color: var(--shiki-token-punctuation, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-punctuation { color: var(--shiki-token-punctuation, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-link { color: var(--shiki-token-link, #0366d6) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-error { color: #f44336 !important; }
|
||||
|
||||
/* Mobile adjustments */
|
||||
@media (max-width: 767px) {
|
||||
${host} {
|
||||
height: 50vh;
|
||||
max-width: 100%;
|
||||
}
|
||||
${host} main {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
${host} main > * {
|
||||
width: 100%;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -26,7 +26,7 @@ function ddeComponent({ attr }){
|
||||
on.connected(e=> console.log(( /** @type {HTMLParagraphElement} */ (e.target)).outerHTML)),
|
||||
);
|
||||
return el().append(
|
||||
el("p", S(()=> `Hello from Custom Element with attribute '${attr()}'`))
|
||||
el("p", S(()=> `Hello from Custom Element with attribute '${attr.get()}'`))
|
||||
);
|
||||
}
|
||||
customElementWithDDE(HTMLCustomElement);
|
||||
|
15
docs/components/examples/debugging/consoleLog.js
Normal file
15
docs/components/examples/debugging/consoleLog.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Debugging a (derived) signal with `console.log`
|
||||
import { S } from "deka-dom-el/signals";
|
||||
const name= S("Alice");
|
||||
const greeting = S(() => {
|
||||
// log derived signals
|
||||
const log = "Hello, " + name.get();
|
||||
console.log(log);
|
||||
console.log(name.valueOf());
|
||||
return log;
|
||||
});
|
||||
|
||||
// log signals in general
|
||||
S.on(greeting, value => console.log("Greeting changed to:", value));
|
||||
|
||||
name.set("Bob"); // Should trigger computation and listener`)
|
15
docs/components/examples/debugging/debouncing.js
Normal file
15
docs/components/examples/debugging/debouncing.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
// Debouncing signal updates
|
||||
function debounce(func, wait) {
|
||||
let timeout;
|
||||
return (...args)=> {
|
||||
clearTimeout(timeout);
|
||||
timeout= setTimeout(() => func(...args), wait);
|
||||
};
|
||||
}
|
||||
|
||||
const inputSignal= S("");
|
||||
const debouncedSet= debounce(value => inputSignal.set(value), 300);
|
||||
|
||||
// In your input handler
|
||||
inputElement.addEventListener("input", e=> debouncedSet(e.target.value));
|
4
docs/components/examples/debugging/dom-reactive-mark.js
Normal file
4
docs/components/examples/debugging/dom-reactive-mark.js
Normal file
@ -0,0 +1,4 @@
|
||||
// Example of reactive element marker
|
||||
<!--<dde:mark type=\"reactive\" source=\"...\">-->
|
||||
<!-- content that updates when signal changes -->
|
||||
<!--</dde:mark>-->
|
15
docs/components/examples/debugging/mutations.js
Normal file
15
docs/components/examples/debugging/mutations.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
// Wrong - direct mutation doesn't trigger updates
|
||||
const todos1 = S([{ text: "Learn signals", completed: false }]);
|
||||
todos1.get().push({ text: "Debug signals", completed: false }); // Won't trigger updates!
|
||||
|
||||
// Correct - using .set() with a new array
|
||||
todos1.set([...todos1.get(), { text: "Debug signals", completed: false }]);
|
||||
|
||||
// Better - using actions
|
||||
const todos2 = S([], {
|
||||
add(text) {
|
||||
this.value.push({ text, completed: false });
|
||||
}
|
||||
});
|
||||
S.action(todos2, "add", "Debug signals");
|
14
docs/components/examples/elements/dde-dom-create.js
Normal file
14
docs/components/examples/elements/dde-dom-create.js
Normal file
@ -0,0 +1,14 @@
|
||||
import { el } from "deka-dom-el";
|
||||
|
||||
// Create element with properties
|
||||
const button = el("button", {
|
||||
textContent: "Click me",
|
||||
className: "primary",
|
||||
disabled: true
|
||||
});
|
||||
|
||||
// Shorter and more expressive
|
||||
// than the native approach
|
||||
|
||||
// Add to DOM
|
||||
document.body.append(button);
|
11
docs/components/examples/elements/dde-dom-tree.js
Normal file
11
docs/components/examples/elements/dde-dom-tree.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { el } from "deka-dom-el";
|
||||
|
||||
// Chainable, natural nesting
|
||||
// append() returns parent element
|
||||
// making chains easy and intuitive
|
||||
document.body.append(
|
||||
el("div").append(
|
||||
el("h1", "Title"),
|
||||
el("p", "Paragraph")
|
||||
)
|
||||
);
|
19
docs/components/examples/elements/native-dom-create.js
Normal file
19
docs/components/examples/elements/native-dom-create.js
Normal file
@ -0,0 +1,19 @@
|
||||
// Create element with properties
|
||||
const button = document.createElement('button');
|
||||
button.textContent = "Click me";
|
||||
button.className = "primary";
|
||||
button.disabled = true;
|
||||
|
||||
// Or using Object.assign()
|
||||
const button2 = Object.assign(
|
||||
document.createElement('button'),
|
||||
{
|
||||
textContent: "Click me",
|
||||
className: "primary",
|
||||
disabled: true
|
||||
}
|
||||
);
|
||||
|
||||
// Add to DOM
|
||||
document.body.appendChild(button);
|
||||
document.body.appendChild(button2);
|
15
docs/components/examples/elements/native-dom-tree.js
Normal file
15
docs/components/examples/elements/native-dom-tree.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Verbose, needs temp variables
|
||||
const div = document.createElement('div');
|
||||
const h1 = document.createElement('h1');
|
||||
h1.textContent = 'Title';
|
||||
div.appendChild(h1);
|
||||
|
||||
const p = document.createElement('p');
|
||||
p.textContent = 'Paragraph';
|
||||
div.appendChild(p);
|
||||
|
||||
// appendChild doesn't return parent
|
||||
// so chaining is not possible
|
||||
|
||||
// Add to DOM
|
||||
document.body.appendChild(div);
|
8
docs/components/examples/events/append-event.js
Normal file
8
docs/components/examples/events/append-event.js
Normal file
@ -0,0 +1,8 @@
|
||||
import { el, on } from "deka-dom-el";
|
||||
|
||||
// Third approach - append with on addon
|
||||
el("button", {
|
||||
textContent: "click me"
|
||||
}).append(
|
||||
on("click", (e) => console.log("Clicked!", e))
|
||||
);
|
7
docs/components/examples/events/attribute-event.js
Normal file
7
docs/components/examples/events/attribute-event.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { el } from "deka-dom-el";
|
||||
|
||||
// Using events with HTML attribute style
|
||||
el("button", {
|
||||
textContent: "click me",
|
||||
"=onclick": "console.log(event)"
|
||||
});
|
8
docs/components/examples/events/chain-event.js
Normal file
8
docs/components/examples/events/chain-event.js
Normal file
@ -0,0 +1,8 @@
|
||||
import { el, on } from "deka-dom-el";
|
||||
|
||||
// Using events as addons - chainable approach
|
||||
el("button", {
|
||||
textContent: "click me",
|
||||
},
|
||||
on("click", (e) => console.log("Clicked!", e))
|
||||
);
|
2
docs/components/examples/events/native-event.js
Normal file
2
docs/components/examples/events/native-event.js
Normal file
@ -0,0 +1,2 @@
|
||||
// Standard DOM event listener approach
|
||||
element.addEventListener('click', callback, options);
|
7
docs/components/examples/events/property-event.js
Normal file
7
docs/components/examples/events/property-event.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { el } from "deka-dom-el";
|
||||
|
||||
// Using events with property assignment
|
||||
el("button", {
|
||||
textContent: "click me",
|
||||
onclick: console.log
|
||||
});
|
14
docs/components/examples/introducing/3ps-before.js
Normal file
14
docs/components/examples/introducing/3ps-before.js
Normal file
@ -0,0 +1,14 @@
|
||||
// pseudocode
|
||||
// Mixed concerns make code hard to maintain
|
||||
const button = document.querySelector('button');
|
||||
let count = 0;
|
||||
|
||||
button.addEventListener('click', () => {
|
||||
count++;
|
||||
document.querySelector('p').textContent =
|
||||
'Clicked ' + count + ' times';
|
||||
|
||||
if (count > 10) {
|
||||
button.disabled = true;
|
||||
}
|
||||
});
|
@ -1,6 +1,14 @@
|
||||
// pseudo code!
|
||||
const onchage=
|
||||
event=>
|
||||
console.log("Reacting to the:", event); // A
|
||||
input.addEventListener("change", onchange); // B
|
||||
input.dispatchEvent(new Event("change")); // C
|
||||
// pseudocode
|
||||
// 1. Create state
|
||||
const count = S(0);
|
||||
|
||||
// 2. React to state changes
|
||||
S.on(count, value => {
|
||||
updateUI(value);
|
||||
if (value > 10) disableButton();
|
||||
});
|
||||
|
||||
// 3. Update state on events
|
||||
button.addEventListener('click', () => {
|
||||
count.set(count.get() + 1);
|
||||
});
|
||||
|
@ -1,19 +1,30 @@
|
||||
import { el } from "deka-dom-el";
|
||||
import { el, on } from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
const threePS= ({ emoji= "🚀" })=> {
|
||||
const clicks= S(0); // A
|
||||
return el().append(
|
||||
el("p", S(()=>
|
||||
"Hello World "+emoji.repeat(clicks()) // B
|
||||
)),
|
||||
el("button", {
|
||||
type: "button",
|
||||
onclick: ()=> clicks(clicks()+1), // C
|
||||
textContent: "Fire",
|
||||
})
|
||||
);
|
||||
};
|
||||
document.body.append(
|
||||
el(threePS, { emoji: "🎉" }),
|
||||
);
|
||||
|
||||
// A HelloWorld component using the 3PS pattern
|
||||
function HelloWorld({ emoji = "🚀" }) {
|
||||
// PART 1: Create reactive state
|
||||
const clicks = S(0);
|
||||
|
||||
return el().append(
|
||||
// PART 2: Bind state to UI elements
|
||||
el("p", {
|
||||
className: "greeting",
|
||||
// This paragraph automatically updates when clicks changes
|
||||
textContent: S(() => `Hello World ${emoji.repeat(clicks.get())}`)
|
||||
}),
|
||||
|
||||
// PART 3: Update state in response to events
|
||||
el("button", {
|
||||
type: "button",
|
||||
textContent: "Add emoji",
|
||||
// When clicked, update the state
|
||||
onclick: () => clicks.set(clicks.get() + 1)
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Use the component in your app
|
||||
document.body.append(
|
||||
el(HelloWorld, { emoji: "🎉" })
|
||||
);
|
37
docs/components/examples/ireland-test/counter.js
Normal file
37
docs/components/examples/ireland-test/counter.js
Normal file
@ -0,0 +1,37 @@
|
||||
import { el } from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
|
||||
const className = "client-side-counter";
|
||||
document.body.append(
|
||||
el("style").append(`
|
||||
.${className} {
|
||||
border: 1px dashed #ccc;
|
||||
padding: 1em;
|
||||
margin: 1em;
|
||||
}
|
||||
`.trim())
|
||||
);
|
||||
|
||||
export function CounterStandard() {
|
||||
// Create reactive state with a signal
|
||||
const count = S(0);
|
||||
|
||||
// Create UI components that react to state changes
|
||||
return el("div", { className }).append(
|
||||
el("h4", "Client-Side Counter"),
|
||||
el("div", {
|
||||
// The textContent updates automatically when count changes
|
||||
textContent: S(() => `Count: ${count.get()}`),
|
||||
}),
|
||||
el("div", { className: "controls" }).append(
|
||||
el("button", {
|
||||
onclick: () => count.set(count.get() - 1),
|
||||
textContent: "-",
|
||||
}),
|
||||
el("button", {
|
||||
onclick: () => count.set(count.get() + 1),
|
||||
textContent: "+",
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
14
docs/components/examples/scopes/custom-scope.js
Normal file
14
docs/components/examples/scopes/custom-scope.js
Normal file
@ -0,0 +1,14 @@
|
||||
import { scope } from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
|
||||
function customSignalLogic() {
|
||||
// Create an isolated scope for a specific operation
|
||||
scope.push(); // Start new scope
|
||||
|
||||
// These signals are in the new scope
|
||||
const isolatedCount = S(0);
|
||||
const isolatedDerived = S(() => isolatedCount.get() * 2);
|
||||
|
||||
// Clean up by returning to previous scope
|
||||
scope.pop();
|
||||
}
|
@ -1,35 +1,26 @@
|
||||
/* PSEUDO-CODE!!! */
|
||||
import { el } from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
function component(){
|
||||
/* prepare changeable data */
|
||||
const dataA= S("data");
|
||||
const dataB= S("data");
|
||||
/* define data flow (can be asynchronous) */
|
||||
fetchAPI().then(data_new=> dataA(data_new));
|
||||
setTimeout(()=> dataB("DATA"));
|
||||
/* declarative UI */
|
||||
return el().append(
|
||||
el("h1", {
|
||||
textContent: "Example",
|
||||
/* declarative attribute(s) */
|
||||
classList: { declarative: dataB }
|
||||
}),
|
||||
el("ul").append(
|
||||
/* declarative element(s) */
|
||||
S.el(dataA, data=> data.map(d=> el("li", d)))
|
||||
),
|
||||
el("ul").append(
|
||||
/* declarative component(s) */
|
||||
S.el(dataA, data=> data.map(d=> el(subcomponent, d)))
|
||||
)
|
||||
function Counter() {
|
||||
// Define state
|
||||
const count = S(0);
|
||||
|
||||
// Define behavior
|
||||
const increment = () => count.set(count.get() + 1);
|
||||
|
||||
// Define data flow
|
||||
setTimeout(increment, 1000);
|
||||
// or fetchAPI().then(increment);
|
||||
|
||||
// Declarative UI (how to render data/`count`)
|
||||
// …automatically updates when changes
|
||||
return el("div").append(
|
||||
// declarative element(s)
|
||||
el("p", S(() => "Count: " + count.get())),
|
||||
el("button", {
|
||||
onclick: increment,
|
||||
textContent: "Increment",
|
||||
// declarative attribute(s)
|
||||
disabled: S(() => count.get() >= 10)
|
||||
})
|
||||
);
|
||||
}
|
||||
function subcomponent({ id }){
|
||||
/* prepare changeable data */
|
||||
const textContent= S("…");
|
||||
/* define data flow (can be asynchronous) */
|
||||
fetchAPI(id).then(text=> textContent(text));
|
||||
/* declarative UI */
|
||||
return el("li", { textContent, dataId: id });
|
||||
}
|
||||
|
@ -1,31 +1,25 @@
|
||||
/* PSEUDO-CODE!!! */
|
||||
import { el, on, scope } from "deka-dom-el";
|
||||
function component(){
|
||||
const { host }= scope;
|
||||
const ul= el("ul");
|
||||
const ac= new AbortController();
|
||||
fetchAPI({ signal: ac.signal }).then(data=> {
|
||||
data.forEach(d=> ul.append(el("li", d)));
|
||||
});
|
||||
host(
|
||||
/* element was remove before data fetched */
|
||||
on.disconnected(()=> ac.abort())
|
||||
import { el, scope } from "deka-dom-el";
|
||||
function Counter() {
|
||||
const { host } = scope;
|
||||
|
||||
let count = 0;
|
||||
const counterText = el("p", "Count: 0");
|
||||
|
||||
// Manually update DOM element
|
||||
const increment = () => {
|
||||
count++;
|
||||
counterText.textContent = "Count: " + count;
|
||||
host().querySelector("button").disabled = count >= 10;
|
||||
};
|
||||
setTimeout(increment, 1000);
|
||||
// or fetchAPI().then(increment);
|
||||
|
||||
return el("div").append(
|
||||
counterText,
|
||||
el("button", {
|
||||
onclick: increment,
|
||||
textContent: "Increment"
|
||||
})
|
||||
);
|
||||
return ul;
|
||||
/**
|
||||
* NEVER EVER!!
|
||||
* let data;
|
||||
* fetchAPI().then(d=> data= O(d));
|
||||
*
|
||||
* OR NEVER EVER!!
|
||||
* const ul= el("ul");
|
||||
* fetchAPI().then(d=> {
|
||||
* const data= O("data");
|
||||
* ul.append(el("li", data));
|
||||
* });
|
||||
*
|
||||
* // THE HOST IS PROBABLY DIFFERENT THAN
|
||||
* // YOU EXPECT AND OBSERVABLES MAY BE
|
||||
* // UNEXPECTEDLY REMOVED!!!
|
||||
* */
|
||||
}
|
||||
|
36
docs/components/examples/scopes/mixed.js
Normal file
36
docs/components/examples/scopes/mixed.js
Normal file
@ -0,0 +1,36 @@
|
||||
/* PSEUDO-CODE!!! */
|
||||
import { el, scope } from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
function Counter() {
|
||||
const { host } = scope;
|
||||
|
||||
let count = S(0);
|
||||
const counterText = el("p", "Count: 0");
|
||||
S.on(count, c=> counterText.textContent= "Count: " + c);
|
||||
|
||||
// Manually update DOM element
|
||||
const increment = () => {
|
||||
count.set(count.get() + 1);
|
||||
// NEVER EVER
|
||||
// count = S(count.get() + 1);
|
||||
// THE HOST IS PROBABLY DIFFERENT THAN
|
||||
// YOU EXPECT AND SIGNAL MAY BE
|
||||
// UNEXPECTEDLY REMOVED!!!
|
||||
host().querySelector("button").disabled = count.get() >= 10;
|
||||
};
|
||||
setTimeout(()=> {
|
||||
// ok, BUT consider extract to separate function
|
||||
// see section below for more info
|
||||
const ok= S(0);
|
||||
S.on(ok, console.log);
|
||||
setInterval(()=> ok.set(ok.get() + 1), 100);
|
||||
}, 100);
|
||||
|
||||
return el("div").append(
|
||||
counterText,
|
||||
el("button", {
|
||||
onclick: increment,
|
||||
textContent: "Increment"
|
||||
})
|
||||
);
|
||||
}
|
45
docs/components/examples/scopes/with-scope.js
Normal file
45
docs/components/examples/scopes/with-scope.js
Normal file
@ -0,0 +1,45 @@
|
||||
import { el, scope } from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
|
||||
function CounterWithIsolatedTimer() {
|
||||
const { host } = scope;
|
||||
|
||||
// Main component state
|
||||
const count = S(0);
|
||||
|
||||
// Create a timer in an isolated scope
|
||||
scope.isolate(() => {
|
||||
// These subscriptions won't be tied to the component lifecycle
|
||||
// They would continue to run even if the component was removed
|
||||
const timer = S(0);
|
||||
|
||||
// Not recommended for real applications!
|
||||
// Just demonstrating scope isolation
|
||||
setInterval(() => {
|
||||
timer.set(timer.get() + 1);
|
||||
console.log(`Timer: ${timer.get()}`);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// Normal component functionality within main scope
|
||||
function increment() {
|
||||
count.set(count.get() + 1);
|
||||
}
|
||||
|
||||
return el("div").append(
|
||||
el("p").append(
|
||||
"Count: ",
|
||||
el("#text", S(() => count.get()))
|
||||
),
|
||||
el("button", {
|
||||
textContent: "Increment",
|
||||
onclick: increment
|
||||
}),
|
||||
el("p", "An isolated timer runs in console")
|
||||
);
|
||||
}
|
||||
|
||||
// Usage
|
||||
document.body.append(
|
||||
el(CounterWithIsolatedTimer)
|
||||
);
|
@ -15,4 +15,4 @@ setTimeout(
|
||||
clearInterval,
|
||||
10*interval,
|
||||
setInterval(oninterval, interval)
|
||||
);
|
||||
);
|
@ -22,9 +22,9 @@ const onsubmit= on("submit", function(event){
|
||||
S.action(todos, "push", data.get("todo"));
|
||||
break;
|
||||
case "E"/*dit*/: {
|
||||
const last= todos().at(-1);
|
||||
const last= todos.get().at(-1);
|
||||
if(!last) break;
|
||||
last(data.get("todo"));
|
||||
last.set(data.get("todo"));
|
||||
break;
|
||||
}
|
||||
case "R"/*emove*/:
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
const signal= S(0);
|
||||
// computation pattern
|
||||
const double= S(()=> 2*signal());
|
||||
const double= S(()=> 2*signal.get());
|
||||
|
||||
const ac= new AbortController();
|
||||
S.on(signal, v=> console.log("signal", v), { signal: ac.signal });
|
||||
S.on(double, v=> console.log("double", v), { signal: ac.signal });
|
||||
|
||||
signal(signal()+1);
|
||||
signal.set(signal.get()+1);
|
||||
const interval= 5 * 1000;
|
||||
const id= setInterval(()=> signal(signal()+1), interval);
|
||||
const id= setInterval(()=> signal.set(signal.get()+1), interval);
|
||||
ac.signal.addEventListener("abort",
|
||||
()=> setTimeout(()=> clearInterval(id), 2*interval));
|
||||
|
||||
setTimeout(()=> ac.abort(), 3*interval)
|
||||
setTimeout(()=> ac.abort(), 3*interval)
|
20
docs/components/examples/signals/debugging-console.js
Normal file
20
docs/components/examples/signals/debugging-console.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
|
||||
// Debugging a derived signal
|
||||
const name = S('Alice');
|
||||
const greeting = S(() => {
|
||||
console.log('Computing greeting...');
|
||||
return 'Hello, ' + name.get();
|
||||
});
|
||||
|
||||
// Monitor the derived signal
|
||||
S.on(greeting, value => console.log('Greeting changed to:', value));
|
||||
|
||||
// Later update the dependency
|
||||
name.set('Bob'); // Should trigger computation and listener
|
||||
|
||||
// Console output:
|
||||
// Computing greeting...
|
||||
// Greeting changed to: Hello, Alice
|
||||
// Computing greeting...
|
||||
// Greeting changed to: Hello, Bob
|
38
docs/components/examples/signals/debugging-dom.js
Normal file
38
docs/components/examples/signals/debugging-dom.js
Normal file
@ -0,0 +1,38 @@
|
||||
import { el, on, scope } from "deka-dom-el";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
|
||||
// Create a component with reactive elements
|
||||
function ReactiveCounter() {
|
||||
const count = S(0);
|
||||
scope.host(on.connected(ev=>
|
||||
console.log(ev.target.__dde_reactive)
|
||||
));
|
||||
|
||||
const counter = el('div', {
|
||||
// This element will be added into the __dde_reactive property
|
||||
textContent: count,
|
||||
});
|
||||
|
||||
const incrementBtn = el('button', {
|
||||
textContent: 'Increment',
|
||||
onclick: () => count.set(count.get() + 1)
|
||||
});
|
||||
|
||||
// Dynamic section will be added into __dde_signal property
|
||||
const counterInfo = S.el(count, value =>
|
||||
el('p', `Current count is ${value}`)
|
||||
);
|
||||
|
||||
return el('div', { id: 'counter' }).append(
|
||||
counter,
|
||||
incrementBtn,
|
||||
counterInfo
|
||||
);
|
||||
}
|
||||
document.body.append(
|
||||
el(ReactiveCounter),
|
||||
);
|
||||
|
||||
// In DevTools console:
|
||||
const counter = document.querySelector('#counter');
|
||||
setTimeout(()=> console.log(counter.__dde_reactive), 1000); // See reactive bindings
|
13
docs/components/examples/signals/derived.js
Normal file
13
docs/components/examples/signals/derived.js
Normal file
@ -0,0 +1,13 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
|
||||
// Create base signals
|
||||
const firstName = S("John");
|
||||
const lastName = S("Doe");
|
||||
|
||||
// Create a derived signal
|
||||
const fullName = S(() => firstName.get() + " " + lastName.get());
|
||||
|
||||
// The fullName signal updates automatically when either dependency changes
|
||||
S.on(fullName, name => console.log("Name changed to:", name));
|
||||
|
||||
firstName.set("Jane"); // logs: "Name changed to: Jane Doe"
|
@ -3,8 +3,8 @@ const count= S(0);
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
document.body.append(
|
||||
el("p", S(()=> "Currently: "+count())),
|
||||
el("p", { classList: { red: S(()=> count()%2 === 0) }, dataset: { count }, textContent: "Attributes example" }),
|
||||
el("p", S(()=> "Currently: "+count.get())),
|
||||
el("p", { classList: { red: S(()=> count.get()%2 === 0) }, dataset: { count }, textContent: "Attributes example" }),
|
||||
);
|
||||
document.head.append(
|
||||
el("style", ".red { color: red; }")
|
||||
@ -12,4 +12,4 @@ document.head.append(
|
||||
|
||||
const interval= 5 * 1000;
|
||||
setTimeout(clearInterval, 10*interval,
|
||||
setInterval(()=> count(count()+1), interval));
|
||||
setInterval(()=> count.set(count.get()+1), interval));
|
@ -2,7 +2,7 @@ import { S } from "deka-dom-el/signals";
|
||||
const count= S(0, {
|
||||
add(){ this.value= this.value + Math.round(Math.random()*10); }
|
||||
});
|
||||
const numbers= S([ count() ], {
|
||||
const numbers= S([ count.get() ], {
|
||||
push(next){ this.value.push(next); }
|
||||
});
|
||||
|
||||
@ -22,5 +22,5 @@ document.body.append(
|
||||
const interval= 5*1000;
|
||||
setTimeout(clearInterval, 10*interval, setInterval(function(){
|
||||
S.action(count, "add");
|
||||
S.action(numbers, "push", count());
|
||||
}, interval));
|
||||
S.action(numbers, "push", count.get());
|
||||
}, interval));
|
@ -1,10 +1,10 @@
|
||||
import { S } from "deka-dom-el/signals";
|
||||
// α — `signal` represents a reactive value
|
||||
// PART 1 — `signal` represents a reactive value
|
||||
const signal= S(0);
|
||||
// β — just reacts on signal changes
|
||||
// PART 2 — just reacts on signal changes
|
||||
S.on(signal, console.log);
|
||||
// γ — just updates the value
|
||||
const update= ()=> signal(signal()+1);
|
||||
// PART 3 — just updates the value
|
||||
const update= ()=> signal.set(signal.get()+1);
|
||||
|
||||
update();
|
||||
const interval= 5*1000;
|
||||
|
43
docs/components/examples/ssr/async-data.js
Normal file
43
docs/components/examples/ssr/async-data.js
Normal file
@ -0,0 +1,43 @@
|
||||
// Handling async data in SSR
|
||||
import { JSDOM } from "jsdom";
|
||||
import { S } from "deka-dom-el/signals";
|
||||
import { register, queue } from "deka-dom-el/jsdom";
|
||||
|
||||
async function renderWithAsyncData() {
|
||||
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
|
||||
const { el } = await register(dom);
|
||||
|
||||
// Create a component that fetches data
|
||||
function AsyncComponent() {
|
||||
const title= S("-");
|
||||
const description= S("-");
|
||||
|
||||
// Use the queue to track the async operation
|
||||
queue(fetch("https://api.example.com/data")
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
title.set(data.title);
|
||||
description.set(data.description);
|
||||
}));
|
||||
|
||||
return el("div", { className: "async-content" }).append(
|
||||
el("h2", title),
|
||||
el("p", description)
|
||||
);
|
||||
}
|
||||
|
||||
// Render the page
|
||||
dom.window.document.body.append(
|
||||
el("h1", "Page with Async Data"),
|
||||
el(AsyncComponent)
|
||||
);
|
||||
|
||||
// IMPORTANT: Wait for all queued operations to complete
|
||||
await queue();
|
||||
|
||||
// Now the HTML includes all async content
|
||||
const html = dom.serialize();
|
||||
console.log(html);
|
||||
}
|
||||
|
||||
renderWithAsyncData();
|
47
docs/components/examples/ssr/basic-example.js
Normal file
47
docs/components/examples/ssr/basic-example.js
Normal file
@ -0,0 +1,47 @@
|
||||
// Basic SSR Example
|
||||
import { JSDOM } from "jsdom";
|
||||
import { register, queue } from "deka-dom-el/jsdom";
|
||||
import { writeFileSync } from "node:fs";
|
||||
|
||||
async function renderPage() {
|
||||
// Create a jsdom instance
|
||||
const dom = new JSDOM("<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head><body></body></html>");
|
||||
|
||||
// Register with deka-dom-el and get the el function
|
||||
const { el } = await register(dom);
|
||||
|
||||
// Create a simple header component
|
||||
function Header({ title }) {
|
||||
return el("header").append(
|
||||
el("h1", title),
|
||||
el("nav").append(
|
||||
el("ul").append(
|
||||
el("li").append(el("a", { href: "/" }, "Home")),
|
||||
el("li").append(el("a", { href: "/about" }, "About")),
|
||||
el("li").append(el("a", { href: "/contact" }, "Contact"))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Create the page content
|
||||
dom.window.document.body.append(
|
||||
el(Header, { title: "My Static Site" }),
|
||||
el("main").append(
|
||||
el("h2", "Welcome!"),
|
||||
el("p", "This page was rendered with deka-dom-el on the server.")
|
||||
),
|
||||
el("footer", "© 2025 My Company")
|
||||
);
|
||||
|
||||
// Wait for any async operations
|
||||
await queue();
|
||||
|
||||
// Get the HTML and write it to a file
|
||||
const html = dom.serialize();
|
||||
writeFileSync("index.html", html);
|
||||
|
||||
console.log("Page rendered successfully!");
|
||||
}
|
||||
|
||||
renderPage().catch(console.error);
|
2
docs/components/examples/ssr/intro.js
Normal file
2
docs/components/examples/ssr/intro.js
Normal file
@ -0,0 +1,2 @@
|
||||
// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js
|
||||
import { register, unregister, queue } from "deka-dom-el/jsdom";
|
35
docs/components/examples/ssr/pages.js
Normal file
35
docs/components/examples/ssr/pages.js
Normal file
@ -0,0 +1,35 @@
|
||||
// ❌ WRONG: Static imports are hoisted and will register before JSDOM is created
|
||||
import { register } from "deka-dom-el/jsdom";
|
||||
import { el } from "deka-dom-el";
|
||||
import { Header } from "./components/Header.js";
|
||||
|
||||
// ✅ CORRECT: Use dynamic imports to ensure proper initialization order
|
||||
import { JSDOM } from "jsdom";
|
||||
|
||||
async function renderPage() {
|
||||
// 1. Create JSDOM instance first
|
||||
const dom = new JSDOM(`<!DOCTYPE html><html><body></body></html>`);
|
||||
|
||||
// 2. Dynamically import jsdom module
|
||||
const { register, queue } = await import("deka-dom-el/jsdom");
|
||||
|
||||
// 3. Register and get el function
|
||||
const { el } = await register(dom);
|
||||
|
||||
// 4. Dynamically import page components
|
||||
const { Header } = await import("./components/Header.js");
|
||||
const { Content } = await import("./components/Content.js");
|
||||
|
||||
// 5. Render components
|
||||
const body = dom.window.document.body;
|
||||
el(body).append(
|
||||
el(Header, { title: "My Page" }),
|
||||
el(Content, { text: "This is server-rendered content" })
|
||||
);
|
||||
|
||||
// 6. Wait for async operations
|
||||
await queue();
|
||||
|
||||
// 7. Get HTML and clean up
|
||||
return dom.serialize();
|
||||
}
|
27
docs/components/examples/ssr/start.js
Normal file
27
docs/components/examples/ssr/start.js
Normal file
@ -0,0 +1,27 @@
|
||||
// Basic jsdom integration example
|
||||
import { JSDOM } from "jsdom";
|
||||
import { register, unregister, queue } from "deka-dom-el/jsdom.js";
|
||||
|
||||
// Create a jsdom instance
|
||||
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
|
||||
|
||||
// Register the dom with deka-dom-el
|
||||
const { el } = await register(dom);
|
||||
|
||||
// Use deka-dom-el normally
|
||||
dom.window.document.body.append(
|
||||
el("div", { className: "container" }).append(
|
||||
el("h1", "Hello, SSR World!"),
|
||||
el("p", "This content was rendered on the server.")
|
||||
)
|
||||
);
|
||||
|
||||
// Wait for any async operations to complete
|
||||
await queue();
|
||||
|
||||
// Get the rendered HTML
|
||||
const html = dom.serialize();
|
||||
console.log(html);
|
||||
|
||||
// Clean up when done
|
||||
unregister();
|
44
docs/components/examples/ssr/static-site-generator.js
Normal file
44
docs/components/examples/ssr/static-site-generator.js
Normal file
@ -0,0 +1,44 @@
|
||||
// Building a simple static site generator
|
||||
import { JSDOM } from "jsdom";
|
||||
import { register, queue } from "deka-dom-el/jsdom";
|
||||
import { writeFileSync, mkdirSync } from "node:fs";
|
||||
|
||||
async function buildSite() {
|
||||
// Define pages to build
|
||||
const pages = [
|
||||
{ id: "index", title: "Home", component: "./pages/home.js" },
|
||||
{ id: "about", title: "About", component: "./pages/about.js" },
|
||||
{ id: "docs", title: "Documentation", component: "./pages/docs.js" }
|
||||
];
|
||||
|
||||
// Create output directory
|
||||
mkdirSync("./dist", { recursive: true });
|
||||
|
||||
// Build each page
|
||||
for (const page of pages) {
|
||||
// Create a fresh jsdom instance for each page
|
||||
const dom = new JSDOM("<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head><body></body></html>");
|
||||
|
||||
// Register with deka-dom-el
|
||||
const { el } = await register(dom);
|
||||
|
||||
// Import the page component
|
||||
const { default: PageComponent } = await import(page.component);
|
||||
|
||||
// Render the page with its metadata
|
||||
dom.window.document.body.append(
|
||||
el(PageComponent, { title: page.title, pages })
|
||||
);
|
||||
|
||||
// Wait for any async operations
|
||||
await queue();
|
||||
|
||||
// Write the HTML to a file
|
||||
const html = dom.serialize();
|
||||
writeFileSync(`./dist/${page.id}.html`, html);
|
||||
|
||||
console.log(`Built page: ${page.id}.html`);
|
||||
}
|
||||
}
|
||||
|
||||
buildSite().catch(console.error);
|
88
docs/components/ireland.html.js
Normal file
88
docs/components/ireland.html.js
Normal file
@ -0,0 +1,88 @@
|
||||
import { el, queue } from "deka-dom-el";
|
||||
import { addEventListener, registerClientFile } from "../ssr.js";
|
||||
import { relative } from "node:path";
|
||||
|
||||
const dir= new URL("./", import.meta.url).pathname;
|
||||
const dirFE= "irelands";
|
||||
// Track all component instances for client-side rehydration
|
||||
const componentsRegistry = new Map();
|
||||
/**
|
||||
* Creates a component that shows code and its runtime output
|
||||
* with server-side pre-rendering and client-side rehydration
|
||||
*
|
||||
* @param {object} attrs
|
||||
* @param {URL} attrs.src - Path to the file containing the component
|
||||
* @param {string} [attrs.exportName="default"] - Name of the export to use
|
||||
* @param {string} attrs.page_id - ID of the current page
|
||||
* @param {object} [attrs.props={}] - Props to pass to the component
|
||||
*/
|
||||
export function ireland({ src, exportName = "default", props = {} }) {
|
||||
// relative src against the current directory
|
||||
const path= "./"+relative(dir, src.pathname);
|
||||
const id = "ireland-" + generateComponentId(src);
|
||||
const element = el.mark({ type: "later", name: ireland.name });
|
||||
queue(import(path).then(module => {
|
||||
const component = module[exportName];
|
||||
element.replaceWith(el(component, props, mark(id)));
|
||||
}));
|
||||
|
||||
if(!componentsRegistry.size)
|
||||
addEventListener("oneachrender", registerClientPart);
|
||||
componentsRegistry.set(id, {
|
||||
src,
|
||||
path: dirFE+"/"+path.split("/").pop(),
|
||||
exportName,
|
||||
props,
|
||||
});
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
function registerClientPart(){
|
||||
const todo= Array.from(componentsRegistry.entries())
|
||||
.map(([ id, d ]) => {
|
||||
registerClientFile(d.src, {
|
||||
folder: dirFE,
|
||||
// not all browsers support importmap
|
||||
replacer(file){
|
||||
return file
|
||||
.replaceAll(/ from "deka-dom-el(\/signals)?";/g, ` from "./esm-with-signals.js";`);
|
||||
}
|
||||
});
|
||||
return [ id, d ];
|
||||
});
|
||||
const store = JSON.stringify(JSON.stringify(todo));
|
||||
registerClientFile(new URL("./ireland.js.js", import.meta.url));
|
||||
registerClientFile(new URL("../../dist/esm-with-signals.js", import.meta.url), { folder: dirFE });
|
||||
document.head.append(
|
||||
// not all browsers support importmap
|
||||
el("script", { type: "importmap" }).append(`
|
||||
{
|
||||
"imports": {
|
||||
"deka-dom-el": "./${dirFE}/esm-with-signals.js",
|
||||
"deka-dom-el/signals": "./${dirFE}/esm-with-signals.js"
|
||||
}
|
||||
}
|
||||
`.trim())
|
||||
);
|
||||
document.body.append(
|
||||
el("script", { type: "module" }).append(`
|
||||
import { loadIrelands } from "./ireland.js.js";
|
||||
loadIrelands(new Map(JSON.parse(${store})));
|
||||
`.trim())
|
||||
)
|
||||
}
|
||||
function mark(id) { return el=> el.dataset.ddeMark= id; }
|
||||
const store_prev= new Map();
|
||||
/** @param {URL} src */
|
||||
function generateComponentId(src){
|
||||
const candidate= parseInt(relative((new URL("..", import.meta.url)).pathname, src.pathname)
|
||||
.split("")
|
||||
.map(ch=> ch.charCodeAt(0))
|
||||
.join(""), 10)
|
||||
.toString(36)
|
||||
.replace(/000+/g, "");
|
||||
const count= 1 + ( store_prev.get(candidate) || 0 );
|
||||
store_prev.set(candidate, count);
|
||||
return count.toString()+"-"+candidate;
|
||||
}
|
13
docs/components/ireland.js.js
Normal file
13
docs/components/ireland.js.js
Normal file
@ -0,0 +1,13 @@
|
||||
// not all browsers support importmaps
|
||||
// import { el } from "deka-dom-el";
|
||||
import { el } from "./irelands/esm-with-signals.js";
|
||||
export function loadIrelands(store) {
|
||||
document.body.querySelectorAll("[data-dde-mark]").forEach(ireland => {
|
||||
const { ddeMark }= ireland.dataset;
|
||||
if(!store.has(ddeMark)) return;
|
||||
const { path, exportName, props }= store.get(ddeMark);
|
||||
import("./"+path).then(module => {
|
||||
ireland.replaceWith(el(module[exportName], props));
|
||||
})
|
||||
});
|
||||
}
|
@ -17,8 +17,14 @@ export function mnemonic(){
|
||||
" — just ", el("code", "<element>.dispatchEvent(new Event(<event>[, <options>]))")
|
||||
),
|
||||
el("li").append(
|
||||
el("code", "dispatchEvent(<event>[, <options>])(element, detail)"),
|
||||
" — just ", el("code", "<element>.dispatchEvent(new CustomEvent(<event>, { detail, ...<options> }))")
|
||||
el("code", "dispatchEvent(<event>, <element>)([<detail>])"),
|
||||
" — just ", el("code", "<element>.dispatchEvent(new Event(<event>))"), " or ",
|
||||
el("code", "<element>.dispatchEvent(new CustomEvent(<event>, { detail: <detail> }))")
|
||||
),
|
||||
el("li").append(
|
||||
el("code", "dispatchEvent(<event>[, <options>])(<element>[, <detail>])"),
|
||||
" — just ", el("code", "<element>.dispatchEvent(new Event(<event>[, <options>] ))"), " or ",
|
||||
el("code", "<element>.dispatchEvent(new CustomEvent(<event>, { detail: <detail> }))")
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1,18 +1,67 @@
|
||||
import { pages, styles } from "../ssr.js";
|
||||
const host= "."+prevNext.name;
|
||||
styles.css`
|
||||
${host}{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 2fr 1fr;
|
||||
margin-top: 1rem;
|
||||
/* Previous/Next navigation */
|
||||
${host} {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 3rem;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid var(--border);
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
${host} [rel=prev]{
|
||||
grid-column: 1;
|
||||
|
||||
${host} a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: var(--border-radius);
|
||||
background-color: var(--primary-dark); /* Darker background for better contrast */
|
||||
color: white;
|
||||
font-weight: 600; /* Bolder text for better readability */
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
|
||||
max-width: 45%;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); /* Subtle shadow for better visibility */
|
||||
}
|
||||
${host} [rel=next]{
|
||||
grid-column: 3;
|
||||
text-align: right;
|
||||
|
||||
${host} a:hover {
|
||||
background-color: var(--primary);
|
||||
transform: translateY(-2px);
|
||||
text-decoration: none;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* Enhanced shadow on hover */
|
||||
}
|
||||
|
||||
${host} [rel=prev] {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
${host} [rel=next] {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
${host} [rel=prev]::before {
|
||||
content: "←";
|
||||
margin-right: 0.75rem;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
${host} [rel=next]::after {
|
||||
content: "→";
|
||||
margin-left: 0.75rem;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* If there's no previous/next, ensure the spacing still works */
|
||||
${host} a:only-child {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
${host} a {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
`;
|
||||
import { el } from "../../index.js";
|
||||
@ -22,21 +71,28 @@ import { el } from "../../index.js";
|
||||
* @param {string} [attrs.id]
|
||||
* */
|
||||
export function h3({ textContent, id }){
|
||||
if(!id) id= "h-"+textContent.toLowerCase().replaceAll(/\s/g, "-").replaceAll(/[^a-z-]/g, "");
|
||||
return el("h3", { id }).append(
|
||||
el("a", { textContent: "#", href: "#"+id, tabIndex: -1 }),
|
||||
" ", textContent
|
||||
);
|
||||
if(!id) id= "h-"+textContent.toLowerCase().replaceAll(/\s/g, "-").replaceAll(/[^a-z-]/g, "");
|
||||
return el("h3", { id }).append(
|
||||
el("a", {
|
||||
className: "heading-anchor",
|
||||
href: "#"+id,
|
||||
textContent: "#",
|
||||
title: `Link to this section: ${textContent}`,
|
||||
"aria-label": `Link to section ${textContent}`
|
||||
}),
|
||||
" ",
|
||||
textContent,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {import("../types.d.ts").Info} page
|
||||
* */
|
||||
export function prevNext(page){
|
||||
const page_index= pages.indexOf(page);
|
||||
return el("div", { className: prevNext.name }).append(
|
||||
el(pageLink, { rel: "prev", page: pages[page_index-1] }),
|
||||
el(pageLink, { rel: "next", page: pages[page_index+1] })
|
||||
);
|
||||
const page_index= pages.indexOf(page);
|
||||
return el("div", { className: prevNext.name }).append(
|
||||
el(pageLink, { rel: "prev", page: pages[page_index-1] }),
|
||||
el(pageLink, { rel: "next", page: pages[page_index+1] })
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {Object} attrs
|
||||
@ -44,11 +100,22 @@ export function prevNext(page){
|
||||
* @param {import("../types.d.ts").Info} [attrs.page]
|
||||
* */
|
||||
function pageLink({ rel, page }){
|
||||
if(!page) return el();
|
||||
let { href, title, description }= page;
|
||||
return el("a", { rel, href, title: description }).append(
|
||||
rel==="next" ?"(next) " : "",
|
||||
title,
|
||||
rel==="prev" ? " (previous)" : "",
|
||||
);
|
||||
if(!page) return el();
|
||||
let { href, title, description }= page;
|
||||
|
||||
// Find the page index to show numbering
|
||||
const pageIndex = pages.findIndex(p => p === page);
|
||||
const pageNumber = pageIndex + 1;
|
||||
|
||||
const linkTitle = rel === "prev"
|
||||
? `Previous: ${pageNumber}. ${title}`
|
||||
: `Next: ${pageNumber}. ${title}`;
|
||||
|
||||
return el("a", {
|
||||
rel,
|
||||
href,
|
||||
title: description || linkTitle
|
||||
}).append(
|
||||
title
|
||||
);
|
||||
}
|
||||
|
@ -1,124 +1,476 @@
|
||||
import { styles } from "./ssr.js";
|
||||
styles.css`
|
||||
@import url(https://cdn.simplecss.org/simple.min.css);
|
||||
:root{
|
||||
--body-max-width: 45rem;
|
||||
--marked: #fb3779;
|
||||
--code: #0d47a1;
|
||||
--accent: #d81b60;
|
||||
:root {
|
||||
--primary: hsl(0, 74%, 42%);
|
||||
--primary-light: hsl(5, 87%, 61%);
|
||||
--primary-dark: hsl(0, 100%, 25%);
|
||||
--primary-hs: 0, 74%;
|
||||
--secondary: hsl(330, 100%, 22%);
|
||||
--secondary-light: hsl(339, 80%, 38%);
|
||||
--secondary-dark: hsl(328, 100%, 15%);
|
||||
--secondary-hs: 330, 100%;
|
||||
|
||||
--font-main: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
||||
Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
--font-mono: 'Fira Code', 'JetBrains Mono', 'SF Mono',
|
||||
SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
|
||||
--body-max-width: 40rem;
|
||||
--sidebar-width: 20rem;
|
||||
--header-height: 4rem;
|
||||
--border-radius: 0.375rem;
|
||||
|
||||
--bg: hsl(0, 0%, 100%);
|
||||
--bg-sidebar: hsl(0, 100%, 98%);
|
||||
--text: hsl(0, 16%, 15%);
|
||||
--text-light: hsl(0, 4%, 33%);
|
||||
--code-bg: hsl(0, 39%, 97%);
|
||||
--code-text: hsl(0, 100%, 30%);
|
||||
--border: hsl(0, 32%, 80%);
|
||||
--selection: hsl(var(--primary-hs), 90%);
|
||||
--marked: var(--primary);
|
||||
--accent: var(--secondary);
|
||||
--shadow: 0 2px 6px hsla(0, 0%, 0%, 0.15);
|
||||
--shadow-sm: 0 2px 4px hsla(0, 0%, 0%, 0.15);
|
||||
|
||||
|
||||
--link-color: hsl(0, 100%, 30%);
|
||||
--link-hover: hsl(0, 100%, 25%);
|
||||
--button-text: hsl(0, 0%, 100%);
|
||||
}
|
||||
@media (prefers-color-scheme:dark) {
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--accent: #f06292;
|
||||
--code: #62c1f0;
|
||||
--bg: hsl(0, 0%, 7%);
|
||||
--bg-sidebar: hsl(0, 9%, 9%);
|
||||
--text: hsl(0, 0%, 100%);
|
||||
--text-light: hsl(0, 0%, 80%);
|
||||
--code-bg: hsl(0, 18%, 15%);
|
||||
--code-text: hsl(20, 100%, 75%);
|
||||
--border: hsl(0, 14%, 27%);
|
||||
--selection: hsla(9, 100%, 64%, 0.25);
|
||||
--primary: hsl(0, 48%, 49%);
|
||||
--primary-light: hsl(5, 100%, 75%);
|
||||
--primary-dark: hsl(0, 67%, 47%);
|
||||
--secondary: hsl(350, 87%, 55%);
|
||||
--secondary-light: hsl(341, 100%, 69%);
|
||||
--secondary-dark: hsl(340, 100%, 35%);
|
||||
--accent: var(--secondary);
|
||||
|
||||
--link-color: hsl(0, 100%, 66%);
|
||||
--link-hover: hsl(5, 100%, 75%);
|
||||
--button-text: hsl(0, 0%, 100%);
|
||||
|
||||
--primary-hs: 0, 48%;
|
||||
--secondary-hs: 350, 87%;
|
||||
}
|
||||
}
|
||||
body {
|
||||
grid-template-columns: 100%;
|
||||
grid-template-areas: "header" "sidebar" "content";
|
||||
|
||||
/* Base styling */
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@media (min-width:768px) {
|
||||
body{
|
||||
grid-template-rows: auto auto;
|
||||
grid-template-columns: calc(10 * var(--body-max-width) / 27) auto;
|
||||
grid-template-areas:
|
||||
"header header"
|
||||
"sidebar content"
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Accessibility improvements */
|
||||
:focus {
|
||||
outline: 3px solid hsl(231, 48%, 70%);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 3px solid hsl(231, 48%, 70%);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Ensure reduced motion preferences are respected */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
/* Skip link for better keyboard navigation */
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: translateX(-100%);
|
||||
z-index: 9999;
|
||||
background-color: var(--primary);
|
||||
color: white;
|
||||
padding: 0.5rem 1rem;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: all .15s;
|
||||
transition: transform 0.3s ease-in-out;
|
||||
}
|
||||
body > nav a.current,
|
||||
body > nav a[aria-current=page] {
|
||||
background-color: var(--bg);
|
||||
|
||||
.skip-link:focus {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
::selection {
|
||||
background-color: var(--selection);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 2rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.25;
|
||||
color: var(--text);
|
||||
}
|
||||
body > nav a:hover{
|
||||
|
||||
h1 {
|
||||
font-size: 2.25rem;
|
||||
margin-top: 0;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
h1 > a {
|
||||
font-weight: unset;
|
||||
color: unset;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.25rem;
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link-color, var(--primary));
|
||||
transition: color 0.2s ease;
|
||||
font-weight: 500;
|
||||
text-underline-offset: 3px;
|
||||
transition: color 0.2s ease, text-underline-offset 0.2s ease;
|
||||
}
|
||||
a:visited {
|
||||
--link-color: var(--secondary, #700037);
|
||||
}
|
||||
a:hover {
|
||||
--link-color: var(--link-hover, var(--primary-light));
|
||||
text-underline-offset: 5px;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.9em;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: var(--code-bg);
|
||||
color: var(--code-text);
|
||||
padding: 0.2em 0.4em;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: var(--code-bg);
|
||||
padding: 1rem;
|
||||
overflow-x: auto;
|
||||
margin-bottom: 1.5rem;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
pre code {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Layout */
|
||||
body {
|
||||
font-family: var(--font-main);
|
||||
background-color: var(--bg);
|
||||
color: var(--accent);
|
||||
color: var(--text);
|
||||
line-height: 1.6;
|
||||
font-size: 1.05rem;
|
||||
display: grid;
|
||||
grid-template-columns: 100%;
|
||||
grid-template-areas:
|
||||
"header"
|
||||
"sidebar"
|
||||
"content";
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
--_gap: .75em;
|
||||
gap: var(--_gap);
|
||||
padding: var(--_gap);
|
||||
}
|
||||
@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;
|
||||
@media (min-width: 768px) {
|
||||
body {
|
||||
grid-template-rows: var(--header-height) 1fr;
|
||||
grid-template-columns: var(--sidebar-width) 1fr;
|
||||
grid-template-areas:
|
||||
"header header"
|
||||
"sidebar content";
|
||||
}
|
||||
}
|
||||
main{
|
||||
body > main {
|
||||
grid-area: content;
|
||||
max-width: 100%;
|
||||
overflow-x: hidden;
|
||||
display: grid;
|
||||
grid-template-columns:
|
||||
[full-main-start] 1fr
|
||||
[main-start] min(var(--body-max-width), 90%) [main-end]
|
||||
1fr [full-main-end];
|
||||
}
|
||||
main > *, main slot > *{
|
||||
body > main > *, body > main slot > * {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin-inline: auto;
|
||||
grid-column: main;
|
||||
}
|
||||
|
||||
/* Page title with ID anchor for skip link */
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.75rem;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
/* Section headings with better visual hierarchy */
|
||||
body > main h3, body > main h4 {
|
||||
scroll-margin-top: calc(var(--header-height) + 1rem);
|
||||
}
|
||||
|
||||
/* Make clickable heading links for better navigation */
|
||||
.heading-anchor {
|
||||
color: var(--text-light);
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
opacity: .4;
|
||||
transition: opacity .2s;
|
||||
|
||||
&:hover { opacity: .8; }
|
||||
}
|
||||
|
||||
/* Boxes */
|
||||
.illustration{
|
||||
grid-column: full-main;
|
||||
width: calc(100% - .75em);
|
||||
}
|
||||
.illustration:not(:has( .comparison)){
|
||||
grid-column: main;
|
||||
|
||||
pre {
|
||||
background: none;
|
||||
border-style: dashed !important;
|
||||
width: fit-content;
|
||||
padding: 1em 2em;
|
||||
}
|
||||
}
|
||||
|
||||
.comparison {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: calc(.75em / 2);
|
||||
margin: 1.5rem 0;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.comparison {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.good-practice, .bad-practice {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--border-radius);
|
||||
border-top: 4px solid var(--practice-color);
|
||||
padding: 0 1rem;
|
||||
}
|
||||
.good-practice {
|
||||
--practice-color: hsl(145, 63%, 49%); }
|
||||
.bad-practice {
|
||||
--practice-color: hsl(340, 82%, 52%); }
|
||||
|
||||
/* Icon styling */
|
||||
.icon {
|
||||
vertical-align: sub;
|
||||
padding-right: .25rem;
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1.3em;
|
||||
margin-right: 0.2rem;
|
||||
height: 1em;
|
||||
vertical-align: -0.125em;
|
||||
stroke-width: 0;
|
||||
stroke: currentColor;
|
||||
fill: currentColor;
|
||||
}
|
||||
.note{
|
||||
font-size: .9rem;
|
||||
font-style: italic;
|
||||
|
||||
/* Information blocks */
|
||||
.note, .tip, .warning, .callout, .troubleshooting {
|
||||
padding: 1rem 1.25rem;
|
||||
margin: 1.5rem 0;
|
||||
border-radius: var(--border-radius);
|
||||
position: relative;
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.5;
|
||||
background-color: var(--bg-sidebar);
|
||||
border-radius: 0 var(--border-radius) var(--border-radius) 0;
|
||||
--block-color: var(--primary);
|
||||
border-left: 4px solid var(--block-color);
|
||||
|
||||
h4 { margin-top: 0; }
|
||||
}
|
||||
.tip {
|
||||
--block-color: hsl(145, 63%, 49%); }
|
||||
.warning {
|
||||
--block-color: hsl(48, 89%, 50%); }
|
||||
|
||||
.callout {
|
||||
--block-color: hsl(231, 48%, 70%); }
|
||||
|
||||
.troubleshooting {
|
||||
--block-color: hsl(340, 82%, 52%); }
|
||||
|
||||
.note::before, .tip::before, .warning::before, .callout::before, .troubleshooting::before {
|
||||
font-weight: 600;
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--block-color);
|
||||
}
|
||||
|
||||
.note::before {
|
||||
content: "Note"; }
|
||||
.warning::before {
|
||||
content: "Warning"; }
|
||||
|
||||
/* Function table styling */
|
||||
.function-table {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 1rem;
|
||||
margin: 1.5rem 0;
|
||||
background-color: var(--bg-sidebar);
|
||||
}
|
||||
|
||||
.function-table h4 {
|
||||
margin-top: 0;
|
||||
color: var(--primary);
|
||||
font-family: var(--font-mono);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.function-table dl {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.function-table dt {
|
||||
font-weight: 600;
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.function-table dd {
|
||||
margin-left: 1rem;
|
||||
margin-bottom: 0.75rem;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/* Tabs styling */
|
||||
.tabs {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--border-radius);
|
||||
margin: 1.5rem 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 1rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.tab:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.tab h4 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.75rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.tabs {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
.tab {
|
||||
flex: 1;
|
||||
min-width: 50%;
|
||||
border-top: none;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
align-items: center;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.tab:first-child {
|
||||
border-inline-end: 1px solid var(--border);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prev/Next buttons */
|
||||
.prev-next {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 3rem;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.prev-next a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: var(--border-radius);
|
||||
background-color: var(--primary);
|
||||
color: white;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.prev-next a:hover {
|
||||
background-color: var(--primary-dark);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.prev-next a:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.prev-next a[rel="prev"]::before {
|
||||
content: "←";
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.prev-next a[rel="next"]::after {
|
||||
content: "→";
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
`;
|
||||
|
@ -2,7 +2,8 @@ import { t, T } from "./utils/index.js";
|
||||
export const info= {
|
||||
href: "./",
|
||||
title: t`Introduction`,
|
||||
description: t`Introducing a library.`,
|
||||
fullTitle: t`Vanilla for flavouring — a full-fledged feast for large projects`,
|
||||
description: t`A lightweight, reactive DOM library for creating dynamic UIs with a declarative syntax`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
@ -26,37 +27,90 @@ const references= {
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("p", t`The library tries to provide pure JavaScript tool(s) to create reactive interfaces using …`),
|
||||
|
||||
el(h3, t`Event-driven programming (3 parts separation ≡ 3PS)`),
|
||||
el("p").append(t`
|
||||
Let's introduce the basic principle on which the library is built. We'll use the JavaScript listener as
|
||||
a starting point.
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/introducing/3ps.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
As we can see, in the code at location “A” we define ${el("em", t`how to react`)} when the function
|
||||
is called with any event as an argument. At that moment, we ${el("em", t`don’t care who/why/how`)}
|
||||
the function was called. Similarly, at point “B”, we reference to a function to be called on the event
|
||||
${el("em", t`without caring`)} what the function will do at that time. Finally, at point “C”, we tell
|
||||
the application that a change has occurred, in the input, and we ${el("em", t`don't care if/how someone`)}
|
||||
is listening for the event.
|
||||
Welcome to Deka DOM Elements (DDE) — a lightweight library for building dynamic UIs with a declarative
|
||||
syntax that stays close to the native DOM API. DDE gives you powerful reactive tools without the complexity
|
||||
and overhead of larger frameworks.
|
||||
`),
|
||||
el("div", { className: "callout" }).append(
|
||||
el("h4", t`What Makes DDE Special`),
|
||||
el("ul").append(
|
||||
el("li", t`No build step required — use directly in the browser`),
|
||||
el("li", t`Lightweight core (~10–15kB minified) with zero dependencies`),
|
||||
el("li", t`Natural DOM API — work with real DOM nodes, not abstractions`),
|
||||
el("li", t`Built-in reactivity with powerful signals system`),
|
||||
el("li", t`Clean code organization with the 3PS pattern`)
|
||||
)
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/introducing/helloWorld.js"), page_id }),
|
||||
|
||||
el(h3, { textContent: t`The 3PS Pattern: A Better Way to Build UIs`, id: "h-3ps" }),
|
||||
el("p").append(...T`
|
||||
The library introduces a new “type” of variable/constant called ${el("em", t`signal`)} allowing us to
|
||||
to use introduced 3PS pattern in our applications. As you can see it in the example above.
|
||||
At the heart of DDE is the 3PS (3-Part Separation) pattern. This simple yet powerful approach helps you
|
||||
organize your UI code into three distinct areas, making your applications more maintainable and easier
|
||||
to reason about.
|
||||
`),
|
||||
el("div", { className: "illustration" }).append(
|
||||
el("div", { className: "tabs" }).append(
|
||||
el("div", { className: "tab" }).append(
|
||||
el("h5", t`Traditional DOM Manipulation`),
|
||||
el(code, { src: fileURL("./components/examples/introducing/3ps-before.js"), page_id }),
|
||||
),
|
||||
el("div", { className: "tab" }).append(
|
||||
el("h5", t`DDE's 3PS Pattern`),
|
||||
el(code, { src: fileURL("./components/examples/introducing/3ps.js"), page_id }),
|
||||
)
|
||||
)
|
||||
),
|
||||
el("p").append(...T`
|
||||
Also please notice that there is very similar 3PS pattern used for separate creation of UI and
|
||||
business logic.
|
||||
The 3PS pattern separates your code into three clear parts:
|
||||
`),
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Create State")}: Define your application's reactive data using signals
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Bind to Elements")}: Define how UI elements react to state changes
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Update State")}: Modify state in response to user events or other triggers
|
||||
`)
|
||||
),
|
||||
|
||||
el("p").append(...T`
|
||||
The 3PS is very simplified definition of the pattern. There are more deep/academic definitions more precisely
|
||||
describe usage in specific situations, see for example ${el("a", { textContent: t`MVVM`, ...references.w_mvv })}
|
||||
or ${el("a", { textContent: t`MVC`, ...references.w_mvc })}.
|
||||
By separating these concerns, your code becomes more modular, testable, and easier to maintain. This
|
||||
approach shares principles with more formal patterns like ${el("a", { textContent: "MVVM",
|
||||
...references.w_mvv })} and ${el("a", { textContent: "MVC", ...references.w_mvc })}, but with less
|
||||
overhead and complexity.
|
||||
`),
|
||||
|
||||
el(h3, t`Organization of the documentation`),
|
||||
el("div", { className: "note" }).append(
|
||||
el("p").append(...T`
|
||||
The 3PS pattern becomes especially powerful when combined with components, allowing you to create
|
||||
reusable pieces of UI with encapsulated state and behavior. You'll learn more about this in the
|
||||
following sections.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`How to Use This Documentation`),
|
||||
el("p").append(...T`
|
||||
This guide will take you through DDE's features step by step:
|
||||
`),
|
||||
el("ol").append(
|
||||
el("li").append(...T`${el("strong", "Elements")} — Creating and manipulating DOM elements`),
|
||||
el("li").append(...T`${el("strong", "Events")} — Handling user interactions and lifecycle events`),
|
||||
el("li").append(...T`${el("strong", "Signals")} — Adding reactivity to your UI`),
|
||||
el("li").append(...T`${el("strong", "Scopes")} — Managing component lifecycles`),
|
||||
el("li").append(...T`${el("strong", "Custom Elements")} — Building web components`),
|
||||
el("li").append(...T`${el("strong", "Debugging")} — Tools to help you build and fix your apps`),
|
||||
el("li").append(...T`${el("strong", "Extensions")} — Integrating third-party functionalities`),
|
||||
el("li").append(...T`${el("strong", "Ireland Components")} —
|
||||
Creating interactive demos with server-side pre-rendering`),
|
||||
el("li").append(...T`${el("strong", "SSR")} — Server-side rendering with DDE`)
|
||||
),
|
||||
el("p").append(...T`
|
||||
Each section builds on the previous ones, so we recommend following them in order.
|
||||
Let's get started with the basics of creating elements!
|
||||
`),
|
||||
);
|
||||
}
|
||||
|
@ -1,38 +1,220 @@
|
||||
import { el, elNS } from "deka-dom-el";
|
||||
import { pages } from "../ssr.js";
|
||||
import { pages, styles } from "../ssr.js";
|
||||
const host= "."+header.name;
|
||||
const host_nav= "."+nav.name;
|
||||
styles.css`
|
||||
/* Header */
|
||||
${host} {
|
||||
grid-area: header;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background-color: var(--primary);
|
||||
color: white;
|
||||
box-shadow: var(--shadow);
|
||||
height: fit-content;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
${host} .header-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
${host} h1 {
|
||||
font-size: 1.25rem;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: white;
|
||||
}
|
||||
|
||||
${host} .version-badge {
|
||||
font-size: 0.75rem;
|
||||
background-color: hsla(0, 0%, 59%, 0.2);
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
${host} p {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
opacity: 0.9;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
${host_nav} .github-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
${host_nav} {
|
||||
grid-area: sidebar;
|
||||
background-color: var(--bg-sidebar);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
${host_nav} a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.625rem 0.75rem;
|
||||
border-radius: var(--border-radius);
|
||||
color: var(--text);
|
||||
transition: background-color 0.1s ease, color 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
${host_nav} a[aria-current=page] {
|
||||
background-color: hsl(var(--primary-hs), 40%);
|
||||
color: whitesmoke;
|
||||
font-weight: 600;
|
||||
box-shadow: var(--shadow);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
${host_nav} a:hover {
|
||||
background-color: hsl(var(--primary-hs), 45%);
|
||||
color: whitesmoke;
|
||||
transform: translateY(-1px);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
${host_nav} a .nav-number {
|
||||
color: rgb(from currentColor r g b / .75);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
${host_nav} {
|
||||
height: fit-content;
|
||||
position: sticky;
|
||||
top: .5rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
${host_nav} {
|
||||
padding: 0.75rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
border-right: none;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
${host_nav} a {
|
||||
font-size: 0.875rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
${host_nav} a .nav-number {
|
||||
width: auto;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
${host_nav} a:first-child {
|
||||
margin-bottom: 0;
|
||||
margin-right: 0.5rem;
|
||||
min-width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
`;
|
||||
/**
|
||||
* @param {object} def
|
||||
* @param {import("../types.d.ts").Info} def.info
|
||||
* @param {import("../types.d.ts").Pkg} def.pkg Package information.
|
||||
* */
|
||||
export function header({ info: { href, title, description }, pkg }){
|
||||
title= `\`${pkg.name}\` — ${title}`;
|
||||
const pageTitle = `${pkg.name} — ${title}`;
|
||||
|
||||
// Add meta elements to the head
|
||||
document.head.append(
|
||||
head({ title, description, pkg })
|
||||
head({ title: pageTitle, description, pkg })
|
||||
);
|
||||
|
||||
return el().append(
|
||||
el("header").append(
|
||||
el("h1", title),
|
||||
el("p", description)
|
||||
),
|
||||
el("nav").append(
|
||||
el("a", { href: pkg.homepage }).append(
|
||||
el(iconGitHub),
|
||||
"GitHub"
|
||||
// Header section with accessibility support
|
||||
el("header", { role: "banner", className: header.name }).append(
|
||||
el("div", { className: "header-title" }).append(
|
||||
el("img", {
|
||||
src: "assets/logo.svg",
|
||||
alt: "DDE Logo",
|
||||
width: "32",
|
||||
height: "32",
|
||||
style: "margin-right: 0.5rem;"
|
||||
}),
|
||||
el("h1").append(
|
||||
el("a", { href: pages[0].href, textContent: pkg.name, title: "Go to documentation homepage" }),
|
||||
),
|
||||
el("span", {
|
||||
className: "version-badge",
|
||||
"aria-label": "Version",
|
||||
textContent: pkg.version || ""
|
||||
})
|
||||
),
|
||||
...pages.map((p, i)=> el("a", {
|
||||
href: p.href==="index" ? "./" : p.href,
|
||||
textContent: (i+1) + ". " + p.title,
|
||||
title: p.description,
|
||||
classList: { current: p.href===href }
|
||||
}))
|
||||
)
|
||||
el("p", description),
|
||||
),
|
||||
|
||||
// Navigation between pages
|
||||
nav({ href, pkg })
|
||||
);
|
||||
}
|
||||
function nav({ href, pkg }){
|
||||
return el("nav", {
|
||||
role: "navigation",
|
||||
"aria-label": "Main navigation",
|
||||
className: nav.name
|
||||
}).append(
|
||||
el("a", {
|
||||
href: pkg.homepage,
|
||||
className: "github-link",
|
||||
"aria-label": "View on GitHub",
|
||||
target: "_blank",
|
||||
rel: "noopener noreferrer",
|
||||
}).append(
|
||||
el(iconGitHub),
|
||||
"GitHub"
|
||||
),
|
||||
...pages.map((p, i) => {
|
||||
const isIndex = p.href === "index";
|
||||
const isCurrent = p.href === href;
|
||||
|
||||
return el("a", {
|
||||
href: isIndex ? "./" : p.href,
|
||||
title: p.description || `Go to ${p.title}`,
|
||||
"aria-current": isCurrent ? "page" : null,
|
||||
}).append(
|
||||
el("span", {
|
||||
className: "nav-number",
|
||||
"aria-hidden": "true",
|
||||
textContent: `${i+1}. `
|
||||
}),
|
||||
p.title
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
function head({ title, description, pkg }){
|
||||
return el().append(
|
||||
el("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
|
||||
el("meta", { name: "description", content: description }),
|
||||
el("meta", { name: "theme-color", content: "#b71c1c" }),
|
||||
el("link", { rel: "icon", href: "assets/favicon.svg", type: "image/svg+xml" }),
|
||||
el("title", title),
|
||||
el(metaAuthor),
|
||||
el(metaTwitter, pkg),
|
||||
@ -53,7 +235,7 @@ function metaTwitter({ name, description, homepage }){
|
||||
el("meta", { name: "twitter:url", content: homepage }),
|
||||
el("meta", { name: "twitter:title", content: name }),
|
||||
el("meta", { name: "twitter:description", content: description }),
|
||||
//el("meta", { name: "twitter:image", content: "" }),
|
||||
el("meta", { name: "twitter:image", content: homepage + "/assets/logo.svg" }),
|
||||
el("meta", { name: "twitter:creator", content: "@jaandrle" }),
|
||||
);
|
||||
}
|
||||
@ -62,7 +244,7 @@ function metaFacebook({ name, description, homepage }){
|
||||
el("meta", { name: "og:url", content: homepage }),
|
||||
el("meta", { name: "og:title", content: name }),
|
||||
el("meta", { name: "og:description", content: description }),
|
||||
//el("meta", { name: "og:image", content: "" }),
|
||||
el("meta", { name: "og:image", content: homepage + "/assets/logo.svg" }),
|
||||
el("meta", { name: "og:creator", content: "@jaandrle" }),
|
||||
);
|
||||
}
|
||||
|
@ -7,9 +7,24 @@ import { prevNext } from "../components/pageUtils.html.js";
|
||||
/** @param {Pick<import("../types.d.ts").PageAttrs, "pkg" | "info">} attrs */
|
||||
export function simplePage({ pkg, info }){
|
||||
return simulateSlots(el().append(
|
||||
// Skip link for keyboard navigation
|
||||
el("a", {
|
||||
href: "#main-content",
|
||||
className: "skip-link",
|
||||
textContent: "Skip to main content"
|
||||
}),
|
||||
|
||||
// Header with site information
|
||||
el(header, { info, pkg }),
|
||||
el("main").append(
|
||||
|
||||
// Main content area
|
||||
el("main", { id: "main-content", role: "main" }).append(
|
||||
el("h2", { textContent: info.fullTitle || info.title }),
|
||||
|
||||
// Main content from child elements
|
||||
el("slot"),
|
||||
|
||||
// Navigation between pages
|
||||
el(prevNext, info)
|
||||
)
|
||||
));
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { T, t } from "./utils/index.js";
|
||||
export const info= {
|
||||
title: t`Elements`,
|
||||
description: t`Basic concepts of elements modifications and creations.`,
|
||||
fullTitle: t`Declarative DOM Element Creation`,
|
||||
description: t`Building user interfaces with declarative DOM element creation.`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
@ -48,107 +49,154 @@ const references= {
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("h2", t`Native JavaScript DOM elements creations`),
|
||||
el("p", t`
|
||||
Let’s go through all patterns we would like to use and what needs to be improved for better experience.
|
||||
el("p").append(...T`
|
||||
Building user interfaces in JavaScript often involves creating and manipulating DOM elements.
|
||||
DDE provides a simple yet powerful approach to element creation that is declarative, chainable,
|
||||
and maintains a clean syntax close to HTML structure.
|
||||
`),
|
||||
el("div", { class: "callout" }).append(
|
||||
el("h4", t`DDE Elements: Key Benefits`),
|
||||
el("ul").append(
|
||||
el("li", t`Declarative element creation with intuitive property assignment`),
|
||||
el("li", t`Chainable methods for natural DOM tree construction`),
|
||||
el("li", t`Simplified component patterns for code reuse`),
|
||||
el("li", t`Normalized property/attribute handling across browsers`),
|
||||
el("li", t`Smart element return values for cleaner code flow`)
|
||||
)
|
||||
),
|
||||
|
||||
el(code, { src: fileURL("./components/examples/elements/intro.js"), page_id }),
|
||||
|
||||
el(h3, t`Creating element(s) (with custom attributes)`),
|
||||
el(h3, t`Creating Elements: Native vs DDE`),
|
||||
el("p").append(...T`
|
||||
You can create a native DOM element by using the ${el("a", references.mdn_create).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", references.mdn_idl).append( el("abbr", { textContent: "IDL", title: "Interface Description Language" }))}
|
||||
also known as a JavaScript property.
|
||||
In standard JavaScript, you create DOM elements using the
|
||||
${el("a", references.mdn_create).append(el("code", "document.createElement()"))} method
|
||||
and then set properties individually or with Object.assign():
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/elements/nativeCreateElement.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
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: fileURL("./components/examples/elements/dekaCreateElement.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
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(...T`
|
||||
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
|
||||
all available IDLs for example for paragraphs, see ${el("a", { textContent: "HTMLParagraphElement",
|
||||
...references.mdn_p })}. Moreover, the ${el("code", "assign")} provides a way to sets declaratively
|
||||
some convenient properties:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li").append(...T`
|
||||
It is possible to sets ${el("code", "data-*")}/${el("code", "aria-*")} attributes using object notation.
|
||||
`),
|
||||
el("li").append(...T`
|
||||
In opposite, it is also possible to sets ${el("code", "data-*")}/${el("code", "aria-*")} attribute
|
||||
using camelCase notation.
|
||||
`),
|
||||
el("li").append(...T`You can use string or object as a value for ${el("code", "style")} property.`),
|
||||
el("li").append(...T`
|
||||
${el("code", "className")} (IDL – preffered)/${el("code", "class")} are ways to add CSS classes
|
||||
to the element. You can use string (similarly to ${el("code", "class=\"…\"")} syntax in HTML).
|
||||
`),
|
||||
el("li").append(...T`
|
||||
Use ${el("code", "classList")} to toggle specific classes. This will be handy later when
|
||||
the reactivity via signals is beeing introduced.
|
||||
`),
|
||||
el("li").append(...T`
|
||||
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(...T`For example, natievly the element’s ${el("code", "id")}
|
||||
is removed by setting the IDL to an empty string.`)}
|
||||
`),
|
||||
el("li").append(...T`
|
||||
You can use ${el("code", "=")} or ${el("code", ".")} to force processing given key as attribute/property
|
||||
of the element.
|
||||
`)
|
||||
el("div", { class: "illustration" }).append(
|
||||
el("div", { class: "comparison" }).append(
|
||||
el("div").append(
|
||||
el("h5", t`Native DOM API`),
|
||||
el(code, { src: fileURL("./components/examples/elements/native-dom-create.js"), page_id })
|
||||
),
|
||||
el("div").append(
|
||||
el("h5", t`DDE Approach`),
|
||||
el(code, { src: fileURL("./components/examples/elements/dde-dom-create.js"), page_id })
|
||||
)
|
||||
)
|
||||
),
|
||||
el("p").append(...T`
|
||||
For processing, the ${el("code", "assign")} internally uses ${el("code", "assignAttribute")} and
|
||||
${el("code", "classListDeclarative")}.
|
||||
The ${el("code", "el")} function provides a simple wrapper around ${el("code", "document.createElement")}
|
||||
with enhanced property assignment.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/elements/dekaCreateElement.js"), page_id }),
|
||||
|
||||
el(h3, t`Advanced Property Assignment`),
|
||||
el("p").append(...T`
|
||||
The ${el("code", "assign")} function is the heart of DDE's element property handling. It is internally used
|
||||
to assign properties using the ${el("code", "el")} function. ${el("code", "assign")} provides intelligent
|
||||
assignment of both properties (IDL) and attributes:
|
||||
`),
|
||||
el("div", { class: "function-table" }).append(
|
||||
el("dl").append(
|
||||
el("dt", t`Property vs Attribute Priority`),
|
||||
el("dd", t`Prefers IDL properties, falls back to setAttribute() when no writable property exists`),
|
||||
|
||||
el("dt", t`Data and ARIA Attributes`),
|
||||
el("dd", t`Both dataset.* and data-* syntaxes supported (same for ARIA)`),
|
||||
|
||||
el("dt", t`Style Handling`),
|
||||
el("dd", t`Accepts string or object notation for style property`),
|
||||
|
||||
el("dt", t`Class Management`),
|
||||
el("dd", t`Works with className, class, or classList object for toggling classes`),
|
||||
|
||||
el("dt", t`Force Modes`),
|
||||
el("dd", t`Use = prefix to force attribute mode, . prefix to force property mode`),
|
||||
|
||||
el("dt", t`Attribute Removal`),
|
||||
el("dd", t`Pass undefined to remove a property or attribute`)
|
||||
)
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/elements/dekaAssign.js"), page_id }),
|
||||
|
||||
el(h3, t`Native JavaScript templating`),
|
||||
el("p", t`By default, the native JS has no good way to define HTML template using DOM API:`),
|
||||
el(example, { src: fileURL("./components/examples/elements/nativeAppend.js"), page_id }),
|
||||
el("div", { class: "note" }).append(
|
||||
el("p").append(...T`
|
||||
You can explore standard HTML element properties in the MDN documentation for
|
||||
${el("a", { textContent: "HTMLElement", ...references.mdn_el })} (base class)
|
||||
and specific element interfaces like ${el("a", { textContent: "HTMLParagraphElement", ...references.mdn_p })}.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`Building DOM Trees with Chainable Methods`),
|
||||
el("p").append(...T`
|
||||
This library therefore overwrites the ${el("code", "append")} method of created elements to always return
|
||||
parent element.
|
||||
One of the most powerful features of DDE is its approach to building element trees.
|
||||
Unlike the native DOM API which doesn't return the parent after appendChild(), DDE's
|
||||
append() always returns the parent element:
|
||||
`),
|
||||
el("div", { class: "illustration" }).append(
|
||||
el("div", { class: "comparison" }).append(
|
||||
el("div", { class: "bad-practice" }).append(
|
||||
el("h5", t`❌ Native DOM API`),
|
||||
el(code, { src: fileURL("./components/examples/elements/native-dom-tree.js"), page_id })
|
||||
),
|
||||
el("div", { class: "good-practice" }).append(
|
||||
el("h5", t`✅ DDE Approach`),
|
||||
el(code, { src: fileURL("./components/examples/elements/dde-dom-tree.js"), page_id })
|
||||
)
|
||||
)
|
||||
),
|
||||
el("p").append(...T`
|
||||
This chainable pattern is much cleaner and easier to follow, especially for deeply nested elements.
|
||||
It also makes it simple to add multiple children to a parent element in a single fluent expression.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/elements/dekaAppend.js"), page_id }),
|
||||
|
||||
|
||||
el(h3, t`Basic (state-less) components`),
|
||||
el(h3, t`Using Components to Build UI Fragments`),
|
||||
el("p").append(...T`
|
||||
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.
|
||||
The ${el("code", "el")} function is overloaded to support both tag names and function components.
|
||||
This lets you refactor complex UI trees into reusable pieces:
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/elements/dekaBasicComponent.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
As you can see, in case of state-less/basic components there is no difference between calling component
|
||||
function directly or using ${el("code", "el")} function.
|
||||
`),
|
||||
el("p", { className: "notice" }).append(...T`
|
||||
It is nice to use similar naming convention as native DOM API. This allows us to use
|
||||
${el("a", { textContent: t`the destructuring assignment syntax`, ...references.mdn_destruct })} and keep
|
||||
track of the native API (things are best remembered through regular use).
|
||||
Component functions receive the properties object as their first argument, just like regular elements.
|
||||
This makes it easy to pass data down to components and create reusable UI fragments.
|
||||
`),
|
||||
el("div", { class: "tip" }).append(
|
||||
el("p").append(...T`
|
||||
It's helpful to use naming conventions similar to native DOM elements for your components.
|
||||
This allows you to use ${el("a", { textContent: "destructuring assignment", ...references.mdn_destruct })}
|
||||
and keeps your code consistent with the DOM API.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`Creating non-HTML elements`),
|
||||
el(h3, t`Working with SVG and Other Namespaces`),
|
||||
el("p").append(...T`
|
||||
Similarly to the native DOM API (${el("a", references.mdn_ns).append(el("code", "document.createElementNS"))})
|
||||
for non-HTML elements we need to tell JavaScript which kind of the element to create. We can use
|
||||
the ${el("code", "elNS")} function:
|
||||
For non-HTML elements like SVG, MathML, or custom namespaces, DDE provides the ${el("code", "elNS")} function
|
||||
which corresponds to the native ${el("a", references.mdn_ns).append(el("code", "document.createElementNS"))}:
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/elements/dekaElNS.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
This function returns a namespace-specific element creator, allowing you to work with any element type
|
||||
using the same consistent interface.
|
||||
`),
|
||||
|
||||
el(h3, t`Best Practices for Declarative DOM Creation`),
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Use component functions for reusable UI fragments:")} Extract common UI patterns
|
||||
into reusable functions that return elements.
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Leverage destructuring for cleaner component code:")} Use
|
||||
${el("a", { textContent: "destructuring", ...references.mdn_destruct })} to extract properties
|
||||
from the props object for cleaner component code.
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Leverage chainable methods for better performance:")} Use chainable methods like
|
||||
${el("code", ".append()")} to build complex DOM trees for better performance and cleaner code.
|
||||
`),
|
||||
),
|
||||
|
||||
el(mnemonic)
|
||||
);
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { T, t } from "./utils/index.js";
|
||||
export const info= {
|
||||
title: t`Events and Addons`,
|
||||
description: t`Using not only events in UI declaratively.`,
|
||||
fullTitle: t`Declarative Event Handling and Addons`,
|
||||
description: t`Using events and addons for declarative UI interactions.`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
@ -15,7 +16,7 @@ const fileURL= url=> new URL(url, import.meta.url);
|
||||
const references= {
|
||||
/** element.addEventListener() */
|
||||
mdn_listen: {
|
||||
title: t`MDN documentation page for elemetn.addEventListener`,
|
||||
title: t`MDN documentation page for element.addEventListener`,
|
||||
href: "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener",
|
||||
},
|
||||
/** AbortSignal+element.addEventListener */
|
||||
@ -45,109 +46,197 @@ const references= {
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("h2", t`Listenning to the native DOM events and other Addons`),
|
||||
el("p").append(...T`
|
||||
We quickly introduce helper to listening to the native DOM events. And library syntax/pattern so-called
|
||||
${el("em", t`Addon`)} to incorporate not only this in UI templates declaratively.
|
||||
Events are at the core of interactive web applications. DDE provides a clean, declarative approach to
|
||||
handling DOM events and extends this pattern with a powerful Addon system to incorporate additional
|
||||
functionalities into your UI templates.
|
||||
`),
|
||||
el("div", { className: "callout" }).append(
|
||||
el("h4", t`Why DDE's Event System and Addons Matters`),
|
||||
el("ul").append(
|
||||
el("li", t`Integrate event handling directly in element declarations`),
|
||||
el("li", t`Leverage lifecycle events for better component design`),
|
||||
el("li", t`Clean up listeners automatically with abort signals`),
|
||||
el("li", t`Extend elements with custom behaviors using Addons`),
|
||||
el("li", t`Maintain clean, readable code with consistent patterns`)
|
||||
)
|
||||
),
|
||||
|
||||
el(code, { src: fileURL("./components/examples/events/intro.js"), page_id }),
|
||||
|
||||
el(h3, t`Events and listenners`),
|
||||
el(h3, t`Events and Listeners: Two Approaches`),
|
||||
el("p").append(...T`
|
||||
In JavaScript you can listen to the native DOM events of the given element by using
|
||||
${el("a", references.mdn_listen).append( el("code", "element.addEventListener(type, listener, options)") )}.
|
||||
The library provides an alternative (${el("code", "on")}) accepting the differen order of the arguments:
|
||||
In JavaScript you can listen to native DOM events using
|
||||
${el("a", references.mdn_listen).append(el("code", "element.addEventListener(type, listener, options)"))}.
|
||||
DDE provides an alternative approach with arguments ordered differently to better fit its declarative style:
|
||||
`),
|
||||
el("div", { className: "illustration" }).append(
|
||||
el("div", { className: "tabs" }).append(
|
||||
el("div", { className: "tab" }).append(
|
||||
el("h5", t`Native DOM API`),
|
||||
el(code, { content: `element.addEventListener('click', callback, options);`, page_id })
|
||||
),
|
||||
el("div", { className: "tab" }).append(
|
||||
el("h5", t`DDE Approach`),
|
||||
el(code, { content: `on('click', callback, options)(element);`, page_id })
|
||||
)
|
||||
)
|
||||
),
|
||||
el("p").append(...T`
|
||||
The main benefit of DDE's approach is that it works as an Addon, making it easy to integrate
|
||||
directly into element declarations.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/events/compare.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
…this is actually one of the two differences. The another one is that ${el("code", "on")} accepts only
|
||||
object as the ${el("code", "options")} (but it is still optional).
|
||||
`),
|
||||
el("p", { className: "notice" }).append(...T`
|
||||
The other difference is that there is ${el("strong", "no")} ${el("code", "off")} function. You can remove
|
||||
listener declaratively using ${el("a", { textContent: "AbortSignal", ...references.mdn_abortListener })}:
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/events/abortSignal.js"), page_id }),
|
||||
el("div", { className: "notice" }).append(
|
||||
el("p", t`So, there are (typically) three ways to handle events. You can use:`),
|
||||
el("ul").append(
|
||||
el("li").append( el("code", `el("button", { textContent: "click me", "=onclick": "console.log(event)" })`)),
|
||||
el("li").append( el("code", `el("button", { textContent: "click me", onclick: console.log })`)),
|
||||
el("li").append( el("code", `el("button", { textContent: "click me" }, on("click", console.log))`))
|
||||
),
|
||||
|
||||
el(h3, t`Removing Event Listeners`),
|
||||
el("div", { className: "note" }).append(
|
||||
el("p").append(...T`
|
||||
In the first example we force to use HTML attribute (it corresponds to
|
||||
${el("code", `<button onclick="console.log(event)">click me</button>`)}). ${el("em", t`Side note:
|
||||
this can be useful in case of SSR.`)} To study difference, you can read a nice summary here:
|
||||
${el("a", { textContent: "GIST @WebReflection/web_events.md", ...references.web_events })}.
|
||||
Unlike the native addEventListener/removeEventListener pattern, DDE uses the ${el("a", {
|
||||
textContent: "AbortSignal", ...references.mdn_abortListener })} for declarative approach for removal:
|
||||
`)
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/events/abortSignal.js"), page_id }),
|
||||
|
||||
el(h3, t`Addons`),
|
||||
el(h3, t`Three Ways to Handle Events`),
|
||||
el("div", { className: "tabs" }).append(
|
||||
el("div", { className: "tab", "data-tab": "html-attr" }).append(
|
||||
el("h4", t`HTML Attribute Style`),
|
||||
el(code, { src: fileURL("./components/examples/events/attribute-event.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
Forces usage as an HTML attribute. Corresponds to
|
||||
${el("code", `<button onclick="console.log(event)">click me</button>`)}. This can be particularly
|
||||
useful for SSR scenarios.
|
||||
`)
|
||||
),
|
||||
el("div", { className: "tab", "data-tab": "property" }).append(
|
||||
el("h4", t`Property Assignment`),
|
||||
el(code, { src: fileURL("./components/examples/events/property-event.js"), page_id }),
|
||||
el("p", t`Assigns the event handler directly to the element's property.`)
|
||||
),
|
||||
el("div", { className: "tab", "data-tab": "addon" }).append(
|
||||
el("h4", t`Addon Approach`),
|
||||
el(code, { src: fileURL("./components/examples/events/chain-event.js"), page_id }),
|
||||
el("p", t`Uses the addon pattern, see above.`)
|
||||
)
|
||||
),
|
||||
el("p").append(...T`
|
||||
From practical point of view, ${el("em", t`Addons`)} are just functions that accept any HTML element as
|
||||
their first parameter. You can see that the ${el("code", "on(…)")} fullfills this requirement.
|
||||
For a deeper comparison of these approaches, see
|
||||
${el("a", { textContent: "WebReflection's detailed analysis", ...references.web_events })}.
|
||||
`),
|
||||
|
||||
el(h3, t`Understanding Addons`),
|
||||
el("p").append(...T`
|
||||
You can use Addons as ≥3rd argument of ${el("code", "el")} function. This way is possible to extends your
|
||||
templates by additional (3rd party) functionalities. But for now mainly, you can add events listeners:
|
||||
Addons are a powerful pattern in DDE that extends beyond just event handling.
|
||||
An Addon is any function that accepts an HTML element as its first parameter.
|
||||
`),
|
||||
el("div", { className: "callout" }).append(
|
||||
el("h4", t`What Can Addons Do?`),
|
||||
el("ul").append(
|
||||
el("li", t`Add event listeners to elements`),
|
||||
el("li", t`Set up lifecycle behaviors`),
|
||||
el("li", t`Integrate third-party libraries`),
|
||||
el("li", t`Create reusable element behaviors`),
|
||||
el("li", t`Capture element references`)
|
||||
)
|
||||
),
|
||||
el("p").append(...T`
|
||||
You can use Addons as ≥3rd argument of the ${el("code", "el")} function, making it possible to
|
||||
extend your templates with additional functionality:
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/events/templateWithListeners.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
As the example shows, you can also provide types in JSDoc+TypeScript by using global type
|
||||
${el("code", "ddeElementAddon")}. Also notice, you can use Addons to get element reference.
|
||||
As the example shows, you can provide types in JSDoc+TypeScript using the global type
|
||||
${el("code", "ddeElementAddon")}. Notice how Addons can also be used to get element references.
|
||||
`),
|
||||
el(h3, t`Life-cycle events`),
|
||||
|
||||
el(h3, t`Lifecycle Events`),
|
||||
el("p").append(...T`
|
||||
Addons are called immediately when the element is created, even it is not connected to live DOM yet.
|
||||
Therefore, you can understand the Addon to be “oncreate” event.
|
||||
Addons are called immediately when an element is created, even before it's connected to the live DOM.
|
||||
You can think of an Addon as an "oncreate" event handler.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
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")}.
|
||||
DDE provides three additional lifecycle events that correspond to custom element lifecycle callbacks:
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/events/live-cycle.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
For Custom elements, we will later introduce a way to replace ${el("code", "*Callback")} syntax with
|
||||
${el("code", "dde:*")} events. The ${el("code", "on.*")} functions then listen to the appropriate
|
||||
Custom Elements events (see ${el("a", { textContent: t`Custom element lifecycle callbacks | MDN`,
|
||||
...references.mdn_customElement })}).
|
||||
`),
|
||||
el("p").append(...T`
|
||||
But, in case of regular elemnets the ${el("a", references.mdn_mutation).append(el("code",
|
||||
"MutationObserver"), " | MDN")} is internaly used to track these events. Therefore, there are some
|
||||
drawbacks:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li").append(...T`
|
||||
To proper listener registration, you need to use ${el("code", "on.*")} not \`on("dde:*", …)\`!
|
||||
`),
|
||||
el("li").append(...T`
|
||||
Use sparingly! Internally, library must loop of all registered events and fires event properly.
|
||||
${el("strong", t`It is good practice to use the fact that if an element is removed, its children are
|
||||
also removed!`)} In this spirit, we will introduce later the ${el("strong", t`host`)} syntax to
|
||||
register, clean up procedures when the component is removed from the app.
|
||||
`),
|
||||
el("div", { className: "function-table" }).append(
|
||||
el("dl").append(
|
||||
el("dt", t`on.connected(callback)`),
|
||||
el("dd", t`Fires when the element is added to the DOM`),
|
||||
|
||||
el("dt", t`on.disconnected(callback)`),
|
||||
el("dd", t`Fires when the element is removed from the DOM`),
|
||||
|
||||
el("dt", t`on.attributeChanged(callback, attributeName)`),
|
||||
el("dd", t`Fires when the specified attribute changes`)
|
||||
)
|
||||
),
|
||||
el("p").append(...T`
|
||||
To provide intuitive behaviour, similar also to how the life-cycle events works in other
|
||||
frameworks/libraries, deka-dom-el library ensures that ${el("code", "on.connected")} and
|
||||
${el("code", "on.disconnected")} are called only once and only when the element, is (dis)connected to
|
||||
live DOM. The solution is inspired by ${el("a", { textContent: "Vue", ...references.vue_fix })}. For using
|
||||
native behaviour re-(dis)connecting element, use:
|
||||
`),
|
||||
el("ul").append(
|
||||
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(example, { src: fileURL("./components/examples/events/live-cycle.js"), page_id }),
|
||||
|
||||
el("div", { className: "note" }).append(
|
||||
el("p").append(...T`
|
||||
For regular elements (non-custom elements), DDE uses
|
||||
${el("a", references.mdn_mutation).append(el("code", "MutationObserver"), " | MDN")}
|
||||
internally to track lifecycle events.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`Final notes`),
|
||||
el("p", t`The library also provides a method to dispatch the events.`),
|
||||
el("div", { className: "warning" }).append(
|
||||
el("ul").append(
|
||||
el("li").append(...T`
|
||||
Always use ${el("code", "on.*")} functions, not ${el("code", "on('dde:*', ...)")}, for proper registration
|
||||
`),
|
||||
el("li").append(...T`
|
||||
Use lifecycle events sparingly, as they require internal tracking
|
||||
`),
|
||||
el("li").append(...T`
|
||||
Leverage parent-child relationships: when a parent is removed, all children are also removed
|
||||
`),
|
||||
el("li").append(...T`
|
||||
…see section later in documentation regarding hosts elements
|
||||
`),
|
||||
el("li").append(...T`
|
||||
DDE ensures that connected/disconnected events fire only once for better predictability
|
||||
`)
|
||||
)
|
||||
),
|
||||
|
||||
el(h3, t`Dispatching Custom Events`),
|
||||
el("p").append(...T`
|
||||
This makes it easy to implement component communication through events,
|
||||
following standard web platform patterns. The curried approach allows for easy reuse
|
||||
of event dispatchers throughout your application.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/events/compareDispatch.js"), page_id }),
|
||||
|
||||
el(h3, t`Best Practices`),
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Clean up listeners")}: Use AbortSignal to prevent memory leaks
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Leverage lifecycle events")}: For component setup and teardown
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Delegate when possible")}: Add listeners to container elements when handling many similar elements
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Maintain consistency")}: Choose one event binding approach and stick with it
|
||||
`)
|
||||
),
|
||||
|
||||
el("div", { className: "troubleshooting" }).append(
|
||||
el("h4", t`Common Event Pitfalls`),
|
||||
el("dl").append(
|
||||
el("dt", t`Event listeners not working`),
|
||||
el("dd", t`Ensure element is in the DOM before expecting events to fire`),
|
||||
|
||||
el("dt", t`Memory leaks`),
|
||||
el("dd", t`Use AbortController to clean up listeners when elements are removed`),
|
||||
|
||||
el("dt", t`Lifecycle events firing unexpectedly`),
|
||||
el("dd", t`Remember that on.connected and on.disconnected events only fire once per connection state`)
|
||||
)
|
||||
),
|
||||
|
||||
el(mnemonic)
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { T, t } from "./utils/index.js";
|
||||
export const info= {
|
||||
title: t`Signals and reactivity`,
|
||||
description: t`Handling reactivity in UI via signals.`,
|
||||
title: t`Signals and Reactivity`,
|
||||
fullTitle: t`Building Reactive UIs with Signals`,
|
||||
description: t`Managing reactive UI state with signals.`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
@ -43,53 +44,124 @@ const references= {
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("h2", t`Using signals to manage reactivity`),
|
||||
el("p").append(...T`
|
||||
How a program responds to variable data or user interactions is one of the fundamental problems of
|
||||
programming. If we desire to solve the issue in a declarative manner, signals may be a viable approach.
|
||||
Signals provide a simple yet powerful way to create reactive applications with DDE. They handle the
|
||||
fundamental challenge of keeping your UI in sync with changing data in a declarative, efficient way.
|
||||
`),
|
||||
el("div", { class: "callout" }).append(
|
||||
el("h4", t`What Makes Signals Special?`),
|
||||
el("ul").append(
|
||||
el("li", t`Fine-grained reactivity without complex state management`),
|
||||
el("li", t`Automatic UI updates when data changes`),
|
||||
el("li", t`Clean separation between data, logic, and UI`),
|
||||
el("li", t`Small runtime with minimal overhead`),
|
||||
el("li").append(...T`${el("strong", "In future")} no dependencies or framework lock-in`)
|
||||
)
|
||||
),
|
||||
el(code, { src: fileURL("./components/examples/signals/intro.js"), page_id }),
|
||||
|
||||
el(h3, t`Introducing signals`),
|
||||
el(h3, t`The 3-Part Structure of Signals`),
|
||||
el("p").append(...T`
|
||||
Let’s re-introduce
|
||||
${el("a", { textContent: t`3PS principle`, href: "./#h-event-driven-programming--parts-separation--ps" })}.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
Using signals, we split program logic into the three parts. Firstly (α), we create a variable (constant)
|
||||
representing reactive value. Somewhere later, we can register (β) a logic reacting to the signal value
|
||||
changes. Similarly, in a remaining part (γ), we can update the signal value.
|
||||
Signals organize your code into three distinct parts, following the
|
||||
${el("a", { textContent: t`3PS principle`, href: "./#h-3ps" })}:
|
||||
`),
|
||||
el("div", { class: "signal-diagram" }).append(
|
||||
el("div", { class: "signal-part" }).append(
|
||||
el("h4", t`PART 1: Create Signal`),
|
||||
el(code, { content: "const count = S(0);", page_id }),
|
||||
el("p", t`Define a reactive value that can be observed and changed`)
|
||||
),
|
||||
el("div", { class: "signal-part" }).append(
|
||||
el("h4", t`PART 2: React to Changes`),
|
||||
el(code, { content: "S.on(count, value => updateUI(value));", page_id }),
|
||||
el("p", t`Subscribe to signal changes with callbacks or effects`)
|
||||
),
|
||||
el("div", { class: "signal-part" }).append(
|
||||
el("h4", t`PART 3: Update Signal`),
|
||||
el(code, { content: "count.set(count.get() + 1);", page_id }),
|
||||
el("p", t`Modify the signal value, which automatically triggers updates`)
|
||||
)
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/signals/signals.js"), page_id }),
|
||||
|
||||
el("div", { class: "note" }).append(
|
||||
el("p").append(...T`
|
||||
Signals implement the ${el("a", { textContent: t`Publish–subscribe pattern`, ...references.wiki_pubsub })},
|
||||
a form of ${el("a", { textContent: t`Event-driven programming`, ...references.wiki_event_driven })}.
|
||||
This architecture allows different parts of your application to stay synchronized through a shared signal,
|
||||
without direct dependencies on each other. Compare for example with ${el("a", { textContent:
|
||||
t`fpubsub library`, ...references.fpubsub })}.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`Signal Essentials: Core API`),
|
||||
el("div", { class: "function-table" }).append(
|
||||
el("dl").append(
|
||||
el("dt", t`Creating a Signal`),
|
||||
el("dd", t`S(initialValue) → creates a signal with the given value`),
|
||||
|
||||
el("dt", t`Reading a Signal`),
|
||||
el("dd", t`signal.get() → returns the current value`),
|
||||
|
||||
el("dt", t`Writing to a Signal`),
|
||||
el("dd", t`signal.set(newValue) → updates the value and notifies subscribers`),
|
||||
|
||||
el("dt", t`Subscribing to Changes`),
|
||||
el("dd", t`S.on(signal, callback) → runs callback whenever signal changes`),
|
||||
|
||||
el("dt", t`Unsubscribing`),
|
||||
el("dd").append(...T`S.on(signal, callback, { signal: abortController.signal }) → Similarly to the
|
||||
${el("code", "on")} function to register DOM events listener.`)
|
||||
)
|
||||
),
|
||||
el("p").append(...T`
|
||||
All this is just an example of
|
||||
${el("a", { textContent: t`Event-driven programming`, ...references.wiki_event_driven })} and
|
||||
${el("a", { textContent: t`Publish–subscribe pattern`, ...references.wiki_pubsub })} (compare for example
|
||||
with ${el("a", { textContent: t`fpubsub library`, ...references.fpubsub })}). All three parts can be in
|
||||
some manner independent and still connected to the same reactive entity.
|
||||
Signals can be created with any type of value, but they work best with
|
||||
${el("a", { textContent: t`primitive types`, ...references.mdn_primitive })} like strings, numbers, and booleans.
|
||||
For complex data types like objects and arrays, you'll want to use Actions (covered below).
|
||||
`),
|
||||
|
||||
el(h3, t`Derived Signals: Computed Values`),
|
||||
el("p").append(...T`
|
||||
Signals are implemented in the library as functions. To see current value of signal, just call it without
|
||||
any arguments ${el("code", "console.log(signal())")}. To update the signal value, pass any argument
|
||||
${el("code", `signal('${t`a new value`}')`)}. For listenning the signal value changes, use
|
||||
${el("code", "S.on(signal, console.log)")}.
|
||||
Computed values (also called derived signals) automatically update when their dependencies change.
|
||||
Create them by passing a function to S():
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/signals/derived.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
Similarly to the ${el("code", "on")} function to register DOM events listener. You can use
|
||||
${el("code", "AbortController")}/${el("code", "AbortSignal")} to ${el("em", "off")}/stop listenning. In
|
||||
example, you also found the way for representing “live” piece of code computation pattern (derived signal):
|
||||
Derived signals are read-only - you can't call .set() on them. Their value is always computed
|
||||
from their dependencies. They're perfect for transforming or combining data from other signals.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/signals/computations-abort.js"), page_id }),
|
||||
|
||||
el(h3, t`Signals and actions`),
|
||||
el(h3, t`Signal Actions: For Complex State`),
|
||||
el("p").append(...T`
|
||||
${el("code", `S(/* ${t`primitive`} */)`)} allows you to declare simple reactive variables, typically, around
|
||||
${el("em", t`immutable`)} ${el("a", { textContent: t`primitive types`, ...references.mdn_primitive })}.
|
||||
However, it may also be necessary to use reactive arrays, objects, or other complex reactive structures.
|
||||
When working with objects, arrays, or other complex data structures, Signal Actions provide
|
||||
a structured way to modify state while maintaining reactivity.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/signals/actions-demo.js"), page_id }),
|
||||
el("p", t`…but typical user-case is object/array (maps, sets and other mutable objects):`),
|
||||
el(example, { src: fileURL("./components/examples/signals/actions-todos.js"), page_id }),
|
||||
el("div", { class: "illustration" }).append(
|
||||
el("h4", t`Actions vs. Direct Mutation`),
|
||||
el("div", { class: "comparison" }).append(
|
||||
el("div", { class: "good-practice" }).append(
|
||||
el("h5", t`✅ With Actions`),
|
||||
el(code, { content: `const todos = S([], {
|
||||
add(text) {
|
||||
this.value.push(text);
|
||||
// Subscribers notified automatically
|
||||
}
|
||||
});
|
||||
|
||||
// Use the action
|
||||
S.action(todos, "add", "New todo");`, page_id })
|
||||
),
|
||||
el("div", { class: "bad-practice" }).append(
|
||||
el("h5", t`❌ Without Actions`),
|
||||
el(code, { content: `
|
||||
const todos = S([]);
|
||||
// Directly mutating the array
|
||||
const items = todos.get();
|
||||
items.push("New todo");
|
||||
// This WON'T trigger updates!`, page_id }))
|
||||
),
|
||||
),
|
||||
el("p").append(...T`
|
||||
In some way, you can compare it with ${el("a", { textContent: "useReducer", ...references.mdn_use_reducer })}
|
||||
hook from React. So, the ${el("code", "S(<data>, <actions>)")} pattern creates a store “machine”. We can
|
||||
@ -98,31 +170,123 @@ export function page({ pkg, info }){
|
||||
${el("code", "this.stopPropagation()")} in the method representing the given action. As it can be seen in
|
||||
examples, the “store” value is available also in the function for given action (${el("code", "this.value")}).
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/signals/actions-demo.js"), page_id }),
|
||||
|
||||
el(h3, t`Reactive DOM attributes and elements`),
|
||||
el("p", t`There are on basic level two distinc situation to mirror dynamic value into the DOM/UI`),
|
||||
el("ol").append(
|
||||
el("li", t`to change some attribute(s) of existing element(s)`),
|
||||
el("li", t`to generate elements itself dynamically – this covers conditions and loops`)
|
||||
el("p").append(...T`
|
||||
Actions provide these benefits:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", t`Encapsulate state change logic in named methods`),
|
||||
el("li", t`Guarantee notifications when state changes`),
|
||||
el("li", t`Prevent accidental direct mutations`),
|
||||
el("li", t`Act similar to reducers in other state management libraries`)
|
||||
),
|
||||
el("p").append(...T`
|
||||
Here's a more complete example of a todo list using signal actions:
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/signals/actions-todos.js"), page_id }),
|
||||
|
||||
el("div", { class: "tip" }).append(
|
||||
el("p").append(...T`
|
||||
${el("strong", "Special Action Methods")}: Signal actions can implement special lifecycle hooks:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", t`[S.symbols.onclear]() - Called when the signal is cleared. Use it to clean up resources.`),
|
||||
)
|
||||
),
|
||||
|
||||
el(h3, t`Connecting Signals to the DOM`),
|
||||
el("p").append(...T`
|
||||
Signals really shine when connected to your UI. DDE provides several ways to bind signals to DOM elements:
|
||||
`),
|
||||
|
||||
el("div", { class: "tabs" }).append(
|
||||
el("div", { class: "tab", "data-tab": "attributes" }).append(
|
||||
el("h4", t`Reactive Attributes`),
|
||||
el("p", t`Bind signal values directly to element attributes, properties, or styles:`),
|
||||
el(code, { content: `// Create a signal
|
||||
const color = S("blue");
|
||||
|
||||
// Bind it to an element's style
|
||||
el("div", {
|
||||
style: {
|
||||
color, // Updates when signal changes
|
||||
fontWeight: S(() => color.get() === "red" ? "bold" : "normal")
|
||||
}
|
||||
}, "This text changes color");
|
||||
|
||||
// Later:
|
||||
color.set("red"); // UI updates automatically`, page_id })
|
||||
),
|
||||
el("div", { class: "tab", "data-tab": "elements" }).append(
|
||||
el("h4", t`Reactive Elements`),
|
||||
el("p", t`Dynamically create or update elements based on signal values:`),
|
||||
el(code, { content: `// Create an array signal
|
||||
const items = S(["Apple", "Banana", "Cherry"]);
|
||||
|
||||
// Create a dynamic list that updates when items change
|
||||
el("ul").append(
|
||||
S.el(items, items =>
|
||||
items.map(item => el("li", item))
|
||||
)
|
||||
);
|
||||
|
||||
// Later:
|
||||
S.action(items, "push", "Dragonfruit"); // List updates automatically`, page_id })
|
||||
)
|
||||
),
|
||||
|
||||
el("p").append(...T`
|
||||
The ${el("code", "assign")} and ${el("code", "el")} functions detect signals automatically and handle binding.
|
||||
You can use special properties like ${el("code", "dataset")}, ${el("code", "ariaset")}, and
|
||||
${el("code", "classList")} for fine-grained control over specific attribute types.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/signals/dom-attrs.js"), page_id }),
|
||||
|
||||
el("p").append(...T`
|
||||
To derived attribute based on value of signal variable just use the signal as a value of the attribute
|
||||
(${el("code", "assign(element, { attribute: S('value') })")}). ${el("code", "assign")}/${el("code", "el")}
|
||||
provides ways to glue reactive attributes/classes more granularly into the DOM. Just use dedicated build-in
|
||||
attributes ${el("code", "dataset")}, ${el("code", "ariaset")} and ${el("code", "classList")}.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
For computation, you can use the “derived signal” (see above) like
|
||||
${el("code", "assign(element, { textContent: S(()=> 'Hello '+WorldSignal()) })")}. This is read-only signal
|
||||
its value is computed based on given function and updated when any signal used in the function changes.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
To represent part of the template filled dynamically based on the signal value use
|
||||
${el("code", "S.el(signal, DOMgenerator)")}. This was already used in the todo example above or see:
|
||||
${el("code", "S.el()")} is especially powerful for conditional rendering and lists:
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/signals/dom-el.js"), page_id }),
|
||||
|
||||
el(h3, t`Best Practices for Signals`),
|
||||
el("p").append(...T`
|
||||
Follow these guidelines to get the most out of signals:
|
||||
`),
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Keep signals small and focused")}: Use many small signals rather than a few large ones
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Use derived signals for computations")}: Don't recompute values in multiple places
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Clean up signal subscriptions")}: Use AbortController or scope.host() to prevent memory leaks
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Use actions for complex state")}: Don't directly mutate objects or arrays in signals
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Avoid infinite loops")}: Be careful when one signal updates another in a subscription
|
||||
`)
|
||||
),
|
||||
|
||||
el("div", { class: "troubleshooting" }).append(
|
||||
el("h4", t`Common Signal Pitfalls`),
|
||||
el("dl").append(
|
||||
el("dt", t`UI not updating when array/object changes`),
|
||||
el("dd", t`Use signal actions instead of direct mutation`),
|
||||
|
||||
el("dt", t`Infinite update loops`),
|
||||
el("dd", t`Check for circular dependencies between signals`),
|
||||
|
||||
el("dt", t`Memory leaks`),
|
||||
el("dd", t`Use AbortController or scope.host() to clean up subscriptions`),
|
||||
|
||||
el("dt", t`Multiple elements updating unnecessarily`),
|
||||
el("dd", t`Split large signals into smaller, more focused ones`)
|
||||
)
|
||||
),
|
||||
|
||||
el(mnemonic)
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { T, t } from "./utils/index.js";
|
||||
export const info= {
|
||||
title: t`Scopes and components`,
|
||||
description: t`Organizing UI into components`,
|
||||
title: t`Scopes and Components`,
|
||||
fullTitle: t`Building Maintainable UIs with Scopes and Components`,
|
||||
description: t`Organizing UI into reusable, manageable components`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
@ -28,59 +29,174 @@ const references= {
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("h2", t`Using functions as UI components`),
|
||||
el("p").append(...T`
|
||||
For state-less components we can use functions as UI components (see “Elements” page). But in real life,
|
||||
we may need to handle the component live-cycle and provide JavaScript the way to properly use
|
||||
we may need to handle the component's life-cycle and provide JavaScript the way to properly use
|
||||
the ${el("a", { textContent: t`Garbage collection`, ...references.garbage_collection })}.
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/scopes/intro.js"), page_id }),
|
||||
el("p").append(...T`The library therefore use ${el("em", t`scopes`)} to provide these functionalities.`),
|
||||
el("p").append(...T`The library therefore uses ${el("em", t`scopes`)} to provide these functionalities.`),
|
||||
|
||||
el(h3, t`Scopes and hosts`),
|
||||
el(h3, t`Understanding Host Elements and Scopes`),
|
||||
el("p").append(...T`
|
||||
The ${el("strong", "host")} is the name for the element representing the component. This is typically
|
||||
element returned by function. To get reference, you can use ${el("code", "scope.host()")} to applly addons
|
||||
The ${el("strong", "host")} is the name for the element representing the component. This is typically the
|
||||
element returned by a function. To get a reference, you can use ${el("code", "scope.host()")}. To apply addons,
|
||||
just use ${el("code", "scope.host(...<addons>)")}.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
Scopes are primarily needed when signals are used in DOM templates (with ${el("code", "el")}, ${el("code",
|
||||
"assign")}, or ${el("code", "S.el")}). They provide a way for automatically removing signal listeners
|
||||
and cleaning up unused signals when components are removed from the DOM.
|
||||
`),
|
||||
el("div", { className: "illustration" }).append(
|
||||
el("h4", t`Component Anatomy`),
|
||||
el("pre").append(el("code", `
|
||||
// 1. Component scope created
|
||||
el(MyComponent);
|
||||
|
||||
function MyComponent() {
|
||||
// 2. access the host element
|
||||
const { host } = scope;
|
||||
|
||||
// 3. Add behavior to host
|
||||
host(
|
||||
on.click(handleClick)
|
||||
);
|
||||
|
||||
// 4. Return the host element
|
||||
return el("div", {
|
||||
className: "my-component"
|
||||
}).append(
|
||||
el("h2", "Title"),
|
||||
el("p", "Content")
|
||||
);
|
||||
}
|
||||
`.trim()))
|
||||
),
|
||||
el("div", { className: "function-table" }).append(
|
||||
el("h4", t`scope.host()`),
|
||||
el("dl").append(
|
||||
el("dt", t`When called with no arguments`),
|
||||
el("dd", t`Returns a reference to the host element (the root element of your component)`),
|
||||
|
||||
el("dt", t`When called with addons/callbacks`),
|
||||
el("dd", t`Applies the addons to the host element and returns the host element`)
|
||||
)
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/scopes/scopes-and-hosts.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
To better understanding we implement function ${el("code", "elClass")} helping to create component as
|
||||
class instances.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/scopes/class-component.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
As you can see, the ${el("code", "scope.host()")} is stored temporarily and synchronously. Therefore, at
|
||||
least in the beginning of using library, it is the good practise to store ${el("code", "host")} in the root
|
||||
of your component. As it may be changed, typically when there is asynchronous code in the component.
|
||||
`),
|
||||
|
||||
el("div", { className: "tip" }).append(
|
||||
el("p").append(...T`
|
||||
${el("strong", "Best Practice:")} Always capture the host reference at the beginning of your component
|
||||
function using ${el("code", "const { host } = scope")} to avoid scope-related issues, especially with
|
||||
asynchronous code.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
If you are interested in the implementation details, see Class-Based Components section.
|
||||
`)
|
||||
),
|
||||
el(code, { src: fileURL("./components/examples/scopes/good-practise.js"), page_id }),
|
||||
|
||||
el(h3, t`Scopes, signals and cleaning magic`),
|
||||
el(h3, t`Class-Based Components`),
|
||||
el("p").append(...T`
|
||||
The ${el("code", "host")} is internally used to register the cleaning procedure, when the component
|
||||
(${el("code", "host")} element) is removed from the DOM.
|
||||
While functional components are the primary pattern in DDE, you can also create class-based components.
|
||||
For this, we implement function ${el("code", "elClass")} and use it to demonstrate implementation details
|
||||
for better understanding of the scope logic.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/scopes/class-component.js"), page_id }),
|
||||
|
||||
el(h3, t`Automatic Cleanup with Scopes`),
|
||||
el("p").append(...T`
|
||||
One of the most powerful features of scopes is automatic cleanup when components are removed from the DOM.
|
||||
This prevents memory leaks and ensures resources are properly released.
|
||||
`),
|
||||
el("div", { className: "illustration" }).append(
|
||||
el("h4", t`Lifecycle Flow`),
|
||||
el("pre").append(el("code", `
|
||||
1. Component created → scope established
|
||||
2. Component added to DOM → connected event
|
||||
3. Component interactions happen
|
||||
4. Component removed from DOM → disconnected event
|
||||
5. Automatic cleanup of:
|
||||
- Event listeners
|
||||
- Signal subscriptions
|
||||
- Custom cleanup code
|
||||
`))
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/scopes/cleaning.js"), page_id }),
|
||||
|
||||
el("div", { className: "note" }).append(
|
||||
el("p").append(...T`
|
||||
In this example, when you click "Remove", the component is removed from the DOM, and all its associated
|
||||
resources are automatically cleaned up, including the signal subscription that updates the text content.
|
||||
This happens because the library internally registers a disconnected event handler on the host element.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`Declarative vs Imperative Components`),
|
||||
el("p").append(...T`
|
||||
The text content of the paragraph is changing when the value of the signal ${el("code", "textContent")}
|
||||
is changed. Internally, there is association between ${el("code", "textContent")} and the paragraph,
|
||||
similar to using ${el("code", `S.on(textContent, /* ${t`update the paragraph`} */)`)}.
|
||||
The library DOM API and signals work best when used declaratively. It means you split your app's logic
|
||||
into three parts as introduced in ${el("a", { textContent: "Signals", ...references.signals })}.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
This listener must be removed when the component is removed from the DOM. To do it, the library assign
|
||||
internally ${el("code", `on.disconnected(/* ${t`remove the listener`} */)(host())`)} to the host element.
|
||||
`),
|
||||
el("p", { className: "notice" }).append(...T`
|
||||
The library DOM API and signals works ideally when used declaratively. It means, you split your app logic
|
||||
into three parts as it was itroduced in ${el("a", { textContent: "Signals", ...references.signals })}.
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/scopes/declarative.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
Strictly speaking, the imperative way of using the library is not prohibited. Just be careful (rather avoid)
|
||||
mixing declarative approach (using signals) and imperative manipulation of elements.
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/scopes/imperative.js"), page_id }),
|
||||
el("div", { className: "note" }).append(
|
||||
el("p").append(...T`
|
||||
Strictly speaking, the imperative way of using the library is not prohibited. Just be careful to avoid
|
||||
mixing the declarative approach (using signals) with imperative manipulation of elements.
|
||||
`)
|
||||
),
|
||||
el("div", { className: "tabs" }).append(
|
||||
el("div", { className: "tab", "data-tab": "declarative" }).append(
|
||||
el("h4", t`✅ Declarative Approach`),
|
||||
el("p", t`Define what your UI should look like based on state:`),
|
||||
el(code, { src: fileURL("./components/examples/scopes/declarative.js"), page_id })
|
||||
),
|
||||
el("div", { className: "tab", "data-tab": "imperative" }).append(
|
||||
el("h4", t`⚠️ Imperative Approach`),
|
||||
el("p", t`Manually update the DOM in response to events:`),
|
||||
el(code, { src: fileURL("./components/examples/scopes/imperative.js"), page_id })
|
||||
),
|
||||
el("div", { className: "tab", "data-tab": "mixed" }).append(
|
||||
el("h4", t`❌ Mixed Approach`),
|
||||
el("p", t`This approach should be avoided:`),
|
||||
el(code, { src: fileURL("./components/examples/scopes/mixed.js"), page_id })
|
||||
)
|
||||
),
|
||||
|
||||
el(h3, t`Best Practices for Scopes and Components`),
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Capture host early:")} Use ${el("code", "const { host } = scope")} at component start
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Define signals as constants:")} ${el("code", "const counter = S(0);")}
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Prefer declarative patterns:")} Use signals to drive UI updates rather than manual DOM manipulation
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Keep components focused:")} Each component should do one thing well
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Add explicit cleanup:")} For resources not managed by DDE, use ${el("code", "on.disconnected")}
|
||||
`)
|
||||
),
|
||||
|
||||
el("div", { className: "troubleshooting" }).append(
|
||||
el("h4", t`Common Scope Pitfalls`),
|
||||
el("dl").append(
|
||||
el("dt", t`Losing host reference in async code`),
|
||||
el("dd", t`Store host reference early with const { host } = scope`),
|
||||
|
||||
el("dt", t`Memory leaks from custom resources`),
|
||||
el("dd", t`Use host(on.disconnected(cleanup)) for manual resource cleanup`),
|
||||
|
||||
el("dt", t`Event handlers with incorrect 'this'`),
|
||||
el("dd", t`Use arrow functions or .bind() to preserve context`),
|
||||
|
||||
el("dt", t`Mixing declarative and imperative styles`),
|
||||
el("dd", t`Choose one approach and be consistent throughout a component`)
|
||||
)
|
||||
),
|
||||
|
||||
el(mnemonic)
|
||||
);
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { T, t } from "./utils/index.js";
|
||||
export const info= {
|
||||
title: t`Web Components`,
|
||||
description: t`Using custom elements in combinantion with DDE`,
|
||||
fullTitle: t`Using Web Components with DDE: Better Together`,
|
||||
description: t`Using custom elements in combination with DDE`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
@ -53,90 +54,220 @@ const references= {
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("h2", t`Using web components in combinantion with DDE`),
|
||||
el("p").append(...T`
|
||||
The DDE library allows for use within ${el("a", references.mdn_web_components).append( el("strong",
|
||||
t`Web Components`) )} for dom-tree generation. However, in order to be able to use signals (possibly
|
||||
mapping to registered ${el("a", references.mdn_observedAttributes).append( el("code", "observedAttributes")
|
||||
)}) and additional functionality is (unfortunately) required to use helpers provided by the library.
|
||||
DDE pairs powerfully with ${el("a", references.mdn_web_components).append(el("strong", t`Web Components`))}
|
||||
to create reusable, encapsulated custom elements with all the benefits of DDE's declarative DOM
|
||||
construction and reactivity system.
|
||||
`),
|
||||
el("div", { className: "callout" }).append(
|
||||
el("h4", t`Why Combine DDE with Web Components?`),
|
||||
el("ul").append(
|
||||
el("li", t`Declarative DOM creation within your components`),
|
||||
el("li", t`Reactive attribute updates through signals`),
|
||||
el("li", t`Simplified event handling with the same events API`),
|
||||
el("li", t`Clean component lifecycle management`),
|
||||
el("li", t`Improved code organization with scopes`)
|
||||
)
|
||||
),
|
||||
el(code, { src: fileURL("./components/examples/customElement/intro.js"), page_id }),
|
||||
|
||||
el(h3, t`Custom Elements Introduction`),
|
||||
el(h3, t`Getting Started: Web Components Basics`),
|
||||
el("p").append(...T`
|
||||
Web Components, specifically Custom Elements, are a set of web platform APIs that allow you to create
|
||||
new HTML tags with custom functionality encapsulated within them. This allows for the creation of reusable
|
||||
components that can be used across web applications.
|
||||
Web Components are a set of standard browser APIs that let you create custom HTML elements with
|
||||
encapsulated functionality. They consist of three main technologies:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Custom Elements:")} Create your own HTML tags with JS-defined behavior
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Shadow DOM:")} Encapsulate styles and markup within a component
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "HTML Templates:")} Define reusable markup structures
|
||||
`)
|
||||
),
|
||||
el("p").append(...T`
|
||||
To start with, let’s see how to use native Custom Elements. As starting point please read
|
||||
${el("a", references.mdn_custom_elements).append( el("strong", t`Using Custom Elements`), t` on MDN` )}.
|
||||
To sum up and for mnemonic see following code overview:
|
||||
Let's start with a basic Custom Element example without DDE to establish the foundation:
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/customElement/native-basic.js"), page_id }),
|
||||
|
||||
el("div", { className: "note" }).append(
|
||||
el("p").append(...T`
|
||||
For complete information on Web Components, see the
|
||||
${el("a", references.mdn_custom_elements).append(el("strong", t`MDN documentation`))}.
|
||||
Also, ${el("a", references.custom_elements_tips).append(el("strong", t`Handy Custom Elements Patterns`))}
|
||||
provides useful techniques for connecting attributes with properties.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`DDE Integration: Step 1 - Event Handling`),
|
||||
el("p").append(...T`
|
||||
For more advanced use of Custom Elements, the summary ${el("a", references.custom_elements_tips)
|
||||
.append( el("strong", t`Handy Custom Elements Patterns`) )} may be useful. Especially pay attention to
|
||||
linking HTML attributes and defining setters/getters, this is very helpful to use in combination with
|
||||
the library (${el("code", `el(HTMLCustomElement.tagName, { customAttribute: "${t`new-value`}" });`)}).
|
||||
`),
|
||||
el("p").append(...T`
|
||||
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` })}. To do it, the library provides function ${el("code", "customElementWithDDE")}…
|
||||
The first step in integrating DDE with Web Components is enabling DDE's event system to work with your
|
||||
Custom Elements. This is done with ${el("code", "customElementWithDDE")}, which makes your Custom Element
|
||||
compatible with DDE's event handling.
|
||||
`),
|
||||
el("div", { className: "function-table" }).append(
|
||||
el("h4", t`customElementWithDDE`),
|
||||
el("dl").append(
|
||||
el("dt", t`Purpose`),
|
||||
el("dd", t`Enables DDE's event system to work with your Custom Element`),
|
||||
el("dt", t`Usage`),
|
||||
el("dd", t`customElementWithDDE(YourElementClass)`),
|
||||
el("dt", t`Benefits`),
|
||||
el("dd", t`Allows using on.connected(), on.disconnected(), etc. with your element`)
|
||||
)
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/customElement/customElementWithDDE.js"), page_id }),
|
||||
|
||||
el("h3", t`Custom Elements with DDE`),
|
||||
el("div", { className: "tip" }).append(
|
||||
el("p").append(...T`
|
||||
${el("strong", "Key Point:")} The ${el("code", "customElementWithDDE")} function adds event dispatching
|
||||
to your Custom Element lifecycle methods, making them work seamlessly with DDE's event system.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`DDE Integration: Step 2 - Rendering Components`),
|
||||
el("p").append(...T`
|
||||
The ${el("code", "customElementWithDDE")} function is only (small) part of the inregration of the library.
|
||||
More important for coexistence is render component function as a body of the Custom Element. For that, you
|
||||
can use ${el("code", "customElementRender")} with arguments instance reference, target for connection,
|
||||
render function and optional properties (will be passed to the render function) see later…
|
||||
The next step is to use DDE's component rendering within your Custom Element. This is done with
|
||||
${el("code", "customElementRender")}, which connects your DDE component function to the Custom Element.
|
||||
`),
|
||||
el("div", { className: "function-table" }).append(
|
||||
el("h4", t`customElementRender`),
|
||||
el("dl").append(
|
||||
el("dt", t`Purpose`),
|
||||
el("dd", t`Connects a DDE component function to a Custom Element`),
|
||||
el("dt", t`Parameters`),
|
||||
el("dd").append(
|
||||
el("ol").append(
|
||||
el("li", t`Target (usually this or this.shadowRoot)`),
|
||||
el("li", t`Component function that returns a DOM tree`),
|
||||
el("li", t`Optional: Attributes transformer function (default or S.observedAttributes)`)
|
||||
)
|
||||
),
|
||||
el("dt", t`Returns`),
|
||||
el("dd", t`The rendered DOM tree`)
|
||||
)
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/customElement/dde.js"), page_id }),
|
||||
|
||||
el("div", { className: "note" }).append(
|
||||
el("p").append(...T`
|
||||
In this example, we're using Shadow DOM (${el("code", "this.attachShadow()")}) for encapsulation,
|
||||
but you can also render directly to the element with ${el("code", "customElementRender(this, ...)")}.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`Reactive Web Components with Signals`),
|
||||
el("p").append(...T`
|
||||
…as you can see, you can use components created based on the documentation previously introduced. To unlock
|
||||
full potential, use with combination ${el("code", "customElementWithDDE")} (allows to use livecycle events)
|
||||
and ${el("code", "observedAttributes")} (converts attributes to render function arguments —
|
||||
${el("em", "default")}) or ${el("code", "S.observedAttributes")} (converts attributes to signals).
|
||||
One of the most powerful features of integrating DDE with Web Components is connecting HTML attributes
|
||||
to DDE's reactive signals system. This creates truly reactive custom elements.
|
||||
`),
|
||||
el("div", { className: "tip" }).append(
|
||||
el("p").append(...T`
|
||||
${el("strong", "Two Ways to Handle Attributes:")}
|
||||
`),
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("code", "observedAttributes")} - Passes attributes as regular values (static)
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("code", "S.observedAttributes")} - Transforms attributes into signals (reactive)
|
||||
`)
|
||||
)
|
||||
),
|
||||
el("p").append(...T`
|
||||
Using ${el("code", "S.observedAttributes")} creates a reactive connection between your element's attributes
|
||||
and its internal rendering. When attributes change, your component automatically updates!
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/customElement/observedAttributes.js"), page_id }),
|
||||
|
||||
el("div", { className: "callout" }).append(
|
||||
el("h4", t`How S.observedAttributes Works`),
|
||||
el("ol").append(
|
||||
el("li", t`Takes each attribute listed in static observedAttributes`),
|
||||
el("li", t`Creates a DDE signal for each one`),
|
||||
el("li", t`Automatically updates these signals when attributes change`),
|
||||
el("li", t`Passes the signals to your component function`),
|
||||
el("li", t`Your component reacts to changes through signal subscriptions`)
|
||||
)
|
||||
),
|
||||
|
||||
el(h3, t`Shadow DOM`),
|
||||
el(h3, t`Working with Shadow DOM`),
|
||||
el("p").append(...T`
|
||||
Shadow DOM is a web platform feature that allows for the encapsulation of a component’s internal DOM tree
|
||||
from the rest of the document. This means that styles and scripts applied to the document will not affect
|
||||
the component’s internal DOM, and vice versa.
|
||||
Shadow DOM provides encapsulation for your component's styles and markup. When using DDE with Shadow DOM,
|
||||
you get the best of both worlds: encapsulation plus declarative DOM creation.
|
||||
`),
|
||||
el("div", { className: "illustration" }).append(
|
||||
el("h4", t`Shadow DOM Encapsulation`),
|
||||
el("pre").append(el("code", `
|
||||
<my-custom-element>
|
||||
┌─────────────────────────┐
|
||||
#shadow-root
|
||||
|
||||
Created with DDE:
|
||||
┌──────────────────┐
|
||||
<div>
|
||||
<h2>Title</h2>
|
||||
<p>Content</p>
|
||||
`))
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/customElement/shadowRoot.js"), page_id }),
|
||||
|
||||
el("p").append(...T`
|
||||
Regarding to ${el("code", "this.attachShadow({ mode: 'open' })")} see quick overview
|
||||
${el("a", { textContent: t`Using Shadow DOM`, ...references.mdn_shadow_dom_depth })}. An another source of
|
||||
information can be ${el("a", { textContent: t`Shadow DOM in Depth`, ...references.shadow_dom_depth })}.
|
||||
For more information on Shadow DOM, see
|
||||
${el("a", { textContent: t`Using Shadow DOM`, ...references.mdn_shadow_dom_depth })}, or the comprehensive
|
||||
${el("a", { textContent: t`Shadow DOM in Depth`, ...references.shadow_dom_depth })}.
|
||||
`),
|
||||
|
||||
el(h3, t`Working with Slots`),
|
||||
el("p").append(...T`
|
||||
Besides the encapsulation, the Shadow DOM allows for using the ${el("a", references.mdn_shadow_dom_slot).append(
|
||||
el("strong", t`<slot>`), t` element(s)`)}. You can simulate this feature using ${el("code", "simulateSlots")}:
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/customElement/simulateSlots.js"), page_id }),
|
||||
el("div", { className: "function-table" }).append(
|
||||
el("h4", t`simulateSlots`),
|
||||
el("dl").append(
|
||||
el("dt", t`Purpose`),
|
||||
el("dd", t`Provides slot functionality when you cannot/do not want to use shadow DOM`),
|
||||
el("dt", t`Parameters`),
|
||||
el("dd", t`A mapping object of slot names to DOM elements`)
|
||||
)
|
||||
),
|
||||
|
||||
el(h3, t`Best Practices for Web Components with DDE`),
|
||||
el("p").append(...T`
|
||||
To sum up:
|
||||
When combining DDE with Web Components, follow these recommendations:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
The use of shadow DOM to encapsulate the internal structure of the custom element, which affects how
|
||||
the custom element can be styled and modified using JavaScript and CSS.
|
||||
${el("strong", "Always use customElementWithDDE")} to enable event integration
|
||||
`),
|
||||
el("li").append(...T`
|
||||
The ability to access and modify the internal structure of the custom element using JavaScript, which
|
||||
is affected by the use of shadow DOM and the mode of the shadow DOM.
|
||||
${el("strong", "Prefer S.observedAttributes")} for reactive attribute connections
|
||||
`),
|
||||
el("li").append(...T`
|
||||
The use of slots to allow for the insertion of content from the parent document into the custom
|
||||
element, which is affected by the use of shadow DOM and the mode of the shadow DOM.
|
||||
${el("strong", "Create reusable component functions")} that your custom elements render
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Use scope.host()")} to clean up event listeners and subscriptions
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Add setters and getters")} for better property access to your element
|
||||
`)
|
||||
),
|
||||
|
||||
el("div", { className: "troubleshooting" }).append(
|
||||
el("h4", t`Common Issues`),
|
||||
el("dl").append(
|
||||
el("dt", t`Events not firing properly`),
|
||||
el("dd", t`Make sure you called customElementWithDDE before defining the element`),
|
||||
el("dt", t`Attributes not updating`),
|
||||
el("dd", t`Check that you've properly listed them in static observedAttributes`),
|
||||
el("dt", t`Component not rendering`),
|
||||
el("dd", t`Verify customElementRender is called in connectedCallback, not constructor`)
|
||||
)
|
||||
),
|
||||
|
||||
el(mnemonic)
|
||||
|
192
docs/p07-debugging.html.js
Normal file
192
docs/p07-debugging.html.js
Normal file
@ -0,0 +1,192 @@
|
||||
import { T, t } from "./utils/index.js";
|
||||
export const info= {
|
||||
title: t`Debugging`,
|
||||
fullTitle: t`Debugging applications with deka-dom-el`,
|
||||
description: t`Techniques for debugging applications using deka-dom-el, especially signals.`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
import { simplePage } from "./layout/simplePage.html.js";
|
||||
import { example } from "./components/example.html.js";
|
||||
import { h3 } from "./components/pageUtils.html.js";
|
||||
import { code } from "./components/code.html.js";
|
||||
/** @param {string} url */
|
||||
const fileURL= url=> new URL(url, import.meta.url);
|
||||
|
||||
/** @param {import("./types.d.ts").PageAttrs} attrs */
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("p").append(...T`
|
||||
Debugging is an essential part of application development. This guide provides techniques
|
||||
and best practices for debugging applications built with deka-dom-el, with a focus on signals.
|
||||
`),
|
||||
|
||||
el(h3, t`Debugging signals`),
|
||||
el("p").append(...T`
|
||||
Signals are reactive primitives that update the UI when their values change. When debugging signals,
|
||||
you need to track their values, understand their dependencies, and identify why updates are or aren't happening.
|
||||
`),
|
||||
|
||||
el("h4", t`Inspecting signal values`),
|
||||
el("p").append(...T`
|
||||
The simplest way to debug a signal is to log its current value by calling the get method:
|
||||
`),
|
||||
el(code, { content: `
|
||||
const signal = S(0);
|
||||
console.log('Current value:', signal.get());
|
||||
// without triggering updates
|
||||
console.log('Current value:', signal.valueOf());
|
||||
`, page_id }),
|
||||
el("p").append(...T`
|
||||
You can also monitor signal changes by adding a listener:
|
||||
`),
|
||||
el(code, {
|
||||
content:
|
||||
"// Log every time the signal changes\nS.on(signal, value => console.log('Signal changed:', value));",
|
||||
page_id }),
|
||||
|
||||
el("h4", t`Debugging derived signals`),
|
||||
el("p").append(...T`
|
||||
With derived signals (created with ${el("code", "S(() => computation))")}), debugging is a bit more complex
|
||||
because the value depends on other signals. To understand why a derived signal isn't updating correctly:
|
||||
`),
|
||||
el("ol").append(
|
||||
el("li", t`Check that all dependency signals are updating correctly`),
|
||||
el("li", t`Add logging inside the computation function to see when it runs`),
|
||||
el("li", t`Verify that the computation function actually accesses the signal values with .get()`)
|
||||
),
|
||||
el(example, { src: fileURL("./components/examples/debugging/consoleLog.js"), page_id }),
|
||||
|
||||
el(h3, t`Common signal debugging issues`),
|
||||
el("h4", t`Signal updates not triggering UI changes`),
|
||||
el("p").append(...T`
|
||||
If signal updates aren't reflected in the UI, check:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", t`That you're using signal.set() to update the value, not modifying objects/arrays directly`),
|
||||
el("li", t`For mutable objects, ensure you're using actions or making proper copies before updating`),
|
||||
el("li", t`That the signal is actually connected to the DOM element (check your S.el or attribute binding code)`)
|
||||
),
|
||||
el(code, { src: fileURL("./components/examples/debugging/mutations.js"), page_id }),
|
||||
|
||||
el("h4", t`Memory leaks with signal listeners`),
|
||||
el("p").append(...T`
|
||||
Signal listeners can cause memory leaks if not properly cleaned up. Always use AbortSignal
|
||||
to cancel listeners.
|
||||
`),
|
||||
|
||||
el("h4", t`Performance issues with frequently updating signals`),
|
||||
el("p").append(...T`
|
||||
If you notice performance issues with signals that update very frequently:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", t`Consider debouncing or throttling signal updates`),
|
||||
el("li", t`Make sure derived signals don't perform expensive calculations unnecessarily`),
|
||||
el("li", t`Keep signal computations focused and minimal`)
|
||||
),
|
||||
el(code, { src: fileURL("./components/examples/debugging/debouncing.js"), page_id }),
|
||||
|
||||
el(h3, t`Browser DevTools tips for deka-dom-el`),
|
||||
el("p").append(...T`
|
||||
When debugging in the browser, deka-dom-el provides several helpful DevTools-friendly features:
|
||||
`),
|
||||
|
||||
el("h4", t`Identifying components in the DOM`),
|
||||
el("p").append(...T`
|
||||
deka-dom-el marks components in the DOM with special comment nodes to help you identify component boundaries.
|
||||
Components created with ${el("code", "el(ComponentFunction)")} are marked with comment nodes
|
||||
${el("code", "<!--<dde:mark type=\"component\" name=\"MyComponent\" host=\"parentElement\"/>-->")} and
|
||||
includes:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", "type - Identifies the type of marker (\"component\", \"reactive\", or \"later\")"),
|
||||
el("li", "name - The name of the component function"),
|
||||
el("li", "host - Indicates whether the host is \"this\" (for DocumentFragments) or \"parentElement\""),
|
||||
),
|
||||
|
||||
el("h4", t`Finding reactive elements in the DOM`),
|
||||
el("p").append(...T`
|
||||
When using ${el("code", "S.el()")}, deka-dom-el creates reactive elements in the DOM
|
||||
that are automatically updated when signal values change. These elements are wrapped in special
|
||||
comment nodes for debugging (to be true they are also used internally, so please do not edit them by hand):
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/debugging/dom-reactive-mark.js"), page_id }),
|
||||
el("p").append(...T`
|
||||
This is particularly useful when debugging why a reactive section isn't updating as expected.
|
||||
You can inspect the elements between the comment nodes to see their current state and the
|
||||
signal connections through \`__dde_reactive\` of the host element.
|
||||
`),
|
||||
|
||||
el("h4", t`DOM inspection properties`),
|
||||
el("p").append(...T`
|
||||
Elements created with the deka-dom-el library have special properties to aid in debugging:
|
||||
`),
|
||||
el("p").append(...T`
|
||||
${el("code", "<element>.__dde_reactive")} - An array property on DOM elements that tracks signal-to-element
|
||||
relationships. This allows you to quickly identify which elements are reactive and what signals they're
|
||||
bound to. Each entry in the array contains:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", "A pair of signal and listener function: [signal, listener]"),
|
||||
el("li", "Additional context information about the element or attribute"),
|
||||
el("li", "Automatically managed by signal.el(), signal.observedAttributes(), and processReactiveAttribute()")
|
||||
),
|
||||
el("p").append(...T`
|
||||
These properties make it easier to understand the reactive structure of your application when inspecting elements.
|
||||
`),
|
||||
el(example, { src: fileURL("./components/examples/signals/debugging-dom.js"), page_id }),
|
||||
|
||||
el("h4", t`Examining signal connections`),
|
||||
el("p").append(...T`
|
||||
${el("code", "<signal>.__dde_signal")} - A Symbol property used to identify and store the internal state of
|
||||
signal objects. It contains the following information:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", "listeners: A Set of functions called when the signal value changes"),
|
||||
el("li", "actions: Custom actions that can be performed on the signal"),
|
||||
el("li", "onclear: Functions to run when the signal is cleared"),
|
||||
el("li", "host: Reference to the host element/scope"),
|
||||
el("li", "defined: Stack trace information for debugging"),
|
||||
el("li", "readonly: Boolean flag indicating if the signal is read-only")
|
||||
),
|
||||
el("p").append(...T`
|
||||
…to determine the current value of the signal, call ${el("code", "signal.valueOf()")}.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
You can inspect (host) element relationships and bindings with signals in the DevTools console using
|
||||
${el("code", "$0.__dde_reactive")} (for currently selected element). In the console you will see a list of
|
||||
${el("code", "[ [ signal, listener ], element, property ]")}, where:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", "signal — the signal triggering the changes"),
|
||||
el("li", "listener — the listener function (this is an internal function for DDE)"),
|
||||
el("li", "element — the DOM element that is bound to the signal"),
|
||||
el("li", "property — the attribute or property name which is changing based on the signal"),
|
||||
),
|
||||
el("p").append(...T`
|
||||
…the structure of \`__dde_reactive\` utilizes the browser's behavior of packing the first field,
|
||||
so you can see the element and property that changes in the console right away.
|
||||
`),
|
||||
|
||||
el("h4", t`Debugging with breakpoints`),
|
||||
el("p").append(...T`
|
||||
Effective use of breakpoints can help track signal flow:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li").append(...T`
|
||||
Set breakpoints in signal update methods to track when values change
|
||||
`),
|
||||
el("li").append(...T`
|
||||
Use conditional breakpoints to only break when specific signals change to certain values
|
||||
`),
|
||||
el("li").append(...T`
|
||||
Set breakpoints in your signal computation functions to see when derived signals recalculate
|
||||
`),
|
||||
el("li").append(...T`
|
||||
Use performance profiling to identify bottlenecks in signal updates
|
||||
`)
|
||||
),
|
||||
|
||||
);
|
||||
}
|
255
docs/p08-extensions.html.js
Normal file
255
docs/p08-extensions.html.js
Normal file
@ -0,0 +1,255 @@
|
||||
import { T, t } from "./utils/index.js";
|
||||
export const info= {
|
||||
title: t`Extensions and 3rd Party`,
|
||||
fullTitle: t`Extending deka-dom-el with Third-Party Functionalities`,
|
||||
description: t`How to extend deka-dom-el with third-party libraries and custom functionalities.`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
import { simplePage } from "./layout/simplePage.html.js";
|
||||
import { h3 } from "./components/pageUtils.html.js";
|
||||
import { code } from "./components/code.html.js";
|
||||
/** @param {string} url */
|
||||
const fileURL= url=> new URL(url, import.meta.url);
|
||||
|
||||
/** @param {import("./types.js").PageAttrs} attrs */
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("p").append(...T`
|
||||
deka-dom-el is designed with extensibility in mind. This page covers how to separate
|
||||
third-party functionalities and integrate them seamlessly with the library, focusing on
|
||||
proper resource cleanup and interoperability.
|
||||
`),
|
||||
|
||||
el(h3, t`DOM Element Extensions with Addons`),
|
||||
el("p").append(...T`
|
||||
The primary method for extending DOM elements in deka-dom-el is through the Addon pattern.
|
||||
Addons are functions that take an element and applying some functionality to it. This pattern enables a
|
||||
clean, functional approach to element enhancement.
|
||||
`),
|
||||
el("div", { className: "callout" }).append(
|
||||
el("h4", t`What are Addons?`),
|
||||
el("p").append(...T`
|
||||
Addons are simply functions with the signature: (element) => void. They:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", t`Accept a DOM element as input`),
|
||||
el("li", t`Apply some behavior, property, or attribute to the element`),
|
||||
)
|
||||
),
|
||||
el(code, { content: `
|
||||
// Basic structure of an addon
|
||||
function myAddon(config) {
|
||||
return function(element) {
|
||||
// Apply functionality to element
|
||||
element.dataset.myAddon = config.option;
|
||||
};
|
||||
}
|
||||
|
||||
// Using an addon
|
||||
el("div", { id: "example" }, myAddon({ option: "value" }));
|
||||
`.trim(), page_id }),
|
||||
|
||||
el(h3, t`Resource Cleanup with Abort Signals`),
|
||||
el("p").append(...T`
|
||||
When extending elements with functionality that uses resources like event listeners, timers,
|
||||
or external subscriptions, it's critical to clean up these resources when the element is removed
|
||||
from the DOM. deka-dom-el provides utilities for this through AbortSignal integration.
|
||||
`),
|
||||
el("div", { className: "tip" }).append(
|
||||
el("p").append(...T`
|
||||
The ${el("code", "on.disconnectedAsAbort")} utility creates an AbortSignal that automatically
|
||||
triggers when an element is disconnected from the DOM, making cleanup much easier to manage.
|
||||
`)
|
||||
),
|
||||
el(code, { content: `
|
||||
// Third-party library addon with proper cleanup
|
||||
function externalLibraryAddon(config, signal) {
|
||||
return function(element) {
|
||||
// Initialize the third-party library
|
||||
const instance = new ExternalLibrary(element, config);
|
||||
|
||||
// Set up cleanup when the element is removed
|
||||
signal.addEventListener('abort', () => {
|
||||
instance.destroy();
|
||||
});
|
||||
|
||||
return element;
|
||||
};
|
||||
}
|
||||
// dde component
|
||||
function Component(){
|
||||
const { host }= scope;
|
||||
const signal= on.disconnectedAsAbort(host);
|
||||
return el("div", null, externalLibraryAddon({ option: "value" }, signal));
|
||||
}
|
||||
`.trim(), page_id }),
|
||||
|
||||
el(h3, t`Building Library-Independent Extensions`),
|
||||
el("p").append(...T`
|
||||
When creating extensions, it's a good practice to make them as library-independent as possible.
|
||||
This approach enables better interoperability and future-proofing.
|
||||
`),
|
||||
el("div", { className: "illustration" }).append(
|
||||
el("h4", t`Library-Independent vs. Library-Dependent Extension`),
|
||||
el("div", { className: "tabs" }).append(
|
||||
el("div", { className: "tab" }).append(
|
||||
el("h5", t`✅ Library-Independent`),
|
||||
el(code, { content: `
|
||||
function enhancementElement({ signal, ...config }) {
|
||||
// do something
|
||||
return function(element) {
|
||||
// do something
|
||||
signal.addEventListener('abort', () => {
|
||||
// do cleanup
|
||||
});
|
||||
};
|
||||
}
|
||||
`.trim(), page_id })
|
||||
),
|
||||
el("div", { className: "tab" }).append(
|
||||
el("h5", t`⚠️ Library-Dependent`),
|
||||
el(code, { content: `
|
||||
// Tightly coupled to deka-dom-el
|
||||
function enhancementElement(config) {
|
||||
return function(element) {
|
||||
// do something
|
||||
on.disconnected(()=> {
|
||||
// do cleanup
|
||||
})(element);
|
||||
};
|
||||
}
|
||||
`.trim(), page_id })
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
el(h3, t`Signal Extensions and Future Compatibility`),
|
||||
el("p").append(...T`
|
||||
Unlike DOM elements, signal functionality in deka-dom-el currently lacks a standardized
|
||||
way to create library-independent extensions. This is because signals are implemented
|
||||
differently across libraries.
|
||||
`),
|
||||
el("div", { className: "note" }).append(
|
||||
el("p").append(...T`
|
||||
In the future, JavaScript may include built-in signals through the
|
||||
${el("a", { href: "https://github.com/tc39/proposal-signals", textContent: "TC39 Signals Proposal" })}.
|
||||
deka-dom-el is designed with future compatibility in mind and will hopefully support these
|
||||
native signals without breaking changes when they become available.
|
||||
`)
|
||||
),
|
||||
el("p").append(...T`
|
||||
For now, when extending signals functionality, focus on clear interfaces and isolation to make
|
||||
future migration easier.
|
||||
`),
|
||||
el(code, { content: `
|
||||
// Signal extension with clear interface
|
||||
function createEnhancedSignal(initialValue) {
|
||||
const signal = S(initialValue);
|
||||
|
||||
// Extension functionality
|
||||
const increment = () => signal.set(signal.get() + 1);
|
||||
const decrement = () => signal.set(signal.get() - 1);
|
||||
|
||||
// Return the original signal with added methods
|
||||
return Object.assign(signal, {
|
||||
increment,
|
||||
decrement
|
||||
});
|
||||
}
|
||||
|
||||
// Usage
|
||||
const counter = createEnhancedSignal(0);
|
||||
el("button")({ onclick: () => counter.increment() }, "Increment");
|
||||
el("div", S.text\`Count: \${counter}\`);
|
||||
`.trim(), page_id }),
|
||||
|
||||
el(h3, t`Using Signals Independently`),
|
||||
el("p").append(...T`
|
||||
While signals are tightly integrated with DDE's DOM elements, you can also use them independently.
|
||||
This can be useful when you need reactivity in non-UI code or want to integrate with other libraries.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
There are two ways to import signals:
|
||||
`),
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Standard import")}: ${el("code", "import { S } from \"deka-dom-el/signals\";")}
|
||||
— This automatically registers signals with DDE's DOM reactivity system
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Independent import")}: ${el("code", "import { S } from \"deka-dom-el/src/signals-lib\";")}
|
||||
— This gives you just the signal system without DOM integration
|
||||
`)
|
||||
),
|
||||
el(code, { content: `// Independent signals without DOM integration
|
||||
import { signal as S, isSignal } from "deka-dom-el/src/signals-lib";
|
||||
|
||||
// Create and use signals as usual
|
||||
const count = S(0);
|
||||
const doubled = S(() => count.get() * 2);
|
||||
|
||||
// Subscribe to changes
|
||||
S.on(count, value => console.log(value));
|
||||
|
||||
// Update signal value
|
||||
count.set(5); // Logs: 5
|
||||
console.log(doubled.get()); // 10`, page_id }),
|
||||
el("p").append(...T`
|
||||
The independent signals API includes all core functionality (${el("code", "S()")}, ${el("code", "S.on()")},
|
||||
${el("code", "S.action()")}).
|
||||
`),
|
||||
el("div", { class: "callout" }).append(
|
||||
el("h4", t`When to Use Independent Signals`),
|
||||
el("ul").append(
|
||||
el("li", t`For non-UI state management in your application`),
|
||||
el("li", t`When integrating with other libraries or frameworks`),
|
||||
el("li", t`To minimize bundle size when you don't need DOM integration`)
|
||||
)
|
||||
),
|
||||
|
||||
el(h3, t`Best Practices for Extensions`),
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Use AbortSignals for cleanup:")} Always implement proper resource cleanup with
|
||||
${el("code", "on.disconnectedAsAbort")} or similar mechanisms
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Separate core logic from library adaptation:")} Make your core functionality work
|
||||
with standard DOM APIs when possible
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Document clearly:")} Provide clear documentation on how your extension works
|
||||
and what resources it uses
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Follow the Addon pattern:")} Keep to the (element) => element signature for
|
||||
DOM element extensions
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Avoid modifying global state:")} Extensions should be self-contained and not
|
||||
affect other parts of the application
|
||||
`)
|
||||
),
|
||||
|
||||
el("div", { className: "troubleshooting" }).append(
|
||||
el("h4", t`Common Extension Pitfalls`),
|
||||
el("dl").append(
|
||||
el("dt", t`Leaking event listeners or resources`),
|
||||
el("dd", t`Always use AbortSignal-based cleanup to automatically remove listeners when elements
|
||||
are disconnected`),
|
||||
|
||||
el("dt", t`Tight coupling with library internals`),
|
||||
el("dd", t`Focus on standard DOM APIs and clean interfaces rather than depending on deka-dom-el
|
||||
implementation details`),
|
||||
|
||||
el("dt", t`Mutating element prototypes`),
|
||||
el("dd", t`Prefer compositional approaches with addons over modifying element prototypes`),
|
||||
|
||||
el("dt", t`Complex initialization in addons`),
|
||||
el("dd", t`Split complex logic into a separate initialization function that the addon can call`)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
138
docs/p09-ssr.html.js
Normal file
138
docs/p09-ssr.html.js
Normal file
@ -0,0 +1,138 @@
|
||||
import { T, t } from "./utils/index.js";
|
||||
export const info= {
|
||||
title: t`Server-Side Rendering (SSR)`,
|
||||
fullTitle: t`Server-Side Rendering with deka-dom-el`,
|
||||
description: t`Using deka-dom-el for server-side rendering with jsdom to generate static HTML.`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
import { simplePage } from "./layout/simplePage.html.js";
|
||||
import { h3 } from "./components/pageUtils.html.js";
|
||||
import { code } from "./components/code.html.js";
|
||||
/** @param {string} url */
|
||||
const fileURL= url=> new URL(url, import.meta.url);
|
||||
|
||||
/** @param {import("./types.js").PageAttrs} attrs */
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("div", { className: "warning" }).append(
|
||||
el("p").append(...T`
|
||||
This part of the documentation is primarily intended for technical enthusiasts and authors of
|
||||
3rd-party libraries. It describes an advanced feature, not a core part of the library. Most users will
|
||||
not need to implement this functionality directly in their applications. This capability will hopefully
|
||||
be covered by third-party libraries or frameworks that provide simpler SSR integration using
|
||||
deka-dom-el.
|
||||
`)
|
||||
),
|
||||
el("p").append(...T`
|
||||
deka-dom-el isn't limited to browser environments. Thanks to its flexible architecture,
|
||||
it can be used for server-side rendering (SSR) to generate static HTML files.
|
||||
This is achieved through integration with for example ${el("a", { href: "https://github.com/tmpvar/jsdom",
|
||||
textContent: "jsdom" })}, a JavaScript implementation of web standards for Node.js.
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/ssr/intro.js"), page_id }),
|
||||
|
||||
el(h3, t`Why Server-Side Rendering?`),
|
||||
el("p").append(...T`
|
||||
SSR offers several benefits:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", t`Improved SEO — Search engines can easily index fully rendered content`),
|
||||
el("li", t`Faster initial page load — Users see content immediately without waiting for JavaScript to load`),
|
||||
el("li", t`Better performance on low-powered devices — Less JavaScript processing on the client`),
|
||||
el("li", t`Content available without JavaScript — Useful for users who have disabled JavaScript`),
|
||||
el("li", t`Static site generation — Build files once, serve them many times`)
|
||||
),
|
||||
|
||||
el(h3, t`How jsdom Integration Works`),
|
||||
el("p").append(...T`
|
||||
The jsdom export in deka-dom-el provides the necessary tools to use the library in Node.js
|
||||
by integrating with jsdom. Here's what it does:
|
||||
`),
|
||||
el("ol").append(
|
||||
el("li", t`Creates a virtual DOM environment in Node.js using jsdom`),
|
||||
el("li", t`Registers DOM globals like HTMLElement, document, etc. for deka-dom-el to use`),
|
||||
el("li", t`Sets an SSR flag in the environment to enable SSR-specific behaviors`),
|
||||
el("li", t`Provides a promise queue system for managing async operations during rendering`),
|
||||
el("li", t`Handles DOM property/attribute mapping differences between browsers and jsdom`)
|
||||
),
|
||||
el(code, { src: fileURL("./components/examples/ssr/start.js"), page_id }),
|
||||
|
||||
el(h3, t`Basic SSR Example`),
|
||||
el("p").append(...T`
|
||||
Here's a simple example of how to use deka-dom-el for server-side rendering in a Node.js script:
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/ssr/basic-example.js"), page_id }),
|
||||
|
||||
el(h3, t`Building a Static Site Generator`),
|
||||
el("p").append(...T`
|
||||
You can build a complete static site generator with deka-dom-el. In fact, this documentation site
|
||||
is built using deka-dom-el for server-side rendering! Here's how the documentation build process works:
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/ssr/static-site-generator.js"), page_id }),
|
||||
|
||||
el(h3, t`Working with Async Content in SSR`),
|
||||
el("p").append(...T`
|
||||
The jsdom export includes a queue system to handle asynchronous operations during rendering.
|
||||
This is crucial for components that fetch data or perform other async tasks.
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/ssr/async-data.js"), page_id }),
|
||||
|
||||
el(h3, t`Working with Dynamic Imports for SSR`),
|
||||
el("p").append(...T`
|
||||
When structuring server-side rendering code, a crucial pattern to follow is using dynamic imports
|
||||
for both the deka-dom-el/jsdom module and your page components.
|
||||
`),
|
||||
el("p").append(...T`
|
||||
Why is this important?
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Static imports are hoisted:")} JavaScript hoists import statements to the top of the file,
|
||||
executing them before any other code
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Environment registration timing:")} The jsdom module auto-registers the DOM environment
|
||||
when imported, which must happen ${el("em", "after")} you've created your JSDOM instance and
|
||||
${el("em", "before")} you import your components using ${el("code", "import { el } from \"deka-dom-el\";")}.
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Correct initialization order:")} You need to control the exact sequence of:
|
||||
create JSDOM → register environment → import components
|
||||
`)
|
||||
),
|
||||
el("p").append(...T`
|
||||
Follow this pattern when creating server-side rendered pages:
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/ssr/pages.js"), page_id }),
|
||||
|
||||
el(h3, t`SSR Considerations and Limitations`),
|
||||
el("p").append(...T`
|
||||
When using deka-dom-el for SSR, keep these considerations in mind:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", t`Browser-specific APIs like window.localStorage are not available in jsdom by default`),
|
||||
el("li", t`Event listeners added during SSR won't be functional in the final HTML unless hydrated on the client`),
|
||||
el("li", t`Some DOM features may behave differently in jsdom compared to real browsers`),
|
||||
el("li", t`For large sites, you may need to optimize memory usage by creating a new jsdom instance for each page`)
|
||||
),
|
||||
el("p").append(...T`
|
||||
For advanced SSR applications, consider implementing hydration on the client-side to restore
|
||||
interactivity after the initial render.
|
||||
`),
|
||||
|
||||
el(h3, t`Real Example: How This Documentation is Built`),
|
||||
el("p").append(...T`
|
||||
This documentation site itself is built using deka-dom-el's SSR capabilities.
|
||||
The build process collects all page components, renders them with jsdom, and outputs static HTML files.
|
||||
`),
|
||||
el(code, { src: fileURL("./components/examples/ssr/static-site-generator.js"), page_id }),
|
||||
|
||||
el("p").append(...T`
|
||||
The resulting static files can be deployed to any static hosting service,
|
||||
providing fast loading times and excellent SEO without the need for client-side JavaScript
|
||||
to render the initial content.
|
||||
`),
|
||||
);
|
||||
}
|
363
docs/p10-ireland.html.js
Normal file
363
docs/p10-ireland.html.js
Normal file
@ -0,0 +1,363 @@
|
||||
import { T, t } from "./utils/index.js";
|
||||
export const info= {
|
||||
title: t`Ireland Components`,
|
||||
fullTitle: t`Interactive Demo Components with Server-Side Pre-Rendering`,
|
||||
description: t`Creating live, interactive component examples in documentation with server-side
|
||||
rendering and client-side hydration.`,
|
||||
};
|
||||
|
||||
import { el } from "deka-dom-el";
|
||||
import { simplePage } from "./layout/simplePage.html.js";
|
||||
import { h3 } from "./components/pageUtils.html.js";
|
||||
import { code } from "./components/code.html.js";
|
||||
import { ireland } from "./components/ireland.html.js";
|
||||
/** @param {string} url */
|
||||
const fileURL= url=> new URL(url, import.meta.url);
|
||||
|
||||
/** @param {import("./types.js").PageAttrs} attrs */
|
||||
export function page({ pkg, info }){
|
||||
const page_id= info.id;
|
||||
return el(simplePage, { info, pkg }).append(
|
||||
el("div", { className: "warning" }).append(
|
||||
el("p").append(...T`
|
||||
This part of the documentation is primarily intended for technical enthusiasts and authors of
|
||||
3rd-party libraries. It describes an advanced feature, not a core part of the library. Most users will
|
||||
not need to implement this functionality directly in their applications. This capability will hopefully
|
||||
be covered by third-party libraries or frameworks that provide simpler SSR integration using
|
||||
deka-dom-el.
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`What Are Ireland Components?`),
|
||||
el("p").append(...T`
|
||||
Ireland components are a special type of documentation component that:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", t`Display source code with syntax highlighting`),
|
||||
el("li", t`Pre-render components on the server during documentation build`),
|
||||
el("li", t`Copy component source files to the documentation output`),
|
||||
el("li", t`Provide client-side rehydration for interactive demos`),
|
||||
el("li", t`Allow users to run and experiment with components in real-time`)
|
||||
),
|
||||
|
||||
el(h3, t`How Ireland Components Work`),
|
||||
el("p").append(...T`
|
||||
The Ireland component system consists of several parts working together:
|
||||
`),
|
||||
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Server-side rendering:")} Components are pre-rendered during the documentation build process
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Component registration:")} Source files are copied to the documentation output directory
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Client-side scripting:")} JavaScript code is generated to load and render components
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "User interaction:")} The "Run Component" button dynamically loads and renders the component
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`Implementation Architecture`),
|
||||
el("p").append(...T`
|
||||
The core of the Ireland system is implemented in ${el("code", "docs/components/ireland.html.js")}.
|
||||
It integrates with the SSR build process using the ${el("code", "registerClientFile")} function
|
||||
from ${el("code", "docs/ssr.js")}.
|
||||
`),
|
||||
|
||||
el(code, { content: `
|
||||
// Basic usage of an ireland component
|
||||
el(ireland, {
|
||||
src: fileURL("./components/examples/path/to/component.js"),
|
||||
exportName: "NamedExport", // optional, defaults to "default",
|
||||
})`, page_id }),
|
||||
|
||||
el("p").append(...T`
|
||||
During the build process (${el("code", "bs/docs.js")}), the following happens:
|
||||
`),
|
||||
|
||||
el("ol").append(
|
||||
el("li", t`Component source code is loaded and displayed with syntax highlighting`),
|
||||
el("li", t`Source files are registered to be copied to the output directory`),
|
||||
el("li", t`Client-side scripts are generated for each page with ireland components`),
|
||||
el("li", t`The component is wrapped in a UI container with controls`)
|
||||
),
|
||||
|
||||
el(h3, t`Core Implementation Details`),
|
||||
el("p").append(...T`
|
||||
Let's look at the key parts of the ireland component implementation:
|
||||
`),
|
||||
|
||||
el("h4", t`Building SSR`),
|
||||
el(code, { content: `
|
||||
// From bs/docs.js - Server-side rendering engine
|
||||
import { createHTMl } from "./docs/jsdom.js";
|
||||
import { register, queue } from "../jsdom.js";
|
||||
import { path_target, dispatchEvent } from "../docs/ssr.js";
|
||||
|
||||
// For each page, render it on the server
|
||||
for(const { id, info } of pages) {
|
||||
// Create a virtual DOM environment for server-side rendering
|
||||
const serverDOM = createHTMl("");
|
||||
serverDOM.registerGlobally("HTMLScriptElement");
|
||||
|
||||
// Register deka-dom-el with the virtual DOM
|
||||
const { el } = await register(serverDOM.dom);
|
||||
|
||||
// Import and render the page component
|
||||
const { page } = await import(\`../docs/\${id}.html.js\`);
|
||||
serverDOM.document.body.append(
|
||||
el(page, { pkg, info }),
|
||||
);
|
||||
|
||||
// Process the queue of asynchronous operations
|
||||
await queue();
|
||||
|
||||
// Trigger render event handlers
|
||||
dispatchEvent("oneachrender", document);
|
||||
|
||||
// Write the HTML to the output file
|
||||
s.echo(serverDOM.serialize()).to(path_target.root+id+".html");
|
||||
}
|
||||
|
||||
// Final build step - trigger SSR end event
|
||||
dispatchEvent("onssrend");
|
||||
`, page_id }),
|
||||
el("h4", t`File Registration`),
|
||||
el(code, { content: `
|
||||
// From docs/ssr.js - File registration system
|
||||
export function registerClientFile(url, { head, folder = "", replacer } = {}) {
|
||||
// Ensure folder path ends with a slash
|
||||
if(folder && !folder.endsWith("/")) folder += "/";
|
||||
|
||||
// Extract filename from URL
|
||||
const file_name = url.pathname.split("/").pop();
|
||||
|
||||
// Create target directory if needed
|
||||
s.mkdir("-p", path_target.root+folder);
|
||||
|
||||
// Get file content and apply optional replacer function
|
||||
let content = s.cat(url);
|
||||
if(replacer) content = s.echo(replacer(content.toString()));
|
||||
|
||||
// Write content to the output directory
|
||||
content.to(path_target.root+folder+file_name);
|
||||
|
||||
// If a head element was provided, add it to the document
|
||||
if(!head) return;
|
||||
head[head instanceof HTMLScriptElement ? "src" : "href"] = file_name;
|
||||
document.head.append(head);
|
||||
}
|
||||
`, page_id }),
|
||||
el("h4", t`Server-Side Rendering`),
|
||||
el(code, { content: `
|
||||
// From docs/components/ireland.html.js - Server-side component implementation
|
||||
export function ireland({ src, exportName = "default", props = {} }) {
|
||||
// Calculate relative path for imports
|
||||
const path = "./"+relative(dir, src.pathname);
|
||||
|
||||
// Generate unique ID for this component instance
|
||||
const id = "ireland-" + generateComponentId(src);
|
||||
|
||||
// Create placeholder element
|
||||
const element = el.mark({ type: "later", name: ireland.name });
|
||||
|
||||
// Import and render the component during SSR
|
||||
queue(import(path).then(module => {
|
||||
const component = module[exportName];
|
||||
element.replaceWith(el(component, props, mark(id)));
|
||||
}));
|
||||
|
||||
// Register client-side hydration on first component
|
||||
if(!componentsRegistry.size)
|
||||
addEventListener("oneachrender", registerClientPart);
|
||||
|
||||
// Store component info for client-side hydration
|
||||
componentsRegistry.set(id, {
|
||||
src,
|
||||
path: dirFE+"/"+path.split("/").pop(),
|
||||
exportName,
|
||||
props,
|
||||
});
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
// Register client-side resources
|
||||
function registerClientPart() {
|
||||
// Process all component registrations
|
||||
const todo = Array.from(componentsRegistry.entries())
|
||||
.map(([ id, d ]) => {
|
||||
// Copy the component source file to output directory
|
||||
registerClientFile(d.src, {
|
||||
folder: dirFE,
|
||||
// Replace bare imports for browser compatibility
|
||||
replacer(file) {
|
||||
return file.replaceAll(
|
||||
/ from "deka-dom-el(\/signals)?";/g,
|
||||
\` from "./esm-with-signals.js";\`
|
||||
);
|
||||
}
|
||||
});
|
||||
return [ id, d ];
|
||||
});
|
||||
|
||||
// Serialize the component registry for client-side use
|
||||
const store = JSON.stringify(JSON.stringify(todo));
|
||||
|
||||
// Copy client-side scripts to output
|
||||
registerClientFile(new URL("./ireland.js.js", import.meta.url));
|
||||
registerClientFile(new URL("../../dist/esm-with-signals.js", import.meta.url), { folder: dirFE });
|
||||
|
||||
// Add import map for package resolution
|
||||
document.head.append(
|
||||
el("script", { type: "importmap" }).append(\`
|
||||
{
|
||||
"imports": {
|
||||
"deka-dom-el": "./\${dirFE}/esm-with-signals.js",
|
||||
"deka-dom-el/signals": "./\${dirFE}/esm-with-signals.js"
|
||||
}
|
||||
}
|
||||
\`.trim())
|
||||
);
|
||||
|
||||
// Add bootstrap script to load components
|
||||
document.body.append(
|
||||
el("script", { type: "module" }).append(\`
|
||||
import { loadIrelands } from "./ireland.js.js";
|
||||
loadIrelands(new Map(JSON.parse(\${store})));
|
||||
\`.trim())
|
||||
);
|
||||
}
|
||||
`, page_id }),
|
||||
el("h4", t`Client-Side Hydration`),
|
||||
el(code, { content: `
|
||||
// From docs/components/ireland.js.js - Client-side hydration
|
||||
import { el } from "./irelands/esm-with-signals.js";
|
||||
|
||||
export function loadIrelands(store) {
|
||||
// Find all marked components in the DOM
|
||||
document.body.querySelectorAll("[data-dde-mark]").forEach(ireland => {
|
||||
const { ddeMark } = ireland.dataset;
|
||||
|
||||
// Skip if this component isn't in our registry
|
||||
if(!store.has(ddeMark)) return;
|
||||
|
||||
// Get component information
|
||||
const { path, exportName, props } = store.get(ddeMark);
|
||||
|
||||
// Dynamically import the component module
|
||||
import("./" + path).then(module => {
|
||||
// Replace the server-rendered element with the client-side version
|
||||
ireland.replaceWith(el(module[exportName], props));
|
||||
});
|
||||
});
|
||||
}
|
||||
`, page_id }),
|
||||
|
||||
el(h3, t`Live Example`),
|
||||
el("p").append(...T`
|
||||
Here's a live example of an Ireland component showing a standard counter.
|
||||
The component is defined in ${el("code", "docs/components/examples/ireland-test/counter.js")} and
|
||||
rendered with the Ireland component system:
|
||||
`),
|
||||
|
||||
el(code, {
|
||||
src: fileURL("./components/examples/ireland-test/counter.js"),
|
||||
page_id
|
||||
}),
|
||||
el(ireland, {
|
||||
src: fileURL("./components/examples/ireland-test/counter.js"),
|
||||
exportName: "CounterStandard",
|
||||
page_id
|
||||
}),
|
||||
|
||||
el("p").append(...T`
|
||||
When the "Run Component" button is clicked, the component is loaded and rendered dynamically.
|
||||
The counter state is maintained using signals, allowing for reactive updates as you click
|
||||
the buttons to increment and decrement the value.
|
||||
`),
|
||||
|
||||
el(h3, t`Creating Your Own Components`),
|
||||
el("p").append(...T`
|
||||
To create components for use with the Ireland system, follow these guidelines:
|
||||
`),
|
||||
|
||||
el("ol").append(
|
||||
el("li").append(...T`
|
||||
${el("strong", "Export a function:")} Components should be exported as named or default functions
|
||||
`),
|
||||
el("li").append(...T`
|
||||
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Accept props:")} Components should accept a props object, even if not using it
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Manage reactivity:")} Use signals for state management where appropriate
|
||||
`),
|
||||
el("li").append(...T`
|
||||
${el("strong", "Handle cleanup:")} Include any necessary cleanup for event listeners or signals
|
||||
`)
|
||||
),
|
||||
|
||||
el(h3, t`Practical Considerations and Limitations`),
|
||||
el("p").append(...T`
|
||||
When implementing Ireland components in real documentation, there are several important
|
||||
considerations to keep in mind:
|
||||
`),
|
||||
|
||||
el("div", { className: "warning" }).append(
|
||||
el("h4", t`Module Resolution and Bundling`),
|
||||
el("p").append(...T`
|
||||
The examples shown here use bare module specifiers like ${el("code", "import { el } from \"deka-dom-el\"")}
|
||||
which aren't supported in all browsers without importmaps. In a production implementation, you would need to:
|
||||
`),
|
||||
el("ol").append(
|
||||
el("li", t`Replace bare import paths with actual paths during the build process`),
|
||||
el("li", t`Bundle component dependencies to avoid multiple requests`),
|
||||
el("li", t`Ensure all module dependencies are properly resolved and copied to the output directory`)
|
||||
),
|
||||
el("p").append(...T`
|
||||
In this documentation, we replace the paths with ${el("code", "./esm-with-signals.js")} and provide
|
||||
a bundled version of the library, but more complex components might require a dedicated bundling step.
|
||||
`)
|
||||
),
|
||||
|
||||
el("div", { className: "note" }).append(
|
||||
el("h4", t`Component Dependencies`),
|
||||
el("p").append(...T`
|
||||
Real-world components typically depend on multiple modules and assets. The Ireland system would need
|
||||
to be extended to:
|
||||
`),
|
||||
el("ul").append(
|
||||
el("li", t`Detect and analyze all dependencies of a component`),
|
||||
el("li", t`Bundle these dependencies together or ensure they're properly copied to the output directory`),
|
||||
el("li", t`Handle non-JavaScript assets like CSS, images, or data files`)
|
||||
)
|
||||
),
|
||||
|
||||
el(h3, t`Advanced Usage`),
|
||||
el("p").append(...T`
|
||||
The Ireland system can be extended in several ways to address these limitations:
|
||||
`),
|
||||
|
||||
el("ul").append(
|
||||
el("li", t`Integrate with a bundler like esbuild, Rollup, or Webpack`),
|
||||
el("li", t`Add props support for configuring components at runtime`),
|
||||
el("li", t`Implement module caching to reduce network requests`),
|
||||
el("li", t`Add code editing capabilities for interactive experimentation`),
|
||||
el("li", t`Support TypeScript and other languages through transpilation`),
|
||||
el("li", t`Implement state persistence between runs`)
|
||||
),
|
||||
|
||||
el("p").append(...T`
|
||||
This documentation site itself is built using the techniques described here,
|
||||
showcasing how deka-dom-el can be used to create both the documentation and
|
||||
the interactive examples within it. The implementation here is simplified for clarity,
|
||||
while a production-ready system would need to address the considerations above.
|
||||
`)
|
||||
);
|
||||
}
|
22
docs/ssr.js
22
docs/ssr.js
@ -1,7 +1,8 @@
|
||||
export { t } from "./utils/index.js";
|
||||
export const path_target= {
|
||||
root: "dist/docs/",
|
||||
css: "dist/docs/"
|
||||
css: "dist/docs/",
|
||||
assets: "dist/docs/assets/"
|
||||
};
|
||||
/**
|
||||
* This variable will be filled with the list of pages during the build process (see `bs/docs.js`).
|
||||
@ -12,16 +13,23 @@ export let pages= [];
|
||||
* @typedef registerClientFile
|
||||
* @type {function}
|
||||
* @param {URL} url
|
||||
* @param {HTMLScriptElement|HTMLLinkElement} [element_head]
|
||||
* @param {Object} [options]
|
||||
* @param {HTMLScriptElement|HTMLLinkElement} [options.head]
|
||||
* @param {string} [options.folder]
|
||||
* @param {function} [options.replacer]
|
||||
* */
|
||||
export function registerClientFile(url, element_head){
|
||||
export function registerClientFile(url, { head, folder= "", replacer }= {}){
|
||||
if(folder && !folder.endsWith("/")) folder+= "/";
|
||||
const file_name= url.pathname.split("/").pop();
|
||||
s.cat(url).to(path_target.root+file_name);
|
||||
s.mkdir("-p", path_target.root+folder);
|
||||
let content= s.cat(url)
|
||||
if(replacer) content= s.echo(replacer(content.toString()));
|
||||
content.to(path_target.root+folder+file_name);
|
||||
|
||||
if(!element_head) return;
|
||||
element_head[element_head instanceof HTMLScriptElement ? "src" : "href"]= file_name;
|
||||
if(!head) return;
|
||||
head[head instanceof HTMLScriptElement ? "src" : "href"]= file_name;
|
||||
document.head.append(
|
||||
element_head
|
||||
head
|
||||
);
|
||||
}
|
||||
|
||||
|
1
docs/types.d.ts
vendored
1
docs/types.d.ts
vendored
@ -4,6 +4,7 @@ export type Info= {
|
||||
id: string,
|
||||
href: string,
|
||||
title: string,
|
||||
fullTitle: string,
|
||||
description: string,
|
||||
}
|
||||
export type Pages=Info[];
|
||||
|
@ -15,7 +15,7 @@ export function thirdParty(){
|
||||
}, {
|
||||
set(key, value){
|
||||
const p= this.value[key] || S();
|
||||
p(value);
|
||||
p.set(value);
|
||||
this.value[key]= p;
|
||||
}
|
||||
});
|
||||
@ -32,7 +32,7 @@ export function thirdParty(){
|
||||
})();
|
||||
return el("input", {
|
||||
className,
|
||||
value: store().value(),
|
||||
value: store.get().value.get(),
|
||||
type: "text",
|
||||
onchange: ev=> S.action(store, "set", "value", ev.target.value)
|
||||
});
|
||||
|
@ -9,24 +9,24 @@ export function fullNameComponent(){
|
||||
const labels= [ "Name", "Surname" ];
|
||||
const name= labels.map(_=> S(""));
|
||||
const full_name= S(()=>
|
||||
name.map(l=> l()).filter(Boolean).join(" ") || "-");
|
||||
name.map(l=> l.get()).filter(Boolean).join(" ") || "-");
|
||||
scope.host(
|
||||
on.connected(()=> console.log(fullNameComponent)),
|
||||
on.disconnected(()=> console.log(fullNameComponent))
|
||||
);
|
||||
|
||||
const count= S(0);
|
||||
setInterval(()=> count(count()+1), 5000);
|
||||
setInterval(()=> count.set(count.get()+1), 5000);
|
||||
const style= { height: "80px", display: "block", fill: "currentColor" };
|
||||
const elSVG= elNS("http://www.w3.org/2000/svg");
|
||||
return el("div", { className }).append(
|
||||
el("h2", "Simple form:"),
|
||||
el("p", { textContent: S(()=> "Count: "+count()),
|
||||
dataset: { count }, classList: { count: S(() => count()%2 === 0) } }),
|
||||
el("p", { textContent: S(()=> "Count: "+count.get()),
|
||||
dataset: { count }, classList: { count: S(() => count.get()%2 === 0) } }),
|
||||
el("form", { onsubmit: ev=> ev.preventDefault() }).append(
|
||||
...name.map((v, i)=>
|
||||
el("label", labels[i]).append(
|
||||
el("input", { type: "text", name: labels[i], value: v() }, on("change", ev=> v(ev.target.value)))
|
||||
el("input", { type: "text", name: labels[i], value: v.get() }, on("change", ev=> v.set(ev.target.value)))
|
||||
))
|
||||
),
|
||||
el("p").append(
|
||||
|
@ -45,7 +45,7 @@ export function todosComponent({ todos= [ "Task A" ] }= {}){
|
||||
: el("ul").append(
|
||||
...Array.from(ts).map(([ value, textContent ])=>
|
||||
memo(value, ()=> el(todoComponent, { textContent, value, className }, onremove)))
|
||||
)
|
||||
),
|
||||
),
|
||||
el("p", "Click to the text to edit it.")
|
||||
),
|
||||
@ -54,11 +54,11 @@ export function todosComponent({ todos= [ "Task A" ] }= {}){
|
||||
el("label", "New todo: ").append(
|
||||
el("input", { name, type: "text", required: true }),
|
||||
),
|
||||
el("button", "+")
|
||||
el("button", "+"),
|
||||
),
|
||||
el("div").append(
|
||||
el("h3", "Output (JSON):"),
|
||||
el("output", S(()=> JSON.stringify(Array.from(todosO()), null, "\t")))
|
||||
el("output", S(()=> JSON.stringify(Array.from(todosO.get()), null, "\t")))
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -80,13 +80,13 @@ function todoComponent({ textContent, value }){
|
||||
const is_editable= S(false);
|
||||
const onedited= on("change", ev=> {
|
||||
const el= /** @type {HTMLInputElement} */ (ev.target);
|
||||
textContent(el.value);
|
||||
is_editable(false);
|
||||
textContent.set(el.value);
|
||||
is_editable.set(false);
|
||||
});
|
||||
return el("li").append(
|
||||
S.el(is_editable, is=> is
|
||||
? el("input", { value: textContent(), type: "text" }, onedited)
|
||||
: el("span", { textContent, onclick: is_editable.bind(null, true) })
|
||||
? el("input", { value: textContent.get(), type: "text" }, onedited)
|
||||
: el("span", { textContent, onclick: ()=> is_editable.set(true) })
|
||||
),
|
||||
el("button", { type: "button", value, textContent: "-" }, onclick)
|
||||
);
|
||||
|
@ -34,7 +34,7 @@ export class CustomHTMLTestElement extends HTMLElement{
|
||||
text(test),
|
||||
text(name),
|
||||
text(preName),
|
||||
el("button", { type: "button", textContent: "pre-name", onclick: ()=> preName("Ahoj") }),
|
||||
el("button", { type: "button", textContent: "pre-name", onclick: ()=> preName.set("Ahoj") }),
|
||||
" | ",
|
||||
el("slot", { className: "test", name: "test" }),
|
||||
);
|
||||
|
@ -20,7 +20,7 @@ document.body.append(
|
||||
el("span", { textContent: "test", slot: "test" }),
|
||||
),
|
||||
el(thirdParty),
|
||||
el(CustomSlottingHTMLElement.tagName, { onclick: ()=> toggle(!toggle()) }).append(
|
||||
el(CustomSlottingHTMLElement.tagName, { onclick: ()=> toggle.set(!toggle.get()) }).append(
|
||||
el("strong", { slot: "name", textContent: "Honzo" }),
|
||||
S.el(toggle, is=> is
|
||||
? el("span", "…default slot")
|
||||
|
94
index.d.ts
vendored
94
index.d.ts
vendored
@ -1,5 +1,4 @@
|
||||
declare global{ /* ddeSignal */ }
|
||||
|
||||
import type { Signal as ddeSignal } from "./signals";
|
||||
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
||||
type SupportedElement=
|
||||
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
||||
@ -9,8 +8,8 @@ type SupportedElement=
|
||||
declare global {
|
||||
type ddeComponentAttributes= Record<any, any> | undefined;
|
||||
type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node>= (element: El)=> any;
|
||||
type ddeString= string | ddeSignal<string>
|
||||
type ddeStringable= ddeString | number | ddeSignal<number>
|
||||
type ddeString= string | ddeSignal<string, {}>
|
||||
type ddeStringable= ddeString | number | ddeSignal<number, {}>
|
||||
}
|
||||
type PascalCase= `${Capitalize<string>}${string}`;
|
||||
type AttrsModified= {
|
||||
@ -18,13 +17,13 @@ type AttrsModified= {
|
||||
* Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API).
|
||||
*/
|
||||
style: Partial<CSSStyleDeclaration> | ddeString
|
||||
| Partial<{ [K in keyof CSSStyleDeclaration]: ddeSignal<CSSStyleDeclaration[K]> }>
|
||||
| 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.
|
||||
*/
|
||||
classList: Record<string,-1|0|1|boolean|ddeSignal<-1|0|1|boolean>>,
|
||||
classList: Record<string,-1|0|1|boolean|ddeSignal<-1|0|1|boolean, {}>>,
|
||||
/**
|
||||
* Used by the dataset HTML attribute to represent data for custom attributes added to elements.
|
||||
* Values are converted to string (see {@link DOMStringMap}).
|
||||
@ -52,9 +51,13 @@ type IsReadonly<T, K extends keyof T> =
|
||||
* @private
|
||||
*/
|
||||
type ElementAttributes<T extends SupportedElement>= Partial<{
|
||||
[K in keyof _fromElsInterfaces<T>]: IsReadonly<_fromElsInterfaces<T>, K> extends false
|
||||
? _fromElsInterfaces<T>[K] | ddeSignal<_fromElsInterfaces<T>[K]>
|
||||
: ddeStringable
|
||||
[K in keyof _fromElsInterfaces<T>]:
|
||||
_fromElsInterfaces<T>[K] extends ((...p: any[])=> any)
|
||||
? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>)=>
|
||||
ddeSignal<ReturnType<_fromElsInterfaces<T>[K]>, {}>)
|
||||
: (IsReadonly<_fromElsInterfaces<T>, K> extends false
|
||||
? _fromElsInterfaces<T>[K] | ddeSignal<_fromElsInterfaces<T>[K], {}>
|
||||
: ddeStringable)
|
||||
} & AttrsModified> & Record<string, any>;
|
||||
export function classListDeclarative<El extends SupportedElement>(
|
||||
element: El,
|
||||
@ -68,6 +71,40 @@ export function assignAttribute<El extends SupportedElement, ATT extends keyof E
|
||||
): ElementAttributes<El>[ATT]
|
||||
|
||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap;
|
||||
export namespace el {
|
||||
/**
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param attrs - Marker attributes
|
||||
* @param [is_open=false] - Whether the marker is open-ended
|
||||
* @returns Comment node marker
|
||||
*/
|
||||
export function mark(
|
||||
attrs: { type: "component"|"reactive"|"later", name?: string, host?: "this"|"parentElement" },
|
||||
is_open?: boolean
|
||||
): Comment;
|
||||
}
|
||||
|
||||
export function el<
|
||||
A extends ddeComponentAttributes,
|
||||
EL extends SupportedElement | ddeDocumentFragment
|
||||
>(
|
||||
component: (attr: A, ...rest: any[])=> EL,
|
||||
attrs?: NoInfer<A>,
|
||||
...addons: ddeElementAddon<EL>[]
|
||||
): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap]
|
||||
? EL
|
||||
: ( EL extends ddeDocumentFragment ? EL : ddeHTMLElement )
|
||||
export function el<
|
||||
A extends { textContent: ddeStringable },
|
||||
EL extends SupportedElement | ddeDocumentFragment
|
||||
>(
|
||||
component: (attr: A, ...rest: any[])=> EL,
|
||||
attrs?: NoInfer<A>["textContent"],
|
||||
...addons: ddeElementAddon<EL>[]
|
||||
): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap]
|
||||
? EL
|
||||
: ( EL extends ddeDocumentFragment ? EL : ddeHTMLElement )
|
||||
export function el<
|
||||
TAG extends keyof ExtendedHTMLElementTagNameMap,
|
||||
>(
|
||||
@ -85,16 +122,6 @@ export function el(
|
||||
attrs?: ElementAttributes<HTMLElement> | ddeStringable,
|
||||
...addons: ddeElementAddon<HTMLElement>[]
|
||||
): ddeHTMLElement
|
||||
|
||||
export function el<
|
||||
C extends (attr: ddeComponentAttributes)=> SupportedElement | ddeDocumentFragment
|
||||
>(
|
||||
component: C,
|
||||
attrs?: Parameters<C>[0] | ddeStringable,
|
||||
...addons: ddeElementAddon<ReturnType<C>>[]
|
||||
): ReturnType<C> extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap]
|
||||
? ReturnType<C>
|
||||
: ( ReturnType<C> extends ddeDocumentFragment ? ReturnType<C> : ddeHTMLElement )
|
||||
export { el as createElement }
|
||||
|
||||
export function elNS(
|
||||
@ -115,7 +142,7 @@ export function elNS(
|
||||
>(
|
||||
tag_name: TAG,
|
||||
attrs?: ddeStringable | Partial<{
|
||||
[key in keyof EL]: EL[key] | ddeSignal<EL[key]> | string | number | boolean
|
||||
[key in keyof EL]: EL[key] | ddeSignal<EL[key], {}> | string | number | boolean
|
||||
}>,
|
||||
...addons: ddeElementAddon<NoInfer<EL>>[]
|
||||
)=> ddeMathMLElement
|
||||
@ -143,6 +170,8 @@ export function simulateSlots<EL extends SupportedElement | DocumentFragment>(
|
||||
body: EL,
|
||||
): EL
|
||||
|
||||
export function dispatchEvent(name: keyof DocumentEventMap | string, element: SupportedElement):
|
||||
(data?: any)=> void;
|
||||
export function dispatchEvent(name: keyof DocumentEventMap | string, options?: EventInit):
|
||||
(element: SupportedElement, data?: any)=> void;
|
||||
export function dispatchEvent(
|
||||
@ -216,7 +245,7 @@ export const scope: {
|
||||
|
||||
state: Scope[],
|
||||
/** Adds new child scope. All attributes are inherited by default. */
|
||||
push(scope: Partial<Scope>): ReturnType<Array<Scope>["push"]>,
|
||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>,
|
||||
/** Adds root scope as a child of the current scope. */
|
||||
pushRoot(): ReturnType<Array<Scope>["push"]>,
|
||||
/** Removes last/current child scope. */
|
||||
@ -225,7 +254,7 @@ export const scope: {
|
||||
|
||||
export function customElementRender<
|
||||
EL extends HTMLElement,
|
||||
P extends any = Record<string, string | ddeSignal<string>>
|
||||
P extends any = Record<string, string | ddeSignal<string, {}>>
|
||||
>(
|
||||
target: ShadowRoot | EL,
|
||||
render: (props: P)=> SupportedElement | DocumentFragment,
|
||||
@ -235,6 +264,27 @@ export function customElementWithDDE<EL extends (new ()=> HTMLElement)>(custom_e
|
||||
export function lifecyclesToEvents<EL extends (new ()=> HTMLElement)>(custom_element: EL): EL
|
||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>
|
||||
|
||||
/**
|
||||
* This is used primarly for server side rendering. To be sure that all async operations
|
||||
* are finished before the page is sent to the client.
|
||||
* ```
|
||||
* // on component
|
||||
* function component(){
|
||||
* …
|
||||
* queue(fetch(...).then(...));
|
||||
* }
|
||||
*
|
||||
* // building the page
|
||||
* async function build(){
|
||||
* const { component }= await import("./component.js");
|
||||
* document.body.append(el(component));
|
||||
* await queue();
|
||||
* retutn document.body.innerHTML;
|
||||
* }
|
||||
* ```
|
||||
* */
|
||||
export function queue(promise?: Promise<unknown>): Promise<unknown>;
|
||||
|
||||
/* TypeScript MEH */
|
||||
declare global{
|
||||
type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
|
||||
|
2
jsdom.js
2
jsdom.js
@ -17,7 +17,7 @@ env.setDeleteAttr= function(obj, prop, value){
|
||||
if(value) return obj.setAttribute(prop, "");
|
||||
obj.removeAttribute(prop);
|
||||
};
|
||||
const keys= { H: "HTMLElement", S: "SVGElement", F: "DocumentFragment", M: "MutationObserver", D: "document" };
|
||||
const keys= { H: "HTMLElement", S: "SVGElement", F: "DocumentFragment", D: "document" };
|
||||
let env_bk= {};
|
||||
let dom_last;
|
||||
|
||||
|
1551
package-lock.json
generated
1551
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
21
package.json
21
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "deka-dom-el",
|
||||
"version": "0.8.0",
|
||||
"version": "0.9.0",
|
||||
"description": "A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks.",
|
||||
"author": "Jan Andrle <andrle.jan@centrum.cz>",
|
||||
"license": "MIT",
|
||||
@ -29,8 +29,8 @@
|
||||
"types": "./jsdom.d.ts"
|
||||
},
|
||||
"./src/signals-lib": {
|
||||
"import": "./src/signals-lib.js",
|
||||
"types": "./src/signals-lib.d.ts"
|
||||
"import": "./src/signals-lib/signals-lib.js",
|
||||
"types": "./src/signals-lib/signals-lib.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
@ -53,7 +53,8 @@
|
||||
"globals": {
|
||||
"requestIdleCallback": false,
|
||||
"AbortController": false,
|
||||
"AbortSignal": false
|
||||
"AbortSignal": false,
|
||||
"FinalizationRegistry": false
|
||||
}
|
||||
},
|
||||
"size-limit": [
|
||||
@ -65,7 +66,7 @@
|
||||
},
|
||||
{
|
||||
"path": "./signals.js",
|
||||
"limit": "12 kB",
|
||||
"limit": "12.5 kB",
|
||||
"gzip": false,
|
||||
"brotli": false
|
||||
},
|
||||
@ -77,7 +78,7 @@
|
||||
},
|
||||
{
|
||||
"path": "./index-with-signals.js",
|
||||
"limit": "5.25 kB"
|
||||
"limit": "5.5 kB"
|
||||
}
|
||||
],
|
||||
"modifyEsbuildConfig": {
|
||||
@ -91,11 +92,11 @@
|
||||
"typescript"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@size-limit/preset-small-lib": "~11.0",
|
||||
"dts-bundler": "~0.1",
|
||||
"@size-limit/preset-small-lib": "~11.2",
|
||||
"dts-bundle-generator": "~9.5",
|
||||
"editorconfig-checker": "~6.0",
|
||||
"esbuild": "~0.24",
|
||||
"jsdom": "~25.0",
|
||||
"esbuild": "~0.25",
|
||||
"jsdom": "~26.0",
|
||||
"jshint": "~2.13",
|
||||
"nodejsscript": "^1.0.2",
|
||||
"size-limit-node-esbuild": "~0.3"
|
||||
|
12
signals.d.ts
vendored
12
signals.d.ts
vendored
@ -1,4 +1,12 @@
|
||||
export type Signal<V, A>= (set?: V)=> V & A;
|
||||
export interface Signal<V, A> {
|
||||
/** The current value of the signal */
|
||||
get(): V;
|
||||
/** Set new value of the signal */
|
||||
set(value: V): V;
|
||||
toJSON(): V;
|
||||
valueOf(): V;
|
||||
}
|
||||
|
||||
type Action<V>= (this: { value: V, stopPropagation(): void }, ...a: any[])=> typeof signal._ | void;
|
||||
//type SymbolSignal= Symbol;
|
||||
type SymbolOnclear= symbol;
|
||||
@ -27,7 +35,7 @@ interface signal{
|
||||
* ```js
|
||||
* const name= S("Jan");
|
||||
* const surname= S("Andrle");
|
||||
* const fullname= S(()=> name()+" "+surname());
|
||||
* const fullname= S(()=> name.get()+" "+surname.get());
|
||||
* ```
|
||||
* @param value Initial signal value. Or function computing value from other signals.
|
||||
* @param actions Use to define actions on the signal. Such as add item to the array.
|
||||
|
@ -1,4 +1,4 @@
|
||||
export { signal, S, isSignal } from "./src/signals-lib.js";
|
||||
import { signals_config } from "./src/signals-lib.js";
|
||||
import { registerReactivity } from "./src/signals-common.js";
|
||||
export { signal, S, isSignal } from "./src/signals-lib/signals-lib.js";
|
||||
import { signals_config } from "./src/signals-lib/signals-lib.js";
|
||||
import { registerReactivity } from "./src/signals-lib/common.js";
|
||||
registerReactivity(signals_config);
|
||||
|
@ -1,6 +1,15 @@
|
||||
import { keyLTE, evc, evd, eva } from "./dom-common.js";
|
||||
import { scope } from "./dom.js";
|
||||
import { c_ch_o } from "./events-observer.js";
|
||||
|
||||
/**
|
||||
* Renders content into a custom element or shadow root
|
||||
*
|
||||
* @param {Element|ShadowRoot} target - The custom element or shadow root to render into
|
||||
* @param {Function} render - The render function that returns content
|
||||
* @param {Function|Object} [props=observedAttributes] - Props to pass to the render function
|
||||
* @returns {Node} The rendered content
|
||||
*/
|
||||
export function customElementRender(target, render, props= observedAttributes){
|
||||
const custom_element= target.host || target;
|
||||
scope.push({
|
||||
@ -17,6 +26,13 @@ export function customElementRender(target, render, props= observedAttributes){
|
||||
scope.pop();
|
||||
return target.append(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms custom element lifecycle callbacks into events
|
||||
*
|
||||
* @param {Function|Object} class_declaration - Custom element class or instance
|
||||
* @returns {Function|Object} The modified class or instance
|
||||
*/
|
||||
export function lifecyclesToEvents(class_declaration){
|
||||
wrapMethod(class_declaration.prototype, "connectedCallback", function(target, thisArg, detail){
|
||||
target.apply(thisArg, detail);
|
||||
@ -38,12 +54,30 @@ export function lifecyclesToEvents(class_declaration){
|
||||
class_declaration.prototype[keyLTE]= true;
|
||||
return class_declaration;
|
||||
}
|
||||
|
||||
/** Public API */
|
||||
export { lifecyclesToEvents as customElementWithDDE };
|
||||
|
||||
/**
|
||||
* Wraps a method with a proxy to intercept calls
|
||||
*
|
||||
* @param {Object} obj - Object containing the method
|
||||
* @param {string} method - Method name to wrap
|
||||
* @param {Function} apply - Function to execute when method is called
|
||||
* @private
|
||||
*/
|
||||
function wrapMethod(obj, method, apply){
|
||||
obj[method]= new Proxy(obj[method] || (()=> {}), { apply });
|
||||
}
|
||||
|
||||
import { observedAttributes as oA } from "./helpers.js";
|
||||
|
||||
/**
|
||||
* Gets observed attributes for a custom element
|
||||
*
|
||||
* @param {Element} instance - Custom element instance
|
||||
* @returns {Object} Object mapping camelCase attribute names to their values
|
||||
*/
|
||||
export function observedAttributes(instance){
|
||||
return oA(instance, (i, n)=> i.getAttribute(n));
|
||||
}
|
||||
|
@ -1,3 +1,15 @@
|
||||
/**
|
||||
* Environment configuration and globals for the library
|
||||
* @typedef {Object} Environment
|
||||
* @property {typeof setDeleteAttr} setDeleteAttr - Function to safely set or delete attributes
|
||||
* @property {string} ssr - Server-side rendering flag
|
||||
* @property {Document} D - Document global
|
||||
* @property {typeof DocumentFragment} F - DocumentFragment constructor
|
||||
* @property {typeof HTMLElement} H - HTMLElement constructor
|
||||
* @property {typeof SVGElement} S - SVGElement constructor
|
||||
* @property {typeof MutationObserver} M - MutationObserver constructor
|
||||
* @property {Function} q - Promise wrapper for Promse queue feature
|
||||
*/
|
||||
export const enviroment= {
|
||||
setDeleteAttr,
|
||||
ssr: "",
|
||||
@ -8,26 +20,43 @@ export const enviroment= {
|
||||
M: globalThis.MutationObserver,
|
||||
q: p=> p || Promise.resolve(),
|
||||
};
|
||||
import { isUndef } from './helpers.js';
|
||||
import { isInstance, isUndef } from './helpers.js';
|
||||
|
||||
/**
|
||||
* Handles attribute setting with special undefined handling
|
||||
*
|
||||
* @param {Object} obj - The object to set the property on
|
||||
* @param {string} prop - The property name
|
||||
* @param {any} val - The value to set
|
||||
* @returns {void}
|
||||
*
|
||||
* Issue:
|
||||
* For some native attrs you can unset only to set empty string.
|
||||
* This can be confusing as it is seen in inspector `<… id=""`.
|
||||
* Options:
|
||||
* 1. Leave it, as it is native behaviour
|
||||
* 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
|
||||
* 4. Point 2. with checks for coincidence (e.g. use special string)
|
||||
*/
|
||||
function setDeleteAttr(obj, prop, val){
|
||||
/* Issue
|
||||
For some native attrs you can unset only to set empty string.
|
||||
This can be confusing as it is seen in inspector `<… id=""`.
|
||||
Options:
|
||||
1. Leave it, as it is native behaviour
|
||||
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
|
||||
4. Point 2. with checks for coincidence (e.g. use special string)
|
||||
*/
|
||||
Reflect.set(obj, prop, val);
|
||||
if(!isUndef(val)) return;
|
||||
Reflect.deleteProperty(obj, prop);
|
||||
if(obj instanceof enviroment.H && obj.getAttribute(prop)==="undefined")
|
||||
if(isInstance(obj, enviroment.H) && obj.getAttribute(prop)==="undefined")
|
||||
return obj.removeAttribute(prop);
|
||||
if(Reflect.get(obj, prop)==="undefined")
|
||||
return Reflect.set(obj, prop, "");
|
||||
}
|
||||
|
||||
/** Property key for tracking lifecycle events */
|
||||
export const keyLTE= "__dde_lifecyclesToEvents"; //boolean
|
||||
|
||||
/** Event name for connected lifecycle event */
|
||||
export const evc= "dde:connected";
|
||||
|
||||
/** Event name for disconnected lifecycle event */
|
||||
export const evd= "dde:disconnected";
|
||||
|
||||
/** Event name for attribute changed lifecycle event */
|
||||
export const eva= "dde:attributeChanged";
|
||||
|
215
src/dom.js
215
src/dom.js
@ -1,38 +1,104 @@
|
||||
import { signals } from "./signals-common.js";
|
||||
import { signals } from "./signals-lib/common.js";
|
||||
import { enviroment as env } from './dom-common.js';
|
||||
import { isInstance, isUndef, oAssign } from "./helpers.js";
|
||||
|
||||
//TODO: add type, docs ≡ make it public
|
||||
/**
|
||||
* Queues a promise, this is helpful for crossplatform components (on server side we can wait for all registered
|
||||
* promises to be resolved before rendering).
|
||||
* @param {Promise} promise - Promise to process
|
||||
* @returns {Promise} Processed promise
|
||||
*/
|
||||
export function queue(promise){ return env.q(promise); }
|
||||
/** @type {{ scope: object, prevent: boolean, host: function }[]} */
|
||||
|
||||
/**
|
||||
* Array of scope contexts for tracking component hierarchies
|
||||
* @type {{ scope: object, prevent: boolean, host: function }[]}
|
||||
*/
|
||||
const scopes= [ {
|
||||
get scope(){ return env.D.body; },
|
||||
host: c=> c ? c(env.D.body) : env.D.body,
|
||||
prevent: true,
|
||||
} ];
|
||||
/**
|
||||
* Scope management utility for tracking component hierarchies
|
||||
*/
|
||||
export const scope= {
|
||||
/**
|
||||
* Gets the current scope
|
||||
* @returns {Object} Current scope context
|
||||
*/
|
||||
get current(){ return scopes[scopes.length-1]; },
|
||||
|
||||
/**
|
||||
* Gets the host element of the current scope
|
||||
* @returns {Function} Host accessor function
|
||||
*/
|
||||
get host(){ return this.current.host; },
|
||||
|
||||
/**
|
||||
* Prevents default behavior in the current scope
|
||||
* @returns {Object} Current scope context
|
||||
*/
|
||||
preventDefault(){
|
||||
const { current }= this;
|
||||
current.prevent= true;
|
||||
return current;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a copy of the current scope stack
|
||||
* @returns {Array} Copy of scope stack
|
||||
*/
|
||||
get state(){ return [ ...scopes ]; },
|
||||
push(s= {}){ return scopes.push(Object.assign({}, this.current, { prevent: false }, s)); },
|
||||
|
||||
/**
|
||||
* Pushes a new scope to the stack
|
||||
* @param {Object} [s={}] - Scope object to push
|
||||
* @returns {number} New length of the scope stack
|
||||
*/
|
||||
push(s= {}){ return scopes.push(oAssign({}, this.current, { prevent: false }, s)); },
|
||||
|
||||
/**
|
||||
* Pushes the root scope to the stack
|
||||
* @returns {number} New length of the scope stack
|
||||
*/
|
||||
pushRoot(){ return scopes.push(scopes[0]); },
|
||||
|
||||
/**
|
||||
* Pops the current scope from the stack
|
||||
* @returns {Object|undefined} Popped scope or undefined if only one scope remains
|
||||
*/
|
||||
pop(){
|
||||
if(scopes.length===1) return;
|
||||
return scopes.pop();
|
||||
},
|
||||
};
|
||||
//NOTE: following chainableAppend implementation is OK as the ElementPrototype.append description already is { writable: true, enumerable: true, configurable: true } // editorconfig-checker-disable-line
|
||||
/**
|
||||
* Chainable append function for elements
|
||||
* @private
|
||||
*/
|
||||
function append(...els){ this.appendOriginal(...els); return this; }
|
||||
|
||||
/**
|
||||
* Makes an element's append method chainable. NOTE: following chainableAppend implementation is OK as the
|
||||
* ElementPrototype.append description already is { writable: true, enumerable: true, configurable: true }
|
||||
* @param {Element} el - Element to modify
|
||||
* @returns {Element} Modified element
|
||||
*/
|
||||
export function chainableAppend(el){
|
||||
if(el.append===append) return el; el.appendOriginal= el.append; el.append= append; return el;
|
||||
}
|
||||
/** Current namespace for element creation */
|
||||
let namespace;
|
||||
|
||||
/**
|
||||
* Creates a DOM element with specified tag, attributes and addons
|
||||
*
|
||||
* @param {string|Function} tag - Element tag name or component function
|
||||
* @param {Object|string|number} [attributes] - Element attributes
|
||||
* @param {...Function} addons - Functions to call with the created element
|
||||
* @returns {Element|DocumentFragment} Created element
|
||||
*/
|
||||
export function createElement(tag, attributes, ...addons){
|
||||
/* jshint maxcomplexity: 15 */
|
||||
const s= signals(this);
|
||||
@ -47,7 +113,7 @@ export function createElement(tag, attributes, ...addons){
|
||||
(scoped===1 ? addons.unshift(...c) : c.forEach(c=> c(el_host)), undefined);
|
||||
scope.push({ scope: tag, host });
|
||||
el= tag(attributes || undefined);
|
||||
const is_fragment= el instanceof env.F;
|
||||
const is_fragment= isInstance(el, env.F);
|
||||
if(el.nodeName==="#comment") break;
|
||||
const el_mark= createElement.mark({
|
||||
type: "component",
|
||||
@ -70,10 +136,15 @@ export function createElement(tag, attributes, ...addons){
|
||||
scoped= 2;
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param { { type: "component", name: string, host: "this" | "parentElement" } | { type: "reactive" | "later" } } attrs
|
||||
* @param {boolean} [is_open=false]
|
||||
* */
|
||||
* Creates a marker comment for elements
|
||||
*
|
||||
* @param {{ type: "component"|"reactive"|"later", name?: string, host?: "this"|"parentElement" }} attrs - Marker
|
||||
* attributes
|
||||
* @param {boolean} [is_open=false] - Whether the marker is open-ended
|
||||
* @returns {Comment} Comment node marker
|
||||
*/
|
||||
createElement.mark= function(attrs, is_open= false){
|
||||
attrs= Object.entries(attrs).map(([ n, v ])=> n+`="${v}"`).join(" ");
|
||||
const end= is_open ? "" : "/";
|
||||
@ -81,8 +152,16 @@ createElement.mark= function(attrs, is_open= false){
|
||||
if(is_open) out.end= env.D.createComment("</dde:mark>");
|
||||
return out;
|
||||
};
|
||||
/** Alias for createElement */
|
||||
export { createElement as el };
|
||||
|
||||
//TODO?: const namespaceHelper= ns=> ns==="svg" ? "http://www.w3.org/2000/svg" : ns;
|
||||
/**
|
||||
* Creates a namespaced element creation function
|
||||
*
|
||||
* @param {string} ns - Namespace URI
|
||||
* @returns {Function} Element creation function for the namespace
|
||||
*/
|
||||
export function createElementNS(ns){
|
||||
const _this= this;
|
||||
return function createElementNSCurried(...rest){
|
||||
@ -92,9 +171,17 @@ export function createElementNS(ns){
|
||||
return el;
|
||||
};
|
||||
}
|
||||
|
||||
/** Alias for createElementNS */
|
||||
export { createElementNS as elNS };
|
||||
|
||||
/** @param {HTMLElement} element @param {HTMLElement} [root] */
|
||||
/**
|
||||
* Simulates slot functionality for elements
|
||||
*
|
||||
* @param {HTMLElement} element - Parent element
|
||||
* @param {HTMLElement} [root=element] - Root element containing slots
|
||||
* @returns {HTMLElement} The root element
|
||||
*/
|
||||
export function simulateSlots(element, root= element){
|
||||
const mark_e= "¹⁰", mark_s= "✓"; //NOTE: Markers to identify slots processed by this function. Also “prevents” native behavior as it is unlikely to use these in names. // editorconfig-checker-disable-line
|
||||
const slots= Object.fromEntries(
|
||||
@ -128,17 +215,34 @@ export function simulateSlots(element, root= element){
|
||||
return root;
|
||||
}
|
||||
|
||||
/** Store for element assignment contexts */
|
||||
const assign_context= new WeakMap();
|
||||
const { setDeleteAttr }= env;
|
||||
|
||||
/**
|
||||
* Assigns attributes to an element
|
||||
*
|
||||
* @param {Element} element - Element to assign attributes to
|
||||
* @param {...Object} attributes - Attribute objects to assign
|
||||
* @returns {Element} The element with attributes assigned
|
||||
*/
|
||||
export function assign(element, ...attributes){
|
||||
if(!attributes.length) return element;
|
||||
assign_context.set(element, assignContext(element, this));
|
||||
|
||||
for(const [ key, value ] of Object.entries(Object.assign({}, ...attributes)))
|
||||
for(const [ key, value ] of Object.entries(oAssign({}, ...attributes)))
|
||||
assignAttribute.call(this, element, key, value);
|
||||
assign_context.delete(element);
|
||||
return element;
|
||||
}
|
||||
/**
|
||||
* Assigns a single attribute to an element
|
||||
*
|
||||
* @param {Element} element - Element to assign attribute to
|
||||
* @param {string} key - Attribute name
|
||||
* @param {any} value - Attribute value
|
||||
* @returns {any} Result of the attribute assignment
|
||||
*/
|
||||
export function assignAttribute(element, key, value){
|
||||
const { setRemoveAttr, s }= assignContext(element, this);
|
||||
const _this= this;
|
||||
@ -170,13 +274,28 @@ export function assignAttribute(element, key, value){
|
||||
}
|
||||
return isPropSetter(element, key) ? setDeleteAttr(element, key, value) : setRemoveAttr(key, value);
|
||||
}
|
||||
/**
|
||||
* Gets or creates assignment context for an element
|
||||
*
|
||||
* @param {Element} element - Element to get context for
|
||||
* @param {Object} _this - Context object
|
||||
* @returns {Object} Assignment context
|
||||
* @private
|
||||
*/
|
||||
function assignContext(element, _this){
|
||||
if(assign_context.has(element)) return assign_context.get(element);
|
||||
const is_svg= element instanceof env.S;
|
||||
const is_svg= isInstance(element, env.S);
|
||||
const setRemoveAttr= (is_svg ? setRemoveNS : setRemove).bind(null, element, "Attribute");
|
||||
const s= signals(_this);
|
||||
return { setRemoveAttr, s };
|
||||
}
|
||||
/**
|
||||
* Applies a declarative classList object to an element
|
||||
*
|
||||
* @param {Element} element - Element to apply classes to
|
||||
* @param {Object} toggle - Object with class names as keys and boolean values
|
||||
* @returns {Element} The element with classes applied
|
||||
*/
|
||||
export function classListDeclarative(element, toggle){
|
||||
const s= signals(this);
|
||||
forEachEntries(s, "classList", element, toggle,
|
||||
@ -184,18 +303,45 @@ export function classListDeclarative(element, toggle){
|
||||
element.classList.toggle(class_name, val===-1 ? undefined : Boolean(val)) );
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic element attribute manipulation
|
||||
*
|
||||
* @param {Element} element - Element to manipulate
|
||||
* @param {string} op - Operation ("set" or "remove")
|
||||
* @param {string} key - Attribute name
|
||||
* @param {any} [value] - Attribute value
|
||||
* @returns {void}
|
||||
*/
|
||||
export function elementAttribute(element, op, key, value){
|
||||
if(element instanceof env.H)
|
||||
if(isInstance(element, env.H))
|
||||
return element[op+"Attribute"](key, value);
|
||||
return element[op+"AttributeNS"](null, key, value);
|
||||
}
|
||||
import { isUndef } from "./helpers.js";
|
||||
|
||||
//TODO: add cache? `(Map/Set)<el.tagName+key,isUndef>`
|
||||
/**
|
||||
* Checks if a property can be set on an element
|
||||
*
|
||||
* @param {Element} el - Element to check
|
||||
* @param {string} key - Property name
|
||||
* @returns {boolean} Whether the property can be set
|
||||
* @private
|
||||
*/
|
||||
function isPropSetter(el, key){
|
||||
if(!(key in el)) return false;
|
||||
const des= getPropDescriptor(el, key);
|
||||
return !isUndef(des.set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a property descriptor from a prototype chain
|
||||
*
|
||||
* @param {Object} p - Prototype object
|
||||
* @param {string} key - Property name
|
||||
* @returns {PropertyDescriptor} Property descriptor
|
||||
* @private
|
||||
*/
|
||||
function getPropDescriptor(p, key){
|
||||
p= Object.getPrototypeOf(p);
|
||||
if(!p) return {};
|
||||
@ -224,9 +370,44 @@ function forEachEntries(s, target, element, obj, cb){
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or removes an attribute based on value
|
||||
*
|
||||
* @param {Element} obj - Element to modify
|
||||
* @param {string} prop - Property suffix ("Attribute")
|
||||
* @param {string} key - Attribute name
|
||||
* @param {any} val - Attribute value
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function setRemove(obj, prop, key, val){
|
||||
return obj[ (isUndef(val) ? "remove" : "set") + prop ](key, val); }
|
||||
return obj[ (isUndef(val) ? "remove" : "set") + prop ](key, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or removes a namespaced attribute based on value
|
||||
*
|
||||
* @param {Element} obj - Element to modify
|
||||
* @param {string} prop - Property suffix ("Attribute")
|
||||
* @param {string} key - Attribute name
|
||||
* @param {any} val - Attribute value
|
||||
* @param {string|null} [ns=null] - Namespace URI
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function setRemoveNS(obj, prop, key, val, ns= null){
|
||||
return obj[ (isUndef(val) ? "remove" : "set") + prop + "NS" ](ns, key, val); }
|
||||
return obj[ (isUndef(val) ? "remove" : "set") + prop + "NS" ](ns, key, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or deletes a property based on value
|
||||
*
|
||||
* @param {Object} obj - Object to modify
|
||||
* @param {string} key - Property name
|
||||
* @param {any} val - Property value
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function setDelete(obj, key, val){
|
||||
Reflect.set(obj, key, val); if(!isUndef(val)) return; return Reflect.deleteProperty(obj, key); }
|
||||
Reflect.set(obj, key, val); if(!isUndef(val)) return; return Reflect.deleteProperty(obj, key);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user