sinho 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.d.ts +9 -3
- package/dist/bundle.js +32 -22
- package/dist/bundle.min.js +1 -1
- package/dist/scope.d.ts +9 -3
- package/dist/scope.js +32 -22
- package/dist/scope.js.map +1 -1
- package/package.json +1 -1
- package/src/scope.ts +52 -28
package/dist/bundle.d.ts
CHANGED
|
@@ -18,6 +18,12 @@ interface Signal<out T> extends SignalLike<T> {
|
|
|
18
18
|
*/
|
|
19
19
|
peek(): T;
|
|
20
20
|
}
|
|
21
|
+
interface SignalOptions<T> extends SetSignalOptions {
|
|
22
|
+
/**
|
|
23
|
+
* A custom equality function to compare the new value with the old value.
|
|
24
|
+
*/
|
|
25
|
+
equals?: (a: T, b: T) => boolean;
|
|
26
|
+
}
|
|
21
27
|
interface SetSignalOptions {
|
|
22
28
|
/**
|
|
23
29
|
* Whether to force the update of the signal even if the new value has the
|
|
@@ -64,7 +70,7 @@ declare const useScope: <T = {}>() => Scope<T>;
|
|
|
64
70
|
* Creates a new signal with the given value.
|
|
65
71
|
* @returns A tuple with the signal and its setter.
|
|
66
72
|
*/
|
|
67
|
-
declare const useSignal: (<T>(value: T, opts?:
|
|
73
|
+
declare const useSignal: (<T>(value: T, opts?: SignalOptions<T>) => readonly [Signal<T>, SignalSetter<T>]) & (<T>(value?: T, opts?: SignalOptions<T | undefined>) => readonly [Signal<T | undefined>, SignalSetter<T | undefined>]);
|
|
68
74
|
/**
|
|
69
75
|
* Runs the given function in a batch.
|
|
70
76
|
*
|
|
@@ -78,7 +84,7 @@ declare const flushBatch: () => void;
|
|
|
78
84
|
*
|
|
79
85
|
* @param fn The computation function.
|
|
80
86
|
*/
|
|
81
|
-
declare const useMemo: <T>(fn: () => T, opts?:
|
|
87
|
+
declare const useMemo: <T>(fn: () => T, opts?: SignalOptions<T>) => Signal<T>;
|
|
82
88
|
/**
|
|
83
89
|
* Executes a function inside a subscope which can be manually destroyed.
|
|
84
90
|
*
|
|
@@ -107,7 +113,7 @@ interface RefSignalSetter<in T> {
|
|
|
107
113
|
/**
|
|
108
114
|
* Creates a new signal with write capabilities.
|
|
109
115
|
*/
|
|
110
|
-
declare const useRef: (<T>(value: T, opts?:
|
|
116
|
+
declare const useRef: (<T>(value: T, opts?: SignalOptions<T>) => RefSignal<T>) & (<T>(value?: T, opts?: SignalOptions<T | undefined>) => RefSignal<T | undefined>);
|
|
111
117
|
/**
|
|
112
118
|
* Represents a value that can be a signal or a constant value.
|
|
113
119
|
*
|
package/dist/bundle.js
CHANGED
|
@@ -52,25 +52,33 @@ const useSignal = (value, opts) => {
|
|
|
52
52
|
signal._effects = new Set();
|
|
53
53
|
signal.peek = () => value;
|
|
54
54
|
const setter = (arg, innerOpts) => {
|
|
55
|
-
|
|
55
|
+
const allOpts = { ...opts, ...innerOpts };
|
|
56
|
+
allOpts.equals ??= (a, b) => a === b;
|
|
56
57
|
if (currBatch) {
|
|
57
58
|
const newValue = typeof arg == "function"
|
|
58
59
|
? arg(signal.peek())
|
|
59
60
|
: arg;
|
|
60
|
-
if (
|
|
61
|
-
if (
|
|
61
|
+
if (allOpts?.force || !allOpts.equals(newValue, signal.peek())) {
|
|
62
|
+
if (allOpts?.force) {
|
|
62
63
|
value = newValue;
|
|
63
64
|
}
|
|
64
65
|
else {
|
|
65
66
|
currBatch._setters.push(() => (value = newValue));
|
|
66
67
|
}
|
|
67
|
-
if (!
|
|
68
|
-
signal._effects.forEach((effect) =>
|
|
68
|
+
if (!allOpts?.silent) {
|
|
69
|
+
signal._effects.forEach((effect) => {
|
|
70
|
+
if (effect._pure) {
|
|
71
|
+
currBatch._pureEffects.add(effect);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
currBatch._effects.add(effect);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
69
77
|
}
|
|
70
78
|
}
|
|
71
79
|
}
|
|
72
80
|
else {
|
|
73
|
-
useBatch(() => setter(arg,
|
|
81
|
+
useBatch(() => setter(arg, allOpts));
|
|
74
82
|
}
|
|
75
83
|
};
|
|
76
84
|
return [signal, setter];
|
|
@@ -84,7 +92,11 @@ const useSignal = (value, opts) => {
|
|
|
84
92
|
const useBatch = (fn) => {
|
|
85
93
|
if (currBatch)
|
|
86
94
|
return fn();
|
|
87
|
-
currBatch = {
|
|
95
|
+
currBatch = {
|
|
96
|
+
_setters: [],
|
|
97
|
+
_effects: new Set(),
|
|
98
|
+
_pureEffects: new Set(),
|
|
99
|
+
};
|
|
88
100
|
try {
|
|
89
101
|
const result = fn();
|
|
90
102
|
flushBatch();
|
|
@@ -95,25 +107,23 @@ const useBatch = (fn) => {
|
|
|
95
107
|
}
|
|
96
108
|
};
|
|
97
109
|
const flushBatch = () => {
|
|
98
|
-
|
|
99
|
-
|
|
110
|
+
while (currBatch &&
|
|
111
|
+
currBatch._setters.length +
|
|
112
|
+
currBatch._effects.size +
|
|
113
|
+
currBatch._pureEffects.size >
|
|
114
|
+
0) {
|
|
100
115
|
// Clean effect subscope
|
|
101
116
|
currBatch._effects.forEach((effect) => effect._clean?.());
|
|
102
117
|
// Run signal updates
|
|
103
118
|
currBatch._setters.forEach((setter) => setter());
|
|
104
119
|
currBatch._setters = [];
|
|
105
120
|
// Run next effect
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
currBatch._effects.delete(effect);
|
|
110
|
-
continue a;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
for (const effect of currBatch._effects) {
|
|
121
|
+
const effect = currBatch._pureEffects.values().next().value ??
|
|
122
|
+
currBatch._effects.values().next().value;
|
|
123
|
+
if (effect) {
|
|
114
124
|
effect._run();
|
|
125
|
+
currBatch._pureEffects.delete(effect);
|
|
115
126
|
currBatch._effects.delete(effect);
|
|
116
|
-
break;
|
|
117
127
|
}
|
|
118
128
|
}
|
|
119
129
|
};
|
|
@@ -174,12 +184,12 @@ const useEffect = (fn, deps) => {
|
|
|
174
184
|
* @param fn The computation function.
|
|
175
185
|
*/
|
|
176
186
|
const useMemo = (fn, opts) => {
|
|
177
|
-
const [memo, setMemo] = useSignal();
|
|
187
|
+
const [memo, setMemo] = useSignal(undefined, opts);
|
|
178
188
|
let firstTime = true;
|
|
179
189
|
pureEffectFlag = true;
|
|
180
190
|
try {
|
|
181
191
|
useEffect(() => {
|
|
182
|
-
setMemo(fn, firstTime ? {
|
|
192
|
+
setMemo(fn, firstTime ? { force: true } : {});
|
|
183
193
|
firstTime = false;
|
|
184
194
|
});
|
|
185
195
|
}
|
|
@@ -221,11 +231,11 @@ const useSubscope = (fn, opts) => {
|
|
|
221
231
|
/**
|
|
222
232
|
* Creates a new signal with write capabilities.
|
|
223
233
|
*/
|
|
224
|
-
const useRef = (value, opts) => {
|
|
234
|
+
const useRef = ((value, opts) => {
|
|
225
235
|
const [signal, setter] = useSignal(value, opts);
|
|
226
236
|
signal.set = setter;
|
|
227
237
|
return signal;
|
|
228
|
-
};
|
|
238
|
+
});
|
|
229
239
|
/**
|
|
230
240
|
* @namespace
|
|
231
241
|
*/
|
package/dist/bundle.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const t=t=>({t:t,o:[],i:[],l:{...t?.l},u(t){const n=o;o=this;try{return t()}finally{o=n}},h(){for(let t=this.i.length-1;t>=0;t--)this.i[t].h();this.i=[];for(let t=this.o.length-1;t>=0;t--){const n=this.o[t];n._?.(),n.u=()=>{},n.p.forEach((t=>t.o.delete(n))),n.p.clear()}this.o=[]}});let n,e,o=t(),s=!1;const r=()=>o,c=(t,o)=>{const r=()=>(!s&&n&&(n.p.add(r),r.o.add(n)),r.peek());r.o=new Set,r.peek=()=>t;const c=(n,s)=>{
|
|
1
|
+
const t=t=>({t:t,o:[],i:[],l:{...t?.l},u(t){const n=o;o=this;try{return t()}finally{o=n}},h(){for(let t=this.i.length-1;t>=0;t--)this.i[t].h();this.i=[];for(let t=this.o.length-1;t>=0;t--){const n=this.o[t];n._?.(),n.u=()=>{},n.p.forEach((t=>t.o.delete(n))),n.p.clear()}this.o=[]}});let n,e,o=t(),s=!1;const r=()=>o,c=(t,o)=>{const r=()=>(!s&&n&&(n.p.add(r),r.o.add(n)),r.peek());r.o=new Set,r.peek=()=>t;const c=(n,s)=>{const l={...o,...s};if(l.equals??=(t,n)=>t===n,e){const o="function"==typeof n?n(r.peek()):n;!l?.force&&l.equals(o,r.peek())||(l?.force?t=o:e.m.push((()=>t=o)),l?.silent||r.o.forEach((t=>{t.v?e.S.add(t):e.o.add(t)})))}else i((()=>c(n,l)))};return[r,c]},i=t=>{if(e)return t();e={m:[],o:new Set,S:new Set};try{const n=t();return l(),n}finally{e=void 0}},l=()=>{for(;e&&e.m.length+e.o.size+e.S.size>0;){e.o.forEach((t=>t._?.())),e.m.forEach((t=>t())),e.m=[];const t=e.S.values().next().value??e.o.values().next().value;t&&(t.u(),e.S.delete(t),e.o.delete(t))}};let u=!1;const f=(t,e)=>{const r=!!e,c={M:o,v:u,p:new Set,u(){const o=n,c=s;n=this;try{this.p.forEach((t=>t.o.delete(this))),this.p.clear(),e&&(s=!1,e.forEach((t=>t()))),s=r,this._?.();const n=this.M.u((()=>i(t)));this._=n?()=>{this.M.u((()=>i(n))),this._=null}:null}finally{n=o,s=c}}};o.o.push(c),c.u(),c.p.size||c._||o.o.pop()},a=(t,n)=>{const[e,o]=c(void 0,n);let s=!0;u=!0;try{f((()=>{o(t,s?{force:!0}:{}),s=!1}))}finally{u=!1}return e},d=(n,s)=>{const r=e;e=void 0;const c=o,i=t(c);Object.assign(i.l,s?.details);try{c.i.push(i);return[i.u(n),()=>{const t=c.i.indexOf(i);t>=0&&c.i.splice(t,1),i.h()}]}finally{e=r}},h=(t,n)=>{const[e,o]=c(t,n);return e.set=o,e},_={upgrade:t=>()=>_.get(t),get:t=>"function"==typeof t?t():t,peek(t){const n=s;s=!0;try{return this.get(t)}finally{s=n}}},p=(t={})=>({k:[],C(t){return this.N?.next().value??t()},...t}),m=()=>{const t=r();return t.l.j??=p()},y=(t,n)=>{const e=m(),o=p({...e,...t}),[s,r]=d(n,{details:{j:o}});return f((()=>r)),s},w=t=>(t[0]??"").toLowerCase()+t.slice(1).replace(/[A-Z]/g,(t=>"-"+t.toLowerCase())),b=t=>t.startsWith("on:")?t.slice(3):w(t.slice(2)),v=Symbol(),g=(t,n)=>({[v]:Math.random().toString(36).slice(2),H:t,L:n}),x=t=>!!t?.[v],S=(t,n,e)=>{n.addEventListener(t[v],(t=>{const n=_.get(e);void 0!==n&&(t.stopPropagation(),t.detail(n))}))},M=t=>{const n=m();return a((()=>{let e=t.H;return n.T?.dispatchEvent(new CustomEvent(t[v],{detail:t=>e=t,bubbles:!0,composed:!0})),e}))},k=(t,n)=>({A:"p",O:t,...n}),C=(t=CustomEvent)=>({A:"e",D:t}),E=Symbol();let N;const j=(t,n)=>{N?N.push([t,n]):f(t,n)},H=(t,n={},e={})=>{const o=[],s=new Map;for(const t in n){const e=n[t];if("p"==e.A&&e.attribute){"function"==typeof e.attribute&&(e.attribute={transform:e.attribute});const n=e.attribute={name:w(t),static:!1,transform:t=>t,...e.attribute};s.set(n.name,{name:t,meta:e}),n.static||o.push(n.name)}}e.shadow??={mode:"open"};class i extends HTMLElement{static[E]={I:t};static observedAttributes=o;props={};events={};[E]={};constructor(){super();for(const t in n){const e=n[t];if("p"==e.A){const n=x(e.O)?e.O:null,[o,s]=c(n?void 0:e.O);this.props[t]=o,n&&S(n,this,o),Object.defineProperty(this,t,{get:o.peek,set:t=>s((()=>t),{force:!0})})}else if("e"==e.A&&t.startsWith("on")){const n=b(t);this.events[t]=t=>this.dispatchEvent(new e.D(n,t))}}}connectedCallback(){const t=(n=this,e.shadow?n.shadowRoot??n.attachShadow(e.shadow):n);var n;this[E].$=d((()=>y({P:!1,T:this,N:t.childNodes.values()},(()=>{this[E].M=r();const n=N;N=[];try{t?.append(...this.render().build()),N.forEach((([t,n])=>f(t,n)))}finally{N=n}}))))[1]}disconnectedCallback(){this[E].$?.()}attributeChangedCallback(t,n,e){const o=s.get(t);o&&(this[o.name]=null!=e?o.meta.attribute.transform.call(this,e):x(o.meta.O)?void 0:o.meta.O)}}return i},L=t=>!!t?.[E],T=(...t)=>{const[n,e]="string"==typeof t[0]?[t[0],t.slice(1)]:["",t];for(const t of e)customElements.define(n+t[E].I,t)},A=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,O=(t,n,e)=>{"-"==n[0]?t.style.setProperty(n,""+e):t.style[n]=null==e?"":"number"!=typeof e||A.test(n)?""+e:e+"px"},D=(t,n,e,o)=>{const s=null==e||!1===e&&!n.includes("-");if(n.startsWith("prop:"))t[n.slice(5)]=e;else if(n.startsWith("attr:"))n=n.slice(5),s?t.removeAttribute(n):t.setAttribute(n,e);else if(!["innerHTML","outerHTML"].includes(n)){if(!["tabIndex","role",...o?["width","height","href","list","form","download","rowSpan","colSpan"]:[]].includes(n)&&n in t)try{return void(t[n]=e)}catch(t){}"function"==typeof e||(s?t.removeAttribute(n):t.setAttribute(n,e))}},I=t=>({build(){const n=t();return n.build?.()??n}}),$=({text:t,marker:n})=>I((()=>{const e=m(),o=n&&e.C((()=>document.createComment(""))),s=e.C((()=>document.createTextNode("")));return f((()=>{const n=""+(_.get(t)??"");s.textContent!=n&&(s.textContent=n)})),o?[o,s]:[s]})),z=({children:t})=>I((()=>Array.isArray(t)?t.flatMap((t=>z({children:t}).build())):null==t?[]:"object"==typeof t?t:$({text:t}))),P=(t,n,e,o)=>{const{ref:s,style:c,children:l,dangerouslySetInnerHTML:u,...a}=e;for(const n in c??{}){const e=c[n];f((()=>{O(t,n,_.get(e))}))}for(const n in a){const e=a[n];if(n.startsWith("on")){const o=r(),s=t=>{o.u((()=>i((()=>e(t)))))},c=b(n);f((()=>(t.addEventListener(c,s),()=>t.removeEventListener(c,s))))}else f((()=>{D(t,n,_.get(e),o)}))}return u&&f((()=>{const n=_.get(u).__html;t.innerHTML!=n&&(t.innerHTML=n)})),s&&f((()=>(s.set(t),()=>s.set(void 0)))),null!=e.children&&t.append(...y({P:n,N:t.childNodes.values()},(()=>z({children:e.children}).build()))),t},V=(t,n={},e)=>(null!=e&&(n.children=e),L(t)?((t,n)=>I((()=>{const e=m().C((()=>new t));return customElements.upgrade(e),P(e,!1,n),[e]})))(t,n):"function"==typeof t?I((()=>t(n))):((t,n={})=>I((()=>{const e=m(),o="svg"==t||!!e.P;return[P(e.C((()=>o?document.createElementNS("http://www.w3.org/2000/svg",t):document.createElement(t))),o,n,!0)]})))(t,n)),Z=new Proxy(V,{get:(t,n)=>(e,o)=>t(n,e,o)}),q=(t,n)=>{const[e,o]=c({V:[],Z:new Map});let s=new Map;return f((()=>{const e=[],r=s,c=((t,n)=>{const e=new Map;for(let o=0;o<t.length;o++){const s=n(t[o],o);if(e.has(s))throw Error(`Duplicate key '${s}'`);e.set(s,o)}return e})(t(),n),i=(t=NaN)=>e.map((t=>"r"==t.q?n=>n<t.B?n:n==t.B?NaN:n-1:"a"==t.q?n=>n<t.B?n:n+1:"m"==t.q?n=>t.F<=n&&n<t.G?n+1:n==t.G?t.F:n:t=>t)).reduce(((t,n)=>n(t)),t);for(const t of r.keys()){const n=i(r.get(t));c.has(t)||e.push({q:"r",J:t,B:n})}for(let o=0;o<t().length;o++){const s=n(t()[o],o),c=i(r.get(s));isNaN(c)?e.push({q:"a",J:s,B:o}):c!=o&&e.push({q:"m",J:s,G:c,F:o})}e.length>0&&o({V:e,Z:c}),s=c})),e},B=t=>I((()=>{const n=m(),e=_.upgrade(t.each??[]),o=n.C((()=>document.createComment(""))),s=t.key??((t,n)=>n),r=[o],i=new Map,l=q(e,s),u=t=>{for(let n=t-1;n>=0;n--){const n=s(e()[t-1],t-1),o=i.get(n)?.K??[];if(o.length>0)return o[o.length-1]}return o};return f((()=>{for(const n of l().V)if("r"==n.q){const{K:t=[],$:e}=i.get(n.J)??{};e?.();const o=r.indexOf(t[0]);o>0&&r.splice(o,t.length),t.forEach((t=>t.parentNode?.removeChild(t))),i.delete(n.J)}else if("a"==n.q){let o=[];const[,s]=d((()=>{const[s,i]=c(n.B),[a,d]=c(e()[n.B]);f((()=>{0<=s()&&s()<e().length&&d((()=>e()[s()]))})),f((()=>{const t=l().Z.get(n.J);null!=t&&i(t)})),o=t.children?.(a,s,e).build()??[];const h=u(n.B),_=r.indexOf(h);_>=0&&r.splice(_+1,0,...o),o.forEach((t=>h.parentNode?.insertBefore(t,h.nextSibling)))}));i.set(n.J,{K:o,$:s})}else if("m"==n.q){const{K:t=[]}=i.get(n.J)??{},e=r.indexOf(t[0]);e>=0&&r.splice(e,t.length);const o=u(n.F),s=r.indexOf(o);s>=0&&r.splice(s+1,0,...t),t.forEach((t=>o.parentNode?.insertBefore(t,o.nextSibling)))}}),[l]),r})),F=t=>(m().k=[],G({condition:t.condition,children:t.children})),G=t=>{const n=m(),e=n.k,o=a((()=>e.every((t=>!t()))&&_.get(t.condition)));return n.k=[...e,o],y({k:[]},(()=>I((()=>{const e=n.C((()=>document.createComment(""))),s=[e],r=a((()=>o()?z({children:t.children}):null));let c=[];return f((()=>{c.forEach((t=>t.parentNode?.removeChild(t))),s.length=1;const[,t]=d((()=>{c=r()?.build()??[],e.after(...c),s.push(...c)}));return t}),[r]),s}))))},J=({children:t})=>G({condition:!0,children:t}),K=({mount:t,children:n})=>I((()=>y({N:void 0},(()=>{const e=z({children:n}).build();return f((()=>(e.forEach((n=>t.appendChild(n))),()=>{e.forEach((t=>t.parentNode?.removeChild(t)))}))),[]})))),Q=Symbol(),R=new Map,U=t=>{const n=t.children;if("function"==typeof n){const e=V("style",{},$({text:n,marker:!1}));return t.light?K({mount:document.head,children:e}):e}if(n){const o=m(),s=t.light?document:o.T?.shadowRoot??document,r=((t,n,e)=>{if(!R.has(n)){const t=new CSSStyleSheet;t.replaceSync(n),R.set(n,{R:t,U:0})}const o=R.get(n);o.U++,t.has(n)||t.set(n,{R:o.R,U:0});const s=t.get(n);return s.U++,f((()=>()=>{--s.U||(t.delete(n),e()),--o.U||R.delete(n)})),s.R})((e=s,e[Q]??=new Map),n,(()=>{s.adoptedStyleSheets=s.adoptedStyleSheets.filter((t=>t!=r))}));s.adoptedStyleSheets.push(r)}var e;return z({})},W=(t,...n)=>{const e=()=>t.reduce(((t,e,o)=>t+e+(_.get(n[o])??"")),"");return n.some((t=>"function"==typeof t))?e:e()},X=(t,n,e)=>(n&&null!=e&&(n.key=e),V(t,n));export{H as Component,J as Else,G as ElseIf,B as For,z as Fragment,F as If,_ as MaybeSignal,K as Portal,U as Style,g as createContext,V as createElement,W as css,T as defineComponents,C as event,l as flushBatch,Z as h,L as isComponent,X as jsx,X as jsxDEV,X as jsxs,k as prop,i as useBatch,M as useContext,j as useEffect,a as useMemo,h as useRef,c as useSignal,d as useSubscope};
|
package/dist/scope.d.ts
CHANGED
|
@@ -18,6 +18,12 @@ export interface Signal<out T> extends SignalLike<T> {
|
|
|
18
18
|
*/
|
|
19
19
|
peek(): T;
|
|
20
20
|
}
|
|
21
|
+
export interface SignalOptions<T> extends SetSignalOptions {
|
|
22
|
+
/**
|
|
23
|
+
* A custom equality function to compare the new value with the old value.
|
|
24
|
+
*/
|
|
25
|
+
equals?: (a: T, b: T) => boolean;
|
|
26
|
+
}
|
|
21
27
|
export interface SetSignalOptions {
|
|
22
28
|
/**
|
|
23
29
|
* Whether to force the update of the signal even if the new value has the
|
|
@@ -64,7 +70,7 @@ export declare const useScope: <T = {}>() => Scope<T>;
|
|
|
64
70
|
* Creates a new signal with the given value.
|
|
65
71
|
* @returns A tuple with the signal and its setter.
|
|
66
72
|
*/
|
|
67
|
-
export declare const useSignal: (<T>(value: T, opts?:
|
|
73
|
+
export declare const useSignal: (<T>(value: T, opts?: SignalOptions<T>) => readonly [Signal<T>, SignalSetter<T>]) & (<T>(value?: T, opts?: SignalOptions<T | undefined>) => readonly [Signal<T | undefined>, SignalSetter<T | undefined>]);
|
|
68
74
|
/**
|
|
69
75
|
* Runs the given function in a batch.
|
|
70
76
|
*
|
|
@@ -84,7 +90,7 @@ export declare const useEffect: (fn: () => Cleanup, deps?: SignalLike<unknown>[]
|
|
|
84
90
|
*
|
|
85
91
|
* @param fn The computation function.
|
|
86
92
|
*/
|
|
87
|
-
export declare const useMemo: <T>(fn: () => T, opts?:
|
|
93
|
+
export declare const useMemo: <T>(fn: () => T, opts?: SignalOptions<T>) => Signal<T>;
|
|
88
94
|
/**
|
|
89
95
|
* Executes a function inside a subscope which can be manually destroyed.
|
|
90
96
|
*
|
|
@@ -113,7 +119,7 @@ export interface RefSignalSetter<in T> {
|
|
|
113
119
|
/**
|
|
114
120
|
* Creates a new signal with write capabilities.
|
|
115
121
|
*/
|
|
116
|
-
export declare const useRef: (<T>(value: T, opts?:
|
|
122
|
+
export declare const useRef: (<T>(value: T, opts?: SignalOptions<T>) => RefSignal<T>) & (<T>(value?: T, opts?: SignalOptions<T | undefined>) => RefSignal<T | undefined>);
|
|
117
123
|
/**
|
|
118
124
|
* Represents a value that can be a signal or a constant value.
|
|
119
125
|
*
|
package/dist/scope.js
CHANGED
|
@@ -52,25 +52,33 @@ export const useSignal = (value, opts) => {
|
|
|
52
52
|
signal._effects = new Set();
|
|
53
53
|
signal.peek = () => value;
|
|
54
54
|
const setter = (arg, innerOpts) => {
|
|
55
|
-
|
|
55
|
+
const allOpts = { ...opts, ...innerOpts };
|
|
56
|
+
allOpts.equals ??= (a, b) => a === b;
|
|
56
57
|
if (currBatch) {
|
|
57
58
|
const newValue = typeof arg == "function"
|
|
58
59
|
? arg(signal.peek())
|
|
59
60
|
: arg;
|
|
60
|
-
if (
|
|
61
|
-
if (
|
|
61
|
+
if (allOpts?.force || !allOpts.equals(newValue, signal.peek())) {
|
|
62
|
+
if (allOpts?.force) {
|
|
62
63
|
value = newValue;
|
|
63
64
|
}
|
|
64
65
|
else {
|
|
65
66
|
currBatch._setters.push(() => (value = newValue));
|
|
66
67
|
}
|
|
67
|
-
if (!
|
|
68
|
-
signal._effects.forEach((effect) =>
|
|
68
|
+
if (!allOpts?.silent) {
|
|
69
|
+
signal._effects.forEach((effect) => {
|
|
70
|
+
if (effect._pure) {
|
|
71
|
+
currBatch._pureEffects.add(effect);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
currBatch._effects.add(effect);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
69
77
|
}
|
|
70
78
|
}
|
|
71
79
|
}
|
|
72
80
|
else {
|
|
73
|
-
useBatch(() => setter(arg,
|
|
81
|
+
useBatch(() => setter(arg, allOpts));
|
|
74
82
|
}
|
|
75
83
|
};
|
|
76
84
|
return [signal, setter];
|
|
@@ -84,7 +92,11 @@ export const useSignal = (value, opts) => {
|
|
|
84
92
|
export const useBatch = (fn) => {
|
|
85
93
|
if (currBatch)
|
|
86
94
|
return fn();
|
|
87
|
-
currBatch = {
|
|
95
|
+
currBatch = {
|
|
96
|
+
_setters: [],
|
|
97
|
+
_effects: new Set(),
|
|
98
|
+
_pureEffects: new Set(),
|
|
99
|
+
};
|
|
88
100
|
try {
|
|
89
101
|
const result = fn();
|
|
90
102
|
flushBatch();
|
|
@@ -95,25 +107,23 @@ export const useBatch = (fn) => {
|
|
|
95
107
|
}
|
|
96
108
|
};
|
|
97
109
|
export const flushBatch = () => {
|
|
98
|
-
|
|
99
|
-
|
|
110
|
+
while (currBatch &&
|
|
111
|
+
currBatch._setters.length +
|
|
112
|
+
currBatch._effects.size +
|
|
113
|
+
currBatch._pureEffects.size >
|
|
114
|
+
0) {
|
|
100
115
|
// Clean effect subscope
|
|
101
116
|
currBatch._effects.forEach((effect) => effect._clean?.());
|
|
102
117
|
// Run signal updates
|
|
103
118
|
currBatch._setters.forEach((setter) => setter());
|
|
104
119
|
currBatch._setters = [];
|
|
105
120
|
// Run next effect
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
currBatch._effects.delete(effect);
|
|
110
|
-
continue a;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
for (const effect of currBatch._effects) {
|
|
121
|
+
const effect = currBatch._pureEffects.values().next().value ??
|
|
122
|
+
currBatch._effects.values().next().value;
|
|
123
|
+
if (effect) {
|
|
114
124
|
effect._run();
|
|
125
|
+
currBatch._pureEffects.delete(effect);
|
|
115
126
|
currBatch._effects.delete(effect);
|
|
116
|
-
break;
|
|
117
127
|
}
|
|
118
128
|
}
|
|
119
129
|
};
|
|
@@ -174,12 +184,12 @@ export const useEffect = (fn, deps) => {
|
|
|
174
184
|
* @param fn The computation function.
|
|
175
185
|
*/
|
|
176
186
|
export const useMemo = (fn, opts) => {
|
|
177
|
-
const [memo, setMemo] = useSignal();
|
|
187
|
+
const [memo, setMemo] = useSignal(undefined, opts);
|
|
178
188
|
let firstTime = true;
|
|
179
189
|
pureEffectFlag = true;
|
|
180
190
|
try {
|
|
181
191
|
useEffect(() => {
|
|
182
|
-
setMemo(fn, firstTime ? {
|
|
192
|
+
setMemo(fn, firstTime ? { force: true } : {});
|
|
183
193
|
firstTime = false;
|
|
184
194
|
});
|
|
185
195
|
}
|
|
@@ -221,11 +231,11 @@ export const useSubscope = (fn, opts) => {
|
|
|
221
231
|
/**
|
|
222
232
|
* Creates a new signal with write capabilities.
|
|
223
233
|
*/
|
|
224
|
-
export const useRef = (value, opts) => {
|
|
234
|
+
export const useRef = ((value, opts) => {
|
|
225
235
|
const [signal, setter] = useSignal(value, opts);
|
|
226
236
|
signal.set = setter;
|
|
227
237
|
return signal;
|
|
228
|
-
};
|
|
238
|
+
});
|
|
229
239
|
/**
|
|
230
240
|
* @namespace
|
|
231
241
|
*/
|
package/dist/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/scope.ts
CHANGED
|
@@ -21,6 +21,13 @@ export interface Signal<out T> extends SignalLike<T> {
|
|
|
21
21
|
peek(): T;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
export interface SignalOptions<T> extends SetSignalOptions {
|
|
25
|
+
/**
|
|
26
|
+
* A custom equality function to compare the new value with the old value.
|
|
27
|
+
*/
|
|
28
|
+
equals?: (a: T, b: T) => boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
24
31
|
export interface SetSignalOptions {
|
|
25
32
|
/**
|
|
26
33
|
* Whether to force the update of the signal even if the new value has the
|
|
@@ -116,6 +123,7 @@ let currBatch:
|
|
|
116
123
|
| {
|
|
117
124
|
_setters: (() => void)[];
|
|
118
125
|
_effects: Set<Effect>;
|
|
126
|
+
_pureEffects: Set<Effect>;
|
|
119
127
|
}
|
|
120
128
|
| undefined;
|
|
121
129
|
|
|
@@ -128,14 +136,14 @@ export const useScope = <T = {}>(): Scope<T> => currScope as Scope<T>;
|
|
|
128
136
|
*/
|
|
129
137
|
export const useSignal: (<T>(
|
|
130
138
|
value: T,
|
|
131
|
-
opts?:
|
|
139
|
+
opts?: SignalOptions<T>,
|
|
132
140
|
) => readonly [Signal<T>, SignalSetter<T>]) &
|
|
133
141
|
(<T>(
|
|
134
142
|
value?: T,
|
|
135
|
-
opts?:
|
|
143
|
+
opts?: SignalOptions<T | undefined>,
|
|
136
144
|
) => readonly [Signal<T | undefined>, SignalSetter<T | undefined>]) = <T>(
|
|
137
145
|
value: T,
|
|
138
|
-
opts?:
|
|
146
|
+
opts?: SignalOptions<T>,
|
|
139
147
|
): readonly [Signal<T>, SignalSetter<T>] => {
|
|
140
148
|
const signal: Signal<T> = () => {
|
|
141
149
|
if (!currUntracked && currEffect) {
|
|
@@ -150,7 +158,8 @@ export const useSignal: (<T>(
|
|
|
150
158
|
signal.peek = () => value;
|
|
151
159
|
|
|
152
160
|
const setter = (arg: T | ((value: T) => T), innerOpts?: SetSignalOptions) => {
|
|
153
|
-
|
|
161
|
+
const allOpts = { ...opts, ...innerOpts };
|
|
162
|
+
allOpts.equals ??= (a, b) => a === b;
|
|
154
163
|
|
|
155
164
|
if (currBatch) {
|
|
156
165
|
const newValue =
|
|
@@ -158,19 +167,25 @@ export const useSignal: (<T>(
|
|
|
158
167
|
? (arg as (value: T) => T)(signal.peek())
|
|
159
168
|
: arg;
|
|
160
169
|
|
|
161
|
-
if (
|
|
162
|
-
if (
|
|
170
|
+
if (allOpts?.force || !allOpts.equals(newValue, signal.peek())) {
|
|
171
|
+
if (allOpts?.force) {
|
|
163
172
|
value = newValue;
|
|
164
173
|
} else {
|
|
165
174
|
currBatch._setters.push(() => (value = newValue));
|
|
166
175
|
}
|
|
167
176
|
|
|
168
|
-
if (!
|
|
169
|
-
signal._effects.forEach((effect) =>
|
|
177
|
+
if (!allOpts?.silent) {
|
|
178
|
+
signal._effects.forEach((effect) => {
|
|
179
|
+
if (effect._pure) {
|
|
180
|
+
currBatch!._pureEffects.add(effect);
|
|
181
|
+
} else {
|
|
182
|
+
currBatch!._effects.add(effect);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
170
185
|
}
|
|
171
186
|
}
|
|
172
187
|
} else {
|
|
173
|
-
useBatch(() => setter(arg,
|
|
188
|
+
useBatch(() => setter(arg, allOpts));
|
|
174
189
|
}
|
|
175
190
|
};
|
|
176
191
|
|
|
@@ -186,7 +201,11 @@ export const useSignal: (<T>(
|
|
|
186
201
|
export const useBatch = <T>(fn: () => T): T => {
|
|
187
202
|
if (currBatch) return fn();
|
|
188
203
|
|
|
189
|
-
currBatch = {
|
|
204
|
+
currBatch = {
|
|
205
|
+
_setters: [],
|
|
206
|
+
_effects: new Set(),
|
|
207
|
+
_pureEffects: new Set(),
|
|
208
|
+
};
|
|
190
209
|
|
|
191
210
|
try {
|
|
192
211
|
const result = fn();
|
|
@@ -198,9 +217,12 @@ export const useBatch = <T>(fn: () => T): T => {
|
|
|
198
217
|
};
|
|
199
218
|
|
|
200
219
|
export const flushBatch = (): void => {
|
|
201
|
-
|
|
220
|
+
while (
|
|
202
221
|
currBatch &&
|
|
203
|
-
|
|
222
|
+
currBatch._setters.length +
|
|
223
|
+
currBatch._effects.size +
|
|
224
|
+
currBatch._pureEffects.size >
|
|
225
|
+
0
|
|
204
226
|
) {
|
|
205
227
|
// Clean effect subscope
|
|
206
228
|
|
|
@@ -213,18 +235,14 @@ export const flushBatch = (): void => {
|
|
|
213
235
|
|
|
214
236
|
// Run next effect
|
|
215
237
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
currBatch._effects.delete(effect);
|
|
220
|
-
continue a;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
238
|
+
const effect: Effect | undefined =
|
|
239
|
+
currBatch._pureEffects.values().next().value ??
|
|
240
|
+
currBatch._effects.values().next().value;
|
|
223
241
|
|
|
224
|
-
|
|
242
|
+
if (effect) {
|
|
225
243
|
effect._run();
|
|
244
|
+
currBatch._pureEffects.delete(effect);
|
|
226
245
|
currBatch._effects.delete(effect);
|
|
227
|
-
break;
|
|
228
246
|
}
|
|
229
247
|
}
|
|
230
248
|
};
|
|
@@ -305,15 +323,18 @@ export const useEffect = (
|
|
|
305
323
|
*
|
|
306
324
|
* @param fn The computation function.
|
|
307
325
|
*/
|
|
308
|
-
export const useMemo = <T>(fn: () => T, opts?:
|
|
309
|
-
const [memo, setMemo] = useSignal<T>(
|
|
326
|
+
export const useMemo = <T>(fn: () => T, opts?: SignalOptions<T>): Signal<T> => {
|
|
327
|
+
const [memo, setMemo] = useSignal<T>(
|
|
328
|
+
undefined,
|
|
329
|
+
opts as SignalOptions<T | undefined>,
|
|
330
|
+
);
|
|
310
331
|
|
|
311
332
|
let firstTime = true;
|
|
312
333
|
pureEffectFlag = true;
|
|
313
334
|
|
|
314
335
|
try {
|
|
315
336
|
useEffect(() => {
|
|
316
|
-
setMemo(fn, firstTime ? {
|
|
337
|
+
setMemo(fn, firstTime ? { force: true } : {});
|
|
317
338
|
|
|
318
339
|
firstTime = false;
|
|
319
340
|
});
|
|
@@ -384,15 +405,18 @@ export interface RefSignalSetter<in T> {
|
|
|
384
405
|
/**
|
|
385
406
|
* Creates a new signal with write capabilities.
|
|
386
407
|
*/
|
|
387
|
-
export const useRef: (<T>(value: T, opts?:
|
|
388
|
-
(<T>(
|
|
408
|
+
export const useRef: (<T>(value: T, opts?: SignalOptions<T>) => RefSignal<T>) &
|
|
409
|
+
(<T>(
|
|
410
|
+
value?: T,
|
|
411
|
+
opts?: SignalOptions<T | undefined>,
|
|
412
|
+
) => RefSignal<T | undefined>) = (<T>(
|
|
389
413
|
value?: T,
|
|
390
|
-
opts?:
|
|
414
|
+
opts?: SignalOptions<T | undefined>,
|
|
391
415
|
): RefSignal<T> & RefSignal<T | undefined> => {
|
|
392
416
|
const [signal, setter] = useSignal(value, opts);
|
|
393
417
|
(signal as RefSignal<T | undefined>).set = setter;
|
|
394
418
|
return signal as RefSignal<T> & RefSignal<T | undefined>;
|
|
395
|
-
};
|
|
419
|
+
}) as any;
|
|
396
420
|
|
|
397
421
|
/**
|
|
398
422
|
* Represents a value that can be a signal or a constant value.
|