1
0
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:
Jan Andrle 2025-03-07 14:40:45 +01:00 committed by GitHub
parent dba4e93b88
commit 4366027658
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
110 changed files with 16261 additions and 4741 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
dist/docs/
dist/.*
# Logs
logs
*.log

166
README.md
View File

@ -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: 1015kB 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

View File

@ -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
View 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);
}

View File

@ -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");

View File

@ -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
View 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

File diff suppressed because it is too large Load Diff

785
dist/dde-with-signals.min.d.ts vendored Normal file
View 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

File diff suppressed because one or more lines are too long

784
dist/dde.d.ts vendored Normal file
View 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

File diff suppressed because it is too large Load Diff

784
dist/dde.min.d.ts vendored Normal file
View 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

File diff suppressed because one or more lines are too long

641
dist/esm-with-signals.d.min.ts vendored Normal file
View 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>
}

File diff suppressed because it is too large Load Diff

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
View 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

File diff suppressed because one or more lines are too long

568
dist/esm.d.min.ts vendored Normal file
View 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
View File

@ -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
View File

@ -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
View 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

File diff suppressed because one or more lines are too long

60
docs/assets/favicon.svg Normal file
View 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
View 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

View File

@ -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;
}

View File

@ -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";
});
}

View File

@ -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;
}
}
`;

View File

@ -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);

View 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`)

View 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));

View File

@ -0,0 +1,4 @@
// Example of reactive element marker
<!--<dde:mark type=\"reactive\" source=\"...\">-->
<!-- content that updates when signal changes -->
<!--</dde:mark>-->

View 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");

View 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);

View 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")
)
);

View 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);

View 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);

View 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))
);

View 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)"
});

View 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))
);

View File

@ -0,0 +1,2 @@
// Standard DOM event listener approach
element.addEventListener('click', callback, options);

View File

@ -0,0 +1,7 @@
import { el } from "deka-dom-el";
// Using events with property assignment
el("button", {
textContent: "click me",
onclick: console.log
});

View 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;
}
});

View File

@ -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);
});

View File

@ -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: "🎉" })
);

View 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: "+",
})
)
);
}

View 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();
}

View File

@ -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 });
}

View File

@ -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!!!
* */
}

View 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"
})
);
}

View 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)
);

View File

@ -15,4 +15,4 @@ setTimeout(
clearInterval,
10*interval,
setInterval(oninterval, interval)
);
);

View File

@ -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*/:

View File

@ -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)

View 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

View 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

View 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"

View File

@ -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));

View File

@ -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));

View File

@ -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;

View 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();

View 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);

View 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";

View 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();
}

View 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();

View 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);

View 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;
}

View 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));
})
});
}

View File

@ -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> }))")
),
);
}

View File

@ -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
);
}

View File

@ -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;
}
`;

View File

@ -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`dont 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 (~1015kB 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!
`),
);
}

View File

@ -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" }),
);
}

View File

@ -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)
)
));

View File

@ -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`
Lets 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 elements ${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)
);

View File

@ -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)
);
}

View File

@ -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`
Lets 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`Publishsubscribe 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`Publishsubscribe 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)
);
}

View File

@ -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)
);

View File

@ -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, lets 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 components internal DOM tree
from the rest of the document. This means that styles and scripts applied to the document will not affect
the components 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
View 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
View 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
View 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
View 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.
`)
);
}

View File

@ -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
View File

@ -4,6 +4,7 @@ export type Info= {
id: string,
href: string,
title: string,
fullTitle: string,
description: string,
}
export type Pages=Info[];

View File

@ -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)
});

View File

@ -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(

View File

@ -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)
);

View File

@ -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" }),
);

View File

@ -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
View File

@ -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;

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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
View File

@ -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.

View File

@ -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);

View File

@ -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));
}

View File

@ -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";

View File

@ -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