sprae 2.5.5 → 2.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/package.json +2 -2
- package/r&d.md +11 -2
- package/readme.md +1 -1
- package/sprae.js +86 -62
- package/sprae.min.js +1 -1
- package/src/core.js +8 -2
- package/src/directives.js +52 -36
- package/test/test.js +33 -0
- package/{plan.md → todo.md} +3 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sprae",
|
|
3
3
|
"description": "DOM microhydration.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.6.1",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"module": "src/index.js",
|
|
7
7
|
"type": "module",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"@preact/signals": "^1.1.2",
|
|
16
16
|
"es-module-shims": "^1.6.2",
|
|
17
17
|
"esbuild": "^0.15.14",
|
|
18
|
-
"hyperf": "^1.
|
|
18
|
+
"hyperf": "^1.5.0",
|
|
19
19
|
"jsdom": "^20.0.3",
|
|
20
20
|
"terser": "^5.15.1",
|
|
21
21
|
"tst": "^7.1.1",
|
package/r&d.md
CHANGED
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
|
|
98
98
|
-> possibly we have to just subscribe via mechanism of signals-like deps, and :with just initializes subtree with extended object
|
|
99
99
|
|
|
100
|
-
## [
|
|
100
|
+
## [x] :with? -> let's use `:with="{x:1,y:2,z:3}"` for now
|
|
101
101
|
|
|
102
102
|
1. Get rid of :with
|
|
103
103
|
+ with is bad JS practice/association
|
|
@@ -223,7 +223,15 @@
|
|
|
223
223
|
? attach-detach?
|
|
224
224
|
? onmount-onunmount?
|
|
225
225
|
- slows down domdiff
|
|
226
|
-
- can be solved as `<x :if="xxx" :="xxx
|
|
226
|
+
- can be solved as `<x :if="xxx" :="xxx && (...)'">` automatically
|
|
227
|
+
|
|
228
|
+
## [x] :onmount/onunmount? -> for now no reasons
|
|
229
|
+
|
|
230
|
+
+ useful for :if, :each
|
|
231
|
+
+ useful to dispose listeners via :onunmount (opposed to hidden symbols)
|
|
232
|
+
- doesn't really solve disposal: if element is attached again, it would need to reattach removed listeners
|
|
233
|
+
-> can be dolved via teardowns returned from updators
|
|
234
|
+
-> nah, event listeners don't need collection, just make sure no refs to element remain
|
|
227
235
|
|
|
228
236
|
## [x] :focus="direct code", :evt="direct code" -> nah, too messy.
|
|
229
237
|
|
|
@@ -394,6 +402,7 @@
|
|
|
394
402
|
.period Period, .
|
|
395
403
|
.slash Foward Slash, /
|
|
396
404
|
- conflict with dot-separated events
|
|
405
|
+
- lots of ad-hoc non-standard rules, can be handled in code
|
|
397
406
|
|
|
398
407
|
## [x] Writing props on elements (like ones in :each) -> nah, just use `:x="this.x=abc"`
|
|
399
408
|
|
package/readme.md
CHANGED
package/sprae.js
CHANGED
|
@@ -6,23 +6,23 @@ function t() {
|
|
|
6
6
|
if (!(n > 1)) {
|
|
7
7
|
var i2, t2 = false;
|
|
8
8
|
while (void 0 !== r) {
|
|
9
|
-
var
|
|
9
|
+
var h = r;
|
|
10
10
|
r = void 0;
|
|
11
11
|
s++;
|
|
12
|
-
while (void 0 !==
|
|
13
|
-
var o2 =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (!(8 &
|
|
12
|
+
while (void 0 !== h) {
|
|
13
|
+
var o2 = h.o;
|
|
14
|
+
h.o = void 0;
|
|
15
|
+
h.f &= -3;
|
|
16
|
+
if (!(8 & h.f) && d(h))
|
|
17
17
|
try {
|
|
18
|
-
|
|
19
|
-
} catch (
|
|
18
|
+
h.c();
|
|
19
|
+
} catch (h2) {
|
|
20
20
|
if (!t2) {
|
|
21
|
-
i2 =
|
|
21
|
+
i2 = h2;
|
|
22
22
|
t2 = true;
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
h = o2;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
s = 0;
|
|
@@ -79,25 +79,25 @@ e.prototype.S = function(i2) {
|
|
|
79
79
|
}
|
|
80
80
|
};
|
|
81
81
|
e.prototype.U = function(i2) {
|
|
82
|
-
var t2 = i2.e,
|
|
82
|
+
var t2 = i2.e, h = i2.x;
|
|
83
83
|
if (void 0 !== t2) {
|
|
84
|
-
t2.x =
|
|
84
|
+
t2.x = h;
|
|
85
85
|
i2.e = void 0;
|
|
86
86
|
}
|
|
87
|
-
if (void 0 !==
|
|
88
|
-
|
|
87
|
+
if (void 0 !== h) {
|
|
88
|
+
h.e = t2;
|
|
89
89
|
i2.x = void 0;
|
|
90
90
|
}
|
|
91
91
|
if (i2 === this.t)
|
|
92
|
-
this.t =
|
|
92
|
+
this.t = h;
|
|
93
93
|
};
|
|
94
94
|
e.prototype.subscribe = function(i2) {
|
|
95
95
|
var t2 = this;
|
|
96
96
|
return b(function() {
|
|
97
|
-
var
|
|
97
|
+
var h = t2.value, o2 = 32 & this.f;
|
|
98
98
|
this.f &= -33;
|
|
99
99
|
try {
|
|
100
|
-
i2(
|
|
100
|
+
i2(h);
|
|
101
101
|
} finally {
|
|
102
102
|
this.f |= o2;
|
|
103
103
|
}
|
|
@@ -117,11 +117,11 @@ Object.defineProperty(e.prototype, "value", { get: function() {
|
|
|
117
117
|
if (void 0 !== i2)
|
|
118
118
|
i2.i = this.i;
|
|
119
119
|
return this.v;
|
|
120
|
-
}, set: function(
|
|
121
|
-
if (
|
|
120
|
+
}, set: function(h) {
|
|
121
|
+
if (h !== this.v) {
|
|
122
122
|
if (s > 100)
|
|
123
123
|
i();
|
|
124
|
-
this.v =
|
|
124
|
+
this.v = h;
|
|
125
125
|
this.i++;
|
|
126
126
|
f++;
|
|
127
127
|
n++;
|
|
@@ -144,33 +144,33 @@ function d(i2) {
|
|
|
144
144
|
}
|
|
145
145
|
function c(i2) {
|
|
146
146
|
for (var t2 = i2.s; void 0 !== t2; t2 = t2.n) {
|
|
147
|
-
var
|
|
148
|
-
if (void 0 !==
|
|
149
|
-
t2.r =
|
|
147
|
+
var h = t2.S.n;
|
|
148
|
+
if (void 0 !== h)
|
|
149
|
+
t2.r = h;
|
|
150
150
|
t2.S.n = t2;
|
|
151
151
|
t2.i = -1;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
function a(i2) {
|
|
155
|
-
var t2 = i2.s,
|
|
155
|
+
var t2 = i2.s, h = void 0;
|
|
156
156
|
while (void 0 !== t2) {
|
|
157
157
|
var o2 = t2.n;
|
|
158
158
|
if (-1 === t2.i) {
|
|
159
159
|
t2.S.U(t2);
|
|
160
160
|
t2.n = void 0;
|
|
161
161
|
} else {
|
|
162
|
-
if (void 0 !==
|
|
163
|
-
|
|
162
|
+
if (void 0 !== h)
|
|
163
|
+
h.p = t2;
|
|
164
164
|
t2.p = void 0;
|
|
165
|
-
t2.n =
|
|
166
|
-
|
|
165
|
+
t2.n = h;
|
|
166
|
+
h = t2;
|
|
167
167
|
}
|
|
168
168
|
t2.S.n = t2.r;
|
|
169
169
|
if (void 0 !== t2.r)
|
|
170
170
|
t2.r = void 0;
|
|
171
171
|
t2 = o2;
|
|
172
172
|
}
|
|
173
|
-
i2.s =
|
|
173
|
+
i2.s = h;
|
|
174
174
|
}
|
|
175
175
|
function l(i2) {
|
|
176
176
|
e.call(this, void 0);
|
|
@@ -259,14 +259,14 @@ function w(i2) {
|
|
|
259
259
|
return new l(i2);
|
|
260
260
|
}
|
|
261
261
|
function y(i2) {
|
|
262
|
-
var
|
|
262
|
+
var h = i2.u;
|
|
263
263
|
i2.u = void 0;
|
|
264
|
-
if ("function" == typeof
|
|
264
|
+
if ("function" == typeof h) {
|
|
265
265
|
n++;
|
|
266
266
|
var r2 = o;
|
|
267
267
|
o = void 0;
|
|
268
268
|
try {
|
|
269
|
-
|
|
269
|
+
h();
|
|
270
270
|
} catch (t2) {
|
|
271
271
|
i2.f &= -2;
|
|
272
272
|
i2.f |= 8;
|
|
@@ -478,12 +478,13 @@ var directives = {};
|
|
|
478
478
|
var directives_default = (el, expr, values, name) => {
|
|
479
479
|
let evt = name.startsWith("on") && name.slice(2);
|
|
480
480
|
let evaluate = parseExpr(el, expr, ":" + name);
|
|
481
|
-
let value;
|
|
482
481
|
if (evaluate)
|
|
483
482
|
return evt ? (state) => {
|
|
484
|
-
value
|
|
485
|
-
|
|
486
|
-
|
|
483
|
+
let value = evaluate(state);
|
|
484
|
+
if (value) {
|
|
485
|
+
addListener(el, evt, value);
|
|
486
|
+
return () => removeListener(el, evt, value);
|
|
487
|
+
}
|
|
487
488
|
} : (state) => attr(el, name, evaluate(state));
|
|
488
489
|
};
|
|
489
490
|
var attr = (el, name, v2) => {
|
|
@@ -501,16 +502,6 @@ directives[""] = (el, expr) => {
|
|
|
501
502
|
attr(el, dashcase(key), value[key]);
|
|
502
503
|
};
|
|
503
504
|
};
|
|
504
|
-
var _each = Symbol(":each");
|
|
505
|
-
var _ref = Symbol(":ref");
|
|
506
|
-
directives["ref"] = (el, expr, state) => {
|
|
507
|
-
if (el.hasAttribute(":each")) {
|
|
508
|
-
el[_ref] = expr;
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
;
|
|
512
|
-
state[expr] = el;
|
|
513
|
-
};
|
|
514
505
|
directives["with"] = (el, expr, rootState) => {
|
|
515
506
|
let evaluate = parseExpr(el, expr, "with");
|
|
516
507
|
sprae(el, signalStruct(evaluate(rootState), rootState));
|
|
@@ -541,6 +532,24 @@ directives["if"] = (el, expr) => {
|
|
|
541
532
|
}
|
|
542
533
|
};
|
|
543
534
|
};
|
|
535
|
+
var _each = Symbol(":each");
|
|
536
|
+
var _ref = Symbol(":ref");
|
|
537
|
+
var _key = Symbol(":key");
|
|
538
|
+
directives["ref"] = (el, expr, state) => {
|
|
539
|
+
if (el.hasAttribute(":each")) {
|
|
540
|
+
el[_ref] = expr;
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
;
|
|
544
|
+
state[expr] = el;
|
|
545
|
+
};
|
|
546
|
+
directives["key"] = (el, expr, state) => {
|
|
547
|
+
if (el.hasAttribute(":each")) {
|
|
548
|
+
el[_key] = expr;
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
;
|
|
552
|
+
};
|
|
544
553
|
directives["each"] = (tpl, expr) => {
|
|
545
554
|
let each = parseForExpression(expr);
|
|
546
555
|
if (!each)
|
|
@@ -548,6 +557,9 @@ directives["each"] = (tpl, expr) => {
|
|
|
548
557
|
const holder = tpl[_each] = document.createTextNode("");
|
|
549
558
|
tpl.replaceWith(holder);
|
|
550
559
|
const evaluate = parseExpr(tpl, each.items, ":each");
|
|
560
|
+
const keyExpr = tpl[_key] || tpl.getAttribute(":key");
|
|
561
|
+
const itemKey = keyExpr ? parseExpr(null, keyExpr) : null;
|
|
562
|
+
tpl.removeAttribute(":key");
|
|
551
563
|
const scopes = /* @__PURE__ */ new WeakMap();
|
|
552
564
|
const itemEls = /* @__PURE__ */ new WeakMap();
|
|
553
565
|
let curEls = [];
|
|
@@ -565,23 +577,25 @@ directives["each"] = (tpl, expr) => {
|
|
|
565
577
|
exprError(Error("Bad list value"), tpl, expr, ":each", list);
|
|
566
578
|
let newEls = [], elScopes = [];
|
|
567
579
|
for (let [idx, item] of list) {
|
|
568
|
-
let
|
|
569
|
-
|
|
570
|
-
|
|
580
|
+
let el, scope, key = itemKey?.({ [each.item]: item, [each.index || ""]: idx });
|
|
581
|
+
if (isPrimitive(key))
|
|
582
|
+
key = primitive_pool_default(key);
|
|
583
|
+
if (key == null)
|
|
571
584
|
el = tpl.cloneNode(true);
|
|
572
|
-
|
|
573
|
-
|
|
585
|
+
else
|
|
586
|
+
(el = itemEls.get(key)) || itemEls.set(key, el = tpl.cloneNode(true));
|
|
574
587
|
newEls.push(el);
|
|
575
|
-
if (!scopes.
|
|
576
|
-
|
|
588
|
+
if (key == null || !(scope = scopes.get(key))) {
|
|
589
|
+
scope = Object.create(state);
|
|
577
590
|
scope[each.item] = item;
|
|
578
591
|
if (each.index)
|
|
579
592
|
scope[each.index] = idx;
|
|
580
593
|
if (tpl[_ref])
|
|
581
594
|
scope[tpl[_ref]] = el;
|
|
582
|
-
|
|
595
|
+
if (key != null)
|
|
596
|
+
scopes.set(key, scope);
|
|
583
597
|
}
|
|
584
|
-
elScopes.push(
|
|
598
|
+
elScopes.push(scope);
|
|
585
599
|
}
|
|
586
600
|
swap_inflate_default(holder.parentNode, curEls, newEls, holder);
|
|
587
601
|
curEls = newEls;
|
|
@@ -654,18 +668,19 @@ directives["value"] = (el, expr) => {
|
|
|
654
668
|
} : (value) => el.value = value;
|
|
655
669
|
return (state) => update(evaluate(state));
|
|
656
670
|
};
|
|
657
|
-
var _stop = Symbol("stop");
|
|
658
671
|
directives["on"] = (el, expr) => {
|
|
659
672
|
let evaluate = parseExpr(el, expr, ":on");
|
|
660
|
-
let listeners = {};
|
|
661
673
|
return (state) => {
|
|
662
|
-
|
|
663
|
-
removeListener(el, evt, listeners[evt]);
|
|
664
|
-
listeners = evaluate(state);
|
|
674
|
+
let listeners = evaluate(state);
|
|
665
675
|
for (let evt in listeners)
|
|
666
676
|
addListener(el, evt, listeners[evt]);
|
|
677
|
+
return () => {
|
|
678
|
+
for (let evt in listeners)
|
|
679
|
+
removeListener(el, evt, listeners[evt]);
|
|
680
|
+
};
|
|
667
681
|
};
|
|
668
682
|
};
|
|
683
|
+
var _stop = Symbol("stop");
|
|
669
684
|
var addListener = (el, evt, startFn) => {
|
|
670
685
|
if (evt.indexOf("..") < 0)
|
|
671
686
|
el.addEventListener(evt, startFn);
|
|
@@ -743,6 +758,9 @@ ${dir}=${expression ? `"${expression}"
|
|
|
743
758
|
function dashcase(str) {
|
|
744
759
|
return str.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g, (match) => "-" + match.toLowerCase());
|
|
745
760
|
}
|
|
761
|
+
function isPrimitive(obj) {
|
|
762
|
+
return typeof obj === "string" || typeof obj === "boolean" || typeof obj === "number";
|
|
763
|
+
}
|
|
746
764
|
|
|
747
765
|
// src/core.js
|
|
748
766
|
var memo = /* @__PURE__ */ new WeakMap();
|
|
@@ -781,8 +799,14 @@ function sprae(container, values) {
|
|
|
781
799
|
}
|
|
782
800
|
};
|
|
783
801
|
init(container);
|
|
784
|
-
for (let update of updates)
|
|
785
|
-
|
|
802
|
+
for (let update of updates) {
|
|
803
|
+
let teardown;
|
|
804
|
+
b(() => {
|
|
805
|
+
if (typeof teardown === "function")
|
|
806
|
+
teardown();
|
|
807
|
+
teardown = update(state);
|
|
808
|
+
});
|
|
809
|
+
}
|
|
786
810
|
Object.seal(state);
|
|
787
811
|
memo.set(container, state);
|
|
788
812
|
return state;
|
package/sprae.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function t(){throw new Error("Cycle detected")}function e(){if(n>1)n--;else{for(var t,e=!1;void 0!==r;){var i=r;for(r=void 0,o++;void 0!==i;){var s=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&f(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=s}}if(o=0,n--,e)throw t}}var i=void 0,r=void 0,n=0,o=0,s=0;function l(t){if(void 0!==i){var e=t.n;if(void 0===e||e.t!==i)return i.s=e={i:0,S:t,p:void 0,n:i.s,t:i,e:void 0,x:void 0,r:e},t.n=e,32&i.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=i.s,i.s.p=e,i.s=e),e}}function a(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function f(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function u(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function h(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function c(t){a.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function v(t){var r=t.u;if(t.u=void 0,"function"==typeof r){n++;var o=i;i=void 0;try{r()}catch(e){throw t.f&=-2,t.f|=8,p(t),e}finally{i=o,e()}}}function p(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,v(t)}function d(t){if(i!==this)throw new Error("Out-of-order effect");h(this),i=t,this.f&=-2,8&this.f&&p(this),e()}function y(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function b(t){var e=new y(t);return e.c(),e.d.bind(e)}a.prototype.h=function(){return!0},a.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},a.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},a.prototype.subscribe=function(t){var e=this;return b((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},a.prototype.valueOf=function(){return this.value},a.prototype.toString=function(){return this.value+""},a.prototype.peek=function(){return this.v},Object.defineProperty(a.prototype,"value",{get:function(){var t=l(this);return void 0!==t&&(t.i=this.i),this.v},set:function(i){if(i!==this.v){o>100&&t(),this.v=i,this.i++,s++,n++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{e()}}}}),(c.prototype=new a).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===s)return!0;if(this.g=s,this.f|=1,this.i>0&&!f(this))return this.f&=-2,!0;var t=i;try{u(this),i=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return i=t,h(this),this.f&=-2,!0},c.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}a.prototype.S.call(this,t)},c.prototype.U=function(t){if(a.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},c.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},c.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(c.prototype,"value",{get:function(){1&this.f&&t();var e=l(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),y.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},y.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,v(this),u(this),n++;var e=i;return i=this,d.bind(this,e)},y.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},y.prototype.d=function(){this.f|=8,1&this.f||p(this)},Symbol.observable||=Symbol("observable");var m=new FinalizationRegistry((t=>t.call?.())),g=(t,e,i,r,n,o)=>{return t&&(s=(t[Symbol.observable]?.()||t).subscribe?.(e,i,r),o=s&&(()=>s.unsubscribe?.())||t.set&&t.call?.(n,e)||(t.then?.((t=>(!n&&e(t),r?.())),i)||(async o=>{try{for await(o of t){if(n)return;e(o)}r?.()}catch(t){i?.(t)}})())&&(t=>n=1),m.register(t,o),o);var s},S=t=>t&&t[x],x=Symbol("signal-struct");function w(t,e){if(S(t)&&!e)return t;if(A(t)){const n=Object.create(e||Object.getPrototypeOf(t)),o={},s=Object.getOwnPropertyDescriptors(t);for(let t in s){let e=s[t];if(e.get){let i=o[t]=new c(e.get.bind(n));Object.defineProperty(n,t,{get:()=>i.value,set:e.set?.bind(n),configurable:!1,enumerable:!0})}else{let s=e.value,l=(r=s)&&!!(r[Symbol.observable]||r[Symbol.asyncIterator]||r.call&&r.set||r.subscribe||r.then),f=o[t]=(i=s)&&i.peek?s:new a(l?void 0:A(s)?Object.seal(w(s)):Array.isArray(s)?w(s):s);l&&g(s,(t=>f.value=t)),Object.defineProperty(n,t,{get:()=>f.value,set(t){if(A(t)){if(A(f.value))try{return void Object.assign(f.value,t)}catch(t){}f.value=Object.seal(w(t))}else Array.isArray(t)?f.value=w(t):f.value=t},enumerable:!0,configurable:!1})}}return Object.defineProperty(n,x,{configurable:!1,enumerable:!1,value:!0}),n}var i,r;return Array.isArray(t)&&!S(t[0])?t.map((t=>w(t))):t}function A(t){return t&&t.constructor===Object}w.isStruct=S;var O=(t,e,i,r=null)=>{let n,o,s,l=0,a=i.length,f=e.length,{remove:u,same:h,insert:c,replace:v}=O;for(;l<a&&l<f&&h(e[l],i[l]);)l++;for(;l<a&&l<f&&h(i[a-1],e[f-1]);)r=i[(--f,--a)];if(l==f)for(;l<a;)c(r,i[l++],t);else{for(n=e[l];l<a;)s=i[l++],o=n?n.nextSibling:r,h(n,s)?n=o:l<a&&h(i[l],o)?(v(n,s,t),n=o):c(n,s,t);for(;!h(n,r);)o=n.nextSibling,u(n,t),n=o}return i};O.same=(t,e)=>t==e,O.replace=(t,e,i)=>i.replaceChild(e,t),O.insert=(t,e,i)=>i.insertBefore(e,t),O.remove=(t,e)=>e.removeChild(t);var j=O,N={},E={},W={},k={},$=(t,e,i,r)=>{let n,o=r.startsWith("on")&&r.slice(2),s=_(t,e,":"+r);if(s)return o?e=>{n&&T(t,o,n),n=s(e),n&&L(t,o,n)}:e=>P(t,r,s(e))},P=(t,e,i)=>{null==i||!1===i?t.removeAttribute(e):t.setAttribute(e,!0===i?"":"number"==typeof i||"string"==typeof i?i:"")};k[""]=(t,e)=>{let i=_(t,e,":");if(i)return e=>{let r=i(e);for(let e in r)P(t,R(e),r[e])}};var C=Symbol(":each"),U=Symbol(":ref");k.ref=(t,e,i)=>{t.hasAttribute(":each")?t[U]=e:i[e]=t},k.with=(t,e,i)=>{I(t,w(_(t,e,"with")(i),i))},k.if=(t,e)=>{let i=document.createTextNode(""),r=[_(t,e,":if")],n=[t],o=t;for(;(o=t.nextElementSibling)&&o.hasAttribute(":else");)o.removeAttribute(":else"),(e=o.getAttribute(":if"))?(o.removeAttribute(":if"),o.remove(),n.push(o),r.push(_(t,e,":else :if"))):(o.remove(),n.push(o),r.push((()=>1)));return t.replaceWith(o=i),t=>{let e=r.findIndex((e=>e(t)));n[e]!=o&&((o[C]||o).replaceWith(o=n[e]||i),I(o,t))}},k.each=(t,e)=>{let i=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r={};r.items=i[2].trim();let n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?(r.item=n.replace(e,"").trim(),r.index=o[1].trim()):r.item=n,r}(e);if(!i)return M(new Error,t,e);const r=t[C]=document.createTextNode("");t.replaceWith(r);const n=_(t,i.items,":each"),o=new WeakMap,s=new WeakMap;let l=[];return a=>{let f=n(a);f?"number"==typeof f?f=Array.from({length:f},((t,e)=>[e,e+1])):Array.isArray(f)?f=f.map(((t,e)=>[e+1,t])):"object"==typeof f?f=Object.entries(f):M(Error("Bad list value"),t,e,":each"):f=[];let u=[],h=[];for(let[e,r]of f){let n=null===(c=r)?E:void 0===c?W:"number"==typeof c||c instanceof Number?N[c]||(N[c]=new Number(c)):"string"==typeof c||c instanceof String?N[c]||(N[c]=new String(c)):"boolean"==typeof c||c instanceof Boolean?N[c]||(N[c]=new Boolean(c)):c,l=s.get(n);if(l||(l=t.cloneNode(!0),s.set(n,l)),u.push(l),!o.has(n)){let s=Object.create(a);s[i.item]=r,i.index&&(s[i.index]=e),t[U]&&(s[t[U]]=l),o.set(n,s)}h.push(o.get(n))}var c;j(r.parentNode,l,u,r),l=u;for(let t=0;t<u.length;t++)I(u[t],h[t])}},k.id=(t,e)=>{let i=_(t,e,":id");return e=>{return r=i(e),t.id=r||0===r?r:"";var r}},k.class=(t,e)=>{let i=_(t,e,":class"),r=t.className;return e=>{let n=i(e);t.className=r+typeof n=="string"?n:(Array.isArray(n)?n:Object.entries(n).map((([t,e])=>e?t:""))).filter(Boolean).join(" ")}},k.style=(t,e)=>{let i=_(t,e,":style"),r=t.getAttribute("style")||"";return r.endsWith(";")||(r+="; "),e=>{let n=i(e);if("string"==typeof n)t.setAttribute("style",r+n);else for(let e in n)t.style[e]=n[e]}},k.text=(t,e)=>{let i=_(t,e,":text");return e=>{let r=i(e);t.textContent=null==r?"":r}},k.value=(t,e)=>{let i,r,n=_(t,e,":value"),o="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"TEXTAREA"===t.tagName||"text"===t.type||""===t.type?e=>(i=t.selectionStart,r=t.selectionEnd,t.setAttribute("value",t.value=null==e?"":e),i&&t.setSelectionRange(i,r)):"checkbox"===t.type?e=>(t.value=e?"on":"",P(t,"checked",e)):"select-one"===t.type?e=>{for(let e in t.options)e.removeAttribute("selected");t.value=e,t.selectedOptions[0]?.setAttribute("selected","")}:e=>t.value=e;return t=>o(n(t))};var B=Symbol("stop");k.on=(t,e)=>{let i=_(t,e,":on"),r={};return e=>{for(let e in r)T(t,e,r[e]);r=i(e);for(let e in r)L(t,e,r[e])}};var L=(t,e,i)=>{if(e.indexOf("..")<0)t.addEventListener(e,i);else{const r=e.split("..").map((t=>t.startsWith("on")?t.slice(2):t)),n=(e,o=0)=>{let s=l=>{t.removeEventListener(r[o],s),"function"!=typeof(e=e.call(t,l))&&(e=()=>{}),++o<r.length?n(e,o):i[B]||n(i)};t.addEventListener(r[o],s)};n(i)}},T=(t,e,i)=>{e.indexOf("..")>=0&&(i[B]=!0),t.removeEventListener(e,i)};k.data=(t,e)=>{let i=_(t,e,":data");return e=>{let r=i(e);for(let e in r)t.dataset[e]=r[e]}},k.aria=(t,e)=>{let i=_(t,e,":aria");return e=>(e=>{for(let i in e)P(t,"aria-"+R(i),null==e[i]?null:e[i]+"")})(i(e))};var D={};function _(t,e,i){let r=D[e];if(!r){let n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=D[e]=new Function("__scope",`with (__scope) { return ${n} };`)}catch(r){return M(r,t,e,i)}}return n=>{let o;try{o=r.call(t,n)}catch(r){return M(r,t,e,i)}return o}}function M(t,e,i,r){Object.assign(t,{element:e,expression:i}),console.warn(`∴ ${t.message}\n\n${r}=${i?`"${i}"\n\n`:""}`,e),setTimeout((()=>{throw t}),0)}function R(t){return t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(t=>"-"+t.toLowerCase()))}var F=new WeakMap;function I(t,e){if(!t.children)return;if(F.has(t))return F.get(t);const i=w(e||{}),r=[],n=(t,e=t.parentNode)=>{if(t.attributes)for(let n=0;n<t.attributes.length;){let o=t.attributes[n];if(":"!==o.name[0]){n++;continue}t.removeAttribute(o.name);let s=o.value;if(!s)continue;let l=o.name.slice(1).split(":");for(let n of l){let o=k[n]||$;if(r.push(o(t,s,i,n)||(()=>{})),F.has(t)||t.parentNode!==e)return!1}}for(let e,i=0;e=t.children[i];i++)!1===n(e,t)&&i--};n(t);for(let t of r)b((()=>t(i)));return Object.seal(i),F.set(t,i),i}var z=I;export{z as default};
|
|
1
|
+
function t(){throw new Error("Cycle detected")}function e(){if(n>1)n--;else{for(var t,e=!1;void 0!==r;){var i=r;for(r=void 0,o++;void 0!==i;){var s=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&f(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=s}}if(o=0,n--,e)throw t}}var i=void 0,r=void 0,n=0,o=0,s=0;function l(t){if(void 0!==i){var e=t.n;if(void 0===e||e.t!==i)return i.s=e={i:0,S:t,p:void 0,n:i.s,t:i,e:void 0,x:void 0,r:e},t.n=e,32&i.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=i.s,i.s.p=e,i.s=e),e}}function a(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function f(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function u(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function h(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function c(t){a.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function v(t){var r=t.u;if(t.u=void 0,"function"==typeof r){n++;var o=i;i=void 0;try{r()}catch(e){throw t.f&=-2,t.f|=8,p(t),e}finally{i=o,e()}}}function p(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,v(t)}function d(t){if(i!==this)throw new Error("Out-of-order effect");h(this),i=t,this.f&=-2,8&this.f&&p(this),e()}function y(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function b(t){var e=new y(t);return e.c(),e.d.bind(e)}a.prototype.h=function(){return!0},a.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},a.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},a.prototype.subscribe=function(t){var e=this;return b((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},a.prototype.valueOf=function(){return this.value},a.prototype.toString=function(){return this.value+""},a.prototype.peek=function(){return this.v},Object.defineProperty(a.prototype,"value",{get:function(){var t=l(this);return void 0!==t&&(t.i=this.i),this.v},set:function(i){if(i!==this.v){o>100&&t(),this.v=i,this.i++,s++,n++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{e()}}}}),(c.prototype=new a).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===s)return!0;if(this.g=s,this.f|=1,this.i>0&&!f(this))return this.f&=-2,!0;var t=i;try{u(this),i=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return i=t,h(this),this.f&=-2,!0},c.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}a.prototype.S.call(this,t)},c.prototype.U=function(t){if(a.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},c.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},c.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(c.prototype,"value",{get:function(){1&this.f&&t();var e=l(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),y.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},y.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,v(this),u(this),n++;var e=i;return i=this,d.bind(this,e)},y.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},y.prototype.d=function(){this.f|=8,1&this.f||p(this)},Symbol.observable||=Symbol("observable");var m=new FinalizationRegistry((t=>t.call?.())),g=(t,e,i,r,n,o)=>{return t&&(s=(t[Symbol.observable]?.()||t).subscribe?.(e,i,r),o=s&&(()=>s.unsubscribe?.())||t.set&&t.call?.(n,e)||(t.then?.((t=>(!n&&e(t),r?.())),i)||(async o=>{try{for await(o of t){if(n)return;e(o)}r?.()}catch(t){i?.(t)}})())&&(t=>n=1),m.register(t,o),o);var s},S=t=>t&&t[x],x=Symbol("signal-struct");function A(t,e){if(S(t)&&!e)return t;if(w(t)){const n=Object.create(e||Object.getPrototypeOf(t)),o={},s=Object.getOwnPropertyDescriptors(t);for(let t in s){let e=s[t];if(e.get){let i=o[t]=new c(e.get.bind(n));Object.defineProperty(n,t,{get:()=>i.value,set:e.set?.bind(n),configurable:!1,enumerable:!0})}else{let s=e.value,l=(r=s)&&!!(r[Symbol.observable]||r[Symbol.asyncIterator]||r.call&&r.set||r.subscribe||r.then),f=o[t]=(i=s)&&i.peek?s:new a(l?void 0:w(s)?Object.seal(A(s)):Array.isArray(s)?A(s):s);l&&g(s,(t=>f.value=t)),Object.defineProperty(n,t,{get:()=>f.value,set(t){if(w(t)){if(w(f.value))try{return void Object.assign(f.value,t)}catch(t){}f.value=Object.seal(A(t))}else Array.isArray(t)?f.value=A(t):f.value=t},enumerable:!0,configurable:!1})}}return Object.defineProperty(n,x,{configurable:!1,enumerable:!1,value:!0}),n}var i,r;return Array.isArray(t)&&!S(t[0])?t.map((t=>A(t))):t}function w(t){return t&&t.constructor===Object}A.isStruct=S;var O=(t,e,i,r=null)=>{let n,o,s,l=0,a=i.length,f=e.length,{remove:u,same:h,insert:c,replace:v}=O;for(;l<a&&l<f&&h(e[l],i[l]);)l++;for(;l<a&&l<f&&h(i[a-1],e[f-1]);)r=i[(--f,--a)];if(l==f)for(;l<a;)c(r,i[l++],t);else{for(n=e[l];l<a;)s=i[l++],o=n?n.nextSibling:r,h(n,s)?n=o:l<a&&h(i[l],o)?(v(n,s,t),n=o):c(n,s,t);for(;!h(n,r);)o=n.nextSibling,u(n,t),n=o}return i};O.same=(t,e)=>t==e,O.replace=(t,e,i)=>i.replaceChild(e,t),O.insert=(t,e,i)=>i.insertBefore(e,t),O.remove=(t,e)=>e.removeChild(t);var j=O,N={},E={},k={},W=t=>null===t?E:void 0===t?k:"number"==typeof t||t instanceof Number?N[t]||(N[t]=new Number(t)):"string"==typeof t||t instanceof String?N[t]||(N[t]=new String(t)):"boolean"==typeof t||t instanceof Boolean?N[t]||(N[t]=new Boolean(t)):t,$={},P=(t,e,i,r)=>{let n=r.startsWith("on")&&r.slice(2),o=R(t,e,":"+r);if(o)return n?e=>{let i=o(e);if(i)return D(t,n,i),()=>_(t,n,i)}:e=>C(t,r,o(e))},C=(t,e,i)=>{null==i||!1===i?t.removeAttribute(e):t.setAttribute(e,!0===i?"":"number"==typeof i||"string"==typeof i?i:"")};$[""]=(t,e)=>{let i=R(t,e,":");if(i)return e=>{let r=i(e);for(let e in r)C(t,I(e),r[e])}},$.with=(t,e,i)=>{X(t,A(R(t,e,"with")(i),i))},$.if=(t,e)=>{let i=document.createTextNode(""),r=[R(t,e,":if")],n=[t],o=t;for(;(o=t.nextElementSibling)&&o.hasAttribute(":else");)o.removeAttribute(":else"),(e=o.getAttribute(":if"))?(o.removeAttribute(":if"),o.remove(),n.push(o),r.push(R(t,e,":else :if"))):(o.remove(),n.push(o),r.push((()=>1)));return t.replaceWith(o=i),t=>{let e=r.findIndex((e=>e(t)));n[e]!=o&&((o[U]||o).replaceWith(o=n[e]||i),X(o,t))}};var U=Symbol(":each"),B=Symbol(":ref"),L=Symbol(":key");$.ref=(t,e,i)=>{t.hasAttribute(":each")?t[B]=e:i[e]=t},$.key=(t,e,i)=>{t.hasAttribute(":each")&&(t[L]=e)},$.each=(t,e)=>{let i=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r={};r.items=i[2].trim();let n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?(r.item=n.replace(e,"").trim(),r.index=o[1].trim()):r.item=n,r}(e);if(!i)return F(new Error,t,e);const r=t[U]=document.createTextNode("");t.replaceWith(r);const n=R(t,i.items,":each"),o=t[L]||t.getAttribute(":key"),s=o?R(null,o):null;t.removeAttribute(":key");const l=new WeakMap,a=new WeakMap;let f=[];return o=>{let u=n(o);u?"number"==typeof u?u=Array.from({length:u},((t,e)=>[e,e+1])):Array.isArray(u)?u=u.map(((t,e)=>[e+1,t])):"object"==typeof u?u=Object.entries(u):F(Error("Bad list value"),t,e,":each"):u=[];let h=[],c=[];for(let[e,r]of u){let n,f,u=s?.({[i.item]:r,[i.index||""]:e});("string"==typeof(v=u)||"boolean"==typeof v||"number"==typeof v)&&(u=W(u)),null==u?n=t.cloneNode(!0):(n=a.get(u))||a.set(u,n=t.cloneNode(!0)),h.push(n),null!=u&&(f=l.get(u))||(f=Object.create(o),f[i.item]=r,i.index&&(f[i.index]=e),t[B]&&(f[t[B]]=n),null!=u&&l.set(u,f)),c.push(f)}var v;j(r.parentNode,f,h,r),f=h;for(let t=0;t<h.length;t++)X(h[t],c[t])}},$.id=(t,e)=>{let i=R(t,e,":id");return e=>{return r=i(e),t.id=r||0===r?r:"";var r}},$.class=(t,e)=>{let i=R(t,e,":class"),r=t.className;return e=>{let n=i(e);t.className=r+typeof n=="string"?n:(Array.isArray(n)?n:Object.entries(n).map((([t,e])=>e?t:""))).filter(Boolean).join(" ")}},$.style=(t,e)=>{let i=R(t,e,":style"),r=t.getAttribute("style")||"";return r.endsWith(";")||(r+="; "),e=>{let n=i(e);if("string"==typeof n)t.setAttribute("style",r+n);else for(let e in n)t.style[e]=n[e]}},$.text=(t,e)=>{let i=R(t,e,":text");return e=>{let r=i(e);t.textContent=null==r?"":r}},$.value=(t,e)=>{let i,r,n=R(t,e,":value"),o="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"TEXTAREA"===t.tagName||"text"===t.type||""===t.type?e=>(i=t.selectionStart,r=t.selectionEnd,t.setAttribute("value",t.value=null==e?"":e),i&&t.setSelectionRange(i,r)):"checkbox"===t.type?e=>(t.value=e?"on":"",C(t,"checked",e)):"select-one"===t.type?e=>{for(let e in t.options)e.removeAttribute("selected");t.value=e,t.selectedOptions[0]?.setAttribute("selected","")}:e=>t.value=e;return t=>o(n(t))},$.on=(t,e)=>{let i=R(t,e,":on");return e=>{let r=i(e);for(let e in r)D(t,e,r[e]);return()=>{for(let e in r)_(t,e,r[e])}}};var T=Symbol("stop"),D=(t,e,i)=>{if(e.indexOf("..")<0)t.addEventListener(e,i);else{const r=e.split("..").map((t=>t.startsWith("on")?t.slice(2):t)),n=(e,o=0)=>{let s=l=>{t.removeEventListener(r[o],s),"function"!=typeof(e=e.call(t,l))&&(e=()=>{}),++o<r.length?n(e,o):i[T]||n(i)};t.addEventListener(r[o],s)};n(i)}},_=(t,e,i)=>{e.indexOf("..")>=0&&(i[T]=!0),t.removeEventListener(e,i)};$.data=(t,e)=>{let i=R(t,e,":data");return e=>{let r=i(e);for(let e in r)t.dataset[e]=r[e]}},$.aria=(t,e)=>{let i=R(t,e,":aria");return e=>(e=>{for(let i in e)C(t,"aria-"+I(i),null==e[i]?null:e[i]+"")})(i(e))};var M={};function R(t,e,i){let r=M[e];if(!r){let n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=M[e]=new Function("__scope",`with (__scope) { return ${n} };`)}catch(r){return F(r,t,e,i)}}return n=>{let o;try{o=r.call(t,n)}catch(r){return F(r,t,e,i)}return o}}function F(t,e,i,r){Object.assign(t,{element:e,expression:i}),console.warn(`∴ ${t.message}\n\n${r}=${i?`"${i}"\n\n`:""}`,e),setTimeout((()=>{throw t}),0)}function I(t){return t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(t=>"-"+t.toLowerCase()))}var z=new WeakMap;function X(t,e){if(!t.children)return;if(z.has(t))return z.get(t);const i=A(e||{}),r=[],n=(t,e=t.parentNode)=>{if(t.attributes)for(let n=0;n<t.attributes.length;){let o=t.attributes[n];if(":"!==o.name[0]){n++;continue}t.removeAttribute(o.name);let s=o.value;if(!s)continue;let l=o.name.slice(1).split(":");for(let n of l){let o=$[n]||P;if(r.push(o(t,s,i,n)||(()=>{})),z.has(t)||t.parentNode!==e)return!1}}for(let e,i=0;e=t.children[i];i++)!1===n(e,t)&&i--};n(t);for(let t of r){let e;b((()=>{"function"==typeof e&&e(),e=t(i)}))}return Object.seal(i),z.set(t,i),i}var Z=X;export{Z as default};
|
package/src/core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import signalStruct from 'signal-struct';
|
|
2
2
|
import defaultDirective, { directives } from './directives.js';
|
|
3
|
-
import { effect
|
|
3
|
+
import { effect } from '@preact/signals-core'
|
|
4
4
|
|
|
5
5
|
// sprae element: apply directives
|
|
6
6
|
const memo = new WeakMap
|
|
@@ -42,7 +42,13 @@ export default function sprae(container, values) {
|
|
|
42
42
|
|
|
43
43
|
// call updates: subscribes directives to state;
|
|
44
44
|
// state is created after inits because directives can extend init values (expose refs etc)
|
|
45
|
-
for (let update of updates)
|
|
45
|
+
for (let update of updates) {
|
|
46
|
+
let teardown
|
|
47
|
+
effect(() => {
|
|
48
|
+
if (typeof teardown === 'function') teardown()
|
|
49
|
+
teardown = update(state)
|
|
50
|
+
});
|
|
51
|
+
}
|
|
46
52
|
|
|
47
53
|
Object.seal(state);
|
|
48
54
|
memo.set(container, state);
|
package/src/directives.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// directives & parsing
|
|
2
2
|
import sprae from './core.js'
|
|
3
3
|
import swap from 'swapdom'
|
|
4
|
-
import p from 'primitive-pool'
|
|
5
4
|
import signalStruct from 'signal-struct'
|
|
5
|
+
import p from 'primitive-pool'
|
|
6
6
|
|
|
7
7
|
// reserved directives - order matters!
|
|
8
8
|
export const directives = {}
|
|
@@ -11,11 +11,12 @@ export const directives = {}
|
|
|
11
11
|
export default (el, expr, values, name) => {
|
|
12
12
|
let evt = name.startsWith('on') && name.slice(2)
|
|
13
13
|
let evaluate = parseExpr(el, expr, ':'+name)
|
|
14
|
-
let value
|
|
15
14
|
if (evaluate) return evt ? state => {
|
|
16
|
-
value
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
let value = evaluate(state)
|
|
16
|
+
if (value) {
|
|
17
|
+
addListener(el, evt, value)
|
|
18
|
+
return () => removeListener(el, evt, value)
|
|
19
|
+
}
|
|
19
20
|
}
|
|
20
21
|
: state => attr(el, name, evaluate(state))
|
|
21
22
|
}
|
|
@@ -34,17 +35,6 @@ directives[''] = (el, expr) => {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
const _each = Symbol(':each'), _ref = Symbol(':ref')
|
|
38
|
-
|
|
39
|
-
directives['ref'] = (el, expr, state) => {
|
|
40
|
-
// make sure :ref is initialized after :each (return to avoid initializing as signal)
|
|
41
|
-
if (el.hasAttribute(':each')) {el[_ref] = expr; return};
|
|
42
|
-
|
|
43
|
-
// FIXME: wait for complex ref use-case
|
|
44
|
-
// parseExpr(el, `__scope[${expr}]=this`, ':ref')(values)
|
|
45
|
-
state[expr] = el;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
38
|
directives['with'] = (el, expr, rootState) => {
|
|
49
39
|
let evaluate = parseExpr(el, expr, 'with')
|
|
50
40
|
sprae(el, signalStruct(evaluate(rootState), rootState));
|
|
@@ -81,6 +71,22 @@ directives['if'] = (el, expr) => {
|
|
|
81
71
|
}
|
|
82
72
|
}
|
|
83
73
|
|
|
74
|
+
const _each = Symbol(':each'), _ref = Symbol(':ref'), _key = Symbol(':key')
|
|
75
|
+
|
|
76
|
+
directives['ref'] = (el, expr, state) => {
|
|
77
|
+
// make sure :ref is initialized after :each (return to avoid initializing as signal)
|
|
78
|
+
if (el.hasAttribute(':each')) {el[_ref] = expr; return};
|
|
79
|
+
|
|
80
|
+
// FIXME: wait for complex ref use-case
|
|
81
|
+
// parseExpr(el, `__scope[${expr}]=this`, ':ref')(values)
|
|
82
|
+
state[expr] = el;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
directives['key'] = (el, expr, state) => {
|
|
86
|
+
// make sure :ref is initialized after :each (return to avoid initializing as signal)
|
|
87
|
+
if (el.hasAttribute(':each')) {el[_key] = expr; return};
|
|
88
|
+
}
|
|
89
|
+
|
|
84
90
|
directives['each'] = (tpl, expr) => {
|
|
85
91
|
let each = parseForExpression(expr);
|
|
86
92
|
if (!each) return exprError(new Error, tpl, expr);
|
|
@@ -92,15 +98,19 @@ directives['each'] = (tpl, expr) => {
|
|
|
92
98
|
|
|
93
99
|
const evaluate = parseExpr(tpl, each.items, ':each');
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
const keyExpr = tpl[_key] || tpl.getAttribute(':key');
|
|
102
|
+
const itemKey = keyExpr ? parseExpr(null, keyExpr) : null;
|
|
103
|
+
tpl.removeAttribute(':key')
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
const scopes = new WeakMap() // stores scope per data item
|
|
107
|
+
const itemEls = new WeakMap() // element per data item
|
|
99
108
|
let curEls = []
|
|
100
109
|
|
|
101
110
|
return (state) => {
|
|
102
111
|
// get items
|
|
103
112
|
let list = evaluate(state)
|
|
113
|
+
|
|
104
114
|
if (!list) list = []
|
|
105
115
|
else if (typeof list === 'number') list = Array.from({length: list}, (_, i)=>[i, i+1])
|
|
106
116
|
else if (Array.isArray(list)) list = list.map((item,i) => [i+1, item])
|
|
@@ -111,23 +121,25 @@ directives['each'] = (tpl, expr) => {
|
|
|
111
121
|
let newEls = [], elScopes = []
|
|
112
122
|
|
|
113
123
|
for (let [idx, item] of list) {
|
|
114
|
-
let
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
124
|
+
let el, scope, key = itemKey?.({[each.item]: item, [each.index || '']: idx})
|
|
125
|
+
if (isPrimitive(key)) key = p(key); // singletonize key
|
|
126
|
+
|
|
127
|
+
// we consider if data items are primitive, then nodes needn't be cached
|
|
128
|
+
// since likely they're very simple to create
|
|
129
|
+
if (key == null) el = tpl.cloneNode(true);
|
|
130
|
+
else (el = itemEls.get(key)) || itemEls.set(key, el = tpl.cloneNode(true));
|
|
131
|
+
|
|
120
132
|
newEls.push(el)
|
|
121
133
|
|
|
122
|
-
if (!scopes.
|
|
123
|
-
|
|
134
|
+
if (key == null || !(scope = scopes.get(key))) {
|
|
135
|
+
scope = Object.create(state)
|
|
124
136
|
scope[each.item] = item
|
|
125
137
|
if (each.index) scope[each.index] = idx;
|
|
126
138
|
// provide ref, if indicated
|
|
127
139
|
if (tpl[_ref]) scope[tpl[_ref]] = el
|
|
128
|
-
scopes.set(
|
|
140
|
+
if (key != null) scopes.set(key, scope)
|
|
129
141
|
}
|
|
130
|
-
elScopes.push(
|
|
142
|
+
elScopes.push(scope)
|
|
131
143
|
}
|
|
132
144
|
|
|
133
145
|
// swap is really fast & tiny
|
|
@@ -225,18 +237,19 @@ directives['value'] = (el, expr) => {
|
|
|
225
237
|
return (state) => update(evaluate(state))
|
|
226
238
|
}
|
|
227
239
|
|
|
228
|
-
const _stop = Symbol('stop')
|
|
229
240
|
directives['on'] = (el, expr) => {
|
|
230
241
|
let evaluate = parseExpr(el, expr, ':on')
|
|
231
|
-
let listeners = {}
|
|
232
242
|
|
|
233
243
|
return (state) => {
|
|
234
|
-
|
|
235
|
-
listeners = evaluate(state);
|
|
244
|
+
let listeners = evaluate(state);
|
|
236
245
|
for (let evt in listeners) addListener(el, evt, listeners[evt])
|
|
246
|
+
return () => {
|
|
247
|
+
for (let evt in listeners) removeListener(el, evt, listeners[evt])
|
|
248
|
+
}
|
|
237
249
|
}
|
|
238
250
|
}
|
|
239
251
|
|
|
252
|
+
const _stop = Symbol('stop')
|
|
240
253
|
const addListener = (el, evt, startFn) => {
|
|
241
254
|
if (evt.indexOf('..')<0) el.addEventListener(evt, startFn);
|
|
242
255
|
|
|
@@ -255,7 +268,6 @@ const addListener = (el, evt, startFn) => {
|
|
|
255
268
|
nextEvt(startFn)
|
|
256
269
|
}
|
|
257
270
|
}
|
|
258
|
-
|
|
259
271
|
const removeListener = (el, evt, fn) => {
|
|
260
272
|
if (evt.indexOf('..')>=0) fn[_stop] = true
|
|
261
273
|
el.removeEventListener(evt, fn);
|
|
@@ -309,7 +321,7 @@ function parseExpr(el, expression, dir) {
|
|
|
309
321
|
// guard runtime eval errors
|
|
310
322
|
return (state) => {
|
|
311
323
|
let result
|
|
312
|
-
try { result = evaluate.call(el, state) }
|
|
324
|
+
try { result = evaluate.call(el, state); }
|
|
313
325
|
catch (e) { return exprError(e, el, expression, dir) }
|
|
314
326
|
return result
|
|
315
327
|
}
|
|
@@ -324,3 +336,7 @@ export function exprError(error, element, expression, dir) {
|
|
|
324
336
|
function dashcase(str) {
|
|
325
337
|
return str.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g, (match) => '-' + match.toLowerCase());
|
|
326
338
|
};
|
|
339
|
+
|
|
340
|
+
function isPrimitive(obj) {
|
|
341
|
+
return typeof obj === 'string' || typeof obj === 'boolean' || typeof obj === 'number'
|
|
342
|
+
}
|
package/test/test.js
CHANGED
|
@@ -374,6 +374,39 @@ test('each: next items have own "this", not single one', async () => {
|
|
|
374
374
|
is(state.log, [1,'1',2,'2',3,'3'])
|
|
375
375
|
})
|
|
376
376
|
|
|
377
|
+
test('each: unkeyed', async () => {
|
|
378
|
+
let el = h`<div><x :each="x in xs" :text="x"></x></div>`
|
|
379
|
+
let state = sprae(el, {xs:[1,2,3]})
|
|
380
|
+
is(el.children.length, 3)
|
|
381
|
+
is(el.textContent, '123')
|
|
382
|
+
// let first = el.firstChild
|
|
383
|
+
state.xs = [1,3,2]
|
|
384
|
+
// is(el.firstChild, first)
|
|
385
|
+
is(el.textContent, '132')
|
|
386
|
+
state.xs = [3,3,3]
|
|
387
|
+
is(el.textContent, '333')
|
|
388
|
+
// is(el.firstChild, first)
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
test('each: keyed', async () => {
|
|
392
|
+
// keyed
|
|
393
|
+
let el = h`<div><x :each="x in xs" :text="x" :key="x"></x></div>`
|
|
394
|
+
let state = sprae(el, {xs:[1,2,3]})
|
|
395
|
+
is(el.children.length, 3)
|
|
396
|
+
is(el.textContent, '123')
|
|
397
|
+
let first = el.firstChild
|
|
398
|
+
state.xs = [1,3,2]
|
|
399
|
+
is(el.firstChild, first)
|
|
400
|
+
is(el.textContent, '132')
|
|
401
|
+
state.xs = [3,3,3]
|
|
402
|
+
is(el.textContent, '3')
|
|
403
|
+
// is(el.firstChild, first)
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
test.todo('each: unmounted elements remove listeners', async () => {
|
|
407
|
+
|
|
408
|
+
})
|
|
409
|
+
|
|
377
410
|
test('on: base', () => {
|
|
378
411
|
let el = h`<div :on="{click(e){log.push('click')},x}"></div>`
|
|
379
412
|
let log = signal([])
|
package/{plan.md → todo.md}
RENAMED
|
@@ -33,9 +33,10 @@
|
|
|
33
33
|
* [x] :text="" empty values shouldn't throw
|
|
34
34
|
* [x] implement :with
|
|
35
35
|
* [x] update :value without losing focus / position
|
|
36
|
+
* ~~[x] run tiredown if element got removed from condition or loop (free memory)~~ no need just make sure no refs to elements stored
|
|
37
|
+
* [ ] `sprae(el, newState)` can update element's state directly (as batch!?) -> must be tested against repeats in directives
|
|
36
38
|
* [ ] :if :ref, :if :with -> context setters must come first always
|
|
37
39
|
* [ ] frameworks benchmark
|
|
38
40
|
* [ ] examples
|
|
39
41
|
* [x] todomvc
|
|
40
|
-
* [
|
|
41
|
-
* [ ] `sprae(el, newState)` can update element's state directly (as batch!?) -> must be tested against repeats in directives
|
|
42
|
+
* [x] waveplay
|