mirror of
https://github.com/jaandrle/deka-dom-el
synced 2024-11-24 01:29:36 +01:00
🚧 mainly wc/ce
This commit is contained in:
parent
56206343d1
commit
10ed0802f2
30
dist/dde-with-signals.js
vendored
30
dist/dde-with-signals.js
vendored
File diff suppressed because one or more lines are too long
31
dist/esm-with-signals.d.ts
vendored
31
dist/esm-with-signals.d.ts
vendored
@ -166,6 +166,34 @@ export const scope: {
|
|||||||
pop(): ReturnType<Array<Scope>["pop"]>,
|
pop(): ReturnType<Array<Scope>["pop"]>,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO TypeScript HACK (better way?)
|
||||||
|
* this doesnt works
|
||||||
|
* ```ts
|
||||||
|
* interface element<el> extends Node{
|
||||||
|
* prototype: el;
|
||||||
|
* append(...els: (SupportedElement | DocumentFragment | string | element<SupportedElement | DocumentFragment>)[]): el
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
export function el<T>(
|
||||||
|
* tag_name?: "<>",
|
||||||
|
* ): element<DocumentFragment>
|
||||||
|
* ```
|
||||||
|
* …as its complains here
|
||||||
|
* ```
|
||||||
|
ts
|
||||||
|
*
|
||||||
|
const d= el("div");
|
||||||
|
*
|
||||||
|
const f= (a: HTMLDivElement)=> a;
|
||||||
|
* f(d);
|
||||||
|
//←
|
||||||
|
* document.head.append( //←
|
||||||
|
* el("script", { src: "https://flems.io/flems.html", type: "text/javascript", charset: "utf-8" }),
|
||||||
|
* );
|
||||||
|
* ```
|
||||||
|
* TODO for SVG
|
||||||
|
* */
|
||||||
type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
|
type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
|
||||||
declare global{
|
declare global{
|
||||||
interface HTMLAnchorElement{
|
interface HTMLAnchorElement{
|
||||||
@ -493,8 +521,7 @@ interface S {
|
|||||||
* */
|
* */
|
||||||
el<S extends any>(signal: Signal<S, any>, el: (v: S)=> Element | Element[]): DocumentFragment;
|
el<S extends any>(signal: Signal<S, any>, el: (v: S)=> Element | Element[]): DocumentFragment;
|
||||||
|
|
||||||
/** Mirrors element attributes for current host (both way). */
|
fromAttribute<T>(element: HTMLElement, name: string, value?: T): Signal<T, {}>;
|
||||||
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
28
dist/esm.d.ts
vendored
28
dist/esm.d.ts
vendored
@ -166,6 +166,34 @@ export const scope: {
|
|||||||
pop(): ReturnType<Array<Scope>["pop"]>,
|
pop(): ReturnType<Array<Scope>["pop"]>,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO TypeScript HACK (better way?)
|
||||||
|
* this doesnt works
|
||||||
|
* ```ts
|
||||||
|
* interface element<el> extends Node{
|
||||||
|
* prototype: el;
|
||||||
|
* append(...els: (SupportedElement | DocumentFragment | string | element<SupportedElement | DocumentFragment>)[]): el
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
export function el<T>(
|
||||||
|
* tag_name?: "<>",
|
||||||
|
* ): element<DocumentFragment>
|
||||||
|
* ```
|
||||||
|
* …as its complains here
|
||||||
|
* ```
|
||||||
|
ts
|
||||||
|
*
|
||||||
|
const d= el("div");
|
||||||
|
*
|
||||||
|
const f= (a: HTMLDivElement)=> a;
|
||||||
|
* f(d);
|
||||||
|
//←
|
||||||
|
* document.head.append( //←
|
||||||
|
* el("script", { src: "https://flems.io/flems.html", type: "text/javascript", charset: "utf-8" }),
|
||||||
|
* );
|
||||||
|
* ```
|
||||||
|
* TODO for SVG
|
||||||
|
* */
|
||||||
type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
|
type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
|
||||||
declare global{
|
declare global{
|
||||||
interface HTMLAnchorElement{
|
interface HTMLAnchorElement{
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
import { el, on, 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef CustomHTMLTestElementInterface
|
* Compatible with `npx -y web-component-analyzer examples/components/webComponent.js`
|
||||||
* @type {object}
|
* @element custom-test
|
||||||
* @property {string} name
|
|
||||||
* */
|
|
||||||
/**
|
|
||||||
* Compatible with `npx-wca test/components/webComponent.js`
|
|
||||||
* */
|
* */
|
||||||
export class CustomHTMLTestElement extends HTMLElement{
|
export class CustomHTMLTestElement extends HTMLElement{
|
||||||
static tagName= "custom-test";
|
static tagName= "custom-test";
|
||||||
@ -16,32 +11,34 @@ export class CustomHTMLTestElement extends HTMLElement{
|
|||||||
return [ "name", "pre-name" ];
|
return [ "name", "pre-name" ];
|
||||||
}
|
}
|
||||||
connectedCallback(){
|
connectedCallback(){
|
||||||
|
if(!this.hasAttribute("pre-name")) this.setAttribute("pre-name", "default");
|
||||||
this.attachShadow({ mode: "open" }).append(
|
this.attachShadow({ mode: "open" }).append(
|
||||||
customElementRender(this, this.render)
|
customElementRender(this, this.render, observedAttributes(S))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render({ test }){
|
render({ name, preName }){
|
||||||
|
const { host }= scope;
|
||||||
|
const { test }= host();
|
||||||
console.log(scope.state);
|
console.log(scope.state);
|
||||||
scope.host(
|
host(
|
||||||
on.connected(()=> console.log(CustomHTMLTestElement)),
|
on.connected(()=> console.log(CustomHTMLTestElement)),
|
||||||
on.attributeChanged(e=> console.log(e)),
|
on.attributeChanged(e=> console.log(e)),
|
||||||
on.disconnected(()=> console.log(CustomHTMLTestElement))
|
on.disconnected(()=> console.log(CustomHTMLTestElement))
|
||||||
);
|
);
|
||||||
|
|
||||||
const name= S.attribute("name");
|
|
||||||
const preName= S.attribute("pre-name");
|
|
||||||
console.log({ name, test, preName});
|
console.log({ name, test, preName});
|
||||||
return el("p").append(
|
return el("p").append(
|
||||||
el("#text", name),
|
el("#text", name),
|
||||||
el("#text", test),
|
|
||||||
el("#text", preName),
|
el("#text", preName),
|
||||||
el("button", { type: "button", textContent: "pre-name", onclick: ()=> preName("Ahoj") })
|
el("button", { type: "button", textContent: "pre-name", onclick: ()=> preName("Ahoj") })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
test= "A";
|
||||||
|
|
||||||
get name(){ return this.getAttribute("name"); }
|
get name(){ return this.getAttribute("name"); }
|
||||||
set name(value){ this.setAttribute("name", value); }
|
set name(value){ this.setAttribute("name", value); }
|
||||||
|
/** @attr pre-name */
|
||||||
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); }
|
||||||
}
|
}
|
||||||
@ -49,12 +46,25 @@ export class CustomHTMLTestElement extends HTMLElement{
|
|||||||
lifecycleToEvents(CustomHTMLTestElement)
|
lifecycleToEvents(CustomHTMLTestElement)
|
||||||
customElements.define(CustomHTMLTestElement.tagName, CustomHTMLTestElement);
|
customElements.define(CustomHTMLTestElement.tagName, CustomHTMLTestElement);
|
||||||
|
|
||||||
function customElementRender(_this, render){
|
function customElementRender(_this, render, props){
|
||||||
|
console.log(_this.shadowRoot, _this.childList);
|
||||||
scope.push({ scope: _this, host: (...c)=> c.length ? c.forEach(c=> c(_this)) : _this, custom_element: _this });
|
scope.push({ scope: _this, host: (...c)=> c.length ? c.forEach(c=> c(_this)) : _this, custom_element: _this });
|
||||||
const out= render(_this);
|
if(typeof props==="function") props= props(_this);
|
||||||
|
const out= render(props);
|
||||||
scope.pop();
|
scope.pop();
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
function observedAttributes(options, element){
|
||||||
|
const fromAttribute= typeof options==="undefined" ? (_1, _2, v)=> v : ( options.fromAttribute || options );
|
||||||
|
if(!element) return observedAttributes.bind(null, fromAttribute)
|
||||||
|
return Object.fromEntries(
|
||||||
|
element.constructor.observedAttributes
|
||||||
|
.map(name=> [
|
||||||
|
name.replace(/-./g, m=> m.slice(1).toUpperCase()),
|
||||||
|
fromAttribute(element, name, element.getAttribute(name))
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
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){
|
||||||
@ -70,6 +80,7 @@ function lifecycleToEvents(class_declaration){
|
|||||||
target.apply(thisArg, detail);
|
target.apply(thisArg, detail);
|
||||||
});
|
});
|
||||||
class_declaration.prototype.__dde_lifecycleToEvents= true;
|
class_declaration.prototype.__dde_lifecycleToEvents= true;
|
||||||
|
return class_declaration;
|
||||||
}
|
}
|
||||||
function wrapMethod(obj, method, apply){
|
function wrapMethod(obj, method, apply){
|
||||||
obj[method]= new Proxy(obj[method] || (()=> {}), { apply });
|
obj[method]= new Proxy(obj[method] || (()=> {}), { apply });
|
||||||
|
3
signals.d.ts
vendored
3
signals.d.ts
vendored
@ -54,8 +54,7 @@ interface S {
|
|||||||
* */
|
* */
|
||||||
el<S extends any>(signal: Signal<S, any>, el: (v: S)=> Element | Element[]): DocumentFragment;
|
el<S extends any>(signal: Signal<S, any>, el: (v: S)=> Element | Element[]): DocumentFragment;
|
||||||
|
|
||||||
/** Mirrors element attributes for current host (both way). */
|
fromAttribute<T>(element: HTMLElement, name: string, value?: T): Signal<T, {}>;
|
||||||
attribute<T>(name: string, initial?: T): Signal<T, {}>
|
|
||||||
}
|
}
|
||||||
export const S: S;
|
export const S: S;
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -62,50 +62,6 @@ S.symbols= {
|
|||||||
signal: mark,
|
signal: mark,
|
||||||
onclear: Symbol.for("Signal.onclear")
|
onclear: Symbol.for("Signal.onclear")
|
||||||
};
|
};
|
||||||
import { on } from "./events.js";
|
|
||||||
import { scope } from "./dom.js";
|
|
||||||
const key_attributes= "__dde_attributes";
|
|
||||||
S.attribute= function(name, initial= undefined){
|
|
||||||
const out= S(initial);
|
|
||||||
let host;
|
|
||||||
scope.host(element=> {
|
|
||||||
host= element;
|
|
||||||
if(element instanceof HTMLElement){
|
|
||||||
if(element.hasAttribute(name)) out(element.getAttribute(name));
|
|
||||||
} else {
|
|
||||||
if(element.hasAttributeNS(null, name)) out(element.getAttributeNS(null, name));
|
|
||||||
}
|
|
||||||
if(element[key_attributes]){
|
|
||||||
element[key_attributes][name]= out;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
element[key_attributes]= { [name]: out };
|
|
||||||
on.attributeChanged(function attributeChangeToSignal({ detail }){
|
|
||||||
/*! This maps attributes to signals (`S.attribute`).
|
|
||||||
* Investigate `__dde_attributes` key of the element.*/
|
|
||||||
const [ name, value ]= detail;
|
|
||||||
const curr= element[key_attributes][name];
|
|
||||||
if(curr) return curr(value);
|
|
||||||
})(element);
|
|
||||||
on.disconnected(function(){
|
|
||||||
/*! This removes all signals mapped to attributes (`S.attribute`).
|
|
||||||
* Investigate `__dde_attributes` key of the element.*/
|
|
||||||
S.clear(...Object.values(element[key_attributes]));
|
|
||||||
host= null;
|
|
||||||
})(element);
|
|
||||||
return element;
|
|
||||||
});
|
|
||||||
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){
|
||||||
Reflect.deleteProperty(signal, "toJSON");
|
Reflect.deleteProperty(signal, "toJSON");
|
||||||
@ -130,6 +86,7 @@ S.clear= function(...signals){
|
|||||||
};
|
};
|
||||||
const key_reactive= "__dde_reactive";
|
const key_reactive= "__dde_reactive";
|
||||||
import { el } from "./dom.js";
|
import { el } from "./dom.js";
|
||||||
|
import { scope } from "./dom.js";
|
||||||
S.el= function(signal, map){
|
S.el= function(signal, map){
|
||||||
const mark_start= el.mark({ type: "reactive" }, false);
|
const mark_start= el.mark({ type: "reactive" }, false);
|
||||||
const mark_end= mark_start.end;
|
const mark_end= mark_start.end;
|
||||||
@ -154,6 +111,34 @@ S.el= function(signal, map){
|
|||||||
reRenderReactiveElement(signal());
|
reRenderReactiveElement(signal());
|
||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
|
import { on } from "./events.js";
|
||||||
|
const key_attributes= "__dde_attributes";
|
||||||
|
S.fromAttribute= function(element, name, value){
|
||||||
|
if(!element[key_attributes]){ // needs registration
|
||||||
|
element[key_attributes]= {};
|
||||||
|
on.attributeChanged(function attributeChangeToSignal({ detail }){
|
||||||
|
/*! This maps attributes to signals (`S.attribute`).
|
||||||
|
* Investigate `__dde_attributes` key of the element.*/
|
||||||
|
const [ name, value ]= detail;
|
||||||
|
const curr= element[key_attributes][name];
|
||||||
|
if(curr) return curr(value);
|
||||||
|
})(element);
|
||||||
|
on.disconnected(function(){
|
||||||
|
/*! This removes all signals mapped to attributes (`S.attribute`).
|
||||||
|
* Investigate `__dde_attributes` key of the element.*/
|
||||||
|
S.clear(...Object.values(element[key_attributes]));
|
||||||
|
})(element);
|
||||||
|
}
|
||||||
|
const store= element[key_attributes];
|
||||||
|
const out= Reflect.has(store, name) ? Reflect.get(store, name) : (store[name]= S(value));
|
||||||
|
return new Proxy(out, {
|
||||||
|
apply(target, _, args){
|
||||||
|
if(!args.length) return target();
|
||||||
|
const value= args[0];
|
||||||
|
return element.setAttribute(name, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
import { typeOf } from './helpers.js';
|
import { typeOf } from './helpers.js';
|
||||||
export const signals_config= {
|
export const signals_config= {
|
||||||
|
Loading…
Reference in New Issue
Block a user