1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2025-07-04 21:42:14 +02:00
This commit is contained in:
2024-11-22 16:26:42 +01:00
parent b50f8449aa
commit 576b33921b
41 changed files with 300 additions and 158 deletions

View File

@ -13,11 +13,11 @@ function setDeleteAttr(obj, prop, val){
For some native attrs you can unset only to set empty string.
This can be confusing as it is seen in inspector `<… id=""`.
Options:
1. Leave it, as it is native behaviour
2. Sets as empty string and removes the corresponding attribute when also has empty string
*3. Sets as undefined and removes the corresponding attribute when "undefined" string discovered
4. Point 2. with checks for coincidence (e.g. use special string)
*/
1. Leave it, as it is native behaviour
2. Sets as empty string and removes the corresponding attribute when also has empty string
3. (*) Sets as undefined and removes the corresponding attribute when "undefined" string discovered
4. Point 2. with checks for coincidence (e.g. use special string)
*/
Reflect.set(obj, prop, val);
if(!isUndef(val)) return;
Reflect.deleteProperty(obj, prop);

View File

@ -10,13 +10,13 @@ const scopes= [ {
export const scope= {
get current(){ return scopes[scopes.length-1]; },
get host(){ return this.current.host; },
preventDefault(){
const { current }= this;
current.prevent= true;
return current;
},
get state(){ return [ ...scopes ]; },
push(s= {}){ return scopes.push(Object.assign({}, this.current, { prevent: false }, s)); },
pushRoot(){ return scopes.push(scopes[0]); },
@ -25,9 +25,11 @@ export const scope= {
return scopes.pop();
},
};
// following chainableAppend implementation is OK as the ElementPrototype.append description already is { writable: true, enumerable: true, configurable: true }
// following chainableAppend implementation is OK as the ElementPrototype.append description already is { writable: true, enumerable: true, configurable: true } // editorconfig-checker-disable-line
function append(...els){ this.appendOriginal(...els); return this; }
export function chainableAppend(el){ if(el.append===append) return el; el.appendOriginal= el.append; el.append= append; return el; }
export function chainableAppend(el){
if(el.append===append) return el; el.appendOriginal= el.append; el.append= append; return el;
}
let namespace;
export function createElement(tag, attributes, ...addons){
/* jshint maxcomplexity: 15 */
@ -40,7 +42,9 @@ export function createElement(tag, attributes, ...addons){
switch(true){
case typeof tag==="function": {
scoped= 1;
scope.push({ scope: tag, host: (...c)=> c.length ? (scoped===1 ? addons.unshift(...c) : c.forEach(c=> c(el_host)), undefined) : el_host });
const host= (...c)=> !c.length ? el_host :
(scoped===1 ? addons.unshift(...c) : c.forEach(c=> c(el_host)), undefined);
scope.push({ scope: tag, host });
el= tag(attributes || undefined);
const is_fragment= el instanceof env.F;
if(el.nodeName==="#comment") break;
@ -108,7 +112,9 @@ export function simulateSlots(element, root, mapper){
}
function simulateSlotReplace(slot, element, mapper){
if(mapper) mapper(slot, element);
try{ slot.replaceWith(assign(element, { className: [ element.className, slot.className ], dataset: { ...slot.dataset } })); }
try{ slot.replaceWith(assign(element, {
className: [ element.className, slot.className ],
dataset: { ...slot.dataset } })); }
catch(_){ slot.replaceWith(element); }
}
/**
@ -141,7 +147,7 @@ const { setDeleteAttr }= env;
export function assign(element, ...attributes){
if(!attributes.length) return element;
assign_context.set(element, assignContext(element, this));
for(const [ key, value ] of Object.entries(Object.assign({}, ...attributes)))
assignAttribute.call(this, element, key, value);
assign_context.delete(element);
@ -150,7 +156,7 @@ export function assign(element, ...attributes){
export function assignAttribute(element, key, value){
const { setRemoveAttr, s }= assignContext(element, this);
const _this= this;
value= s.processReactiveAttribute(element, key, value,
(key, value)=> assignAttribute.call(_this, element, key, value));
const [ k ]= key;
@ -216,7 +222,9 @@ function getPropDescriptor(p, key){
return des;
}
/** @template {Record<any, any>} T @param {object} s @param {T} obj @param {(param: [ keyof T, T[keyof T] ])=> void} cb */
/**
* @template {Record<any, any>} T @param {object} s @param {T} obj @param {(param: [ keyof T, T[keyof T] ])=> void} cb
* */
function forEachEntries(s, obj, cb){
if(typeof obj !== "object" || obj===null) return;
return Object.entries(obj).forEach(function process([ key, val ]){
@ -227,6 +235,9 @@ function forEachEntries(s, obj, cb){
}
function attrArrToStr(attr){ return Array.isArray(attr) ? attr.filter(Boolean).join(" ") : attr; }
function setRemove(obj, prop, key, val){ return obj[ (isUndef(val) ? "remove" : "set") + prop ](key, attrArrToStr(val)); }
function setRemoveNS(obj, prop, key, val, ns= null){ return obj[ (isUndef(val) ? "remove" : "set") + prop + "NS" ](ns, key, attrArrToStr(val)); }
function setDelete(obj, key, val){ Reflect.set(obj, key, val); if(!isUndef(val)) return; return Reflect.deleteProperty(obj, key); }
function setRemove(obj, prop, key, val){
return obj[ (isUndef(val) ? "remove" : "set") + prop ](key, attrArrToStr(val)); }
function setRemoveNS(obj, prop, key, val, ns= null){
return obj[ (isUndef(val) ? "remove" : "set") + prop + "NS" ](ns, key, attrArrToStr(val)); }
function setDelete(obj, key, val){
Reflect.set(obj, key, val); if(!isUndef(val)) return; return Reflect.deleteProperty(obj, key); }

View File

@ -103,10 +103,10 @@ function connectionsChangesObserverConstructor(){
for(const element of addedNodes){
if(is_root) collectChildren(element).then(observerAdded);
if(!store.has(element)) continue;
const ls= store.get(element);
if(!ls.length_c) continue;
element.dispatchEvent(new Event(evc));
ls.connected= new WeakSet();
ls.length_c= 0;
@ -120,7 +120,7 @@ function connectionsChangesObserverConstructor(){
for(const element of removedNodes){
if(is_root) collectChildren(element).then(observerRemoved);
if(!store.has(element)) continue;
const ls= store.get(element);
if(!ls.length_d) continue;
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));

View File

@ -64,9 +64,9 @@ on.attributeChanged= function(listener, options){
element.addEventListener(eva, listener, options);
if(element[keyLTE] || els_attribute_store.has(element))
return element;
if(!env.M) return element;
const observer= new env.M(function(mutations){
for(const { attributeName, target } of mutations)
target.dispatchEvent(
@ -77,4 +77,4 @@ on.attributeChanged= function(listener, options){
//TODO: clean up when element disconnected
return element;
};
};
};

View File

@ -21,7 +21,7 @@ export function signal(value, actions){
if(typeof value!=="function")
return create(false, value, actions);
if(isSignal(value)) return value;
const out= create(true);
const contextReWatch= function(){
const [ origin, ...deps_old ]= deps.get(contextReWatch);
@ -77,11 +77,11 @@ signal.clear= function(...signals){
o.listeners.forEach(l=> {
o.listeners.delete(l);
if(!deps.has(l)) return;
const ls= deps.get(l);
ls.delete(s);
if(ls.size>1) return;
s.clear(...ls);
deps.delete(l);
});

View File

@ -21,7 +21,7 @@ export function signal(value, actions){
if(typeof value!=="function")
return create(false, value, actions);
if(isSignal(value)) return value;
const out= create(true);
const contextReWatch= function(){
const [ origin, ...deps_old ]= deps.get(contextReWatch);
@ -77,11 +77,11 @@ signal.clear= function(...signals){
o.listeners.forEach(l=> {
o.listeners.delete(l);
if(!deps.has(l)) return;
const ls= deps.get(l);
ls.delete(s);
if(ls.size>1) return;
s.clear(...ls);
deps.delete(l);
});