mirror of
https://github.com/jaandrle/deka-dom-el
synced 2025-07-01 20:32:13 +02:00
✨ Add signals functionality and reactive attributes in assign
This commit is contained in:
10
src/dom.js
10
src/dom.js
@ -20,14 +20,22 @@ export function createElementNS(tag, attributes, attributes_todo){
|
||||
}
|
||||
export { createElementNS as elNS };
|
||||
|
||||
import { watch } from './signals.js';
|
||||
function isReactive(key, attr){
|
||||
if(typeof attr !== "function") return false;
|
||||
if(key.startsWith("on")) return false;
|
||||
return true;
|
||||
}
|
||||
export function assign(element, ...attributes){
|
||||
if(!attributes.length) return element;
|
||||
const is_svg= element instanceof SVGElement;
|
||||
const setRemoveAttr= (is_svg ? setRemoveNS : setRemove).bind(null, element, "Attribute");
|
||||
|
||||
Object.entries(Object.assign({}, ...attributes)).forEach(function([ key, attr ]){
|
||||
Object.entries(Object.assign({}, ...attributes)).forEach(function assignNth([ key, attr ]){
|
||||
if(key[0]==="=") return setRemoveAttr(key.slice(1), attr);
|
||||
if(key[0]===".") return setDelete(element, key.slice(1), attr);
|
||||
if(isReactive(key, attr))
|
||||
return watch(()=> assignNth([ key, attr() ]));
|
||||
if(typeof attr === "object"){
|
||||
switch(key){
|
||||
case "style": return forEachEntries(attr, setRemove.bind(null, element.style, "Property"))
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { isSignal } from './signals.js';
|
||||
export function listen(event, listener, options){
|
||||
if(isSignal(event)) return event.listeners.add(listener);
|
||||
return element=> element.addEventListener(event, listener, options);
|
||||
}
|
||||
export function dispatch(event, detail){
|
||||
|
52
src/signals.js
Normal file
52
src/signals.js
Normal file
@ -0,0 +1,52 @@
|
||||
const mark= Symbol.for("signal");
|
||||
export function isSignal(candidate){
|
||||
try{
|
||||
return Reflect.has(candidate, mark);
|
||||
} catch(e){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export function S(signal, ...value){
|
||||
if(typeof signal==="function"){
|
||||
const out= create();
|
||||
watch(()=> S(out, signal()));
|
||||
return out;
|
||||
}
|
||||
if(!isSignal(signal))
|
||||
return create(signal);
|
||||
|
||||
if(value.length===0)
|
||||
return read(signal);
|
||||
return write(signal, value[0]);
|
||||
}
|
||||
const stack= [];
|
||||
export function watch(context){
|
||||
stack.push(context);
|
||||
context();
|
||||
stack.pop();
|
||||
};
|
||||
|
||||
function currentContext(){
|
||||
return stack[stack.length - 1];
|
||||
}
|
||||
function create(value){
|
||||
if(typeof value==="object" && value!==null)
|
||||
return Object.fromEntries(
|
||||
Object.entries(value)
|
||||
.map(([ key, value ])=> [ key, create(value) ])
|
||||
);
|
||||
return {
|
||||
[mark]: true,
|
||||
value,
|
||||
listeners: new Set()
|
||||
};
|
||||
}
|
||||
function read({ value, listeners }){
|
||||
const context= currentContext();
|
||||
if(context) listeners.add(context);
|
||||
return value;
|
||||
}
|
||||
function write(signal, value){
|
||||
signal.value= value;
|
||||
signal.listeners.forEach(fn=> fn(value))
|
||||
}
|
Reference in New Issue
Block a user