@wrnrlr/prelude 0.2.1 → 0.2.3

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/deno.jsonc CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrnrlr/prelude",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "exports": "./src/mod.ts",
5
5
  "compilerOptions": {
6
6
  "strict": true,
@@ -0,0 +1,53 @@
1
+ <!DOCTYPE html>
2
+ <title>Todo</title>
3
+
4
+ <script type="module">
5
+
6
+ import {h,signal,effect,batch,wrap,render,List} from '../src/mod.ts'
7
+
8
+ function Checkbox(props) {
9
+ // effect(()=>console.log('checkbox value ', props.value))
10
+ return h('input',{
11
+ type: 'checkbox',
12
+ checked: props.value,
13
+ onInput: e => props.value(e.target.checked)
14
+ })
15
+ }
16
+
17
+ function App() {
18
+ const todos = signal([true,false])
19
+ // const obj = signal({todos:[true]})
20
+ // const todos = wrap(obj,'todos')
21
+ const first = wrap(todos, 0)
22
+ const removeItem = i => {
23
+ // console.log('remove', i)
24
+ // batch(()=>{
25
+ const old = todos()
26
+ todos(old.toSpliced(i(),1))
27
+ // })
28
+ }
29
+ return [
30
+ h('button', {onClick:(e)=>{const old = todos(); todos([false, ...old])}}, '+'),
31
+ h('ol', h(List, {each:()=>todos}, (value, i) =>
32
+ h('li', [
33
+ h(Checkbox, { value: ()=>value }),
34
+ h('button', { onClick: e=>removeItem(i) }, '\u2715')
35
+ ])
36
+ )),
37
+ h('button', {onClick:(e)=>{const old = todos(); todos([...old, true])}}, '+'),
38
+ h(Checkbox, { value:()=>first }),
39
+ h('pre.hello',()=>'todos: '+JSON.stringify(todos(),undefined,2))
40
+ ]
41
+ }
42
+
43
+ render(App, document.body)
44
+
45
+ </script>
46
+
47
+ <style>
48
+ html {background-color:lightgray}
49
+ ul {margin:0;padding:0}
50
+ /* ul,li {list-style-type: none} */
51
+ input {border-width: 0 0 1px 0; margin:0.25em}
52
+ li>button {border:none; background:none}
53
+ </style>
@@ -1,38 +1,8 @@
1
1
  <!DOCTYPE html>
2
- <title>Todo</title>
2
+ <title>Examples</title>
3
3
 
4
- <script type="module">
5
-
6
- import {h,signal,effect,batch,wrap,render,List} from '../src/mod.ts'
7
-
8
- function Checkbox(props) {
9
- // effect(()=>console.log('checkbox value ', props.value))
10
- return h('input',{
11
- type: 'checkbox',
12
- checked: props.value,
13
- onInput: e => props.value(e.target.checked)
14
- })
15
- }
16
-
17
- function App() {
18
- // const todos = signal([false])
19
- const obj = signal({todos:[false]})
20
- const todos = wrap(obj,'todos')
21
- const first = wrap(todos, 0)
22
- return [
23
- h('button', {onClick:(e)=>{const old = todos(); todos([...old, false])}}, '+'),
24
- h('ol', h(List, {each:()=>todos}, (value, i) =>
25
- // (console.log('value',value),h('li', h(Checkbox, { value:()=>value })))
26
- h('li', h(Checkbox, { value:()=>value }))
27
- )),
28
- h(Checkbox, { value:()=>first }),
29
- h('pre.hello',()=>'todos: '+JSON.stringify(todos(),undefined,2))
30
- ]
31
- }
32
-
33
- render(App, document.body)
34
-
35
- </script>
4
+ <a href="checkbox.html">Checkboxes</a>
5
+ <a href="todo.html">Todo</a>
36
6
 
37
7
  <style>
38
8
  html {background-color:lightgray}
@@ -0,0 +1,77 @@
1
+ <!DOCTYPE html>
2
+ <title>Todo</title>
3
+
4
+ <script type="module">
5
+
6
+ import {h,signal,effect,batch,wrap,render,List} from '../src/mod.ts'
7
+
8
+ const data = [
9
+ // {description:'Buy groceries',done:false},
10
+ {description:'Clean car',done:false},
11
+ {description:'File taxes',done:true},
12
+ ]
13
+
14
+ function Input(props) {
15
+ return h('input',{
16
+ value:props.value,
17
+ onInput:e => props.value(e.target.value),
18
+ tabindex:props.tabindex
19
+ })
20
+ }
21
+
22
+ function Checkbox(props) {
23
+ return h('input',{
24
+ type:'checkbox',
25
+ checked:props.value,
26
+ onInput:e => props.value(e.target.checked)
27
+ })
28
+ }
29
+
30
+ function TodoItem(props) {
31
+ // const description = wrap(props.value,'description')
32
+ const done = wrap(props.value,'done')
33
+ return h('li', [
34
+ h(Checkbox,{value:()=>done}),
35
+ // h(Input,{value:()=>description}),
36
+ h('button',{onClick:props.onDelete},'\u2715')
37
+ ])
38
+ }
39
+
40
+ function App() {
41
+ const name = signal('')
42
+ const todos = signal(data)
43
+ function onSubmit(e) {
44
+ e.preventDefault()
45
+ todos(v => v.toSpliced(v.length, 0, {description:name(), done:false}))
46
+ name('')
47
+ }
48
+ const removeItem = i => e => {
49
+ batch(()=>{
50
+ const old = todos()
51
+ console.log('old',old, i)
52
+ todos(old.toSpliced(i,1))
53
+ })
54
+ }
55
+ return [
56
+ h('h3','Todo'),
57
+ h('ul',[h(List, {each:()=>todos}, (value,i) =>
58
+ h(TodoItem, {
59
+ value:()=>value,
60
+ onDelete: removeItem(i())
61
+ })
62
+ )]),
63
+ h('form',{onSubmit},[h(Input,{value:()=>name,tabindex:1})]),
64
+ h('pre.hello',()=>'todos: '+JSON.stringify(todos(),undefined,2))
65
+ ]
66
+ }
67
+
68
+ render(App, document.body)
69
+
70
+ </script>
71
+
72
+ <style>
73
+ ul {margin:0;padding:0}
74
+ ul,li {list-style-type: none}
75
+ input {border-width: 0 0 1px 0; margin:0.25em}
76
+ li>button {border:none; background:none}
77
+ </style>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wrnrlr/prelude",
3
3
  "type": "module",
4
- "version": "0.2.1",
4
+ "version": "0.2.3",
5
5
  "author": "Werner Laurensse",
6
6
  "description": "A signal based frontend library with fine-grained reactivity",
7
7
  "main": "./src/mod.ts",
@@ -49,24 +49,24 @@ type ItemHolder<T> = {
49
49
  disposer: ()=>void
50
50
  }
51
51
 
52
- function listArray<T, U extends Mountable>(
52
+ export function listArray<T, U extends Mountable>(
53
53
  list: Getter<T[]>,
54
54
  mapFn: (v: Getter<T>, i: Getter<number>) => U,
55
55
  options: { fallback?: Mountable }
56
56
  ): () => U[]
57
- function listArray<T, U extends Mountable>(
57
+ export function listArray<T, U extends Mountable>(
58
58
  list: Signal<T[]>,
59
59
  mapFn: (v: Signal<T>, i: Getter<number>) => U,
60
60
  options: { fallback?: Mountable }
61
61
  ): () => U[]
62
- function listArray<T, U extends Mountable>(
62
+ export function listArray<T, U extends Mountable>(
63
63
  list: Getter<T[]> | Signal<T[]>,
64
64
  mapFn: (v: Signal<T>, i: Getter<number>) => U,
65
65
  options: { fallback?: Mountable } = {}
66
66
  ): () => U[] {
67
67
  const items: ListItem<T>[] = [];
68
68
  let mapped: U[] = [],
69
- unusedItems: number,
69
+ // unusedItems: number,
70
70
  i: number,
71
71
  j: number,
72
72
  item: ListItem<T>,
@@ -92,7 +92,7 @@ function listArray<T, U extends Mountable>(
92
92
  }
93
93
 
94
94
  const temp: U[] = new Array(newItems.length); // new mapped array
95
- unusedItems = items.length;
95
+ let unusedItems = items.length;
96
96
 
97
97
  // 1) no change when values & indexes match
98
98
  for (j = unusedItems - 1; j >= 0; --j) {
@@ -186,8 +186,7 @@ function listArray<T, U extends Mountable>(
186
186
  return (mapped = temp);
187
187
  })
188
188
  }
189
- // const indexes = cb.length > 1 ? [] : null;
190
- function newValueGetter(_:unknown) { return newValue }
189
+ function newValueGetter(a:unknown) { console.log({a}); return newValue }
191
190
  function changeBoth() {
192
191
  item!.index = i!
193
192
  item!.indexSetter?.(i)
@@ -195,25 +194,26 @@ function listArray<T, U extends Mountable>(
195
194
  item!.valueSetter?.(newValueGetter)
196
195
  }
197
196
  function mapper(disposer: ()=>void) {
198
- const I = i
199
- const t = {value: newValue, index: I, disposer}
197
+ const t = {value: newValue, index: i, disposer}
200
198
  items.push(t)
201
- const sI = () => { t.indexSetter = I; return signal(I) }
199
+ let sI = (...a) => {
200
+ sI = signal(t.index);
201
+ t.indexSetter = sI;
202
+ return sI(...a)
203
+ }
202
204
  let sV = (...a) => {
203
- const k = I
204
205
  sV = (...a) => {
205
206
  if (a.length===0) {
206
- const bk = list()[k]
207
- return bk
207
+ return list()[sI()]
208
208
  } else {
209
- const b = untrack(list)
210
- return list(b.toSpliced(k, 1, a[0])).at(k)
209
+ const k = untrack(sI)
210
+ return list(b => b.toSpliced(k, 1, typeof a[0] === 'function' ? a[0]() : a[0])).at(k)
211
211
  }
212
212
  }
213
213
  t.valueSetter = sV
214
214
  return sV(...a)
215
215
  }
216
- return mapFn(sV, () => sI())
216
+ return mapFn(sV, sI)
217
217
  }
218
218
  }
219
219
 
package/src/mod.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type {Getter,Setter,Fn,EqualsFn,ErrorFn,RootFn,UpdateFn} from './reactive.ts'
1
+ export type {Getter,Setter,Fn,EqualsFn,ErrorFn,RootFn,UpdateFn,Signal} from './reactive.ts'
2
2
  export {signal,effect,untrack,batch,memo,root,wrap,fuse,onMount,onCleanup} from './reactive.ts'
3
3
  export {nbsp} from './constants.ts'
4
4
  export {Show,List} from './controlflow.ts'
package/src/runtime.ts CHANGED
@@ -338,7 +338,7 @@ function setAttribute(node: Element, name: string, value?: string): undefined {
338
338
  value===undefined || value===null ? node.removeAttribute(name) : node.setAttribute(name, value)
339
339
  }
340
340
 
341
- function setAttributeNS(node:Node, ns:string, name:string, value?:string):any {
341
+ function setAttributeNS(node:Node, ns:string, name:string, value?:string):void {
342
342
  value ? node.setAttributeNS(ns, name, value) : node.removeAttributeNS(ns, name)
343
343
  }
344
344
 
package/test/list.js ADDED
@@ -0,0 +1,34 @@
1
+ import {assertEquals,assert} from '@std/assert'
2
+ import {describe,it} from '@std/testing/bdd'
3
+
4
+ import { signal } from '../src/reactive.ts'
5
+ import { listArray } from '../src/controlflow.ts'
6
+
7
+ // Deno.test('listArray applies list to mapFn', ()=>{
8
+ // const l = signal([0,1,2])
9
+ // const r = listArray(l, (e,i)=>({e:e(), i:i()}))
10
+ // assertEquals(r(), [{e:0,i:0}, {e:1,i:1}, {e:2,i:2}])
11
+ // })
12
+
13
+ // Deno.test('listArray append element', ()=>{
14
+ // const l = signal([0,1,2])
15
+ // const r = listArray(l, (e,i)=>({e:e(), i:i()}))
16
+ // assert(r(), [{e:0,i:0}, {e:1,i:1}, {e:2,i:2}])
17
+ // l(l => [...l,3])
18
+ // assertEquals(r(), [{e:0,i:0}, {e:1,i:1}, {e:2,i:2}, {e:3,i:3}])
19
+ // })
20
+
21
+ // Deno.test('listArray prepend element', ()=>{
22
+ // const l = signal([0,1,2])
23
+ // const r = listArray(l, (e,i)=>({e:e(), i:i()}))
24
+ // r()
25
+ // l(l => [3, ...l])
26
+ // assertEquals(r(), [{e:3,i:0}, {e:0,i:1}, {e:1,i:2}, {e:2,i:3}])
27
+ // })
28
+ const l1 = signal(['a'])
29
+ const r1 = listArray(l1, (e,i)=>([i(),e()]))
30
+ // r1()
31
+ l1(l => ['x', ...l])
32
+ // l1(l => [...l, 'x', 'y'])
33
+ console.log(JSON.stringify(r1()))
34
+ // assertEquals(r(), )