1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2024-11-22 16:55:23 +01:00
This commit is contained in:
Jan Andrle 2024-01-04 16:05:41 +01:00
parent eb920f7bbd
commit 89f9880277
Signed by: jaandrle
GPG Key ID: B3A25AED155AFFAB
6 changed files with 42 additions and 17 deletions

View File

@ -7,7 +7,7 @@ export function mnemonic(){
el("code", "O(<value>)"), " — observable: reactive value",
),
el("li").append(
el("code", "O(()=> <computation>)"), " — observable: reactive value dependent on calculation using other observables",
el("code", "O(()=> <computation>)"), " — read-only observable: reactive value dependent on calculation using other observables",
),
el("li").append(
el("code", "O.on(<observable>, <listener>[, <options>])"), " — listen to the observable value changes",

View File

@ -88,7 +88,9 @@ export function page({ pkg, info }){
el("code", "ariaset"), " and ", el("code", "classList"), "."
),
el("p").append(
"For computation, you can use the derived observable (see above) like ", el("code", "assign(element, { textContent: O(()=> 'Hello '+WorldObservable()) })"), "."
"For computation, you can use the “derived observable” (see above) like ", el("code", "assign(element, { textContent: O(()=> 'Hello '+WorldObservable()) })"), ".",
" ",
"This is read-only observable its value is computed based on given function and updated when any observable used in the function changes."
),
el("p").append(
"To represent part of the template filled dynamically based on the observable value use ", el("code", "O.el(observable, DOMgenerator)"), ".",

View File

@ -1,4 +1,4 @@
import { style, el, O } from '../exports.js';
import { style, el, O, isObservable } from '../exports.js';
const className= style.host(thirdParty).css`
:host {
color: green;
@ -22,12 +22,13 @@ export function thirdParty(){
// Array.from((new URL(location)).searchParams.entries())
// .forEach(([ key, value ])=> O.action(store, "set", key, value));
// O.on(store, data=> history.replaceState("", "", "?"+(new URLSearchParams(JSON.parse(JSON.stringify(data)))).toString()));
useAdapter(store, store_adapter, {
useStore(store_adapter, {
onread(data){
Array.from(data.entries())
.forEach(([ key, value ])=> O.action(store, "set", key, value));
return store;
}
});
})();
return el("input", {
className,
value: store().value(),
@ -36,9 +37,14 @@ export function thirdParty(){
});
}
function useAdapter(observable, adapter, { onread, onbeforewrite }= {}){
if(!onread) onread= observable;
function useStore(adapter_in, { onread, onbeforewrite }= {}){
const adapter= typeof adapter_in === "function" ? { read: adapter_in } : adapter_in;
if(!onread) onread= O;
if(!onbeforewrite) onbeforewrite= data=> JSON.parse(JSON.stringify(data));
onread(adapter.read()); //TODO OK as synchronous
O.on(observable, data=> adapter.write(onbeforewrite(data)));
return function useStoreInner(data_read){
const observable= onread(adapter.read(data_read)); //TODO OK as synchronous
if(adapter.write && isObservable(observable))
O.on(observable, data=> adapter.write(onbeforewrite(data)));
return observable;
};
}

View File

@ -12,12 +12,13 @@ export class CustomHTMLTestElement extends HTMLElement{
}
connectedCallback(){
if(!this.hasAttribute("pre-name")) this.setAttribute("pre-name", "default");
console.log(observedAttributes(this));
this.attachShadow({ mode: "open" }).append(
customElementRender(this, this.render)
);
}
render({ test }){
render(test){
console.log(scope.state);
scope.host(
on.connected(()=> console.log(CustomHTMLTestElement)),

View File

@ -1,10 +1,11 @@
import { scope } from "./dom.js";
export function customElementRender(custom_element, render, props= custom_element){
export function customElementRender(custom_element, render, props= observedAttributes){
scope.push({
scope: custom_element,
host: (...c)=> c.length ? c.forEach(c=> c(custom_element)) : custom_element,
custom_element
});
if(typeof props==="function") props= props(custom_element);
const out= render.call(custom_element, props);
scope.pop();
return out;
@ -31,3 +32,17 @@ export { lifecycleToEvents as customElementWithDDE };
function wrapMethod(obj, method, apply){
obj[method]= new Proxy(obj[method] || (()=> {}), { apply });
}
function observedAttribute(instance, name){
const out= (...args)=> !args.length
? instance.getAttribute(name)
: instance.setAttribute(name, ...args);
out.attribute= name;
return out;
}
export function observedAttributes(instance){
const { observedAttributes= [] }= instance.constructor;
return observedAttributes
.map(name=> [ name.replace(/-./g, x=> x[1].toUpperCase()), name ])
.reduce((out, [ key, name ])=> ( Reflect.set(out, key, observedAttribute(instance, name)), out ), {});
}

View File

@ -18,16 +18,16 @@ const stack_watch= [];
const deps= new WeakMap();
export function observable(value, actions){
if(typeof value!=="function")
return create(value, actions);
return create(false, value, actions);
if(isObservable(value)) return value;
const out= create();
const out= create(true);
const contextReWatch= function(){
const [ origin, ...deps_old ]= deps.get(contextReWatch);
deps.set(contextReWatch, new Set([ origin ]));
stack_watch.push(contextReWatch);
out(value());
write(out, value());
stack_watch.pop();
if(!deps_old.length) return;
@ -180,9 +180,10 @@ function removeObservablesFromElements(o, listener, ...notes){
});
}
function create(value, actions){
const o= (...value)=>
value.length ? write(o, ...value) : read(o);
function create(is_readonly, value, actions){
const o= is_readonly
? ()=> read(o)
: (...value)=> value.length ? write(o, ...value) : read(o);
return toObservable(o, value, actions);
}
const protoSigal= Object.assign(Object.create(null), {