mirror of
https://github.com/jaandrle/deka-dom-el
synced 2024-11-23 00:59:38 +01:00
Compare commits
No commits in common. "971b5959275f7ccba9fd1790d61088f31428b4c6" and "a5d43e692568d2dddd7baae09f42cf6c9c82eacd" have entirely different histories.
971b595927
...
a5d43e6925
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 lifecyclesToEvents<EL extends HTMLElement>(custom_element: EL): EL
|
export function lifecycleToEvents<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 lifecyclesToEvents<EL extends HTMLElement>(custom_element: EL): EL
|
export function lifecycleToEvents<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 { lifecyclesToEvents } from "deka-dom-el";
|
import { lifecycleToEvents } 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" ];
|
||||||
@ -31,4 +31,4 @@ import { lifecyclesToEvents } from "deka-dom-el";
|
|||||||
set customAttribute(value){ this.setAttribute("custom-attribute", value); }
|
set customAttribute(value){ this.setAttribute("custom-attribute", value); }
|
||||||
}
|
}
|
||||||
customElements.define(CustomHTMLElement.tagName, CustomHTMLElement);
|
customElements.define(CustomHTMLElement.tagName, CustomHTMLElement);
|
||||||
</code></div><p><a href="https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4" title="Ideas and tips from WebReflection">Handy Custom Elements' Patterns</a></p><div class="notice"><!--<dde:mark type="component" name="mnemonic" host="parentElement" ssr/>--><h3 id="h-mnemonic"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-mnemonic" tabindex="-1">#</a> Mnemonic</h3><ul><li><code>customElementRender(<custom-element>, <render-function>[, <properties>])</code> — use function to render DOM structure for given <custom-element></li><li><code>customElementWithDDE(<custom-element>)</code> — register <custom-element> to DDE library, see also `lifecycleToEvents`, can be also used as decorator</li><li><code>observedAttributes(<custom-element>)</code> — returns record of observed attributes (keys uses camelCase)</li><li><code>O.observedAttributes(<custom-element>)</code> — returns record of observed attributes (keys uses camelCase and values are observables)</li><li><code>lifecycleToEvents(<class-declaration>)</code> — convert lifecycle methods to events, can be also used as decorator</li></ul></div><div class="prevNext"><!--<dde:mark type="component" name="prevNext" host="parentElement" ssr/>--><a rel="prev" href="p05-scopes" title="Organizing UI into components"><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr/>-->Scopes and components (previous)</a><!--<dde:mark type="component" name="pageLink" host="this" ssr/>--></div></main></body></html>
|
</code></div><p><a href="https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4" title="Ideas and tips from WebReflection">Handy Custom Elements' Patterns</a></p><div class="notice"><!--<dde:mark type="component" name="mnemonic" host="parentElement" ssr/>--><h3 id="h-mnemonic"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-mnemonic" tabindex="-1">#</a> Mnemonic</h3><ul><li><code>customElementRender(<custom-element>, <render-function>[, <properties>])</code> — use function to render DOM structure for given <custom-element></li><li><code>customElementWithDDE(<custom-element>)</code> — register <custom-element> to DDE library, see also `lifecycleToEvents`, can be also used as decorator</li><li><code>observedAttributes(<custom-element>)</code> — returns record of observed attributes (keys uses camelCase)</li><li><code>O.observedAttributes(<custom-element>)</code> — returns record of observed attributes (keys uses camelCase and values are observables)</li><li><code>lifecycleToEvents(<class-declaration>)</code> — convert lifecycle methods to events, can be also used as decorator</li></ul></div><div class="prevNext"><!--<dde:mark type="component" name="prevNext" host="parentElement" ssr/>--><a rel="prev" href="p05-scopes" title="Organizing UI into components"><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr/>-->Scopes and components (previous)</a><!--<dde:mark type="component" name="pageLink" host="this" ssr/>--></div></main></body></html>
|
@ -9,4 +9,4 @@ import { O } from "deka-dom-el/observables";
|
|||||||
O.observedAttributes;
|
O.observedAttributes;
|
||||||
|
|
||||||
// “internal” utils
|
// “internal” utils
|
||||||
import { lifecyclesToEvents } from "deka-dom-el";
|
import { lifecycleToEvents } 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 `lifecyclesToEvents`, can be also used as decorator",
|
el("code", "customElementWithDDE(<custom-element>)"), " — register <custom-element> to DDE library, see also `lifecycleToEvents`, 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", "lifecyclesToEvents(<class-declaration>)"), " — convert lifecycle methods to events, can be also used as decorator",
|
el("code", "lifecycleToEvents(<class-declaration>)"), " — convert lifecycle methods to events, can be also used as decorator",
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,10 @@ const className= style.host(todosComponent).css`
|
|||||||
`;
|
`;
|
||||||
/** @param {{ todos: string[] }} */
|
/** @param {{ todos: string[] }} */
|
||||||
export function todosComponent({ todos= [ "Task A" ] }= {}){
|
export function todosComponent({ todos= [ "Task A" ] }= {}){
|
||||||
let key= 0;
|
const todosO= O(todos.map(t=> O(t)), {
|
||||||
const todosO= O(new Map(), {
|
add(v){ this.value.push(O(v)); },
|
||||||
add(v){ this.value.set(key++, O(v)); },
|
remove(i){ O.clear(this.value.splice(i, 1)[0]); }
|
||||||
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=> {
|
||||||
@ -33,16 +31,24 @@ 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, memo)=> !ts.size
|
O.el(todosO, ts=> !ts.length
|
||||||
? el("p", "No todos yet")
|
? el("p", "No todos yet")
|
||||||
: el("ul").append(
|
: ( !(ul_todos_version-1) ? ul_todos_v1 : ul_todos_v2(ts) )
|
||||||
...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.")
|
||||||
),
|
),
|
||||||
@ -55,7 +61,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(Array.from(todosO()), null, "\t")))
|
el("output", O(()=> JSON.stringify(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 lifecyclesToEvents<EL extends HTMLElement>(custom_element: EL): EL
|
export function lifecycleToEvents<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.25 kB"
|
"limit": "5 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) lifecyclesToEvents(custom_element);
|
if(!is_lte) lifecycleToEvents(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 lifecyclesToEvents(class_declaration){
|
export function lifecycleToEvents(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 lifecyclesToEvents(class_declaration){
|
|||||||
class_declaration.prototype[keyLTE]= true;
|
class_declaration.prototype[keyLTE]= true;
|
||||||
return class_declaration;
|
return class_declaration;
|
||||||
}
|
}
|
||||||
export { lifecyclesToEvents as customElementWithDDE };
|
export { lifecycleToEvents 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_lifecyclesToEvents"; //boolean
|
export const keyLTE= "__dde_lifecycleToEvents"; //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,13 +65,12 @@ 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= hasOwn(slots, _default);
|
const has_d= Reflect.has(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;
|
||||||
@ -199,7 +198,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(!(key in el)) return false;
|
if(!Reflect.has(el, key)) return false;
|
||||||
const des= getPropDescriptor(el, key);
|
const des= getPropDescriptor(el, key);
|
||||||
return !isUndef(des.set);
|
return !isUndef(des.set);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
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;
|
||||||
@ -20,7 +19,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){
|
||||||
out[kebabToCamel(name)]= observedAttribute(instance, name);
|
Reflect.set(out, kebabToCamel(name), observedAttribute(instance, name));
|
||||||
return out;
|
return out;
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
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 hasOwn(candidate, mark); }
|
try{ return Reflect.has(candidate, mark); }
|
||||||
catch(e){ return false; }
|
catch(e){ return false; }
|
||||||
}
|
}
|
||||||
/** @type {function[]} */
|
/** @type {function[]} */
|
||||||
@ -46,10 +45,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 || !(name in actions))
|
if(!actions || !Reflect.has(actions, name))
|
||||||
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 (delete s.skip);
|
if(s.skip) return Reflect.deleteProperty(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= {}){
|
||||||
@ -66,12 +65,11 @@ 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);
|
||||||
delete o[mark];
|
Reflect.deleteProperty(o, mark);
|
||||||
}
|
}
|
||||||
function clearListDeps(o, s){
|
function clearListDeps(o, s){
|
||||||
s.listeners.forEach(l=> {
|
s.listeners.forEach(l=> {
|
||||||
@ -91,38 +89,24 @@ 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, function useCache(key, fun){
|
let els= map(v);
|
||||||
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 ];
|
||||||
mark_start.after(...els);
|
let el_r= mark_start;
|
||||||
const el_last_keep= els[els.length-1];
|
while(( el_r= mark_start.nextSibling ) !== mark_end)
|
||||||
let el_r;
|
|
||||||
while(( el_r= el_last_keep.nextSibling ) !== mark_end)
|
|
||||||
el_r.remove();
|
el_r.remove();
|
||||||
|
mark_start.after(...els);
|
||||||
if(mark_start.isConnected)
|
if(mark_start.isConnected)
|
||||||
requestCleanUpReactives(current.host());
|
requestCleanUpReactives(current.host());
|
||||||
};
|
};
|
||||||
@ -199,7 +183,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] && o[mark].host && o[mark].host() === element))
|
removeObservableListener(o, listener, o[mark]?.host() === element))
|
||||||
)(element);
|
)(element);
|
||||||
}
|
}
|
||||||
element[key_reactive].push([ [ o, listener ], ...notes ]);
|
element[key_reactive].push([ [ o, listener ], ...notes ]);
|
||||||
@ -232,7 +216,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]);
|
||||||
delete actions[ocs];
|
Reflect.deleteProperty(actions, ocs);
|
||||||
}
|
}
|
||||||
const { host }= scope;
|
const { host }= scope;
|
||||||
Reflect.defineProperty(o, mark, {
|
Reflect.defineProperty(o, mark, {
|
||||||
@ -286,4 +270,4 @@ function removeObservableListener(o, listener, clear_when_empty){
|
|||||||
deps.get(c).forEach(sig=> removeObservableListener(sig, c, true));
|
deps.get(c).forEach(sig=> removeObservableListener(sig, c, true));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user