@solidrt/core 0.0.1 → 0.0.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/package.json +5 -1
- package/src/focus.ts +6 -0
- package/src/index.ts +3 -1
- package/src/renderer.ts +4 -1
- package/src/text.ts +5 -0
- package/src/types.d.ts +24 -4
- package/src/window.ts +34 -1
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidrt/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"license": "MIT",
|
|
5
|
+
"author": "Antoine van Wel",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "src/index.ts",
|
|
7
8
|
"exports": {
|
|
@@ -17,6 +18,9 @@
|
|
|
17
18
|
"dependencies": {
|
|
18
19
|
"colord": "^2.9.3"
|
|
19
20
|
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@solidrt/flux-types": "0.0.3"
|
|
23
|
+
},
|
|
20
24
|
"peerDependencies": {
|
|
21
25
|
"@solidjs/signals": "2.0.0-beta.13",
|
|
22
26
|
"@solidjs/universal": "2.0.0-beta.13"
|
package/src/focus.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { getEventHandler } from "./events"
|
|
|
3
3
|
// Currently-focused node id. Reset to null automatically across engine
|
|
4
4
|
// reloads because the JS environment is rebuilt from scratch.
|
|
5
5
|
let focusedNodeId: number | null = null
|
|
6
|
+
let textInputActive = false
|
|
6
7
|
|
|
7
8
|
export function setFocus(nodeId: number | null): void {
|
|
8
9
|
if (nodeId === focusedNodeId) return
|
|
@@ -14,6 +15,11 @@ export function setFocus(nodeId: number | null): void {
|
|
|
14
15
|
if (nodeId != null) {
|
|
15
16
|
getEventHandler(nodeId, "onFocus")?.()
|
|
16
17
|
}
|
|
18
|
+
let wantActive = nodeId != null && getEventHandler(nodeId, "onTextInput") != null
|
|
19
|
+
if (wantActive !== textInputActive) {
|
|
20
|
+
textInputActive = wantActive
|
|
21
|
+
ffi.setTextInputActive(wantActive)
|
|
22
|
+
}
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
export function getFocusedNodeId(): number | null {
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export * from "./renderer"
|
|
2
2
|
export { setFocus, getFocusedNodeId } from "./focus"
|
|
3
|
-
export { onRender, onResize, onWindowFocus, onWindowBlur } from "./window"
|
|
3
|
+
export { onRender, onLayout, onResize, onWindowFocus, onWindowBlur } from "./window"
|
|
4
|
+
export { measureText } from "./text"
|
|
5
|
+
export type { MeasureTextOptions } from "./types"
|
package/src/renderer.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { createRenderer } from "@solidjs/universal"
|
|
|
3
3
|
import { attachWindow } from "./window"
|
|
4
4
|
import { parseColorToU32, isColorProp } from "./color"
|
|
5
5
|
import { setEventHandler, cleanupNodeHandlers } from "./events"
|
|
6
|
+
import { getFocusedNodeId, setFocus } from "./focus"
|
|
6
7
|
|
|
7
8
|
export { getEventHandler } from "./events"
|
|
8
9
|
|
|
@@ -124,9 +125,11 @@ export let {
|
|
|
124
125
|
|
|
125
126
|
ffi.deleteNode(parent.id, node.id)
|
|
126
127
|
|
|
127
|
-
// Recursively clean up node and all descendants
|
|
128
|
+
// Recursively clean up node and all descendants. Clear focus before
|
|
129
|
+
// dropping handlers so onBlur still fires for a focused descendant.
|
|
128
130
|
let cleanup = (n: ProxyNode) => {
|
|
129
131
|
for (let child of n.children) cleanup(child)
|
|
132
|
+
if (n.id === getFocusedNodeId()) setFocus(null)
|
|
130
133
|
nodes.delete(n.id)
|
|
131
134
|
cleanupNodeHandlers(n.id)
|
|
132
135
|
}
|
package/src/text.ts
ADDED
package/src/types.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
+
/// <reference types="@solidrt/flux-types" />
|
|
2
|
+
|
|
1
3
|
import type { Accessor, JSX as SolidJSX } from "@solidjs/signals"
|
|
2
4
|
|
|
3
5
|
declare global {
|
|
4
|
-
let Flux: {
|
|
5
|
-
on(event: string, callback: (data: any) => void): () => void
|
|
6
|
-
}
|
|
7
6
|
|
|
8
7
|
let ffi: {
|
|
9
8
|
createRoot(id: number): void
|
|
@@ -11,9 +10,19 @@ declare global {
|
|
|
11
10
|
insertNode(parentId: number, nodeId: number, anchorId?: number): void
|
|
12
11
|
deleteNode(parentId: number, nodeId: number): void
|
|
13
12
|
setProperty(nodeId: number, name: string, value: unknown): void
|
|
13
|
+
setTextInputActive(active: boolean): void
|
|
14
|
+
measureText(text: string, options?: MeasureTextOptions): { width: number, height: number }
|
|
14
15
|
}
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
export interface MeasureTextOptions {
|
|
19
|
+
fontFamily?: "sans" | "mono" | (string & {})
|
|
20
|
+
fontSize?: number
|
|
21
|
+
fontStyle?: "normal" | "italic"
|
|
22
|
+
fontWeight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
|
23
|
+
maxLines?: number
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
type Children = SolidJSX.Element
|
|
18
27
|
|
|
19
28
|
type OA<T> = T | Accessor<T>
|
|
@@ -22,6 +31,7 @@ interface FlexboxProps {
|
|
|
22
31
|
gap?: number
|
|
23
32
|
rowGap?: number
|
|
24
33
|
columnGap?: number
|
|
34
|
+
flex?: number | "none" | "auto" | (string & {})
|
|
25
35
|
flexGrow?: number
|
|
26
36
|
flexShrink?: number
|
|
27
37
|
flexBasis?: number
|
|
@@ -77,6 +87,8 @@ export interface LayoutProps extends FlexboxProps, GridProps {
|
|
|
77
87
|
marginLeft?: Dimension
|
|
78
88
|
|
|
79
89
|
overflow?: "visible" | "clip" | "hidden" | "scroll"
|
|
90
|
+
overflowX?: "visible" | "clip" | "hidden" | "scroll"
|
|
91
|
+
overflowY?: "visible" | "clip" | "hidden" | "scroll"
|
|
80
92
|
}
|
|
81
93
|
|
|
82
94
|
import type { LCH } from "./color"
|
|
@@ -97,6 +109,10 @@ export interface TransformProps {
|
|
|
97
109
|
scale?: OA<number>
|
|
98
110
|
x?: OA<number>
|
|
99
111
|
y?: OA<number>
|
|
112
|
+
cx?: OA<number>
|
|
113
|
+
cy?: OA<number>
|
|
114
|
+
scrollX?: OA<number>
|
|
115
|
+
scrollY?: OA<number>
|
|
100
116
|
}
|
|
101
117
|
|
|
102
118
|
export interface PointerProps {
|
|
@@ -124,6 +140,7 @@ interface Position {
|
|
|
124
140
|
export interface WindowProps extends LayoutProps {
|
|
125
141
|
children?: Children
|
|
126
142
|
title?: string
|
|
143
|
+
fullscreen?: boolean
|
|
127
144
|
vsync?: boolean
|
|
128
145
|
fps?: boolean
|
|
129
146
|
}
|
|
@@ -159,9 +176,12 @@ export interface PathProps extends Position, PaintProps, PointerProps {
|
|
|
159
176
|
}
|
|
160
177
|
|
|
161
178
|
export interface TextProps extends PaintProps {
|
|
162
|
-
children
|
|
179
|
+
children?: Children
|
|
180
|
+
fontFamily?: "sans" | "mono" | (string & {})
|
|
163
181
|
fontSize?: number
|
|
182
|
+
lineHeight?: number
|
|
164
183
|
fontStyle?: "normal" | "italic"
|
|
184
|
+
fontWeight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
|
165
185
|
textAlign?: "left" | "right" | "center" | "justify"
|
|
166
186
|
maxLines?: number
|
|
167
187
|
}
|
package/src/window.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { onCleanup, onSettled } from "@solidjs/signals"
|
|
2
2
|
import { getEventHandler } from "./events"
|
|
3
|
-
import { getFocusedNodeId } from "./focus"
|
|
3
|
+
import { getFocusedNodeId, setFocus } from "./focus"
|
|
4
4
|
|
|
5
5
|
// ------ Animation frames ----------------
|
|
6
6
|
|
|
@@ -50,6 +50,16 @@ export function onResize(fn: (data: ResizeEvent) => void) {
|
|
|
50
50
|
return unsubscribe
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
// Fires after layout has been computed for the current frame but before paint.
|
|
54
|
+
// Setting properties that affect layout from this callback will be picked up
|
|
55
|
+
// by a re-layout pass before painting (one extra pass; cascades beyond that
|
|
56
|
+
// paint stale).
|
|
57
|
+
export function onLayout(fn: () => void) {
|
|
58
|
+
let unsubscribe = Flux.on("postLayout", fn)
|
|
59
|
+
onCleanup(unsubscribe)
|
|
60
|
+
return unsubscribe
|
|
61
|
+
}
|
|
62
|
+
|
|
53
63
|
export function onWindowFocus(fn: () => void) {
|
|
54
64
|
let unsubscribe = Flux.on("windowFocus", fn)
|
|
55
65
|
onCleanup(unsubscribe)
|
|
@@ -74,6 +84,8 @@ export function attachWindow(_nodeId: number) {
|
|
|
74
84
|
let unsubWheel: () => void = null!
|
|
75
85
|
let unsubKeyDown: () => void = null!
|
|
76
86
|
let unsubKeyUp: () => void = null!
|
|
87
|
+
let unsubTextInput: () => void = null!
|
|
88
|
+
let unsubKeyboardVisibility: () => void = null!
|
|
77
89
|
|
|
78
90
|
onSettled(() => {
|
|
79
91
|
unsubscribe = Flux.on("render", ({ time, frame }: { time: number, frame: number }) => {
|
|
@@ -92,6 +104,12 @@ export function attachWindow(_nodeId: number) {
|
|
|
92
104
|
for (let nodeId of targets) {
|
|
93
105
|
getEventHandler(nodeId, "onPointerDown")?.(e)
|
|
94
106
|
}
|
|
107
|
+
// Outside-tap blur. Read focus AFTER per-node handlers so a tap that
|
|
108
|
+
// moves focus to a new node is not immediately blurred again.
|
|
109
|
+
let focused = getFocusedNodeId()
|
|
110
|
+
if (focused != null && !targets.includes(focused)) {
|
|
111
|
+
setFocus(null)
|
|
112
|
+
}
|
|
95
113
|
})
|
|
96
114
|
|
|
97
115
|
unsubUp = Flux.on("pointerUp", ({ targets, ...e }: { targets: number[], [k: string]: any }) => {
|
|
@@ -138,6 +156,19 @@ export function attachWindow(_nodeId: number) {
|
|
|
138
156
|
}
|
|
139
157
|
})
|
|
140
158
|
|
|
159
|
+
unsubTextInput = Flux.on("textInput", (e: any) => {
|
|
160
|
+
let id = getFocusedNodeId()
|
|
161
|
+
if (id != null) {
|
|
162
|
+
getEventHandler(id, "onTextInput")?.(e)
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// When the user dismisses the on-screen keyboard (swipe down, "Done",
|
|
167
|
+
// back button), blur the focused node so the app's UI state catches up.
|
|
168
|
+
unsubKeyboardVisibility = Flux.on("keyboardVisibility", ({ shown }: { shown: boolean }) => {
|
|
169
|
+
if (!shown) setFocus(null)
|
|
170
|
+
})
|
|
171
|
+
|
|
141
172
|
// trigger first draw
|
|
142
173
|
draw()
|
|
143
174
|
})
|
|
@@ -152,5 +183,7 @@ export function attachWindow(_nodeId: number) {
|
|
|
152
183
|
if (unsubWheel) unsubWheel()
|
|
153
184
|
if (unsubKeyDown) unsubKeyDown()
|
|
154
185
|
if (unsubKeyUp) unsubKeyUp()
|
|
186
|
+
if (unsubTextInput) unsubTextInput()
|
|
187
|
+
if (unsubKeyboardVisibility) unsubKeyboardVisibility()
|
|
155
188
|
})
|
|
156
189
|
}
|