UNPKG

react-native-edge-to-edge

Version:

Effortlessly enable edge-to-edge display in React Native

272 lines (261 loc) 8.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SystemBars = SystemBars; var _react = require("react"); var _reactNative = require("react-native"); var _NativeEdgeToEdgeModule = _interopRequireDefault(require("./specs/NativeEdgeToEdgeModule")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function isLightColorScheme() { const colorScheme = _reactNative.Appearance?.getColorScheme() ?? "light"; return colorScheme === "light"; } function resolveSystemBarStyle(style) { switch (style) { case "auto": return isLightColorScheme() ? "dark" : "light"; case "inverted": return isLightColorScheme() ? "light" : "dark"; default: return style; } } function toNativeBarStyle(style) { return style === "light" || style === "dark" ? `${style}-content` : "default"; } /** * Merges the entries stack. */ function mergeEntriesStack(entriesStack) { return entriesStack.reduce((prev, cur) => { for (const prop in cur) { if (cur[prop] != null) { // @ts-expect-error prev[prop] = cur[prop]; } } return prev; }, { statusBarStyle: undefined, navigationBarStyle: undefined, statusBarHidden: undefined, navigationBarHidden: undefined }); } function resolveProps({ hidden, style }) { const compactStyle = typeof style === "string"; const compactHidden = typeof hidden === "boolean"; return { statusBarStyle: compactStyle ? style : style?.statusBar, navigationBarStyle: compactStyle ? style : style?.navigationBar, statusBarHidden: compactHidden ? hidden : hidden?.statusBar, navigationBarHidden: compactHidden ? hidden : hidden?.navigationBar }; } /** * Returns an object to insert in the props stack from the props. */ function createStackEntry(props) { return resolveProps(props); } const entriesStack = []; // Timer for updating the native module values at the end of the frame. let updateImmediate = null; // The current merged values from the entries stack. const currentValues = { statusBarStyle: undefined, navigationBarStyle: undefined, statusBarHidden: undefined, navigationBarHidden: undefined }; function setStatusBarStyle(style) { if (style !== currentValues.statusBarStyle) { currentValues.statusBarStyle = style; const nativeStyle = toNativeBarStyle(style); if (_reactNative.Platform.OS === "android") { _NativeEdgeToEdgeModule.default?.setStatusBarStyle(nativeStyle); } else if (_reactNative.Platform.OS === "ios") { _reactNative.StatusBar.setBarStyle(nativeStyle, true); } } } function setNavigationBarStyle(style) { if (style !== currentValues.navigationBarStyle) { currentValues.navigationBarStyle = style; if (_reactNative.Platform.OS === "android") { const nativeStyle = toNativeBarStyle(style); _NativeEdgeToEdgeModule.default?.setNavigationBarStyle(nativeStyle); } } } function setStatusBarHidden(hidden) { if (hidden !== currentValues.statusBarHidden) { currentValues.statusBarHidden = hidden; if (_reactNative.Platform.OS === "android") { _NativeEdgeToEdgeModule.default?.setStatusBarHidden(hidden); } else if (_reactNative.Platform.OS === "ios") { _reactNative.StatusBar.setHidden(hidden, "fade"); // 'slide' doesn't work in this context } } } function setNavigationBarHidden(hidden) { if (hidden !== currentValues.navigationBarHidden) { currentValues.navigationBarHidden = hidden; if (_reactNative.Platform.OS === "android") { _NativeEdgeToEdgeModule.default?.setNavigationBarHidden(hidden); } } } /** * Updates the native system bars with the entries from the stack. */ function updateEntriesStack() { if (_reactNative.Platform.OS === "android" || _reactNative.Platform.OS === "ios") { if (updateImmediate != null) { clearImmediate(updateImmediate); } updateImmediate = setImmediate(() => { const mergedEntries = mergeEntriesStack(entriesStack); const { statusBarHidden, navigationBarHidden } = mergedEntries; const statusBarStyle = resolveSystemBarStyle(mergedEntries.statusBarStyle); const navigationBarStyle = resolveSystemBarStyle(mergedEntries.navigationBarStyle); setStatusBarStyle(statusBarStyle); setNavigationBarStyle(navigationBarStyle); if (statusBarHidden != null) { setStatusBarHidden(statusBarHidden); } if (navigationBarHidden != null) { setNavigationBarHidden(navigationBarHidden); } }); } } /** * Push a `SystemBars` entry onto the stack. * The return value should be passed to `popStackEntry` when complete. * * @param props Object containing the `SystemBars` props to use in the stack entry. */ function pushStackEntry(props) { const entry = createStackEntry(props); entriesStack.push(entry); updateEntriesStack(); return entry; } /** * Remove an existing `SystemBars` stack entry from the stack. * * @param entry Entry returned from `pushStackEntry`. */ function popStackEntry(entry) { const index = entriesStack.indexOf(entry); if (index !== -1) { entriesStack.splice(index, 1); } updateEntriesStack(); } /** * Replace an existing `SystemBars` stack entry with new props. * * @param entry Entry returned from `pushStackEntry` to replace. * @param props Object containing the `SystemBars` props to use in the replacement stack entry. */ function replaceStackEntry(entry, props) { const newEntry = createStackEntry(props); const index = entriesStack.indexOf(entry); if (index !== -1) { entriesStack[index] = newEntry; } updateEntriesStack(); return newEntry; } /** * Set the system bars style. * * @param style System bars style to set. */ function setStyle(style) { const props = resolveProps({ style }); const statusBarStyle = resolveSystemBarStyle(props.statusBarStyle); const navigationBarStyle = resolveSystemBarStyle(props.navigationBarStyle); if (typeof statusBarStyle === "string") { setStatusBarStyle(statusBarStyle); } if (typeof navigationBarStyle === "string") { setNavigationBarStyle(navigationBarStyle); } } /** * Show or hide the system bars. * * @param hidden Hide the system bars. */ function setHidden(hidden) { const { statusBarHidden, navigationBarHidden } = resolveProps({ hidden }); if (typeof statusBarHidden === "boolean") { setStatusBarHidden(statusBarHidden); } if (typeof navigationBarHidden === "boolean") { setNavigationBarHidden(navigationBarHidden); } } function SystemBars(props) { const { statusBarStyle, navigationBarStyle, statusBarHidden, navigationBarHidden } = resolveProps(props); const stableProps = (0, _react.useMemo)(() => ({ style: statusBarStyle === navigationBarStyle ? statusBarStyle : { statusBar: statusBarStyle, navigationBar: navigationBarStyle }, hidden: statusBarHidden === navigationBarHidden ? statusBarHidden : { statusBar: statusBarHidden, navigationBar: navigationBarHidden } }), [statusBarStyle, navigationBarStyle, statusBarHidden, navigationBarHidden]); const colorScheme = (0, _reactNative.useColorScheme)(); const stackEntryRef = (0, _react.useRef)(null); (0, _react.useEffect)(() => { // Every time a SystemBars component is mounted, we push it's prop to a stack // and always update the native system bars with the props from the top of then // stack. This allows having multiple SystemBars components and the one that is // added last or is deeper in the view hierarchy will have priority. stackEntryRef.current = pushStackEntry(stableProps); return () => { // When a SystemBars is unmounted, remove itself from the stack and update // the native bars with the next props. if (stackEntryRef.current) { popStackEntry(stackEntryRef.current); } }; }, []); (0, _react.useEffect)(() => { if (stackEntryRef.current) { stackEntryRef.current = replaceStackEntry(stackEntryRef.current, stableProps); } }, [colorScheme, stableProps]); return null; } SystemBars.pushStackEntry = pushStackEntry; SystemBars.popStackEntry = popStackEntry; SystemBars.replaceStackEntry = replaceStackEntry; SystemBars.setStyle = setStyle; SystemBars.setHidden = setHidden; //# sourceMappingURL=SystemBars.js.map