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.
Files changed (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +734 -2
  3. package/android/build.gradle +32 -0
  4. package/android/src/main/AndroidManifest.xml +2 -0
  5. package/android/src/main/baseline-prof.txt +4 -0
  6. package/android/src/main/java/expo/modules/themereveal/CapturePlan.kt +199 -0
  7. package/android/src/main/java/expo/modules/themereveal/CaptureRules.kt +50 -0
  8. package/android/src/main/java/expo/modules/themereveal/GpuSnapshot.kt +367 -0
  9. package/android/src/main/java/expo/modules/themereveal/KeptBitmaps.kt +102 -0
  10. package/android/src/main/java/expo/modules/themereveal/KeptTarget.kt +103 -0
  11. package/android/src/main/java/expo/modules/themereveal/Motion.kt +79 -0
  12. package/android/src/main/java/expo/modules/themereveal/Once.kt +13 -0
  13. package/android/src/main/java/expo/modules/themereveal/RenderThreadReveal.kt +107 -0
  14. package/android/src/main/java/expo/modules/themereveal/RevealOverlayView.kt +192 -0
  15. package/android/src/main/java/expo/modules/themereveal/SecondSnapshotWait.kt +112 -0
  16. package/android/src/main/java/expo/modules/themereveal/ShapePath.kt +47 -0
  17. package/android/src/main/java/expo/modules/themereveal/ThemeRevealModule.kt +904 -0
  18. package/android/src/main/java/expo/modules/themereveal/TransitionArgs.kt +50 -0
  19. package/android/src/main/java/expo/modules/themereveal/WindowSnapshot.kt +536 -0
  20. package/build/ThemeRevealModule.d.ts +11 -0
  21. package/build/ThemeRevealModule.d.ts.map +1 -0
  22. package/build/ThemeRevealModule.js +11 -0
  23. package/build/ThemeRevealModule.js.map +1 -0
  24. package/build/createThemeReveal.d.ts +39 -0
  25. package/build/createThemeReveal.d.ts.map +1 -0
  26. package/build/createThemeReveal.js +186 -0
  27. package/build/createThemeReveal.js.map +1 -0
  28. package/build/index.d.ts +9 -0
  29. package/build/index.d.ts.map +1 -0
  30. package/build/index.js +5 -0
  31. package/build/index.js.map +1 -0
  32. package/build/originFromPress.d.ts +12 -0
  33. package/build/originFromPress.d.ts.map +1 -0
  34. package/build/originFromPress.js +26 -0
  35. package/build/originFromPress.js.map +1 -0
  36. package/build/resolveTransition.d.ts +13 -0
  37. package/build/resolveTransition.d.ts.map +1 -0
  38. package/build/resolveTransition.js +43 -0
  39. package/build/resolveTransition.js.map +1 -0
  40. package/build/store.d.ts +8 -0
  41. package/build/store.d.ts.map +1 -0
  42. package/build/store.js +23 -0
  43. package/build/store.js.map +1 -0
  44. package/build/types.d.ts +31 -0
  45. package/build/types.d.ts.map +1 -0
  46. package/build/types.js +2 -0
  47. package/build/types.js.map +1 -0
  48. package/expo-module.config.json +9 -0
  49. package/ios/Motion.swift +171 -0
  50. package/ios/RevealOverlay.swift +115 -0
  51. package/ios/SVGPath.swift +373 -0
  52. package/ios/ThemeReveal.podspec +26 -0
  53. package/ios/ThemeRevealModule.swift +264 -0
  54. package/mocks/ThemeReveal.js +10 -0
  55. package/package.json +67 -4
  56. package/src/ThemeRevealModule.ts +24 -0
  57. package/src/createThemeReveal.ts +262 -0
  58. package/src/index.ts +14 -0
  59. package/src/originFromPress.ts +40 -0
  60. package/src/resolveTransition.ts +63 -0
  61. package/src/store.ts +30 -0
  62. 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'