@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.
Files changed (2) hide show
  1. package/README.md +0 -55
  2. 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.2",
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-runtime-internal": "^0.4.2",
35
- "@sigx/lynx": "^0.4.2"
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.2",
41
- "@sigx/lynx-testing": "^0.4.2",
42
- "@sigx/lynx-plugin": "^0.4.2"
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",