react-native-parity-blur 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 (109) hide show
  1. package/LICENSE +20 -0
  2. package/ParityBlur.podspec +20 -0
  3. package/README.md +198 -0
  4. package/android/build.gradle +57 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/parityblur/AndroidBlurCalibration.kt +82 -0
  7. package/android/src/main/java/com/parityblur/BlurEngine.kt +132 -0
  8. package/android/src/main/java/com/parityblur/ParityBlurDebug.kt +24 -0
  9. package/android/src/main/java/com/parityblur/ParityBlurPackage.kt +17 -0
  10. package/android/src/main/java/com/parityblur/ParityBlurView.kt +542 -0
  11. package/android/src/main/java/com/parityblur/ParityBlurViewManager.kt +161 -0
  12. package/android/src/main/java/com/parityblur/PipelineMath.kt +202 -0
  13. package/android/src/main/java/com/parityblur/PixelCopySnapshotProvider.kt +108 -0
  14. package/android/src/main/java/com/parityblur/SoftwareSnapshotProvider.kt +173 -0
  15. package/android/src/main/java/com/parityblur/WindowBlurContext.kt +116 -0
  16. package/android/src/test/java/com/parityblur/MiniJson.kt +179 -0
  17. package/android/src/test/java/com/parityblur/PipelineFixturesTest.kt +222 -0
  18. package/ios/BlurEngine.swift +106 -0
  19. package/ios/ColorPipeline.swift +72 -0
  20. package/ios/MetalPresentationSurface.swift +51 -0
  21. package/ios/ParityBlurCoreView.swift +382 -0
  22. package/ios/ParityBlurDebug.swift +18 -0
  23. package/ios/ParityBlurView.h +14 -0
  24. package/ios/ParityBlurView.mm +135 -0
  25. package/ios/PipelineMath.swift +177 -0
  26. package/ios/SnapshotProvider.swift +128 -0
  27. package/ios/WindowBlurContext.swift +111 -0
  28. package/lib/module/BlurView.js +124 -0
  29. package/lib/module/BlurView.js.map +1 -0
  30. package/lib/module/ParityBlurViewNativeComponent.ts +82 -0
  31. package/lib/module/defaults.js +13 -0
  32. package/lib/module/defaults.js.map +1 -0
  33. package/lib/module/index.js +5 -0
  34. package/lib/module/index.js.map +1 -0
  35. package/lib/module/package.json +1 -0
  36. package/lib/module/pipeline/androidCalibration.js +55 -0
  37. package/lib/module/pipeline/androidCalibration.js.map +1 -0
  38. package/lib/module/pipeline/captureRect.js +151 -0
  39. package/lib/module/pipeline/captureRect.js.map +1 -0
  40. package/lib/module/pipeline/color.js +82 -0
  41. package/lib/module/pipeline/color.js.map +1 -0
  42. package/lib/module/pipeline/constants.js +65 -0
  43. package/lib/module/pipeline/constants.js.map +1 -0
  44. package/lib/module/pipeline/downsample.js +61 -0
  45. package/lib/module/pipeline/downsample.js.map +1 -0
  46. package/lib/module/pipeline/index.js +23 -0
  47. package/lib/module/pipeline/index.js.map +1 -0
  48. package/lib/module/pipeline/overlay.js +56 -0
  49. package/lib/module/pipeline/overlay.js.map +1 -0
  50. package/lib/module/pipeline/saturation.js +52 -0
  51. package/lib/module/pipeline/saturation.js.map +1 -0
  52. package/lib/module/pipeline/types.js +23 -0
  53. package/lib/module/pipeline/types.js.map +1 -0
  54. package/lib/module/pipeline/units.js +33 -0
  55. package/lib/module/pipeline/units.js.map +1 -0
  56. package/lib/module/presets.js +96 -0
  57. package/lib/module/presets.js.map +1 -0
  58. package/lib/module/types.js +4 -0
  59. package/lib/module/types.js.map +1 -0
  60. package/lib/typescript/package.json +1 -0
  61. package/lib/typescript/src/BlurView.d.ts +16 -0
  62. package/lib/typescript/src/BlurView.d.ts.map +1 -0
  63. package/lib/typescript/src/ParityBlurViewNativeComponent.d.ts +63 -0
  64. package/lib/typescript/src/ParityBlurViewNativeComponent.d.ts.map +1 -0
  65. package/lib/typescript/src/defaults.d.ts +12 -0
  66. package/lib/typescript/src/defaults.d.ts.map +1 -0
  67. package/lib/typescript/src/index.d.ts +5 -0
  68. package/lib/typescript/src/index.d.ts.map +1 -0
  69. package/lib/typescript/src/pipeline/androidCalibration.d.ts +42 -0
  70. package/lib/typescript/src/pipeline/androidCalibration.d.ts.map +1 -0
  71. package/lib/typescript/src/pipeline/captureRect.d.ts +84 -0
  72. package/lib/typescript/src/pipeline/captureRect.d.ts.map +1 -0
  73. package/lib/typescript/src/pipeline/color.d.ts +19 -0
  74. package/lib/typescript/src/pipeline/color.d.ts.map +1 -0
  75. package/lib/typescript/src/pipeline/constants.d.ts +52 -0
  76. package/lib/typescript/src/pipeline/constants.d.ts.map +1 -0
  77. package/lib/typescript/src/pipeline/downsample.d.ts +31 -0
  78. package/lib/typescript/src/pipeline/downsample.d.ts.map +1 -0
  79. package/lib/typescript/src/pipeline/index.d.ts +20 -0
  80. package/lib/typescript/src/pipeline/index.d.ts.map +1 -0
  81. package/lib/typescript/src/pipeline/overlay.d.ts +31 -0
  82. package/lib/typescript/src/pipeline/overlay.d.ts.map +1 -0
  83. package/lib/typescript/src/pipeline/saturation.d.ts +38 -0
  84. package/lib/typescript/src/pipeline/saturation.d.ts.map +1 -0
  85. package/lib/typescript/src/pipeline/types.d.ts +32 -0
  86. package/lib/typescript/src/pipeline/types.d.ts.map +1 -0
  87. package/lib/typescript/src/pipeline/units.d.ts +23 -0
  88. package/lib/typescript/src/pipeline/units.d.ts.map +1 -0
  89. package/lib/typescript/src/presets.d.ts +57 -0
  90. package/lib/typescript/src/presets.d.ts.map +1 -0
  91. package/lib/typescript/src/types.d.ts +116 -0
  92. package/lib/typescript/src/types.d.ts.map +1 -0
  93. package/package.json +167 -0
  94. package/src/BlurView.tsx +195 -0
  95. package/src/ParityBlurViewNativeComponent.ts +82 -0
  96. package/src/defaults.ts +20 -0
  97. package/src/index.ts +10 -0
  98. package/src/pipeline/androidCalibration.ts +64 -0
  99. package/src/pipeline/captureRect.ts +172 -0
  100. package/src/pipeline/color.ts +66 -0
  101. package/src/pipeline/constants.ts +65 -0
  102. package/src/pipeline/downsample.ts +74 -0
  103. package/src/pipeline/index.ts +20 -0
  104. package/src/pipeline/overlay.ts +46 -0
  105. package/src/pipeline/saturation.ts +65 -0
  106. package/src/pipeline/types.ts +37 -0
  107. package/src/pipeline/units.ts +32 -0
  108. package/src/presets.ts +103 -0
  109. package/src/types.ts +132 -0
package/src/presets.ts ADDED
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Material-like presets (plan §11, plan §41 / Milestone 8).
3
+ *
4
+ * A preset is nothing more than a fixed, explicit
5
+ * `{ blurRadius, saturation, overlayColor }` prop bundle. There is no
6
+ * hidden or platform-specific behavior: applying `BlurPresets.dark` is
7
+ * exactly equivalent to spreading that plain object onto `<BlurView>`
8
+ * yourself, and the resulting three numbers/strings go through the same
9
+ * calibrated pipeline as any other explicit props (docs/PIPELINE_SPEC.md).
10
+ * Because blurRadius/saturation/overlayColor are calibrated to match
11
+ * cross-platform (docs/CALIBRATION_REPORT.md — worst measured ΔE76 0.90,
12
+ * SSIM ≥ 0.983), a given preset renders the same on iOS and Android.
13
+ *
14
+ * These are *approximations* of the visual weight of iOS system materials
15
+ * (UIBlurEffect styles), chosen by eye against reasonable blurRadius /
16
+ * saturation / overlayColor values — they are not derived from, measured
17
+ * against, or guaranteed to match `UIVisualEffectView` output, and Android
18
+ * has no equivalent native material to match at all. Treat the names as a
19
+ * starting point, not a parity claim (plan §43 — nested/material stacking
20
+ * is deterministic, not an Apple material emulation).
21
+ *
22
+ * Usage:
23
+ * ```tsx
24
+ * <BlurView {...BlurPresets.dark} style={styles.sheet}>
25
+ * {children}
26
+ * </BlurView>
27
+ * ```
28
+ *
29
+ * Every field is a plain public prop, so you can still override any one of
30
+ * them by spreading the preset first and your own prop second:
31
+ * ```tsx
32
+ * <BlurView {...BlurPresets.dark} blurRadius={30} />
33
+ * ```
34
+ *
35
+ * Or, for the same effect without spreading, pass the `preset` prop
36
+ * directly to `<BlurView>` (`src/BlurView.tsx`) — it resolves to this same
37
+ * object client-side before any explicit blurRadius/saturation/overlayColor
38
+ * prop is applied on top of it. Both forms are pure JS convenience; neither
39
+ * adds a native prop.
40
+ */
41
+
42
+ /** One named preset: an explicit bundle of public BlurView props. */
43
+ export interface BlurPreset {
44
+ /** Gaussian sigma in dp — see `BlurViewProps.blurRadius`. */
45
+ blurRadius: number;
46
+ /** See `BlurViewProps.saturation`. */
47
+ saturation: number;
48
+ /** See `BlurViewProps.overlayColor`. */
49
+ overlayColor: string;
50
+ }
51
+
52
+ /** Keys of {@link BlurPresets}. */
53
+ export type BlurPresetName =
54
+ 'ultraThin' | 'thin' | 'regular' | 'thick' | 'chrome' | 'light' | 'dark';
55
+
56
+ /**
57
+ * Named material-like preset table. See the module doc comment above for
58
+ * semantics and the "not a parity claim" caveat.
59
+ */
60
+ export const BlurPresets: Readonly<Record<BlurPresetName, BlurPreset>> = {
61
+ /** Barely-there frosted glass: minimal blur, faint light tint. */
62
+ ultraThin: {
63
+ blurRadius: 10,
64
+ saturation: 1.3,
65
+ overlayColor: 'rgba(255,255,255,0.15)',
66
+ },
67
+ /** Light frosted glass, subtle. */
68
+ thin: {
69
+ blurRadius: 14,
70
+ saturation: 1.4,
71
+ overlayColor: 'rgba(255,255,255,0.25)',
72
+ },
73
+ /** Neutral, medium-weight — a reasonable default over photos/color. */
74
+ regular: {
75
+ blurRadius: 20,
76
+ saturation: 1.2,
77
+ overlayColor: 'rgba(128,128,128,0.16)',
78
+ },
79
+ /** Heavier blur, more opaque neutral-dark tint. */
80
+ thick: {
81
+ blurRadius: 28,
82
+ saturation: 1.3,
83
+ overlayColor: 'rgba(20,20,20,0.35)',
84
+ },
85
+ /** Near-opaque, low-saturation — for toolbar/nav-bar-like surfaces. */
86
+ chrome: {
87
+ blurRadius: 24,
88
+ saturation: 1.1,
89
+ overlayColor: 'rgba(230,230,230,0.55)',
90
+ },
91
+ /** Classic light material: strong blur, warm-white tint, boosted saturation. */
92
+ light: {
93
+ blurRadius: 20,
94
+ saturation: 1.8,
95
+ overlayColor: 'rgba(255,255,255,0.4)',
96
+ },
97
+ /** Classic dark material: strong blur, near-black tint, boosted saturation. */
98
+ dark: {
99
+ blurRadius: 20,
100
+ saturation: 1.5,
101
+ overlayColor: 'rgba(16,16,16,0.45)',
102
+ },
103
+ };
package/src/types.ts ADDED
@@ -0,0 +1,132 @@
1
+ import type * as React from 'react';
2
+ import type { StyleProp, ViewStyle } from 'react-native';
3
+
4
+ import type { BlurPresetName } from './presets';
5
+
6
+ /** Public blur mode (plan §20/§21). default: 'static'. */
7
+ export type BlurMode = 'static' | 'live';
8
+
9
+ /** Public quality tier (plan §13). default: 'balanced'. */
10
+ export type BlurQuality = 'high' | 'balanced' | 'performance';
11
+
12
+ /** Public downsample selector (plan §12). default: 'auto'. */
13
+ export type BlurDownsample = 'auto' | 1 | 2 | 4 | 8;
14
+
15
+ export interface BlurViewProps {
16
+ /**
17
+ * Gaussian sigma in dp (plan §5.1) — the same canonical unit on both
18
+ * platforms (iOS pt ≡ Android dp semantically). Internally converted to
19
+ * each native backend's own blur parameter (docs/PIPELINE_SPEC.md §2), so
20
+ * the same number produces calibrated matching visual weight on iOS and
21
+ * Android (worst measured ΔE76 0.90, SSIM ≥ 0.983 across the parity
22
+ * suite — docs/CALIBRATION_REPORT.md). `0` (or omitted) renders no blur.
23
+ * Non-finite or negative values clamp to 0 with a DEV warning.
24
+ * default: 0.
25
+ */
26
+ blurRadius?: number;
27
+
28
+ /**
29
+ * `'static'` captures the backdrop once (on mount, layout change, or a
30
+ * prop change that affects the capture) and presents a still blurred
31
+ * snapshot; call `refresh()` to recapture after the backdrop changes
32
+ * underneath it. `'live'` recaptures continuously (throttled by
33
+ * `maxFps`) while the view is on screen. default: 'static'.
34
+ */
35
+ mode?: BlurMode;
36
+
37
+ /**
38
+ * Named material-like preset (plan §11) resolved client-side to a base
39
+ * `{ blurRadius, saturation, overlayColor }` bundle before this
40
+ * component's own explicit props are applied on top — see
41
+ * `BlurPresets`/`BlurPresetName` in `presets.ts` for the exact values.
42
+ * Pure JS convenience: it does not add a native prop, and any of those
43
+ * three props passed explicitly alongside `preset` overrides the
44
+ * preset's value for that prop only. default: none.
45
+ */
46
+ preset?: BlurPresetName;
47
+
48
+ /**
49
+ * Straight-alpha color composited source-over the blurred + saturated
50
+ * result (docs/PIPELINE_SPEC.md §8) — the only tint anywhere in the
51
+ * pipeline; there is no hidden per-platform tint. An unparseable color
52
+ * resolves to "no overlay" with a DEV warning. default: 'transparent'
53
+ * (no overlay).
54
+ */
55
+ overlayColor?: string;
56
+
57
+ /**
58
+ * Post-blur saturation multiplier (docs/PIPELINE_SPEC.md §7), applied
59
+ * after blur and before the overlay: `1` = unchanged, `0` = Rec.709
60
+ * grayscale, values `> 1` boost saturation. Negative or non-finite values
61
+ * clamp to the default with a DEV warning. default: 1.
62
+ */
63
+ saturation?: number;
64
+
65
+ /**
66
+ * Consumer-friendly quality tier that biases automatic downsample
67
+ * selection (plan §13): `'high'` prefers 1x/2x snapshots, `'balanced'`
68
+ * prefers 2x/4x, `'performance'` prefers 4x/8x. Has no effect when
69
+ * `downsample` is an explicit numeric override. default: 'balanced'.
70
+ */
71
+ quality?: BlurQuality;
72
+
73
+ /**
74
+ * Snapshot downsample factor (plan §12). `'auto'` derives a factor from
75
+ * requested sigma, capture area, and `quality` (docs/PIPELINE_SPEC.md
76
+ * §4); `1 | 2 | 4 | 8` forces that exact factor for advanced tuning.
77
+ * default: 'auto'.
78
+ */
79
+ downsample?: BlurDownsample;
80
+
81
+ /**
82
+ * Upper bound on live-mode recapture rate, in frames per second. Ignored
83
+ * in `'static'` mode. Clamped to `[1, 120]` with a DEV warning outside
84
+ * that range. default: 30.
85
+ */
86
+ maxFps?: number;
87
+
88
+ /**
89
+ * Color rendered in place of a real blur wherever real blur is
90
+ * unavailable: Android below API 31 (no `RenderEffect`) or, on either
91
+ * platform, when the OS-level "Reduce Transparency" accessibility
92
+ * setting is on. Has no effect on a device/OS combination where real
93
+ * blur runs. default: none (renders fully transparent when the fallback
94
+ * path is active and no `fallbackColor` is set).
95
+ */
96
+ fallbackColor?: string;
97
+
98
+ /**
99
+ * Target view whose subtree should be captured as the blur backdrop,
100
+ * instead of the default (the content behind this `BlurView` within its
101
+ * own window) (plan §18). **Not implemented in v1** — accepted only to
102
+ * keep the public API shape stable for a later release; passing it
103
+ * currently has no native-side effect. Deferred to v1.1 — see
104
+ * docs/LIMITATIONS.md.
105
+ */
106
+ blurTarget?: React.RefObject<any>;
107
+
108
+ /** Content rendered on top of the blur; unaffected by it. */
109
+ children?: React.ReactNode;
110
+
111
+ /**
112
+ * Standard React Native view style. `borderRadius` (and other clipping
113
+ * styles) clip the blur output itself, not just the children (plan §31).
114
+ */
115
+ style?: StyleProp<ViewStyle>;
116
+ }
117
+
118
+ /**
119
+ * Imperative handle exposed via ref (plan §29).
120
+ */
121
+ export interface BlurViewRef {
122
+ /**
123
+ * Schedules a coalesced recapture of the backdrop on the next valid
124
+ * frame — fully implemented end-to-end on both native backends (not a
125
+ * no-op). Repeated calls before the pending capture runs coalesce into a
126
+ * single recapture. Primarily useful in `mode="static"` after the
127
+ * backdrop has changed; in `mode="live"` the view is already recapturing
128
+ * continuously, so `refresh()` has no additional effect beyond nudging
129
+ * the next scheduled frame.
130
+ */
131
+ refresh(): void;
132
+ }