@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/components",
3
- "version": "0.0.38",
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.20",
21
- "@solidrt/core": "0.0.38"
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={press.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
- let state = (): PressState => ({ pressed: pressed(), hovered: hovered() })
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
@@ -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 with a hairline between, single-pane shows one pane at a
24
- * time per `showDetail`. Keep pane state (selection, scroll) in the app, not
25
- * in the panes: crossing a breakpoint re-arranges and can remount them.
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>