mirror of
https://github.com/jaandrle/deka-dom-el
synced 2024-11-24 09:29:37 +01:00
💥 customElement (+enhance slotting simulation) + enh. types
This commit is contained in:
parent
64ddd3f41f
commit
eb920f7bbd
39
dist/dde-with-observables.js
vendored
39
dist/dde-with-observables.js
vendored
File diff suppressed because one or more lines are too long
29
dist/dde.js
vendored
29
dist/dde.js
vendored
File diff suppressed because one or more lines are too long
32
dist/esm-with-observables.d.ts
vendored
32
dist/esm-with-observables.d.ts
vendored
@ -107,18 +107,19 @@ type _fromElsInterfaces<EL extends SupportedElement>= Omit<EL, keyof AttrsModifi
|
|||||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
type ElementAttributes<T extends SupportedElement>= Partial<_fromElsInterfaces<T> & { [K in keyof _fromElsInterfaces<T>]: Observable<_fromElsInterfaces<T>[K], any> } & AttrsModified>;
|
type ElementAttributes<T extends SupportedElement>= Partial<_fromElsInterfaces<T> & { [K in keyof _fromElsInterfaces<T>]: Observable<_fromElsInterfaces<T>[K], any> } & AttrsModified> & Record<string, any>;
|
||||||
export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El
|
export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El
|
||||||
export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El
|
export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El
|
||||||
export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]
|
export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]
|
||||||
|
|
||||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap
|
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap
|
||||||
|
type textContent= string | ( (set?: string)=> string ); // TODO: for some reason `Observable<string, any>` leads to `attrs?: any`
|
||||||
export function el<
|
export function el<
|
||||||
TAG extends keyof ExtendedHTMLElementTagNameMap & string,
|
TAG extends keyof ExtendedHTMLElementTagNameMap & string,
|
||||||
EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : HTMLElement)
|
EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : HTMLElement)
|
||||||
>(
|
>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | Observable<string, any> | ElementAttributes<EL>,
|
attrs?: ElementAttributes<EL> | textContent,
|
||||||
...addons: ddeElementAddon<EL>[]
|
...addons: ddeElementAddon<EL>[]
|
||||||
): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement
|
): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement
|
||||||
export function el(
|
export function el(
|
||||||
@ -126,34 +127,39 @@ export function el(
|
|||||||
): ddeDocumentFragment
|
): ddeDocumentFragment
|
||||||
|
|
||||||
export function el<
|
export function el<
|
||||||
A extends ddeComponentAttributes,
|
C extends (attr: ddeComponentAttributes)=> SupportedElement | ddeDocumentFragment
|
||||||
C extends (attr: Partial<A>)=> SupportedElement | DocumentFragment
|
|
||||||
>(
|
>(
|
||||||
component: C,
|
component: C,
|
||||||
attrs?: A | string,
|
attrs?: Parameters<C>[0] | textContent,
|
||||||
...addons: ddeElementAddon<ReturnType<C>>[]
|
...addons: ddeElementAddon<ReturnType<C>>[]
|
||||||
): ReturnType<C>
|
): ReturnType<C> extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? ReturnType<C> : ( ReturnType<C> extends ddeDocumentFragment ? ReturnType<C> : ddeHTMLElement )
|
||||||
export { el as createElement }
|
export { el as createElement }
|
||||||
|
|
||||||
export function elNS(
|
export function elNS(
|
||||||
namespace: "http://www.w3.org/2000/svg"
|
namespace: "http://www.w3.org/2000/svg"
|
||||||
): <TAG, EL extends ( TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement ), KEYS extends keyof EL & { d: string }>(
|
): <
|
||||||
|
TAG extends keyof SVGElementTagNameMap & string,
|
||||||
|
EL extends ( TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement ),
|
||||||
|
>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | Partial<{ [key in KEYS]: EL[key] | string | number | boolean }>,
|
attrs?: ElementAttributes<EL> | textContent,
|
||||||
...addons: ddeElementAddon<EL>[]
|
...addons: ddeElementAddon<EL>[]
|
||||||
)=> EL
|
)=> TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement
|
||||||
export function elNS(
|
export function elNS(
|
||||||
namespace: "http://www.w3.org/1998/Math/MathML"
|
namespace: "http://www.w3.org/1998/Math/MathML"
|
||||||
): <TAG extends keyof MathMLElementTagNameMap, KEYS extends keyof MathMLElementTagNameMap[TAG] & { d: string }>(
|
): <
|
||||||
|
TAG extends keyof MathMLElementTagNameMap & string,
|
||||||
|
EL extends ( TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement ),
|
||||||
|
>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | Partial<{ [key in KEYS]: MathMLElementTagNameMap[TAG][key] | string | number | boolean }>,
|
attrs?: string | textContent | Partial<{ [key in keyof EL]: EL[key] | Observable<EL[key], any> | string | number | boolean }>,
|
||||||
...addons: ddeElementAddon<MathMLElementTagNameMap[TAG]>[]
|
...addons: ddeElementAddon<EL>[]
|
||||||
)=> ddeMathMLElement
|
)=> ddeMathMLElement
|
||||||
export function elNS(
|
export function elNS(
|
||||||
namespace: string
|
namespace: string
|
||||||
): (
|
): (
|
||||||
tag_name: string,
|
tag_name: string,
|
||||||
attrs?: string | Record<string, any>,
|
attrs?: string | textContent | Record<string, any>,
|
||||||
...addons: ddeElementAddon<SupportedElement>[]
|
...addons: ddeElementAddon<SupportedElement>[]
|
||||||
)=> SupportedElement
|
)=> SupportedElement
|
||||||
export { elNS as createElementNS }
|
export { elNS as createElementNS }
|
||||||
|
8
dist/esm-with-observables.js
vendored
8
dist/esm-with-observables.js
vendored
File diff suppressed because one or more lines are too long
32
dist/esm.d.ts
vendored
32
dist/esm.d.ts
vendored
@ -107,18 +107,19 @@ type _fromElsInterfaces<EL extends SupportedElement>= Omit<EL, keyof AttrsModifi
|
|||||||
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
* There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
type ElementAttributes<T extends SupportedElement>= Partial<_fromElsInterfaces<T> & { [K in keyof _fromElsInterfaces<T>]: Observable<_fromElsInterfaces<T>[K], any> } & AttrsModified>;
|
type ElementAttributes<T extends SupportedElement>= Partial<_fromElsInterfaces<T> & { [K in keyof _fromElsInterfaces<T>]: Observable<_fromElsInterfaces<T>[K], any> } & AttrsModified> & Record<string, any>;
|
||||||
export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El
|
export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El
|
||||||
export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El
|
export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El
|
||||||
export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]
|
export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]
|
||||||
|
|
||||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap
|
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap
|
||||||
|
type textContent= string | ( (set?: string)=> string ); // TODO: for some reason `Observable<string, any>` leads to `attrs?: any`
|
||||||
export function el<
|
export function el<
|
||||||
TAG extends keyof ExtendedHTMLElementTagNameMap & string,
|
TAG extends keyof ExtendedHTMLElementTagNameMap & string,
|
||||||
EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : HTMLElement)
|
EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : HTMLElement)
|
||||||
>(
|
>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | Observable<string, any> | ElementAttributes<EL>,
|
attrs?: ElementAttributes<EL> | textContent,
|
||||||
...addons: ddeElementAddon<EL>[]
|
...addons: ddeElementAddon<EL>[]
|
||||||
): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement
|
): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement
|
||||||
export function el(
|
export function el(
|
||||||
@ -126,34 +127,39 @@ export function el(
|
|||||||
): ddeDocumentFragment
|
): ddeDocumentFragment
|
||||||
|
|
||||||
export function el<
|
export function el<
|
||||||
A extends ddeComponentAttributes,
|
C extends (attr: ddeComponentAttributes)=> SupportedElement | ddeDocumentFragment
|
||||||
C extends (attr: Partial<A>)=> SupportedElement | DocumentFragment
|
|
||||||
>(
|
>(
|
||||||
component: C,
|
component: C,
|
||||||
attrs?: A | string,
|
attrs?: Parameters<C>[0] | textContent,
|
||||||
...addons: ddeElementAddon<ReturnType<C>>[]
|
...addons: ddeElementAddon<ReturnType<C>>[]
|
||||||
): ReturnType<C>
|
): ReturnType<C> extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? ReturnType<C> : ( ReturnType<C> extends ddeDocumentFragment ? ReturnType<C> : ddeHTMLElement )
|
||||||
export { el as createElement }
|
export { el as createElement }
|
||||||
|
|
||||||
export function elNS(
|
export function elNS(
|
||||||
namespace: "http://www.w3.org/2000/svg"
|
namespace: "http://www.w3.org/2000/svg"
|
||||||
): <TAG, EL extends ( TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement ), KEYS extends keyof EL & { d: string }>(
|
): <
|
||||||
|
TAG extends keyof SVGElementTagNameMap & string,
|
||||||
|
EL extends ( TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement ),
|
||||||
|
>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | Partial<{ [key in KEYS]: EL[key] | string | number | boolean }>,
|
attrs?: ElementAttributes<EL> | textContent,
|
||||||
...addons: ddeElementAddon<EL>[]
|
...addons: ddeElementAddon<EL>[]
|
||||||
)=> EL
|
)=> TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement
|
||||||
export function elNS(
|
export function elNS(
|
||||||
namespace: "http://www.w3.org/1998/Math/MathML"
|
namespace: "http://www.w3.org/1998/Math/MathML"
|
||||||
): <TAG extends keyof MathMLElementTagNameMap, KEYS extends keyof MathMLElementTagNameMap[TAG] & { d: string }>(
|
): <
|
||||||
|
TAG extends keyof MathMLElementTagNameMap & string,
|
||||||
|
EL extends ( TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement ),
|
||||||
|
>(
|
||||||
tag_name: TAG,
|
tag_name: TAG,
|
||||||
attrs?: string | Partial<{ [key in KEYS]: MathMLElementTagNameMap[TAG][key] | string | number | boolean }>,
|
attrs?: string | textContent | Partial<{ [key in keyof EL]: EL[key] | Observable<EL[key], any> | string | number | boolean }>,
|
||||||
...addons: ddeElementAddon<MathMLElementTagNameMap[TAG]>[]
|
...addons: ddeElementAddon<EL>[]
|
||||||
)=> ddeMathMLElement
|
)=> ddeMathMLElement
|
||||||
export function elNS(
|
export function elNS(
|
||||||
namespace: string
|
namespace: string
|
||||||
): (
|
): (
|
||||||
tag_name: string,
|
tag_name: string,
|
||||||
attrs?: string | Record<string, any>,
|
attrs?: string | textContent | Record<string, any>,
|
||||||
...addons: ddeElementAddon<SupportedElement>[]
|
...addons: ddeElementAddon<SupportedElement>[]
|
||||||
)=> SupportedElement
|
)=> SupportedElement
|
||||||
export { elNS as createElementNS }
|
export { elNS as createElementNS }
|
||||||
|
2
dist/esm.js
vendored
2
dist/esm.js
vendored
File diff suppressed because one or more lines are too long
@ -31,7 +31,7 @@ export function fullNameComponent(){
|
|||||||
),
|
),
|
||||||
elSVG("svg", { viewBox: "0 0 240 80", style: { height: "80px", display: "block" } }).append(
|
elSVG("svg", { viewBox: "0 0 240 80", style: { height: "80px", display: "block" } }).append(
|
||||||
//elSVG("style", { })
|
//elSVG("style", { })
|
||||||
elSVG("text", { x: 20, y: 35, textContent: "Text" })
|
elSVG("text", { x: 20, y: 35, textContent: "Text" }),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { el, on, scope } from "../../index.js";
|
import { el, on, customElementRender, customElementWithDDE, scope, simulateSlots } from "../../index.js";
|
||||||
import { O } from "../../observables.js";
|
import { O } from "../../observables.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,35 +42,24 @@ export class CustomHTMLTestElement extends HTMLElement{
|
|||||||
get preName(){ return this.getAttribute("pre-name"); }
|
get preName(){ return this.getAttribute("pre-name"); }
|
||||||
set preName(value){ this.setAttribute("pre-name", value); }
|
set preName(value){ this.setAttribute("pre-name", value); }
|
||||||
}
|
}
|
||||||
// https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4
|
customElementWithDDE(CustomHTMLTestElement);
|
||||||
lifecycleToEvents(CustomHTMLTestElement)
|
|
||||||
customElements.define(CustomHTMLTestElement.tagName, CustomHTMLTestElement);
|
customElements.define(CustomHTMLTestElement.tagName, CustomHTMLTestElement);
|
||||||
|
|
||||||
function customElementRender(_this, render, props= _this){
|
export class CustomSlottingHTMLElement extends HTMLElement{
|
||||||
console.log(_this.shadowRoot, _this.childList);
|
static tagName= "custom-slotting";
|
||||||
scope.push({ scope: _this, host: (...c)=> c.length ? c.forEach(c=> c(_this)) : _this, custom_element: _this });
|
render(){
|
||||||
if(typeof props==="function") props= props(_this);
|
return simulateSlots(this, el().append(
|
||||||
const out= render(props);
|
el("p").append(
|
||||||
scope.pop();
|
"Ahoj ", el("slot", { name: "name", className: "name", textContent: "World" })
|
||||||
return out;
|
),
|
||||||
}
|
el("p").append(
|
||||||
function lifecycleToEvents(class_declaration){
|
"BTW ", el("slot")
|
||||||
for (const name of [ "connected", "disconnected" ])
|
)
|
||||||
wrapMethod(class_declaration.prototype, name+"Callback", function(target, thisArg, detail){
|
));
|
||||||
target.apply(thisArg, detail);
|
}
|
||||||
thisArg.dispatchEvent(new Event("dde:"+name));
|
connectedCallback(){
|
||||||
});
|
this.append(customElementRender(this, this.render));
|
||||||
const name= "attributeChanged";
|
}
|
||||||
wrapMethod(class_declaration.prototype, name+"Callback", function(target, thisArg, detail){
|
|
||||||
const [ attribute, , value ]= detail;
|
|
||||||
thisArg.dispatchEvent(new CustomEvent("dde:"+name, {
|
|
||||||
detail: [ attribute, value ]
|
|
||||||
}));
|
|
||||||
target.apply(thisArg, detail);
|
|
||||||
});
|
|
||||||
class_declaration.prototype.__dde_lifecycleToEvents= true;
|
|
||||||
return class_declaration;
|
|
||||||
}
|
|
||||||
function wrapMethod(obj, method, apply){
|
|
||||||
obj[method]= new Proxy(obj[method] || (()=> {}), { apply });
|
|
||||||
}
|
}
|
||||||
|
customElementWithDDE(CustomSlottingHTMLElement);
|
||||||
|
customElements.define(CustomSlottingHTMLElement.tagName, CustomSlottingHTMLElement);
|
||||||
|
@ -2,7 +2,7 @@ import { style, el } from './exports.js';
|
|||||||
document.head.append(style.element);
|
document.head.append(style.element);
|
||||||
import { fullNameComponent } from './components/fullNameComponent.js';
|
import { fullNameComponent } from './components/fullNameComponent.js';
|
||||||
import { todosComponent } from './components/todosComponent.js';
|
import { todosComponent } from './components/todosComponent.js';
|
||||||
import { CustomHTMLTestElement } from "./components/webComponent.js";
|
import { CustomHTMLTestElement, CustomSlottingHTMLElement } from "./components/webComponent.js";
|
||||||
import { thirdParty } from "./components/3rd-party.js";
|
import { thirdParty } from "./components/3rd-party.js";
|
||||||
|
|
||||||
document.body.append(
|
document.body.append(
|
||||||
@ -10,5 +10,9 @@ document.body.append(
|
|||||||
el(fullNameComponent),
|
el(fullNameComponent),
|
||||||
el(todosComponent),
|
el(todosComponent),
|
||||||
el(CustomHTMLTestElement.tagName, { name: "attr" }),
|
el(CustomHTMLTestElement.tagName, { name: "attr" }),
|
||||||
el(thirdParty)
|
el(thirdParty),
|
||||||
|
el(CustomSlottingHTMLElement.tagName).append(
|
||||||
|
el("strong", { slot: "name", textContent: "Honzo" }),
|
||||||
|
el("span", "…default slot")
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
2
index.d.ts
vendored
2
index.d.ts
vendored
@ -68,7 +68,7 @@ export function el<
|
|||||||
component: C,
|
component: C,
|
||||||
attrs?: Parameters<C>[0] | textContent,
|
attrs?: Parameters<C>[0] | textContent,
|
||||||
...addons: ddeElementAddon<ReturnType<C>>[]
|
...addons: ddeElementAddon<ReturnType<C>>[]
|
||||||
): ReturnType<C> extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? ReturnType<C> : ddeHTMLElement
|
): ReturnType<C> extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? ReturnType<C> : ( ReturnType<C> extends ddeDocumentFragment ? ReturnType<C> : ddeHTMLElement )
|
||||||
export { el as createElement }
|
export { el as createElement }
|
||||||
|
|
||||||
export function elNS(
|
export function elNS(
|
||||||
|
1
index.js
1
index.js
@ -1,2 +1,3 @@
|
|||||||
export * from "./src/dom.js";
|
export * from "./src/dom.js";
|
||||||
|
export * from "./src/customElement.js";
|
||||||
export * from "./src/events.js";
|
export * from "./src/events.js";
|
||||||
|
18
package.json
18
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "deka-dom-el",
|
"name": "deka-dom-el",
|
||||||
"version": "0.7.3",
|
"version": "0.7.5",
|
||||||
"description": "A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks.",
|
"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>",
|
"author": "Jan Andrle <andrle.jan@centrum.cz>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -58,7 +58,7 @@
|
|||||||
"size-limit": [
|
"size-limit": [
|
||||||
{
|
{
|
||||||
"path": "./index.js",
|
"path": "./index.js",
|
||||||
"limit": "9 kB",
|
"limit": "9.75 kB",
|
||||||
"gzip": false,
|
"gzip": false,
|
||||||
"brotli": false
|
"brotli": false
|
||||||
|
|
||||||
@ -71,19 +71,7 @@
|
|||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "./jsdom.js",
|
"path": "./index-with-observables.js",
|
||||||
"limit": "10 kB",
|
|
||||||
"gzip": false,
|
|
||||||
"brotli": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "./examples/components/webComponent.js",
|
|
||||||
"limit": "13 kB",
|
|
||||||
"gzip": false,
|
|
||||||
"brotli": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "./examples/components/webComponent.js",
|
|
||||||
"limit": "5 kB"
|
"limit": "5 kB"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
33
src/customElement.js
Normal file
33
src/customElement.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { scope } from "./dom.js";
|
||||||
|
export function customElementRender(custom_element, render, props= custom_element){
|
||||||
|
scope.push({
|
||||||
|
scope: custom_element,
|
||||||
|
host: (...c)=> c.length ? c.forEach(c=> c(custom_element)) : custom_element,
|
||||||
|
custom_element
|
||||||
|
});
|
||||||
|
const out= render.call(custom_element, props);
|
||||||
|
scope.pop();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
export function lifecycleToEvents(class_declaration){
|
||||||
|
for (const name of [ "connected", "disconnected" ])
|
||||||
|
wrapMethod(class_declaration.prototype, name+"Callback", function(target, thisArg, detail){
|
||||||
|
target.apply(thisArg, detail);
|
||||||
|
thisArg.dispatchEvent(new Event("dde:"+name));
|
||||||
|
});
|
||||||
|
const name= "attributeChanged";
|
||||||
|
wrapMethod(class_declaration.prototype, name+"Callback", function(target, thisArg, detail){
|
||||||
|
const [ attribute, , value ]= detail;
|
||||||
|
thisArg.dispatchEvent(new CustomEvent("dde:"+name, {
|
||||||
|
detail: [ attribute, value ]
|
||||||
|
}));
|
||||||
|
target.apply(thisArg, detail);
|
||||||
|
});
|
||||||
|
class_declaration.prototype.__dde_lifecycleToEvents= true;
|
||||||
|
return class_declaration;
|
||||||
|
}
|
||||||
|
// https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4
|
||||||
|
export { lifecycleToEvents as customElementWithDDE };
|
||||||
|
function wrapMethod(obj, method, apply){
|
||||||
|
obj[method]= new Proxy(obj[method] || (()=> {}), { apply });
|
||||||
|
}
|
25
src/dom.js
25
src/dom.js
@ -66,14 +66,14 @@ export function createElement(tag, attributes, ...addons){
|
|||||||
scoped= 2;
|
scoped= 2;
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
/** @param {HTMLElement} element */
|
/** @param {HTMLElement} element @param {HTMLElement} [root] */
|
||||||
export function simulateSlots(element){
|
export function simulateSlots(element, root= element, mapper= undefined){
|
||||||
const _default= Symbol.for("default");
|
const _default= Symbol.for("default");
|
||||||
const slots= Array.from(element.querySelectorAll("slot"))
|
const slots= Array.from(root.querySelectorAll("slot"))
|
||||||
.reduce((out, curr)=> Reflect.set(out, curr.name || _default, curr) && out, {});
|
.reduce((out, curr)=> Reflect.set(out, curr.name || _default, curr) && out, {});
|
||||||
const has_d= Reflect.has(slots, _default);
|
const has_d= Reflect.has(slots, _default);
|
||||||
element.append= new Proxy(element.append, {
|
element.append= new Proxy(element.append, {
|
||||||
apply(_1, _2, els){
|
apply(orig, _, els){
|
||||||
if(!els.length) return element;
|
if(!els.length) return element;
|
||||||
|
|
||||||
const d= document.createDocumentFragment();
|
const d= document.createDocumentFragment();
|
||||||
@ -83,19 +83,28 @@ export function simulateSlots(element){
|
|||||||
const slot= slots[name];
|
const slot= slots[name];
|
||||||
elementAttribute(el, "remove", "slot");
|
elementAttribute(el, "remove", "slot");
|
||||||
if(!slot) continue;
|
if(!slot) continue;
|
||||||
slot.replaceWith(el);
|
simulateSlotReplace(slot, el, mapper);
|
||||||
Reflect.deleteProperty(slots, name);
|
Reflect.deleteProperty(slots, name);
|
||||||
}
|
}
|
||||||
if(has_d){
|
if(has_d){
|
||||||
slots[_default].replaceWith(d);
|
slots[_default].replaceWith(d);
|
||||||
Reflect.deleteProperty(slots, _default);
|
Reflect.deleteProperty(slots, _default);
|
||||||
}
|
}
|
||||||
Object.values(slots)
|
element.append= orig; //TODO: better memory management, but non-native behavior!
|
||||||
.forEach(slot=> slot.replaceWith(createElement().append(...Array.from(slot.childNodes))));
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return element;
|
if(element!==root){
|
||||||
|
const els= Array.from(element.childNodes);
|
||||||
|
els.forEach(el=> el.remove());
|
||||||
|
element.append(...els);
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
function simulateSlotReplace(slot, element, mapper){
|
||||||
|
if(mapper) mapper(slot, element);
|
||||||
|
try{ slot.replaceWith(assign(element, { className: [ element.className, slot.className ], dataset: { ...slot.dataset } })); }
|
||||||
|
catch(_){ slot.replaceWith(element); }
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param { { type: "component", name: string, host: "this" | "parentElement" } | { type: "reactive" | "later" } } attrs
|
* @param { { type: "component", name: string, host: "this" | "parentElement" } | { type: "reactive" | "later" } } attrs
|
||||||
|
Loading…
Reference in New Issue
Block a user