@wrnrlr/prelude 0.2.17 → 0.2.18
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 +2 -2
- package/example/context.html +29 -0
- package/example/h.html +24 -0
- package/example/index.html +2 -0
- package/example/style.css +1 -3
- package/package.json +1 -1
- package/readme.md +4 -0
- package/src/hyperscript.ts +184 -140
- package/src/reactive.ts +15 -32
- package/src/runtime.ts +3 -17
- package/test/hyperscript.js +4 -7
package/deno.jsonc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@wrnrlr/prelude",
|
3
|
-
"version": "0.2.
|
3
|
+
"version": "0.2.18",
|
4
4
|
"exports": {
|
5
5
|
".": "./src/mod.ts",
|
6
6
|
"./style.css": "./src/style.css"
|
@@ -18,7 +18,7 @@
|
|
18
18
|
},
|
19
19
|
"tasks": {
|
20
20
|
"dev": "deno run -A npm:vite --config www/vite.config.js",
|
21
|
-
"test": "deno test -A ./test/*.[jt]s",
|
21
|
+
"test": "deno test -A ./test/*.[jt]s --no-check",
|
22
22
|
"release": "git push origin main:release"
|
23
23
|
},
|
24
24
|
"lint": {
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<script type="module">
|
2
|
+
|
3
|
+
import {h,signal,effect,batch,wrap,render,context,useContext,List} from '../src/mod.ts'
|
4
|
+
|
5
|
+
const CounterCtx = context()
|
6
|
+
|
7
|
+
const useCounter = () => {
|
8
|
+
const c = useContext(CounterCtx)
|
9
|
+
return c
|
10
|
+
}
|
11
|
+
|
12
|
+
function CounterProvider(props) {
|
13
|
+
const counter = signal(0)
|
14
|
+
const increment = ()=>(console.log('increment', counter()),counter(v=>++v))
|
15
|
+
return h(CounterCtx, {value:()=>[counter, increment]}, props.children)
|
16
|
+
}
|
17
|
+
|
18
|
+
function Counter() {
|
19
|
+
const [val, increment] = useCounter()
|
20
|
+
return [val, h('button', {onClick:e=>increment()}, '+')]
|
21
|
+
}
|
22
|
+
|
23
|
+
function App() {
|
24
|
+
return h(CounterProvider, ()=>h(Counter))
|
25
|
+
}
|
26
|
+
|
27
|
+
render(App, document.body)
|
28
|
+
|
29
|
+
</script>
|
package/example/h.html
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<script type="module">
|
2
|
+
|
3
|
+
// import { createSignal, createEffect } from 'solid'
|
4
|
+
import { render } from 'https://esm.sh/solid-js/web'
|
5
|
+
import h from 'https://esm.sh/solid-js/h'
|
6
|
+
|
7
|
+
function A(props) {
|
8
|
+
console.log('A')
|
9
|
+
return ['A', h(B)]
|
10
|
+
}
|
11
|
+
|
12
|
+
function B() {
|
13
|
+
console.log('B')
|
14
|
+
return 'B'
|
15
|
+
}
|
16
|
+
|
17
|
+
function App() {
|
18
|
+
console.log('App')
|
19
|
+
return h(A, h(B))
|
20
|
+
}
|
21
|
+
|
22
|
+
render(App, document.body)
|
23
|
+
|
24
|
+
</script>
|
package/example/index.html
CHANGED
@@ -11,6 +11,8 @@
|
|
11
11
|
<li><a href="todo.html">Todo</a></li>
|
12
12
|
<li><a href="widget.html">Widget</a></li>
|
13
13
|
<li><a href="table.html">Table</a></li>
|
14
|
+
<li><a href="context.html">Context (Dependency Injection)</a></li>
|
15
|
+
<li><a href="h.html">h</a></li>
|
14
16
|
</ul>
|
15
17
|
<!-- <a href="router.html">Router</a> -->
|
16
18
|
<!-- <a href="context.html">Context</a> -->
|
package/example/style.css
CHANGED
package/package.json
CHANGED
package/readme.md
CHANGED
@@ -227,3 +227,7 @@ deno task test
|
|
227
227
|
* [Homepage](https://wrnrlr.github.io/prelude)
|
228
228
|
* [NPM](https://www.npmjs.com/package/@wrnrlr/prelude)
|
229
229
|
* [JSR](https://jsr.io/@wrnrlr/prelude)
|
230
|
+
|
231
|
+
## More Links
|
232
|
+
|
233
|
+
* [Fine-grained reactivity - A deep dive into SolidJS](https://github.com/everweij/solidjs-fine-grained-reactivity)
|
package/src/hyperscript.ts
CHANGED
@@ -1,167 +1,211 @@
|
|
1
1
|
import type {DOMElements} from './constants.ts'
|
2
|
-
import type {
|
2
|
+
import type {Mountable} from './runtime.ts'
|
3
3
|
import {r} from './runtime.ts'
|
4
4
|
|
5
|
-
const
|
6
|
-
|
7
|
-
// export type Mountable = View | HTMLElement | string | number | bigint | symbol | boolean | Date | Mountable[];
|
8
|
-
export type Component<T> = ((props:T) => Mountable) | ((props:T) => Mountable[])
|
9
|
-
export type Tag = typeof DOMElements extends Set<infer K> ? K : never;
|
10
|
-
export type Child = { ():Child } | Element | Child[] | string | number | symbol | bigint | boolean | Date | Record<string,unknown> | {():Child, [ELEMENT]:boolean}
|
11
|
-
export type View = {():void, [ELEMENT]?:boolean}
|
5
|
+
// const document = globalThis.document
|
12
6
|
|
13
7
|
export const h = hyperscript(r)
|
14
8
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
9
|
+
type MountableElement = Element | Document | ShadowRoot | DocumentFragment | Node
|
10
|
+
|
11
|
+
interface Runtime {
|
12
|
+
insert(parent: MountableElement, accessor: any, marker?: Node | null, init?: any): any;
|
13
|
+
spread(node: Element, accessor: any, isSVG?: Boolean, skipChildren?: Boolean): void;
|
14
|
+
assign(node: Element, props: any, isSVG?: Boolean, skipChildren?: Boolean): void;
|
15
|
+
component(Comp: (props: any) => any, props: any): any;
|
16
|
+
SVGElements: Set<string>;
|
17
|
+
}
|
18
|
+
|
19
|
+
const $ELEMENT = Symbol("hyper-element");
|
25
20
|
|
26
|
-
|
21
|
+
type ExpandableNode = Node & { [key: string]: any };
|
22
|
+
type Props = { [key: string]: any };
|
27
23
|
|
28
24
|
export type HyperScript = {
|
29
|
-
(
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
(first: Component<Record<string,never>>): View
|
35
|
-
<P extends Record<string, unknown>>(first: Component<P>, second: P): View
|
36
|
-
<C>(first: Component<{children:C}>, second: C): View
|
37
|
-
<P extends Record<string, unknown>, C>(first: Component<P & {children:C}>, second:P, third:C): View
|
38
|
-
}
|
25
|
+
(...args: any[]): () => ExpandableNode | ExpandableNode[];
|
26
|
+
Fragment: (props: {
|
27
|
+
children: (() => ExpandableNode) | (() => ExpandableNode)[];
|
28
|
+
}) => ExpandableNode[];
|
29
|
+
};
|
39
30
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
function item(e: Element, c: Child, m?: null): void {
|
48
|
-
if (c===null) return
|
49
|
-
const t = typeof c
|
50
|
-
if (isArray(c))
|
51
|
-
for (const child of c)
|
52
|
-
item(e, child, m)
|
53
|
-
else if (t === 'object' && r.isChild(c))
|
54
|
-
r.insert(e, c, m)
|
55
|
-
else if (t === 'string')
|
56
|
-
e.appendChild(r.text((c as string)))
|
57
|
-
else if (t === 'function') {
|
58
|
-
// while (c[ELEMENT]?.call) c = (c as any)()
|
59
|
-
r.insert(e, c, m)
|
60
|
-
} else e.appendChild(r.text(c.toString()))
|
61
|
-
}
|
31
|
+
// Inspired by https://github.com/hyperhype/hyperscript
|
32
|
+
export function hyperscript(r: Runtime): HyperScript {
|
33
|
+
function h() {
|
34
|
+
let args: any = [].slice.call(arguments),
|
35
|
+
e: ExpandableNode | undefined,
|
36
|
+
classes:string[] = [],
|
37
|
+
multiExpression = false;
|
62
38
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
39
|
+
while (Array.isArray(args[0])) args = args[0];
|
40
|
+
if (args[0][$ELEMENT]) args.unshift(h.Fragment);
|
41
|
+
typeof args[0] === "string" && detectMultiExpression(args);
|
42
|
+
const ret: (() => ExpandableNode) & { [$ELEMENT]?: boolean } = () => {
|
43
|
+
while (args.length) item(args.shift());
|
44
|
+
if (e instanceof globalThis.Element && classes.length) e.classList.add(...classes)
|
45
|
+
return e as ExpandableNode;
|
46
|
+
};
|
47
|
+
ret[$ELEMENT] = true;
|
48
|
+
return ret;
|
49
|
+
|
50
|
+
function item(l: any) {
|
51
|
+
const type = typeof l;
|
52
|
+
if (l == null) void 0;
|
53
|
+
else if ("string" === type) {
|
54
|
+
if (!e) parseHtmlTag(l);
|
55
|
+
else e.appendChild(globalThis.document.createTextNode(l));
|
56
|
+
} else if (
|
57
|
+
"number" === type ||
|
58
|
+
"boolean" === type ||
|
59
|
+
"bigint" === type ||
|
60
|
+
"symbol" === type ||
|
61
|
+
l instanceof Date ||
|
62
|
+
l instanceof RegExp
|
63
|
+
) {
|
64
|
+
(e as Node).appendChild(globalThis.document.createTextNode(l.toString()));
|
65
|
+
} else if (Array.isArray(l)) {
|
66
|
+
for (let i = 0; i < l.length; i++) item(l[i]);
|
67
|
+
} else if (l instanceof globalThis.Element) {
|
68
|
+
r.insert(e as globalThis.Element, l, multiExpression ? null : undefined);
|
69
|
+
} else if ("object" === type) {
|
70
|
+
let dynamic = false;
|
71
|
+
const d = Object.getOwnPropertyDescriptors(l);
|
72
|
+
for (const k in d) {
|
73
|
+
if (k === "class" && classes.length !== 0) {
|
74
|
+
console.log('classes',classes)
|
75
|
+
const fixedClasses = classes.join(" "),
|
76
|
+
value = typeof d["class"].value === "function" ?
|
77
|
+
()=>[...classes,...(d["class"].value()??'').split(' ')].filter(c=>c).join(' ') :
|
78
|
+
[...classes,...(d["class"].value??'').split(' ')].filter(c=>c).join(' ')
|
79
|
+
Object.defineProperty(l,"class",{...d[k],value})
|
80
|
+
// classes = []
|
81
|
+
}
|
82
|
+
if (k !== "ref" && k.slice(0, 2) !== "on" && typeof d[k].value === "function") {
|
83
|
+
dynamicProperty(l, k);
|
84
|
+
dynamic = true;
|
85
|
+
} else if (d[k].get) dynamic = true;
|
86
|
+
}
|
87
|
+
dynamic
|
88
|
+
? r.spread(e as globalThis.Element, l, !!args.length)
|
89
|
+
: r.assign(e as globalThis.Element, l, !!args.length);
|
90
|
+
} else if ("function" === type) {
|
91
|
+
if (!e) {
|
92
|
+
let props: Props | undefined,
|
93
|
+
next = args[0];
|
94
|
+
if (
|
95
|
+
next == null ||
|
96
|
+
(typeof next === "object" && !Array.isArray(next) && !(next instanceof globalThis.Element))
|
97
|
+
)
|
98
|
+
props = args.shift();
|
99
|
+
props || (props = {});
|
100
|
+
if (args.length) {
|
101
|
+
props.children = args.length > 1 ? args : args[0];
|
102
|
+
}
|
103
|
+
const d = Object.getOwnPropertyDescriptors(props);
|
104
|
+
for (const k in d) {
|
105
|
+
if (Array.isArray(d[k].value)) {
|
106
|
+
const list = d[k].value;
|
107
|
+
props[k] = () => {
|
108
|
+
for (let i = 0; i < list.length; i++) {
|
109
|
+
while (list[i][$ELEMENT]) list[i] = list[i]();
|
110
|
+
}
|
111
|
+
return list;
|
112
|
+
};
|
113
|
+
dynamicProperty(props, k);
|
114
|
+
} else if (typeof d[k].value === "function" && !d[k].value.length)
|
115
|
+
dynamicProperty(props, k);
|
116
|
+
}
|
117
|
+
e = r.component(l, props);
|
118
|
+
args = [];
|
119
|
+
} else {
|
120
|
+
while ((l as any)[$ELEMENT]) l = ((l as unknown) as () => ExpandableNode)();
|
121
|
+
r.insert(e as globalThis.Element, l, multiExpression ? null : undefined);
|
122
|
+
}
|
123
|
+
}
|
77
124
|
}
|
125
|
+
function parseHtmlTag(s: string) {
|
126
|
+
let i:number
|
127
|
+
|
128
|
+
i = s.indexOf('#')
|
129
|
+
if (i===-1) i = s.indexOf('.')
|
130
|
+
if (i===-1) i = s.length
|
131
|
+
const name = s.slice(0, i) || 'div'
|
132
|
+
e = r.SVGElements.has(name)
|
133
|
+
? globalThis.document.createElementNS("http://www.w3.org/2000/svg", name)
|
134
|
+
: globalThis.document.createElement(name);
|
135
|
+
s = s.slice(i)
|
136
|
+
|
137
|
+
if (s[0]==='#') {
|
138
|
+
i = s.indexOf('.')
|
139
|
+
if (i===-1) i = s.length
|
140
|
+
e!.setAttribute("id", s.slice(1, i))
|
141
|
+
s = s.slice(i)
|
142
|
+
}
|
78
143
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
const e = r.element(tag.name)
|
85
|
-
const props2 = props as P & {class?: string|(()=>string)}
|
86
|
-
if (tag.id) e.setAttribute('id',tag.id)
|
87
|
-
if (tag.classes?.length) {
|
88
|
-
const cd = Object.getOwnPropertyDescriptor(props2,'class') ?? ({value:'',writable:true,enumerable:true});
|
89
|
-
props2.class = (cd.value?.call) ?
|
90
|
-
() => [...tag.classes,...(cd.value()??'').split(' ')].filter(c=>c).join(' ') :
|
91
|
-
[...tag.classes,...(cd.value??'').split(' ')].filter(c=>c).join(' ')
|
144
|
+
while(s[0]==='.') {
|
145
|
+
i = s.indexOf('.',1)
|
146
|
+
if (i===-1) i = s.length
|
147
|
+
classes.push(s.slice(1, i))
|
148
|
+
s = s.slice(i)
|
92
149
|
}
|
93
|
-
|
94
|
-
|
95
|
-
const
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
150
|
+
}
|
151
|
+
function parseClass(string: string) {
|
152
|
+
const m = string.split(/([\.#]?[^\s#.]+)/);
|
153
|
+
if (/^\.|#/.test(m[1])) e = globalThis.document.createElement("div");
|
154
|
+
for (let i = 0; i < m.length; i++) {
|
155
|
+
let v = m[i]
|
156
|
+
const s = v.substring(1, v.length);
|
157
|
+
if (!v) v = 'div';
|
158
|
+
if (!e)
|
159
|
+
e = r.SVGElements.has(v)
|
160
|
+
? globalThis.document.createElementNS("http://www.w3.org/2000/svg", v)
|
161
|
+
: globalThis.document.createElement(v);
|
162
|
+
if (v[0] === ".") classes.push(s);
|
163
|
+
else if (v[0] === "#") e.setAttribute("id", s);
|
101
164
|
}
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
const list = d[k].value;
|
111
|
-
(props as Record<string, ()=>unknown>)[k] = () => {
|
112
|
-
for (let i = 0; i < list.length; i++)
|
113
|
-
while (list[i][ELEMENT]) list[i] = list[i]()
|
114
|
-
return list
|
115
|
-
}
|
116
|
-
dynamicProperty(props, k)
|
117
|
-
} else if (typeof d[k].value==='function' && !d[k].value.length) { // A function with zero arguments
|
118
|
-
dynamicProperty(props, k)
|
165
|
+
}
|
166
|
+
function detectMultiExpression(list: any[]) {
|
167
|
+
for (let i = 1; i < list.length; i++) {
|
168
|
+
if (typeof list[i] === "function") {
|
169
|
+
multiExpression = true;
|
170
|
+
return;
|
171
|
+
} else if (Array.isArray(list[i])) {
|
172
|
+
detectMultiExpression(list[i]);
|
119
173
|
}
|
120
174
|
}
|
121
|
-
const e = r.component(() => (first as Component<P>)(props))
|
122
|
-
ret = () => e
|
123
175
|
}
|
124
|
-
ret[ELEMENT] = true
|
125
|
-
return ret
|
126
176
|
}
|
127
|
-
}
|
128
177
|
|
129
|
-
|
130
|
-
|
131
|
-
else if (!isArray(children)) return false
|
132
|
-
for (const i of children) {
|
133
|
-
if (typeof i === 'function') return true
|
134
|
-
else if (isArray(i)) return detectMultiExpression(i)
|
135
|
-
}
|
136
|
-
return false
|
178
|
+
h.Fragment = (props: any) => props.children;
|
179
|
+
return h;
|
137
180
|
}
|
138
181
|
|
182
|
+
|
139
183
|
// ^([a-zA-Z]\w*)?(#[a-zA-Z][-\w]*)?(.[a-zA-Z][-\w]*)*
|
140
|
-
export function parseHtmlTag(s:Tag) {
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
i = s.indexOf('#')
|
145
|
-
if (i===-1) i = s.indexOf('.')
|
146
|
-
if (i===-1) i = s.length
|
147
|
-
const name = s.slice(0, i) || 'div'
|
148
|
-
s = s.slice(i)
|
149
|
-
|
150
|
-
if (s[0]==='#') {
|
151
|
-
i = s.indexOf('.')
|
152
|
-
if (i===-1) i = s.length
|
153
|
-
id = s.slice(1, i)
|
154
|
-
s = s.slice(i)
|
155
|
-
}
|
184
|
+
// export function parseHtmlTag(s:Tag) {
|
185
|
+
// const classes:string[] = [];
|
186
|
+
// let id:string|undefined = undefined, i:number
|
156
187
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
188
|
+
// i = s.indexOf('#')
|
189
|
+
// if (i===-1) i = s.indexOf('.')
|
190
|
+
// if (i===-1) i = s.length
|
191
|
+
// const name = s.slice(0, i) || 'div'
|
192
|
+
// s = s.slice(i)
|
193
|
+
|
194
|
+
// if (s[0]==='#') {
|
195
|
+
// i = s.indexOf('.')
|
196
|
+
// if (i===-1) i = s.length
|
197
|
+
// id = s.slice(1, i)
|
198
|
+
// s = s.slice(i)
|
199
|
+
// }
|
200
|
+
|
201
|
+
// while(s[0]==='.') {
|
202
|
+
// i = s.indexOf('.',1)
|
203
|
+
// if (i===-1) i = s.length
|
204
|
+
// classes.push(s.slice(1, i))
|
205
|
+
// s = s.slice(i)
|
206
|
+
// }
|
207
|
+
// return {name:name as string,classes,id:id}
|
208
|
+
// }
|
165
209
|
|
166
210
|
function dynamicProperty<T>(props: Record<string, unknown>, key: string) {
|
167
211
|
const src = props[key] as ()=>unknown
|
package/src/reactive.ts
CHANGED
@@ -59,13 +59,6 @@ export type Setter<T> = {
|
|
59
59
|
(value: T): T
|
60
60
|
}
|
61
61
|
|
62
|
-
export type Context<T> = {
|
63
|
-
id: symbol,
|
64
|
-
defaultValue: T,
|
65
|
-
get(): T,
|
66
|
-
set(value: T): void
|
67
|
-
}
|
68
|
-
|
69
62
|
export type Options<T> = {
|
70
63
|
equals?: false | EqualsFn<T>
|
71
64
|
}
|
@@ -297,42 +290,32 @@ export function root<T>(fn: RootFn<T>): T {
|
|
297
290
|
return new Root().wrap(fn)
|
298
291
|
}
|
299
292
|
|
300
|
-
export
|
301
|
-
|
293
|
+
export type Context<T> = {
|
294
|
+
id: symbol,
|
295
|
+
defaultValue: T,
|
296
|
+
get(): T,
|
297
|
+
set(value: T): void
|
298
|
+
}
|
299
|
+
|
300
|
+
export function context<T>(): Context<T | undefined>
|
301
|
+
export function context<T>(defaultValue: T): Context<T>
|
302
302
|
export function context<T>(defaultValue?: T) {
|
303
303
|
const id = Symbol()
|
304
|
-
const
|
305
|
-
|
306
|
-
|
307
|
-
const s = {id, defaultValue, get, set}
|
308
|
-
const f = Object.assign((props:any) => {
|
309
|
-
set(props.value)
|
304
|
+
const s = {id, defaultValue}
|
305
|
+
return Object.assign((props:any) => {
|
306
|
+
OBSERVER?.set(id, props.value)
|
310
307
|
return () => props.children.call ? props.children() : props.children
|
311
|
-
}, s)
|
312
|
-
return f as unknown as Context<T>
|
313
|
-
// return {id, Provider, defaultValue} as unknown as Context<T>
|
308
|
+
}, s) as unknown as Context<T>
|
314
309
|
}
|
315
310
|
|
316
|
-
function
|
317
|
-
return
|
318
|
-
let res;
|
319
|
-
renderEffect(() => (res = untrack(() => {
|
320
|
-
console.log('observer', OBSERVER, props)
|
321
|
-
OBSERVER!.context = { ...OBSERVER!.context, [id]: props.value };
|
322
|
-
return children(() => props.children);
|
323
|
-
})))
|
324
|
-
return res;
|
325
|
-
};
|
311
|
+
export function useContext<T>(ctx: Context<T>): T {
|
312
|
+
return OBSERVER?.get(ctx.id) ?? ctx.defaultValue
|
326
313
|
}
|
327
314
|
|
328
315
|
export function renderEffect(fn:()=>void) {
|
329
316
|
return globalThis.requestAnimationFrame(()=>effect(fn))
|
330
317
|
}
|
331
318
|
|
332
|
-
export function useContext<T>(context: Context<T>): T {
|
333
|
-
return context.get()
|
334
|
-
}
|
335
|
-
|
336
319
|
export type S<T> = Getter<T> | Setter<T>
|
337
320
|
|
338
321
|
/**
|
package/src/runtime.ts
CHANGED
@@ -2,26 +2,12 @@
|
|
2
2
|
import {effect,untrack,root} from './reactive.ts'
|
3
3
|
import {SVGNamespace,SVGElements,ChildProperties,getPropAlias,Properties,Aliases,DelegatedEvents} from './constants.ts'
|
4
4
|
import {reconcileArrays} from './domdiff.ts'
|
5
|
-
// import type {Mountable} from './constants.ts'
|
6
5
|
|
7
6
|
const {isArray} = Array
|
8
7
|
|
9
8
|
export type Mountable = HTMLElement | Document | ShadowRoot | DocumentFragment | Node | string | number | bigint | symbol;
|
10
9
|
|
11
|
-
export const r = { render, insert, spread, assign, element, component, text, isChild, clearDelegatedEvents}
|
12
|
-
|
13
|
-
// declare global {
|
14
|
-
// interface Document {
|
15
|
-
// '_$DX_DELEGATE'?: Record<string, Set<unknown>>
|
16
|
-
// }
|
17
|
-
// // interface SVGElement {}
|
18
|
-
// }
|
19
|
-
|
20
|
-
// interface Element {
|
21
|
-
// style?: string
|
22
|
-
// }
|
23
|
-
|
24
|
-
// declare const globalThis: Document
|
10
|
+
export const r = { render, insert, spread, assign, element, component, text, isChild, clearDelegatedEvents, SVGElements }
|
25
11
|
|
26
12
|
/**
|
27
13
|
|
@@ -67,8 +53,8 @@ function isChild(a:unknown): a is Element {
|
|
67
53
|
return a instanceof Element
|
68
54
|
}
|
69
55
|
|
70
|
-
function component(fn:()=>unknown) {
|
71
|
-
return untrack(fn)
|
56
|
+
function component(fn:()=>unknown, props: unknown) {
|
57
|
+
return untrack(()=>fn(props))
|
72
58
|
}
|
73
59
|
|
74
60
|
function render(code: ()=>void, element:Element|Document, init?: unknown): void {
|
package/test/hyperscript.js
CHANGED
@@ -1,16 +1,13 @@
|
|
1
|
-
// import {runtime} from '../src/runtime.ts'
|
2
1
|
import { Window } from 'happy-dom'
|
3
2
|
import {assertEquals} from '@std/assert'
|
4
3
|
|
5
4
|
const window = new Window
|
6
5
|
|
7
|
-
globalThis
|
8
|
-
globalThis.document = window.document
|
9
|
-
globalThis.navigator = window.navigator
|
6
|
+
globalThis = window
|
10
7
|
|
11
|
-
import {signal,root} from '../src/reactive.ts'
|
8
|
+
import { signal, root } from '../src/reactive.ts'
|
12
9
|
import { r } from '../src/runtime.ts'
|
13
|
-
import {h} from '../src/hyperscript.ts'
|
10
|
+
import { h } from '../src/hyperscript.ts'
|
14
11
|
|
15
12
|
function testing(name, props, f=props) {
|
16
13
|
const htest = t => (name, f) => {
|
@@ -44,7 +41,7 @@ testing('h with basic element', async test => {
|
|
44
41
|
await test("number content", () => assertHTML(h('i',1), '<i>1</i>'))
|
45
42
|
await test("bigint content", () => assertHTML(h('i',2n), '<i>2</i>'))
|
46
43
|
await test("symbol content", () => assertHTML(h('i',Symbol('A')), '<i>Symbol(A)</i>'))
|
47
|
-
|
44
|
+
await test('regex content', () => assertHTML(h('b',/\w/), '<b>/\\w/</b>'))
|
48
45
|
await test("signal content", () => assertHTML(h('i',()=>1), '<i>1</i>'))
|
49
46
|
await test('array content', () => assertHTML(h('i',['A',1,2n]), '<i>A12</i>'))
|
50
47
|
await test('ref property', () => assertHTML(h('hr',{ref:el=>el.setAttribute('a','1')}), '<hr a="1">'))
|