@sigx/lynx-safe-area 0.4.2 → 0.4.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/README.md +0 -55
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
# @sigx/lynx-safe-area
|
|
2
|
-
|
|
3
2
|
Safe-area insets (notch, home indicator, status bar, navigation bar, keyboard) for sigx-lynx. Native publisher on iOS + Android emits insets every time they change; the JS side surfaces them as a reactive BG signal, four per-edge `SharedValue`s for MT-driven layout, and CSS variables for utility-class styling.
|
|
4
|
-
|
|
5
3
|
Mirrors React Native's `react-native-safe-area-context` API where it makes sense, but built for sigx-lynx's two-thread model so layout-bound insets don't bounce through the bridge.
|
|
6
|
-
|
|
7
4
|
## Install
|
|
8
|
-
|
|
9
5
|
```bash
|
|
10
6
|
pnpm add @sigx/lynx-safe-area
|
|
11
7
|
```
|
|
12
|
-
|
|
13
8
|
`sigx prebuild` auto-discovers the package, copies `SafeAreaPublisher.swift` / `SafeAreaPublisher.kt` into your `ios/` and `android/` source trees, and registers them in the auto-generated `GeneratedLifecyclePublishers.{swift,kt}` so they attach to every `LynxView` before first paint. No additional native wiring required.
|
|
14
|
-
|
|
15
9
|
## Quick start
|
|
16
|
-
|
|
17
10
|
Wrap your app once, anywhere above the views that need insets:
|
|
18
|
-
|
|
19
11
|
```tsx
|
|
20
12
|
import { defineApp } from '@sigx/lynx';
|
|
21
13
|
import { SafeAreaProvider, SafeAreaView } from '@sigx/lynx-safe-area';
|
|
22
|
-
|
|
23
14
|
defineApp(() => () => (
|
|
24
15
|
<SafeAreaProvider>
|
|
25
16
|
<SafeAreaView edges={['top', 'bottom']} class="bg-base-100">
|
|
@@ -28,64 +19,45 @@ defineApp(() => () => (
|
|
|
28
19
|
</SafeAreaProvider>
|
|
29
20
|
));
|
|
30
21
|
```
|
|
31
|
-
|
|
32
22
|
`<SafeAreaView>` reactively applies the current insets as `padding` (default) or `margin` to the configured `edges`. Inset-aware first paint: insets are seeded synchronously from `lynx.__globalProps` before render, so there's no flash of unsafe content.
|
|
33
|
-
|
|
34
23
|
**Sensible layout defaults** — `<SafeAreaProvider>` defaults its host
|
|
35
24
|
view to `height: 100vh` + `flex-direction: column`, and `<SafeAreaView>`
|
|
36
25
|
defaults to flex-fill long-form. Consumers don't need to add inline
|
|
37
26
|
`height: '100vh'` anchors or `flex-1` classes for the layout chain to
|
|
38
27
|
work. Pass `style={…}` to override.
|
|
39
|
-
|
|
40
28
|
## API
|
|
41
|
-
|
|
42
29
|
### `<SafeAreaProvider>`
|
|
43
|
-
|
|
44
30
|
Provides the context that hooks consume. Mount once at the app root.
|
|
45
|
-
|
|
46
31
|
| Prop | Type | Notes |
|
|
47
32
|
| ------- | --------------------------------- | ------------------------------------------- |
|
|
48
33
|
| `class` | `string` | Forwarded to the host `<view>`. |
|
|
49
34
|
| `style` | `Record<string, string \| number>` | Merged after the auto-injected CSS vars. |
|
|
50
|
-
|
|
51
35
|
The host view exposes the current insets as CSS variables (`--sat`, `--sar`, `--sab`, `--sal`, `--safe-area-keyboard`) — handy for utility-class consumers:
|
|
52
|
-
|
|
53
36
|
```tsx
|
|
54
37
|
<SafeAreaProvider>
|
|
55
38
|
<view class="pt-[var(--sat)] pb-[var(--sab)]">…</view>
|
|
56
39
|
</SafeAreaProvider>
|
|
57
40
|
```
|
|
58
|
-
|
|
59
41
|
### `<SafeAreaView>`
|
|
60
|
-
|
|
61
42
|
Drop-in container that applies insets as padding or margin.
|
|
62
|
-
|
|
63
43
|
| Prop | Type | Default |
|
|
64
44
|
| ------- | --------------------------------- | -------------------------------- |
|
|
65
45
|
| `edges` | `('top' \| 'right' \| 'bottom' \| 'left')[]` | All four sides |
|
|
66
46
|
| `mode` | `'padding' \| 'margin'` | `'padding'` |
|
|
67
47
|
| `class` | `string` | — |
|
|
68
48
|
| `style` | `Record<string, string \| number>` | Merged after inset styles |
|
|
69
|
-
|
|
70
49
|
Implementation note: applies insets via inline style (BG signal), not via `useAnimatedStyle`. `setStyleProperties` writes that affect layout fire **after** the first layout pass, and children that capture their frame eagerly (notably `<scroll-view>`) don't reflow when insets arrive that way. Inline style avoids the timing trap.
|
|
71
|
-
|
|
72
50
|
### `useSafeAreaInsets()`
|
|
73
|
-
|
|
74
51
|
```ts
|
|
75
52
|
function useSafeAreaInsets(): PrimitiveSignal<EdgeInsets> | Computed<EdgeInsets>;
|
|
76
53
|
```
|
|
77
|
-
|
|
78
54
|
Returns a BG-side reactive signal of `EdgeInsets`. Components calling this re-render on every inset change (rotation, keyboard show/hide, split-view resize on iPad).
|
|
79
|
-
|
|
80
55
|
```tsx
|
|
81
56
|
const insets = useSafeAreaInsets();
|
|
82
57
|
return () => <view style={{ paddingTop: `${insets.value.top}px` }}>…</view>;
|
|
83
58
|
```
|
|
84
|
-
|
|
85
59
|
If no `<SafeAreaProvider>` is in scope, returns a signal seeded with `ZERO_INSETS` and warns in dev (so test/storybook fragments degrade gracefully instead of throwing).
|
|
86
|
-
|
|
87
60
|
### `useSafeAreaSharedValues()`
|
|
88
|
-
|
|
89
61
|
```ts
|
|
90
62
|
function useSafeAreaSharedValues(): {
|
|
91
63
|
top: SharedValue<number>;
|
|
@@ -94,32 +66,22 @@ function useSafeAreaSharedValues(): {
|
|
|
94
66
|
left: SharedValue<number>;
|
|
95
67
|
} | null;
|
|
96
68
|
```
|
|
97
|
-
|
|
98
69
|
Per-edge `SharedValue`s for MT-driven `useAnimatedStyle` bindings. Use when an animation or gesture worklet needs the current inset on MT without a BG round-trip. Returns `null` outside of `<SafeAreaProvider>`.
|
|
99
|
-
|
|
100
70
|
### `useSafeAreaFrame(viewportWidth, viewportHeight)`
|
|
101
|
-
|
|
102
71
|
```ts
|
|
103
72
|
function useSafeAreaFrame(
|
|
104
73
|
viewportWidth: number,
|
|
105
74
|
viewportHeight: number,
|
|
106
75
|
): Computed<{ x: number; y: number; width: number; height: number }>;
|
|
107
76
|
```
|
|
108
|
-
|
|
109
77
|
Computed inner safe frame — `(x, y)` origin and `width`/`height` of the rect inside the insets. Useful for absolute-positioned overlays and modal bounds that need to know "the visible content rect", not just inset deltas.
|
|
110
|
-
|
|
111
78
|
`viewportWidth`/`viewportHeight` are caller-supplied (typically a one-time read via `@sigx/lynx-device-info`); the safe-area module deliberately doesn't pull device-info as a transitive dependency.
|
|
112
|
-
|
|
113
79
|
### `useSafeAreaInsetsMT()`
|
|
114
|
-
|
|
115
80
|
```ts
|
|
116
81
|
function useSafeAreaInsetsMT(): EdgeInsets;
|
|
117
82
|
```
|
|
118
|
-
|
|
119
83
|
Synchronous read from inside a `'main thread'`-marked worklet. Reads `lynx.__globalProps` directly — there's no signal subscription, so callers re-evaluate per worklet invocation rather than reactively. For declarative MT-driven layout the recommended path is `<SafeAreaView>` (which composes `useSafeAreaSharedValues()` with `useAnimatedStyle`).
|
|
120
|
-
|
|
121
84
|
### Types
|
|
122
|
-
|
|
123
85
|
```ts
|
|
124
86
|
interface EdgeInsets {
|
|
125
87
|
top: number;
|
|
@@ -135,25 +97,17 @@ interface EdgeInsets {
|
|
|
135
97
|
/** Navigation-bar height (Android gesture/3-button nav at bottom). */
|
|
136
98
|
navigationBar: number;
|
|
137
99
|
}
|
|
138
|
-
|
|
139
100
|
const ZERO_INSETS: EdgeInsets;
|
|
140
101
|
```
|
|
141
|
-
|
|
142
102
|
All values are in dp/pt (logical pixels), not raw pixels.
|
|
143
|
-
|
|
144
103
|
### Lower-level escape hatches
|
|
145
|
-
|
|
146
104
|
```ts
|
|
147
105
|
import { readGlobalSafeArea, GLOBAL_PROPS_KEY } from '@sigx/lynx-safe-area';
|
|
148
106
|
```
|
|
149
|
-
|
|
150
107
|
- `readGlobalSafeArea()` — synchronous one-shot read from `lynx.__globalProps`. Returns `EdgeInsets` (zeros if the publisher hasn't run yet). What `<SafeAreaProvider>` uses to seed initial values.
|
|
151
108
|
- `GLOBAL_PROPS_KEY` — the key the native publisher writes under. Exported for tests/debugging.
|
|
152
|
-
|
|
153
109
|
## CSS variables
|
|
154
|
-
|
|
155
110
|
The provider's host view exposes these on the element style — descendant selectors inherit them via the cascade:
|
|
156
|
-
|
|
157
111
|
| Variable | Maps to |
|
|
158
112
|
| ----------------------- | ---------------------------------------- |
|
|
159
113
|
| `--sat` | `insets.top` (in px) |
|
|
@@ -161,11 +115,8 @@ The provider's host view exposes these on the element style — descendant selec
|
|
|
161
115
|
| `--sab` | `insets.bottom` |
|
|
162
116
|
| `--sal` | `insets.left` |
|
|
163
117
|
| `--safe-area-keyboard` | `insets.keyboard` |
|
|
164
|
-
|
|
165
118
|
Works uniformly across iOS and Android — upstream's `env(safe-area-inset-*)` is iOS-only, so this is what you reach for if you're using DaisyUI/Tailwind utilities like `pt-[var(--sat)]`.
|
|
166
|
-
|
|
167
119
|
## How it works
|
|
168
|
-
|
|
169
120
|
```
|
|
170
121
|
┌──────────────────────────────────────┐
|
|
171
122
|
│ Native (iOS UIView / Android View) │
|
|
@@ -200,11 +151,5 @@ Works uniformly across iOS and Android — upstream's `env(safe-area-inset-*)` i
|
|
|
200
151
|
│ useSafeAreaInsets() consumers │
|
|
201
152
|
└──────────────────────────────────────┘
|
|
202
153
|
```
|
|
203
|
-
|
|
204
154
|
Why `SharedValue`s for the four edges but a plain `signal` for keyboard/statusBar/navigationBar? The four edges drive layout (`<SafeAreaView>` wants to write padding from a worklet on every flush) and the SV bridge is the right tool for that. The extras are informational — keyboard already lives in `bottom` on iOS, statusBar/navigationBar are decorative — so the SV plumbing isn't worth the cost there.
|
|
205
|
-
|
|
206
155
|
A custom `safeAreaChanged` event is used instead of upstream's `onGlobalPropsChanged` because the upstream event-name conventions have churned across Lynx releases and we want the contract in our hands.
|
|
207
|
-
|
|
208
|
-
## Reference app
|
|
209
|
-
|
|
210
|
-
`examples/lynx-one/my-sigx-app/src/App.tsx` mounts `<SafeAreaProvider>` and a `<SafeAreaView>` for the page chrome — useful as a copy-paste reference and as the smoke-test target when porting the publisher to a new platform.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigx/lynx-safe-area",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Safe area insets (notch, home indicator, status bar, keyboard) for sigx-lynx",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,15 +31,15 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@sigx/reactivity": "^0.4.8",
|
|
34
|
-
"@sigx/lynx
|
|
35
|
-
"@sigx/lynx": "^0.4.
|
|
34
|
+
"@sigx/lynx": "^0.4.3",
|
|
35
|
+
"@sigx/lynx-runtime-internal": "^0.4.3"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@typescript/native-preview": "7.0.0-dev.20260521.1",
|
|
39
39
|
"typescript": "^6.0.3",
|
|
40
|
-
"@sigx/lynx-runtime-main": "^0.4.
|
|
41
|
-
"@sigx/lynx-
|
|
42
|
-
"@sigx/lynx-
|
|
40
|
+
"@sigx/lynx-runtime-main": "^0.4.3",
|
|
41
|
+
"@sigx/lynx-plugin": "^0.4.3",
|
|
42
|
+
"@sigx/lynx-testing": "^0.4.3"
|
|
43
43
|
},
|
|
44
44
|
"repository": {
|
|
45
45
|
"type": "git",
|