@solidrt/components 0.0.38 → 0.0.39
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 +3 -3
- package/src/button.tsx +5 -1
- package/src/press.ts +21 -1
- package/src/pressable.tsx +7 -1
- package/src/split-view.tsx +10 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidrt/components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.39",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Antoine van Wel",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"qrcode-generator": "^2.0.4"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@solidjs/signals": "2.0.0-beta.
|
|
21
|
-
"@solidrt/core": "0.0.
|
|
20
|
+
"@solidjs/signals": "2.0.0-beta.26",
|
|
21
|
+
"@solidrt/core": "0.0.39"
|
|
22
22
|
}
|
|
23
23
|
}
|
package/src/button.tsx
CHANGED
|
@@ -24,6 +24,7 @@ export interface ButtonProps {
|
|
|
24
24
|
size?: ButtonSize
|
|
25
25
|
onPress?: () => void
|
|
26
26
|
disabled?: boolean
|
|
27
|
+
ref?: (node: { id: number }) => void
|
|
27
28
|
layout?: LayoutProps
|
|
28
29
|
style?: StyleProps
|
|
29
30
|
}
|
|
@@ -93,7 +94,10 @@ export function Button(props: ButtonProps) {
|
|
|
93
94
|
|
|
94
95
|
return (
|
|
95
96
|
<view
|
|
96
|
-
ref={
|
|
97
|
+
ref={(n: { id: number }) => {
|
|
98
|
+
press.ref(n)
|
|
99
|
+
props.ref?.(n)
|
|
100
|
+
}}
|
|
97
101
|
repaintBoundary
|
|
98
102
|
flexDirection="row"
|
|
99
103
|
alignItems="center"
|
package/src/press.ts
CHANGED
|
@@ -2,6 +2,10 @@ import { createSignal, onSettled, getBoundingBoxViewport } from "@solidrt/core"
|
|
|
2
2
|
import type { PointerEvent } from "@solidrt/core"
|
|
3
3
|
import { claim, release } from "./arena"
|
|
4
4
|
|
|
5
|
+
// A live view of a recognizer's state, not a snapshot: both fields are getters,
|
|
6
|
+
// so a consumer that reads one inside a JSX prop or child expression tracks that
|
|
7
|
+
// signal there and nothing else re-runs. Read them in those positions, not
|
|
8
|
+
// eagerly into a local, or the read lands in whatever scope destructured it.
|
|
5
9
|
export type PressState = { pressed: boolean; hovered: boolean }
|
|
6
10
|
|
|
7
11
|
export interface PressOptions {
|
|
@@ -43,7 +47,23 @@ export function createPress(options: PressOptions) {
|
|
|
43
47
|
let active: number | null = null
|
|
44
48
|
let inside = false
|
|
45
49
|
|
|
46
|
-
|
|
50
|
+
// One stable object of getters, handed out as-is. Returning a fresh snapshot
|
|
51
|
+
// instead would read both signals at call time, making them dependencies of
|
|
52
|
+
// the caller's scope - and for render-prop children that scope is the one
|
|
53
|
+
// that builds the subtree, so a hover or press would rebuild it. A rebuild
|
|
54
|
+
// mid-gesture replaces a nested recognizer with a fresh one that never saw
|
|
55
|
+
// the down, so its up fires nothing: invisible with a mouse (hover settles
|
|
56
|
+
// long before the click) and fatal on touch, where the finger's arrival flips
|
|
57
|
+
// the ancestor's hover during the very gesture it is meant to recognize.
|
|
58
|
+
let live: PressState = {
|
|
59
|
+
get pressed() {
|
|
60
|
+
return pressed()
|
|
61
|
+
},
|
|
62
|
+
get hovered() {
|
|
63
|
+
return hovered()
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
let state = (): PressState => live
|
|
47
67
|
let ref = (n: { id: number }) => {
|
|
48
68
|
node = n
|
|
49
69
|
}
|
package/src/pressable.tsx
CHANGED
|
@@ -7,7 +7,9 @@ export type { PressState } from "./press"
|
|
|
7
7
|
|
|
8
8
|
export interface PressableProps extends PointerProps {
|
|
9
9
|
// children and style may be functions of the press state, so a caller can
|
|
10
|
-
// restyle on press/hover without wiring their own signals.
|
|
10
|
+
// restyle on press/hover without wiring their own signals. The state is live
|
|
11
|
+
// (getters, not a snapshot): read it inside a prop or child expression, never
|
|
12
|
+
// eagerly into a local, or the value is captured once where it was read.
|
|
11
13
|
children?: any | ((state: PressState) => any)
|
|
12
14
|
ref?: (node: { id: number }) => void
|
|
13
15
|
layout?: LayoutProps
|
|
@@ -29,6 +31,10 @@ export function Pressable(props: PressableProps) {
|
|
|
29
31
|
// ((state) => ...) passes through it intact because flatten only unwraps
|
|
30
32
|
// zero-arg functions.
|
|
31
33
|
let resolved = children(() => props.children)
|
|
34
|
+
// The render prop runs once: the state it receives is a live object of getters
|
|
35
|
+
// (see press.ts), so a press or hover updates only the props that read it
|
|
36
|
+
// rather than rebuilding this subtree - which is what keeps a nested
|
|
37
|
+
// recognizer's in-flight gesture alive.
|
|
32
38
|
let kids = () => {
|
|
33
39
|
// children()'s return type erases the render-prop variant, hence the any.
|
|
34
40
|
let c = resolved() as any
|
package/src/split-view.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Show } from "@solidrt/core"
|
|
2
2
|
import type { LayoutProps } from "@solidrt/core"
|
|
3
|
-
import { theme } from "./theme"
|
|
4
3
|
import { policy } from "./policy"
|
|
5
4
|
|
|
6
5
|
export interface SplitViewProps {
|
|
@@ -20,11 +19,18 @@ const LIST_WIDTH = 320
|
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
21
|
* A list-detail container driven by the layout policy: two-pane shows the list
|
|
23
|
-
* beside the detail
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* beside the detail, single-pane shows one pane at a time per `showDetail`.
|
|
23
|
+
* Keep pane state (selection, scroll) in the app, not in the panes: crossing
|
|
24
|
+
* a breakpoint re-arranges and can remount them.
|
|
26
25
|
* SplitView draws no chrome; a back affordance in the single-pane detail is
|
|
27
26
|
* the app's to render (fork on policy.layout, as the shell example does).
|
|
27
|
+
*
|
|
28
|
+
* Panes get no padding, max-width or alignment either - that is content, and
|
|
29
|
+
* SplitView cannot know the intended reading width. Give the single-pane
|
|
30
|
+
* detail the same treatment as the list (centered max-width column), otherwise
|
|
31
|
+
* crossing the breakpoint leaves the detail hugging the window's left edge
|
|
32
|
+
* while every other screen stays centered. Two-pane wants the opposite: the
|
|
33
|
+
* detail sits against the pane edge, since the pane already bounds its width.
|
|
28
34
|
*/
|
|
29
35
|
export function SplitView(props: SplitViewProps) {
|
|
30
36
|
return (
|
|
@@ -42,9 +48,6 @@ export function SplitView(props: SplitViewProps) {
|
|
|
42
48
|
<view width={props.listWidth ?? LIST_WIDTH} flexDirection="column">
|
|
43
49
|
{props.list}
|
|
44
50
|
</view>
|
|
45
|
-
<view width={1}>
|
|
46
|
-
<d-rect color={theme.color.border} />
|
|
47
|
-
</view>
|
|
48
51
|
<view flex={1} flexDirection="column">
|
|
49
52
|
{props.detail}
|
|
50
53
|
</view>
|