@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 +3 -4
- package/src/components/flow/AGENTS.md +0 -4
- package/src/components/flow/flow.tsx +0 -1
- package/src/components/section-progress/AGENTS.md +0 -3
- package/src/components/section-progress/section-progress-ring.tsx +0 -1
- package/src/components/signature/AGENTS.md +0 -4
- package/src/components/signature/signature-ink.tsx +0 -1
- package/src/components/sketch/AGENTS.md +0 -4
- package/src/components/sketch/sketch-canvas.tsx +0 -1
- package/src/components/tour/tour-mask.tsx +0 -1
- package/src/lib/skia-native-id.test.ts +0 -29
- package/src/lib/skia-native-id.ts +0 -42
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@delacour/react-native-ui",
|
|
3
|
-
"version": "0.5.0-alpha.
|
|
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.
|
|
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());
|