@solidrt/core 0.0.7 → 0.0.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 +2 -2
- package/src/index.ts +1 -1
- package/src/types.d.ts +9 -0
- package/src/window.ts +24 -42
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidrt/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Antoine van Wel",
|
|
6
6
|
"type": "module",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"colord": "^2.9.3"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@solidrt/flux-types": "0.0.
|
|
23
|
+
"@solidrt/flux-types": "0.0.9"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"@solidjs/signals": "2.0.0-beta.14",
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from "./renderer"
|
|
2
2
|
export { setFocus, getFocusedNodeId, measureText, getBoundingBox } from "./core"
|
|
3
3
|
export type { BoundingBox } from "./core"
|
|
4
|
-
export { onFrame,
|
|
4
|
+
export { onFrame, onLayout, onResize, onWindowFocus, onWindowBlur } from "./window"
|
|
5
5
|
export { createTexture, decodeImage } from "./gpu"
|
|
6
6
|
export type { DecodedImage } from "./gpu"
|
|
7
7
|
export type {
|
package/src/types.d.ts
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
import type { JSX as SolidJSX } from "@solidjs/signals"
|
|
4
4
|
|
|
5
5
|
declare global {
|
|
6
|
+
function requestAnimationFrame(callback: (time: number) => void): number
|
|
7
|
+
function cancelAnimationFrame(id: number): void
|
|
8
|
+
|
|
9
|
+
// UI event bus (lattice). on/once return an unsubscribe function.
|
|
10
|
+
let srt: {
|
|
11
|
+
on(event: string, callback: (data: any) => void): () => void
|
|
12
|
+
once(event: string, callback: (data: any) => void): () => void
|
|
13
|
+
}
|
|
14
|
+
|
|
6
15
|
let ffi: {
|
|
7
16
|
createRoot(id: number): void
|
|
8
17
|
createNode(id: number, kind: string): void
|
package/src/window.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { onCleanup, onSettled, flush
|
|
1
|
+
import { onCleanup, onSettled, flush } from "@solidjs/signals"
|
|
2
2
|
import { getEventHandler, getFocusedNodeId, setFocus } from "./core"
|
|
3
3
|
|
|
4
4
|
// ------ Animation frames ----------------
|
|
@@ -11,10 +11,12 @@ let animationFrames = new Map<number, Function>()
|
|
|
11
11
|
let refreshRate = 60
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Calls `fn` before every frame is painted
|
|
15
|
-
* is the
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* Calls `fn` before every frame is painted: `tick` is the time in ms, `frame` is
|
|
15
|
+
* the present count, and `rate` is the current refresh rate in Hz. `tick` is paced
|
|
16
|
+
* by the runtime (one refresh period per present, slow-corrected toward the wall
|
|
17
|
+
* clock) so animations driven off it stay smooth even when swap-return times
|
|
18
|
+
* jitter. For raw, continuous wall-clock time (e.g. measuring code), use
|
|
19
|
+
* performance.now() instead.
|
|
18
20
|
* Returns a cleanup function; also auto-cleans within a reactive scope.
|
|
19
21
|
*/
|
|
20
22
|
export function onFrame(fn: (tick: number, frame: number, rate: number) => void) {
|
|
@@ -34,26 +36,6 @@ export function onFrame(fn: (tick: number, frame: number, rate: number) => void)
|
|
|
34
36
|
return cleanup
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
/**
|
|
38
|
-
* Opt-in smooth clock built on the raw onFrame signals. Paces by present count
|
|
39
|
-
* (one refresh period per frame) and slowly corrects toward the raw wall-clock
|
|
40
|
-
* tick, so it stays smooth while keeping up and tracks real time when the
|
|
41
|
-
* framerate drops. `gain` (0..1) trades convergence speed for jitter. Returns an
|
|
42
|
-
* accessor for the paced time in milliseconds.
|
|
43
|
-
*/
|
|
44
|
-
export function createPacedClock(opts?: { gain?: number }) {
|
|
45
|
-
let gain = opts?.gain ?? 0.05
|
|
46
|
-
let [time, setTime] = createSignal(0)
|
|
47
|
-
let clock = 0
|
|
48
|
-
onFrame((tick, _frame, rate) => {
|
|
49
|
-
let period = 1000 / rate
|
|
50
|
-
clock += period
|
|
51
|
-
clock += (tick - clock) * gain
|
|
52
|
-
setTime(clock)
|
|
53
|
-
})
|
|
54
|
-
return time
|
|
55
|
-
}
|
|
56
|
-
|
|
57
39
|
// ------ Resize ----------------
|
|
58
40
|
|
|
59
41
|
interface SafeArea {
|
|
@@ -71,7 +53,7 @@ interface ResizeEvent {
|
|
|
71
53
|
}
|
|
72
54
|
|
|
73
55
|
export function onResize(fn: (data: ResizeEvent) => void) {
|
|
74
|
-
let unsubscribe =
|
|
56
|
+
let unsubscribe = srt.on("resize", fn)
|
|
75
57
|
onCleanup(unsubscribe)
|
|
76
58
|
return unsubscribe
|
|
77
59
|
}
|
|
@@ -81,19 +63,19 @@ export function onResize(fn: (data: ResizeEvent) => void) {
|
|
|
81
63
|
// by a re-layout pass before painting (one extra pass; cascades beyond that
|
|
82
64
|
// paint stale).
|
|
83
65
|
export function onLayout(fn: () => void) {
|
|
84
|
-
let unsubscribe =
|
|
66
|
+
let unsubscribe = srt.on("postLayout", fn)
|
|
85
67
|
onCleanup(unsubscribe)
|
|
86
68
|
return unsubscribe
|
|
87
69
|
}
|
|
88
70
|
|
|
89
71
|
export function onWindowFocus(fn: () => void) {
|
|
90
|
-
let unsubscribe =
|
|
72
|
+
let unsubscribe = srt.on("windowFocus", fn)
|
|
91
73
|
onCleanup(unsubscribe)
|
|
92
74
|
return unsubscribe
|
|
93
75
|
}
|
|
94
76
|
|
|
95
77
|
export function onWindowBlur(fn: () => void) {
|
|
96
|
-
let unsubscribe =
|
|
78
|
+
let unsubscribe = srt.on("windowBlur", fn)
|
|
97
79
|
onCleanup(unsubscribe)
|
|
98
80
|
return unsubscribe
|
|
99
81
|
}
|
|
@@ -127,15 +109,15 @@ export function attachWindow(_nodeId: number) {
|
|
|
127
109
|
|
|
128
110
|
onSettled(() => {
|
|
129
111
|
// Sticky event: a late subscriber still receives the current rate.
|
|
130
|
-
unsubRefreshRate =
|
|
112
|
+
unsubRefreshRate = srt.on("displayRefreshRate", ({ hz }: { hz: number }) => {
|
|
131
113
|
if (hz > 0) refreshRate = hz
|
|
132
114
|
})
|
|
133
115
|
|
|
134
|
-
unsubscribe =
|
|
116
|
+
unsubscribe = srt.on("render", ({ time, frame }: { time: number; frame: number }) => {
|
|
135
117
|
runFrame(time * 1000, frame)
|
|
136
118
|
})
|
|
137
119
|
|
|
138
|
-
unsubDown =
|
|
120
|
+
unsubDown = srt.on(
|
|
139
121
|
"pointerDown",
|
|
140
122
|
({ targets, ...e }: { targets: number[]; [k: string]: any }) => {
|
|
141
123
|
for (let nodeId of targets) {
|
|
@@ -150,13 +132,13 @@ export function attachWindow(_nodeId: number) {
|
|
|
150
132
|
},
|
|
151
133
|
)
|
|
152
134
|
|
|
153
|
-
unsubUp =
|
|
135
|
+
unsubUp = srt.on("pointerUp", ({ targets, ...e }: { targets: number[]; [k: string]: any }) => {
|
|
154
136
|
for (let nodeId of targets) {
|
|
155
137
|
getEventHandler(nodeId, "onPointerUp")?.(e)
|
|
156
138
|
}
|
|
157
139
|
})
|
|
158
140
|
|
|
159
|
-
unsubMove =
|
|
141
|
+
unsubMove = srt.on(
|
|
160
142
|
"pointerMove",
|
|
161
143
|
({ targets, ...e }: { targets: number[]; [k: string]: any }) => {
|
|
162
144
|
for (let nodeId of targets) {
|
|
@@ -165,7 +147,7 @@ export function attachWindow(_nodeId: number) {
|
|
|
165
147
|
},
|
|
166
148
|
)
|
|
167
149
|
|
|
168
|
-
unsubEnter =
|
|
150
|
+
unsubEnter = srt.on(
|
|
169
151
|
"pointerEnter",
|
|
170
152
|
({ targets, ...e }: { targets: number[]; [k: string]: any }) => {
|
|
171
153
|
for (let nodeId of targets) {
|
|
@@ -174,7 +156,7 @@ export function attachWindow(_nodeId: number) {
|
|
|
174
156
|
},
|
|
175
157
|
)
|
|
176
158
|
|
|
177
|
-
unsubLeave =
|
|
159
|
+
unsubLeave = srt.on(
|
|
178
160
|
"pointerLeave",
|
|
179
161
|
({ targets, ...e }: { targets: number[]; [k: string]: any }) => {
|
|
180
162
|
for (let nodeId of targets) {
|
|
@@ -183,27 +165,27 @@ export function attachWindow(_nodeId: number) {
|
|
|
183
165
|
},
|
|
184
166
|
)
|
|
185
167
|
|
|
186
|
-
unsubWheel =
|
|
168
|
+
unsubWheel = srt.on("wheel", ({ targets, ...e }: { targets: number[]; [k: string]: any }) => {
|
|
187
169
|
for (let nodeId of targets) {
|
|
188
170
|
getEventHandler(nodeId, "onWheel")?.(e)
|
|
189
171
|
}
|
|
190
172
|
})
|
|
191
173
|
|
|
192
|
-
unsubKeyDown =
|
|
174
|
+
unsubKeyDown = srt.on("keydown", (e: any) => {
|
|
193
175
|
let id = getFocusedNodeId()
|
|
194
176
|
if (id != null) {
|
|
195
177
|
getEventHandler(id, "onKeyDown")?.(e)
|
|
196
178
|
}
|
|
197
179
|
})
|
|
198
180
|
|
|
199
|
-
unsubKeyUp =
|
|
181
|
+
unsubKeyUp = srt.on("keyup", (e: any) => {
|
|
200
182
|
let id = getFocusedNodeId()
|
|
201
183
|
if (id != null) {
|
|
202
184
|
getEventHandler(id, "onKeyUp")?.(e)
|
|
203
185
|
}
|
|
204
186
|
})
|
|
205
187
|
|
|
206
|
-
unsubTextInput =
|
|
188
|
+
unsubTextInput = srt.on("textInput", (e: any) => {
|
|
207
189
|
let id = getFocusedNodeId()
|
|
208
190
|
if (id != null) {
|
|
209
191
|
getEventHandler(id, "onTextInput")?.(e)
|
|
@@ -212,7 +194,7 @@ export function attachWindow(_nodeId: number) {
|
|
|
212
194
|
|
|
213
195
|
// When the user dismisses the on-screen keyboard (swipe down, "Done",
|
|
214
196
|
// back button), blur the focused node so the app's UI state catches up.
|
|
215
|
-
unsubKeyboardVisibility =
|
|
197
|
+
unsubKeyboardVisibility = srt.on("keyboardVisibility", ({ shown }: { shown: boolean }) => {
|
|
216
198
|
if (!shown) setFocus(null)
|
|
217
199
|
})
|
|
218
200
|
|
|
@@ -223,7 +205,7 @@ export function attachWindow(_nodeId: number) {
|
|
|
223
205
|
// synchronously here, while we are still inside this onSettled callback
|
|
224
206
|
// where flush() is illegal (not reentrant). Defer runFrame to a microtask
|
|
225
207
|
// so the first frame always runs after this callback returns.
|
|
226
|
-
unsubFirstResize =
|
|
208
|
+
unsubFirstResize = srt.once("resize", () => {
|
|
227
209
|
queueMicrotask(() => runFrame(0, 0))
|
|
228
210
|
})
|
|
229
211
|
})
|