sprae 1.0.0 → 2.0.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/test/test.js CHANGED
@@ -1,4 +1,5 @@
1
- import { signal } from '@preact/signals'
1
+ // import { signal } from 'usignal'
2
+ import { signal } from '@preact/signals-core'
2
3
  import test, {is, any, throws} from 'tst'
3
4
  import {tick, time} from 'wait-please'
4
5
  import sprae from '../src/index.js'
@@ -21,34 +22,34 @@ test.skip('autoinit', async () => {
21
22
  test('hidden: core', async () => {
22
23
  let el = h`<div :hidden="hidden"></div>`
23
24
  let params = sprae(el, {hidden:true})
24
- is(el.outerHTML, `<div class="∴hidden" hidden=""></div>`)
25
+ is(el.outerHTML, `<div hidden=""></div>`)
25
26
  params.hidden = false
26
- is(el.outerHTML, `<div class="∴hidden"></div>`)
27
+ is(el.outerHTML, `<div></div>`)
27
28
  })
28
29
 
29
30
  test('hidden: reactive', async () => {
30
31
  const hidden = signal(true)
31
32
  let el = h`<div :hidden="hidden"></div>`
32
33
  sprae(el, {hidden})
33
- is(el.outerHTML, `<div class="∴hidden" hidden=""></div>`)
34
+ is(el.outerHTML, `<div hidden=""></div>`)
34
35
  hidden.value = false
35
- is(el.outerHTML, `<div class="∴hidden"></div>`)
36
+ is(el.outerHTML, `<div></div>`)
36
37
  })
37
38
 
38
39
  test('common: reactive', async () => {
39
40
  let el = h`<label :for="name" :text="name" ></label><input :id="name" :name="name" :type="name" :disabled="!name"/><a :href="url"></a><img :src="url"/>`
40
41
  let params = sprae(el, {name:'text', url:'//google.com'})
41
- is(el.outerHTML, `<label class="∴text ∴for" for="text">text</label><input class="∴id ∴name ∴type ∴disabled" id="text" name="text" type="text"><a class="∴href" href="//google.com"></a><img class="∴src" src="//google.com">`)
42
+ is(el.outerHTML, `<label for="text">text</label><input id="text" name="text" type="text"><a href="//google.com"></a><img src="//google.com">`)
42
43
  params.name = 'email'
43
- is(el.outerHTML, `<label class="∴text ∴for" for="email">email</label><input class="∴id ∴name ∴type ∴disabled" id="email" name="email" type="email"><a class="∴href" href="//google.com"></a><img class="∴src" src="//google.com">`)
44
+ is(el.outerHTML, `<label for="email">email</label><input id="email" name="email" type="email"><a href="//google.com"></a><img src="//google.com">`)
44
45
  })
45
46
 
46
47
  test('common: style', async () => {
47
48
  let el = h`<x :style="style"></x>`
48
49
  let params = sprae(el, {style: "top: 1px"})
49
- is(el.outerHTML, `<x class="∴style" style="top: 1px"></x>`)
50
+ is(el.outerHTML, `<x style="top: 1px"></x>`)
50
51
  params.style = {top: '2px'}
51
- is(el.outerHTML, `<x class="∴style" style="top: 2px"></x>`)
52
+ is(el.outerHTML, `<x style="top: 2px"></x>`)
52
53
  })
53
54
 
54
55
  test('common: class', async () => {
@@ -62,111 +63,111 @@ test('common: class', async () => {
62
63
  is(el.outerHTML, `<x class="x"></x><y class="y w"></y><z class="b c"></z>`);
63
64
  })
64
65
 
65
- test('props: base', async () => {
66
- let el = h`<input :prop="{for:1, title:2, help:3, type:4, placeholder: 5}"/>`
66
+ test('spread props: base', async () => {
67
+ let el = h`<input :id="0" :="{for:1, title:2, help:3, type:4, placeholder: 5, value: 6}" :value="7"/>`
67
68
  let params = sprae(el)
68
- is(el.outerHTML, `<input class="∴prop" for="1" title="2" help="3" type="4" placeholder="5">`)
69
+ is(el.outerHTML, `<input id="0" for="1" title="2" help="3" type="4" placeholder="5" value="7">`)
69
70
  })
70
71
 
71
72
  test('data: base', async () => {
72
73
  let el = h`<input :data="{a:1, fooBar:2}"/>`
73
74
  let params = sprae(el)
74
- is(el.outerHTML, `<input class="∴data" data-a="1" data-foo-bar="2">`)
75
+ is(el.outerHTML, `<input data-a="1" data-foo-bar="2">`)
75
76
  })
76
77
 
77
78
  test('aria: base', async () => {
78
- let el = h`<input type="text" id="jokes" role="combobox" :aria="{controls:'joketypes', autocomplete:'list', expanded:false, activeOption:'item1', activedescendant:''}"/>`
79
+ let el = h`<input type="text" id="jokes" role="combobox" :aria="{controls:'joketypes', autocomplete:'list', expanded:false, activeOption:'item1', activedescendant:'', xxx:null}"/>`
79
80
  sprae(el)
80
- is(el.outerHTML, `<input type="text" id="jokes" role="combobox" class="∴aria" aria-controls="joketypes" aria-autocomplete="list" aria-expanded="false" aria-active-option="item1" aria-activedescendant="">`)
81
+ is(el.outerHTML, `<input type="text" id="jokes" role="combobox" aria-controls="joketypes" aria-autocomplete="list" aria-expanded="false" aria-active-option="item1" aria-activedescendant="">`)
81
82
  })
82
83
 
83
- test('input: direct', async () => {
84
+ test('value: direct', async () => {
84
85
  let el = h`<input :value="a" />`
85
86
  let state = sprae(el, {a:1})
86
87
  is(el.value, '1')
87
- is(el.outerHTML, `<input class="∴value" value="1">`)
88
+ is(el.outerHTML, `<input value="1">`)
88
89
  state.a = 2
89
90
  is(el.value, '2')
90
- is(el.outerHTML, `<input class="∴value" value="2">`)
91
+ is(el.outerHTML, `<input value="2">`)
91
92
 
92
93
  el.value = 3
93
- el.dispatchEvent(new window.Event('change'))
94
- is(state.a, '3')
94
+ // el.dispatchEvent(new window.Event('change'))
95
+ // is(state.a, '3')
95
96
  })
96
97
 
97
98
  test('text: core', async () => {
98
99
  let el = h`<div :text="text"></div>`
99
100
  let params = sprae(el, {text:'abc'})
100
- is(el.outerHTML, `<div class="∴text">abc</div>`)
101
+ is(el.outerHTML, `<div>abc</div>`)
101
102
  params.text = null
102
- is(el.outerHTML, `<div class="∴text"></div>`)
103
+ is(el.outerHTML, `<div></div>`)
103
104
  })
104
105
 
105
106
  test('conditions: base', async () => {
106
107
  let el = h`<p>
107
108
  <span :if="a==1">a</span>
108
- <span :else-if="a==2">b</span>
109
+ <span :else :if="a==2">b</span>
109
110
  <span :else >c</span>
110
111
  </p>`
111
112
 
112
113
  const params = sprae(el, { a: 1 })
113
114
 
114
- is(el.innerHTML, '<span class="∴if">a</span>')
115
+ is(el.innerHTML, '<span>a</span>')
115
116
  params.a = 2
116
- is(el.innerHTML, '<span class="∴else-if">b</span>')
117
+ is(el.innerHTML, '<span>b</span>')
117
118
  params.a = 3
118
- is(el.innerHTML, '<span class="∴else">c</span>')
119
-
120
- delete params.a
119
+ is(el.innerHTML, '<span>c</span>')
120
+ params.a = null
121
+ is(el.innerHTML, '<span>c</span>')
121
122
  })
122
123
 
123
124
  test('conditions: short with insertions', async () => {
124
125
  let el = h`<p>
125
126
  <span :if="a==1" :text="'1:'+a"></span>
126
- <span :else-if="a==2" :text="'2:'+a"></span>
127
+ <span :else :if="a==2" :text="'2:'+a"></span>
127
128
  <span :else :text="a"></span>
128
129
  </p>`
129
130
 
130
131
  const params = sprae(el, { a: 1 })
131
132
 
132
- is(el.innerHTML, '<span class="∴text ∴if">1:1</span>')
133
+ is(el.innerHTML, '<span>1:1</span>')
133
134
  params.a = 2
134
- is(el.innerHTML, '<span class="∴text ∴else-if">2:2</span>')
135
+ is(el.innerHTML, '<span>2:2</span>')
135
136
  params.a = 3
136
- is(el.innerHTML, '<span class="∴text ∴else">3</span>')
137
+ is(el.innerHTML, '<span>3</span>')
137
138
  params.a = 4
138
- is(el.innerHTML, '<span class="∴text ∴else">4</span>')
139
+ is(el.innerHTML, '<span>4</span>')
139
140
 
140
141
  params.a = 1
141
- is(el.innerHTML, '<span class="∴text ∴if">1:1</span>')
142
+ is(el.innerHTML, '<span>1:1</span>')
142
143
  params.a = 4
143
- is(el.innerHTML, '<span class="∴text ∴else">4</span>')
144
+ is(el.innerHTML, '<span>4</span>')
144
145
 
145
- delete params.a
146
+ params.a = null
146
147
  })
147
148
 
148
149
  test('conditions: reactive values', async () => {
149
150
  let el = h`<p>
150
151
  <span :if="a==1" :text="'1:'+a"></span>
151
- <span :else-if="a==2" :text="'2:'+a"></span>
152
+ <span :else :if="a==2" :text="'2:'+a"></span>
152
153
  <span :else :text="a"></span>
153
154
  </p>`
154
155
 
155
156
  const a = signal(1)
156
157
  sprae(el, { a })
157
158
 
158
- is(el.innerHTML, '<span class="∴text ∴if">1:1</span>')
159
+ is(el.innerHTML, '<span>1:1</span>')
159
160
  a.value = 2
160
- is(el.innerHTML, '<span class="∴text ∴else-if">2:2</span>')
161
+ is(el.innerHTML, '<span>2:2</span>')
161
162
  a.value = 3
162
- is(el.innerHTML, '<span class="∴text ∴else">3</span>')
163
+ is(el.innerHTML, '<span>3</span>')
163
164
  a.value = 4
164
- is(el.innerHTML, '<span class="∴text ∴else">4</span>')
165
+ is(el.innerHTML, '<span>4</span>')
165
166
 
166
167
  a.value = 1
167
- is(el.innerHTML, '<span class="∴text ∴if">1:1</span>')
168
+ is(el.innerHTML, '<span>1:1</span>')
168
169
  a.value = 4
169
- is(el.innerHTML, '<span class="∴text ∴else">4</span>')
170
+ is(el.innerHTML, '<span>4</span>')
170
171
  })
171
172
 
172
173
 
@@ -179,12 +180,34 @@ test('each: base', async () => {
179
180
  const params = sprae(el, { b: [] })
180
181
 
181
182
  is(el.innerHTML, '')
183
+ console.log('set 1,2')
182
184
  params.b = [1,2]
183
- is(el.innerHTML, '<span class="∴each ∴text">1</span><span class="∴each ∴text">2</span>')
185
+ is(el.innerHTML, '<span>1</span><span>2</span>')
184
186
  params.b = []
185
187
  is(el.innerHTML, '')
186
- delete params.b
188
+ params.b = null
189
+ is(el.innerHTML, '')
190
+ })
191
+
192
+ test('each: loop within loop', async () => {
193
+ let el = h`<p>
194
+ <x :each="b in c"><y :each="a in b" :text="a"></y></x>
195
+ </p>`
196
+
197
+ const params = sprae(el, { c: [[1,2], [3,4]] })
198
+
199
+ is(el.innerHTML, '<x><y>1</y><y>2</y></x><x><y>3</y><y>4</y></x>')
200
+ // console.log('set 1,2')
201
+ params.c = [[5,6], [3,4]]
202
+ is(el.innerHTML, '<x><y>5</y><y>6</y></x><x><y>3</y><y>4</y></x>')
203
+ // params.c[1] = [7,8]
204
+ params.c = [params.c[0], [7,8]]
205
+ is(el.innerHTML, '<x><y>5</y><y>6</y></x><x><y>7</y><y>8</y></x>')
206
+ // is(el.innerHTML, '<span>1</span><span>2</span>')
207
+ params.c = []
187
208
  is(el.innerHTML, '')
209
+ // params.b = null
210
+ // is(el.innerHTML, '')
188
211
  })
189
212
 
190
213
  test('each: reactive values', async () => {
@@ -197,10 +220,10 @@ test('each: reactive values', async () => {
197
220
 
198
221
  is(el.innerHTML, '')
199
222
  b.value = [1,2]
200
- is(el.innerHTML, '<span class="∴each ∴text">1</span><span class="∴each ∴text">2</span>')
223
+ is(el.innerHTML, '<span>1</span><span>2</span>')
201
224
  b.value = []
202
225
  is(el.innerHTML, '')
203
- delete params.b
226
+ params.b = null
204
227
  is(el.innerHTML, '')
205
228
  })
206
229
 
@@ -209,28 +232,48 @@ test('each: loop with condition', async () => {
209
232
  <span :each="a in b" :text="a" :if="c"></span>
210
233
  </p>`
211
234
 
212
- const params = sprae(el, { b: [1,2], c:false })
235
+ const params = sprae(el, { b: [1,2], c: false })
213
236
 
214
237
  is(el.innerHTML, '')
215
238
  params.c = true
216
- is(el.innerHTML, '<span class="∴each ∴text ∴if">1</span><span class="∴each ∴text ∴if">2</span>')
239
+ is(el.innerHTML, '<span>1</span><span>2</span>')
240
+ params.b = [1]
241
+ is(el.innerHTML, '<span>1</span>')
242
+ params.b = null
243
+ is(el.innerHTML, '')
244
+ })
245
+
246
+ test('each: condition with loop', async () => {
247
+ let el = h`<p>
248
+ <span :if="c" :each="a in b" :text="a"></span>
249
+ <span :else :text="c"></span>
250
+ </p>`
251
+
252
+ const params = sprae(el, { b: [1,2], c: false })
253
+
254
+ is(el.innerHTML, '<span>false</span>')
255
+ params.c = true
256
+ is(el.innerHTML, '<span>1</span><span>2</span>')
217
257
  params.b = [1]
218
- is(el.innerHTML, '<span class="∴each ∴text ∴if">1</span>')
219
- delete params.b
258
+ is(el.innerHTML, '<span>1</span>')
259
+ params.b = null
220
260
  is(el.innerHTML, '')
261
+ console.log('c=false')
262
+ params.c = false
263
+ is(el.innerHTML, '<span>false</span>')
221
264
  })
222
265
 
223
266
  test('each: loop within condition', async () => {
224
267
  let el = h`<p>
225
268
  <x :if="a==1"><y :each="i in a" :text="i"></y></x>
226
- <x :else-if="a==2"><y :each="i in a" :text="-i"></y></x>
269
+ <x :else :if="a==2"><y :each="i in a" :text="-i"></y></x>
227
270
  </p>`
228
271
 
229
272
  const params = sprae(el, { a: 1 })
230
273
 
231
- is(el.innerHTML, '<x class="∴if"><y class="∴each ∴text">1</y></x>')
274
+ is(el.innerHTML, '<x><y>1</y></x>')
232
275
  params.a = 2
233
- is(el.innerHTML, '<x class="∴else-if"><y class="∴each ∴text">-1</y><y class="∴each ∴text">-2</y></x>')
276
+ is(el.innerHTML, '<x><y>-1</y><y>-2</y></x>')
234
277
  params.a = 0
235
278
  is(el.innerHTML, '')
236
279
  })
@@ -239,17 +282,17 @@ test('each: condition within loop', async () => {
239
282
  let el = h`<p>
240
283
  <x :each="a in b">
241
284
  <y :if="a==1" :text="'1:'+a"></y>
242
- <y :else-if="a==2" :text="'2:'+a"></y>
285
+ <y :else :if="a==2" :text="'2:'+a"></y>
243
286
  <y :else :text="a"></y>
244
287
  </x>
245
288
  </p>`
246
289
 
247
290
  const params = sprae(el, { b: [1,2,3] })
248
291
 
249
- is(el.innerHTML, '<x class="∴each"><y class="∴text ∴if">1:1</y></x><x class="∴each"><y class="∴text ∴else-if">2:2</y></x><x class="∴each"><y class="∴text ∴else">3</y></x>')
292
+ is(el.innerHTML, '<x><y>1:1</y></x><x><y>2:2</y></x><x><y>3</y></x>')
250
293
  params.b = [2]
251
- is(el.innerHTML, '<x class="∴each"><y class="∴text ∴else-if">2:2</y></x>')
252
- delete params.b
294
+ is(el.innerHTML, '<x><y>2:2</y></x>')
295
+ params.b = null
253
296
  is(el.innerHTML, '')
254
297
  })
255
298
 
@@ -258,7 +301,7 @@ test('on: base', () => {
258
301
  let log = signal([])
259
302
  let params = sprae(el, {x(){log.value.push('x')}, log})
260
303
 
261
- is(el.outerHTML, `<div class="∴on"></div>`);
304
+ is(el.outerHTML, `<div></div>`);
262
305
  el.dispatchEvent(new window.Event('click'));
263
306
  is(log.value, ['click'])
264
307
  el.dispatchEvent(new window.Event('x'));
@@ -268,7 +311,7 @@ test('on: base', () => {
268
311
  el.dispatchEvent(new window.Event('x'));
269
312
  is(log.value, ['click','x','xx']);
270
313
 
271
- delete params.x;
314
+ params.x = null;
272
315
  el.dispatchEvent(new window.Event('x'));
273
316
  is(log.value, ['click','x','xx']);
274
317
  })
@@ -277,27 +320,61 @@ test('with: inline', () => {
277
320
  let el = h`<x :with="{foo:'bar', baz}"><y :text="foo + baz"></y></x>`
278
321
  let state = sprae(el, {baz: 'qux'})
279
322
  // FIXME: this doesn't inherit root scope baz property and instead uses hard-initialized one
280
- is(el.innerHTML, `<y class="∴text">barqux</y>`)
323
+ is(el.innerHTML, `<y>barqux</y>`)
281
324
  state.baz = 'quux'
282
- is(el.innerHTML, `<y class="∴text">barquux</y>`)
325
+ is(el.innerHTML, `<y>barquux</y>`)
326
+ })
327
+ test('with: inline reactive', () => {
328
+ let el = h`<x :with="{foo:'bar', baz}"><y :text="foo + baz"></y></x>`
329
+ let baz = signal('qux')
330
+ let state = sprae(el, {baz})
331
+ // FIXME: this doesn't inherit root scope baz property and instead uses hard-initialized one
332
+ is(el.innerHTML, `<y>barqux</y>`)
333
+ baz.value = 'quux'
334
+ is(el.innerHTML, `<y>barquux</y>`)
283
335
  })
284
336
  test('with: data', () => {
285
337
  let el = h`<x :with="x"><y :text="foo"></y></x>`
286
- let [state, update] = sprae(el, {x:{foo:'bar'}})
287
- is(el.innerHTML, `<y class="∴text">bar</y>`)
288
- update({x:{foo:'baz'}})
289
- is(el.innerHTML, `<y class="∴text">baz</y>`)
338
+ let state = sprae(el, {x:{foo:'bar'}})
339
+ is(el.innerHTML, `<y>bar</y>`)
340
+ console.log('update')
341
+ Object.assign(state, {x:{foo:'baz'}})
342
+ is(el.innerHTML, `<y>baz</y>`)
290
343
  })
291
- test('with: inheritance', () => {
344
+ test('with: transparency', () => {
292
345
  // NOTE: y:text initializes through directive, not through parent
293
346
  // therefore by default :text uses parent's state, not defined by element itself
294
347
  let el = h`<x :with="{foo:'foo'}"><y :with="b" :text="foo+bar"></y></x>`
295
- sprae(el, {b:{bar:'bar'}})
296
- is(el.innerHTML, `<y class="∴with ∴text">foobar</y>`)
348
+ let params = sprae(el, {b:{bar:'bar'}})
349
+ is(el.innerHTML, `<y>foobar</y>`)
350
+ params.b.bar = 'baz'
351
+ is(el.innerHTML, `<y>foobaz</y>`)
297
352
  })
298
- test('with: reactive inheritance', () => {
353
+ test('with: reactive transparency', () => {
299
354
  let el = h`<x :with="{foo:1}"><y :with="b.c" :text="foo+bar"></y></x>`
300
355
  const bar = signal('2')
301
356
  sprae(el, {b:{c:{bar}}})
302
- is(el.innerHTML, `<y class="∴with ∴text">12</y>`)
357
+ is(el.innerHTML, `<y>12</y>`)
358
+ bar.value = '3'
359
+ is(el.innerHTML, `<y>13</y>`)
360
+ })
361
+ test('with: writes to state', () => {
362
+ let a = h`<x :with="{a:1}"><y :on="{x(){a++}}" :text="a"></y></x>`
363
+ sprae(a)
364
+ is(a.innerHTML, `<y>1</y>`)
365
+ a.firstChild.dispatchEvent(new window.Event('x'))
366
+ is(a.innerHTML, `<y>2</y>`)
367
+ a.firstChild.dispatchEvent(new window.Event('x'))
368
+ is(a.innerHTML, `<y>3</y>`)
369
+ })
370
+
371
+ test('reactives', async () => {
372
+ let a = new Promise((ok) => setTimeout(() => ok(2), 10))
373
+
374
+ let el = h`<x :text="a">1</x>`
375
+ sprae(el, {a})
376
+ is(el.outerHTML, `<x></x>`)
377
+
378
+ await time(20)
379
+ is(el.outerHTML, `<x>2</x>`)
303
380
  })
@@ -1,10 +0,0 @@
1
- import { directive, parseExpr } from '../core.js'
2
- import { prop } from 'element-props'
3
-
4
- directive(':aria', (el, expr) => {
5
- let evaluate = parseExpr(expr);
6
- return (state) => {
7
- let value = evaluate(state);
8
- for (let key in value) prop(el, 'aria'+key[0].toUpperCase()+key.slice(1), value[key]);
9
- }
10
- })
@@ -1,15 +0,0 @@
1
- // common directives just set/map value as is
2
- import { directive, parseExpr } from '../core.js'
3
- import {prop} from 'element-props'
4
-
5
- common(`id`), common(`name`), common(`for`), common(`type`), common(`hidden`), common(`disabled`), common(`href`), common(`src`), common(`style`), common(`class`)
6
-
7
- function common(name) {
8
- directive(':'+name, (el,expr) => {
9
- let evaluate = parseExpr(expr)
10
- return state => {
11
- let value = evaluate(state);
12
- prop(el, name, value)
13
- }
14
- })
15
- }
@@ -1,10 +0,0 @@
1
- import { directive, parseExpr } from '../core.js'
2
- import { prop } from 'element-props'
3
-
4
- directive(':data', (el, expr) => {
5
- let evaluate = parseExpr(expr);
6
- return (state) => {
7
- let value = evaluate(state);
8
- for (let key in value) el.dataset[key] = value[key];
9
- }
10
- })
@@ -1,31 +0,0 @@
1
- import { directive, parseExpr } from '../core.js'
2
-
3
- directive(':if', (el, expr) => {
4
- let cur = el, els = [el], clauses = [parseExpr(expr)], holder = new Text
5
-
6
- // collect clauses
7
- while (cur = el.nextElementSibling) {
8
- if (expr = cur.getAttribute(':else-if')) {
9
- cur.removeAttribute(':else-if');
10
- cur.classList.add('∴else-if')
11
- cur.remove();
12
- els.push(cur); clauses.push(parseExpr(expr));
13
- continue
14
- }
15
- if (cur.hasAttribute(':else')) {
16
- cur.removeAttribute(':else');
17
- cur.classList.add('∴else')
18
- cur.remove();
19
- els.push(cur); clauses.push(() => 1);
20
- }
21
- break;
22
- }
23
-
24
- cur = els[0]
25
-
26
- return state => {
27
- let idx = clauses.findIndex(match => match(state));
28
- if (idx >= 0) cur.replaceWith(cur = els[idx]);
29
- else cur.replaceWith(cur = holder);
30
- }
31
- })
@@ -1,11 +0,0 @@
1
- // order defines precedence
2
- import './with.js'
3
- import './each.js'
4
- import './text.js'
5
- import './if.js' // if must go last, after other directives are initialized, since it removes :else, :else-if from tree
6
- import './common.js'
7
- import './prop.js'
8
- import './data.js'
9
- import './aria.js'
10
- import './value.js'
11
- import './on.js'
@@ -1,12 +0,0 @@
1
- import { directive, parseExpr } from '../core.js'
2
-
3
- directive(':on', (el, expr) => {
4
- let evaluate = parseExpr(expr);
5
- let listeners = {}
6
- return (state) => {
7
- for (let evt in listeners) el.removeEventListener(evt, listeners[evt]);
8
- listeners = evaluate(state);
9
- for (let evt in listeners) el.addEventListener(evt, listeners[evt]);
10
- }
11
- })
12
-
@@ -1,10 +0,0 @@
1
- import { directive, parseExpr } from '../core.js'
2
- import { prop } from 'element-props'
3
-
4
- directive(':prop', (el, expr) => {
5
- let evaluate = parseExpr(expr);
6
- return (state) => {
7
- let value = evaluate(state);
8
- for (let key in value) prop(el, key, value[key]);
9
- }
10
- })
@@ -1,10 +0,0 @@
1
- import { directive, parseExpr } from '../core.js'
2
-
3
- directive(':text', (el, expr) => {
4
- let evaluate = parseExpr(expr);
5
- return (state) => {
6
- let value = evaluate(state);
7
- el.textContent = value == null ? '' : value;
8
- }
9
- })
10
-
@@ -1,26 +0,0 @@
1
- import { input, prop } from "element-props";
2
- import { directive, parseExpr } from '../core.js';
3
-
4
- // connect expr to element value
5
- directive(':value', (el, expr) => {
6
- let evaluateGet = parseExpr(expr);
7
- let [get, set] = input(el);
8
- let evaluateSet = parseSetter(expr);
9
- let curState, onchange = e => evaluateSet(curState, get(el));
10
- el.addEventListener('input', onchange);
11
- el.addEventListener('change', onchange);
12
- return (state) => {
13
- let value = evaluateGet(curState = state);
14
- prop(el, 'value', value)
15
- set(value);
16
- }
17
- })
18
-
19
- const memo = {}
20
- function parseSetter(expr) {
21
- if (memo[expr]) return memo[expr]
22
- return memo[expr] = new Function(
23
- ['scope', 'value'],
24
- `with (scope) { ${expr} = value };`
25
- )
26
- }
@@ -1,21 +0,0 @@
1
- import sprae, { directive, parseExpr } from '../core.js'
2
-
3
- directive(':with', (el, expr, rootValues) => {
4
- let evaluate = parseExpr(expr);
5
-
6
- // it subsprays with shadowed values
7
- // rootValues get updated by parent directives
8
- // subscope doesn't contain reactive values
9
- let subscope = Object.create(rootValues)
10
-
11
- // FIXME: wonder if we better pass initial state rather than values snapshot, to let subtree subscribe to more complete set
12
- // FIXME: likely initial set can be reactive itself then
13
- Object.assign(subscope, evaluate(rootValues))
14
- let [subvalues, subupdate] = sprae(el, subscope)
15
-
16
- return (values) => {
17
- let withValues = evaluate(values);
18
- subupdate(withValues)
19
- }
20
- })
21
-