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 CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "sprae",
3
3
  "description": "DOM microhydration.",
4
- "version": "2.4.0",
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.6.0",
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 enable easy init syntax
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
- function SignalStruct(values) {
367
- if (isStruct(values))
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 = {}, signals = {};
372
+ state = Object.create(proto || Object.getPrototypeOf(values)), signals = {};
372
373
  let desc = Object.getOwnPropertyDescriptors(values);
373
- for (let key in desc)
374
- signals[key] = defineSignal(state, key, desc[key].get ? w(desc[key].get.bind(state)) : desc[key].value);
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) => SignalStruct(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(SignalStruct(value)) : u((isObservable = observable(value)) ? void 0 : value);
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 = SignalStruct(v2) : (v2) => s2.value = SignalStruct(v2),
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, values) => {
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, values) => {
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
- values[expr] = el;
490
+ state[expr] = el;
487
491
  };
488
492
  directives["with"] = (el, expr, rootState) => {
489
493
  let evaluate = parseExpr(el, expr, "with");
490
- throw "Unimplemented";
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, values) => {
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, values) => {
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, each.items, ":each", list);
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, values) => {
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, values) => {
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, values) => {
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, values) => {
617
+ directives["text"] = (el, expr) => {
617
618
  let evaluate = parseExpr(el, expr, ":text");
618
- const update = (value) => {
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, values) => {
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, values) => {
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, values) => {
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, values) => {
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, values, attrName) || (() => {
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
- // FIXME: init values must read "snapshot" of signals to avoid leaking actual signals to directives
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, values, attrName) || (()=>{}));
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, values) => {
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, values) => {
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
- values[expr] = el;
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, values) => {
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, values) => {
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 exprError(Error('Bad list value'), tpl, each.items, ':each', list)
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, values) => {
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, values) => {
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, values) => {
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, values) => {
195
+ directives['text'] = (el, expr) => {
214
196
  let evaluate = parseExpr(el, expr, ':text')
215
197
 
216
- const update = (value) => {
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, values) => {
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, values) => {
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, values) => {
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, values) => {
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.todo('with: inline', () => {
467
- let el = h`<x :with="{foo:'bar', baz}"><y :text="foo + baz"></y></x>`
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.todo('with: inline reactive', () => {
475
- let el = h`<x :with="{foo:'bar', baz}"><y :text="foo + baz"></y></x>`
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
- let state = sprae(el, {baz})
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.todo('with: data', () => {
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
- Object.assign(state, {x:{foo:'baz'}})
488
+ state.x.foo = 'baz'
489
+ // Object.assign(state, {x:{foo:'baz'}})
489
490
  is(el.innerHTML, `<y>baz</y>`)
490
491
  })
491
- test.todo('with: transparency', () => {
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.todo('with: reactive transparency', () => {
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.todo('with: writes to state', () => {
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>`)