@rific/auto-paper 0.12.1 → 0.12.3
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/README.md +3 -1
- package/dist/index.js +45 -11
- package/dist/index.mjs +49 -15
- package/package.json +1 -1
- package/src/ThemeProvider.tsx +12 -2
- package/src/components/BlurView.tsx +14 -2
- package/src/components/Dialog.tsx +25 -9
- package/src/components/Menu.tsx +57 -6
package/README.md
CHANGED
|
@@ -265,7 +265,7 @@ export default function App() {
|
|
|
265
265
|
| `onChange` | `(settings: ThemeSettings) => void` | Called whenever settings change via `useThemeSettings().set()` |
|
|
266
266
|
| `children` | `ReactNode` | |
|
|
267
267
|
| `defaults` | `PaperDefaults` | Prop defaults for wrapper components (see below) |
|
|
268
|
-
| `expoBlur` | `ExpoBlurModule` | Injects `expo-blur` (`import * as ExpoBlur from 'expo-blur'`) so `<BlurView>` renders the real frosted-glass effect. Omit to always render its solid fallback. |
|
|
268
|
+
| `expoBlur` | `ExpoBlurModule` | Injects `expo-blur` (`import * as ExpoBlur from 'expo-blur'`) so `<BlurView>` renders the real frosted-glass effect. Omit to always render its solid fallback. On Android, expo-blur only blurs when given a `blurTarget` and a `blurMethod` (`'dimezisBlurView'`, or `'dimezisBlurViewSdk31Plus'` on API 31+); without both, `<BlurView>` renders the solid fallback there too, rather than expo-blur's unblurred translucent tint. |
|
|
269
269
|
| `fontFamily` | `string` | Applied to every Paper typography variant (`bodyLarge`, `headlineMedium`, `labelSmall`, ...) via `configureFonts`'s flat-config mode — each variant keeps its own MD3 fontSize/lineHeight/weight, only fontFamily changes. Omit to keep each platform's system font. |
|
|
270
270
|
| `navigationBar` | `ExpoNavigationBarModule` | Injects `expo-navigation-bar` (`import * as ExpoNavigationBar from 'expo-navigation-bar'`) so the Android nav bar icon style auto-syncs with the theme while a `BottomNavigation` is mounted. Omit (and don't pass `onNavBarChange`) to skip nav bar syncing entirely. |
|
|
271
271
|
| `onNavBarChange` | `(color: string, dark: boolean) => void` | Overrides the built-in nav bar sync: called on Android when the theme changes while a `BottomNavigation` is mounted, instead of the automatic `navigationBar`-driven icon-style sync |
|
|
@@ -274,6 +274,8 @@ export default function App() {
|
|
|
274
274
|
| `statusBarProps` | `StatusBarProps` | Spread over the auto-derived `StatusBar` defaults |
|
|
275
275
|
| `style` | `StyleProp<ViewStyle>` | Applied to the wrapper `View` |
|
|
276
276
|
|
|
277
|
+
`Provider` also renders its own `Portal.Host`, nested inside everything it injects, so anything rendered through `react-native-paper`'s `Portal` (this package's `Dialog`, Paper's `Menu` and `Tooltip`, or a `Modal`/`Snackbar`/anything else you wrap in `<Portal>` yourself) still sees `expoBlur`, `reanimated` and `defaults`. Paper's own host sits above all of those and its `Portal` only carries the theme across, so without this a portaled `Dialog` or `Menu` would silently render its solid fallback. Contexts your app provides *inside* `Provider` (a toast provider, say) are a separate matter: portal content can't see them unless you render another `<Portal.Host>` below them.
|
|
278
|
+
|
|
277
279
|
`ThemeSettings` fields:
|
|
278
280
|
|
|
279
281
|
| Field | Type | Default |
|
package/dist/index.js
CHANGED
|
@@ -706,7 +706,7 @@ function ThemeProviderBody({ children, defaults, expoBlur, fontFamily, navigatio
|
|
|
706
706
|
if (!theme) return null;
|
|
707
707
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native_paper4.Provider, { theme, children: [
|
|
708
708
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native3.StatusBar, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }),
|
|
709
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ReanimatedModuleContext.Provider, { value: reanimated, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native3.View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) }) })
|
|
709
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ReanimatedModuleContext.Provider, { value: reanimated, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_paper4.Portal.Host, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native3.View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) }) }) })
|
|
710
710
|
] });
|
|
711
711
|
}
|
|
712
712
|
var styles = import_react_native3.StyleSheet.create({
|
|
@@ -718,6 +718,11 @@ var import_react6 = require("react");
|
|
|
718
718
|
var import_react_native4 = require("react-native");
|
|
719
719
|
var import_react_native_paper5 = require("react-native-paper");
|
|
720
720
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
721
|
+
var blursOnAndroid = ({ blurMethod, blurTarget, experimentalBlurMethod }) => {
|
|
722
|
+
const method = blurMethod ?? experimentalBlurMethod ?? "none";
|
|
723
|
+
if (!blurTarget || method === "none") return false;
|
|
724
|
+
return method === "dimezisBlurView" || Number(import_react_native4.Platform.Version) >= 31;
|
|
725
|
+
};
|
|
721
726
|
var ELEVATION_OPACITY = { 0: 0, 1: 0.05, 2: 0.08, 3: 0.11, 4: 0.12, 5: 0.14 };
|
|
722
727
|
var VARIANT_TINT_OPACITY = { light: 0.12, dark: 0.18 };
|
|
723
728
|
var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacity, variant = "surface", ...props }) => {
|
|
@@ -729,7 +734,7 @@ var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacit
|
|
|
729
734
|
const resolvedTintColor = tintColor ?? variantColor ?? (elevation !== void 0 ? colors.primary : void 0);
|
|
730
735
|
const resolvedTintOpacity = tintOpacity ?? (tintColor ? dark ? 0.24 : 0.16 : variantColor ? dark ? VARIANT_TINT_OPACITY.dark : VARIANT_TINT_OPACITY.light : elevation !== void 0 ? ELEVATION_OPACITY[elevation] : 0);
|
|
731
736
|
const tint = resolvedTintColor && resolvedTintOpacity > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.View, { style: [import_react_native4.StyleSheet.absoluteFill, { backgroundColor: resolvedTintColor, opacity: resolvedTintOpacity }] }) : null;
|
|
732
|
-
if (blur && expoBlur)
|
|
737
|
+
if (blur && expoBlur && (import_react_native4.Platform.OS !== "android" || blursOnAndroid(props)))
|
|
733
738
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(expoBlur.BlurView, { ...props, tint: dark ? "dark" : "light", style, children: [
|
|
734
739
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.View, { style: [import_react_native4.StyleSheet.absoluteFill, { backgroundColor: surfaceColor, opacity: settings.blurTint }] }),
|
|
735
740
|
tint,
|
|
@@ -745,6 +750,8 @@ var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacit
|
|
|
745
750
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
746
751
|
var ANIMATION_DURATION = 220;
|
|
747
752
|
var DIALOG_MARGIN = 32;
|
|
753
|
+
var AnimatedBlurView = import_react_native5.Animated.createAnimatedComponent(BlurView);
|
|
754
|
+
var AnimatedPressable = import_react_native5.Animated.createAnimatedComponent(import_react_native5.Pressable);
|
|
748
755
|
function DialogComponent({ animatedStyle, blur: blurProp, dismissable = true, dismissableBackButton = dismissable, visible, onDismiss, children, style, testID = "dialog" }) {
|
|
749
756
|
const blur = useBlur(blurProp);
|
|
750
757
|
const reanimated = useReanimatedModule();
|
|
@@ -788,9 +795,16 @@ function DialogComponent({ animatedStyle, blur: blurProp, dismissable = true, di
|
|
|
788
795
|
return child;
|
|
789
796
|
});
|
|
790
797
|
const borderRadius = (isV3 ? 7 : 1) * roundness;
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
798
|
+
const web = import_react_native5.Platform.OS === "web";
|
|
799
|
+
const fade = { opacity };
|
|
800
|
+
const styleOpacity = import_react_native5.StyleSheet.flatten(style)?.opacity;
|
|
801
|
+
const cardFade = typeof styleOpacity === "number" ? { opacity: import_react_native5.Animated.multiply(opacity, styleOpacity) } : fade;
|
|
802
|
+
const Backdrop = web ? AnimatedPressable : import_react_native5.Pressable;
|
|
803
|
+
const Card = web ? AnimatedBlurView : BlurView;
|
|
804
|
+
const card = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Card, { blur, style: [styles2.card, { borderRadius }, style, web && cardFade], testID: `${testID}-surface`, children: content });
|
|
805
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper6.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native5.Animated.View, { accessibilityLiveRegion: "polite", accessibilityViewIsModal: true, pointerEvents: visible ? "box-none" : "none", style: [import_react_native5.StyleSheet.absoluteFill, !web && fade], testID, children: [
|
|
806
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Backdrop, { accessibilityLabel: "Close modal", accessibilityRole: "button", disabled: !dismissable, onPress: dismissable ? onDismiss : void 0, style: [import_react_native5.StyleSheet.absoluteFill, { backgroundColor: colors.backdrop }, web && fade], testID: `${testID}-backdrop` }),
|
|
807
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.View, { pointerEvents: "box-none", style: [styles2.wrapper, { marginBottom: bottom, marginTop: top, paddingHorizontal: Math.max(left, right, DIALOG_MARGIN) }], testID: `${testID}-wrapper`, children: reanimated && animatedStyle ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(reanimated.View, { style: animatedStyle, testID: `${testID}-animated-wrapper`, children: card }) : card })
|
|
794
808
|
] }) });
|
|
795
809
|
}
|
|
796
810
|
DialogComponent.Title = import_react_native_paper6.Dialog.Title;
|
|
@@ -1031,25 +1045,45 @@ function IconButton({ variant, iconColor, containerColor, ...props }) {
|
|
|
1031
1045
|
}
|
|
1032
1046
|
|
|
1033
1047
|
// src/components/Menu.tsx
|
|
1048
|
+
var import_react11 = require("react");
|
|
1034
1049
|
var import_react_native9 = require("react-native");
|
|
1035
1050
|
var import_react_native_paper15 = require("react-native-paper");
|
|
1036
1051
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1052
|
+
var ANIMATION_DURATION2 = 250;
|
|
1053
|
+
var EASING = import_react_native9.Easing.bezier(0.4, 0, 0.2, 1);
|
|
1054
|
+
var DEFAULT_ELEVATION = 2;
|
|
1055
|
+
var SHADOW_HEIGHT = [0, 1, 2, 4, 6, 8];
|
|
1056
|
+
var SHADOW_RADIUS = [0, 3, 6, 8, 10, 12];
|
|
1057
|
+
var AnimatedBlurView2 = import_react_native9.Animated.createAnimatedComponent(BlurView);
|
|
1058
|
+
var FadingBlurView = ({ blur, children, elevation, theme: themeOverrides, visible }) => {
|
|
1059
|
+
const { animation, roundness } = (0, import_react_native_paper15.useTheme)(themeOverrides);
|
|
1060
|
+
const [opacity] = (0, import_react11.useState)(() => new import_react_native9.Animated.Value(0));
|
|
1061
|
+
const [closing, setClosing] = (0, import_react11.useState)(false);
|
|
1062
|
+
if (!visible && !closing) setClosing(true);
|
|
1063
|
+
(0, import_react11.useEffect)(() => {
|
|
1064
|
+
import_react_native9.Animated.timing(opacity, { duration: animation.scale * ANIMATION_DURATION2, easing: EASING, toValue: closing ? 0 : 1, useNativeDriver: false }).start();
|
|
1065
|
+
}, [animation.scale, closing, opacity]);
|
|
1066
|
+
const shadow = elevation > 0 ? { shadowColor: "#000000", shadowOffset: { height: SHADOW_HEIGHT[elevation], width: 0 }, shadowOpacity: 0.3, shadowRadius: SHADOW_RADIUS[elevation] } : null;
|
|
1067
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AnimatedBlurView2, { blur, style: [{ borderRadius: roundness, opacity }, shadow], children });
|
|
1068
|
+
};
|
|
1037
1069
|
var MenuComponent = ({ blur: blurProp, children, ...props }) => {
|
|
1038
1070
|
const blur = useBlur(blurProp);
|
|
1039
|
-
|
|
1071
|
+
const web = import_react_native9.Platform.OS === "web";
|
|
1072
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native_paper15.Menu, { ...props, contentStyle: [styles5.content, web && styles5.webSurface, props.contentStyle], children: web ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(FadingBlurView, { blur, elevation: props.mode === "flat" ? 0 : props.elevation ?? DEFAULT_ELEVATION, theme: props.theme, visible: props.visible, children }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(BlurView, { blur, children }) });
|
|
1040
1073
|
};
|
|
1041
1074
|
var Menu = Object.assign(MenuComponent, {
|
|
1042
1075
|
Item: import_react_native_paper15.Menu.Item
|
|
1043
1076
|
});
|
|
1044
1077
|
var styles5 = import_react_native9.StyleSheet.create({
|
|
1045
|
-
content: { backgroundColor: "transparent", paddingVertical: 0 }
|
|
1078
|
+
content: { backgroundColor: "transparent", paddingVertical: 0 },
|
|
1079
|
+
webSurface: { opacity: 1, shadowOpacity: 0 }
|
|
1046
1080
|
});
|
|
1047
1081
|
|
|
1048
1082
|
// src/components/TextInput.tsx
|
|
1049
|
-
var
|
|
1083
|
+
var import_react12 = require("react");
|
|
1050
1084
|
var import_react_native_paper16 = require("react-native-paper");
|
|
1051
1085
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1052
|
-
var TextInput = (0,
|
|
1086
|
+
var TextInput = (0, import_react12.forwardRef)(function TextInput2(props, ref) {
|
|
1053
1087
|
const defaults = usePaperDefaults();
|
|
1054
1088
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native_paper16.TextInput, { ref, ...defaults.TextInput, ...props });
|
|
1055
1089
|
});
|
|
@@ -1080,10 +1114,10 @@ var import_react_native_paper17 = require("react-native-paper");
|
|
|
1080
1114
|
var useAutoPaperTheme = () => (0, import_react_native_paper17.useTheme)();
|
|
1081
1115
|
|
|
1082
1116
|
// src/useThemeBridgeProps.ts
|
|
1083
|
-
var
|
|
1117
|
+
var import_react13 = require("react");
|
|
1084
1118
|
function useThemeBridgeProps(props) {
|
|
1085
1119
|
const { initialValue, onChange, onReady } = props;
|
|
1086
|
-
return (0,
|
|
1120
|
+
return (0, import_react13.useMemo)(() => ({ initialValue, onChange, onReady }), [initialValue, onChange, onReady]);
|
|
1087
1121
|
}
|
|
1088
1122
|
|
|
1089
1123
|
// src/utils/getThirdColor.ts
|
package/dist/index.mjs
CHANGED
|
@@ -416,14 +416,14 @@ import { Icon, TouchableRipple, useTheme as useTheme4 } from "react-native-paper
|
|
|
416
416
|
|
|
417
417
|
// src/components/Dialog.tsx
|
|
418
418
|
import React, { useEffect as useEffect3, useState as useState3 } from "react";
|
|
419
|
-
import { Animated, BackHandler, Easing, Pressable, StyleSheet as StyleSheet3, View as View3 } from "react-native";
|
|
420
|
-
import { Dialog as PaperDialog, Portal, useTheme as useTheme3 } from "react-native-paper";
|
|
419
|
+
import { Animated, BackHandler, Easing, Platform as Platform2, Pressable, StyleSheet as StyleSheet3, View as View3 } from "react-native";
|
|
420
|
+
import { Dialog as PaperDialog, Portal as Portal2, useTheme as useTheme3 } from "react-native-paper";
|
|
421
421
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
422
422
|
|
|
423
423
|
// src/ThemeProvider.tsx
|
|
424
424
|
import { createContext as createContext2, useContext as useContext3, useEffect as useEffect2, useMemo, useRef } from "react";
|
|
425
425
|
import { StatusBar as StatusBar2, StyleSheet, View } from "react-native";
|
|
426
|
-
import { configureFonts, Provider as PaperProvider } from "react-native-paper";
|
|
426
|
+
import { configureFonts, Portal, Provider as PaperProvider } from "react-native-paper";
|
|
427
427
|
|
|
428
428
|
// src/useComputedTheme.ts
|
|
429
429
|
import { useCallback, useEffect, useState as useState2 } from "react";
|
|
@@ -623,7 +623,7 @@ function ThemeProviderBody({ children, defaults, expoBlur, fontFamily, navigatio
|
|
|
623
623
|
if (!theme) return null;
|
|
624
624
|
return /* @__PURE__ */ jsxs2(PaperProvider, { theme, children: [
|
|
625
625
|
/* @__PURE__ */ jsx4(StatusBar2, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }),
|
|
626
|
-
/* @__PURE__ */ jsx4(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ jsx4(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ jsx4(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ jsx4(ReanimatedModuleContext.Provider, { value: reanimated, children: /* @__PURE__ */ jsx4(View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) }) })
|
|
626
|
+
/* @__PURE__ */ jsx4(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ jsx4(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ jsx4(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ jsx4(ReanimatedModuleContext.Provider, { value: reanimated, children: /* @__PURE__ */ jsx4(Portal.Host, { children: /* @__PURE__ */ jsx4(View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) }) }) })
|
|
627
627
|
] });
|
|
628
628
|
}
|
|
629
629
|
var styles = StyleSheet.create({
|
|
@@ -632,9 +632,14 @@ var styles = StyleSheet.create({
|
|
|
632
632
|
|
|
633
633
|
// src/components/BlurView.tsx
|
|
634
634
|
import { useContext as useContext4 } from "react";
|
|
635
|
-
import { StyleSheet as StyleSheet2, View as View2 } from "react-native";
|
|
635
|
+
import { Platform, StyleSheet as StyleSheet2, View as View2 } from "react-native";
|
|
636
636
|
import { useTheme as useTheme2 } from "react-native-paper";
|
|
637
637
|
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
638
|
+
var blursOnAndroid = ({ blurMethod, blurTarget, experimentalBlurMethod }) => {
|
|
639
|
+
const method = blurMethod ?? experimentalBlurMethod ?? "none";
|
|
640
|
+
if (!blurTarget || method === "none") return false;
|
|
641
|
+
return method === "dimezisBlurView" || Number(Platform.Version) >= 31;
|
|
642
|
+
};
|
|
638
643
|
var ELEVATION_OPACITY = { 0: 0, 1: 0.05, 2: 0.08, 3: 0.11, 4: 0.12, 5: 0.14 };
|
|
639
644
|
var VARIANT_TINT_OPACITY = { light: 0.12, dark: 0.18 };
|
|
640
645
|
var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacity, variant = "surface", ...props }) => {
|
|
@@ -646,7 +651,7 @@ var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacit
|
|
|
646
651
|
const resolvedTintColor = tintColor ?? variantColor ?? (elevation !== void 0 ? colors.primary : void 0);
|
|
647
652
|
const resolvedTintOpacity = tintOpacity ?? (tintColor ? dark ? 0.24 : 0.16 : variantColor ? dark ? VARIANT_TINT_OPACITY.dark : VARIANT_TINT_OPACITY.light : elevation !== void 0 ? ELEVATION_OPACITY[elevation] : 0);
|
|
648
653
|
const tint = resolvedTintColor && resolvedTintOpacity > 0 ? /* @__PURE__ */ jsx5(View2, { style: [StyleSheet2.absoluteFill, { backgroundColor: resolvedTintColor, opacity: resolvedTintOpacity }] }) : null;
|
|
649
|
-
if (blur && expoBlur)
|
|
654
|
+
if (blur && expoBlur && (Platform.OS !== "android" || blursOnAndroid(props)))
|
|
650
655
|
return /* @__PURE__ */ jsxs3(expoBlur.BlurView, { ...props, tint: dark ? "dark" : "light", style, children: [
|
|
651
656
|
/* @__PURE__ */ jsx5(View2, { style: [StyleSheet2.absoluteFill, { backgroundColor: surfaceColor, opacity: settings.blurTint }] }),
|
|
652
657
|
tint,
|
|
@@ -662,6 +667,8 @@ var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacit
|
|
|
662
667
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
663
668
|
var ANIMATION_DURATION = 220;
|
|
664
669
|
var DIALOG_MARGIN = 32;
|
|
670
|
+
var AnimatedBlurView = Animated.createAnimatedComponent(BlurView);
|
|
671
|
+
var AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
|
665
672
|
function DialogComponent({ animatedStyle, blur: blurProp, dismissable = true, dismissableBackButton = dismissable, visible, onDismiss, children, style, testID = "dialog" }) {
|
|
666
673
|
const blur = useBlur(blurProp);
|
|
667
674
|
const reanimated = useReanimatedModule();
|
|
@@ -705,9 +712,16 @@ function DialogComponent({ animatedStyle, blur: blurProp, dismissable = true, di
|
|
|
705
712
|
return child;
|
|
706
713
|
});
|
|
707
714
|
const borderRadius = (isV3 ? 7 : 1) * roundness;
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
715
|
+
const web = Platform2.OS === "web";
|
|
716
|
+
const fade = { opacity };
|
|
717
|
+
const styleOpacity = StyleSheet3.flatten(style)?.opacity;
|
|
718
|
+
const cardFade = typeof styleOpacity === "number" ? { opacity: Animated.multiply(opacity, styleOpacity) } : fade;
|
|
719
|
+
const Backdrop = web ? AnimatedPressable : Pressable;
|
|
720
|
+
const Card = web ? AnimatedBlurView : BlurView;
|
|
721
|
+
const card = /* @__PURE__ */ jsx6(Card, { blur, style: [styles2.card, { borderRadius }, style, web && cardFade], testID: `${testID}-surface`, children: content });
|
|
722
|
+
return /* @__PURE__ */ jsx6(Portal2, { children: /* @__PURE__ */ jsxs4(Animated.View, { accessibilityLiveRegion: "polite", accessibilityViewIsModal: true, pointerEvents: visible ? "box-none" : "none", style: [StyleSheet3.absoluteFill, !web && fade], testID, children: [
|
|
723
|
+
/* @__PURE__ */ jsx6(Backdrop, { accessibilityLabel: "Close modal", accessibilityRole: "button", disabled: !dismissable, onPress: dismissable ? onDismiss : void 0, style: [StyleSheet3.absoluteFill, { backgroundColor: colors.backdrop }, web && fade], testID: `${testID}-backdrop` }),
|
|
724
|
+
/* @__PURE__ */ jsx6(View3, { pointerEvents: "box-none", style: [styles2.wrapper, { marginBottom: bottom, marginTop: top, paddingHorizontal: Math.max(left, right, DIALOG_MARGIN) }], testID: `${testID}-wrapper`, children: reanimated && animatedStyle ? /* @__PURE__ */ jsx6(reanimated.View, { style: animatedStyle, testID: `${testID}-animated-wrapper`, children: card }) : card })
|
|
711
725
|
] }) });
|
|
712
726
|
}
|
|
713
727
|
DialogComponent.Title = PaperDialog.Title;
|
|
@@ -876,7 +890,7 @@ var AutoPalettePicker = (props) => {
|
|
|
876
890
|
|
|
877
891
|
// src/components/BottomNavigation.tsx
|
|
878
892
|
import { useEffect as useEffect4 } from "react";
|
|
879
|
-
import { Platform } from "react-native";
|
|
893
|
+
import { Platform as Platform3 } from "react-native";
|
|
880
894
|
import { BottomNavigation as PaperBottomNavigation, useTheme as useTheme6 } from "react-native-paper";
|
|
881
895
|
|
|
882
896
|
// src/navigation-bar.ts
|
|
@@ -891,7 +905,7 @@ function useNavigationBarSync() {
|
|
|
891
905
|
const theme = useTheme6();
|
|
892
906
|
const { navigationBar, onNavBarChange } = useNavBarContext();
|
|
893
907
|
useEffect4(() => {
|
|
894
|
-
if (
|
|
908
|
+
if (Platform3.OS !== "android") return;
|
|
895
909
|
if (onNavBarChange) onNavBarChange(theme.colors.surface, theme.dark);
|
|
896
910
|
else if (navigationBar) setNavigationBarStyle(navigationBar, theme.dark);
|
|
897
911
|
}, [theme, onNavBarChange, navigationBar]);
|
|
@@ -948,18 +962,38 @@ function IconButton({ variant, iconColor, containerColor, ...props }) {
|
|
|
948
962
|
}
|
|
949
963
|
|
|
950
964
|
// src/components/Menu.tsx
|
|
951
|
-
import {
|
|
952
|
-
import {
|
|
965
|
+
import { useEffect as useEffect5, useState as useState6 } from "react";
|
|
966
|
+
import { Animated as Animated2, Easing as Easing2, Platform as Platform4, StyleSheet as StyleSheet6 } from "react-native";
|
|
967
|
+
import { Menu as PaperMenu, useTheme as useTheme9 } from "react-native-paper";
|
|
953
968
|
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
969
|
+
var ANIMATION_DURATION2 = 250;
|
|
970
|
+
var EASING = Easing2.bezier(0.4, 0, 0.2, 1);
|
|
971
|
+
var DEFAULT_ELEVATION = 2;
|
|
972
|
+
var SHADOW_HEIGHT = [0, 1, 2, 4, 6, 8];
|
|
973
|
+
var SHADOW_RADIUS = [0, 3, 6, 8, 10, 12];
|
|
974
|
+
var AnimatedBlurView2 = Animated2.createAnimatedComponent(BlurView);
|
|
975
|
+
var FadingBlurView = ({ blur, children, elevation, theme: themeOverrides, visible }) => {
|
|
976
|
+
const { animation, roundness } = useTheme9(themeOverrides);
|
|
977
|
+
const [opacity] = useState6(() => new Animated2.Value(0));
|
|
978
|
+
const [closing, setClosing] = useState6(false);
|
|
979
|
+
if (!visible && !closing) setClosing(true);
|
|
980
|
+
useEffect5(() => {
|
|
981
|
+
Animated2.timing(opacity, { duration: animation.scale * ANIMATION_DURATION2, easing: EASING, toValue: closing ? 0 : 1, useNativeDriver: false }).start();
|
|
982
|
+
}, [animation.scale, closing, opacity]);
|
|
983
|
+
const shadow = elevation > 0 ? { shadowColor: "#000000", shadowOffset: { height: SHADOW_HEIGHT[elevation], width: 0 }, shadowOpacity: 0.3, shadowRadius: SHADOW_RADIUS[elevation] } : null;
|
|
984
|
+
return /* @__PURE__ */ jsx16(AnimatedBlurView2, { blur, style: [{ borderRadius: roundness, opacity }, shadow], children });
|
|
985
|
+
};
|
|
954
986
|
var MenuComponent = ({ blur: blurProp, children, ...props }) => {
|
|
955
987
|
const blur = useBlur(blurProp);
|
|
956
|
-
|
|
988
|
+
const web = Platform4.OS === "web";
|
|
989
|
+
return /* @__PURE__ */ jsx16(PaperMenu, { ...props, contentStyle: [styles5.content, web && styles5.webSurface, props.contentStyle], children: web ? /* @__PURE__ */ jsx16(FadingBlurView, { blur, elevation: props.mode === "flat" ? 0 : props.elevation ?? DEFAULT_ELEVATION, theme: props.theme, visible: props.visible, children }) : /* @__PURE__ */ jsx16(BlurView, { blur, children }) });
|
|
957
990
|
};
|
|
958
991
|
var Menu = Object.assign(MenuComponent, {
|
|
959
992
|
Item: PaperMenu.Item
|
|
960
993
|
});
|
|
961
994
|
var styles5 = StyleSheet6.create({
|
|
962
|
-
content: { backgroundColor: "transparent", paddingVertical: 0 }
|
|
995
|
+
content: { backgroundColor: "transparent", paddingVertical: 0 },
|
|
996
|
+
webSurface: { opacity: 1, shadowOpacity: 0 }
|
|
963
997
|
});
|
|
964
998
|
|
|
965
999
|
// src/components/TextInput.tsx
|
package/package.json
CHANGED
package/src/ThemeProvider.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createContext, type ReactNode, useContext, useEffect, useMemo, useRef } from 'react'
|
|
2
2
|
import { StatusBar, type StatusBarProps, type StyleProp, StyleSheet, View, type ViewStyle } from 'react-native'
|
|
3
|
-
import { configureFonts, Provider as PaperProvider } from 'react-native-paper'
|
|
3
|
+
import { configureFonts, Portal, Provider as PaperProvider } from 'react-native-paper'
|
|
4
4
|
|
|
5
5
|
import type { ExpoBlurModule } from './components/BlurView'
|
|
6
6
|
import type { ReanimatedModule } from './components/Dialog'
|
|
@@ -99,7 +99,17 @@ function ThemeProviderBody({ children, defaults, expoBlur, fontFamily, navigatio
|
|
|
99
99
|
<NavBarContext.Provider value={{ navigationBar, onNavBarChange }}>
|
|
100
100
|
<BlurModuleContext.Provider value={expoBlur}>
|
|
101
101
|
<ReanimatedModuleContext.Provider value={reanimated}>
|
|
102
|
-
|
|
102
|
+
{/* PaperProvider's own PortalHost sits above every context provided here, and Paper's
|
|
103
|
+
Portal only carries its theme and settings across, so anything rendered through a
|
|
104
|
+
Portal (this package's Dialog, Paper's Menu and Tooltip, or anything an app wraps
|
|
105
|
+
in <Portal> itself) would otherwise lose expoBlur, reanimated, defaults and the nav
|
|
106
|
+
bar hooks: Dialog/Menu's blur silently fell back to solid. This nested host is the
|
|
107
|
+
nearest one for every Portal under Provider, so their content mounts inside all of
|
|
108
|
+
these contexts instead. It wraps the styled View, not the other way round, so
|
|
109
|
+
portals still cover the full area regardless of `style`. */}
|
|
110
|
+
<Portal.Host>
|
|
111
|
+
<View style={[styles.flex, { backgroundColor: theme.colors.background }, style]}>{children}</View>
|
|
112
|
+
</Portal.Host>
|
|
103
113
|
</ReanimatedModuleContext.Provider>
|
|
104
114
|
</BlurModuleContext.Provider>
|
|
105
115
|
</NavBarContext.Provider>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ComponentType, type ReactNode, type RefObject, useContext } from 'react'
|
|
2
|
-
import { type StyleProp, StyleSheet, View, type ViewProps, type ViewStyle } from 'react-native'
|
|
2
|
+
import { Platform, type StyleProp, StyleSheet, View, type ViewProps, type ViewStyle } from 'react-native'
|
|
3
3
|
import { useTheme } from 'react-native-paper'
|
|
4
4
|
|
|
5
5
|
import { useBlurModule } from '../ThemeProvider'
|
|
@@ -33,6 +33,18 @@ type ExpoBlurViewProps = {
|
|
|
33
33
|
tint?: ExpoBlurTint
|
|
34
34
|
} & ViewProps
|
|
35
35
|
|
|
36
|
+
// On Android, expo-blur only really blurs when it has both a blurTarget and a blur method
|
|
37
|
+
// ('dimezisBlurView', or 'dimezisBlurViewSdk31Plus' on API 31+); blurMethod defaults to 'none'.
|
|
38
|
+
// Otherwise it paints its tint as a flat translucent fill (roughly 0.35-0.39 alpha at the default
|
|
39
|
+
// intensity) with the screen showing through unblurred, so BlurView renders its solid look instead.
|
|
40
|
+
// Checks the blurTarget ref object, not its .current, same as expo-blur's own JS: the target view
|
|
41
|
+
// usually commits after this render, so .current is still null here even when wired correctly.
|
|
42
|
+
const blursOnAndroid = ({ blurMethod, blurTarget, experimentalBlurMethod }: ExpoBlurViewProps) => {
|
|
43
|
+
const method = blurMethod ?? experimentalBlurMethod ?? 'none'
|
|
44
|
+
if (!blurTarget || method === 'none') return false
|
|
45
|
+
return method === 'dimezisBlurView' || Number(Platform.Version) >= 31
|
|
46
|
+
}
|
|
47
|
+
|
|
36
48
|
const ELEVATION_OPACITY: Record<number, number> = { 0: 0, 1: 0.05, 2: 0.08, 3: 0.11, 4: 0.12, 5: 0.14 }
|
|
37
49
|
const VARIANT_TINT_OPACITY = { light: 0.12, dark: 0.18 }
|
|
38
50
|
|
|
@@ -55,7 +67,7 @@ export const BlurView = ({ blur = true, children, elevation, style, tintColor, t
|
|
|
55
67
|
const resolvedTintColor = tintColor ?? variantColor ?? (elevation !== undefined ? colors.primary : undefined)
|
|
56
68
|
const resolvedTintOpacity = tintOpacity ?? (tintColor ? (dark ? 0.24 : 0.16) : variantColor ? (dark ? VARIANT_TINT_OPACITY.dark : VARIANT_TINT_OPACITY.light) : elevation !== undefined ? ELEVATION_OPACITY[elevation] : 0)
|
|
57
69
|
const tint = resolvedTintColor && resolvedTintOpacity > 0 ? <View style={[StyleSheet.absoluteFill, { backgroundColor: resolvedTintColor, opacity: resolvedTintOpacity }]} /> : null
|
|
58
|
-
if (blur && expoBlur)
|
|
70
|
+
if (blur && expoBlur && (Platform.OS !== 'android' || blursOnAndroid(props)))
|
|
59
71
|
return (
|
|
60
72
|
<expoBlur.BlurView {...props} tint={dark ? 'dark' : 'light'} style={style}>
|
|
61
73
|
<View style={[StyleSheet.absoluteFill, { backgroundColor: surfaceColor, opacity: settings.blurTint }]} />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { type ComponentType, type ReactNode, useEffect, useState } from 'react'
|
|
2
|
-
import { Animated, BackHandler, Easing, Pressable, type StyleProp, StyleSheet, View, type ViewStyle } from 'react-native'
|
|
2
|
+
import { Animated, BackHandler, Easing, Platform, Pressable, type StyleProp, StyleSheet, View, type ViewStyle } from 'react-native'
|
|
3
3
|
import { Dialog as PaperDialog, type DialogActionsProps, type DialogContentProps, type DialogProps as PaperDialogProps, type DialogScrollAreaProps, type DialogTitleProps, Portal, useTheme } from 'react-native-paper'
|
|
4
4
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
5
5
|
|
|
@@ -39,6 +39,9 @@ const ANIMATION_DURATION = 220
|
|
|
39
39
|
// Minimum breathing room between the card and the screen edge, clamped up from safe-area insets.
|
|
40
40
|
const DIALOG_MARGIN = 32
|
|
41
41
|
|
|
42
|
+
const AnimatedBlurView = Animated.createAnimatedComponent(BlurView)
|
|
43
|
+
const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
|
|
44
|
+
|
|
42
45
|
function DialogComponent({ animatedStyle, blur: blurProp, dismissable = true, dismissableBackButton = dismissable, visible, onDismiss, children, style, testID = 'dialog' }: DialogProps) {
|
|
43
46
|
const blur = useBlur(blurProp)
|
|
44
47
|
const reanimated = useReanimatedModule()
|
|
@@ -93,21 +96,34 @@ function DialogComponent({ animatedStyle, blur: blurProp, dismissable = true, di
|
|
|
93
96
|
|
|
94
97
|
const borderRadius = (isV3 ? 7 : 1) * roundness
|
|
95
98
|
|
|
99
|
+
// On web, an ancestor below opacity 1 cuts the card's CSS backdrop-filter off from the page behind
|
|
100
|
+
// it, and Chromium doesn't restore the blur once that ancestor fades back up to 1, so fading the
|
|
101
|
+
// whole layer would leave the open card see-through. There the fade runs on the backdrop and on the
|
|
102
|
+
// card (the backdrop-filter element) itself instead, off the same value. A numeric opacity in the
|
|
103
|
+
// card's own style still applies there, multiplied into the fade.
|
|
104
|
+
const web = Platform.OS === 'web'
|
|
105
|
+
const fade = { opacity }
|
|
106
|
+
const styleOpacity = StyleSheet.flatten(style)?.opacity
|
|
107
|
+
const cardFade = typeof styleOpacity === 'number' ? { opacity: Animated.multiply(opacity, styleOpacity) } : fade
|
|
108
|
+
const Backdrop = web ? AnimatedPressable : Pressable
|
|
109
|
+
const Card = web ? AnimatedBlurView : BlurView
|
|
110
|
+
const card = (
|
|
111
|
+
<Card blur={blur} style={[styles.card, { borderRadius }, style, web && cardFade]} testID={`${testID}-surface`}>
|
|
112
|
+
{content}
|
|
113
|
+
</Card>
|
|
114
|
+
)
|
|
115
|
+
|
|
96
116
|
return (
|
|
97
117
|
<Portal>
|
|
98
|
-
<Animated.View accessibilityLiveRegion='polite' accessibilityViewIsModal pointerEvents={visible ? 'box-none' : 'none'} style={[StyleSheet.absoluteFill,
|
|
99
|
-
<
|
|
118
|
+
<Animated.View accessibilityLiveRegion='polite' accessibilityViewIsModal pointerEvents={visible ? 'box-none' : 'none'} style={[StyleSheet.absoluteFill, !web && fade]} testID={testID}>
|
|
119
|
+
<Backdrop accessibilityLabel='Close modal' accessibilityRole='button' disabled={!dismissable} onPress={dismissable ? onDismiss : undefined} style={[StyleSheet.absoluteFill, { backgroundColor: colors.backdrop }, web && fade]} testID={`${testID}-backdrop`} />
|
|
100
120
|
<View pointerEvents='box-none' style={[styles.wrapper, { marginBottom: bottom, marginTop: top, paddingHorizontal: Math.max(left, right, DIALOG_MARGIN) }]} testID={`${testID}-wrapper`}>
|
|
101
121
|
{reanimated && animatedStyle ? (
|
|
102
122
|
<reanimated.View style={animatedStyle} testID={`${testID}-animated-wrapper`}>
|
|
103
|
-
|
|
104
|
-
{content}
|
|
105
|
-
</BlurView>
|
|
123
|
+
{card}
|
|
106
124
|
</reanimated.View>
|
|
107
125
|
) : (
|
|
108
|
-
|
|
109
|
-
{content}
|
|
110
|
-
</BlurView>
|
|
126
|
+
card
|
|
111
127
|
)}
|
|
112
128
|
</View>
|
|
113
129
|
</Animated.View>
|
package/src/components/Menu.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { StyleSheet } from 'react-native'
|
|
3
|
-
import { Menu as PaperMenu, type MenuItemProps, type MenuProps as PaperMenuProps } from 'react-native-paper'
|
|
1
|
+
import React, { type ReactNode, useEffect, useState } from 'react'
|
|
2
|
+
import { Animated, Easing, Platform, StyleSheet } from 'react-native'
|
|
3
|
+
import { type MD2Theme, type MD3Theme, Menu as PaperMenu, type MenuItemProps, type MenuProps as PaperMenuProps, useTheme } from 'react-native-paper'
|
|
4
4
|
|
|
5
5
|
import { useBlur } from '../BlurContext'
|
|
6
6
|
import { BlurView } from './BlurView'
|
|
@@ -9,11 +9,61 @@ export type MenuProps = PaperMenuProps & {
|
|
|
9
9
|
blur?: boolean
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
// Mirror react-native-paper's Menu: its fade (ANIMATION_DURATION * theme.animation.scale, eased with
|
|
13
|
+
// EASING), its default elevation, and the MD3 shadow its Surface draws at each elevation level.
|
|
14
|
+
const ANIMATION_DURATION = 250
|
|
15
|
+
const EASING = Easing.bezier(0.4, 0, 0.2, 1)
|
|
16
|
+
const DEFAULT_ELEVATION = 2
|
|
17
|
+
const SHADOW_HEIGHT = [0, 1, 2, 4, 6, 8]
|
|
18
|
+
const SHADOW_RADIUS = [0, 3, 6, 8, 10, 12]
|
|
19
|
+
|
|
20
|
+
const AnimatedBlurView = Animated.createAnimatedComponent(BlurView)
|
|
21
|
+
|
|
22
|
+
type FadingBlurViewProps = {
|
|
23
|
+
blur: boolean
|
|
24
|
+
children: ReactNode
|
|
25
|
+
elevation: number
|
|
26
|
+
theme: PaperMenuProps['theme']
|
|
27
|
+
visible: boolean
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Paper fades the menu's Surface in and out. On web, an ancestor below opacity 1 cuts BlurView's CSS
|
|
31
|
+
// backdrop-filter off from the page behind it, and Chromium doesn't restore the blur once the Surface
|
|
32
|
+
// reaches 1, so the open menu stays see-through until something else repaints it. So on web the Surface
|
|
33
|
+
// is pinned at opacity 1 with its shadow hidden, and BlurView itself (the backdrop-filter element) runs
|
|
34
|
+
// Paper's fades and draws that shadow, so the two still fade together.
|
|
35
|
+
const FadingBlurView = ({ blur, children, elevation, theme: themeOverrides, visible }: FadingBlurViewProps) => {
|
|
36
|
+
const { animation, roundness } = useTheme<MD2Theme | MD3Theme>(themeOverrides)
|
|
37
|
+
const [opacity] = useState(() => new Animated.Value(0))
|
|
38
|
+
// Once Paper starts hiding the menu it unmounts this content when that fade-out ends, even if visible
|
|
39
|
+
// turns back on first, so a close is final here too rather than fading back in only to vanish.
|
|
40
|
+
const [closing, setClosing] = useState(false)
|
|
41
|
+
if (!visible && !closing) setClosing(true)
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
Animated.timing(opacity, { duration: animation.scale * ANIMATION_DURATION, easing: EASING, toValue: closing ? 0 : 1, useNativeDriver: false }).start()
|
|
45
|
+
}, [animation.scale, closing, opacity])
|
|
46
|
+
|
|
47
|
+
const shadow = elevation > 0 ? { shadowColor: '#000000', shadowOffset: { height: SHADOW_HEIGHT[elevation], width: 0 }, shadowOpacity: 0.3, shadowRadius: SHADOW_RADIUS[elevation] } : null
|
|
48
|
+
return (
|
|
49
|
+
<AnimatedBlurView blur={blur} style={[{ borderRadius: roundness, opacity }, shadow]}>
|
|
50
|
+
{children}
|
|
51
|
+
</AnimatedBlurView>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
12
55
|
const MenuComponent = ({ blur: blurProp, children, ...props }: MenuProps) => {
|
|
13
56
|
const blur = useBlur(blurProp)
|
|
57
|
+
const web = Platform.OS === 'web'
|
|
14
58
|
return (
|
|
15
|
-
<PaperMenu {...props} contentStyle={[styles.content, props.contentStyle]}>
|
|
16
|
-
|
|
59
|
+
<PaperMenu {...props} contentStyle={[styles.content, web && styles.webSurface, props.contentStyle]}>
|
|
60
|
+
{web ? (
|
|
61
|
+
<FadingBlurView blur={blur} elevation={props.mode === 'flat' ? 0 : (props.elevation ?? DEFAULT_ELEVATION)} theme={props.theme} visible={props.visible}>
|
|
62
|
+
{children}
|
|
63
|
+
</FadingBlurView>
|
|
64
|
+
) : (
|
|
65
|
+
<BlurView blur={blur}>{children}</BlurView>
|
|
66
|
+
)}
|
|
17
67
|
</PaperMenu>
|
|
18
68
|
)
|
|
19
69
|
}
|
|
@@ -23,5 +73,6 @@ export const Menu = Object.assign(MenuComponent, {
|
|
|
23
73
|
})
|
|
24
74
|
|
|
25
75
|
const styles = StyleSheet.create({
|
|
26
|
-
content: { backgroundColor: 'transparent', paddingVertical: 0 }
|
|
76
|
+
content: { backgroundColor: 'transparent', paddingVertical: 0 },
|
|
77
|
+
webSurface: { opacity: 1, shadowOpacity: 0 }
|
|
27
78
|
})
|