mirror of
				https://github.com/jaandrle/deka-dom-el
				synced 2025-11-03 22:59:16 +01:00 
			
		
		
		
	✨ Add attrsPropsToSignals
				
					
				
			This commit is contained in:
		@@ -1,64 +1,56 @@
 | 
			
		||||
import { el } from "../../index.js";
 | 
			
		||||
import { S } from "../../src/signals.js";
 | 
			
		||||
const store= new WeakMap();
 | 
			
		||||
Object.assign(S, {
 | 
			
		||||
	customElementParams(_this){
 | 
			
		||||
		const observedProperties= store.get(_this.constructor).observedProperties;
 | 
			
		||||
		observedProperties.forEach(p=> _this[p]);
 | 
			
		||||
		return store.has(_this) ? store.get(_this) : getAttributes(_this);
 | 
			
		||||
	},
 | 
			
		||||
	customElementPrototype(cls){
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
const { hasOwnProperty }= Object.prototype;
 | 
			
		||||
 | 
			
		||||
const store= attrsPropsToSignals([ "test" ]);
 | 
			
		||||
/**
 | 
			
		||||
 * Compatible with `npx-wca test/components/webComponent.js`
 | 
			
		||||
 * */
 | 
			
		||||
export class CustomHTMLTestElement extends HTMLElement{
 | 
			
		||||
	static get observedAttributes(){
 | 
			
		||||
		return [ "name" ];
 | 
			
		||||
		return [ "name", "pre-name" ];
 | 
			
		||||
	}
 | 
			
		||||
	connectedCallback(){
 | 
			
		||||
		customElementRender(this, this.attachShadow({ mode: "open" }), this.render);
 | 
			
		||||
		this.attachShadow({ mode: "open" }).append(
 | 
			
		||||
			customElementRender(this, store.toRender(this), this.render)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render({ name, test }, host){
 | 
			
		||||
	render({ name, test, preName }, host){
 | 
			
		||||
		host(on.connected(console.log));
 | 
			
		||||
		return el("p", { className: test, textContent: name });
 | 
			
		||||
		return el("p").append(
 | 
			
		||||
			el("#text", { textContent: name }),
 | 
			
		||||
			el("#text", { textContent: test }),
 | 
			
		||||
			el("#text", { textContent: preName }),
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
customElementsAssign(
 | 
			
		||||
	CustomHTMLTestElement,
 | 
			
		||||
	reflectObservedAttributes,
 | 
			
		||||
	lifecycleToEvents(true),
 | 
			
		||||
	attrsPropsToSignals([ "test" ])
 | 
			
		||||
	lifecycleToEvents(false),
 | 
			
		||||
	store.connect
 | 
			
		||||
);
 | 
			
		||||
customElements.define("custom-test", CustomHTMLTestElement);
 | 
			
		||||
 | 
			
		||||
function customElementRender(_this, root, render){
 | 
			
		||||
function customElementRender(_this, attrs, render){
 | 
			
		||||
	const host= (...a)=> a.length ? a[0](_this) : _this;
 | 
			
		||||
	const attrs= S.customElementParams ? S.customElementParams(_this) : getAttributes(_this);
 | 
			
		||||
	root.appendChild(render(attrs, host));
 | 
			
		||||
}
 | 
			
		||||
function getAttributes(_this){
 | 
			
		||||
	return Object.fromEntries(_this.getAttributeNames().map(n=> [ n, _this.getAttribute(n) ]));
 | 
			
		||||
	return render(attrs, host);
 | 
			
		||||
}
 | 
			
		||||
/** @returns {HTMLElement} */
 | 
			
		||||
function customElementsAssign(class_base, ...automatize){
 | 
			
		||||
	automatize.forEach(a=> a(class_base, getStore));
 | 
			
		||||
	function getStore(t){
 | 
			
		||||
		if(store.has(t)) return store.get(t);
 | 
			
		||||
		const s= {};
 | 
			
		||||
		store.set(t, s);
 | 
			
		||||
		return s;
 | 
			
		||||
	}
 | 
			
		||||
	automatize.forEach(a=> a(class_base));
 | 
			
		||||
}
 | 
			
		||||
function reflectObservedAttributes(c){
 | 
			
		||||
	for(const name of c.observedAttributes)
 | 
			
		||||
		Reflect.defineProperty(c.prototype, name, {
 | 
			
		||||
	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(is_attrs){
 | 
			
		||||
	return function(c){
 | 
			
		||||
@@ -78,12 +70,25 @@ function lifecycleToEvents(is_attrs){
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
function attrsPropsToSignals(props= []){
 | 
			
		||||
	return function(c, getStore){
 | 
			
		||||
		const store= getStore(c);
 | 
			
		||||
		store.observedProperties= props;
 | 
			
		||||
	const store_attrs= new WeakMap();
 | 
			
		||||
	const store_props= new WeakMap();
 | 
			
		||||
	return {
 | 
			
		||||
		toRender(target){
 | 
			
		||||
			const out= {};
 | 
			
		||||
			const sattrs= get(store_attrs, target);
 | 
			
		||||
			target.constructor.observedAttributes.forEach(function(name){
 | 
			
		||||
				const name_camel= name.replace(/([a-z])-([a-z])/g, (_, l, r)=> l+r.toUpperCase());
 | 
			
		||||
				if(!hasOwnProperty.call(sattrs, name)) sattrs[name]= S(undefined);
 | 
			
		||||
				out[name_camel]= sattrs[name];
 | 
			
		||||
			});
 | 
			
		||||
			const sprops= get(store_props, target);
 | 
			
		||||
			props.forEach(p=> !hasOwnProperty.call(sprops, p) && (sprops[p]= S(undefined)));
 | 
			
		||||
			return Object.assign(out, sprops);
 | 
			
		||||
		},
 | 
			
		||||
		connect(c){
 | 
			
		||||
			wrapMethod(c.prototype, "attributeChangedCallback", function(target, thisArg, detail){
 | 
			
		||||
				const [ name, _, value ]= detail;
 | 
			
		||||
			const s= getStore(thisArg);
 | 
			
		||||
				const s= get(store_attrs, thisArg);
 | 
			
		||||
				if(s[name]) s[name](value);
 | 
			
		||||
				else s[name]= S(value);
 | 
			
		||||
				
 | 
			
		||||
@@ -92,20 +97,24 @@ function attrsPropsToSignals(props= []){
 | 
			
		||||
			for(const name of props){
 | 
			
		||||
				Reflect.defineProperty(c.prototype, name, {
 | 
			
		||||
					get(){
 | 
			
		||||
					const s= getStore(this);
 | 
			
		||||
						const s= get(store_props, this);
 | 
			
		||||
						if(s[name]) return s[name]();
 | 
			
		||||
					const out= S(undefined);
 | 
			
		||||
					s[name]= out;
 | 
			
		||||
					return out();
 | 
			
		||||
					},
 | 
			
		||||
					set(value){
 | 
			
		||||
					const s= getStore(this);
 | 
			
		||||
						const s= get(store_props, this);
 | 
			
		||||
						if(s[name]) s[name](value);
 | 
			
		||||
						else s[name]= S(value);
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
	function get(store, t){
 | 
			
		||||
		if(store.has(t)) return store.get(t);
 | 
			
		||||
		const s= {};
 | 
			
		||||
		store.set(t, s);
 | 
			
		||||
		return s;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
function wrapMethod(obj, method, apply){
 | 
			
		||||
	obj[method]= new Proxy(obj[method] || (()=> {}), { apply });
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user