@delacour/react-native-ui 0.5.0-alpha.20261021212209 → 0.5.0-alpha.20261022200024

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": "@delacour/react-native-ui",
3
- "version": "0.5.0-alpha.20261021212209",
3
+ "version": "0.5.0-alpha.20261022200024",
4
4
  "description": "React Native UI components — Uniwind, Reanimated, Gesture Handler",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -162,7 +162,6 @@
162
162
  "./lib/scroll-edges": "./src/lib/scroll-edges.ts",
163
163
  "./lib/scroll-maths": "./src/lib/scroll-maths.ts",
164
164
  "./lib/scroll-sections": "./src/lib/scroll-sections.ts",
165
- "./lib/skia-native-id": "./src/lib/skia-native-id.ts",
166
165
  "./lib/slot": "./src/lib/slot.tsx",
167
166
  "./lib/tv": "./src/lib/tv.ts",
168
167
  "./lib/wrap-text-children": "./src/lib/wrap-text-children.ts",
@@ -184,9 +183,9 @@
184
183
  "@maplibre/maplibre-react-native": "^11.5.0",
185
184
  "@central-icons-react-native/round-outlined-radius-1-stroke-1.5": "^1.1",
186
185
  "@delacour/react-native-bottom-sheet": ">=0.2.0",
187
- "@delacour/react-native-charts": "0.2.0-alpha.20261021212209",
186
+ "@delacour/react-native-charts": "0.2.0-alpha.20261022200024",
188
187
  "@legendapp/list": ">=3.3",
189
- "react-native-skia": ">=3",
188
+ "react-native-skia": ">=3.7.3",
190
189
  "expo-linear-gradient": ">=15",
191
190
  "expo-router": ">=57",
192
191
  "react": ">=19",
@@ -79,10 +79,6 @@ parts: `Background`, `Node`, `Handle`, `Edge`, `Group`, `Controls`, `MiniMap`, a
79
79
  the canvas — the trick `@delacour/react-native-charts` uses. A part off the canvas gets `null`
80
80
  from `useFlowCanvasLayer()` and warns. The preview and the minimap own their canvases and
81
81
  resolve their colours just outside them.
82
- - **`flow.tsx` imports `lib/skia-native-id` for its effect.** After a JS reload Skia reused the old
83
- runtime's canvas ids, which its native registry still held as torn down, so the edges and the
84
- background came up blank — the minimap too — until a re-render (pressing the lock was enough).
85
- The import moves this runtime's ids to a fresh range before any of the three canvases asks for one.
86
82
  - **Shared values go straight into Skia props.** The pan and zoom are one derived `transform` on
87
83
  the canvas's `Group`; an edge's route is a derived `SkPath` (`Skia.Path.MakeFromSVGString` in
88
84
  the worklet), its march a `DashPathEffect` `phase`. Nothing crosses to the JS thread per frame.
@@ -21,7 +21,6 @@ import Animated, {
21
21
  } from "react-native-reanimated";
22
22
  import { Canvas, Group } from "react-native-skia";
23
23
  import { scheduleOnRN } from "react-native-worklets";
24
- import "../../lib/skia-native-id";
25
24
  import { useCalmMotion } from "../../hooks/use-calm-motion";
26
25
  import { useThemeColors } from "../../hooks/use-theme-color";
27
26
  import {
@@ -167,9 +167,6 @@ rule keeps such a type in its consumer's file.
167
167
 
168
168
  - **`react-native-skia` (3 or later) is an optional peer, needed here.** The ring draws with it, as
169
169
  `Chart`, `Flow` and `Sketch` do; `react-native-svg` is no longer imported by this component.
170
- - **The ring imports `lib/skia-native-id` for its effect.** After a JS reload Skia reuses the old
171
- runtime's canvas ids, so a ring mounted then would draw nothing until it re-rendered. The import
172
- moves this runtime's ids to a fresh range before the canvas asks for one, as `Sketch` does.
173
170
 
174
171
  ## What it does not do
175
172
 
@@ -2,7 +2,6 @@ import type { ReactElement } from "react";
2
2
  import { View } from "react-native";
3
3
  import { useDerivedValue } from "react-native-reanimated";
4
4
  import { Canvas, Circle, Path, Skia } from "react-native-skia";
5
- import "../../lib/skia-native-id";
6
5
  import { useThemeColor } from "../../hooks/use-theme-color";
7
6
  import { useSectionProgressPart } from "./section-progress.context";
8
7
  import {
@@ -53,10 +53,6 @@ standalone SVG document, or as a PNG.
53
53
  and had it parsed back on every move. Each stroke is still its own `drawPath`,
54
54
  so a translucent ink darkens where two strokes cross exactly as separate SVG
55
55
  paths did.
56
- - **The canvas imports `lib/skia-native-id` for its effect**, as `Sketch.Canvas`
57
- does. After a JS reload Skia reused the old runtime's canvas ids, which its
58
- native registry still held as torn down, so the pad came up blank until a
59
- stroke re-rendered it.
60
56
  - **The live and the finished stroke are traced by the same function.**
61
57
  `traceStroke` is a worklet, so the UI thread and the committed picture build
62
58
  the identical path and a stroke does not shift by a hair when it is handed
@@ -3,7 +3,6 @@ import { StyleSheet } from "react-native";
3
3
  import { type SharedValue, useDerivedValue, useSharedValue, withTiming } from "react-native-reanimated";
4
4
  import { Canvas, Group, Path, Picture, Skia, type SkPicture } from "react-native-skia";
5
5
  import { scheduleOnRN } from "react-native-worklets";
6
- import "../../lib/skia-native-id";
7
6
  import { recordSignaturePicture } from "./signature.skia";
8
7
  import { traceStroke } from "./signature.stroke";
9
8
  import type { SignaturePoint, SignatureStroke } from "./signature.types";
@@ -136,10 +136,6 @@ DisplayNames: `DelacourUI.Sketch`, `.Sketch.Canvas`, `.Toolbar`, `.Tool`,
136
136
  - **`toSVG()` is vector and `toPNG()` is raster; both hold the marks and the
137
137
  background only.** Neither includes what `Sketch.Canvas` children paint under
138
138
  the marks.
139
- - **The canvas imports `lib/skia-native-id` for its effect.** After a JS reload Skia reused the
140
- old runtime's canvas ids, which its native registry still held as torn down, so a sketch came up
141
- blank until something re-rendered it. The import moves this runtime's ids to a fresh range
142
- before the canvas asks for one.
143
139
  - **`toPNG()` renders off screen**, on a CPU surface (`Skia.Surface.MakeRaster`) sized
144
140
  to the canvas times `scale` (default the screen's pixel ratio), by the same
145
141
  `drawSketchItems` the picture records — not a snapshot of the visible canvas,
@@ -4,7 +4,6 @@ import { Gesture, GestureDetector } from "react-native-gesture-handler";
4
4
  import { useDerivedValue, useSharedValue } from "react-native-reanimated";
5
5
  import { Canvas, Group, Path, Picture, Skia } from "react-native-skia";
6
6
  import { scheduleOnRN, scheduleOnUI } from "react-native-worklets";
7
- import "../../lib/skia-native-id";
8
7
  import { useSketchPart } from "./sketch.context";
9
8
  import {
10
9
  appendSketchSegment,
@@ -2,7 +2,6 @@ import type { ReactElement } from "react";
2
2
  import { StyleSheet } from "react-native";
3
3
  import { type SharedValue, useDerivedValue } from "react-native-reanimated";
4
4
  import { Canvas, Group, Rect, RoundedRect, Skia } from "react-native-skia";
5
- import "../../lib/skia-native-id";
6
5
  import { useThemeColor } from "../../hooks/use-theme-color";
7
6
  import { resolveMaskHole, TOUR_SCRIM_TOKEN, type TourSize } from "./tour.variants";
8
7
 
@@ -1,29 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import { resolveSkiaNativeId, SKIA_NATIVE_ID_FLOOR } from "./skia-native-id";
3
-
4
- describe("resolveSkiaNativeId", () => {
5
- test("moves a fresh runtime's counter off Skia's starting id", () => {
6
- expect(resolveSkiaNativeId(1000, 0)).toBe(SKIA_NATIVE_ID_FLOOR);
7
- expect(resolveSkiaNativeId(1000, 0.5)).toBeGreaterThan(SKIA_NATIVE_ID_FLOOR);
8
- });
9
-
10
- test("keeps the ids a runtime already handed out behind the new counter", () => {
11
- expect(resolveSkiaNativeId(1003, 0)).toBe(SKIA_NATIVE_ID_FLOOR + 3);
12
- });
13
-
14
- test("leaves a counter that is already seeded alone, so two copies seed once", () => {
15
- const seeded = resolveSkiaNativeId(1000, 0.25);
16
- expect(resolveSkiaNativeId(seeded, 0.75)).toBe(seeded);
17
- expect(resolveSkiaNativeId(seeded + 12, 0.75)).toBe(seeded + 12);
18
- });
19
-
20
- test("spreads runtimes far enough apart that one's ids never reach the next's", () => {
21
- const a = resolveSkiaNativeId(1000, 0.1);
22
- const b = resolveSkiaNativeId(1000, 0.1 + 1 / 100_000);
23
- expect(b - a).toBeGreaterThanOrEqual(10_000);
24
- });
25
-
26
- test("stays inside a signed 32-bit int, which Skia's native side casts ids to", () => {
27
- expect(resolveSkiaNativeId(1000, 0.999_999_999)).toBeLessThan(2 ** 31 - 1_000_000);
28
- });
29
- });
@@ -1,42 +0,0 @@
1
- import { SkiaViewNativeId } from "react-native-skia/src/views/SkiaViewNativeId";
2
-
3
- /** Skia's counter starts at 1000; anything at or above this has been seeded. */
4
- export const SKIA_NATIVE_ID_FLOOR = 10_000;
5
-
6
- /** Ids a runtime may hand out before it reaches the next runtime's range. */
7
- const SKIA_NATIVE_ID_SPAN = 10_000;
8
-
9
- /** How many ranges a runtime can land in — 1e9 at the top, inside a signed 32-bit int. */
10
- const SKIA_NATIVE_ID_SLOTS = 100_000;
11
-
12
- /**
13
- * Where a JS runtime's Skia canvas ids should start, given the counter as it stands and a number
14
- * in `[0, 1)`. A counter already at or above the floor is returned as it is, so every copy of this
15
- * module in an app can run it and only the first moves anything.
16
- */
17
- export function resolveSkiaNativeId(current: number, random: number): number {
18
- if (current >= SKIA_NATIVE_ID_FLOOR) return current;
19
- const slot = Math.floor(random * SKIA_NATIVE_ID_SLOTS);
20
- return SKIA_NATIVE_ID_FLOOR + slot * SKIA_NATIVE_ID_SPAN + (current - 1000);
21
- }
22
-
23
- /**
24
- * Starts this runtime's canvas ids somewhere the last runtime's never were.
25
- *
26
- * **A canvas mounted after a JS reload drew nothing until it re-rendered.** Skia numbers canvases
27
- * from a module-level counter that restarts at 1000 in every runtime, while its native
28
- * `ViewRegistry` is a process-wide singleton that outlives the reload. The old runtime's views are
29
- * torn down after the new one has started, and each leaves a tombstone for its id; the new
30
- * runtime's first canvases reuse those ids, their pictures are handed to a throwaway entry, and the
31
- * view registers to an empty one. Nothing draws until the next React commit sends the picture again.
32
- * A dev-menu reload hits it, and so does `Updates.reloadAsync` after an OTA update.
33
- * Reported upstream as wcandillon/react-native-skia#4312; drop this once a release fixes it.
34
- *
35
- * Evaluated once per runtime, on import, before any canvas has asked for an id. `SkiaViewNativeId`
36
- * is not exported from the package root, so this reaches it by path — the same file Metro resolves
37
- * `Canvas` from through the package's `react-native` field.
38
- *
39
- * `@delacour/react-native-charts` keeps an identical copy in `src/skia/native-id.ts` for its own
40
- * canvases, since `Chart` draws through it; change both together.
41
- */
42
- SkiaViewNativeId.current = resolveSkiaNativeId(SkiaViewNativeId.current, Math.random());