@solidrt/core 0.0.1-exp.7 → 0.0.1-exp.9
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 +6 -3
- package/src/color.ts +9 -0
- package/src/events.ts +22 -0
- package/src/renderer.ts +27 -14
- package/src/types.d.ts +3 -1
- package/src/window.ts +25 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidrt/core",
|
|
3
|
-
"version": "0.0.1-exp.
|
|
3
|
+
"version": "0.0.1-exp.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -14,8 +14,11 @@
|
|
|
14
14
|
"jsx-runtime.d.ts",
|
|
15
15
|
"LICENSE"
|
|
16
16
|
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"colord": "^2.9.3"
|
|
19
|
+
},
|
|
17
20
|
"peerDependencies": {
|
|
18
|
-
"@solidjs/signals": "2.0.0-beta.
|
|
19
|
-
"@solidjs/universal": "2.0.0-beta.
|
|
21
|
+
"@solidjs/signals": "2.0.0-beta.13",
|
|
22
|
+
"@solidjs/universal": "2.0.0-beta.13"
|
|
20
23
|
}
|
|
21
24
|
}
|
package/src/color.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { colord, extend } from "colord"
|
|
2
|
+
import namesPlugin from "colord/plugins/names"
|
|
3
|
+
extend([namesPlugin])
|
|
4
|
+
|
|
5
|
+
// Parses any CSS color string and returns a packed u32: 0xRRGGBBAA
|
|
6
|
+
export function parseColorToU32(color: string): number {
|
|
7
|
+
let { r, g, b, a } = colord(color).toRgb()
|
|
8
|
+
return (((r & 0xFF) << 24) | ((g & 0xFF) << 16) | ((b & 0xFF) << 8) | ((a * 255) & 0xFF)) >>> 0
|
|
9
|
+
}
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
let handlers = new Map<number, Map<string, Function>>()
|
|
2
|
+
|
|
3
|
+
export function setEventHandler(nodeId: number, name: string, fn: Function | null | undefined): void {
|
|
4
|
+
if (fn == null) {
|
|
5
|
+
handlers.get(nodeId)?.delete(name)
|
|
6
|
+
return
|
|
7
|
+
}
|
|
8
|
+
let nodeHandlers = handlers.get(nodeId)
|
|
9
|
+
if (!nodeHandlers) {
|
|
10
|
+
nodeHandlers = new Map()
|
|
11
|
+
handlers.set(nodeId, nodeHandlers)
|
|
12
|
+
}
|
|
13
|
+
nodeHandlers.set(name, fn)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getEventHandler(nodeId: number, name: string): Function | undefined {
|
|
17
|
+
return handlers.get(nodeId)?.get(name)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function cleanupNodeHandlers(nodeId: number): void {
|
|
21
|
+
handlers.delete(nodeId)
|
|
22
|
+
}
|
package/src/renderer.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { createRoot, createEffect } from "@solidjs/signals"
|
|
2
2
|
import { createRenderer } from "@solidjs/universal"
|
|
3
3
|
import { attachWindow } from "./window"
|
|
4
|
+
import { parseColorToU32, isColorProp } from "./color"
|
|
5
|
+
import { setEventHandler, cleanupNodeHandlers } from "./events"
|
|
6
|
+
|
|
7
|
+
export { getEventHandler } from "./events"
|
|
4
8
|
|
|
5
9
|
export let nodes = new Map()
|
|
6
10
|
|
|
@@ -42,7 +46,7 @@ export let {
|
|
|
42
46
|
createElement: (elementType: string): ProxyNode => {
|
|
43
47
|
let proxy = createProxyNode(elementType)
|
|
44
48
|
|
|
45
|
-
console.
|
|
49
|
+
// console.debug("[srt] createElement", proxy.id, elementType)
|
|
46
50
|
|
|
47
51
|
if (elementType === "window") ffi.createRoot(proxy.id)
|
|
48
52
|
else ffi.createNode(proxy.id, elementType)
|
|
@@ -52,23 +56,32 @@ export let {
|
|
|
52
56
|
|
|
53
57
|
createTextNode: (value: string): ProxyNode => {
|
|
54
58
|
let proxy = createProxyNode("span")
|
|
55
|
-
console.
|
|
59
|
+
// console.debug("[srt] createTextNode", proxy.id, value)
|
|
56
60
|
ffi.createNode(proxy.id, "span")
|
|
57
61
|
ffi.setProperty(proxy.id, "text", "" + value)
|
|
58
62
|
return proxy
|
|
59
63
|
},
|
|
60
64
|
|
|
61
65
|
replaceText: (node: ProxyNode, value: string): void => {
|
|
62
|
-
console.
|
|
66
|
+
// console.debug("[srt] replaceText", node.id, value)
|
|
63
67
|
ffi.setProperty(node.id, "text", "" + value)
|
|
64
68
|
},
|
|
65
69
|
|
|
66
70
|
isTextNode: (node: ProxyNode): boolean => node?.elementType === "span",
|
|
67
|
-
setProperty: <T>(node: ProxyNode, name: string, value: T
|
|
71
|
+
setProperty: <T>(node: ProxyNode, name: string, value: T): void => {
|
|
68
72
|
if (!node) return
|
|
69
73
|
|
|
70
|
-
console.
|
|
71
|
-
|
|
74
|
+
// console.debug("[srt] setProperty", node.id, name, value)
|
|
75
|
+
|
|
76
|
+
if (/^on[A-Z]/.test(name) && (value == null || typeof value === "function")) {
|
|
77
|
+
setEventHandler(node.id, name, value as Function | null | undefined)
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (name === "color" && typeof value === "string") {
|
|
82
|
+
ffi.setProperty(node.id, name, parseColorToU32(value))
|
|
83
|
+
return
|
|
84
|
+
}
|
|
72
85
|
|
|
73
86
|
ffi.setProperty(node.id, name, value)
|
|
74
87
|
},
|
|
@@ -90,7 +103,7 @@ export let {
|
|
|
90
103
|
}
|
|
91
104
|
}
|
|
92
105
|
|
|
93
|
-
console.
|
|
106
|
+
// console.debug("[srt] insertNode", parent.id, node.id, anchor?.id ?? "")
|
|
94
107
|
|
|
95
108
|
if (anchor) ffi.insertNode(parent.id, node.id, anchor.id)
|
|
96
109
|
else ffi.insertNode(parent.id, node.id)
|
|
@@ -100,7 +113,7 @@ export let {
|
|
|
100
113
|
removeNode: (parent: ProxyNode, node: ProxyNode): void => {
|
|
101
114
|
if (!node || !parent) return
|
|
102
115
|
|
|
103
|
-
console.
|
|
116
|
+
// console.debug("[srt] removeNode", parent.id, node.id)
|
|
104
117
|
|
|
105
118
|
// Update JS tree references
|
|
106
119
|
let index = parent.children.indexOf(node)
|
|
@@ -112,12 +125,12 @@ export let {
|
|
|
112
125
|
ffi.deleteNode(parent.id, node.id)
|
|
113
126
|
|
|
114
127
|
// Recursively clean up node and all descendants
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
let cleanup = (n: ProxyNode) => {
|
|
129
|
+
for (let child of n.children) cleanup(child)
|
|
130
|
+
nodes.delete(n.id)
|
|
131
|
+
cleanupNodeHandlers(n.id)
|
|
132
|
+
}
|
|
133
|
+
cleanup(node)
|
|
121
134
|
},
|
|
122
135
|
|
|
123
136
|
getParentNode: (node: ProxyNode) => node?.parent,
|
package/src/types.d.ts
CHANGED
|
@@ -143,7 +143,9 @@ export interface AudioProps {
|
|
|
143
143
|
export interface RectProps extends Position, PaintProps, PointerProps {
|
|
144
144
|
w?: number
|
|
145
145
|
h?: number
|
|
146
|
-
|
|
146
|
+
// Corner radius. A single number applies to all four corners; an array is
|
|
147
|
+
// [top-left, top-right, bottom-right, bottom-left] (CSS border-radius order).
|
|
148
|
+
radius?: number | [number, number, number, number]
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
export interface OvalProps extends Position, PaintProps, PointerProps {
|
package/src/window.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { onCleanup, onSettled } from "@solidjs/signals"
|
|
2
|
+
import { getEventHandler } from "./events"
|
|
2
3
|
|
|
3
4
|
// ------ Animation frames ----------------
|
|
4
5
|
|
|
@@ -52,6 +53,9 @@ export function onResize(fn: (data: ResizeEvent) => void) {
|
|
|
52
53
|
|
|
53
54
|
export function attachWindow(_nodeId: number) {
|
|
54
55
|
let unsubscribe: () => void = null!
|
|
56
|
+
let unsubDown: () => void = null!
|
|
57
|
+
let unsubEnter: () => void = null!
|
|
58
|
+
let unsubLeave: () => void = null!
|
|
55
59
|
|
|
56
60
|
onSettled(() => {
|
|
57
61
|
unsubscribe = Flux.on("render", ({ time, frame }: { time: number, frame: number }) => {
|
|
@@ -66,11 +70,32 @@ export function attachWindow(_nodeId: number) {
|
|
|
66
70
|
draw()
|
|
67
71
|
})
|
|
68
72
|
|
|
73
|
+
unsubDown = Flux.on("pointerDown", ({ targets, button, clientX, clientY }: { targets: number[], button: number, clientX: number, clientY: number }) => {
|
|
74
|
+
for (let nodeId of targets) {
|
|
75
|
+
getEventHandler(nodeId, "onPointerDown")?.({ button, clientX, clientY })
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
unsubEnter = Flux.on("pointerEnter", ({ targets }: { targets: number[] }) => {
|
|
80
|
+
for (let nodeId of targets) {
|
|
81
|
+
getEventHandler(nodeId, "onPointerEnter")?.()
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
unsubLeave = Flux.on("pointerLeave", ({ targets }: { targets: number[] }) => {
|
|
86
|
+
for (let nodeId of targets) {
|
|
87
|
+
getEventHandler(nodeId, "onPointerLeave")?.()
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
|
|
69
91
|
// trigger first draw
|
|
70
92
|
draw()
|
|
71
93
|
})
|
|
72
94
|
|
|
73
95
|
onCleanup(() => {
|
|
74
96
|
if (unsubscribe) unsubscribe()
|
|
97
|
+
if (unsubDown) unsubDown()
|
|
98
|
+
if (unsubEnter) unsubEnter()
|
|
99
|
+
if (unsubLeave) unsubLeave()
|
|
75
100
|
})
|
|
76
101
|
}
|