@oxyhq/bloom 0.57.1 → 0.58.1
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/lib/commonjs/bottom-sheet/BottomSheetBase.js +15 -9
- package/lib/commonjs/bottom-sheet/BottomSheetBase.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.web.js +17 -23
- package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
- package/lib/commonjs/overlay/index.js +56 -10
- package/lib/commonjs/overlay/index.js.map +1 -1
- package/lib/commonjs/provider/index.js +6 -0
- package/lib/commonjs/provider/index.js.map +1 -1
- package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js +27 -16
- package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js.map +1 -1
- package/lib/module/bottom-sheet/BottomSheetBase.js +16 -10
- package/lib/module/bottom-sheet/BottomSheetBase.js.map +1 -1
- package/lib/module/dialog/Dialog.web.js +17 -23
- package/lib/module/dialog/Dialog.web.js.map +1 -1
- package/lib/module/overlay/index.js +58 -11
- package/lib/module/overlay/index.js.map +1 -1
- package/lib/module/provider/index.js +6 -0
- package/lib/module/provider/index.js.map +1 -1
- package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js +27 -16
- package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js.map +1 -1
- package/lib/typescript/commonjs/bottom-sheet/BottomSheetBase.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/overlay/index.d.ts +33 -8
- package/lib/typescript/commonjs/overlay/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/provider/index.d.ts +6 -0
- package/lib/typescript/commonjs/provider/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +1 -1
- package/lib/typescript/module/bottom-sheet/BottomSheetBase.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/module/overlay/index.d.ts +33 -8
- package/lib/typescript/module/overlay/index.d.ts.map +1 -1
- package/lib/typescript/module/provider/index.d.ts +6 -0
- package/lib/typescript/module/provider/index.d.ts.map +1 -1
- package/lib/typescript/module/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/overlay-pointer-events.test.tsx +41 -0
- package/src/bottom-sheet/BottomSheetBase.tsx +18 -9
- package/src/dialog/Dialog.web.tsx +20 -24
- package/src/overlay/index.tsx +82 -17
- package/src/provider/index.tsx +6 -0
- package/src/zoomable-image-gallery/ZoomableImageGallery.tsx +32 -17
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* The shared plumbing every portaled surface needs: an interactive ROOT and a
|
|
3
3
|
* press-to-dismiss BACKDROP. Dialog, BottomSheet, the image gallery, menus and
|
|
4
4
|
* toasts each used to hand-roll both, and each one got the web contract subtly
|
|
5
|
-
* wrong in its own way
|
|
5
|
+
* wrong in its own way — and looked different while doing it (the image viewer
|
|
6
|
+
* blurred, everything else only dimmed).
|
|
6
7
|
*
|
|
7
8
|
* ## The contract these two components encode
|
|
8
9
|
*
|
|
@@ -26,11 +27,27 @@
|
|
|
26
27
|
* which is what makes it look like a dismissal bug rather than a hit-testing
|
|
27
28
|
* one.
|
|
28
29
|
*
|
|
30
|
+
* A backdrop also only dismisses what is actually ON TOP of it: a full-screen
|
|
31
|
+
* layer rendered ABOVE the backdrop (a pager, a zoom container) receives the
|
|
32
|
+
* press first and swallows it. Either that layer opts out (`pointerEvents
|
|
33
|
+
*="box-none"`) or it owns the dismiss itself — the backdrop being present is
|
|
34
|
+
* not enough.
|
|
35
|
+
*
|
|
36
|
+
* EXPO/EXPO-ROUTER APPS ONLY for `BloomProvider` — see `src/provider`; these
|
|
37
|
+
* two components are universal.
|
|
38
|
+
*
|
|
29
39
|
* Use `<OverlayRoot>` for the surface's outermost node and `<Backdrop>` for its
|
|
30
40
|
* dimming layer; do not re-implement either with raw `View`s.
|
|
31
41
|
*/
|
|
32
42
|
import { type ReactNode } from 'react';
|
|
33
|
-
import { type StyleProp, type ViewStyle } from 'react-native';
|
|
43
|
+
import { View, type StyleProp, type ViewStyle } from 'react-native';
|
|
44
|
+
/**
|
|
45
|
+
* One blur radius for every Bloom overlay. Surfaces differ in what they show,
|
|
46
|
+
* not in how the app behind them recedes.
|
|
47
|
+
*/
|
|
48
|
+
export declare const BACKDROP_BLUR_INTENSITY = 40;
|
|
49
|
+
/** Dim laid over the blur — the blur alone does not give enough contrast. */
|
|
50
|
+
export declare const BACKDROP_DIM_OPACITY = 0.45;
|
|
34
51
|
export interface OverlayRootProps {
|
|
35
52
|
children?: ReactNode;
|
|
36
53
|
style?: StyleProp<ViewStyle>;
|
|
@@ -51,17 +68,25 @@ export interface BackdropProps {
|
|
|
51
68
|
onPress?: () => void;
|
|
52
69
|
/** `true` keeps the dim but makes it inert — a blocking dialog, a busy state. */
|
|
53
70
|
disabled?: boolean;
|
|
54
|
-
/**
|
|
71
|
+
/** Blur radius behind the dim. `0` renders the dim alone. */
|
|
72
|
+
blurIntensity?: number;
|
|
73
|
+
/** Blur tint. Backdrops dim the app, so `dark` is the default on every theme. */
|
|
74
|
+
blurTint?: 'light' | 'dark' | 'default';
|
|
75
|
+
/** Dim colour over the blur. */
|
|
76
|
+
dimColor?: string;
|
|
77
|
+
/** Dim opacity, 0–1. */
|
|
78
|
+
dimOpacity?: number;
|
|
79
|
+
/** Extra style on the press target — animated opacity, insets, z-index. */
|
|
55
80
|
style?: StyleProp<ViewStyle>;
|
|
56
|
-
/** Rendered
|
|
81
|
+
/** Rendered ON TOP of the dim, inside the press target (Dialog's panel does this). */
|
|
57
82
|
children?: ReactNode;
|
|
58
83
|
accessibilityLabel?: string;
|
|
59
84
|
testID?: string;
|
|
60
85
|
}
|
|
61
86
|
/**
|
|
62
|
-
* Full-bleed
|
|
63
|
-
*
|
|
64
|
-
*
|
|
87
|
+
* Full-bleed blur + dim that dismisses the surface when pressed. Always takes
|
|
88
|
+
* pointer events (that is its whole job), so anything that must stay pressable
|
|
89
|
+
* goes INSIDE it as `children`, never as a sibling rendered over it.
|
|
65
90
|
*/
|
|
66
|
-
export declare const Backdrop: import("react").NamedExoticComponent<BackdropProps
|
|
91
|
+
export declare const Backdrop: import("react").NamedExoticComponent<BackdropProps & import("react").RefAttributes<View>>;
|
|
67
92
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/overlay/index.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/overlay/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAIL,IAAI,EACJ,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAItB;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAMxE;yBANe,WAAW;;;AAU3B,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACxC,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,sFAAsF;IACtF,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,2FAuDlB,CAAC"}
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
* Nesting extra contexts costs nothing at runtime — the win is that scope is no
|
|
19
19
|
* longer a per-app decision.
|
|
20
20
|
*
|
|
21
|
+
* EXPO/EXPO-ROUTER APPS ONLY. The scroll-restoration provider it mounts imports
|
|
22
|
+
* `expo-router` (its web implementation keys offsets on the focused route), so
|
|
23
|
+
* a Vite/SPA consumer that has no expo-router cannot resolve this module. Those
|
|
24
|
+
* apps keep mounting `BloomThemeProvider` (and any other piece they need)
|
|
25
|
+
* directly — that is not a lesser path, just the one without a router.
|
|
26
|
+
*
|
|
21
27
|
* NOT included, on purpose — these are OUTLETS, not state, and their placement
|
|
22
28
|
* in the tree is a real app decision (z-order, safe areas, and mounting a
|
|
23
29
|
* second one duplicates every surface it renders):
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/provider/index.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/provider/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAG9E,OAAO,EAAsB,KAAK,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAG5E,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC;IACnF,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,wFAAwF;IACxF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,aAAa,EACb,OAAc,EACd,GAAG,UAAU,EACd,EAAE,kBAAkB,2CAcpB;yBAnBe,aAAa"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ZoomableImageGallery.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-image-gallery/ZoomableImageGallery.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAmEjF,OAAO,KAAK,EAGV,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ZoomableImageGallery.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-image-gallery/ZoomableImageGallery.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAmEjF,OAAO,KAAK,EAGV,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAs5BjB,eAAO,MAAM,oBAAoB,8GAA4B,CAAC;AAyK9D,eAAe,oBAAoB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheetBase.d.ts","sourceRoot":"","sources":["../../../../src/bottom-sheet/BottomSheetBase.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAMH,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,SAAS,EACjB,MAAM,cAAc,CAAC;AAItB,OAAiB,EACb,KAAK,aAAa,EAGlB,KAAK,WAAW,EAMnB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"BottomSheetBase.d.ts","sourceRoot":"","sources":["../../../../src/bottom-sheet/BottomSheetBase.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAMH,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,SAAS,EACjB,MAAM,cAAc,CAAC;AAItB,OAAiB,EACb,KAAK,aAAa,EAGlB,KAAK,WAAW,EAMnB,MAAM,yBAAyB,CAAC;AAyBjC,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;IAC7F,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;IACjH;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5C,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;;;OAcG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACxC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9B;;;;OAIG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACjD;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,qBAAqB;IAClC,kEAAkE;IAClE,OAAO,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B;;;OAGG;IACH,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC1D,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;CACrD;AAID,eAAO,MAAM,eAAe,6FA4mB1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.web.d.ts","sourceRoot":"","sources":["../../../../src/dialog/Dialog.web.tsx"],"names":[],"mappings":"AAuCA,OAAO,EAOL,4BAA4B,EAM7B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,YAAY,EAGZ,WAAW,EACZ,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"Dialog.web.d.ts","sourceRoot":"","sources":["../../../../src/dialog/Dialog.web.tsx"],"names":[],"mappings":"AAuCA,OAAO,EAOL,4BAA4B,EAM7B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,YAAY,EAGZ,WAAW,EACZ,MAAM,SAAS,CAAC;AA4DjB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,WAAW,2CAazD;AA+ZD,OAAO,EAAE,4BAA4B,EAAE,CAAC;AAoPxC;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,WAAW,EACX,OAAO,EACP,SAAS,GACV,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB,2CAgBA;AAiCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,gBAAgB,mZAK5B,CAAC"}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* The shared plumbing every portaled surface needs: an interactive ROOT and a
|
|
3
3
|
* press-to-dismiss BACKDROP. Dialog, BottomSheet, the image gallery, menus and
|
|
4
4
|
* toasts each used to hand-roll both, and each one got the web contract subtly
|
|
5
|
-
* wrong in its own way
|
|
5
|
+
* wrong in its own way — and looked different while doing it (the image viewer
|
|
6
|
+
* blurred, everything else only dimmed).
|
|
6
7
|
*
|
|
7
8
|
* ## The contract these two components encode
|
|
8
9
|
*
|
|
@@ -26,11 +27,27 @@
|
|
|
26
27
|
* which is what makes it look like a dismissal bug rather than a hit-testing
|
|
27
28
|
* one.
|
|
28
29
|
*
|
|
30
|
+
* A backdrop also only dismisses what is actually ON TOP of it: a full-screen
|
|
31
|
+
* layer rendered ABOVE the backdrop (a pager, a zoom container) receives the
|
|
32
|
+
* press first and swallows it. Either that layer opts out (`pointerEvents
|
|
33
|
+
*="box-none"`) or it owns the dismiss itself — the backdrop being present is
|
|
34
|
+
* not enough.
|
|
35
|
+
*
|
|
36
|
+
* EXPO/EXPO-ROUTER APPS ONLY for `BloomProvider` — see `src/provider`; these
|
|
37
|
+
* two components are universal.
|
|
38
|
+
*
|
|
29
39
|
* Use `<OverlayRoot>` for the surface's outermost node and `<Backdrop>` for its
|
|
30
40
|
* dimming layer; do not re-implement either with raw `View`s.
|
|
31
41
|
*/
|
|
32
42
|
import { type ReactNode } from 'react';
|
|
33
|
-
import { type StyleProp, type ViewStyle } from 'react-native';
|
|
43
|
+
import { View, type StyleProp, type ViewStyle } from 'react-native';
|
|
44
|
+
/**
|
|
45
|
+
* One blur radius for every Bloom overlay. Surfaces differ in what they show,
|
|
46
|
+
* not in how the app behind them recedes.
|
|
47
|
+
*/
|
|
48
|
+
export declare const BACKDROP_BLUR_INTENSITY = 40;
|
|
49
|
+
/** Dim laid over the blur — the blur alone does not give enough contrast. */
|
|
50
|
+
export declare const BACKDROP_DIM_OPACITY = 0.45;
|
|
34
51
|
export interface OverlayRootProps {
|
|
35
52
|
children?: ReactNode;
|
|
36
53
|
style?: StyleProp<ViewStyle>;
|
|
@@ -51,17 +68,25 @@ export interface BackdropProps {
|
|
|
51
68
|
onPress?: () => void;
|
|
52
69
|
/** `true` keeps the dim but makes it inert — a blocking dialog, a busy state. */
|
|
53
70
|
disabled?: boolean;
|
|
54
|
-
/**
|
|
71
|
+
/** Blur radius behind the dim. `0` renders the dim alone. */
|
|
72
|
+
blurIntensity?: number;
|
|
73
|
+
/** Blur tint. Backdrops dim the app, so `dark` is the default on every theme. */
|
|
74
|
+
blurTint?: 'light' | 'dark' | 'default';
|
|
75
|
+
/** Dim colour over the blur. */
|
|
76
|
+
dimColor?: string;
|
|
77
|
+
/** Dim opacity, 0–1. */
|
|
78
|
+
dimOpacity?: number;
|
|
79
|
+
/** Extra style on the press target — animated opacity, insets, z-index. */
|
|
55
80
|
style?: StyleProp<ViewStyle>;
|
|
56
|
-
/** Rendered
|
|
81
|
+
/** Rendered ON TOP of the dim, inside the press target (Dialog's panel does this). */
|
|
57
82
|
children?: ReactNode;
|
|
58
83
|
accessibilityLabel?: string;
|
|
59
84
|
testID?: string;
|
|
60
85
|
}
|
|
61
86
|
/**
|
|
62
|
-
* Full-bleed
|
|
63
|
-
*
|
|
64
|
-
*
|
|
87
|
+
* Full-bleed blur + dim that dismisses the surface when pressed. Always takes
|
|
88
|
+
* pointer events (that is its whole job), so anything that must stay pressable
|
|
89
|
+
* goes INSIDE it as `children`, never as a sibling rendered over it.
|
|
65
90
|
*/
|
|
66
|
-
export declare const Backdrop: import("react").NamedExoticComponent<BackdropProps
|
|
91
|
+
export declare const Backdrop: import("react").NamedExoticComponent<BackdropProps & import("react").RefAttributes<View>>;
|
|
67
92
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/overlay/index.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/overlay/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAIL,IAAI,EACJ,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAItB;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAMxE;yBANe,WAAW;;;AAU3B,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACxC,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,sFAAsF;IACtF,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,2FAuDlB,CAAC"}
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
* Nesting extra contexts costs nothing at runtime — the win is that scope is no
|
|
19
19
|
* longer a per-app decision.
|
|
20
20
|
*
|
|
21
|
+
* EXPO/EXPO-ROUTER APPS ONLY. The scroll-restoration provider it mounts imports
|
|
22
|
+
* `expo-router` (its web implementation keys offsets on the focused route), so
|
|
23
|
+
* a Vite/SPA consumer that has no expo-router cannot resolve this module. Those
|
|
24
|
+
* apps keep mounting `BloomThemeProvider` (and any other piece they need)
|
|
25
|
+
* directly — that is not a lesser path, just the one without a router.
|
|
26
|
+
*
|
|
21
27
|
* NOT included, on purpose — these are OUTLETS, not state, and their placement
|
|
22
28
|
* in the tree is a real app decision (z-order, safe areas, and mounting a
|
|
23
29
|
* second one duplicates every surface it renders):
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/provider/index.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/provider/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAG9E,OAAO,EAAsB,KAAK,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAG5E,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC;IACnF,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,wFAAwF;IACxF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,aAAa,EACb,OAAc,EACd,GAAG,UAAU,EACd,EAAE,kBAAkB,2CAcpB;yBAnBe,aAAa"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ZoomableImageGallery.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-image-gallery/ZoomableImageGallery.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAmEjF,OAAO,KAAK,EAGV,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ZoomableImageGallery.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-image-gallery/ZoomableImageGallery.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAmEjF,OAAO,KAAK,EAGV,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAs5BjB,eAAO,MAAM,oBAAoB,8GAA4B,CAAC;AAyK9D,eAAe,oBAAoB,CAAC"}
|
package/package.json
CHANGED
|
@@ -106,6 +106,47 @@ describe('overlay pointer-events contract (web)', () => {
|
|
|
106
106
|
container.remove();
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
+
// Every Bloom surface dims the app the same way: the blur is part of the
|
|
110
|
+
// shared backdrop, not something each surface opts into (it used to be — the
|
|
111
|
+
// image viewer blurred, dialogs and sheets only dimmed).
|
|
112
|
+
it('blurs by default and drops the blur layer only when asked', () => {
|
|
113
|
+
const withBlur = render(createElement(Backdrop, { onPress: () => {}, testID: 'a' }));
|
|
114
|
+
expect(withBlur.container.getElementsByTagName('blurview').length).toBe(1);
|
|
115
|
+
act(() => withBlur.root.unmount());
|
|
116
|
+
withBlur.container.remove();
|
|
117
|
+
|
|
118
|
+
const noBlur = render(
|
|
119
|
+
createElement(Backdrop, { onPress: () => {}, blurIntensity: 0, testID: 'b' }),
|
|
120
|
+
);
|
|
121
|
+
expect(noBlur.container.getElementsByTagName('blurview').length).toBe(0);
|
|
122
|
+
act(() => noBlur.root.unmount());
|
|
123
|
+
noBlur.container.remove();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Surfaces animate the backdrop via `Animated.createAnimatedComponent(Backdrop)`,
|
|
127
|
+
// and reanimated writes those updates through the ref. Swallow it and an
|
|
128
|
+
// opacity animated from 0 never moves: the backdrop stays fully transparent
|
|
129
|
+
// while the surface floats over an undimmed app (shipped exactly once).
|
|
130
|
+
it('forwards its ref to a host node so animated styles can land', () => {
|
|
131
|
+
let node: unknown = null;
|
|
132
|
+
const { root, container } = render(
|
|
133
|
+
createElement(Backdrop, {
|
|
134
|
+
onPress: () => {},
|
|
135
|
+
testID: 'backdrop',
|
|
136
|
+
ref: (el: unknown) => {
|
|
137
|
+
node = el;
|
|
138
|
+
},
|
|
139
|
+
} as never),
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
expect(node).not.toBeNull();
|
|
143
|
+
expect(node).toBeInstanceOf(HTMLElement);
|
|
144
|
+
expect((node as HTMLElement).getAttribute('data-testid')).toBe('backdrop');
|
|
145
|
+
|
|
146
|
+
act(() => root.unmount());
|
|
147
|
+
container.remove();
|
|
148
|
+
});
|
|
149
|
+
|
|
109
150
|
it('a disabled Backdrop dims without dismissing', () => {
|
|
110
151
|
const onPress = jest.fn();
|
|
111
152
|
const { root, container } = render(
|
|
@@ -25,6 +25,7 @@ import Animated, {
|
|
|
25
25
|
withTiming,
|
|
26
26
|
} from 'react-native-reanimated';
|
|
27
27
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
28
|
+
import { Backdrop } from '../overlay';
|
|
28
29
|
import { useTheme } from '../theme/use-theme';
|
|
29
30
|
|
|
30
31
|
/** Hook that returns current screen dimensions and updates on rotation/resize. */
|
|
@@ -198,6 +199,8 @@ export interface BottomSheetBaseProps extends BottomSheetProps {
|
|
|
198
199
|
Shell: React.ComponentType<BottomSheetShellProps>;
|
|
199
200
|
}
|
|
200
201
|
|
|
202
|
+
const AnimatedBackdrop = Animated.createAnimatedComponent(Backdrop);
|
|
203
|
+
|
|
201
204
|
export const BottomSheetBase = forwardRef((props: BottomSheetBaseProps, ref: React.ForwardedRef<BottomSheetRef>) => {
|
|
202
205
|
const {
|
|
203
206
|
Shell,
|
|
@@ -783,15 +786,21 @@ export const BottomSheetBase = forwardRef((props: BottomSheetBaseProps, ref: Rea
|
|
|
783
786
|
return (
|
|
784
787
|
<Shell visible={rendered} onRequestClose={dismiss} keyboardHeight={keyboardHeight}>
|
|
785
788
|
<View style={StyleSheet.absoluteFill}>
|
|
786
|
-
|
|
787
|
-
{
|
|
788
|
-
backdropComponent({ onPress: handleBackdropPress })
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
789
|
+
{backdropComponent ? (
|
|
790
|
+
<Animated.View style={[StyleSheet.absoluteFill, backdropStyle]}>
|
|
791
|
+
{backdropComponent({ onPress: handleBackdropPress })}
|
|
792
|
+
</Animated.View>
|
|
793
|
+
) : (
|
|
794
|
+
// The ONE Bloom backdrop (blur + dim + press-to-dismiss).
|
|
795
|
+
// `backdropStyle` drives the fade; the dim level rides on
|
|
796
|
+
// `backdropOpacity`, so the shared component's own dim is
|
|
797
|
+
// switched off here to keep a single source of dimming.
|
|
798
|
+
<AnimatedBackdrop
|
|
799
|
+
onPress={handleBackdropPress}
|
|
800
|
+
dimOpacity={1}
|
|
801
|
+
style={[styles.backdrop, backdropStyle]}
|
|
802
|
+
/>
|
|
803
|
+
)}
|
|
795
804
|
|
|
796
805
|
<GestureDetector gesture={panGesture}>
|
|
797
806
|
<Animated.View
|
|
@@ -60,6 +60,12 @@ import type {
|
|
|
60
60
|
|
|
61
61
|
const FADE_OUT_DURATION = CENTER_FADE_OUT_DURATION;
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* The centered card's scrim reads darker than a sheet's because the card floats
|
|
65
|
+
* in the middle of it; the shared blur underneath is identical.
|
|
66
|
+
*/
|
|
67
|
+
const DIALOG_BACKDROP_DIM_OPACITY = 0.6;
|
|
68
|
+
|
|
63
69
|
/**
|
|
64
70
|
* The four CSS `animation` shorthands driving the centered card and its backdrop.
|
|
65
71
|
* `animation` has no `ViewStyle` key at all — react-native-web forwards it to the
|
|
@@ -325,15 +331,18 @@ function CenterOrSideDialog({
|
|
|
325
331
|
onPress={() => close()}
|
|
326
332
|
disabled={!dismissOnBackdrop}
|
|
327
333
|
accessibilityLabel={label ? `Dismiss ${label}` : 'Dismiss dialog'}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
334
|
+
dimOpacity={DIALOG_BACKDROP_DIM_OPACITY}
|
|
335
|
+
style={[
|
|
336
|
+
{
|
|
337
|
+
position: WEB_POSITION_FIXED,
|
|
338
|
+
zIndex: dialogZIndex.backdrop,
|
|
339
|
+
alignItems: 'center',
|
|
340
|
+
justifyContent: 'center',
|
|
341
|
+
paddingHorizontal: 20,
|
|
342
|
+
},
|
|
343
|
+
isClosing ? BACKDROP_FADE_OUT : BACKDROP_FADE_IN,
|
|
344
|
+
]}
|
|
335
345
|
>
|
|
336
|
-
<DialogBackdrop isClosing={isClosing} />
|
|
337
346
|
<DialogPanel
|
|
338
347
|
testID={testID}
|
|
339
348
|
label={label}
|
|
@@ -693,6 +702,9 @@ function SheetSurface({
|
|
|
693
702
|
accessibilityLabel={label ? `Dismiss ${label}` : 'Dismiss dialog'}
|
|
694
703
|
onPress={handleBackdropPress}
|
|
695
704
|
disabled={!dismissOnBackdrop}
|
|
705
|
+
// The dim rides on the element's own animated opacity here, so the
|
|
706
|
+
// shared component's dim layer stays fully opaque under it.
|
|
707
|
+
dimOpacity={1}
|
|
696
708
|
style={[
|
|
697
709
|
sheetStyles.backdrop,
|
|
698
710
|
backdropTransition,
|
|
@@ -799,22 +811,6 @@ function cancelFrame(token: FrameToken): void {
|
|
|
799
811
|
clearTimeout(token.timer);
|
|
800
812
|
}
|
|
801
813
|
|
|
802
|
-
function DialogBackdrop({ isClosing }: { isClosing: boolean }) {
|
|
803
|
-
const style: ViewStyle[] = [
|
|
804
|
-
{
|
|
805
|
-
position: WEB_POSITION_FIXED,
|
|
806
|
-
top: 0,
|
|
807
|
-
left: 0,
|
|
808
|
-
right: 0,
|
|
809
|
-
bottom: 0,
|
|
810
|
-
backgroundColor: 'rgba(0,0,0,0.8)',
|
|
811
|
-
},
|
|
812
|
-
isClosing ? BACKDROP_FADE_OUT : BACKDROP_FADE_IN,
|
|
813
|
-
];
|
|
814
|
-
|
|
815
|
-
return <View style={style} />;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
814
|
/**
|
|
819
815
|
* Inline imperative dialog used by `alert()`. Mounts and immediately
|
|
820
816
|
* presents; resolves the host's `onResolve` once the dialog has finished
|
package/src/overlay/index.tsx
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* The shared plumbing every portaled surface needs: an interactive ROOT and a
|
|
3
3
|
* press-to-dismiss BACKDROP. Dialog, BottomSheet, the image gallery, menus and
|
|
4
4
|
* toasts each used to hand-roll both, and each one got the web contract subtly
|
|
5
|
-
* wrong in its own way
|
|
5
|
+
* wrong in its own way — and looked different while doing it (the image viewer
|
|
6
|
+
* blurred, everything else only dimmed).
|
|
6
7
|
*
|
|
7
8
|
* ## The contract these two components encode
|
|
8
9
|
*
|
|
@@ -26,14 +27,39 @@
|
|
|
26
27
|
* which is what makes it look like a dismissal bug rather than a hit-testing
|
|
27
28
|
* one.
|
|
28
29
|
*
|
|
30
|
+
* A backdrop also only dismisses what is actually ON TOP of it: a full-screen
|
|
31
|
+
* layer rendered ABOVE the backdrop (a pager, a zoom container) receives the
|
|
32
|
+
* press first and swallows it. Either that layer opts out (`pointerEvents
|
|
33
|
+
*="box-none"`) or it owns the dismiss itself — the backdrop being present is
|
|
34
|
+
* not enough.
|
|
35
|
+
*
|
|
36
|
+
* EXPO/EXPO-ROUTER APPS ONLY for `BloomProvider` — see `src/provider`; these
|
|
37
|
+
* two components are universal.
|
|
38
|
+
*
|
|
29
39
|
* Use `<OverlayRoot>` for the surface's outermost node and `<Backdrop>` for its
|
|
30
40
|
* dimming layer; do not re-implement either with raw `View`s.
|
|
31
41
|
*/
|
|
32
|
-
import { memo, type ReactNode } from 'react';
|
|
33
|
-
import {
|
|
42
|
+
import { forwardRef, memo, type ReactNode } from 'react';
|
|
43
|
+
import { BlurView } from 'expo-blur';
|
|
44
|
+
import {
|
|
45
|
+
Platform,
|
|
46
|
+
Pressable,
|
|
47
|
+
StyleSheet,
|
|
48
|
+
View,
|
|
49
|
+
type StyleProp,
|
|
50
|
+
type ViewStyle,
|
|
51
|
+
} from 'react-native';
|
|
34
52
|
|
|
35
53
|
import { WEB_POSITION_FIXED } from '../styles/web-view-style';
|
|
36
54
|
|
|
55
|
+
/**
|
|
56
|
+
* One blur radius for every Bloom overlay. Surfaces differ in what they show,
|
|
57
|
+
* not in how the app behind them recedes.
|
|
58
|
+
*/
|
|
59
|
+
export const BACKDROP_BLUR_INTENSITY = 40;
|
|
60
|
+
/** Dim laid over the blur — the blur alone does not give enough contrast. */
|
|
61
|
+
export const BACKDROP_DIM_OPACITY = 0.45;
|
|
62
|
+
|
|
37
63
|
export interface OverlayRootProps {
|
|
38
64
|
children?: ReactNode;
|
|
39
65
|
style?: StyleProp<ViewStyle>;
|
|
@@ -61,30 +87,52 @@ export interface BackdropProps {
|
|
|
61
87
|
onPress?: () => void;
|
|
62
88
|
/** `true` keeps the dim but makes it inert — a blocking dialog, a busy state. */
|
|
63
89
|
disabled?: boolean;
|
|
64
|
-
/**
|
|
90
|
+
/** Blur radius behind the dim. `0` renders the dim alone. */
|
|
91
|
+
blurIntensity?: number;
|
|
92
|
+
/** Blur tint. Backdrops dim the app, so `dark` is the default on every theme. */
|
|
93
|
+
blurTint?: 'light' | 'dark' | 'default';
|
|
94
|
+
/** Dim colour over the blur. */
|
|
95
|
+
dimColor?: string;
|
|
96
|
+
/** Dim opacity, 0–1. */
|
|
97
|
+
dimOpacity?: number;
|
|
98
|
+
/** Extra style on the press target — animated opacity, insets, z-index. */
|
|
65
99
|
style?: StyleProp<ViewStyle>;
|
|
66
|
-
/** Rendered
|
|
100
|
+
/** Rendered ON TOP of the dim, inside the press target (Dialog's panel does this). */
|
|
67
101
|
children?: ReactNode;
|
|
68
102
|
accessibilityLabel?: string;
|
|
69
103
|
testID?: string;
|
|
70
104
|
}
|
|
71
105
|
|
|
72
106
|
/**
|
|
73
|
-
* Full-bleed
|
|
74
|
-
*
|
|
75
|
-
*
|
|
107
|
+
* Full-bleed blur + dim that dismisses the surface when pressed. Always takes
|
|
108
|
+
* pointer events (that is its whole job), so anything that must stay pressable
|
|
109
|
+
* goes INSIDE it as `children`, never as a sibling rendered over it.
|
|
76
110
|
*/
|
|
77
|
-
export const Backdrop = memo(function Backdrop(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
111
|
+
export const Backdrop = memo(forwardRef<View, BackdropProps>(function Backdrop(
|
|
112
|
+
{
|
|
113
|
+
onPress,
|
|
114
|
+
disabled = false,
|
|
115
|
+
blurIntensity = BACKDROP_BLUR_INTENSITY,
|
|
116
|
+
blurTint = 'dark',
|
|
117
|
+
dimColor = '#000',
|
|
118
|
+
dimOpacity = BACKDROP_DIM_OPACITY,
|
|
119
|
+
style,
|
|
120
|
+
children,
|
|
121
|
+
accessibilityLabel = 'Dismiss',
|
|
122
|
+
testID,
|
|
123
|
+
},
|
|
124
|
+
ref,
|
|
125
|
+
) {
|
|
85
126
|
const inert = disabled || !onPress;
|
|
86
127
|
return (
|
|
87
128
|
<Pressable
|
|
129
|
+
// MUST forward the ref: surfaces animate the backdrop through
|
|
130
|
+
// `Animated.createAnimatedComponent(Backdrop)`, and reanimated applies
|
|
131
|
+
// those updates by reaching the underlying host view. With the ref
|
|
132
|
+
// swallowed the animated style never lands, so a backdrop whose opacity
|
|
133
|
+
// is animated from 0 stays at 0 — fully transparent, with the surface
|
|
134
|
+
// floating over an undimmed app.
|
|
135
|
+
ref={ref}
|
|
88
136
|
pointerEvents="auto"
|
|
89
137
|
onPress={inert ? undefined : onPress}
|
|
90
138
|
disabled={inert}
|
|
@@ -97,10 +145,27 @@ export const Backdrop = memo(function Backdrop({
|
|
|
97
145
|
testID={testID}
|
|
98
146
|
style={[StyleSheet.absoluteFill, style]}
|
|
99
147
|
>
|
|
148
|
+
{blurIntensity > 0 ? (
|
|
149
|
+
<BlurView
|
|
150
|
+
intensity={blurIntensity}
|
|
151
|
+
tint={blurTint}
|
|
152
|
+
// Android's default blur is a no-op on many devices; this is the
|
|
153
|
+
// implementation that actually renders there.
|
|
154
|
+
experimentalBlurMethod="dimezisBlurView"
|
|
155
|
+
pointerEvents="none"
|
|
156
|
+
style={StyleSheet.absoluteFill}
|
|
157
|
+
/>
|
|
158
|
+
) : null}
|
|
159
|
+
<View
|
|
160
|
+
pointerEvents="none"
|
|
161
|
+
style={[StyleSheet.absoluteFill, { backgroundColor: dimColor, opacity: dimOpacity }]}
|
|
162
|
+
/>
|
|
100
163
|
{children}
|
|
101
164
|
</Pressable>
|
|
102
165
|
);
|
|
103
|
-
});
|
|
166
|
+
}));
|
|
167
|
+
|
|
168
|
+
Backdrop.displayName = 'Backdrop';
|
|
104
169
|
|
|
105
170
|
const styles = StyleSheet.create({
|
|
106
171
|
root: {
|
package/src/provider/index.tsx
CHANGED
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
* Nesting extra contexts costs nothing at runtime — the win is that scope is no
|
|
19
19
|
* longer a per-app decision.
|
|
20
20
|
*
|
|
21
|
+
* EXPO/EXPO-ROUTER APPS ONLY. The scroll-restoration provider it mounts imports
|
|
22
|
+
* `expo-router` (its web implementation keys offsets on the focused route), so
|
|
23
|
+
* a Vite/SPA consumer that has no expo-router cannot resolve this module. Those
|
|
24
|
+
* apps keep mounting `BloomThemeProvider` (and any other piece they need)
|
|
25
|
+
* directly — that is not a lesser path, just the one without a router.
|
|
26
|
+
*
|
|
21
27
|
* NOT included, on purpose — these are OUTLETS, not state, and their placement
|
|
22
28
|
* in the tree is a real app decision (z-order, safe areas, and mounting a
|
|
23
29
|
* second one duplicates every surface it renders):
|