mirror of
				https://github.com/jaandrle/deka-dom-el
				synced 2025-11-04 07:09:15 +01:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			a5d43e6925
			...
			971b595927
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						971b595927
	
				 | 
					
					
						|||
| b740b8e020 | 
							
								
								
									
										52
									
								
								dist/dde-with-observables.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								dist/dde-with-observables.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										32
									
								
								dist/dde.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								dist/dde.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/esm-with-observables.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/esm-with-observables.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -245,7 +245,7 @@ export function customElementRender<
 | 
				
			|||||||
	props?: P | ((...args: any[])=> P)
 | 
						props?: P | ((...args: any[])=> P)
 | 
				
			||||||
): EL
 | 
					): EL
 | 
				
			||||||
export function customElementWithDDE<EL extends HTMLElement>(custom_element: EL): EL
 | 
					export function customElementWithDDE<EL extends HTMLElement>(custom_element: EL): EL
 | 
				
			||||||
export function lifecycleToEvents<EL extends HTMLElement>(custom_element: EL): EL
 | 
					export function lifecyclesToEvents<EL extends HTMLElement>(custom_element: EL): EL
 | 
				
			||||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>
 | 
					export function observedAttributes(custom_element: HTMLElement): Record<string, string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TypeScript MEH */
 | 
					/* TypeScript MEH */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								dist/esm-with-observables.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								dist/esm-with-observables.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/esm.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/esm.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -245,7 +245,7 @@ export function customElementRender<
 | 
				
			|||||||
	props?: P | ((...args: any[])=> P)
 | 
						props?: P | ((...args: any[])=> P)
 | 
				
			||||||
): EL
 | 
					): EL
 | 
				
			||||||
export function customElementWithDDE<EL extends HTMLElement>(custom_element: EL): EL
 | 
					export function customElementWithDDE<EL extends HTMLElement>(custom_element: EL): EL
 | 
				
			||||||
export function lifecycleToEvents<EL extends HTMLElement>(custom_element: EL): EL
 | 
					export function lifecyclesToEvents<EL extends HTMLElement>(custom_element: EL): EL
 | 
				
			||||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>
 | 
					export function observedAttributes(custom_element: HTMLElement): Record<string, string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TypeScript MEH */
 | 
					/* TypeScript MEH */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								dist/esm.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/esm.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -9,7 +9,7 @@ import { O } from "deka-dom-el/observables";
 | 
				
			|||||||
O.observedAttributes;
 | 
					O.observedAttributes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// “internal” utils
 | 
					// “internal” utils
 | 
				
			||||||
import { lifecycleToEvents } from "deka-dom-el";
 | 
					import { lifecyclesToEvents } from "deka-dom-el";
 | 
				
			||||||
</code></div><h3 id="h-custom-elements-introduction"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-custom-elements-introduction" tabindex="-1">#</a> Custom Elements Introduction</h3><p><a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements" title="Article about custom elements on MDN">Using custom elements</a></p><div class="code" data-js="todo"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">class CustomHTMLElement extends HTMLElement{
 | 
					</code></div><h3 id="h-custom-elements-introduction"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-custom-elements-introduction" tabindex="-1">#</a> Custom Elements Introduction</h3><p><a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements" title="Article about custom elements on MDN">Using custom elements</a></p><div class="code" data-js="todo"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">class CustomHTMLElement extends HTMLElement{
 | 
				
			||||||
	static tagName = "custom-element"; // just suggestion, we can use `el(CustomHTMLElement.tagName)`
 | 
						static tagName = "custom-element"; // just suggestion, we can use `el(CustomHTMLElement.tagName)`
 | 
				
			||||||
	static observedAttributes= [ "custom-attribute" ];
 | 
						static observedAttributes= [ "custom-attribute" ];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,4 +9,4 @@ import { O } from "deka-dom-el/observables";
 | 
				
			|||||||
O.observedAttributes;
 | 
					O.observedAttributes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// “internal” utils
 | 
					// “internal” utils
 | 
				
			||||||
import { lifecycleToEvents } from "deka-dom-el";
 | 
					import { lifecyclesToEvents } from "deka-dom-el";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ export function mnemonic(){
 | 
				
			|||||||
			el("code", "customElementRender(<custom-element>, <render-function>[, <properties>])"), " — use function to render DOM structure for given <custom-element>",
 | 
								el("code", "customElementRender(<custom-element>, <render-function>[, <properties>])"), " — use function to render DOM structure for given <custom-element>",
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		el("li").append(
 | 
							el("li").append(
 | 
				
			||||||
			el("code", "customElementWithDDE(<custom-element>)"), " — register <custom-element> to DDE library, see also `lifecycleToEvents`, can be also used as decorator",
 | 
								el("code", "customElementWithDDE(<custom-element>)"), " — register <custom-element> to DDE library, see also `lifecyclesToEvents`, can be also used as decorator",
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		el("li").append(
 | 
							el("li").append(
 | 
				
			||||||
			el("code", "observedAttributes(<custom-element>)"), " — returns record of observed attributes (keys uses camelCase)",
 | 
								el("code", "observedAttributes(<custom-element>)"), " — returns record of observed attributes (keys uses camelCase)",
 | 
				
			||||||
@@ -16,7 +16,7 @@ export function mnemonic(){
 | 
				
			|||||||
			el("code", "O.observedAttributes(<custom-element>)"), " — returns record of observed attributes (keys uses camelCase and values are observables)",
 | 
								el("code", "O.observedAttributes(<custom-element>)"), " — returns record of observed attributes (keys uses camelCase and values are observables)",
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		el("li").append(
 | 
							el("li").append(
 | 
				
			||||||
			el("code", "lifecycleToEvents(<class-declaration>)"), " — convert lifecycle methods to events, can be also used as decorator",
 | 
								el("code", "lifecyclesToEvents(<class-declaration>)"), " — convert lifecycle methods to events, can be also used as decorator",
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,10 +16,12 @@ const className= style.host(todosComponent).css`
 | 
				
			|||||||
`;
 | 
					`;
 | 
				
			||||||
/** @param {{ todos: string[] }} */
 | 
					/** @param {{ todos: string[] }} */
 | 
				
			||||||
export function todosComponent({ todos= [ "Task A" ] }= {}){
 | 
					export function todosComponent({ todos= [ "Task A" ] }= {}){
 | 
				
			||||||
	const todosO= O(todos.map(t=> O(t)), {
 | 
						let key= 0;
 | 
				
			||||||
		add(v){ this.value.push(O(v)); },
 | 
						const todosO= O(new Map(), {
 | 
				
			||||||
		remove(i){ O.clear(this.value.splice(i, 1)[0]); }
 | 
							add(v){ this.value.set(key++, O(v)); },
 | 
				
			||||||
 | 
							remove(key){ O.clear(this.value.get(key)); this.value.delete(key); }
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
						todos.forEach(text=> O.action(todosO, "add", text));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const name= "todoName";
 | 
						const name= "todoName";
 | 
				
			||||||
	const onsubmitAdd= on("submit", event=> {
 | 
						const onsubmitAdd= on("submit", event=> {
 | 
				
			||||||
@@ -31,24 +33,16 @@ export function todosComponent({ todos= [ "Task A" ] }= {}){
 | 
				
			|||||||
	const onremove= on("remove", event=>
 | 
						const onremove= on("remove", event=>
 | 
				
			||||||
		O.action(todosO, "remove", event.detail));
 | 
							O.action(todosO, "remove", event.detail));
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	const ul_todos_version= 1; // ul_todos_v1/ul_todos_v2
 | 
					 | 
				
			||||||
	const ul_todos_v1= el("ul").append(
 | 
					 | 
				
			||||||
		O.el(todosO, ts=> ts
 | 
					 | 
				
			||||||
			.map((textContent, value)=>
 | 
					 | 
				
			||||||
				el(todoComponent, { textContent, value, className }, onremove))
 | 
					 | 
				
			||||||
	));
 | 
					 | 
				
			||||||
	const ul_todos_v2= ts=> el("ul").append(
 | 
					 | 
				
			||||||
		...ts.map((textContent, value)=>
 | 
					 | 
				
			||||||
			el(todoComponent, { textContent, value, className }, onremove))
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	return el("div", { className }).append(
 | 
						return el("div", { className }).append(
 | 
				
			||||||
		el("div").append(
 | 
							el("div").append(
 | 
				
			||||||
			el("h2", "Todos:"),
 | 
								el("h2", "Todos:"),
 | 
				
			||||||
			el("h3", "List of todos:"),
 | 
								el("h3", "List of todos:"),
 | 
				
			||||||
			O.el(todosO, ts=> !ts.length
 | 
								O.el(todosO, (ts, memo)=> !ts.size
 | 
				
			||||||
				? el("p", "No todos yet")
 | 
									? el("p", "No todos yet")
 | 
				
			||||||
				: ( !(ul_todos_version-1) ? ul_todos_v1 : ul_todos_v2(ts) )
 | 
									: el("ul").append(
 | 
				
			||||||
 | 
										...Array.from(ts).map(([ value, textContent ])=>
 | 
				
			||||||
 | 
											memo(value, ()=> el(todoComponent, { textContent, value, className }, onremove)))
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
			),
 | 
								),
 | 
				
			||||||
			el("p", "Click to the text to edit it.")
 | 
								el("p", "Click to the text to edit it.")
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
@@ -61,7 +55,7 @@ export function todosComponent({ todos= [ "Task A" ] }= {}){
 | 
				
			|||||||
		),
 | 
							),
 | 
				
			||||||
		el("div").append(
 | 
							el("div").append(
 | 
				
			||||||
			el("h3", "Output (JSON):"),
 | 
								el("h3", "Output (JSON):"),
 | 
				
			||||||
			el("output", O(()=> JSON.stringify(todosO, null, "\t")))
 | 
								el("output", O(()=> JSON.stringify(Array.from(todosO()), null, "\t")))
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								index.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -180,7 +180,7 @@ export function customElementRender<
 | 
				
			|||||||
	props?: P | ((...args: any[])=> P)
 | 
						props?: P | ((...args: any[])=> P)
 | 
				
			||||||
): EL
 | 
					): EL
 | 
				
			||||||
export function customElementWithDDE<EL extends HTMLElement>(custom_element: EL): EL
 | 
					export function customElementWithDDE<EL extends HTMLElement>(custom_element: EL): EL
 | 
				
			||||||
export function lifecycleToEvents<EL extends HTMLElement>(custom_element: EL): EL
 | 
					export function lifecyclesToEvents<EL extends HTMLElement>(custom_element: EL): EL
 | 
				
			||||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>
 | 
					export function observedAttributes(custom_element: HTMLElement): Record<string, string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TypeScript MEH */
 | 
					/* TypeScript MEH */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,7 +79,7 @@
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"path": "./index-with-observables.js",
 | 
								"path": "./index-with-observables.js",
 | 
				
			||||||
			"limit": "5 kB"
 | 
								"limit": "5.25 kB"
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	],
 | 
						],
 | 
				
			||||||
	"modifyEsbuildConfig": {
 | 
						"modifyEsbuildConfig": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ export function customElementRender(custom_element, target, render, props= obser
 | 
				
			|||||||
	});
 | 
						});
 | 
				
			||||||
	if(typeof props==="function") props= props.call(custom_element, custom_element);
 | 
						if(typeof props==="function") props= props.call(custom_element, custom_element);
 | 
				
			||||||
	const is_lte= custom_element[keyLTE];
 | 
						const is_lte= custom_element[keyLTE];
 | 
				
			||||||
	if(!is_lte) lifecycleToEvents(custom_element);
 | 
						if(!is_lte) lifecyclesToEvents(custom_element);
 | 
				
			||||||
	const out= render.call(custom_element, props);
 | 
						const out= render.call(custom_element, props);
 | 
				
			||||||
	if(!is_lte) custom_element.dispatchEvent(new Event(evc));
 | 
						if(!is_lte) custom_element.dispatchEvent(new Event(evc));
 | 
				
			||||||
	if(target.nodeType===11 && typeof target.mode==="string") // is ShadowRoot
 | 
						if(target.nodeType===11 && typeof target.mode==="string") // is ShadowRoot
 | 
				
			||||||
@@ -16,7 +16,7 @@ export function customElementRender(custom_element, target, render, props= obser
 | 
				
			|||||||
	scope.pop();
 | 
						scope.pop();
 | 
				
			||||||
	return target.append(out);
 | 
						return target.append(out);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
export function lifecycleToEvents(class_declaration){
 | 
					export function lifecyclesToEvents(class_declaration){
 | 
				
			||||||
	wrapMethod(class_declaration.prototype, "connectedCallback", function(target, thisArg, detail){
 | 
						wrapMethod(class_declaration.prototype, "connectedCallback", function(target, thisArg, detail){
 | 
				
			||||||
		target.apply(thisArg, detail);
 | 
							target.apply(thisArg, detail);
 | 
				
			||||||
		thisArg.dispatchEvent(new Event(evc));
 | 
							thisArg.dispatchEvent(new Event(evc));
 | 
				
			||||||
@@ -37,7 +37,7 @@ export function lifecycleToEvents(class_declaration){
 | 
				
			|||||||
	class_declaration.prototype[keyLTE]= true;
 | 
						class_declaration.prototype[keyLTE]= true;
 | 
				
			||||||
	return class_declaration;
 | 
						return class_declaration;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
export { lifecycleToEvents as customElementWithDDE };
 | 
					export { lifecyclesToEvents as customElementWithDDE };
 | 
				
			||||||
function wrapMethod(obj, method, apply){
 | 
					function wrapMethod(obj, method, apply){
 | 
				
			||||||
	obj[method]= new Proxy(obj[method] || (()=> {}), { apply });
 | 
						obj[method]= new Proxy(obj[method] || (()=> {}), { apply });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ function setDeleteAttr(obj, prop, val){
 | 
				
			|||||||
	if(Reflect.get(obj, prop)==="undefined")
 | 
						if(Reflect.get(obj, prop)==="undefined")
 | 
				
			||||||
		return Reflect.set(obj, prop, "");
 | 
							return Reflect.set(obj, prop, "");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
export const keyLTE= "__dde_lifecycleToEvents"; //boolean
 | 
					export const keyLTE= "__dde_lifecyclesToEvents"; //boolean
 | 
				
			||||||
export const evc= "dde:connected";
 | 
					export const evc= "dde:connected";
 | 
				
			||||||
export const evd= "dde:disconnected";
 | 
					export const evd= "dde:disconnected";
 | 
				
			||||||
export const eva= "dde:attributeChanged";
 | 
					export const eva= "dde:attributeChanged";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,12 +65,13 @@ export function createElement(tag, attributes, ...addons){
 | 
				
			|||||||
	scoped= 2;
 | 
						scoped= 2;
 | 
				
			||||||
	return el;
 | 
						return el;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					import { hasOwn } from "./helpers.js";
 | 
				
			||||||
/** @param {HTMLElement} element @param {HTMLElement} [root] */
 | 
					/** @param {HTMLElement} element @param {HTMLElement} [root] */
 | 
				
			||||||
export function simulateSlots(element, root= element, mapper= undefined){
 | 
					export function simulateSlots(element, root= element, mapper= undefined){
 | 
				
			||||||
	const _default= Symbol.for("default");
 | 
						const _default= Symbol.for("default");
 | 
				
			||||||
	const slots= Array.from(root.querySelectorAll("slot"))
 | 
						const slots= Array.from(root.querySelectorAll("slot"))
 | 
				
			||||||
		.reduce((out, curr)=> Reflect.set(out, curr.name || _default, curr) && out, {});
 | 
							.reduce((out, curr)=> Reflect.set(out, curr.name || _default, curr) && out, {});
 | 
				
			||||||
	const has_d= Reflect.has(slots, _default);
 | 
						const has_d= hasOwn(slots, _default);
 | 
				
			||||||
	element.append= new Proxy(element.append, {
 | 
						element.append= new Proxy(element.append, {
 | 
				
			||||||
		apply(orig, _, els){
 | 
							apply(orig, _, els){
 | 
				
			||||||
			if(!els.length) return element;
 | 
								if(!els.length) return element;
 | 
				
			||||||
@@ -198,7 +199,7 @@ export function elementAttribute(element, op, key, value){
 | 
				
			|||||||
import { isUndef } from "./helpers.js";
 | 
					import { isUndef } from "./helpers.js";
 | 
				
			||||||
//TODO add cache? `(Map/Set)<el.tagName+key,isUndef>`
 | 
					//TODO add cache? `(Map/Set)<el.tagName+key,isUndef>`
 | 
				
			||||||
function isPropSetter(el, key){
 | 
					function isPropSetter(el, key){
 | 
				
			||||||
	if(!Reflect.has(el, key)) return false;
 | 
						if(!(key in el)) return false;
 | 
				
			||||||
	const des= getPropDescriptor(el, key);
 | 
						const des= getPropDescriptor(el, key);
 | 
				
			||||||
	return !isUndef(des.set);
 | 
						return !isUndef(des.set);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					export const hasOwn= (...a)=> Object.prototype.hasOwnProperty.call(...a);
 | 
				
			||||||
export function isUndef(value){ return typeof value==="undefined"; }
 | 
					export function isUndef(value){ return typeof value==="undefined"; }
 | 
				
			||||||
export function typeOf(v){
 | 
					export function typeOf(v){
 | 
				
			||||||
	const t= typeof v;
 | 
						const t= typeof v;
 | 
				
			||||||
@@ -19,7 +20,7 @@ export function observedAttributes(instance, observedAttribute){
 | 
				
			|||||||
	const { observedAttributes= [] }= instance.constructor;
 | 
						const { observedAttributes= [] }= instance.constructor;
 | 
				
			||||||
	return observedAttributes
 | 
						return observedAttributes
 | 
				
			||||||
		.reduce(function(out, name){
 | 
							.reduce(function(out, name){
 | 
				
			||||||
			Reflect.set(out, kebabToCamel(name), observedAttribute(instance, name));
 | 
								out[kebabToCamel(name)]= observedAttribute(instance, name);
 | 
				
			||||||
			return out;
 | 
								return out;
 | 
				
			||||||
		}, {});
 | 
							}, {});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,8 @@
 | 
				
			|||||||
export const mark= "__dde_observable";
 | 
					export const mark= "__dde_observable";
 | 
				
			||||||
 | 
					import { hasOwn } from "./helpers.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function isObservable(candidate){
 | 
					export function isObservable(candidate){
 | 
				
			||||||
	try{ return Reflect.has(candidate, mark); }
 | 
						try{ return hasOwn(candidate, mark); }
 | 
				
			||||||
	catch(e){ return false; }
 | 
						catch(e){ return false; }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/** @type {function[]} */
 | 
					/** @type {function[]} */
 | 
				
			||||||
@@ -45,10 +46,10 @@ export function observable(value, actions){
 | 
				
			|||||||
export { observable as O };
 | 
					export { observable as O };
 | 
				
			||||||
observable.action= function(o, name, ...a){
 | 
					observable.action= function(o, name, ...a){
 | 
				
			||||||
	const s= o[mark], { actions }= s;
 | 
						const s= o[mark], { actions }= s;
 | 
				
			||||||
	if(!actions || !Reflect.has(actions, name))
 | 
						if(!actions || !(name in actions))
 | 
				
			||||||
		throw new Error(`'${o}' has no action with name '${name}'!`);
 | 
							throw new Error(`'${o}' has no action with name '${name}'!`);
 | 
				
			||||||
	actions[name].apply(s, a);
 | 
						actions[name].apply(s, a);
 | 
				
			||||||
	if(s.skip) return Reflect.deleteProperty(s, "skip");
 | 
						if(s.skip) return (delete s.skip);
 | 
				
			||||||
	s.listeners.forEach(l=> l(s.value));
 | 
						s.listeners.forEach(l=> l(s.value));
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
observable.on= function on(o, listener, options= {}){
 | 
					observable.on= function on(o, listener, options= {}){
 | 
				
			||||||
@@ -65,11 +66,12 @@ observable.symbols= {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
observable.clear= function(...observables){
 | 
					observable.clear= function(...observables){
 | 
				
			||||||
	for(const o of observables){
 | 
						for(const o of observables){
 | 
				
			||||||
		Reflect.deleteProperty(o, "toJSON");
 | 
					 | 
				
			||||||
		const s= o[mark];
 | 
							const s= o[mark];
 | 
				
			||||||
 | 
							if(!s) continue;
 | 
				
			||||||
 | 
							delete o.toJSON;
 | 
				
			||||||
		s.onclear.forEach(f=> f.call(s));
 | 
							s.onclear.forEach(f=> f.call(s));
 | 
				
			||||||
		clearListDeps(o, s);
 | 
							clearListDeps(o, s);
 | 
				
			||||||
		Reflect.deleteProperty(o, mark);
 | 
							delete o[mark];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	function clearListDeps(o, s){
 | 
						function clearListDeps(o, s){
 | 
				
			||||||
		s.listeners.forEach(l=> {
 | 
							s.listeners.forEach(l=> {
 | 
				
			||||||
@@ -89,24 +91,38 @@ const key_reactive= "__dde_reactive";
 | 
				
			|||||||
import { enviroment as env } from "./dom-common.js";
 | 
					import { enviroment as env } from "./dom-common.js";
 | 
				
			||||||
import { el } from "./dom.js";
 | 
					import { el } from "./dom.js";
 | 
				
			||||||
import { scope } from "./dom.js";
 | 
					import { scope } from "./dom.js";
 | 
				
			||||||
 | 
					// TODO: third argument for handle `cache_tmp` in re-render
 | 
				
			||||||
observable.el= function(o, map){
 | 
					observable.el= function(o, map){
 | 
				
			||||||
	const mark_start= el.mark({ type: "reactive" }, true);
 | 
						const mark_start= el.mark({ type: "reactive" }, true);
 | 
				
			||||||
	const mark_end= mark_start.end;
 | 
						const mark_end= mark_start.end;
 | 
				
			||||||
	const out= env.D.createDocumentFragment();
 | 
						const out= env.D.createDocumentFragment();
 | 
				
			||||||
	out.append(mark_start, mark_end);
 | 
						out.append(mark_start, mark_end);
 | 
				
			||||||
	const { current }= scope;
 | 
						const { current }= scope;
 | 
				
			||||||
 | 
						let cache= {};
 | 
				
			||||||
	const reRenderReactiveElement= v=> {
 | 
						const reRenderReactiveElement= v=> {
 | 
				
			||||||
		if(!mark_start.parentNode || !mark_end.parentNode) // isConnected or wasn’t yet rendered
 | 
							if(!mark_start.parentNode || !mark_end.parentNode) // === `isConnected` or wasn’t yet rendered
 | 
				
			||||||
			return removeObservableListener(o, reRenderReactiveElement);
 | 
								return removeObservableListener(o, reRenderReactiveElement);
 | 
				
			||||||
 | 
							const cache_tmp= cache; // will be reused in the useCache or removed in the while loop on the end
 | 
				
			||||||
 | 
							cache= {};
 | 
				
			||||||
		scope.push(current);
 | 
							scope.push(current);
 | 
				
			||||||
		let els= map(v);
 | 
							let els= map(v, function useCache(key, fun){
 | 
				
			||||||
 | 
								let value;
 | 
				
			||||||
 | 
								if(hasOwn(cache_tmp, key)){
 | 
				
			||||||
 | 
									value= cache_tmp[key];
 | 
				
			||||||
 | 
									delete cache_tmp[key];
 | 
				
			||||||
 | 
								} else
 | 
				
			||||||
 | 
									value= fun();
 | 
				
			||||||
 | 
								cache[key]= value;
 | 
				
			||||||
 | 
								return value;
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
		scope.pop();
 | 
							scope.pop();
 | 
				
			||||||
		if(!Array.isArray(els))
 | 
							if(!Array.isArray(els))
 | 
				
			||||||
			els= [ els ];
 | 
								els= [ els ];
 | 
				
			||||||
		let el_r= mark_start;
 | 
					 | 
				
			||||||
		while(( el_r= mark_start.nextSibling ) !== mark_end)
 | 
					 | 
				
			||||||
			el_r.remove();
 | 
					 | 
				
			||||||
		mark_start.after(...els);
 | 
							mark_start.after(...els);
 | 
				
			||||||
 | 
							const el_last_keep= els[els.length-1];
 | 
				
			||||||
 | 
							let el_r;
 | 
				
			||||||
 | 
							while(( el_r= el_last_keep.nextSibling ) !== mark_end)
 | 
				
			||||||
 | 
								el_r.remove();
 | 
				
			||||||
		if(mark_start.isConnected)
 | 
							if(mark_start.isConnected)
 | 
				
			||||||
			requestCleanUpReactives(current.host());
 | 
								requestCleanUpReactives(current.host());
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@@ -183,7 +199,7 @@ function removeObservablesFromElements(o, listener, ...notes){
 | 
				
			|||||||
				 * You can investigate the `__dde_reactive` key of the element.
 | 
									 * You can investigate the `__dde_reactive` key of the element.
 | 
				
			||||||
				 * */
 | 
									 * */
 | 
				
			||||||
				element[key_reactive].forEach(([ [ o, listener ] ])=>
 | 
									element[key_reactive].forEach(([ [ o, listener ] ])=>
 | 
				
			||||||
					removeObservableListener(o, listener, o[mark]?.host() === element))
 | 
										removeObservableListener(o, listener, o[mark] && o[mark].host && o[mark].host() === element))
 | 
				
			||||||
			)(element);
 | 
								)(element);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		element[key_reactive].push([ [ o, listener ], ...notes ]);
 | 
							element[key_reactive].push([ [ o, listener ], ...notes ]);
 | 
				
			||||||
@@ -216,7 +232,7 @@ function toObservable(o, value, actions, readonly= false){
 | 
				
			|||||||
	const { onclear: ocs }= observable.symbols;
 | 
						const { onclear: ocs }= observable.symbols;
 | 
				
			||||||
	if(actions[ocs]){
 | 
						if(actions[ocs]){
 | 
				
			||||||
		onclear.push(actions[ocs]);
 | 
							onclear.push(actions[ocs]);
 | 
				
			||||||
		Reflect.deleteProperty(actions, ocs);
 | 
							delete actions[ocs];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	const { host }= scope;
 | 
						const { host }= scope;
 | 
				
			||||||
	Reflect.defineProperty(o, mark, {
 | 
						Reflect.defineProperty(o, mark, {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user