1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2024-12-03 12:33:54 +01:00

cross-platform using enviroment (#14)

* 🎉

* Dev bugs@v0.7.6 (#12)

* Update observables-lib.js

* `collectChildren`

* Update todosComponent.js

* 🚀 filter for `collectChildren`

* finalization
This commit is contained in:
Jan Andrle 2024-01-07 13:22:55 +01:00 committed by GitHub
parent d2ddaaec6f
commit 5e7f7558b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 90 additions and 66 deletions

File diff suppressed because one or more lines are too long

22
dist/dde.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/esm.js vendored

File diff suppressed because one or more lines are too long

8
jsdom.d.ts vendored
View File

@ -1,5 +1,13 @@
import { el, assign, on } from "./index.d";
export * from "./index.d";
type JSDOM= {
window: Window,
document: Document,
HTMLElement: typeof HTMLElement,
SVGElement: typeof SVGElement,
DocumentFragment: typeof DocumentFragment,
MutationObserver?: typeof MutationObserver
};
export function register(dom: JSDOM): Promise<{
el: typeof el,
assign: typeof assign,

View File

@ -1,23 +1,25 @@
//TODO: https://www.npmjs.com/package/html-element
import { enviroment } from './src/dom-common.js';
enviroment.ssr= " ssr";
const { setDeleteAttr }= enviroment;
import { enviroment as env } from './src/dom-common.js';
env.ssr= " ssr";
const { setDeleteAttr }= env;
/** @param {HTMLElement} obj */
enviroment.setDeleteAttr= function(obj, prop, value){
env.setDeleteAttr= function(obj, prop, value){
if("value"===prop) return obj.setAttribute(prop, value);
if("checked"!==prop) return setDeleteAttr(obj, prop, value);
if(value) return obj.setAttribute(prop, "");
obj.removeAttribute(prop);
};
const keys= [ "HTMLElement", "SVGElement", "DocumentFragment", "MutationObserver", "document" ];
const keys= { H: "HTMLElement", S: "SVGElement", F: "DocumentFragment", M: "MutationObserver", D: "document" };
let env_bk= {};
let dom_last;
export function register(dom, keys_aditional= []){
export function register(dom){
if(dom_last!==dom){
keys.push(...keys_aditional);
const w= dom.window;
keys.forEach(key=> globalThis[key]= w[key]);
globalThis.window= w;
Object.entries(keys).forEach(([ kE, kW ])=> {
env_bk[kE]= env[kE];
env[kE]= w[kW];
});
w.console= globalThis.console;
}
dom_last= dom;
@ -28,8 +30,8 @@ export function unregister(){
if(!dom_last)
return false;
keys.forEach(key=> Reflect.deleteProperty(globalThis, key));
Reflect.deleteProperty(globalThis, "window");
Object.assign(env, env_bk);
env_bk= {};
dom_last= undefined;
return true;
}

View File

@ -59,7 +59,7 @@
"size-limit": [
{
"path": "./index.js",
"limit": "9.9 kB",
"limit": "10 kB",
"gzip": false,
"brotli": false

View File

@ -1,4 +1,12 @@
export const enviroment= { setDeleteAttr, ssr: "" };
export const enviroment= {
setDeleteAttr,
ssr: "",
D: globalThis.document,
F: globalThis.DocumentFragment,
H: globalThis.HTMLElement,
S: globalThis.SVGElement,
M: globalThis.MutationObserver,
};
import { isUndef } from './helpers.js';
function setDeleteAttr(obj, prop, val){
/* Issue
@ -13,7 +21,7 @@ function setDeleteAttr(obj, prop, val){
Reflect.set(obj, prop, val);
if(!isUndef(val)) return;
Reflect.deleteProperty(obj, prop);
if(obj instanceof HTMLElement && obj.getAttribute(prop)==="undefined")
if(obj instanceof enviroment.H && obj.getAttribute(prop)==="undefined")
return obj.removeAttribute(prop);
if(Reflect.get(obj, prop)==="undefined")
return Reflect.set(obj, prop, "");

View File

@ -1,10 +1,10 @@
import { observables } from "./observables-common.js";
import { enviroment } from './dom-common.js';
import { enviroment as env } from './dom-common.js';
/** @type {{ scope: object, prevent: boolean, host: function }[]} */
const scopes= [ {
scope: document.body,
host: c=> c ? c(document.body) : document.body,
get scope(){ return env.D.body; },
host: c=> c ? c(env.D.body) : env.D.body,
custom_element: false,
prevent: true,
} ];
@ -43,7 +43,7 @@ export function createElement(tag, attributes, ...addons){
scoped= 1;
scope.push({ scope: tag, host: (...c)=> c.length ? (scoped===1 ? addons.unshift(...c) : c.forEach(c=> c(el_host)), undefined) : el_host });
el= tag(attributes || undefined);
const is_fragment= el instanceof DocumentFragment;
const is_fragment= el instanceof env.F;
if(el.nodeName==="#comment") break;
const el_mark= createElement.mark({
type: "component",
@ -54,10 +54,10 @@ export function createElement(tag, attributes, ...addons){
if(is_fragment) el_host= el_mark;
break;
}
case tag==="#text": el= assign.call(this, document.createTextNode(""), attributes); break;
case tag==="<>" || !tag: el= assign.call(this, document.createDocumentFragment(), attributes); break;
case Boolean(namespace): el= assign.call(this, document.createElementNS(namespace, tag), attributes); break;
case !el: el= assign.call(this, document.createElement(tag), attributes);
case tag==="#text": el= assign.call(this, env.D.createTextNode(""), attributes); break;
case tag==="<>" || !tag: el= assign.call(this, env.D.createDocumentFragment(), attributes); break;
case Boolean(namespace): el= assign.call(this, env.D.createElementNS(namespace, tag), attributes); break;
case !el: el= assign.call(this, env.D.createElement(tag), attributes);
}
chainableAppend(el);
if(!el_host) el_host= el;
@ -76,7 +76,7 @@ export function simulateSlots(element, root= element, mapper= undefined){
apply(orig, _, els){
if(!els.length) return element;
const d= document.createDocumentFragment();
const d= env.D.createDocumentFragment();
for(const el of els){
if(!el || !el.slot){ if(has_d) d.appendChild(el); continue; }
const name= el.slot;
@ -113,8 +113,8 @@ function simulateSlotReplace(slot, element, mapper){
createElement.mark= function(attrs, is_open= false){
attrs= Object.entries(attrs).map(([ n, v ])=> n+`="${v}"`).join(" ");
const end= is_open ? "" : "/";
const out= document.createComment(`<dde:mark ${attrs}${enviroment.ssr}${end}>`);
if(!is_open) out.end= document.createComment("</dde:mark>");
const out= env.D.createComment(`<dde:mark ${attrs}${env.ssr}${end}>`);
if(!is_open) out.end= env.D.createComment("</dde:mark>");
return out;
};
export { createElement as el };
@ -131,8 +131,8 @@ export function createElementNS(ns){
}
export { createElementNS as elNS };
const { setDeleteAttr }= enviroment;
const assign_context= new WeakMap();
const { setDeleteAttr }= env;
export function assign(element, ...attributes){
if(!attributes.length) return element;
assign_context.set(element, assignContext(element, this));
@ -175,7 +175,7 @@ export function assignAttribute(element, key, value){
}
function assignContext(element, _this){
if(assign_context.has(element)) return assign_context.get(element);
const is_svg= element instanceof SVGElement;
const is_svg= element instanceof env.S;
const setRemoveAttr= (is_svg ? setRemoveNS : setRemove).bind(null, element, "Attribute");
const s= observables(_this);
return { setRemoveAttr, s };
@ -192,7 +192,7 @@ export function empty(el){
return el;
}
export function elementAttribute(element, op, key, value){
if(element instanceof HTMLElement)
if(element instanceof env.H)
return element[op+"Attribute"](key, value);
return element[op+"AttributeNS"](null, key, value);
}

View File

@ -1,4 +1,5 @@
export { registerReactivity } from './observables-common.js';
import { enviroment as env } from './dom-common.js';
export function dispatchEvent(name, options, host){
if(!options) options= {};
@ -18,7 +19,9 @@ export function on(event, listener, options){
};
}
const c_ch_o= connectionsChangesObserverConstructor();
const c_ch_o= env.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
get(){ return ()=> {}; }
});
const els_attribute_store= new WeakSet();
import { scope } from "./dom.js";
import { onAbort } from './helpers.js';
@ -77,7 +80,9 @@ on.attributeChanged= function(listener, options){
if(element.__dde_lifecycleToEvents || els_attribute_store.has(element))
return element;
const observer= new MutationObserver(function(mutations){
if(!env.M) return element;
const observer= new env.M(function(mutations){
for(const { attributeName, target } of mutations)
target.dispatchEvent(
new CustomEvent(event, { detail: [ attributeName, target.getAttribute(attributeName) ] }));
@ -92,7 +97,7 @@ on.attributeChanged= function(listener, options){
function connectionsChangesObserverConstructor(){
const store= new Map();
let is_observing= false;
const observer= new MutationObserver(function(mutations){
const observer= new env.M(function(mutations){
for(const mutation of mutations){
if(mutation.type!=="childList") continue;
if(observerAdded(mutation.addedNodes, true)){
@ -155,7 +160,7 @@ function connectionsChangesObserverConstructor(){
function start(){
if(is_observing) return;
is_observing= true;
observer.observe(document.body, { childList: true, subtree: true });
observer.observe(env.D.body, { childList: true, subtree: true });
}
function stop(){
if(!is_observing || store.size) return;

View File

@ -86,12 +86,13 @@ observable.clear= function(...observables){
}
};
const key_reactive= "__dde_reactive";
import { el, elementAttribute } from "./dom.js";
import { enviroment as env } from "./dom-common.js";
import { el } from "./dom.js";
import { scope } from "./dom.js";
observable.el= function(o, map){
const mark_start= el.mark({ type: "reactive" }, false);
const mark_end= mark_start.end;
const out= document.createDocumentFragment();
const out= env.D.createDocumentFragment();
out.append(mark_start, mark_end);
const { current }= scope;
const reRenderReactiveElement= v=> {