sprae 10.0.1 → 10.1.0
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/core.js +49 -66
- package/directive/each.js +7 -4
- package/directive/with.js +16 -8
- package/dist/sprae.js +65 -102
- package/dist/sprae.min.js +1 -1
- package/package.json +1 -1
- package/readme.md +5 -4
- package/sprae.js +0 -4
- package/store.js +5 -7
package/core.js
CHANGED
|
@@ -1,90 +1,73 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { use } from "./signal.js";
|
|
2
2
|
import store, { _signals } from './store.js';
|
|
3
3
|
|
|
4
4
|
// polyfill
|
|
5
5
|
const _dispose = (Symbol.dispose ||= Symbol("dispose"));
|
|
6
6
|
|
|
7
|
-
// mark
|
|
8
|
-
const SPRAE = `∴`
|
|
9
|
-
|
|
10
7
|
// reserved directives - order matters!
|
|
11
8
|
export const directive = {};
|
|
12
9
|
|
|
13
10
|
// sprae element: apply directives
|
|
14
11
|
const memo = new WeakMap();
|
|
15
12
|
|
|
16
|
-
export default function sprae(
|
|
17
|
-
|
|
13
|
+
export default function sprae(el, values) {
|
|
14
|
+
// text nodes, comments etc - but collections are fine
|
|
15
|
+
if (!el?.children) return
|
|
18
16
|
|
|
19
|
-
//
|
|
20
|
-
if (
|
|
17
|
+
// repeated call can be caused by :each with new objects with old keys needs an update
|
|
18
|
+
if (memo.has(el)) {
|
|
19
|
+
// we rewrite signals instead of update, because user should have what he provided
|
|
20
|
+
return Object.assign(memo.get(el), values)
|
|
21
|
+
}
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (el?.children) {
|
|
25
|
-
// repeated call can be caused by :each with new objects with old keys needs an update
|
|
26
|
-
if (memo.has(el)) {
|
|
27
|
-
// we rewrite signals instead of update, because user should have what he provided
|
|
28
|
-
Object.assign(memo.get(el), values)
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
// take over existing state instead of creating clone
|
|
32
|
-
state ||= store(values || {});
|
|
23
|
+
// take over existing state instead of creating clone
|
|
24
|
+
const state = store(values || {}), disposes = []
|
|
33
25
|
|
|
34
|
-
|
|
26
|
+
init(el);
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
// if element was spraed by :with or :each instruction - skip, otherwise save
|
|
29
|
+
if (!memo.has(el)) memo.set(el, state);
|
|
30
|
+
|
|
31
|
+
el[_dispose] = () => {
|
|
32
|
+
while (disposes.length) disposes.pop()();
|
|
33
|
+
memo.delete(el);
|
|
34
|
+
}
|
|
41
35
|
|
|
42
36
|
return state;
|
|
43
|
-
}
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
38
|
+
function init(el, parent = el.parentNode) {
|
|
39
|
+
if (el.attributes) {
|
|
40
|
+
// init generic-name attributes second
|
|
41
|
+
for (let i = 0; i < el.attributes.length;) {
|
|
42
|
+
let attr = el.attributes[i];
|
|
43
|
+
|
|
44
|
+
if (attr.name[0] === ':') {
|
|
45
|
+
el.removeAttribute(attr.name);
|
|
46
|
+
|
|
47
|
+
// multiple attributes like :id:for=""
|
|
48
|
+
let names = attr.name.slice(1).split(':')
|
|
49
|
+
|
|
50
|
+
// NOTE: secondary directives don't stop flow nor extend state, so no need to check
|
|
51
|
+
for (let name of names) {
|
|
52
|
+
let dir = directive[name] || directive.default
|
|
53
|
+
let evaluate = (dir.parse || parse)(attr.value, parse)
|
|
54
|
+
let dispose = dir(el, evaluate, state, name);
|
|
55
|
+
if (dispose) disposes.push(dispose);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// stop if element was spraed by internal directive
|
|
59
|
+
if (memo.has(el)) return disposes.push(el[_dispose]);
|
|
60
|
+
|
|
61
|
+
// stop if element is skipped (detached) like in case of :if or :each
|
|
62
|
+
if (el.parentNode !== parent) return;
|
|
63
|
+
} else i++;
|
|
64
|
+
}
|
|
72
65
|
}
|
|
73
|
-
}
|
|
74
66
|
|
|
75
|
-
|
|
67
|
+
for (let child of [...el.children]) init(child, el)
|
|
68
|
+
};
|
|
69
|
+
}
|
|
76
70
|
|
|
77
|
-
// mark spraed element
|
|
78
|
-
el.classList?.add(SPRAE);
|
|
79
|
-
el[_dispose] = () => {
|
|
80
|
-
while (effects.length) effects.pop()();
|
|
81
|
-
el.classList.remove(SPRAE);
|
|
82
|
-
memo.delete(el);
|
|
83
|
-
// NOTE: each child disposes own children etc.
|
|
84
|
-
let els = el.getElementsByClassName(SPRAE);
|
|
85
|
-
while (els.length) els[0][_dispose]?.()
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
71
|
|
|
89
72
|
// compiler
|
|
90
73
|
const evalMemo = {};
|
package/directive/each.js
CHANGED
|
@@ -58,15 +58,18 @@ directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
|
|
|
58
58
|
[itemVar]: { get() { return cur[idx] } },
|
|
59
59
|
[idxVar]: { value: keys ? keys[idx] : idx },
|
|
60
60
|
}),
|
|
61
|
-
el = (tpl.content || tpl).cloneNode(true),
|
|
62
|
-
|
|
61
|
+
el = (tpl.content || tpl).cloneNode(true),
|
|
62
|
+
frag = tpl.content ?
|
|
63
|
+
// fake fragment to init sprae
|
|
64
|
+
{ children: [...el.children], remove() { this.children.map(el => el.remove()) } } :
|
|
65
|
+
el;
|
|
63
66
|
|
|
64
67
|
holder.before(el);
|
|
65
|
-
sprae(
|
|
68
|
+
sprae(frag, scope);
|
|
66
69
|
|
|
67
70
|
// signal/holder disposal removes element
|
|
68
71
|
((cur[_signals] ||= [])[i] ||= {})[Symbol.dispose] = () => {
|
|
69
|
-
|
|
72
|
+
frag[Symbol.dispose](), frag.remove()
|
|
70
73
|
};
|
|
71
74
|
}
|
|
72
75
|
}
|
package/directive/with.js
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import sprae, { directive } from "../core.js";
|
|
2
2
|
import store, { _signals } from '../store.js';
|
|
3
3
|
import { effect } from "../signal.js";
|
|
4
|
+
import { signal } from "ulive";
|
|
4
5
|
|
|
5
6
|
directive.with = (el, evaluate, rootState) => {
|
|
6
|
-
let state
|
|
7
|
+
let state
|
|
7
8
|
return effect(() => {
|
|
8
|
-
values = evaluate(rootState);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
)
|
|
14
|
-
|
|
9
|
+
let values = evaluate(rootState);
|
|
10
|
+
|
|
11
|
+
if (!state) {
|
|
12
|
+
state = store({});
|
|
13
|
+
// inherit root signals
|
|
14
|
+
Object.assign(state[_signals], rootState[_signals]);
|
|
15
|
+
// create local scope signals
|
|
16
|
+
for (let key in values) state[_signals][key] = null, state[key] = values[key]
|
|
17
|
+
|
|
18
|
+
sprae(el, state)
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
Object.assign(state, values)
|
|
22
|
+
}
|
|
15
23
|
})
|
|
16
24
|
};
|
package/dist/sprae.js
CHANGED
|
@@ -21,17 +21,16 @@ function use(s) {
|
|
|
21
21
|
// store.js
|
|
22
22
|
var _signals = Symbol("signals");
|
|
23
23
|
var _change = Symbol("length");
|
|
24
|
-
function store(values
|
|
24
|
+
function store(values) {
|
|
25
25
|
if (!values)
|
|
26
26
|
return values;
|
|
27
|
-
if (values[_signals]
|
|
27
|
+
if (values[_signals])
|
|
28
28
|
return values;
|
|
29
29
|
if (Array.isArray(values))
|
|
30
30
|
return list(values);
|
|
31
31
|
if (values.constructor !== Object)
|
|
32
32
|
return values;
|
|
33
|
-
let _len = signal(Object.values(values).length);
|
|
34
|
-
signals ||= {};
|
|
33
|
+
let signals = {}, _len = signal(Object.values(values).length);
|
|
35
34
|
const state = new Proxy(signals, {
|
|
36
35
|
get: (_, key) => key === _change ? _len : key === _signals ? signals : signals[key]?.valueOf(),
|
|
37
36
|
set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s || ++_len.value),
|
|
@@ -41,19 +40,15 @@ function store(values, signals) {
|
|
|
41
40
|
return Reflect.ownKeys(signals);
|
|
42
41
|
}
|
|
43
42
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
(signals[key] = computed(desc.get.bind(state)))._set = desc.set?.bind(state);
|
|
52
|
-
} else {
|
|
53
|
-
signals[key] = null;
|
|
54
|
-
set(signals, key, values[key]);
|
|
55
|
-
}
|
|
43
|
+
for (let key in values) {
|
|
44
|
+
const desc = Object.getOwnPropertyDescriptor(values, key);
|
|
45
|
+
if (desc?.get) {
|
|
46
|
+
(signals[key] = computed(desc.get.bind(state)))._set = desc.set?.bind(state);
|
|
47
|
+
} else {
|
|
48
|
+
signals[key] = null;
|
|
49
|
+
set(signals, key, values[key]);
|
|
56
50
|
}
|
|
51
|
+
}
|
|
57
52
|
return state;
|
|
58
53
|
}
|
|
59
54
|
function list(values) {
|
|
@@ -131,62 +126,50 @@ function del(signals, key) {
|
|
|
131
126
|
|
|
132
127
|
// core.js
|
|
133
128
|
var _dispose = Symbol.dispose ||= Symbol("dispose");
|
|
134
|
-
var SPRAE = `\u2234`;
|
|
135
129
|
var directive = {};
|
|
136
130
|
var memo = /* @__PURE__ */ new WeakMap();
|
|
137
|
-
function sprae(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (el?.children) {
|
|
143
|
-
if (memo.has(el)) {
|
|
144
|
-
Object.assign(memo.get(el), values);
|
|
145
|
-
} else {
|
|
146
|
-
state ||= store(values || {});
|
|
147
|
-
init(el, state);
|
|
148
|
-
if (!memo.has(el))
|
|
149
|
-
memo.set(el, state);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
;
|
|
154
|
-
return state;
|
|
155
|
-
}
|
|
156
|
-
function init(el, state, parent = el.parentNode, effects = []) {
|
|
157
|
-
if (el.attributes) {
|
|
158
|
-
for (let i = 0; i < el.attributes.length; ) {
|
|
159
|
-
let attr2 = el.attributes[i];
|
|
160
|
-
if (attr2.name[0] === ":") {
|
|
161
|
-
el.removeAttribute(attr2.name);
|
|
162
|
-
let names = attr2.name.slice(1).split(":");
|
|
163
|
-
for (let name of names) {
|
|
164
|
-
let dir = directive[name] || directive.default;
|
|
165
|
-
let evaluate = (dir.parse || parse)(attr2.value, parse);
|
|
166
|
-
let dispose = dir(el, evaluate, state, name);
|
|
167
|
-
if (dispose)
|
|
168
|
-
effects.push(dispose);
|
|
169
|
-
}
|
|
170
|
-
if (memo.has(el))
|
|
171
|
-
return;
|
|
172
|
-
if (el.parentNode !== parent)
|
|
173
|
-
return;
|
|
174
|
-
} else
|
|
175
|
-
i++;
|
|
176
|
-
}
|
|
131
|
+
function sprae(el, values) {
|
|
132
|
+
if (!el?.children)
|
|
133
|
+
return;
|
|
134
|
+
if (memo.has(el)) {
|
|
135
|
+
return Object.assign(memo.get(el), values);
|
|
177
136
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
137
|
+
const state = store(values || {}), disposes = [];
|
|
138
|
+
init(el);
|
|
139
|
+
if (!memo.has(el))
|
|
140
|
+
memo.set(el, state);
|
|
181
141
|
el[_dispose] = () => {
|
|
182
|
-
while (
|
|
183
|
-
|
|
184
|
-
el.classList.remove(SPRAE);
|
|
142
|
+
while (disposes.length)
|
|
143
|
+
disposes.pop()();
|
|
185
144
|
memo.delete(el);
|
|
186
|
-
let els = el.getElementsByClassName(SPRAE);
|
|
187
|
-
while (els.length)
|
|
188
|
-
els[0][_dispose]?.();
|
|
189
145
|
};
|
|
146
|
+
return state;
|
|
147
|
+
function init(el2, parent = el2.parentNode) {
|
|
148
|
+
if (el2.attributes) {
|
|
149
|
+
for (let i = 0; i < el2.attributes.length; ) {
|
|
150
|
+
let attr2 = el2.attributes[i];
|
|
151
|
+
if (attr2.name[0] === ":") {
|
|
152
|
+
el2.removeAttribute(attr2.name);
|
|
153
|
+
let names = attr2.name.slice(1).split(":");
|
|
154
|
+
for (let name of names) {
|
|
155
|
+
let dir = directive[name] || directive.default;
|
|
156
|
+
let evaluate = (dir.parse || parse)(attr2.value, parse);
|
|
157
|
+
let dispose = dir(el2, evaluate, state, name);
|
|
158
|
+
if (dispose)
|
|
159
|
+
disposes.push(dispose);
|
|
160
|
+
}
|
|
161
|
+
if (memo.has(el2))
|
|
162
|
+
return disposes.push(el2[_dispose]);
|
|
163
|
+
if (el2.parentNode !== parent)
|
|
164
|
+
return;
|
|
165
|
+
} else
|
|
166
|
+
i++;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for (let child of [...el2.children])
|
|
170
|
+
init(child, el2);
|
|
171
|
+
}
|
|
172
|
+
;
|
|
190
173
|
}
|
|
191
174
|
var evalMemo = {};
|
|
192
175
|
var parse = (expr, dir, fn) => {
|
|
@@ -273,28 +256,6 @@ var batch2 = (fn) => {
|
|
|
273
256
|
};
|
|
274
257
|
var untracked2 = (fn, prev, v) => (prev = current, current = null, v = fn(), current = prev, v);
|
|
275
258
|
|
|
276
|
-
// node_modules/swapdom/deflate.js
|
|
277
|
-
var swap = (parent, a, b, end = null, { remove, insert } = swap) => {
|
|
278
|
-
let i = 0, cur, next, bi, bidx = new Set(b);
|
|
279
|
-
while (bi = a[i++])
|
|
280
|
-
!bidx.has(bi) ? remove(bi, parent) : cur = cur || bi;
|
|
281
|
-
cur = cur || end, i = 0;
|
|
282
|
-
while (bi = b[i++]) {
|
|
283
|
-
next = cur ? cur.nextSibling : end;
|
|
284
|
-
if (cur === bi)
|
|
285
|
-
cur = next;
|
|
286
|
-
else {
|
|
287
|
-
if (b[i] === next)
|
|
288
|
-
cur = next;
|
|
289
|
-
insert(bi, cur, parent);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
return b;
|
|
293
|
-
};
|
|
294
|
-
swap.insert = (a, b, parent) => parent.insertBefore(a, b);
|
|
295
|
-
swap.remove = (a, parent) => parent.removeChild(a);
|
|
296
|
-
var deflate_default = swap;
|
|
297
|
-
|
|
298
259
|
// directive/each.js
|
|
299
260
|
var _each = Symbol(":each");
|
|
300
261
|
directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
|
|
@@ -336,12 +297,13 @@ directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
|
|
|
336
297
|
return cur[idx];
|
|
337
298
|
} },
|
|
338
299
|
[idxVar]: { value: keys2 ? keys2[idx] : idx }
|
|
339
|
-
}), el = (tpl.content || tpl).cloneNode(true),
|
|
300
|
+
}), el = (tpl.content || tpl).cloneNode(true), frag = tpl.content ? { children: [...el.children], remove() {
|
|
301
|
+
this.children.map((el2) => el2.remove());
|
|
302
|
+
} } : el;
|
|
340
303
|
holder.before(el);
|
|
341
|
-
sprae(
|
|
304
|
+
sprae(frag, scope);
|
|
342
305
|
((cur[_signals] ||= [])[i] ||= {})[Symbol.dispose] = () => {
|
|
343
|
-
|
|
344
|
-
el2[Symbol.dispose](), el2.remove();
|
|
306
|
+
frag[Symbol.dispose](), frag.remove();
|
|
345
307
|
};
|
|
346
308
|
}
|
|
347
309
|
}
|
|
@@ -543,16 +505,18 @@ directive.ref.parse = (expr) => expr;
|
|
|
543
505
|
|
|
544
506
|
// directive/with.js
|
|
545
507
|
directive.with = (el, evaluate, rootState) => {
|
|
546
|
-
let state
|
|
508
|
+
let state;
|
|
547
509
|
return effect(() => {
|
|
548
|
-
values = evaluate(rootState);
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
)
|
|
555
|
-
|
|
510
|
+
let values = evaluate(rootState);
|
|
511
|
+
if (!state) {
|
|
512
|
+
state = store({});
|
|
513
|
+
Object.assign(state[_signals], rootState[_signals]);
|
|
514
|
+
for (let key in values)
|
|
515
|
+
state[_signals][key] = null, state[key] = values[key];
|
|
516
|
+
sprae(el, state);
|
|
517
|
+
} else {
|
|
518
|
+
Object.assign(state, values);
|
|
519
|
+
}
|
|
556
520
|
});
|
|
557
521
|
};
|
|
558
522
|
|
|
@@ -637,7 +601,6 @@ directive.fx = (el, evaluate, state) => {
|
|
|
637
601
|
// sprae.js
|
|
638
602
|
sprae.use(ulive_es_exports);
|
|
639
603
|
sprae.use({ compile: (expr) => sprae.constructor(`__scope`, `with (__scope) { return ${expr} };`) });
|
|
640
|
-
sprae.use({ swap: deflate_default });
|
|
641
604
|
var sprae_default = sprae;
|
|
642
605
|
export {
|
|
643
606
|
sprae_default as default
|
package/dist/sprae.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e,t,r,l,n,s=Object.defineProperty,a=Symbol("signals"),o=Symbol("length");function i(t
|
|
1
|
+
var e,t,r,l,n,s=Object.defineProperty,a=Symbol("signals"),o=Symbol("length");function i(t){if(!t)return t;if(t[a])return t;if(Array.isArray(t))return function(t){let r;if(t[a])return t;let l=e(t.length),n=Array(t.length).fill(null);const s=new Proxy(n,{get:(s,c)=>c===o?l:c===a?n:"length"===c?Array.prototype[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)=>(u(n,t),!0)});return s}(t);if(t.constructor!==Object)return t;let r={},l=e(Object.values(t).length);const s=new Proxy(r,{get:(e,t)=>t===o?l:t===a?r:r[t]?.valueOf(),set:(e,t,n,s)=>(s=r[t],c(r,t,n),s||++l.value),deleteProperty:(e,t)=>u(r,t)&&l.value--,ownKeys:()=>(l.value,Reflect.ownKeys(r))});for(let e in t){const l=Object.getOwnPropertyDescriptor(t,e);l?.get?(r[e]=n(l.get.bind(s)))._set=l.set?.bind(s):(r[e]=null,c(r,e,t[e]))}return s}function c(t,n,s){let a=t[n];if(a)if(s===a.peek());else if(a._set)a._set(s);else if(Array.isArray(s)&&Array.isArray(a.peek())){const e=a.peek();e[o]?r((()=>{l((()=>{let t=0,r=s.length;for(;t<r;t++)e[t]=s[t];e.length=r}))})):a.value=s}else a.value=i(s);else t[n]=a=s?.peek?s:e(i(s))}function u(e,t){const r=e[t];if(r){const l=r[Symbol.dispose];return l&&delete r[Symbol.dispose],delete e[t],l?.(),!0}}var f=Symbol.dispose||=Symbol("dispose"),p={},d=new WeakMap;function y(e,t){if(!e?.children)return;if(d.has(e))return Object.assign(d.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=p[n]||p.default,a=e(t,(e.parse||g)(s.value,g),r,n);a&&l.push(a)}if(d.has(t))return l.push(t[f]);if(t.parentNode!==n)return}else e++}for(let r of[...t.children])e(r,t)}(e),d.has(e)||d.set(e,r),e[f]=()=>{for(;l.length;)l.pop()();d.delete(e)},r}var v,h={},g=(e,t,r)=>{if(r=h[e=e.trim()])return r;try{r=v(e)}catch(r){throw Object.assign(r,{message:`∴ ${r.message}\n\n${t}${e?`="${e}"\n\n`:""}`,expr:e})}return h[e]=r};y.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&&(v=s.compile)};var b,m,k={};((e,t)=>{for(var r in t)s(e,r,{get:t[r],enumerable:!0})})(k,{batch:()=>O,computed:()=>w,effect:()=>S,signal:()=>A,untracked:()=>N});var A=(e,t,r=new Set)=>((t={get value(){return b?.deps.push(r.add(b)),e},set value(t){if(t!==e){e=t;for(let e of r)m?m.add(e):e()}},peek:()=>e}).toJSON=t.then=t.toString=t.valueOf=()=>t.value,t),S=(e,t,r,l)=>(l=(r=l=>{t?.call?.(),l=b,b=r;try{t=e()}finally{b=l}}).deps=[],r(),e=>{for(t?.call?.();e=l.pop();)e.delete(r)}),w=(e,t=A(),r,l)=>((r={get value(){return l||=S((()=>t.value=e())),t.value},peek:t.peek}).toJSON=r.then=r.toString=r.valueOf=()=>r.value,r),O=e=>{let t=m;t||(m=new Set);try{e()}finally{if(!t){t=m,m=null;for(const e of t)e()}}},N=(e,t,r)=>(t=b,b=null,r=e(),b=t,r),j=Symbol(":each");p.each=(e,[l,s,i],c)=>{const u=e[j]=document.createTextNode("");e.replaceWith(u);let f,p,d=0;const v=n((()=>{p=null;let e=i(c);return"number"==typeof e&&(e=Array.from({length:e},((e,t)=>t+1))),e?.constructor===Object&&(p=Object.keys(e),e=Object.values(e)),e||[]})),h=()=>{r((()=>{let t=0,r=v.value,n=r.length;if(f&&!f[o]){for(let e of f[a]||[])e[Symbol.dispose]();f=null,d=0}if(n<d)f.length=n;else{if(f)for(;t<d;t++)f[t]=r[t];else f=r;for(;t<n;t++){f[t]=r[t];let n=t,o=Object.create(c,{[l]:{get:()=>f[n]},[s]:{value:p?p[n]:n}}),i=(e.content||e).cloneNode(!0),d=e.content?{children:[...i.children],remove(){this.children.map((e=>e.remove()))}}:i;u.before(i),y(d,o),((f[a]||=[])[t]||={})[Symbol.dispose]=()=>{d[Symbol.dispose](),d.remove()}}}d=n}))};let g=0;return t((()=>{f||v.value[o]?.value,g?g++:(h(),queueMicrotask((()=>(g&&h(),g=0))))}))},p.each.parse=(e,t)=>{let[r,l]=e.split(/\s+in\s+/),[n,s="$"]=r.split(/\s*,\s*/);return[n,s,t(l)]};var x=Symbol("if");p.if=(e,r,l)=>{let n,s,a,o=e.parentNode,i=e.nextElementSibling,c=document.createTextNode(""),u=[];return e.after(c),e.content?(n=u,e.remove(),s=[...e.content.childNodes]):s=n=[e],i?.hasAttribute(":else")?(i.removeAttribute(":else"),i.hasAttribute(":if")?a=u:(i.remove(),a=i.content?[...i.content.childNodes]:[i])):a=u,t((()=>{const t=r(l)?s:e[x]?u:a;if(i&&(i[x]=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)o.insertBefore(e,c),y(e,l)}}))},p.default=(e,r,l,n)=>{let s,a=n.startsWith("on")&&n.slice(2);return t(a?()=>(s?.(),s=$(e,a,r(l))):()=>{let t=r(l);if(n)T(e,n,D(t,l));else for(let r in t)T(e,_(r),D(t[r],l))})};var $=(e,t,r=(()=>{}))=>{const l={evt:"",target:e,test:()=>!0};l.evt=t.replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,r="")=>(l.test=E[t]?.(l,...r.split("-"))||l.test,"")));const{evt:n,target:s,test:a,defer:o,stop:i,prevent:c,...u}=l;o&&(r=o(r));const f=e=>a(e)&&(i&&e.stopPropagation(),c&&e.preventDefault(),r.call(s,e));return s.addEventListener(n,f,u),()=>s.removeEventListener(n,f,u)},E={prevent(e){e.prevent=!0},stop(e){e.stop=!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=>W(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=>P.ctrl(e)&&t.every((t=>P[t]?P[t](e):e.key===t)),shift:(e,...t)=>e=>P.shift(e)&&t.every((t=>P[t]?P[t](e):e.key===t)),alt:(e,...t)=>e=>P.alt(e)&&t.every((t=>P[t]?P[t](e):e.key===t)),meta:(e,...t)=>e=>P.meta(e)&&t.every((t=>P[t]?P[t](e):e.key===t)),arrow:()=>P.arrow,enter:()=>P.enter,escape:()=>P.escape,tab:()=>P.tab,space:()=>P.space,backspace:()=>P.backspace,delete:()=>P.delete,digit:()=>P.digit,letter:()=>P.letter,character:()=>P.character},P={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,escape:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,backspace:e=>"Backspace"===e.key,delete:e=>"Delete"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^[a-zA-Z]$/.test(e.key),character:e=>/^\S$/.test(e.key)},T=(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))},W=(e,t)=>{let r;return l=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(l)}),t)}},_=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),D=(e,t)=>e?.replace?e.replace(/\$<([^>]+)>/g,((e,r)=>t[r]??"")):e;p.ref=(e,t,r)=>{Object.defineProperty(r,D(t,r),{value:e})},p.ref.parse=e=>e,p.with=(e,r,l)=>{let n;return t((()=>{let t=r(l);if(n)Object.assign(n,t);else{n=i({}),Object.assign(n[a],l[a]);for(let e in t)n[a][e]=null,n[e]=t[e];y(e,n)}}))},p.html=(e,t,r)=>{let l=t(r);if(!l)return;let n=(l.content||l).cloneNode(!0);e.replaceChildren(n),y(e,r)},p.text=(e,r,l)=>(e.content&&e.replaceWith(e=document.createTextNode("")),t((()=>{let t=r(l);e.textContent=null==t?"":t}))),p.class=(e,r,l)=>{let n=new Set;return t((()=>{let t=r(l),s=new Set;t&&("string"==typeof t?D(t,l).split(" ").map((e=>s.add(e))):Array.isArray(t)?t.map((e=>(e=D(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)}))},p.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+D(t,l));else{e.setAttribute("style",n);for(let r in t)e.style.setProperty(r,D(t[r],l))}}))},p.value=(e,r,l)=>{let n,s,a="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,T(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((()=>a(r(l))))},p.fx=(e,r,l)=>t((()=>r(l))),y.use(k),y.use({compile:e=>y.constructor("__scope",`with (__scope) { return ${e} };`)});var K=y;export{K as default};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -144,7 +144,7 @@ Set any attribute(s).
|
|
|
144
144
|
Define values for a subtree.
|
|
145
145
|
|
|
146
146
|
```html
|
|
147
|
-
<x :with="{ foo:
|
|
147
|
+
<x :with="{ foo: 'bar' }">
|
|
148
148
|
<y :with="{ baz: 'qux' }" :text="foo + baz"></y>
|
|
149
149
|
</x>
|
|
150
150
|
```
|
|
@@ -335,7 +335,7 @@ import { effect } from 'sprae/signal'
|
|
|
335
335
|
import * as signals from '@preact/signals'
|
|
336
336
|
import compile from 'subscript'
|
|
337
337
|
|
|
338
|
-
//
|
|
338
|
+
// standard directives
|
|
339
339
|
import 'sprae/directive/if.js'
|
|
340
340
|
import 'sprae/directive/text.js'
|
|
341
341
|
|
|
@@ -358,9 +358,10 @@ To destroy state and detach sprae handlers, call `element[Symbol.dispose]()`. --
|
|
|
358
358
|
|
|
359
359
|
## Justification
|
|
360
360
|
|
|
361
|
-
[Template-parts](https://github.com/dy/template-parts) is stuck with native HTML quirks ([parsing table](https://github.com/github/template-parts/issues/24), [SVG attributes](https://github.com/github/template-parts/issues/25), [liquid syntax](https://shopify.github.io/liquid/tags/template/#raw) conflict etc)
|
|
361
|
+
[Template-parts](https://github.com/dy/template-parts) is stuck with native HTML quirks ([parsing table](https://github.com/github/template-parts/issues/24), [SVG attributes](https://github.com/github/template-parts/issues/25), [liquid syntax](https://shopify.github.io/liquid/tags/template/#raw) conflict etc).<br/>
|
|
362
|
+
[Alpine](https://github.com/alpinejs/alpine) / [petite-vue](https://github.com/vuejs/petite-vue) / [lucia](https://github.com/aidenyabi/lucia) escape native HTML quirks, but have excessive API (`:`, `x-`, `{}`, `@`, `$`) and tend to [self-encapsulate](https://github.com/alpinejs/alpine/discussions/3223).
|
|
362
363
|
|
|
363
|
-
_Sprae_ holds open & minimalistic philosophy, combining _`:`-directives_ with
|
|
364
|
+
_Sprae_ holds open & minimalistic philosophy, combining _`:`-directives_ with _signals_.
|
|
364
365
|
|
|
365
366
|
<!--
|
|
366
367
|
| | [AlpineJS](https://github.com/alpinejs/alpine) | [Petite-Vue](https://github.com/vuejs/petite-vue) | Sprae |
|
package/sprae.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import sprae from './core.js'
|
|
2
2
|
|
|
3
3
|
import * as signals from 'ulive'
|
|
4
|
-
import swap from 'swapdom/deflate'
|
|
5
4
|
|
|
6
5
|
// default directives
|
|
7
6
|
import './directive/if.js'
|
|
@@ -22,7 +21,4 @@ sprae.use(signals)
|
|
|
22
21
|
// default compiler (indirect new Function to avoid detector)
|
|
23
22
|
sprae.use({ compile: expr => sprae.constructor(`__scope`, `with (__scope) { return ${expr} };`) })
|
|
24
23
|
|
|
25
|
-
// defaul dom swapper
|
|
26
|
-
sprae.use({ swap })
|
|
27
|
-
|
|
28
24
|
export default sprae
|
package/store.js
CHANGED
|
@@ -4,11 +4,11 @@ import { signal, computed, effect, batch, untracked } from './signal.js'
|
|
|
4
4
|
export const _signals = Symbol('signals'), _change = Symbol('length');
|
|
5
5
|
|
|
6
6
|
// object store is not lazy
|
|
7
|
-
export default function store(values
|
|
7
|
+
export default function store(values) {
|
|
8
8
|
if (!values) return values
|
|
9
9
|
|
|
10
10
|
// ignore existing state as argument
|
|
11
|
-
if (values[_signals]
|
|
11
|
+
if (values[_signals]) return values;
|
|
12
12
|
|
|
13
13
|
// redirect for optimized array store
|
|
14
14
|
if (Array.isArray(values)) return list(values)
|
|
@@ -17,9 +17,8 @@ export default function store(values, signals) {
|
|
|
17
17
|
if (values.constructor !== Object) return values;
|
|
18
18
|
|
|
19
19
|
// NOTE: if you decide to unlazy values, think about large arrays - init upfront can be costly
|
|
20
|
-
let _len = signal(Object.values(values).length)
|
|
20
|
+
let signals = {}, _len = signal(Object.values(values).length)
|
|
21
21
|
|
|
22
|
-
signals ||= {}
|
|
23
22
|
// proxy conducts prop access to signals
|
|
24
23
|
const state = new Proxy(signals, {
|
|
25
24
|
get: (_, key) => key === _change ? _len : key === _signals ? signals : signals[key]?.valueOf(),
|
|
@@ -32,9 +31,8 @@ export default function store(values, signals) {
|
|
|
32
31
|
},
|
|
33
32
|
})
|
|
34
33
|
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
else for (let key in values) {
|
|
34
|
+
// init signals for values
|
|
35
|
+
for (let key in values) {
|
|
38
36
|
const desc = Object.getOwnPropertyDescriptor(values, key)
|
|
39
37
|
|
|
40
38
|
// getter turns into computed
|