mirror of
https://github.com/jaandrle/deka-dom-el
synced 2024-11-21 23:39:37 +01:00
🔨 mainly types + 💥 ddePublicElementTagNameMap
This commit is contained in:
parent
14fe70e8f6
commit
5c038f0427
16
dist/dde-with-signals.js
vendored
16
dist/dde-with-signals.js
vendored
File diff suppressed because one or more lines are too long
54
dist/esm-with-signals.d.ts
vendored
54
dist/esm-with-signals.d.ts
vendored
@ -1,9 +1,14 @@
|
|||||||
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
||||||
|
declare global {
|
||||||
|
interface ddePublicElementTagNameMap{
|
||||||
|
}
|
||||||
|
}
|
||||||
type SupportedElement=
|
type SupportedElement=
|
||||||
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
||||||
| SVGElementTagNameMap[keyof SVGElementTagNameMap]
|
| SVGElementTagNameMap[keyof SVGElementTagNameMap]
|
||||||
| MathMLElementTagNameMap[keyof MathMLElementTagNameMap]
|
| MathMLElementTagNameMap[keyof MathMLElementTagNameMap]
|
||||||
| CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
| CustomElementTagNameMap[keyof CustomElementTagNameMap]
|
||||||
|
| ddePublicElementTagNameMap[keyof ddePublicElementTagNameMap];
|
||||||
declare global {
|
declare global {
|
||||||
type ddeComponentAttributes= Record<any, any> | undefined | string;
|
type ddeComponentAttributes= Record<any, any> | undefined | string;
|
||||||
type ddeElementModifier<El extends SupportedElement | DocumentFragment>= (element: El)=> El;
|
type ddeElementModifier<El extends SupportedElement | DocumentFragment>= (element: El)=> El;
|
||||||
@ -36,7 +41,7 @@ type AttrsModified= {
|
|||||||
*/
|
*/
|
||||||
type ElementAttributes<T extends SupportedElement>= Omit<T,keyof AttrsModified> & AttrsModified;
|
type ElementAttributes<T extends SupportedElement>= Omit<T,keyof AttrsModified> & AttrsModified;
|
||||||
export function assign<El extends SupportedElement>(element: El, ...attrs_array: Partial<ElementAttributes<El>>[]): El
|
export function assign<El extends SupportedElement>(element: El, ...attrs_array: Partial<ElementAttributes<El>>[]): El
|
||||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap
|
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap
|
||||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(
|
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | Partial<ElementAttributes<ExtendedHTMLElementTagNameMap[TAG]>>,
|
attrs?: string | Partial<ElementAttributes<ExtendedHTMLElementTagNameMap[TAG]>>,
|
||||||
@ -81,6 +86,7 @@ export function elNS(
|
|||||||
export function dispatchEvent(element: SupportedElement, name: keyof DocumentEventMap): void;
|
export function dispatchEvent(element: SupportedElement, name: keyof DocumentEventMap): void;
|
||||||
export function dispatchEvent(element: SupportedElement, name: string, data: any): void;
|
export function dispatchEvent(element: SupportedElement, name: string, data: any): void;
|
||||||
interface On{
|
interface On{
|
||||||
|
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||||
<
|
<
|
||||||
EE extends ddeElementModifier<SupportedElement>,
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never ),
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never ),
|
||||||
@ -89,6 +95,7 @@ interface On{
|
|||||||
listener: (this: El, ev: DocumentEventMap[Event]) => any,
|
listener: (this: El, ev: DocumentEventMap[Event]) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
|
/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
||||||
connected<
|
connected<
|
||||||
EE extends ddeElementModifier<SupportedElement>,
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||||
@ -96,6 +103,7 @@ interface On{
|
|||||||
listener: (el: El) => any,
|
listener: (el: El) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
|
/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
||||||
disconnected<
|
disconnected<
|
||||||
EE extends ddeElementModifier<SupportedElement>,
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||||
@ -103,10 +111,36 @@ interface On{
|
|||||||
listener: (el: El) => any,
|
listener: (el: El) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
|
/** Listens to the element attribute changes. In case of custom elements uses [`attributeChangedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
||||||
|
attributeChanged<
|
||||||
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||||
|
>(
|
||||||
|
listener: (el: El) => any,
|
||||||
|
options?: AddEventListenerOptions
|
||||||
|
) : EE;
|
||||||
}
|
}
|
||||||
export const on: On;
|
export const on: On;
|
||||||
|
type Scope= { scope: Node | Function | Object, host: ddeElementModifier<any>, prevent: boolean }
|
||||||
|
/** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */
|
||||||
export const scope: {
|
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 Modifier (function to be called when component is initized)
|
||||||
|
* — `scope.host(on.connected(console.log))`.
|
||||||
|
* */
|
||||||
host: ddeElementModifier<any>,
|
host: ddeElementModifier<any>,
|
||||||
|
|
||||||
|
state: Scope[],
|
||||||
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
|
push(scope: Partial<Scope>): ReturnType<Array<Scope>["push"]>
|
||||||
|
/** Removes last/current child scope. */
|
||||||
|
pop(): ReturnType<Array<Scope>["pop"]>
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* TODO TypeScript HACK (better way?)
|
* TODO TypeScript HACK (better way?)
|
||||||
@ -430,6 +464,10 @@ interface S {
|
|||||||
* by `S.clear`.
|
* by `S.clear`.
|
||||||
* */
|
* */
|
||||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||||
|
/**
|
||||||
|
* Computations signal. This creates a signal which is computed from other signals.
|
||||||
|
* */
|
||||||
|
<V>(computation: ()=> V): Signal<V, {}>
|
||||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(
|
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(
|
||||||
signal: S,
|
signal: S,
|
||||||
name: N,
|
name: N,
|
||||||
@ -441,7 +479,17 @@ interface S {
|
|||||||
signal: SymbolSignal;
|
signal: SymbolSignal;
|
||||||
onclear: SymbolOnclear;
|
onclear: SymbolOnclear;
|
||||||
}
|
}
|
||||||
el<S extends any, T extends HTMLElement>(signal: Signal<S, any>, el: (v: S)=> T): T;
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/** Mirrors element attributes for current host (both way). */
|
||||||
|
attribute<T>(name: string, initial?: T): Signal<T, {}>
|
||||||
}
|
}
|
||||||
export const S: S;
|
export const S: S;
|
||||||
declare global {
|
declare global {
|
||||||
|
8
dist/esm-with-signals.js
vendored
8
dist/esm-with-signals.js
vendored
File diff suppressed because one or more lines are too long
38
dist/esm.d.ts
vendored
38
dist/esm.d.ts
vendored
@ -1,9 +1,14 @@
|
|||||||
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
||||||
|
declare global {
|
||||||
|
interface ddePublicElementTagNameMap{
|
||||||
|
}
|
||||||
|
}
|
||||||
type SupportedElement=
|
type SupportedElement=
|
||||||
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
||||||
| SVGElementTagNameMap[keyof SVGElementTagNameMap]
|
| SVGElementTagNameMap[keyof SVGElementTagNameMap]
|
||||||
| MathMLElementTagNameMap[keyof MathMLElementTagNameMap]
|
| MathMLElementTagNameMap[keyof MathMLElementTagNameMap]
|
||||||
| CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
| CustomElementTagNameMap[keyof CustomElementTagNameMap]
|
||||||
|
| ddePublicElementTagNameMap[keyof ddePublicElementTagNameMap];
|
||||||
declare global {
|
declare global {
|
||||||
type ddeComponentAttributes= Record<any, any> | undefined | string;
|
type ddeComponentAttributes= Record<any, any> | undefined | string;
|
||||||
type ddeElementModifier<El extends SupportedElement | DocumentFragment>= (element: El)=> El;
|
type ddeElementModifier<El extends SupportedElement | DocumentFragment>= (element: El)=> El;
|
||||||
@ -36,7 +41,7 @@ type AttrsModified= {
|
|||||||
*/
|
*/
|
||||||
type ElementAttributes<T extends SupportedElement>= Omit<T,keyof AttrsModified> & AttrsModified;
|
type ElementAttributes<T extends SupportedElement>= Omit<T,keyof AttrsModified> & AttrsModified;
|
||||||
export function assign<El extends SupportedElement>(element: El, ...attrs_array: Partial<ElementAttributes<El>>[]): El
|
export function assign<El extends SupportedElement>(element: El, ...attrs_array: Partial<ElementAttributes<El>>[]): El
|
||||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap
|
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap
|
||||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(
|
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | Partial<ElementAttributes<ExtendedHTMLElementTagNameMap[TAG]>>,
|
attrs?: string | Partial<ElementAttributes<ExtendedHTMLElementTagNameMap[TAG]>>,
|
||||||
@ -81,6 +86,7 @@ export function elNS(
|
|||||||
export function dispatchEvent(element: SupportedElement, name: keyof DocumentEventMap): void;
|
export function dispatchEvent(element: SupportedElement, name: keyof DocumentEventMap): void;
|
||||||
export function dispatchEvent(element: SupportedElement, name: string, data: any): void;
|
export function dispatchEvent(element: SupportedElement, name: string, data: any): void;
|
||||||
interface On{
|
interface On{
|
||||||
|
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||||
<
|
<
|
||||||
EE extends ddeElementModifier<SupportedElement>,
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never ),
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never ),
|
||||||
@ -89,6 +95,7 @@ interface On{
|
|||||||
listener: (this: El, ev: DocumentEventMap[Event]) => any,
|
listener: (this: El, ev: DocumentEventMap[Event]) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
|
/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
||||||
connected<
|
connected<
|
||||||
EE extends ddeElementModifier<SupportedElement>,
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||||
@ -96,6 +103,7 @@ interface On{
|
|||||||
listener: (el: El) => any,
|
listener: (el: El) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
|
/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
||||||
disconnected<
|
disconnected<
|
||||||
EE extends ddeElementModifier<SupportedElement>,
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||||
@ -103,10 +111,36 @@ interface On{
|
|||||||
listener: (el: El) => any,
|
listener: (el: El) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
|
/** Listens to the element attribute changes. In case of custom elements uses [`attributeChangedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
||||||
|
attributeChanged<
|
||||||
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||||
|
>(
|
||||||
|
listener: (el: El) => any,
|
||||||
|
options?: AddEventListenerOptions
|
||||||
|
) : EE;
|
||||||
}
|
}
|
||||||
export const on: On;
|
export const on: On;
|
||||||
|
type Scope= { scope: Node | Function | Object, host: ddeElementModifier<any>, prevent: boolean }
|
||||||
|
/** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */
|
||||||
export const scope: {
|
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 Modifier (function to be called when component is initized)
|
||||||
|
* — `scope.host(on.connected(console.log))`.
|
||||||
|
* */
|
||||||
host: ddeElementModifier<any>,
|
host: ddeElementModifier<any>,
|
||||||
|
|
||||||
|
state: Scope[],
|
||||||
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
|
push(scope: Partial<Scope>): ReturnType<Array<Scope>["push"]>
|
||||||
|
/** Removes last/current child scope. */
|
||||||
|
pop(): ReturnType<Array<Scope>["pop"]>
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* TODO TypeScript HACK (better way?)
|
* TODO TypeScript HACK (better way?)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="elements.css"><meta name="description" content="Basic concepts of elements modifications and creations."><!--<dde:mark type="component" name="metaTwitter" host="this"/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this"/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><title>`deka-dom-el` — Elements</title><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script></head><body><!--<dde:mark type="component" name="page" host="this"/>--><!--<dde:mark type="component" name="header" host="this"/>--><header><h1>`deka-dom-el` — Elements</h1><p>Basic concepts of elements modifications and creations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewbox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement"/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a library and motivations.">1. Introduction</a><a href="elements" title="Basic concepts of elements modifications and creations." class="current">2. Elements</a></nav><main><h2>Native JavaScript DOM elements creations</h2><p>Let’s go through all patterns we would like to use and what needs to be improved for better experience.</p><h3>Creating element(s) (with custom attributes)</h3><p>You can create a native DOM element by using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement" title="MDN documentation for document.createElement()"><code>document.createElement()</code></a>. It is also possible to provide a some attribute(s) declaratively using <code>Object.assign()</code>. More precisely, this way you can sets some <a href="https://developer.mozilla.org/en-US/docs/Glossary/IDL" title="MDN page about Interface Description Language"><abbr title="Interface Description Language">IDL</abbr></a>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-zxdx3" class="example"><pre><code class="language-javascript">document.body.append(
|
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="elements.css"><meta name="description" content="Basic concepts of elements modifications and creations."><!--<dde:mark type="component" name="metaTwitter" host="this"/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this"/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><title>`deka-dom-el` — Elements</title><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script></head><body><!--<dde:mark type="component" name="page" host="this"/>--><!--<dde:mark type="component" name="header" host="this"/>--><header><h1>`deka-dom-el` — Elements</h1><p>Basic concepts of elements modifications and creations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewbox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement"/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a library and motivations.">1. Introduction</a><a href="elements" title="Basic concepts of elements modifications and creations." class="current">2. Elements</a></nav><main><h2>Native JavaScript DOM elements creations</h2><p>Let’s go through all patterns we would like to use and what needs to be improved for better experience.</p><h3>Creating element(s) (with custom attributes)</h3><p>You can create a native DOM element by using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement" title="MDN documentation for document.createElement()"><code>document.createElement()</code></a>. It is also possible to provide a some attribute(s) declaratively using <code>Object.assign()</code>. More precisely, this way you can sets some <a href="https://developer.mozilla.org/en-US/docs/Glossary/IDL" title="MDN page about Interface Description Language"><abbr title="Interface Description Language">IDL</abbr></a>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-m4hdt" class="example"><pre><code class="language-javascript">document.body.append(
|
||||||
document.createElement("div")
|
document.createElement("div")
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
@ -12,7 +12,7 @@ document.body.append(
|
|||||||
{ textContent: "Element’s text content.", style: "color: coral;" }
|
{ textContent: "Element’s text content.", style: "color: coral;" }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
</code></pre></div><script>Flems(document.getElementById("code-zxdx3"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"document.body.append(\\n\\tdocument.createElement(\\\"div\\\")\\n);\\nconsole.log(\\n\\t\\\"Emty div is generated inside <body>:\\\",\\n\\tdocument.body.innerHTML.includes(\\\"<div></div>\\\")\\n);\\n\\ndocument.body.append(\\n\\tObject.assign(\\n\\t\\tdocument.createElement(\\\"p\\\"),\\n\\t\\t{ textContent: \\\"Element’s text content.\\\", style: \\\"color: coral;\\\" }\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><p>To make this easier, you can use the <code>el</code> function. Internally in basic examples, it is wrapper around <code>assign(document.createElement(…), { … })</code>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-98ya3" class="example"><pre><code class="language-javascript">import { el, assign } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
</code></pre></div><script>Flems(document.getElementById("code-m4hdt"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"document.body.append(\\n\\tdocument.createElement(\\\"div\\\")\\n);\\nconsole.log(\\n\\t\\\"Emty div is generated inside <body>:\\\",\\n\\tdocument.body.innerHTML.includes(\\\"<div></div>\\\")\\n);\\n\\ndocument.body.append(\\n\\tObject.assign(\\n\\t\\tdocument.createElement(\\\"p\\\"),\\n\\t\\t{ textContent: \\\"Element’s text content.\\\", style: \\\"color: coral;\\\" }\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><p>To make this easier, you can use the <code>el</code> function. Internally in basic examples, it is wrapper around <code>assign(document.createElement(…), { … })</code>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-5855d" class="example"><pre><code class="language-javascript">import { el, assign } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
||||||
const color= "lightcoral";
|
const color= "lightcoral";
|
||||||
document.body.append(
|
document.body.append(
|
||||||
el("p", { textContent: "Hello (first time)", style: { color } })
|
el("p", { textContent: "Hello (first time)", style: { color } })
|
||||||
@ -23,7 +23,7 @@ document.body.append(
|
|||||||
{ textContent: "Hello (second time)", style: { color } }
|
{ textContent: "Hello (second time)", style: { color } }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
</code></pre></div><script>Flems(document.getElementById("code-98ya3"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, assign } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst color= \\\"lightcoral\\\";\\ndocument.body.append(\\n\\tel(\\\"p\\\", { textContent: \\\"Hello (first time)\\\", style: { color } })\\n);\\ndocument.body.append(\\n\\tassign(\\n\\t\\tdocument.createElement(\\\"p\\\"),\\n\\t\\t{ textContent: \\\"Hello (second time)\\\", style: { color } }\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><p>The <code>assign</code> function provides improved behaviour of <code>Object.assign()</code>. You can declaratively sets any IDL and attribute of the given element. Function prefers IDL and fallback to the <code>element.setAttribute</code> if there is no writable property in the element prototype.</p><p>You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements inherits from <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement">HTMLElement</a>. To see all available IDLs for example for paragraphs, see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement">HTMLParagraphElement</a>. Moreover, the <code>assign</code> provides a way to sets declaratively some convenient properties:</p><ul><li>It is possible to sets <code>data-*</code>/<code>aria-*</code> attributes using object notation.</li><li>In opposite, it is also possible to sets <code>data-*</code>/<code>aria-*</code> attribute using camelCase notation.</li><li>You can use string or object as a value for <code>style</code> property.</li><li><code>className</code> (IDL – preffered)/<code>class</code> are ways to add CSS class to the element. You can use string (similarly to <code>class="…"</code> syntax in HTML) or array of strings. This is handy to concat conditional classes.</li><li>Use <code>classList</code> to toggle specific classes. This will be handy later when the reactivity via signals is beeing introduced.</li><li>The <code>assign</code> also accepts the <code>undefined</code> as a value for any property to remove it from the element declaratively. Also for some IDL the corresponding attribute is removed as it can be confusing. <em>For example, natievly the element’s <code>id</code> is removed by setting the IDL to an empty string.</em></li></ul><p>For processing, the <code>assign</code> internally uses <code>assignAttribute</code> and <code>classListDeclarative</code>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-bfx2a" class="example"><pre><code class="language-javascript">import { assignAttribute, classListDeclarative } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
</code></pre></div><script>Flems(document.getElementById("code-5855d"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, assign } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst color= \\\"lightcoral\\\";\\ndocument.body.append(\\n\\tel(\\\"p\\\", { textContent: \\\"Hello (first time)\\\", style: { color } })\\n);\\ndocument.body.append(\\n\\tassign(\\n\\t\\tdocument.createElement(\\\"p\\\"),\\n\\t\\t{ textContent: \\\"Hello (second time)\\\", style: { color } }\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><p>The <code>assign</code> function provides improved behaviour of <code>Object.assign()</code>. You can declaratively sets any IDL and attribute of the given element. Function prefers IDL and fallback to the <code>element.setAttribute</code> if there is no writable property in the element prototype.</p><p>You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements inherits from <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement">HTMLElement</a>. To see all available IDLs for example for paragraphs, see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement">HTMLParagraphElement</a>. Moreover, the <code>assign</code> provides a way to sets declaratively some convenient properties:</p><ul><li>It is possible to sets <code>data-*</code>/<code>aria-*</code> attributes using object notation.</li><li>In opposite, it is also possible to sets <code>data-*</code>/<code>aria-*</code> attribute using camelCase notation.</li><li>You can use string or object as a value for <code>style</code> property.</li><li><code>className</code> (IDL – preffered)/<code>class</code> are ways to add CSS class to the element. You can use string (similarly to <code>class="…"</code> syntax in HTML) or array of strings. This is handy to concat conditional classes.</li><li>Use <code>classList</code> to toggle specific classes. This will be handy later when the reactivity via signals is beeing introduced.</li><li>The <code>assign</code> also accepts the <code>undefined</code> as a value for any property to remove it from the element declaratively. Also for some IDL the corresponding attribute is removed as it can be confusing. <em>For example, natievly the element’s <code>id</code> is removed by setting the IDL to an empty string.</em></li></ul><p>For processing, the <code>assign</code> internally uses <code>assignAttribute</code> and <code>classListDeclarative</code>.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-5f8sp" class="example"><pre><code class="language-javascript">import { assignAttribute, classListDeclarative } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
||||||
const paragraph= document.createElement("p");
|
const paragraph= document.createElement("p");
|
||||||
|
|
||||||
assignAttribute(paragraph, "textContent", "Hello, world!");
|
assignAttribute(paragraph, "textContent", "Hello, world!");
|
||||||
@ -48,7 +48,7 @@ console.log(paragraph.outerHTML);
|
|||||||
document.body.append(
|
document.body.append(
|
||||||
paragraph
|
paragraph
|
||||||
);
|
);
|
||||||
</code></pre></div><script>Flems(document.getElementById("code-bfx2a"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { assignAttribute, classListDeclarative } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst paragraph= document.createElement(\\\"p\\\");\\n\\nassignAttribute(paragraph, \\\"textContent\\\", \\\"Hello, world!\\\");\\nassignAttribute(paragraph, \\\"style\\\", { color: \\\"navy\\\" });\\n\\nassignAttribute(paragraph, \\\"dataTest1\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"dataset\\\", { test2: \\\"v2\\\" });\\n\\nassignAttribute(paragraph, \\\"ariaLabel\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"ariaset\\\", { role: \\\"none\\\" });\\n\\n\\nclassListDeclarative(paragraph, {\\n\\tclassAdd: true,\\n\\tclassRemove: false,\\n\\tclassAdd1: 1,\\n\\tclassRemove1: 0,\\n\\tclassToggle: -1\\n});\\n\\nconsole.log(paragraph.outerHTML);\\ndocument.body.append(\\n\\tparagraph\\n);\\n\"}],\"toolbar\":false}"));</script><h3>Native JavaScript templating</h3><p>By default, the native JS has no good way to define HTML template using DOM API:</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-0enam" class="example"><pre><code class="language-javascript">document.body.append(
|
</code></pre></div><script>Flems(document.getElementById("code-5f8sp"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { assignAttribute, classListDeclarative } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst paragraph= document.createElement(\\\"p\\\");\\n\\nassignAttribute(paragraph, \\\"textContent\\\", \\\"Hello, world!\\\");\\nassignAttribute(paragraph, \\\"style\\\", { color: \\\"navy\\\" });\\n\\nassignAttribute(paragraph, \\\"dataTest1\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"dataset\\\", { test2: \\\"v2\\\" });\\n\\nassignAttribute(paragraph, \\\"ariaLabel\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"ariaset\\\", { role: \\\"none\\\" });\\n\\n\\nclassListDeclarative(paragraph, {\\n\\tclassAdd: true,\\n\\tclassRemove: false,\\n\\tclassAdd1: 1,\\n\\tclassRemove1: 0,\\n\\tclassToggle: -1\\n});\\n\\nconsole.log(paragraph.outerHTML);\\ndocument.body.append(\\n\\tparagraph\\n);\\n\"}],\"toolbar\":false}"));</script><h3>Native JavaScript templating</h3><p>By default, the native JS has no good way to define HTML template using DOM API:</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-48dwd" class="example"><pre><code class="language-javascript">document.body.append(
|
||||||
document.createElement("div"),
|
document.createElement("div"),
|
||||||
document.createElement("span"),
|
document.createElement("span"),
|
||||||
document.createElement("main")
|
document.createElement("main")
|
||||||
@ -59,7 +59,7 @@ const template= document.createElement("main").append(
|
|||||||
document.createElement("span"),
|
document.createElement("span"),
|
||||||
);
|
);
|
||||||
console.log(typeof template==="undefined");
|
console.log(typeof template==="undefined");
|
||||||
</code></pre></div><script>Flems(document.getElementById("code-0enam"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"document.body.append(\\n\\tdocument.createElement(\\\"div\\\"),\\n\\tdocument.createElement(\\\"span\\\"),\\n\\tdocument.createElement(\\\"main\\\")\\n);\\nconsole.log(document.body.innerHTML.includes(\\\"<div></div><span></span><main></main>\\\"));\\nconst template= document.createElement(\\\"main\\\").append(\\n\\tdocument.createElement(\\\"div\\\"),\\n\\tdocument.createElement(\\\"span\\\"),\\n);\\nconsole.log(typeof template===\\\"undefined\\\");\\n\"}],\"toolbar\":false}"));</script><p>This library therefore overwrites the <code>append</code> method of created elements to always return parent element.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-dvz29" class="example"><pre><code class="language-javascript">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
</code></pre></div><script>Flems(document.getElementById("code-48dwd"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"document.body.append(\\n\\tdocument.createElement(\\\"div\\\"),\\n\\tdocument.createElement(\\\"span\\\"),\\n\\tdocument.createElement(\\\"main\\\")\\n);\\nconsole.log(document.body.innerHTML.includes(\\\"<div></div><span></span><main></main>\\\"));\\nconst template= document.createElement(\\\"main\\\").append(\\n\\tdocument.createElement(\\\"div\\\"),\\n\\tdocument.createElement(\\\"span\\\"),\\n);\\nconsole.log(typeof template===\\\"undefined\\\");\\n\"}],\"toolbar\":false}"));</script><p>This library therefore overwrites the <code>append</code> method of created elements to always return parent element.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-k8b3j" class="example"><pre><code class="language-javascript">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
||||||
document.head.append(
|
document.head.append(
|
||||||
el("style").append(
|
el("style").append(
|
||||||
"tr, td{ border: 1px solid red; padding: 1em; }",
|
"tr, td{ border: 1px solid red; padding: 1em; }",
|
||||||
@ -83,7 +83,7 @@ document.body.append(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
</code></pre></div><script>Flems(document.getElementById("code-dvz29"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\"tr, td{ border: 1px solid red; padding: 1em; }\\\",\\n\\t\\t\\\"table{ border-collapse: collapse; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(\\\"p\\\", \\\"Example of a complex template. Using for example nesting lists:\\\"),\\n\\tel(\\\"ul\\\").append(\\n\\t\\tel(\\\"li\\\", \\\"List item 1\\\"),\\n\\t\\tel(\\\"li\\\").append(\\n\\t\\t\\tel(\\\"ul\\\").append(\\n\\t\\t\\t\\tel(\\\"li\\\", \\\"Nested list item 1\\\"),\\n\\t\\t\\t)\\n\\t\\t)\\n\\t),\\n\\tel(\\\"table\\\").append(\\n\\t\\tel(\\\"tr\\\").append(\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 – Col 1\\\"),\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 – Col 2\\\")\\n\\t\\t)\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><h2>Creating advanced (reactive) templates and components</h2><h3>Basic components</h3><p>You can use functions for encapsulation (repeating) logic. The <code>el</code> accepts function as first argument. In that case, the function should return dom elements and the second argument for <code>el</code> is argument for given element.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-4r8hj" class="example"><pre><code class="language-javascript">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
</code></pre></div><script>Flems(document.getElementById("code-k8b3j"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\"tr, td{ border: 1px solid red; padding: 1em; }\\\",\\n\\t\\t\\\"table{ border-collapse: collapse; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(\\\"p\\\", \\\"Example of a complex template. Using for example nesting lists:\\\"),\\n\\tel(\\\"ul\\\").append(\\n\\t\\tel(\\\"li\\\", \\\"List item 1\\\"),\\n\\t\\tel(\\\"li\\\").append(\\n\\t\\t\\tel(\\\"ul\\\").append(\\n\\t\\t\\t\\tel(\\\"li\\\", \\\"Nested list item 1\\\"),\\n\\t\\t\\t)\\n\\t\\t)\\n\\t),\\n\\tel(\\\"table\\\").append(\\n\\t\\tel(\\\"tr\\\").append(\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 – Col 1\\\"),\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 – Col 2\\\")\\n\\t\\t)\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><h2>Creating advanced (reactive) templates and components</h2><h3>Basic components</h3><p>You can use functions for encapsulation (repeating) logic. The <code>el</code> accepts function as first argument. In that case, the function should return dom elements and the second argument for <code>el</code> is argument for given element.</p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-4qwvd" class="example"><pre><code class="language-javascript">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
||||||
document.head.append(
|
document.head.append(
|
||||||
el("style").append(
|
el("style").append(
|
||||||
".class1{ font-weight: bold; }",
|
".class1{ font-weight: bold; }",
|
||||||
@ -100,4 +100,4 @@ function component({ className, textContent }){
|
|||||||
el("p", textContent)
|
el("p", textContent)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
</code></pre></div><script>Flems(document.getElementById("code-4r8hj"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\".class1{ font-weight: bold; }\\\",\\n\\t\\t\\\".class2{ color: purple; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(component, { className: \\\"class2\\\", textContent: \\\"Hello World!\\\" }),\\n\\tcomponent({ className: \\\"class2\\\", textContent: \\\"Hello World!\\\" })\\n);\\n\\nfunction component({ className, textContent }){\\n\\treturn el(\\\"div\\\", { className: [ \\\"class1\\\", className ] }).append(\\n\\t\\tel(\\\"p\\\", textContent)\\n\\t);\\n}\\n\"}],\"toolbar\":false}"));</script><p>It is nice to use similar naming convention as native DOM API.</p></main></body></html>
|
</code></pre></div><script>Flems(document.getElementById("code-4qwvd"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\".class1{ font-weight: bold; }\\\",\\n\\t\\t\\\".class2{ color: purple; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(component, { className: \\\"class2\\\", textContent: \\\"Hello World!\\\" }),\\n\\tcomponent({ className: \\\"class2\\\", textContent: \\\"Hello World!\\\" })\\n);\\n\\nfunction component({ className, textContent }){\\n\\treturn el(\\\"div\\\", { className: [ \\\"class1\\\", className ] }).append(\\n\\t\\tel(\\\"p\\\", textContent)\\n\\t);\\n}\\n\"}],\"toolbar\":false}"));</script><p>It is nice to use similar naming convention as native DOM API.</p></main></body></html>
|
@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="index.css"><meta name="description" content="Introducing a library and motivations."><!--<dde:mark type="component" name="metaTwitter" host="this"/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this"/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><title>`deka-dom-el` — Introduction</title><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script></head><body><!--<dde:mark type="component" name="page" host="this"/>--><!--<dde:mark type="component" name="header" host="this"/>--><header><h1>`deka-dom-el` — Introduction</h1><p>Introducing a library and motivations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewbox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement"/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a library and motivations." class="current">1. Introduction</a><a href="elements" title="Basic concepts of elements modifications and creations.">2. Elements</a></nav><main><p>The library tries to provide pure JavaScript tool(s) to create reactive interfaces. </p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-pzi4k" class="example"><pre><code class="language-javascript">import { el, S } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="index.css"><meta name="description" content="Introducing a library and motivations."><!--<dde:mark type="component" name="metaTwitter" host="this"/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this"/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><title>`deka-dom-el` — Introduction</title><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script></head><body><!--<dde:mark type="component" name="page" host="this"/>--><!--<dde:mark type="component" name="header" host="this"/>--><header><h1>`deka-dom-el` — Introduction</h1><p>Introducing a library and motivations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewbox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement"/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a library and motivations." class="current">1. Introduction</a><a href="elements" title="Basic concepts of elements modifications and creations.">2. Elements</a></nav><main><p>The library tries to provide pure JavaScript tool(s) to create reactive interfaces. </p><!--<dde:mark type="component" name="example" host="this"/>--><div id="code-duj4w" class="example"><pre><code class="language-javascript">import { el, S } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
|
||||||
const clicks= S(0);
|
const clicks= S(0);
|
||||||
document.body.append(
|
document.body.append(
|
||||||
el().append(
|
el().append(
|
||||||
@ -12,4 +12,4 @@ document.body.append(
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
</code></pre></div><script>Flems(document.getElementById("code-pzi4k"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, S } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst clicks= S(0);\\ndocument.body.append(\\n\\tel().append(\\n\\t\\tel(\\\"p\\\", S(()=>\\n\\t\\t\\t\\\"Hello World \\\"+\\\"🎉\\\".repeat(clicks())\\n\\t\\t)),\\n\\t\\tel(\\\"button\\\", {\\n\\t\\t\\ttype: \\\"button\\\",\\n\\t\\t\\tonclick: ()=> clicks(clicks()+1),\\n\\t\\t\\ttextContent: \\\"Fire\\\"\\n\\t\\t})\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script></main></body></html>
|
</code></pre></div><script>Flems(document.getElementById("code-duj4w"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, S } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst clicks= S(0);\\ndocument.body.append(\\n\\tel().append(\\n\\t\\tel(\\\"p\\\", S(()=>\\n\\t\\t\\t\\\"Hello World \\\"+\\\"🎉\\\".repeat(clicks())\\n\\t\\t)),\\n\\t\\tel(\\\"button\\\", {\\n\\t\\t\\ttype: \\\"button\\\",\\n\\t\\t\\tonclick: ()=> clicks(clicks()+1),\\n\\t\\t\\ttextContent: \\\"Fire\\\"\\n\\t\\t})\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script></main></body></html>
|
6
docs_src/types.d.ts
vendored
6
docs_src/types.d.ts
vendored
@ -19,3 +19,9 @@ export type PageAttrs= {
|
|||||||
registerClientFile: registerClientFile
|
registerClientFile: registerClientFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import type { CustomHTMLTestElement } from "../examples/components/webComponent.js";
|
||||||
|
declare global{
|
||||||
|
interface ddePublicElementTagNameMap{
|
||||||
|
["custom-test"]: CustomHTMLTestElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
import { el, scope } from "../../index.js";
|
import { el, on, scope } from "../../index.js";
|
||||||
import { S } from "../../signals.js";
|
import { S } from "../../signals.js";
|
||||||
const { hasOwnProperty }= Object.prototype;
|
const { hasOwnProperty }= Object.prototype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef CustomHTMLTestElementInterface
|
||||||
|
* @type {object}
|
||||||
|
* @property {string} name
|
||||||
|
* */
|
||||||
/**
|
/**
|
||||||
* Compatible with `npx-wca test/components/webComponent.js`
|
* Compatible with `npx-wca test/components/webComponent.js`
|
||||||
* */
|
* */
|
||||||
export class CustomHTMLTestElement extends HTMLElement{
|
export class CustomHTMLTestElement extends HTMLElement{
|
||||||
|
static tagName= "custom-test";
|
||||||
static get observedAttributes(){
|
static get observedAttributes(){
|
||||||
return [ "name", "pre-name" ];
|
return [ "name", "pre-name" ];
|
||||||
}
|
}
|
||||||
@ -28,16 +34,18 @@ export class CustomHTMLTestElement extends HTMLElement{
|
|||||||
el("#text", { textContent: name }),
|
el("#text", { textContent: name }),
|
||||||
el("#text", { textContent: test }),
|
el("#text", { textContent: test }),
|
||||||
el("#text", { textContent: preName }),
|
el("#text", { textContent: preName }),
|
||||||
|
el("button", { type: "button", textContent: "pre-name", onclick: ()=> preName("Ahoj") })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get name(){ return this.getAttribute("name"); }
|
||||||
|
set name(value){ this.setAttribute("name", value); }
|
||||||
|
get preName(){ return this.getAttribute("pre-name"); }
|
||||||
|
set preName(value){ this.setAttribute("pre-name", value); }
|
||||||
}
|
}
|
||||||
// https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4
|
// https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4
|
||||||
customElementsAssign(
|
lifecycleToEvents(CustomHTMLTestElement)
|
||||||
CustomHTMLTestElement,
|
customElements.define(CustomHTMLTestElement.tagName, CustomHTMLTestElement);
|
||||||
reflectObservedAttributes,
|
|
||||||
lifecycleToEvents,
|
|
||||||
);
|
|
||||||
customElements.define("custom-test", CustomHTMLTestElement);
|
|
||||||
|
|
||||||
function customElementRender(_this, render){
|
function customElementRender(_this, render){
|
||||||
scope.push({ scope: _this, host: (...a)=> a.length ? a[0](_this) : _this });
|
scope.push({ scope: _this, host: (...a)=> a.length ? a[0](_this) : _this });
|
||||||
@ -45,21 +53,6 @@ function customElementRender(_this, render){
|
|||||||
scope.pop();
|
scope.pop();
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
/** @returns {HTMLElement} */
|
|
||||||
function customElementsAssign(class_base, ...automatize){
|
|
||||||
automatize.forEach(a=> a(class_base));
|
|
||||||
}
|
|
||||||
function reflectObservedAttributes(c){
|
|
||||||
for(const name of c.observedAttributes){
|
|
||||||
const name_camel= name.replace(/([a-z])-([a-z])/g, (_, l, r)=> l+r.toUpperCase());
|
|
||||||
if(hasOwnProperty.call(c.prototype, name_camel))
|
|
||||||
continue;
|
|
||||||
Reflect.defineProperty(c.prototype, name_camel, {
|
|
||||||
get(){ return this.getAttribute(name); },
|
|
||||||
set(value){ this.setAttribute(name, value); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function lifecycleToEvents(class_declaration){
|
function lifecycleToEvents(class_declaration){
|
||||||
for (const name of [ "connected", "disconnected" ])
|
for (const name of [ "connected", "disconnected" ])
|
||||||
wrapMethod(class_declaration.prototype, name+"Callback", function(target, thisArg, detail){
|
wrapMethod(class_declaration.prototype, name+"Callback", function(target, thisArg, detail){
|
||||||
|
@ -8,5 +8,5 @@ document.body.append(
|
|||||||
el("h1", "Experiments:"),
|
el("h1", "Experiments:"),
|
||||||
el(fullNameComponent),
|
el(fullNameComponent),
|
||||||
el(todosComponent),
|
el(todosComponent),
|
||||||
el(customElements.getName(CustomHTMLTestElement), { name: "attr" })
|
el(CustomHTMLTestElement.tagName, { name: "attr" })
|
||||||
);
|
);
|
||||||
|
38
index.d.ts
vendored
38
index.d.ts
vendored
@ -1,9 +1,14 @@
|
|||||||
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
type CustomElementTagNameMap= { '#text': Text, '#comment': Comment }
|
||||||
|
declare global {
|
||||||
|
interface ddePublicElementTagNameMap{
|
||||||
|
}
|
||||||
|
}
|
||||||
type SupportedElement=
|
type SupportedElement=
|
||||||
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
|
||||||
| SVGElementTagNameMap[keyof SVGElementTagNameMap]
|
| SVGElementTagNameMap[keyof SVGElementTagNameMap]
|
||||||
| MathMLElementTagNameMap[keyof MathMLElementTagNameMap]
|
| MathMLElementTagNameMap[keyof MathMLElementTagNameMap]
|
||||||
| CustomElementTagNameMap[keyof CustomElementTagNameMap];
|
| CustomElementTagNameMap[keyof CustomElementTagNameMap]
|
||||||
|
| ddePublicElementTagNameMap[keyof ddePublicElementTagNameMap];
|
||||||
declare global {
|
declare global {
|
||||||
type ddeComponentAttributes= Record<any, any> | undefined | string;
|
type ddeComponentAttributes= Record<any, any> | undefined | string;
|
||||||
type ddeElementModifier<El extends SupportedElement | DocumentFragment>= (element: El)=> El;
|
type ddeElementModifier<El extends SupportedElement | DocumentFragment>= (element: El)=> El;
|
||||||
@ -37,7 +42,7 @@ type AttrsModified= {
|
|||||||
type ElementAttributes<T extends SupportedElement>= Omit<T,keyof AttrsModified> & AttrsModified;
|
type ElementAttributes<T extends SupportedElement>= Omit<T,keyof AttrsModified> & AttrsModified;
|
||||||
export function assign<El extends SupportedElement>(element: El, ...attrs_array: Partial<ElementAttributes<El>>[]): El
|
export function assign<El extends SupportedElement>(element: El, ...attrs_array: Partial<ElementAttributes<El>>[]): El
|
||||||
|
|
||||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap
|
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap
|
||||||
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(
|
export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | Partial<ElementAttributes<ExtendedHTMLElementTagNameMap[TAG]>>,
|
attrs?: string | Partial<ElementAttributes<ExtendedHTMLElementTagNameMap[TAG]>>,
|
||||||
@ -86,6 +91,7 @@ export function elNS(
|
|||||||
export function dispatchEvent(element: SupportedElement, name: keyof DocumentEventMap): void;
|
export function dispatchEvent(element: SupportedElement, name: keyof DocumentEventMap): void;
|
||||||
export function dispatchEvent(element: SupportedElement, name: string, data: any): void;
|
export function dispatchEvent(element: SupportedElement, name: string, data: any): void;
|
||||||
interface On{
|
interface On{
|
||||||
|
/** Listens to the DOM event. See {@link Document.addEventListener} */
|
||||||
<
|
<
|
||||||
EE extends ddeElementModifier<SupportedElement>,
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never ),
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never ),
|
||||||
@ -94,6 +100,7 @@ interface On{
|
|||||||
listener: (this: El, ev: DocumentEventMap[Event]) => any,
|
listener: (this: El, ev: DocumentEventMap[Event]) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
|
/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
||||||
connected<
|
connected<
|
||||||
EE extends ddeElementModifier<SupportedElement>,
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||||
@ -101,6 +108,7 @@ interface On{
|
|||||||
listener: (el: El) => any,
|
listener: (el: El) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
|
/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
||||||
disconnected<
|
disconnected<
|
||||||
EE extends ddeElementModifier<SupportedElement>,
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||||
@ -108,11 +116,37 @@ interface On{
|
|||||||
listener: (el: El) => any,
|
listener: (el: El) => any,
|
||||||
options?: AddEventListenerOptions
|
options?: AddEventListenerOptions
|
||||||
) : EE;
|
) : EE;
|
||||||
|
/** Listens to the element attribute changes. In case of custom elements uses [`attributeChangedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */
|
||||||
|
attributeChanged<
|
||||||
|
EE extends ddeElementModifier<SupportedElement>,
|
||||||
|
El extends ( EE extends ddeElementModifier<infer El> ? El : never )
|
||||||
|
>(
|
||||||
|
listener: (el: El) => any,
|
||||||
|
options?: AddEventListenerOptions
|
||||||
|
) : EE;
|
||||||
}
|
}
|
||||||
export const on: On;
|
export const on: On;
|
||||||
|
|
||||||
|
type Scope= { scope: Node | Function | Object, host: ddeElementModifier<any>, prevent: boolean }
|
||||||
|
/** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */
|
||||||
export const scope: {
|
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 Modifier (function to be called when component is initized)
|
||||||
|
* — `scope.host(on.connected(console.log))`.
|
||||||
|
* */
|
||||||
host: ddeElementModifier<any>,
|
host: ddeElementModifier<any>,
|
||||||
|
|
||||||
|
state: Scope[],
|
||||||
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
|
push(scope: Partial<Scope>): ReturnType<Array<Scope>["push"]>
|
||||||
|
/** Removes last/current child scope. */
|
||||||
|
pop(): ReturnType<Array<Scope>["pop"]>
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
16
signals.d.ts
vendored
16
signals.d.ts
vendored
@ -30,6 +30,10 @@ interface S {
|
|||||||
* by `S.clear`.
|
* by `S.clear`.
|
||||||
* */
|
* */
|
||||||
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>;
|
||||||
|
/**
|
||||||
|
* Computations signal. This creates a signal which is computed from other signals.
|
||||||
|
* */
|
||||||
|
<V>(computation: ()=> V): Signal<V, {}>
|
||||||
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(
|
action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(
|
||||||
signal: S,
|
signal: S,
|
||||||
name: N,
|
name: N,
|
||||||
@ -41,7 +45,17 @@ interface S {
|
|||||||
signal: SymbolSignal;
|
signal: SymbolSignal;
|
||||||
onclear: SymbolOnclear;
|
onclear: SymbolOnclear;
|
||||||
}
|
}
|
||||||
el<S extends any, T extends HTMLElement>(signal: Signal<S, any>, el: (v: S)=> T): T;
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/** Mirrors element attributes for current host (both way). */
|
||||||
|
attribute<T>(name: string, initial?: T): Signal<T, {}>
|
||||||
}
|
}
|
||||||
export const S: S;
|
export const S: S;
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -67,7 +67,9 @@ import { scope } from "./dom.js";
|
|||||||
const key_attributes= "__dde_attributes";
|
const key_attributes= "__dde_attributes";
|
||||||
S.attribute= function(name, initial= undefined){
|
S.attribute= function(name, initial= undefined){
|
||||||
const out= S(initial);
|
const out= S(initial);
|
||||||
|
let host;
|
||||||
scope.host(element=> {
|
scope.host(element=> {
|
||||||
|
host= element;
|
||||||
if(element instanceof HTMLElement){
|
if(element instanceof HTMLElement){
|
||||||
if(element.hasAttribute(name)) out(element.getAttribute(name));
|
if(element.hasAttribute(name)) out(element.getAttribute(name));
|
||||||
} else {
|
} else {
|
||||||
@ -83,16 +85,26 @@ S.attribute= function(name, initial= undefined){
|
|||||||
* Investigate `__dde_attributes` key of the element.*/
|
* Investigate `__dde_attributes` key of the element.*/
|
||||||
const [ name, value ]= detail;
|
const [ name, value ]= detail;
|
||||||
const curr= element[key_attributes][name];
|
const curr= element[key_attributes][name];
|
||||||
if(curr) curr(value);
|
if(curr) return curr(value);
|
||||||
})(element);
|
})(element);
|
||||||
on.disconnected(function(){
|
on.disconnected(function(){
|
||||||
/*! This removes all signals mapped to attributes (`S.attribute`).
|
/*! This removes all signals mapped to attributes (`S.attribute`).
|
||||||
* Investigate `__dde_attributes` key of the element.*/
|
* Investigate `__dde_attributes` key of the element.*/
|
||||||
S.clear(...Object.values(element[key_attributes]));
|
S.clear(...Object.values(element[key_attributes]));
|
||||||
|
host= null;
|
||||||
})(element);
|
})(element);
|
||||||
return element;
|
return element;
|
||||||
});
|
});
|
||||||
return out;
|
return new Proxy(out, {
|
||||||
|
apply(target, _, args){
|
||||||
|
if(!args.length) return target();
|
||||||
|
if(!host) return;
|
||||||
|
const value= args[0];
|
||||||
|
if(host instanceof HTMLElement)
|
||||||
|
return host.setAttribute(name, value);
|
||||||
|
return host.setAttributeNS(null, name, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
S.clear= function(...signals){
|
S.clear= function(...signals){
|
||||||
for(const signal of signals){
|
for(const signal of signals){
|
||||||
|
Loading…
Reference in New Issue
Block a user