react-native-theme-reveal 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +734 -2
- package/android/build.gradle +32 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/baseline-prof.txt +4 -0
- package/android/src/main/java/expo/modules/themereveal/CapturePlan.kt +199 -0
- package/android/src/main/java/expo/modules/themereveal/CaptureRules.kt +50 -0
- package/android/src/main/java/expo/modules/themereveal/GpuSnapshot.kt +367 -0
- package/android/src/main/java/expo/modules/themereveal/KeptBitmaps.kt +102 -0
- package/android/src/main/java/expo/modules/themereveal/KeptTarget.kt +103 -0
- package/android/src/main/java/expo/modules/themereveal/Motion.kt +79 -0
- package/android/src/main/java/expo/modules/themereveal/Once.kt +13 -0
- package/android/src/main/java/expo/modules/themereveal/RenderThreadReveal.kt +107 -0
- package/android/src/main/java/expo/modules/themereveal/RevealOverlayView.kt +192 -0
- package/android/src/main/java/expo/modules/themereveal/SecondSnapshotWait.kt +112 -0
- package/android/src/main/java/expo/modules/themereveal/ShapePath.kt +47 -0
- package/android/src/main/java/expo/modules/themereveal/ThemeRevealModule.kt +904 -0
- package/android/src/main/java/expo/modules/themereveal/TransitionArgs.kt +50 -0
- package/android/src/main/java/expo/modules/themereveal/WindowSnapshot.kt +536 -0
- package/build/ThemeRevealModule.d.ts +11 -0
- package/build/ThemeRevealModule.d.ts.map +1 -0
- package/build/ThemeRevealModule.js +11 -0
- package/build/ThemeRevealModule.js.map +1 -0
- package/build/createThemeReveal.d.ts +39 -0
- package/build/createThemeReveal.d.ts.map +1 -0
- package/build/createThemeReveal.js +186 -0
- package/build/createThemeReveal.js.map +1 -0
- package/build/index.d.ts +9 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +5 -0
- package/build/index.js.map +1 -0
- package/build/originFromPress.d.ts +12 -0
- package/build/originFromPress.d.ts.map +1 -0
- package/build/originFromPress.js +26 -0
- package/build/originFromPress.js.map +1 -0
- package/build/resolveTransition.d.ts +13 -0
- package/build/resolveTransition.d.ts.map +1 -0
- package/build/resolveTransition.js +43 -0
- package/build/resolveTransition.js.map +1 -0
- package/build/store.d.ts +8 -0
- package/build/store.d.ts.map +1 -0
- package/build/store.js +23 -0
- package/build/store.js.map +1 -0
- package/build/types.d.ts +31 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/Motion.swift +171 -0
- package/ios/RevealOverlay.swift +115 -0
- package/ios/SVGPath.swift +373 -0
- package/ios/ThemeReveal.podspec +26 -0
- package/ios/ThemeRevealModule.swift +264 -0
- package/mocks/ThemeReveal.js +10 -0
- package/package.json +67 -4
- package/src/ThemeRevealModule.ts +24 -0
- package/src/createThemeReveal.ts +262 -0
- package/src/index.ts +14 -0
- package/src/originFromPress.ts +40 -0
- package/src/resolveTransition.ts +63 -0
- package/src/store.ts +30 -0
- package/src/types.ts +17 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Point, Shape, Transition, TransitionType, WipeDirection } from './types'
|
|
2
|
+
|
|
3
|
+
export type ResolveTransitionInput = {
|
|
4
|
+
requested?: TransitionType
|
|
5
|
+
fallback?: TransitionType
|
|
6
|
+
origin: Point | null
|
|
7
|
+
shape?: Shape
|
|
8
|
+
durations?: Partial<Record<TransitionType, number>>
|
|
9
|
+
wipeDirection?: WipeDirection
|
|
10
|
+
requestedShape?: Shape
|
|
11
|
+
requestedWipeDirection?: WipeDirection
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const DEFAULT_DURATIONS: Record<TransitionType, number> = {
|
|
15
|
+
reveal: 450,
|
|
16
|
+
inverseReveal: 450,
|
|
17
|
+
wipe: 400,
|
|
18
|
+
crossfade: 300,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const MAX_DURATION_MS = 10_000
|
|
22
|
+
|
|
23
|
+
const isValidDuration = (ms: number | undefined): ms is number =>
|
|
24
|
+
ms !== undefined && Number.isFinite(ms) && ms > 0 && ms <= MAX_DURATION_MS
|
|
25
|
+
|
|
26
|
+
const isNumber = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value)
|
|
27
|
+
|
|
28
|
+
const isPoint = (value: unknown): value is Point =>
|
|
29
|
+
typeof value === 'object' && value !== null && isNumber((value as Point).x) && isNumber((value as Point).y)
|
|
30
|
+
|
|
31
|
+
const isShape = (value: unknown): value is Shape =>
|
|
32
|
+
typeof value === 'object' &&
|
|
33
|
+
value !== null &&
|
|
34
|
+
typeof (value as Shape).path === 'string' &&
|
|
35
|
+
isPoint((value as Shape).anchor) &&
|
|
36
|
+
isNumber((value as Shape).inscribedRadius)
|
|
37
|
+
|
|
38
|
+
export function resolveTransition(input: ResolveTransitionInput): Transition {
|
|
39
|
+
const { requested, fallback, durations } = input
|
|
40
|
+
// Untyped callers can pass null, undefined or other non-numbers inside origin or shape. Android rejects start for
|
|
41
|
+
// those before its parser runs, so here they fall back to no origin and the circle.
|
|
42
|
+
const origin = isPoint(input.origin) ? input.origin : null
|
|
43
|
+
const type = requested ?? fallback ?? (origin ? 'reveal' : 'crossfade')
|
|
44
|
+
const requestedShape = input.requestedShape ?? input.shape
|
|
45
|
+
const shape = isShape(requestedShape) ? requestedShape : undefined
|
|
46
|
+
const wipeDirection = input.requestedWipeDirection ?? input.wipeDirection
|
|
47
|
+
const durationOf = (kind: TransitionType) => {
|
|
48
|
+
const ms = durations?.[kind]
|
|
49
|
+
return isValidDuration(ms) ? ms : DEFAULT_DURATIONS[kind]
|
|
50
|
+
}
|
|
51
|
+
switch (type) {
|
|
52
|
+
case 'reveal':
|
|
53
|
+
case 'inverseReveal':
|
|
54
|
+
if (!origin) return { type: 'crossfade', durationMs: durationOf('crossfade') }
|
|
55
|
+
return shape
|
|
56
|
+
? { type, origin, durationMs: durationOf(type), shape }
|
|
57
|
+
: { type, origin, durationMs: durationOf(type) }
|
|
58
|
+
case 'wipe':
|
|
59
|
+
return { type, direction: wipeDirection ?? 'up', durationMs: durationOf(type) }
|
|
60
|
+
case 'crossfade':
|
|
61
|
+
return { type, durationMs: durationOf(type) }
|
|
62
|
+
}
|
|
63
|
+
}
|
package/src/store.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react'
|
|
2
|
+
|
|
3
|
+
export type Store<S> = {
|
|
4
|
+
get(): S
|
|
5
|
+
set(partial: Partial<S>): void
|
|
6
|
+
subscribe(listener: () => void): () => void
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function createStore<S>(initial: S): Store<S> {
|
|
10
|
+
let state = initial
|
|
11
|
+
const listeners = new Set<() => void>()
|
|
12
|
+
return {
|
|
13
|
+
get: () => state,
|
|
14
|
+
set: (partial) => {
|
|
15
|
+
state = { ...state, ...partial }
|
|
16
|
+
listeners.forEach((listener) => listener())
|
|
17
|
+
},
|
|
18
|
+
subscribe: (listener) => {
|
|
19
|
+
listeners.add(listener)
|
|
20
|
+
return () => {
|
|
21
|
+
listeners.delete(listener)
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function useStore<S, V>(store: Store<S>, select: (state: S) => V): V {
|
|
28
|
+
const getSnapshot = () => select(store.get())
|
|
29
|
+
return useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot)
|
|
30
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type Point = { x: number; y: number }
|
|
2
|
+
|
|
3
|
+
export type Shape = { path: string; anchor: Point; inscribedRadius: number }
|
|
4
|
+
|
|
5
|
+
export type WipeDirection = 'up' | 'down' | 'left' | 'right'
|
|
6
|
+
|
|
7
|
+
export type Transition =
|
|
8
|
+
| { type: 'reveal'; origin: Point; durationMs: number; shape?: Shape }
|
|
9
|
+
| { type: 'inverseReveal'; origin: Point; durationMs: number; shape?: Shape }
|
|
10
|
+
| { type: 'wipe'; direction: WipeDirection; durationMs: number }
|
|
11
|
+
| { type: 'crossfade'; durationMs: number }
|
|
12
|
+
|
|
13
|
+
export type TransitionType = Transition['type']
|
|
14
|
+
|
|
15
|
+
// How the snapshot was taken. Android: 'gpu' (a GPU draw of the window, API 29+) or 'pixelcopy' (a readback).
|
|
16
|
+
// iOS: 'view' (snapshotView).
|
|
17
|
+
export type CapturePath = 'gpu' | 'pixelcopy' | 'view'
|