sprae 10.5.0 → 10.6.1
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/sprae.js +6 -4
- package/dist/sprae.min.js +1 -1
- package/package.json +1 -1
- package/readme.md +28 -18
- package/store.js +7 -5
package/dist/sprae.js
CHANGED
|
@@ -33,7 +33,7 @@ function store(values, parent) {
|
|
|
33
33
|
let signals = { ...parent?.[_signals] }, _len = signal(Object.values(values).length);
|
|
34
34
|
const state = new Proxy(signals, {
|
|
35
35
|
get: (_, key) => key === _change ? _len : key === _signals ? signals : signals[key]?.valueOf(),
|
|
36
|
-
set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s
|
|
36
|
+
set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s ?? ++_len.value, 1),
|
|
37
37
|
deleteProperty: (_, key) => (signals[key] && (del(signals, key), _len.value--), 1),
|
|
38
38
|
ownKeys() {
|
|
39
39
|
_len.value;
|
|
@@ -45,7 +45,7 @@ function store(values, parent) {
|
|
|
45
45
|
if (desc?.get) {
|
|
46
46
|
(signals[key] = computed(desc.get.bind(state)))._set = desc.set?.bind(state);
|
|
47
47
|
} else {
|
|
48
|
-
signals[key] =
|
|
48
|
+
signals[key] = void 0;
|
|
49
49
|
set(signals, key, values[key]);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -56,7 +56,7 @@ function list(values) {
|
|
|
56
56
|
let lastProp;
|
|
57
57
|
if (values[_signals])
|
|
58
58
|
return values;
|
|
59
|
-
let _len = signal(values.length), signals = Array(values.length).fill(
|
|
59
|
+
let _len = signal(values.length), signals = Array(values.length).fill();
|
|
60
60
|
const state = new Proxy(signals, {
|
|
61
61
|
get(_, key) {
|
|
62
62
|
if (typeof key === "symbol")
|
|
@@ -87,7 +87,9 @@ function list(values) {
|
|
|
87
87
|
}
|
|
88
88
|
function set(signals, key, v) {
|
|
89
89
|
let s = signals[key];
|
|
90
|
-
if (
|
|
90
|
+
if (key[0] === "_")
|
|
91
|
+
signals[key] = v;
|
|
92
|
+
else if (!s) {
|
|
91
93
|
signals[key] = s = v?.peek ? v : signal(store(v));
|
|
92
94
|
} else if (v === s.peek())
|
|
93
95
|
;
|
package/dist/sprae.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e,t,r,l,n,s=Object.defineProperty,o=Symbol("signals"),a=Symbol("length");function i(t,r){if(!t)return t;if(t[o])return t;if(Array.isArray(t))return function(t){let r;if(t[o])return t;let l=e(t.length),n=Array(t.length).fill(
|
|
1
|
+
var e,t,r,l,n,s=Object.defineProperty,o=Symbol("signals"),a=Symbol("length");function i(t,r){if(!t)return t;if(t[o])return t;if(Array.isArray(t))return function(t){let r;if(t[o])return t;let l=e(t.length),n=Array(t.length).fill();const s=new Proxy(n,{get:(s,c)=>"symbol"==typeof c?c===a?l:c===o?n:n[c]:"length"===c?u[r]?l.peek():l.value:(r=c,n[c]?n[c].valueOf():c<n.length?(n[c]=e(i(t[c]))).value:void 0),set(e,t,r){if("length"===t){for(let e=r,t=n.length;e<t;e++)delete s[e];return l.value=n.length=r,!0}return c(n,t,r),t>=l.peek()&&(l.value=n.length=Number(t)+1),!0},deleteProperty:(e,t)=>(n[t]&&f(n,t),1)});return s}(t);if(t.constructor!==Object)return t;let l={...r?.[o]},s=e(Object.values(t).length);const p=new Proxy(l,{get:(e,t)=>t===a?s:t===o?l:l[t]?.valueOf(),set:(e,t,r,n)=>(n=l[t],c(l,t,r),n??++s.value,1),deleteProperty:(e,t)=>(l[t]&&(f(l,t),s.value--),1),ownKeys:()=>(s.value,Reflect.ownKeys(l))});for(let e in t){const r=Object.getOwnPropertyDescriptor(t,e);r?.get?(l[e]=n(r.get.bind(p)))._set=r.set?.bind(p):(l[e]=void 0,c(l,e,t[e]))}return p}var u={push:1,pop:1,shift:1,unshift:1,splice:1};function c(t,n,s){let o=t[n];if("_"===n[0])t[n]=s;else if(o)if(s===o.peek());else if(o._set)o._set(s);else if(Array.isArray(s)&&Array.isArray(o.peek())){const e=o.peek();e[a]?r((()=>{l((()=>{let t=0,r=s.length;for(;t<r;t++)e[t]=s[t];e.length=r}))})):o.value=s}else o.value=i(s);else t[n]=o=s?.peek?s:e(i(s))}function f(e,t){const r=e[t],l=r[Symbol.dispose];l&&delete r[Symbol.dispose],delete e[t],l?.()}var p=Symbol.dispose||=Symbol("dispose"),d={},y=new WeakMap;function h(e,t){if(!e?.children)return;if(y.has(e))return Object.assign(y.get(e),t);const r=i(t||{}),l=[];return function e(t,n=t.parentNode){if(t.attributes)for(let e=0;e<t.attributes.length;){let s=t.attributes[e];if(":"===s.name[0]){t.removeAttribute(s.name);let e=s.name.slice(1).split(":");for(let n of e){let e=d[n]||d.default,o=e(t,(e.parse||g)(s.value,g),r,n);o&&l.push(o)}if(y.has(t))return l.push(t[p]);if(t.parentNode!==n)return}else e++}for(let r of[...t.children])e(r,t)}(e),y.has(e)||y.set(e,r),e[p]=()=>{for(;l.length;)l.pop()();y.delete(e)},r}var m,v={},g=(e,t,r)=>{if(r=v[e=e.trim()])return r;try{r=m(e)}catch(r){b(r,t,e)}return v[e]=r},b=(e,t,r="")=>{throw Object.assign(e,{message:`∴ ${e.message}\n\n${t}${r?`="${r}"\n\n`:""}`,expr:r})};h.use=s=>{s.signal&&function(s){e=s.signal,t=s.effect,n=s.computed,l=s.batch||(e=>e()),r=s.untracked||l}(s),s.compile&&(m=s.compile)};var k,A,S={};((e,t)=>{for(var r in t)s(e,r,{get:t[r],enumerable:!0})})(S,{batch:()=>x,computed:()=>N,effect:()=>O,signal:()=>w,untracked:()=>$});var w=(e,t,r=new Set)=>((t={get value(){return k?.deps.push(r.add(k)),e},set value(t){if(t!==e){e=t;for(let e of r)A?A.add(e):e()}},peek:()=>e}).toJSON=t.then=t.toString=t.valueOf=()=>t.value,t),O=(e,t,r,l)=>(l=(r=l=>{t?.call?.(),l=k,k=r;try{t=e()}finally{k=l}}).deps=[],r(),e=>{for(t?.call?.();e=l.pop();)e.delete(r)}),N=(e,t=w(),r,l)=>((r={get value(){return l||=O((()=>t.value=e())),t.value},peek:t.peek}).toJSON=r.then=r.toString=r.valueOf=()=>r.value,r),x=e=>{let t=A;t||(A=new Set);try{e()}finally{if(!t){t=A,A=null;for(const e of t)e()}}},$=(e,t,r)=>(t=k,k=null,r=e(),k=t,r),j=Symbol(":each");d.each=(e,[l,s,u],c)=>{const f=e[j]=document.createTextNode("");e.replaceWith(f);let p,d,y=0;const m=n((()=>{d=null;let e=u(c);return"number"==typeof e&&(e=Array.from({length:e},((e,t)=>t+1))),e?.constructor===Object&&(d=Object.keys(e),e=Object.values(e)),e||[]})),v=()=>{r((()=>{let t=0,r=m.value,n=r.length;if(p&&!p[a]){for(let e of p[o]||[])e[Symbol.dispose]();p=null,y=0}if(n<y)p.length=n;else{if(p)for(;t<y;t++)p[t]=r[t];else p=r;for(;t<n;t++){p[t]=r[t];let n=t,a=i({[l]:p[o]?.[n]||p[n],[s]:d?d[n]:n},c),u=(e.content||e).cloneNode(!0),y=e.content?{children:[...u.children],remove(){this.children.map((e=>e.remove()))}}:u;f.before(u),h(y,a),((p[o]||=[])[t]||={})[Symbol.dispose]=()=>{y[Symbol.dispose](),y.remove()}}}y=n}))};let g=0;return t((()=>{m.value[a]?.value,g?g++:(v(),queueMicrotask((()=>(g&&v(),g=0))))}))},d.each.parse=(e,t)=>{let[r,l]=e.split(/\s+in\s+/),[n,s="$"]=r.split(/\s*,\s*/);return[n,s,t(l)]};var E=Symbol("if");d.if=(e,r,l)=>{let n,s,o,a=e.parentNode,i=e.nextElementSibling,u=document.createTextNode(""),c=[];return e.after(u),e.content?(n=c,e.remove(),s=[...e.content.childNodes]):s=n=[e],i?.hasAttribute(":else")?(i.removeAttribute(":else"),i.hasAttribute(":if")?o=c:(i.remove(),o=i.content?[...i.content.childNodes]:[i])):o=c,t((()=>{const t=r(l)?s:e[E]?c:o;if(i&&(i[E]=t===s),n!=t){n[0]?.[j]&&(n=[n[0][j]]);for(let e of n)e.remove();n=t;for(let e of n)a.insertBefore(e,u),h(e,l)}}))},d.default=(e,r,l,n)=>{if(!n.startsWith("on"))return t((()=>{let t=r(l);if(n)W(e,n,K(t,l));else for(let r in t)W(e,D(r),K(t[r],l))}));const s=n.split("..").map((t=>{let r={evt:"",target:e,test:()=>!0};return r.evt=(t.startsWith("on")?t.slice(2):t).replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,l="")=>(r.test=P[t]?.(r,...l.split("-"))||r.test,""))),r}));if(1==s.length)return t((()=>f(r(l),s[0])));let o,a,i,u=0;const c=e=>{i=f((t=>(i(),a=e?.(t),(u=++u%s.length)?c(a):o&&c(o))),s[u])};return t((()=>(o=r(l),!i&&c(o),()=>o=null)));function f(e,{evt:t,target:r,test:l,defer:n,stop:s,prevent:o,immediate:a,...i}){n&&(e=n(e));const u=r=>{try{l(r)&&(s&&(a?r.stopImmediatePropagation():r.stopPropagation()),o&&r.preventDefault(),e?.(r))}catch(r){b(r,`:on${t}`,e)}};return r.addEventListener(t,u,i),()=>r.removeEventListener(t,u,i)}};var P={prevent(e){e.prevent=!0},stop(e){e.stop=!0},immediate(e){e.immediate=!0},once(e){e.once=!0},passive(e){e.passive=!0},capture(e){e.capture=!0},window(e){e.target=window},document(e){e.target=document},throttle(e,t){e.defer=e=>C(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>_(e,t?Number(t)||0:108)},outside:e=>t=>{let r=e.target;return!(r.contains(t.target)||!1===t.target.isConnected||r.offsetWidth<1&&r.offsetHeight<1)},self:e=>t=>t.target===e.target,ctrl:(e,...t)=>e=>T.ctrl(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),shift:(e,...t)=>e=>T.shift(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),alt:(e,...t)=>e=>T.alt(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),meta:(e,...t)=>e=>T.meta(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),arrow:()=>T.arrow,enter:()=>T.enter,esc:()=>T.esc,tab:()=>T.tab,space:()=>T.space,delete:()=>T.delete,digit:()=>T.digit,letter:()=>T.letter,char:()=>T.char},T={ctrl:e=>e.ctrlKey||"Control"===e.key||"Ctrl"===e.key,shift:e=>e.shiftKey||"Shift"===e.key,alt:e=>e.altKey||"Alt"===e.key,meta:e=>e.metaKey||"Meta"===e.key||"Command"===e.key,arrow:e=>e.key.startsWith("Arrow"),enter:e=>"Enter"===e.key,esc:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,delete:e=>"Delete"===e.key||"Backspace"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^\p{L}$/gu.test(e.key),char:e=>/^\S$/.test(e.key)},W=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},C=(e,t)=>{let r,l,n=s=>{r=!0,setTimeout((()=>{if(r=!1,l)return l=!1,n(s),e(s)}),t)};return t=>r?l=!0:(n(t),e(t))},_=(e,t)=>{let r;return l=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(l)}),t)}},D=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),K=(e,t)=>e?.replace?e.replace(/\$<([^>]+)>/g,((e,r)=>t[r]??"")):e;d.ref=(e,t,r)=>{r[K(t,r)]=e},d.ref.parse=e=>e,d.with=(e,r,l)=>{let n;return t((()=>{let t=r(l);h(e,n?t:n=i(t,l))}))},d.html=(e,t,r)=>{let l=t(r);if(!l)return;let n=(l.content||l).cloneNode(!0);e.replaceChildren(n),h(e,r)},d.text=(e,r,l)=>(e.content&&e.replaceWith(e=document.createTextNode("")),t((()=>{let t=r(l);e.textContent=null==t?"":t}))),d.class=(e,r,l)=>{let n=new Set;return t((()=>{let t=r(l),s=new Set;t&&("string"==typeof t?K(t,l).split(" ").map((e=>s.add(e))):Array.isArray(t)?t.map((e=>(e=K(e,l))&&s.add(e))):Object.entries(t).map((([e,t])=>t&&s.add(e))));for(let t of n)s.has(t)?s.delete(t):e.classList.remove(t);for(let t of n=s)e.classList.add(t)}))},d.style=(e,r,l)=>{let n=e.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),t((()=>{let t=r(l);if("string"==typeof t)e.setAttribute("style",n+K(t,l));else{e.setAttribute("style",n);for(let r in t)e.style.setProperty(r,K(t[r],l))}}))},d.value=(e,r,l)=>{let n,s,o="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(n=e.selectionStart,s=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),n&&e.setSelectionRange(n,s)):"checkbox"===e.type?t=>(e.checked=t,W(e,"checked",t)):"select-one"===e.type?t=>{for(let t in e.options)t.removeAttribute("selected");e.value=t,e.selectedOptions[0]?.setAttribute("selected","")}:t=>e.value=t;return t((()=>o(r(l))))},d.fx=(e,r,l)=>t((()=>r(l))),h.use(S),h.use({compile:e=>h.constructor("__scope",`with (__scope) { return ${e} };`)});var L=h;export{L as default};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ∴ spræ [](https://github.com/dy/sprae/actions/workflows/node.js.yml) [](https://github.com/dy/sprae/actions/workflows/node.js.yml) [](https://bundlejs.com/?q=sprae) [](https://npmjs.org/sprae)
|
|
2
2
|
|
|
3
3
|
> DOM tree microhydration
|
|
4
4
|
|
|
@@ -206,23 +206,6 @@ Attach event(s) listener with optional modifiers.
|
|
|
206
206
|
* `.ctrl-<key>, .alt-<key>, .meta-<key>, .shift-<key>` – key combinations, eg. `.ctrl-alt-delete` or `.meta-x`.
|
|
207
207
|
* `.*` – any other modifier has no effect, but allows binding multiple handlers to same event (like jQuery event classes).
|
|
208
208
|
|
|
209
|
-
#### `:html="element"` 🔌
|
|
210
|
-
|
|
211
|
-
> Include as `import 'sprae/directive/html'`.
|
|
212
|
-
|
|
213
|
-
Set html content of an element or instantiate a template.
|
|
214
|
-
|
|
215
|
-
```html
|
|
216
|
-
Hello, <span :html="userElement">Guest</span>.
|
|
217
|
-
|
|
218
|
-
<!-- fragment -->
|
|
219
|
-
Hello, <template :html="user.name">Guest</template>.
|
|
220
|
-
|
|
221
|
-
<!-- instantiate template -->
|
|
222
|
-
<template :ref="tpl"><span :text="foo"></span></template>
|
|
223
|
-
<div :html="tpl" :with="{foo:'bar'}">...inserted here...</div>
|
|
224
|
-
```
|
|
225
|
-
|
|
226
209
|
#### `:data="values"` 🔌
|
|
227
210
|
|
|
228
211
|
> Include as `import 'sprae/directive/data'`.
|
|
@@ -253,6 +236,24 @@ Set `aria-*` attributes. Boolean values are stringified.
|
|
|
253
236
|
-->
|
|
254
237
|
```
|
|
255
238
|
|
|
239
|
+
|
|
240
|
+
#### `:html="element"` 🔌 (experimental)
|
|
241
|
+
|
|
242
|
+
> Include as `import 'sprae/directive/html'`.
|
|
243
|
+
|
|
244
|
+
Set html content of an element or instantiate a template.
|
|
245
|
+
|
|
246
|
+
```html
|
|
247
|
+
Hello, <span :html="userElement">Guest</span>.
|
|
248
|
+
|
|
249
|
+
<!-- fragment -->
|
|
250
|
+
Hello, <template :html="user.name">Guest</template>.
|
|
251
|
+
|
|
252
|
+
<!-- instantiate template -->
|
|
253
|
+
<template :ref="tpl"><span :text="foo"></span></template>
|
|
254
|
+
<div :html="tpl" :with="{foo:'bar'}">...inserted here...</div>
|
|
255
|
+
```
|
|
256
|
+
|
|
256
257
|
<!--
|
|
257
258
|
#### `:onvisible..oninvisible="e => e => {}"`
|
|
258
259
|
|
|
@@ -302,6 +303,15 @@ Provider | Size | Feature
|
|
|
302
303
|
[`@preact/signals-core`](https://ghub.io/@preact/signals-core) | 1.47kb | Best performance, good for any states, industry standard.
|
|
303
304
|
[`signal-polyfill`](https://github.com/proposal-signals/signal-polyfill) | 2.5kb | Proposal signals. Use via [adapter](https://gist.github.com/dy/bbac687464ccf5322ab0e2fd0680dc4d).
|
|
304
305
|
|
|
306
|
+
## Untracked
|
|
307
|
+
|
|
308
|
+
Properties prefixed with `_` indicate untracked value:
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
let state = sprae(el, {x:1, _y:2})
|
|
312
|
+
state.x++ // updates template
|
|
313
|
+
state._y++ // no side-effect
|
|
314
|
+
```
|
|
305
315
|
|
|
306
316
|
## Evaluator
|
|
307
317
|
|
package/store.js
CHANGED
|
@@ -21,8 +21,8 @@ export default function store(values, parent) {
|
|
|
21
21
|
|
|
22
22
|
// proxy conducts prop access to signals
|
|
23
23
|
const state = new Proxy(signals, {
|
|
24
|
-
get: (_, key) => key === _change ? _len : key === _signals ? signals : signals[key]?.valueOf(),
|
|
25
|
-
set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s
|
|
24
|
+
get: (_, key) => key === _change ? _len : key === _signals ? signals : (signals[key]?.valueOf()),
|
|
25
|
+
set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s ?? (++_len.value), 1), // bump length for new signal
|
|
26
26
|
deleteProperty: (_, key) => (signals[key] && (del(signals, key), _len.value--), 1),
|
|
27
27
|
ownKeys() {
|
|
28
28
|
// subscribe to length when object is spread
|
|
@@ -42,7 +42,7 @@ export default function store(values, parent) {
|
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
44
44
|
// init blank signal - make sure we don't take prototype one
|
|
45
|
-
signals[key] =
|
|
45
|
+
signals[key] = undefined
|
|
46
46
|
set(signals, key, values[key]);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -64,7 +64,7 @@ export function list(values) {
|
|
|
64
64
|
// .length signal is stored separately, since it cannot be replaced on array
|
|
65
65
|
let _len = signal(values.length),
|
|
66
66
|
// gotta fill with null since proto methods like .reduce may fail
|
|
67
|
-
signals = Array(values.length).fill(
|
|
67
|
+
signals = Array(values.length).fill();
|
|
68
68
|
|
|
69
69
|
// proxy conducts prop access to signals
|
|
70
70
|
const state = new Proxy(signals, {
|
|
@@ -114,8 +114,10 @@ export function list(values) {
|
|
|
114
114
|
function set(signals, key, v) {
|
|
115
115
|
let s = signals[key]
|
|
116
116
|
|
|
117
|
+
// untracked
|
|
118
|
+
if (key[0] === '_') signals[key] = v
|
|
117
119
|
// new property
|
|
118
|
-
if (!s) {
|
|
120
|
+
else if (!s) {
|
|
119
121
|
// preserve signal value as is
|
|
120
122
|
signals[key] = s = v?.peek ? v : signal(store(v))
|
|
121
123
|
}
|