@wrnrlr/prelude 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.github/workflows/publish.yml +12 -11
  2. package/{deno.json → deno.jsonc} +10 -9
  3. package/example/index.html +43 -0
  4. package/package.json +6 -2
  5. package/src/constants.ts +110 -52
  6. package/src/controlflow.ts +140 -92
  7. package/src/hyperscript.ts +81 -106
  8. package/src/mod.ts +11 -19
  9. package/src/reactive.ts +29 -17
  10. package/src/runtime.ts +126 -66
  11. package/test/hyperscript.js +7 -6
  12. package/test/reactive.js +22 -2
  13. package/test/types.ts +44 -0
  14. package/src/components.js +0 -20
  15. package/src/ui/accordion.ts +0 -8
  16. package/src/ui/button.ts +0 -9
  17. package/src/ui/canvas.ts +0 -8
  18. package/src/ui/date.ts +0 -8
  19. package/src/ui/dialog.ts +0 -12
  20. package/src/ui/filter.ts +0 -8
  21. package/src/ui/form.ts +0 -7
  22. package/src/ui/h.ts +0 -48
  23. package/src/ui/image.ts +0 -5
  24. package/src/ui/input.ts +0 -49
  25. package/src/ui/mod.ts +0 -12
  26. package/src/ui/multiselect.ts +0 -42
  27. package/src/ui/option.ts +0 -1
  28. package/src/ui/select.ts +0 -28
  29. package/src/ui/tab.ts +0 -7
  30. package/src/ui/table.ts +0 -9
  31. package/src/ui/upload.ts +0 -7
  32. package/www/assets/css/presets.css +0 -504
  33. package/www/assets/css/style.css +0 -90
  34. package/www/demo.html +0 -28
  35. package/www/index.html +0 -211
  36. package/www/playground.html +0 -184
  37. package/www/public/banner.svg +0 -6
  38. package/www/public/example/admin.html +0 -88
  39. package/www/public/example/counter.html +0 -24
  40. package/www/public/example/greeting.html +0 -25
  41. package/www/public/example/select.html +0 -27
  42. package/www/public/example/show.html +0 -18
  43. package/www/public/example/todo.html +0 -70
  44. package/www/public/fonts/fab.ttf +0 -0
  45. package/www/public/fonts/fab.woff2 +0 -0
  46. package/www/public/fonts/far.ttf +0 -0
  47. package/www/public/fonts/far.woff2 +0 -0
  48. package/www/public/fonts/fas.ttf +0 -0
  49. package/www/public/fonts/fas.woff2 +0 -0
  50. package/www/public/logo.svg +0 -16
  51. package/www/typedoc.json +0 -13
  52. package/www/ui.html +0 -49
  53. package/www/vite.config.js +0 -106
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck:
2
2
  import type { Child } from './hyperscript.ts'
3
- import {signal,untrack,batch,memo,root,type Signal} from './reactive.ts'
3
+ import {signal,untrack,batch,memo,root,onCleanup,type Signal, type Setter, type Mountable} from './reactive.ts'
4
4
 
5
5
  export type ShowProps<T> = {
6
6
  when: T,
@@ -12,7 +12,7 @@ export type ShowProps<T> = {
12
12
  Show children if `when` prop is true, otherwise show `fallback`.
13
13
  @group Components
14
14
  */
15
- export function Show<T>(props:any) {
15
+ export function Show<T>(props:ShowProps) {
16
16
  const condition = memo(()=>props.when)
17
17
  return memo(()=>{
18
18
  const c = condition()
@@ -24,152 +24,200 @@ export function Show<T>(props:any) {
24
24
  })
25
25
  }
26
26
 
27
- type ItemHolder = {
28
- index:number,
29
- indexSetter?:any,
30
- value:unknown,
31
- valueSetter:any,
32
- disposer: any
33
- }
34
-
35
- export type ListProps<T> = {
36
- when: T,
37
- each: any,
38
- children: Child | ((a:()=>T)=>void),
39
- fallback: unknown
27
+ export type ListProps<T, U extends Mountable, F = Getter | Signal> = {
28
+ each: F<T[]>,
29
+ children: (item: F<T>, index: F<number>) => U,
30
+ fallback?: Mountable
40
31
  }
41
32
 
42
33
  /**
43
34
  List
44
35
  @group Components
45
36
  */
46
- export function List<T>(props:any) {
47
- const fallback = "fallback" in props && { fallback: () => props.fallback }
48
- const list = props.each
49
- const cb:any = (props.children as any)?.call ? props.children : (v:any)=>v
50
- let items:ItemHolder[] = [],
51
- item: undefined|ItemHolder,
52
- // unusedItems,
53
- i: undefined|number,
54
- newValue: undefined|number,
55
- mapped: number[],
37
+ export function List<T>(
38
+ props: ListProps<T>
39
+ ) {
40
+ const fallback = "fallback" in props && { fallback: () => props.fallback };
41
+ return memo(listArray<T>(props.each, props.children, fallback || undefined))
42
+ }
43
+
44
+ type ItemHolder<T> = {
45
+ index: number,
46
+ indexSetter?: Getter<number>,
47
+ value: T,
48
+ valueSetter?: Setter<T>,
49
+ disposer: ()=>void
50
+ }
51
+
52
+ function listArray<T, U extends Mountable>(
53
+ list: Getter<T[]>,
54
+ mapFn: (v: Getter<T>, i: Getter<number>) => U,
55
+ options: { fallback?: Mountable }
56
+ ): () => U[]
57
+ function listArray<T, U extends Mountable>(
58
+ list: Signal<T[]>,
59
+ mapFn: (v: Signal<T>, i: Getter<number>) => U,
60
+ options: { fallback?: Mountable }
61
+ ): () => U[]
62
+ function listArray<T, U extends Mountable>(
63
+ list: Getter<T[]> | Signal<T[]>,
64
+ mapFn: (v: Signal<T>, i: Getter<number>) => U,
65
+ options: { fallback?: Mountable } = {}
66
+ ): () => U[] {
67
+ const items: ListItem<T>[] = [];
68
+ let mapped: U[] = [],
69
+ unusedItems: number,
70
+ i: number,
71
+ j: number,
72
+ item: ListItem<T>,
73
+ oldValue: T,
56
74
  oldIndex: number,
57
- oldValue: unknown
58
- const indexes = cb.length > 1 ? [] : null;
59
- function newValueGetter(_:unknown) { return newValue }
60
- function changeBoth() {
61
- item!.index = i!
62
- item!.indexSetter?.(i)
63
- item!.value = newValue!
64
- item!.valueSetter?.(newValueGetter)
65
- }
66
- function mapperWithIndexes(disposer:any) {
67
- const V = newValue, I = i, Is = signal(I), Vs = signal(V)
68
- items.push({value: newValue, index: I!, disposer, indexSetter: Is, valueSetter: Vs})
69
- return cb(
70
- (...a:any[]) => a.length ?
71
- untrack(()=>list((list:any)=>list.toSpliced(I,1,a[0])))
72
- : Vs(),
73
- ()=>Is())
74
- }
75
- function mapperWithoutIndexes(disposer:any) {
76
- const V = newValue, I = i, Vs = signal(V)
77
- items.push({value: V, index: i!, disposer, valueSetter: Vs})
78
- return cb((...a:unknown[]) => a.length ?
79
- untrack(()=>list((list:any)=>list.toSpliced(I,1,a[0])))
80
- : Vs())
81
- }
82
- const mapper = indexes ? mapperWithIndexes : mapperWithoutIndexes
83
- return memo(() => {
84
- const newItems = list.call ? list() : list
85
- // (newItems)[$TRACK]; // top level tracking
75
+ newValue: T,
76
+ fallback: U[] | undefined,
77
+ fallbackDisposer: undefined | (() => void)
78
+
79
+ onCleanup(() => {
80
+ fallbackDisposer?.()
81
+ fallbackDisposer = undefined
82
+ disposeList(items)
83
+ })
84
+
85
+ return () => {
86
+ const newItems = typeof list==='function' ? list() || [] : list;
86
87
  return untrack(() => {
87
- const temp = new Array(newItems.length) // new mapped array
88
- let unusedItems = items.length
88
+ if (newItems.length > 0 && fallbackDisposer) {
89
+ fallbackDisposer();
90
+ fallbackDisposer = undefined;
91
+ fallback = undefined;
92
+ }
93
+
94
+ const temp: U[] = new Array(newItems.length); // new mapped array
95
+ unusedItems = items.length;
89
96
 
90
97
  // 1) no change when values & indexes match
91
- for (let j = unusedItems - 1; j >= 0; --j) {
92
- item = items[j]
98
+ for (j = unusedItems - 1; j >= 0; --j) {
99
+ item = items[j]!;
93
100
  oldIndex = item.index
94
101
  if (oldIndex < newItems.length && newItems[oldIndex] === item.value) {
95
- temp[oldIndex] = mapped[oldIndex]
102
+ temp[oldIndex] = mapped[oldIndex]!
96
103
  if (--unusedItems !== j) {
97
- items[j] = items[unusedItems]
104
+ items[j] = items[unusedItems]!
98
105
  items[unusedItems] = item
99
106
  }
100
107
  }
101
108
  }
102
109
 
103
110
  // #2 prepare values matcher
104
- const matcher = new Map()
111
+ const matcher = new Map<T, number[]>()
105
112
  const matchedItems = new Uint8Array(unusedItems)
106
- for (let j = unusedItems - 1; j >= 0; --j) {
107
- oldValue = items[j].value
113
+ for (j = unusedItems - 1; j >= 0; --j) {
114
+ oldValue = items[j]!.value
108
115
  matcher.get(oldValue)?.push(j) ?? matcher.set(oldValue, [j])
109
116
  }
110
117
 
111
118
  // 2) change indexes when values match
112
119
  for (i = 0; i < newItems.length; ++i) {
113
120
  if (i in temp) continue
114
- newValue = newItems[i]
115
- const j = matcher.get(newValue)?.pop() ?? -1
121
+ newValue = newItems[i]!
122
+ j = matcher.get(newValue)?.pop() ?? -1;
116
123
  if (j >= 0) {
117
- item = items[j as number]
118
- oldIndex = item!.index
119
- temp[i] = mapped[oldIndex]
120
- item!.index = i
121
- item!.indexSetter?.(i)
122
- matchedItems[j as number] = 1
124
+ item = items[j]!
125
+ oldIndex = item.index
126
+ temp[i] = mapped[oldIndex]!
127
+ item.index = i
128
+ item.indexSetter?.(i)
129
+ matchedItems[j] = 1
123
130
  }
124
131
  }
125
132
 
126
- // 3) reduce unusedItems for matched items
127
- for (let j = matchedItems.length - 1; j >= 0; --j) {
133
+ // #2 reduce unusedItems for matched items
134
+ for (j = matchedItems.length - 1; j >= 0; --j) {
128
135
  if (matchedItems[j] && --unusedItems !== j) {
129
- item = items[j]
130
- items[j] = items[unusedItems]
136
+ item = items[j]!
137
+ items[j] = items[unusedItems]!
131
138
  items[unusedItems] = item
132
139
  }
133
140
  }
134
141
 
135
- // 4) change values when indexes match
136
- for (let j = unusedItems - 1; j >= 0; --j) {
137
- item = items[j];
138
- oldIndex = item!.index;
142
+ // 3) change values when indexes match
143
+ for (j = unusedItems - 1; j >= 0; --j) {
144
+ item = items[j]!
145
+ oldIndex = item.index;
139
146
  if (!(oldIndex in temp) && oldIndex < newItems.length) {
140
- temp[oldIndex] = mapped[oldIndex]
141
- newValue = newItems[oldIndex]
147
+ temp[oldIndex] = mapped[oldIndex]!
148
+ newValue = newItems[oldIndex]!
142
149
  item.value = newValue
143
- item.valueSetter?.(item.valueSetter)
150
+ item.valueSetter?.(newValue)
144
151
  if (--unusedItems !== j) {
145
- items[j] = items[unusedItems]
152
+ items[j] = items[unusedItems]!
146
153
  items[unusedItems] = item
147
154
  }
148
155
  }
149
156
  }
150
157
 
151
- // 5) change value & index when none matched and create new if no unused items left
158
+ // 4) change value & index when none matched
159
+ // 5) create new if no unused items left
152
160
  for (i = 0; i < newItems.length; ++i) {
153
- if (i in temp) continue
154
- newValue = newItems[i]
161
+ if (i in temp) continue;
162
+ newValue = newItems[i]!;
155
163
  if (unusedItems > 0) {
156
- item = items[--unusedItems]
157
- temp[i] = mapped[item.index]
164
+ item = items[--unusedItems]!;
165
+ temp[i] = mapped[item.index]!;
158
166
  batch(changeBoth);
159
167
  } else {
160
- temp[i] = root(mapper)
168
+ temp[i] = root(mapper);
161
169
  }
162
170
  }
163
171
 
164
172
  // 6) delete any old unused items left
165
- disposeList(items.splice(0, unusedItems))
173
+ disposeList(items.splice(0, unusedItems));
166
174
 
175
+ if (newItems.length === 0 && options.fallback) {
176
+ if (!fallbackDisposer) {
177
+ fallback = [
178
+ root(d => {
179
+ fallbackDisposer = d;
180
+ return options.fallback!();
181
+ }),
182
+ ];
183
+ }
184
+ return fallback!;
185
+ }
167
186
  return (mapped = temp);
168
187
  })
169
- })
188
+ }
189
+ // const indexes = cb.length > 1 ? [] : null;
190
+ function newValueGetter(_:unknown) { return newValue }
191
+ function changeBoth() {
192
+ item!.index = i!
193
+ item!.indexSetter?.(i)
194
+ item!.value = newValue!
195
+ item!.valueSetter?.(newValueGetter)
196
+ }
197
+ function mapper(disposer: ()=>void) {
198
+ const I = i
199
+ const t = {value: newValue, index: I, disposer}
200
+ items.push(t)
201
+ const sI = () => { t.indexSetter = I; return signal(I) }
202
+ let sV = (...a) => {
203
+ const k = I
204
+ sV = (...a) => {
205
+ if (a.length===0) {
206
+ const bk = list()[k]
207
+ return bk
208
+ } else {
209
+ const b = untrack(list)
210
+ return list(b.toSpliced(k, 1, a[0])).at(k)
211
+ }
212
+ }
213
+ t.valueSetter = sV
214
+ return sV(...a)
215
+ }
216
+ return mapFn(sV, () => sI())
217
+ }
170
218
  }
171
219
 
172
- function disposeList(list:any[]) {
220
+ function disposeList(list:{disposer?:()=>unknown}[]) {
173
221
  for (let i = 0; i < list.length; i++) {
174
222
  list[i]?.disposer()
175
223
  }
@@ -1,146 +1,121 @@
1
- // @ts-nocheck:
2
- import {untrack} from './reactive.ts'
3
- import type {Properties,BooleanAttributes,DelegatedEvents,DOMElements, Mountable} from './constants.ts'
4
- import type {Runtime,$RUNTIME} from './runtime.ts'
1
+ import type {DOMElements} from './constants.ts'
2
+ import type {Runtime} from './runtime.ts'
5
3
 
6
4
  const ELEMENT: unique symbol = Symbol(), {isArray} = Array
7
5
 
8
- export type PropsKeys = typeof Properties extends Set<infer K> ? K : never;
9
- export type BooleanProps = typeof BooleanAttributes extends Set<infer K> ? K : never;
10
- export type HandlerProps = typeof DelegatedEvents extends Set<infer K> ? K : never;
11
- export type ChildProps = {children?:any[]}
12
-
13
- export type ElementProps = BooleanProps & HandlerProps & ChildProps & {class: string}
14
- export type ComponentProps = { children?:Child }
15
-
16
- /**
17
- * @group Hyperscript
18
- */
19
- export type Props = {}
6
+ export type Mountable = View | HTMLElement | string | number | bigint | symbol | boolean | Date | Mountable[];
7
+ export type Component<T> = ((props:T) => Mountable) | ((props:T) => Mountable[])
8
+ export type Tag = typeof DOMElements extends Set<infer K> ? K : never;
9
+ export type Child = { ():Child } | Element | Child[] | string | number | symbol | bigint | boolean | Date | Record<string,unknown> | {():Child, [ELEMENT]:boolean}
10
+ export type View = {():void, [ELEMENT]?:boolean}
20
11
 
21
- type AllProps = ElementProps | ComponentProps
12
+ // export type PropsKeys = typeof Properties extends Set<infer K> ? K : never;
13
+ // export type BooleanProps = typeof BooleanAttributes ext ends Set<infer K> ? K : never;
14
+ // export type HandlerProps = typeof DelegatedEvents extends Set<infer K> ? K : never;
15
+ // export type ChildProps = {children?:any[]}
16
+ // export type ElementProps = BooleanProps & HandlerProps & ChildProps & {class: string}
17
+ // export type ComponentProps = { children?:Child }
18
+ // export type Props = Record<string, any>
19
+ // type AllProps = ElementProps | ComponentProps
20
+ // type EmptyProps = Record<string,never>
21
+ // const Fragment:Component<Props> = <T extends Props>(props:T):Mountable => (props as any).children
22
22
 
23
- type EmptyProps = Record<string,never>
23
+ export type TagParser = <T extends string>(s:T) => {name:string,id?:string,classes:string[],namespace?:string}
24
24
 
25
- /**
26
- @group Hyperscript
27
- */
28
25
  export type HyperScript = {
29
- // (children:Child[]): View
30
-
31
- (element:Tag, props:ElementProps, children:Child): View
32
- (element:Tag, props:ElementProps): View
33
- (element:Tag, children:Child): View
34
- (element:Tag): View
35
-
36
- <T,K>(element:Component<T & {children:K}>, props:T, children:K): View
37
- <T>(element:Component<T>, props:T): View
38
- <K>(element:Component<{children:K}>, children:K): View
39
- (element:Component<undefined>): View
26
+ (first: Tag): View
27
+ <P>(first: Tag, second: P): View
28
+ <C extends Child>(first: Tag, second: C): View
29
+ <C extends Child, P>(first: Tag, second: P, third: C): View
30
+
31
+ (first: Component<Record<string,never>>): View
32
+ <P extends Record<string, unknown>>(first: Component<P>, second: P): View
33
+ <C>(first: Component<{children:C}>, second: C): View
34
+ <P extends Record<string, unknown>, C>(first: Component<P & {children:C}>, second:P, third:C): View
40
35
  }
41
36
 
42
37
  /**
43
- * @group Hyperscript
44
- */
45
- export type Child = { call:any } | Child[] | string | number | symbol | bigint | boolean | Record<string,unknown> | {():Child, [ELEMENT]:boolean}
46
- /**
47
- * @group Hyperscript
48
- */
49
- export type View = {():void, [ELEMENT]?:boolean}
50
- /**
51
- * @group Hyperscript
52
- */
53
- export type Component<T> = {(props:T): Mountable, [ELEMENT]?: Runtime}
54
- /**
55
- * @group Hyperscript
56
- */
57
- export type Tag = typeof DOMElements extends Set<infer K> ? K : never;
58
-
59
- const Fragment:Component<Props> = <T extends Props>(props:T):Mountable => (props as any).children
60
-
61
- /**
62
-
63
38
  @param r
64
39
  @param patch
65
40
  @group Hyperscript
66
41
  */
67
- export function hyperscript(r:Runtime, patch?:any):HyperScript {
42
+ export function hyperscript(r: Runtime, parseTag: TagParser = parseHtmlTag): HyperScript {
68
43
 
69
- function item<T extends Props>(e: Element, c: Child, m?: null) {
44
+ function item(e: Element, c: Child, m?: null): void {
70
45
  if (c===null) return
46
+ const t = typeof c
71
47
  if (isArray(c))
72
48
  for (const child of c)
73
49
  item(e, child, m)
74
- else if (typeof c === 'object' && r.isChild(c))
50
+ else if (t === 'object' && r.isChild(c))
75
51
  r.insert(e, c, m)
76
- else if (typeof c==='string')
77
- (e as Element).appendChild(r.text(c))
78
- else if ((c as any).call) {
79
- while ((c as any)[ELEMENT]?.call) c = (c as any)()
52
+ else if (t === 'string')
53
+ e.appendChild(r.text((c as string)))
54
+ else if (t === 'function') {
55
+ // while (c[ELEMENT]?.call) c = (c as any)()
80
56
  r.insert(e, c, m)
81
- } else (e as Element).appendChild(r.text(c.toString()))
57
+ } else e.appendChild(r.text(c.toString()))
82
58
  }
83
59
 
84
- return function h<T,K=unknown>(
85
- element:Component<T&{children:K}>|Tag, // , Child[]
86
- second?:T|K|Child,
87
- third?:K|Child
60
+ return function h<P extends Record<string,unknown>, C = never>(
61
+ first: Tag | Component<P>,
62
+ second?: P | C,
63
+ third?: C
88
64
  ): View {
89
- let props: T
65
+ let props: P
90
66
  let children: Child
91
67
 
92
68
  if (typeof second === 'object' && !isArray(second)) {
93
69
  children = (third as Child) || [];
94
- props = ((second ?? {}) as T&{children:K})
70
+ props = ((second ?? {}) as P & {children:C})
95
71
  } else {
96
72
  children = (second as Child) || []
97
- props = {} as T&{children:K}
73
+ props = {} as P & {children:C}
98
74
  }
99
75
 
100
76
  let ret:View
101
77
 
102
- if ((element as Component<T>).call) {
103
- let e:any
104
- const d = Object.getOwnPropertyDescriptors(props)
105
- if (children) (props as any).children = children
106
- for (const k in d) {
107
- if (isArray(d[k].value)) {
108
- const list:any[] = d[k].value;
109
- (props as any)[k] = () => {
110
- for (let i = 0; i < list.length; i++)
111
- while (list[i][ELEMENT]) list[i] = list[i]()
112
- return list
113
- }
114
- dynamicProperty(props as any, k)
115
- } else if (d[k].value?.call && !d[k].value.length) { // A function with zero arguments
116
- dynamicProperty(props as any, k)
117
- }
118
- }
119
- e = untrack(()=>(element as Component<T&{children:K}>)(props as T&{children:K}))
120
- ret = () => e
121
- } else {
122
- const tag = parseTag(element as Tag)
78
+ if (typeof first === 'string') {
79
+ const tag = parseTag(first)
123
80
  const multiExpression = detectMultiExpression(children) ? null : undefined
124
81
  const e = r.element(tag.name)
125
- const props2 = props as T
82
+ const props2 = props as P & {class?: string|(()=>string)}
126
83
  if (tag.id) e.setAttribute('id',tag.id)
127
84
  if (tag.classes?.length) {
128
- const cd = Object.getOwnPropertyDescriptor(props2,'class') ?? ({value:'',writable:true,enumerable:true} as any);
129
- (props2 as any).class = (cd.value?.call) ?
85
+ const cd = Object.getOwnPropertyDescriptor(props2,'class') ?? ({value:'',writable:true,enumerable:true});
86
+ props2.class = (cd.value?.call) ?
130
87
  () => [...tag.classes,...(cd.value()??'').split(' ')].filter(c=>c).join(' ') :
131
88
  [...tag.classes,...(cd.value??'').split(' ')].filter(c=>c).join(' ')
132
89
  }
133
- if (patch) patch(props2)
90
+ // if (patch) patch(props2)
134
91
  let dynamic = false
135
92
  const d = Object.getOwnPropertyDescriptors(props2)
136
93
  for (const k in d) {
137
- if (k !== 'ref' && !k.startsWith('on') && d[k].value?.call) {
138
- dynamicProperty(props2 as any, k)
94
+ if (k !== 'ref' && !k.startsWith('on') && typeof d[k].value === 'function') {
95
+ dynamicProperty(props2, k)
139
96
  dynamic = true
140
97
  } else if (d[k].get) dynamic = true
141
98
  }
142
- (dynamic ? r.spread : r.assign) (e, props2, !!(children as Child[])?.length)
143
- item(e,children as any,multiExpression)
99
+ (dynamic ? r.spread : r.assign) (e, props2, !!(children as {length?: number})?.length)
100
+ item(e, children, multiExpression)
101
+ ret = () => e
102
+ } else {
103
+ const d = Object.getOwnPropertyDescriptors(props)
104
+ if (children) (props as unknown as {children:unknown}).children = children
105
+ for (const k in d) {
106
+ if (isArray(d[k].value)) {
107
+ const list = d[k].value;
108
+ (props as Record<string, ()=>unknown>)[k] = () => {
109
+ for (let i = 0; i < list.length; i++)
110
+ while (list[i][ELEMENT]) list[i] = list[i]()
111
+ return list
112
+ }
113
+ dynamicProperty(props, k)
114
+ } else if (typeof d[k].value==='function' && !d[k].value.length) { // A function with zero arguments
115
+ dynamicProperty(props, k)
116
+ }
117
+ }
118
+ const e = r.component(() => (first as Component<P>)(props))
144
119
  ret = () => e
145
120
  }
146
121
  ret[ELEMENT] = true
@@ -148,18 +123,18 @@ export function hyperscript(r:Runtime, patch?:any):HyperScript {
148
123
  }
149
124
  }
150
125
 
151
- function detectMultiExpression(list:any):boolean {
152
- if (list.call) return true
153
- else if (!isArray(list)) return false
154
- for (const i of list) {
155
- if (i.call) return true
126
+ function detectMultiExpression(children: Child): boolean {
127
+ if (typeof children === 'function') return true
128
+ else if (!isArray(children)) return false
129
+ for (const i of children) {
130
+ if (typeof i === 'function') return true
156
131
  else if (isArray(i)) return detectMultiExpression(i)
157
132
  }
158
133
  return false
159
134
  }
160
135
 
161
136
  // ^([a-zA-Z]\w*)?(#[a-zA-Z][-\w]*)?(.[a-zA-Z][-\w]*)*
162
- function parseTag(s:string):{name:string,id?:string,classes:string[]} {
137
+ export function parseHtmlTag(s:Tag) {
163
138
  const classes:string[] = [];
164
139
  let id:string|undefined = undefined, i:number
165
140
 
@@ -185,10 +160,10 @@ function parseTag(s:string):{name:string,id?:string,classes:string[]} {
185
160
  return {name:name as string,classes,id:id}
186
161
  }
187
162
 
188
- function dynamicProperty(props:Record<string,any>, key:string):Record<string,any> {
189
- const src = props[key]
190
- Object.defineProperty(props, key, {get() {return src()},enumerable:true})
191
- return props
163
+ function dynamicProperty<T>(props: Record<string, unknown>, key: string) {
164
+ const src = props[key] as ()=>unknown
165
+ Object.defineProperty(props, key, {get() {return src()}, enumerable:true})
166
+ // return props
192
167
  }
193
168
 
194
169
  // function tw(rules) {
package/src/mod.ts CHANGED
@@ -1,18 +1,15 @@
1
- // @ts-nocheck:
2
1
  export type {Getter,Setter,Fn,EqualsFn,ErrorFn,RootFn,UpdateFn} from './reactive.ts'
3
2
  export {signal,effect,untrack,batch,memo,root,wrap,fuse,onMount,onCleanup} from './reactive.ts'
4
3
  export {nbsp} from './constants.ts'
5
4
  export {Show,List} from './controlflow.ts'
6
5
  export {runtime, type Runtime} from './runtime.ts'
7
6
  import {runtime, type Runtime} from './runtime.ts'
8
- export {hyperscript,type HyperScript,type Child,type Props,type Tag,type View,type Component} from './hyperscript.ts'
9
- import {type HyperScript, hyperscript} from './hyperscript.ts'
7
+ export {hyperscript,type Child,type Tag,type View,type Component} from './hyperscript.ts'
8
+ import {hyperscript, parseHtmlTag, type HyperScript} from './hyperscript.ts'
10
9
  export {Router} from './router.js'
11
10
  export {resource,makeAbortable,abortable} from './resource.js'
12
- // export {Input,Table} from './components.js'
13
- // export * from './canvas.js'
14
11
 
15
- const r:Runtime = /*#__PURE__*/ (typeof window === 'object') ? runtime(window as any) : undefined as any
12
+ const r:Runtime = /*#__PURE__*/ (typeof window === 'object') ? runtime(window) : undefined as unknown as Runtime
16
13
 
17
14
  /** h
18
15
  @example Element with a single child
@@ -29,19 +26,14 @@ h(Input,{onInput:e => {}})
29
26
  ```
30
27
  @group Hyperscript
31
28
  */
32
- const h:HyperScript = /*#__PURE__*/ r ? hyperscript(r) : undefined
29
+ export const h: HyperScript = /*#__PURE__*/ hyperscript(r, parseHtmlTag)
33
30
 
34
- const render = /*#__PURE__*/ r?.render
31
+ /** render
35
32
 
36
- // import {signal,wrap} from './reactive.ts'
33
+ Render component to DOM element.
37
34
 
38
- // /**
39
- // @group Utils
40
- // */
41
- // export function $(a:any,b:any):any {
42
- // const t = typeof a
43
- // if (t==='function') return wrap(a,b)
44
- // else return signal(a,b)
45
- // }
46
-
47
- export {h,render}
35
+ ```js
36
+ render(()=>'hi', document.body)
37
+ ```
38
+ */
39
+ export const render:(code:()=>void, element:Element, init:unknown) => void = /*#__PURE__*/ r?.render