sprae 2.4.0 → 2.5.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/package.json +2 -2
- package/r&d.md +3 -2
- package/readme.md +18 -0
- package/sprae.js +35 -34
- package/sprae.min.js +1 -1
- package/src/core.js +4 -5
- package/src/directives.js +19 -38
- package/test/test.js +11 -10
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sprae",
|
|
3
3
|
"description": "DOM microhydration.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.5.0",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"module": "src/index.js",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@preact/signals-core": "^1.2.2",
|
|
10
10
|
"primitive-pool": "^2.0.0",
|
|
11
|
-
"signal-struct": "^1.
|
|
11
|
+
"signal-struct": "^1.8.0",
|
|
12
12
|
"swapdom": "^1.1.1"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
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
|
-
## [ ] :with? ->
|
|
100
|
+
## [ ] :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
|
|
@@ -120,7 +120,8 @@
|
|
|
120
120
|
* that plays role of watch that doesn't require to be outside of local component state.
|
|
121
121
|
- `:with` allows local component state not cluttering global state. There's really no way to define local state that doesn't affect global state.
|
|
122
122
|
1.1 Slim `:with="{a,b,c}"` - just initializes vars
|
|
123
|
-
- Doesn't
|
|
123
|
+
- Doesn't give easy init syntax
|
|
124
|
+
+ Convevtional and not hard to implement
|
|
124
125
|
2. Use `:let="x, y=2"`?
|
|
125
126
|
+ Doesn't pollute scope but instead cleanly declares local variables
|
|
126
127
|
+ Indicates only local initializer, not subscription
|
package/readme.md
CHANGED
|
@@ -195,6 +195,23 @@ Set [aria-role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA)
|
|
|
195
195
|
-->
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
+
#### `:with="data"`
|
|
199
|
+
|
|
200
|
+
Define variables for a subtree fragment scope.
|
|
201
|
+
|
|
202
|
+
```html
|
|
203
|
+
<!-- Inline data -->
|
|
204
|
+
<x :with="{ foo: 'bar' }" :text="foo"></x>
|
|
205
|
+
|
|
206
|
+
<!-- External data -->
|
|
207
|
+
<y :with="data"></y>
|
|
208
|
+
|
|
209
|
+
<!-- Transparency -->
|
|
210
|
+
<x :with="{ foo: 'bar' }">
|
|
211
|
+
<y :with="{ baz: 'qux' }" :text="foo + baz"></y>
|
|
212
|
+
</x>
|
|
213
|
+
```
|
|
214
|
+
|
|
198
215
|
#### `:ref="id"`
|
|
199
216
|
|
|
200
217
|
Expose element to data scope with the `id`:
|
|
@@ -219,6 +236,7 @@ Expose element to data scope with the `id`:
|
|
|
219
236
|
</script>
|
|
220
237
|
```
|
|
221
238
|
|
|
239
|
+
|
|
222
240
|
<!--
|
|
223
241
|
|
|
224
242
|
### Reactivity
|
package/sprae.js
CHANGED
|
@@ -363,33 +363,37 @@ var sube_default = (target, next, error, complete, stop, unsub) => target && (un
|
|
|
363
363
|
var isSignal = (v2) => v2 && v2.peek;
|
|
364
364
|
var isStruct = (v2) => v2 && v2[_struct];
|
|
365
365
|
var _struct = Symbol("signal-struct");
|
|
366
|
-
|
|
367
|
-
|
|
366
|
+
signalStruct.isStruct = isStruct;
|
|
367
|
+
function signalStruct(values, proto) {
|
|
368
|
+
if (isStruct(values) && !proto)
|
|
368
369
|
return values;
|
|
369
370
|
let state, signals;
|
|
370
371
|
if (isObject(values)) {
|
|
371
|
-
state =
|
|
372
|
+
state = Object.create(proto || Object.getPrototypeOf(values)), signals = {};
|
|
372
373
|
let desc = Object.getOwnPropertyDescriptors(values);
|
|
373
|
-
|
|
374
|
-
|
|
374
|
+
if (isStruct(values))
|
|
375
|
+
for (let key in desc)
|
|
376
|
+
Object.defineProperty(state, key, desc[key]);
|
|
377
|
+
else
|
|
378
|
+
for (let key in desc)
|
|
379
|
+
signals[key] = defineSignal(state, key, desc[key].get ? w(desc[key].get.bind(state)) : desc[key].value);
|
|
375
380
|
Object.defineProperty(state, _struct, { configurable: false, enumerable: false, value: true });
|
|
376
|
-
Object.seal(state);
|
|
377
381
|
return state;
|
|
378
382
|
}
|
|
379
383
|
if (Array.isArray(values)) {
|
|
380
|
-
return values.map((v2) =>
|
|
384
|
+
return values.map((v2) => signalStruct(v2));
|
|
381
385
|
}
|
|
382
386
|
return values;
|
|
383
387
|
}
|
|
384
388
|
function defineSignal(state, key, value) {
|
|
385
|
-
let isObservable, s2 = isSignal(value) ? value : isObject(value) || Array.isArray(value) ? u(
|
|
389
|
+
let isObservable, s2 = isSignal(value) ? value : isObject(value) || Array.isArray(value) ? u(signalStruct(value)) : u((isObservable = observable(value)) ? void 0 : value);
|
|
386
390
|
if (isObservable)
|
|
387
391
|
sube_default(value, (v2) => s2.value = v2);
|
|
388
392
|
Object.defineProperty(state, key, {
|
|
389
393
|
get() {
|
|
390
394
|
return s2.value;
|
|
391
395
|
},
|
|
392
|
-
set: !isSignal(value) && isObject(value) ? (v2) => v2 ? Object.assign(s2.value, v2) : s2.value =
|
|
396
|
+
set: !isSignal(value) && isObject(value) ? (v2) => v2 ? Object.assign(s2.value, v2) : s2.value = signalStruct(v2) : (v2) => s2.value = signalStruct(v2),
|
|
393
397
|
enumerable: true,
|
|
394
398
|
configurable: false
|
|
395
399
|
});
|
|
@@ -467,7 +471,7 @@ var attr = (el, name, v2) => {
|
|
|
467
471
|
else
|
|
468
472
|
el.setAttribute(name, v2 === true ? "" : typeof v2 === "number" || typeof v2 === "string" ? v2 : "");
|
|
469
473
|
};
|
|
470
|
-
directives[""] = (el, expr
|
|
474
|
+
directives[""] = (el, expr) => {
|
|
471
475
|
let evaluate = parseExpr(el, expr, ":");
|
|
472
476
|
return (state) => {
|
|
473
477
|
let value = evaluate(state);
|
|
@@ -477,22 +481,19 @@ directives[""] = (el, expr, values) => {
|
|
|
477
481
|
};
|
|
478
482
|
var _each = Symbol(":each");
|
|
479
483
|
var _ref = Symbol(":ref");
|
|
480
|
-
directives["ref"] = (el, expr,
|
|
484
|
+
directives["ref"] = (el, expr, state) => {
|
|
481
485
|
if (el.hasAttribute(":each")) {
|
|
482
486
|
el[_ref] = expr;
|
|
483
487
|
return;
|
|
484
488
|
}
|
|
485
489
|
;
|
|
486
|
-
|
|
490
|
+
state[expr] = el;
|
|
487
491
|
};
|
|
488
492
|
directives["with"] = (el, expr, rootState) => {
|
|
489
493
|
let evaluate = parseExpr(el, expr, "with");
|
|
490
|
-
|
|
491
|
-
let withValues = evaluate(rootState);
|
|
492
|
-
let newState = Object.assign(Object.create(rootState), withValues);
|
|
493
|
-
sprae(el, newState);
|
|
494
|
+
sprae(el, signalStruct(evaluate(rootState), rootState));
|
|
494
495
|
};
|
|
495
|
-
directives["if"] = (el, expr
|
|
496
|
+
directives["if"] = (el, expr) => {
|
|
496
497
|
let holder = document.createTextNode(""), clauses = [parseExpr(el, expr, ":if")], els = [el], cur = el;
|
|
497
498
|
while (cur = el.nextElementSibling) {
|
|
498
499
|
if (cur.hasAttribute(":else")) {
|
|
@@ -518,7 +519,7 @@ directives["if"] = (el, expr, values) => {
|
|
|
518
519
|
}
|
|
519
520
|
};
|
|
520
521
|
};
|
|
521
|
-
directives["each"] = (tpl, expr
|
|
522
|
+
directives["each"] = (tpl, expr) => {
|
|
522
523
|
let each = parseForExpression(expr);
|
|
523
524
|
if (!each)
|
|
524
525
|
return exprError(new Error(), tpl, expr);
|
|
@@ -534,12 +535,12 @@ directives["each"] = (tpl, expr, values) => {
|
|
|
534
535
|
list = [];
|
|
535
536
|
else if (typeof list === "number")
|
|
536
537
|
list = Array.from({ length: list }, (_2, i2) => [i2, i2 + 1]);
|
|
537
|
-
else if (list.constructor === Object)
|
|
538
|
-
list = Object.entries(list);
|
|
539
538
|
else if (Array.isArray(list))
|
|
540
539
|
list = list.map((item, i2) => [i2 + 1, item]);
|
|
540
|
+
else if (typeof list === "object")
|
|
541
|
+
list = Object.entries(list);
|
|
541
542
|
else
|
|
542
|
-
exprError(Error("Bad list value"), tpl,
|
|
543
|
+
exprError(Error("Bad list value"), tpl, expr, ":each", list);
|
|
543
544
|
let newEls = [], elScopes = [];
|
|
544
545
|
for (let [idx, item] of list) {
|
|
545
546
|
let itemKey = primitive_pool_default(item);
|
|
@@ -586,12 +587,12 @@ function parseForExpression(expression) {
|
|
|
586
587
|
}
|
|
587
588
|
return res;
|
|
588
589
|
}
|
|
589
|
-
directives["id"] = (el, expr
|
|
590
|
+
directives["id"] = (el, expr) => {
|
|
590
591
|
let evaluate = parseExpr(el, expr, ":id");
|
|
591
592
|
const update = (v2) => el.id = v2 || v2 === 0 ? v2 : "";
|
|
592
593
|
return (state) => update(evaluate(state));
|
|
593
594
|
};
|
|
594
|
-
directives["class"] = (el, expr
|
|
595
|
+
directives["class"] = (el, expr) => {
|
|
595
596
|
let evaluate = parseExpr(el, expr, ":class");
|
|
596
597
|
let initClassName = el.className;
|
|
597
598
|
return (state) => {
|
|
@@ -599,7 +600,7 @@ directives["class"] = (el, expr, values) => {
|
|
|
599
600
|
el.className = initClassName + typeof v2 === "string" ? v2 : (Array.isArray(v2) ? v2 : Object.entries(v2).map(([k, v3]) => v3 ? k : "")).filter(Boolean).join(" ");
|
|
600
601
|
};
|
|
601
602
|
};
|
|
602
|
-
directives["style"] = (el, expr
|
|
603
|
+
directives["style"] = (el, expr) => {
|
|
603
604
|
let evaluate = parseExpr(el, expr, ":style");
|
|
604
605
|
let initStyle = el.getAttribute("style") || "";
|
|
605
606
|
if (!initStyle.endsWith(";"))
|
|
@@ -613,14 +614,14 @@ directives["style"] = (el, expr, values) => {
|
|
|
613
614
|
el.style[k] = v2[k];
|
|
614
615
|
};
|
|
615
616
|
};
|
|
616
|
-
directives["text"] = (el, expr
|
|
617
|
+
directives["text"] = (el, expr) => {
|
|
617
618
|
let evaluate = parseExpr(el, expr, ":text");
|
|
618
|
-
|
|
619
|
+
return (state) => {
|
|
620
|
+
let value = evaluate(state);
|
|
619
621
|
el.textContent = value == null ? "" : value;
|
|
620
622
|
};
|
|
621
|
-
return (state) => update(evaluate(state));
|
|
622
623
|
};
|
|
623
|
-
directives["value"] = (el, expr
|
|
624
|
+
directives["value"] = (el, expr) => {
|
|
624
625
|
let evaluate = parseExpr(el, expr, ":value");
|
|
625
626
|
let update = el.type === "text" || el.type === "" ? (value) => el.setAttribute("value", el.value = value == null ? "" : value) : el.type === "checkbox" ? (value) => (el.value = value ? "on" : "", attr(el, "checked", value)) : el.type === "select-one" ? (value) => {
|
|
626
627
|
for (let option in el.options)
|
|
@@ -631,7 +632,7 @@ directives["value"] = (el, expr, values) => {
|
|
|
631
632
|
return (state) => update(evaluate(state));
|
|
632
633
|
};
|
|
633
634
|
var _stop = Symbol("stop");
|
|
634
|
-
directives["on"] = (el, expr
|
|
635
|
+
directives["on"] = (el, expr) => {
|
|
635
636
|
let evaluate = parseExpr(el, expr, ":on");
|
|
636
637
|
let listeners = {};
|
|
637
638
|
return (state) => {
|
|
@@ -668,7 +669,7 @@ var removeListener = (el, evt, fn) => {
|
|
|
668
669
|
console.log("rewire"), fn[_stop] = true;
|
|
669
670
|
el.removeEventListener(evt, fn);
|
|
670
671
|
};
|
|
671
|
-
directives["data"] = (el, expr
|
|
672
|
+
directives["data"] = (el, expr) => {
|
|
672
673
|
let evaluate = parseExpr(el, expr, ":data");
|
|
673
674
|
return (state) => {
|
|
674
675
|
let value = evaluate(state);
|
|
@@ -676,7 +677,7 @@ directives["data"] = (el, expr, values) => {
|
|
|
676
677
|
el.dataset[key] = value[key];
|
|
677
678
|
};
|
|
678
679
|
};
|
|
679
|
-
directives["aria"] = (el, expr
|
|
680
|
+
directives["aria"] = (el, expr) => {
|
|
680
681
|
let evaluate = parseExpr(el, expr, ":aria");
|
|
681
682
|
const update = (value) => {
|
|
682
683
|
for (let key in value)
|
|
@@ -727,7 +728,7 @@ function sprae(container, values) {
|
|
|
727
728
|
return;
|
|
728
729
|
if (memo.has(container))
|
|
729
730
|
return memo.get(container);
|
|
730
|
-
values
|
|
731
|
+
const state = signalStruct(values || {});
|
|
731
732
|
const updates = [];
|
|
732
733
|
const init = (el, parent = el.parentNode) => {
|
|
733
734
|
if (el.attributes) {
|
|
@@ -744,7 +745,7 @@ function sprae(container, values) {
|
|
|
744
745
|
let attrNames = attr2.name.slice(1).split(":");
|
|
745
746
|
for (let attrName of attrNames) {
|
|
746
747
|
let dir = directives[attrName] || directives_default;
|
|
747
|
-
updates.push(dir(el, expr,
|
|
748
|
+
updates.push(dir(el, expr, state, attrName) || (() => {
|
|
748
749
|
}));
|
|
749
750
|
if (memo.has(el) || el.parentNode !== parent)
|
|
750
751
|
return false;
|
|
@@ -757,9 +758,9 @@ function sprae(container, values) {
|
|
|
757
758
|
}
|
|
758
759
|
};
|
|
759
760
|
init(container);
|
|
760
|
-
const state = SignalStruct(values);
|
|
761
761
|
for (let update of updates)
|
|
762
762
|
b(() => update(state));
|
|
763
|
+
Object.seal(state);
|
|
763
764
|
memo.set(container, state);
|
|
764
765
|
return state;
|
|
765
766
|
}
|
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)&&u(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 f(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 l(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function a(t){return new l(t)}function u(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 h(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 c(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 v(t){l.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function p(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,d(t),e}finally{i=o,e()}}}function d(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,p(t)}function y(t){if(i!==this)throw new Error("Out-of-order effect");c(this),i=t,this.f&=-2,8&this.f&&d(this),e()}function b(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function m(t){var e=new b(t);return e.c(),e.d.bind(e)}l.prototype.h=function(){return!0},l.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)},l.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)},l.prototype.subscribe=function(t){var e=this;return m((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},l.prototype.valueOf=function(){return this.value},l.prototype.toString=function(){return this.value+""},l.prototype.peek=function(){return this.v},Object.defineProperty(l.prototype,"value",{get:function(){var t=f(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()}}}}),(v.prototype=new l).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&&!u(this))return this.f&=-2,!0;var t=i;try{h(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,c(this),this.f&=-2,!0},v.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)}l.prototype.S.call(this,t)},v.prototype.U=function(t){if(l.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)}},v.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},v.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(v.prototype,"value",{get:function(){1&this.f&&t();var e=f(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),b.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},b.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,p(this),h(this),n++;var e=i;return i=this,y.bind(this,e)},b.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},b.prototype.d=function(){this.f|=8,1&this.f||d(this)},Symbol.observable||=Symbol("observable");var g=new FinalizationRegistry((t=>t.call?.())),S=t=>t&&t.peek,w=Symbol("signal-struct");function x(t){if((e=t)&&e[w])return t;var e;let i,r;if(O(t)){i={},r={};let e=Object.getOwnPropertyDescriptors(t);for(let t in e)r[t]=A(i,t,e[t].get?new v(e[t].get.bind(i)):e[t].value);return Object.defineProperty(i,w,{configurable:!1,enumerable:!1,value:!0}),Object.seal(i),i}return Array.isArray(t)?t.map((t=>x(t))):t}function A(t,e,i){let r,n=S(i)?i:O(i)||Array.isArray(i)?a(x(i)):a((r=(o=i)&&!!(o[Symbol.observable]||o[Symbol.asyncIterator]||o.call&&o.set||o.subscribe||o.then))?void 0:i);var o,s,f,l,u,h,c;return r&&(f=t=>n.value=t,(s=i)&&(c=(s[Symbol.observable]?.()||s).subscribe?.(f,l,undefined),h=c&&(()=>c.unsubscribe?.())||s.set&&s.call?.(u,f)||(s.then?.((t=>{!u&&f(t)}),l)||(async t=>{try{for await(t of s){if(u)return;f(t)}}catch(t){}})())&&(t=>u=1),g.register(s,h))),Object.defineProperty(t,e,{get:()=>n.value,set:!S(i)&&O(i)?t=>t?Object.assign(n.value,t):n.value=x(t):t=>n.value=x(t),enumerable:!0,configurable:!1}),n}function O(t){return t&&t.constructor===Object}var j=(t,e,i,r=null)=>{let n,o,s,f=0,l=i.length,a=e.length,{remove:u,same:h,insert:c,replace:v}=j;for(;f<l&&f<a&&h(e[f],i[f]);)f++;for(;f<l&&f<a&&h(i[l-1],e[a-1]);)r=i[(--a,--l)];if(f==a)for(;f<l;)c(r,i[f++],t);else{for(n=e[f];f<l;)s=i[f++],o=n?n.nextSibling:r,h(n,s)?n=o:f<l&&h(i[f],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};j.same=(t,e)=>t==e,j.replace=(t,e,i)=>i.replaceChild(e,t),j.insert=(t,e,i)=>i.insertBefore(e,t),j.remove=(t,e)=>e.removeChild(t);var N=j,E={},W={},k={},$={},U=(t,e,i,r)=>{let n,o=r.startsWith("on")&&r.slice(2),s=T(t,e,":"+r);return o?e=>{n&&_(t,o,n),n=s(e),n&&D(t,o,n)}:e=>C(t,r,s(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,i)=>{let r=T(t,e,":");return e=>{let i=r(e);for(let e in i)C(t,I(e),i[e])}};var B=Symbol(":each"),L=Symbol(":ref");$.ref=(t,e,i)=>{t.hasAttribute(":each")?t[L]=e:i[e]=t},$.with=(t,e,i)=>{throw T(t,e,"with"),"Unimplemented"},$.if=(t,e,i)=>{let r=document.createTextNode(""),n=[T(t,e,":if")],o=[t],s=t;for(;(s=t.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(e=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),o.push(s),n.push(T(t,e,":else :if"))):(s.remove(),o.push(s),n.push((()=>1)));return t.replaceWith(s=r),t=>{let e=n.findIndex((e=>e(t)));o[e]!=s&&((s[B]||s).replaceWith(s=o[e]||r),R(s,t))}},$.each=(t,e,i)=>{let r=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(!r)return F(new Error,t,e);const n=t[B]=document.createTextNode("");t.replaceWith(n);const o=T(t,r.items,":each"),s=new WeakMap,f=new WeakMap;let l=[];return e=>{let i=o(e);i?"number"==typeof i?i=Array.from({length:i},((t,e)=>[e,e+1])):i.constructor===Object?i=Object.entries(i):Array.isArray(i)?i=i.map(((t,e)=>[e+1,t])):F(Error("Bad list value"),t,r.items,":each"):i=[];let a=[],u=[];for(let[n,o]of i){let i=null===(h=o)?W:void 0===h?k:"number"==typeof h||h instanceof Number?E[h]||(E[h]=new Number(h)):"string"==typeof h||h instanceof String?E[h]||(E[h]=new String(h)):"boolean"==typeof h||h instanceof Boolean?E[h]||(E[h]=new Boolean(h)):h,l=f.get(i);if(l||(l=t.cloneNode(!0),f.set(i,l)),a.push(l),!s.has(i)){let f=Object.create(e);f[r.item]=o,r.index&&(f[r.index]=n),t[L]&&(f[t[L]]=l),s.set(i,f)}u.push(s.get(i))}var h;N(n.parentNode,l,a,n),l=a;for(let t=0;t<a.length;t++)R(a[t],u[t])}},$.id=(t,e,i)=>{let r=T(t,e,":id");return e=>{return i=r(e),t.id=i||0===i?i:"";var i}},$.class=(t,e,i)=>{let r=T(t,e,":class"),n=t.className;return e=>{let i=r(e);t.className=n+typeof i=="string"?i:(Array.isArray(i)?i:Object.entries(i).map((([t,e])=>e?t:""))).filter(Boolean).join(" ")}},$.style=(t,e,i)=>{let r=T(t,e,":style"),n=t.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),e=>{let i=r(e);if("string"==typeof i)t.setAttribute("style",n+i);else for(let e in i)t.style[e]=i[e]}},$.text=(t,e,i)=>{let r=T(t,e,":text");return e=>{return i=r(e),void(t.textContent=null==i?"":i);var i}},$.value=(t,e,i)=>{let r=T(t,e,":value"),n="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"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=>n(r(t))};var P=Symbol("stop");$.on=(t,e,i)=>{let r=T(t,e,":on"),n={};return e=>{for(let e in n)_(t,e,n[e]);n=r(e);for(let e in n)D(t,e,n[e])}};var 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=f=>{t.removeEventListener(r[o],s),"function"!=typeof(e=e.call(t,f))&&(e=()=>{}),++o<r.length?n(e,o):i[P]||(console.log("reset"),n(i))};t.addEventListener(r[o],s)};n(i)}},_=(t,e,i)=>{e.indexOf("..")>=0&&(console.log("rewire"),i[P]=!0),t.removeEventListener(e,i)};$.data=(t,e,i)=>{let r=T(t,e,":data");return e=>{let i=r(e);for(let e in i)t.dataset[e]=i[e]}},$.aria=(t,e,i)=>{let r=T(t,e,":aria");return e=>(e=>{for(let i in e)C(t,"aria-"+I(i),null==e[i]?null:e[i]+"")})(r(e))};var M={};function T(t,e,i){if(M[e])return M[e];let r,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=new Function("__scope",`with (__scope) { return (${n}) };`).bind(t)}catch(r){return F(r,t,e,i)}return M[e]=n=>{let o;try{o=r(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 R(t,e){if(!t.children)return;if(z.has(t))return z.get(t);e||={};const i=[],r=(t,n=t.parentNode)=>{if(t.attributes)for(let r=0;r<t.attributes.length;){let o=t.attributes[r];if(":"!==o.name[0]){r++;continue}t.removeAttribute(o.name);let s=o.value;if(!s)continue;let f=o.name.slice(1).split(":");for(let r of f){let o=$[r]||U;if(i.push(o(t,s,e,r)||(()=>{})),z.has(t)||t.parentNode!==n)return!1}}for(let e,i=0;e=t.children[i];i++)!1===r(e,t)&&i--};r(t);const n=x(e);for(let t of i)m((()=>t(n)));return z.set(t,n),n}var Z=R;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)&&u(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 f(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 l(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function a(t){return new l(t)}function u(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 h(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 c(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 v(t){l.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function p(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,d(t),e}finally{i=o,e()}}}function d(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,p(t)}function y(t){if(i!==this)throw new Error("Out-of-order effect");c(this),i=t,this.f&=-2,8&this.f&&d(this),e()}function b(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function m(t){var e=new b(t);return e.c(),e.d.bind(e)}l.prototype.h=function(){return!0},l.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)},l.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)},l.prototype.subscribe=function(t){var e=this;return m((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},l.prototype.valueOf=function(){return this.value},l.prototype.toString=function(){return this.value+""},l.prototype.peek=function(){return this.v},Object.defineProperty(l.prototype,"value",{get:function(){var t=f(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()}}}}),(v.prototype=new l).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&&!u(this))return this.f&=-2,!0;var t=i;try{h(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,c(this),this.f&=-2,!0},v.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)}l.prototype.S.call(this,t)},v.prototype.U=function(t){if(l.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)}},v.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},v.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(v.prototype,"value",{get:function(){1&this.f&&t();var e=f(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),b.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},b.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,p(this),h(this),n++;var e=i;return i=this,y.bind(this,e)},b.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},b.prototype.d=function(){this.f|=8,1&this.f||d(this)},Symbol.observable||=Symbol("observable");var g=new FinalizationRegistry((t=>t.call?.())),S=t=>t&&t.peek,x=t=>t&&t[w],w=Symbol("signal-struct");function A(t,e){if(x(t)&&!e)return t;let i,r;if(j(t)){i=Object.create(e||Object.getPrototypeOf(t)),r={};let n=Object.getOwnPropertyDescriptors(t);if(x(t))for(let t in n)Object.defineProperty(i,t,n[t]);else for(let t in n)r[t]=O(i,t,n[t].get?new v(n[t].get.bind(i)):n[t].value);return Object.defineProperty(i,w,{configurable:!1,enumerable:!1,value:!0}),i}return Array.isArray(t)?t.map((t=>A(t))):t}function O(t,e,i){let r,n=S(i)?i:j(i)||Array.isArray(i)?a(A(i)):a((r=(o=i)&&!!(o[Symbol.observable]||o[Symbol.asyncIterator]||o.call&&o.set||o.subscribe||o.then))?void 0:i);var o,s,f,l,u,h,c;return r&&(f=t=>n.value=t,(s=i)&&(c=(s[Symbol.observable]?.()||s).subscribe?.(f,l,undefined),h=c&&(()=>c.unsubscribe?.())||s.set&&s.call?.(u,f)||(s.then?.((t=>{!u&&f(t)}),l)||(async t=>{try{for await(t of s){if(u)return;f(t)}}catch(t){}})())&&(t=>u=1),g.register(s,h))),Object.defineProperty(t,e,{get:()=>n.value,set:!S(i)&&j(i)?t=>t?Object.assign(n.value,t):n.value=A(t):t=>n.value=A(t),enumerable:!0,configurable:!1}),n}function j(t){return t&&t.constructor===Object}A.isStruct=x;var N=(t,e,i,r=null)=>{let n,o,s,f=0,l=i.length,a=e.length,{remove:u,same:h,insert:c,replace:v}=N;for(;f<l&&f<a&&h(e[f],i[f]);)f++;for(;f<l&&f<a&&h(i[l-1],e[a-1]);)r=i[(--a,--l)];if(f==a)for(;f<l;)c(r,i[f++],t);else{for(n=e[f];f<l;)s=i[f++],o=n?n.nextSibling:r,h(n,s)?n=o:f<l&&h(i[f],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};N.same=(t,e)=>t==e,N.replace=(t,e,i)=>i.replaceChild(e,t),N.insert=(t,e,i)=>i.insertBefore(e,t),N.remove=(t,e)=>e.removeChild(t);var E=N,W={},k={},$={},P={},C=(t,e,i,r)=>{let n,o=r.startsWith("on")&&r.slice(2),s=F(t,e,":"+r);return o?e=>{n&&M(t,o,n),n=s(e),n&&_(t,o,n)}:e=>U(t,r,s(e))},U=(t,e,i)=>{null==i||!1===i?t.removeAttribute(e):t.setAttribute(e,!0===i?"":"number"==typeof i||"string"==typeof i?i:"")};P[""]=(t,e)=>{let i=F(t,e,":");return e=>{let r=i(e);for(let e in r)U(t,z(e),r[e])}};var B=Symbol(":each"),L=Symbol(":ref");P.ref=(t,e,i)=>{t.hasAttribute(":each")?t[L]=e:i[e]=t},P.with=(t,e,i)=>{Z(t,A(F(t,e,"with")(i),i))},P.if=(t,e)=>{let i=document.createTextNode(""),r=[F(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(F(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[B]||o).replaceWith(o=n[e]||i),Z(o,t))}},P.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 I(new Error,t,e);const r=t[B]=document.createTextNode("");t.replaceWith(r);const n=F(t,i.items,":each"),o=new WeakMap,s=new WeakMap;let f=[];return l=>{let a=n(l);a?"number"==typeof a?a=Array.from({length:a},((t,e)=>[e,e+1])):Array.isArray(a)?a=a.map(((t,e)=>[e+1,t])):"object"==typeof a?a=Object.entries(a):I(Error("Bad list value"),t,e,":each"):a=[];let u=[],h=[];for(let[e,r]of a){let n=null===(c=r)?k:void 0===c?$:"number"==typeof c||c instanceof Number?W[c]||(W[c]=new Number(c)):"string"==typeof c||c instanceof String?W[c]||(W[c]=new String(c)):"boolean"==typeof c||c instanceof Boolean?W[c]||(W[c]=new Boolean(c)):c,f=s.get(n);if(f||(f=t.cloneNode(!0),s.set(n,f)),u.push(f),!o.has(n)){let s=Object.create(l);s[i.item]=r,i.index&&(s[i.index]=e),t[L]&&(s[t[L]]=f),o.set(n,s)}h.push(o.get(n))}var c;E(r.parentNode,f,u,r),f=u;for(let t=0;t<u.length;t++)Z(u[t],h[t])}},P.id=(t,e)=>{let i=F(t,e,":id");return e=>{return r=i(e),t.id=r||0===r?r:"";var r}},P.class=(t,e)=>{let i=F(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(" ")}},P.style=(t,e)=>{let i=F(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]}},P.text=(t,e)=>{let i=F(t,e,":text");return e=>{let r=i(e);t.textContent=null==r?"":r}},P.value=(t,e)=>{let i=F(t,e,":value"),r="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"checkbox"===t.type?e=>(t.value=e?"on":"",U(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=>r(i(t))};var D=Symbol("stop");P.on=(t,e)=>{let i=F(t,e,":on"),r={};return e=>{for(let e in r)M(t,e,r[e]);r=i(e);for(let e in r)_(t,e,r[e])}};var _=(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=f=>{t.removeEventListener(r[o],s),"function"!=typeof(e=e.call(t,f))&&(e=()=>{}),++o<r.length?n(e,o):i[D]||(console.log("reset"),n(i))};t.addEventListener(r[o],s)};n(i)}},M=(t,e,i)=>{e.indexOf("..")>=0&&(console.log("rewire"),i[D]=!0),t.removeEventListener(e,i)};P.data=(t,e)=>{let i=F(t,e,":data");return e=>{let r=i(e);for(let e in r)t.dataset[e]=r[e]}},P.aria=(t,e)=>{let i=F(t,e,":aria");return e=>(e=>{for(let i in e)U(t,"aria-"+z(i),null==e[i]?null:e[i]+"")})(i(e))};var T={};function F(t,e,i){if(T[e])return T[e];let r,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=new Function("__scope",`with (__scope) { return (${n}) };`).bind(t)}catch(r){return I(r,t,e,i)}return T[e]=n=>{let o;try{o=r(n)}catch(r){return I(r,t,e,i)}return o}}function I(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 z(t){return t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(t=>"-"+t.toLowerCase()))}var R=new WeakMap;function Z(t,e){if(!t.children)return;if(R.has(t))return R.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 f=o.name.slice(1).split(":");for(let n of f){let o=P[n]||C;if(r.push(o(t,s,i,n)||(()=>{})),R.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)m((()=>t(i)));return Object.seal(i),R.set(t,i),i}var q=Z;export{q as default};
|
package/src/core.js
CHANGED
|
@@ -8,9 +8,8 @@ export default function sprae(container, values) {
|
|
|
8
8
|
if (!container.children) return
|
|
9
9
|
if (memo.has(container)) return memo.get(container)
|
|
10
10
|
|
|
11
|
-
values
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
// signalStruct returns values if it's signalStruct already
|
|
12
|
+
const state = signalStruct(values || {});
|
|
14
13
|
const updates = []
|
|
15
14
|
|
|
16
15
|
// init directives on element
|
|
@@ -25,7 +24,7 @@ export default function sprae(container, values) {
|
|
|
25
24
|
let attrNames = attr.name.slice(1).split(':')
|
|
26
25
|
for (let attrName of attrNames) {
|
|
27
26
|
let dir = directives[attrName] || defaultDirective;
|
|
28
|
-
updates.push(dir(el, expr,
|
|
27
|
+
updates.push(dir(el, expr, state, attrName) || (()=>{}));
|
|
29
28
|
|
|
30
29
|
// stop if element was spraed by directive or skipped
|
|
31
30
|
if (memo.has(el) || el.parentNode !== parent) return false
|
|
@@ -43,9 +42,9 @@ export default function sprae(container, values) {
|
|
|
43
42
|
|
|
44
43
|
// call updates: subscribes directives to state;
|
|
45
44
|
// state is created after inits because directives can extend init values (expose refs etc)
|
|
46
|
-
const state = signalStruct(values);
|
|
47
45
|
for (let update of updates) effect(() => update(state));
|
|
48
46
|
|
|
47
|
+
Object.seal(state);
|
|
49
48
|
memo.set(container, state);
|
|
50
49
|
|
|
51
50
|
return state;
|
package/src/directives.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import sprae from './core.js'
|
|
3
3
|
import swap from 'swapdom'
|
|
4
4
|
import p from 'primitive-pool'
|
|
5
|
+
import signalStruct from 'signal-struct'
|
|
5
6
|
|
|
6
7
|
// reserved directives - order matters!
|
|
7
8
|
export const directives = {}
|
|
@@ -26,7 +27,7 @@ const attr = (el, name, v) => {
|
|
|
26
27
|
else el.setAttribute(name, v === true ? '' : (typeof v === 'number' || typeof v === 'string') ? v : '')
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
directives[''] = (el, expr
|
|
30
|
+
directives[''] = (el, expr) => {
|
|
30
31
|
let evaluate = parseExpr(el, expr, ':')
|
|
31
32
|
return (state) => {
|
|
32
33
|
let value = evaluate(state)
|
|
@@ -36,40 +37,21 @@ directives[''] = (el, expr, values) => {
|
|
|
36
37
|
|
|
37
38
|
const _each = Symbol(':each'), _ref = Symbol(':ref')
|
|
38
39
|
|
|
39
|
-
directives['ref'] = (el, expr,
|
|
40
|
+
directives['ref'] = (el, expr, state) => {
|
|
40
41
|
// make sure :ref is initialized after :each (return to avoid initializing as signal)
|
|
41
42
|
if (el.hasAttribute(':each')) {el[_ref] = expr; return};
|
|
42
43
|
|
|
43
44
|
// FIXME: wait for complex ref use-case
|
|
44
45
|
// parseExpr(el, `__scope[${expr}]=this`, ':ref')(values)
|
|
45
|
-
|
|
46
|
+
state[expr] = el;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
directives['with'] = (el, expr, rootState) => {
|
|
49
50
|
let evaluate = parseExpr(el, expr, 'with')
|
|
50
|
-
|
|
51
|
-
throw 'Unimplemented';
|
|
52
|
-
|
|
53
|
-
// prev iteration
|
|
54
|
-
// // Instead of extending signals (which is a bit hard since signal-struct internals is not uniform)
|
|
55
|
-
// // we bind updating
|
|
56
|
-
// const params = computed(() => Object.assign({}, rootState, evaluate(rootState)))
|
|
57
|
-
|
|
58
|
-
// // NOTE: initialized element doesn't proceed with its children
|
|
59
|
-
// let state = sprae(el, params.value)
|
|
60
|
-
|
|
61
|
-
// // but update is still called with parent state
|
|
62
|
-
// return (rootState) => batch(() => Object.assign(state, params.value))
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// must be as simple as
|
|
66
|
-
// don't care if root state updates - we're subscribed to it via inheritance _or_ shadowing it
|
|
67
|
-
let withValues = evaluate(rootState);
|
|
68
|
-
let newState = Object.assign(Object.create(rootState), withValues)
|
|
69
|
-
sprae(el, newState)
|
|
51
|
+
sprae(el, signalStruct(evaluate(rootState), rootState));
|
|
70
52
|
}
|
|
71
53
|
|
|
72
|
-
directives['if'] = (el, expr
|
|
54
|
+
directives['if'] = (el, expr) => {
|
|
73
55
|
let holder = document.createTextNode(''),
|
|
74
56
|
clauses = [parseExpr(el, expr, ':if')],
|
|
75
57
|
els = [el], cur = el
|
|
@@ -100,7 +82,7 @@ directives['if'] = (el, expr, values) => {
|
|
|
100
82
|
}
|
|
101
83
|
}
|
|
102
84
|
|
|
103
|
-
directives['each'] = (tpl, expr
|
|
85
|
+
directives['each'] = (tpl, expr) => {
|
|
104
86
|
let each = parseForExpression(expr);
|
|
105
87
|
if (!each) return exprError(new Error, tpl, expr);
|
|
106
88
|
|
|
@@ -122,9 +104,9 @@ directives['each'] = (tpl, expr, values) => {
|
|
|
122
104
|
let list = evaluate(state)
|
|
123
105
|
if (!list) list = []
|
|
124
106
|
else if (typeof list === 'number') list = Array.from({length: list}, (_, i)=>[i, i+1])
|
|
125
|
-
else if (list.constructor === Object) list = Object.entries(list)
|
|
126
107
|
else if (Array.isArray(list)) list = list.map((item,i) => [i+1, item])
|
|
127
|
-
else
|
|
108
|
+
else if (typeof list === 'object') list = Object.entries(list)
|
|
109
|
+
else exprError(Error('Bad list value'), tpl, expr, ':each', list)
|
|
128
110
|
|
|
129
111
|
// collect elements/scopes for items
|
|
130
112
|
let newEls = [], elScopes = []
|
|
@@ -184,13 +166,13 @@ function parseForExpression(expression) {
|
|
|
184
166
|
return res
|
|
185
167
|
}
|
|
186
168
|
|
|
187
|
-
directives['id'] = (el, expr
|
|
169
|
+
directives['id'] = (el, expr) => {
|
|
188
170
|
let evaluate = parseExpr(el, expr, ':id')
|
|
189
171
|
const update = v => el.id = v || v === 0 ? v : ''
|
|
190
172
|
return (state) => update(evaluate(state))
|
|
191
173
|
}
|
|
192
174
|
|
|
193
|
-
directives['class'] = (el, expr
|
|
175
|
+
directives['class'] = (el, expr) => {
|
|
194
176
|
let evaluate = parseExpr(el, expr, ':class')
|
|
195
177
|
let initClassName = el.className
|
|
196
178
|
return (state) => {
|
|
@@ -199,7 +181,7 @@ directives['class'] = (el, expr, values) => {
|
|
|
199
181
|
}
|
|
200
182
|
}
|
|
201
183
|
|
|
202
|
-
directives['style'] = (el, expr
|
|
184
|
+
directives['style'] = (el, expr) => {
|
|
203
185
|
let evaluate = parseExpr(el, expr, ':style')
|
|
204
186
|
let initStyle = el.getAttribute('style') || ''
|
|
205
187
|
if (!initStyle.endsWith(';')) initStyle += '; '
|
|
@@ -210,18 +192,17 @@ directives['style'] = (el, expr, values) => {
|
|
|
210
192
|
}
|
|
211
193
|
}
|
|
212
194
|
|
|
213
|
-
directives['text'] = (el, expr
|
|
195
|
+
directives['text'] = (el, expr) => {
|
|
214
196
|
let evaluate = parseExpr(el, expr, ':text')
|
|
215
197
|
|
|
216
|
-
|
|
198
|
+
return (state) => {
|
|
199
|
+
let value = evaluate(state)
|
|
217
200
|
el.textContent = value == null ? '' : value;
|
|
218
201
|
}
|
|
219
|
-
|
|
220
|
-
return (state) => update(evaluate(state))
|
|
221
202
|
}
|
|
222
203
|
|
|
223
204
|
// connect expr to element value
|
|
224
|
-
directives['value'] = (el, expr
|
|
205
|
+
directives['value'] = (el, expr) => {
|
|
225
206
|
let evaluate = parseExpr(el, expr, ':value')
|
|
226
207
|
|
|
227
208
|
let update = (
|
|
@@ -239,7 +220,7 @@ directives['value'] = (el, expr, values) => {
|
|
|
239
220
|
}
|
|
240
221
|
|
|
241
222
|
const _stop = Symbol('stop')
|
|
242
|
-
directives['on'] = (el, expr
|
|
223
|
+
directives['on'] = (el, expr) => {
|
|
243
224
|
let evaluate = parseExpr(el, expr, ':on')
|
|
244
225
|
let listeners = {}
|
|
245
226
|
|
|
@@ -274,7 +255,7 @@ const removeListener = (el, evt, fn) => {
|
|
|
274
255
|
el.removeEventListener(evt, fn);
|
|
275
256
|
}
|
|
276
257
|
|
|
277
|
-
directives['data'] = (el, expr
|
|
258
|
+
directives['data'] = (el, expr) => {
|
|
278
259
|
let evaluate = parseExpr(el, expr, ':data')
|
|
279
260
|
|
|
280
261
|
return ((state) => {
|
|
@@ -283,7 +264,7 @@ directives['data'] = (el, expr, values) => {
|
|
|
283
264
|
})
|
|
284
265
|
}
|
|
285
266
|
|
|
286
|
-
directives['aria'] = (el, expr
|
|
267
|
+
directives['aria'] = (el, expr) => {
|
|
287
268
|
let evaluate = parseExpr(el, expr, ':aria')
|
|
288
269
|
const update = (value) => {
|
|
289
270
|
for (let key in value) attr(el, 'aria-' + dashcase(key), value[key] == null ? null : value[key] + '');
|
package/test/test.js
CHANGED
|
@@ -463,32 +463,33 @@ test('on: state changes between chain of events', e => {
|
|
|
463
463
|
is(log, [1, 1.1, 2])
|
|
464
464
|
})
|
|
465
465
|
|
|
466
|
-
test
|
|
467
|
-
let el = h`<x :with="{foo:'bar'
|
|
466
|
+
test('with: inline', () => {
|
|
467
|
+
let el = h`<x :with="{foo:'bar'}"><y :text="foo + baz"></y></x>`
|
|
468
468
|
let state = sprae(el, {baz: 'qux'})
|
|
469
469
|
// FIXME: this doesn't inherit root scope baz property and instead uses hard-initialized one
|
|
470
470
|
is(el.innerHTML, `<y>barqux</y>`)
|
|
471
471
|
state.baz = 'quux'
|
|
472
472
|
is(el.innerHTML, `<y>barquux</y>`)
|
|
473
473
|
})
|
|
474
|
-
test
|
|
475
|
-
let el = h`<x :with="{foo:'bar'
|
|
474
|
+
test('with: inline reactive', () => {
|
|
475
|
+
let el = h`<x :with="{foo:'bar'}"><y :text="foo + baz"></y></x>`
|
|
476
476
|
let baz = signal('qux')
|
|
477
|
-
|
|
477
|
+
sprae(el, {baz})
|
|
478
478
|
// FIXME: this doesn't inherit root scope baz property and instead uses hard-initialized one
|
|
479
479
|
is(el.innerHTML, `<y>barqux</y>`)
|
|
480
480
|
baz.value = 'quux'
|
|
481
481
|
is(el.innerHTML, `<y>barquux</y>`)
|
|
482
482
|
})
|
|
483
|
-
test
|
|
483
|
+
test('with: data', () => {
|
|
484
484
|
let el = h`<x :with="x"><y :text="foo"></y></x>`
|
|
485
485
|
let state = sprae(el, {x:{foo:'bar'}})
|
|
486
486
|
is(el.innerHTML, `<y>bar</y>`)
|
|
487
487
|
console.log('update')
|
|
488
|
-
|
|
488
|
+
state.x.foo = 'baz'
|
|
489
|
+
// Object.assign(state, {x:{foo:'baz'}})
|
|
489
490
|
is(el.innerHTML, `<y>baz</y>`)
|
|
490
491
|
})
|
|
491
|
-
test
|
|
492
|
+
test('with: transparency', () => {
|
|
492
493
|
// NOTE: y:text initializes through directive, not through parent
|
|
493
494
|
// therefore by default :text uses parent's state, not defined by element itself
|
|
494
495
|
let el = h`<x :with="{foo:'foo'}"><y :with="b" :text="foo+bar"></y></x>`
|
|
@@ -497,7 +498,7 @@ test.todo('with: transparency', () => {
|
|
|
497
498
|
params.b.bar = 'baz'
|
|
498
499
|
is(el.innerHTML, `<y>foobaz</y>`)
|
|
499
500
|
})
|
|
500
|
-
test
|
|
501
|
+
test('with: reactive transparency', () => {
|
|
501
502
|
let el = h`<x :with="{foo:1}"><y :with="b.c" :text="foo+bar"></y></x>`
|
|
502
503
|
const bar = signal('2')
|
|
503
504
|
sprae(el, {b:{c:{bar}}})
|
|
@@ -505,7 +506,7 @@ test.todo('with: reactive transparency', () => {
|
|
|
505
506
|
bar.value = '3'
|
|
506
507
|
is(el.innerHTML, `<y>13</y>`)
|
|
507
508
|
})
|
|
508
|
-
test
|
|
509
|
+
test('with: writes to state', () => {
|
|
509
510
|
let a = h`<x :with="{a:1}"><y :on="{x(){a++}}" :text="a"></y></x>`
|
|
510
511
|
sprae(a)
|
|
511
512
|
is(a.innerHTML, `<y>1</y>`)
|