From 2b3ede7a603df4bef2e5925d36eed7037c49c496 Mon Sep 17 00:00:00 2001 From: Jacek Pudysz Date: Tue, 7 Nov 2023 13:29:46 +0100 Subject: [PATCH] feat: implement orientations for mobile, add demo --- examples/expo/src/App.tsx | 1 + examples/expo/src/common/navigation.ts | 2 + examples/expo/src/examples/HomeScreen.tsx | 4 + .../src/examples/OrientationBreakpoints.tsx | 77 +++++++++++++++++++ examples/expo/src/examples/index.ts | 1 + src/global.ts | 3 +- src/utils/breakpoints.ts | 20 ++++- src/utils/common.ts | 6 ++ src/utils/index.ts | 2 +- 9 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 examples/expo/src/examples/OrientationBreakpoints.tsx diff --git a/examples/expo/src/App.tsx b/examples/expo/src/App.tsx index 0e7e89fc..f6d613f6 100644 --- a/examples/expo/src/App.tsx +++ b/examples/expo/src/App.tsx @@ -26,6 +26,7 @@ export const App: React.FunctionComponent = () => ( + diff --git a/examples/expo/src/common/navigation.ts b/examples/expo/src/common/navigation.ts index f128a76e..502d355b 100644 --- a/examples/expo/src/common/navigation.ts +++ b/examples/expo/src/common/navigation.ts @@ -11,6 +11,7 @@ export enum DemoNames { NoBreakpoints = 'NoBreakpoints', WithBreakpoints = 'WithBreakpoints', MediaQueriesWidthHeight = 'MediaQueriesWidthHeight', + OrientationBreakpoints = 'OrientationBreakpoints' } export type DemoStackParams = { @@ -24,6 +25,7 @@ export type DemoStackParams = { [DemoNames.NoBreakpoints]: undefined, [DemoNames.WithBreakpoints]: undefined, [DemoNames.MediaQueriesWidthHeight]: undefined, + [DemoNames.OrientationBreakpoints]: undefined } export type NavigationProps = NavigationProp diff --git a/examples/expo/src/examples/HomeScreen.tsx b/examples/expo/src/examples/HomeScreen.tsx index 56282c56..5915de51 100644 --- a/examples/expo/src/examples/HomeScreen.tsx +++ b/examples/expo/src/examples/HomeScreen.tsx @@ -64,6 +64,10 @@ export const HomeScreen = () => { description="With breakpoints" onPress={() => navigation.navigate(DemoNames.WithBreakpoints)} /> + navigation.navigate(DemoNames.OrientationBreakpoints)} + /> { + useLazyRegistryForDemo(() => { + UnistylesRegistry + .addThemes({ + light: lightTheme, + dark: darkTheme, + premium: premiumTheme + }) + .addConfig({ + adaptiveThemes: true + }) + }) + + const { styles } = useStyles(stylesheet) + + return ( + + + + This demo has no registered breakpoints. On mobile Unistyles will provide you two breakpoints: + + + landscape and portrait + + + The current orientation is: {UnistylesRuntime.orientation === ScreenOrientation.Portrait ? 'portrait' : 'landscape'} + + + You should see circles on portrait and rectangles on landscape + + + {Array.from(new Array(10)).map((_, index) => ( + + ))} + + + + ) +} + +const stylesheet = createStyleSheet(theme => ({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + paddingHorizontal: 20, + backgroundColor: theme.colors.backgroundColor, + rowGap: 20 + }, + text: { + textAlign: 'center', + color: theme.colors.typography + }, + objectContainer: { + flexDirection: 'row', + columnGap: 10 + }, + object: { + width: 40, + height: 40, + backgroundColor: theme.colors.accent, + borderRadius: { + portrait: undefined, + landscape: 20 + } + } +})) diff --git a/examples/expo/src/examples/index.ts b/examples/expo/src/examples/index.ts index 1a398215..11e18841 100644 --- a/examples/expo/src/examples/index.ts +++ b/examples/expo/src/examples/index.ts @@ -7,4 +7,5 @@ export { MultipleThemesScreen } from './MultipleThemesScreen' export { MultipleThemesAdaptiveScreen } from './MultipleThemesAdaptiveScreen' export { NoBreakpointsScreen } from './NoBreakpointsScreen' export { WithBreakpointsScreen } from './WithBreakpointsScreen' +export { OrientationBreakpoints } from './OrientationBreakpoints' export { MediaQueriesWidthHeight } from './MediaQueriesWidthHeight' diff --git a/src/global.ts b/src/global.ts index d5307ddd..d90905fd 100644 --- a/src/global.ts +++ b/src/global.ts @@ -1,4 +1,5 @@ export interface UnistylesThemes {} export interface UnistylesBreakpoints { - default?: 0 + landscape?: number, + portrait?: number, } diff --git a/src/utils/breakpoints.ts b/src/utils/breakpoints.ts index e734e02e..616dc443 100644 --- a/src/utils/breakpoints.ts +++ b/src/utils/breakpoints.ts @@ -1,6 +1,7 @@ import { unistyles } from '../Unistyles' -import { throwError } from './common' +import { isMobile, Orientation, throwError } from './common' import type { ScreenSize, MediaQueries } from '../types' +import { ScreenOrientation } from '../types' import { getKeyForCustomMediaQuery, isMediaQuery } from './mediaQueries' import type { UnistylesBreakpoints } from '../global' @@ -118,7 +119,20 @@ export const getValueForBreakpoint = ( return value[customMediaQueryKey] } - // if no custom media query, or didn't match, proceed with defined breakpoints + // at this point user didn't use custom media queries (:w, :h) + // check if user defined any breakpoints + const hasBreakpoints = unistyles.runtime.sortedBreakpoints.length > 0 + + // if not then we can fallback to horizontal and portrait (mobile only) + if (!hasBreakpoints && isMobile && (Orientation.Landscape in value || Orientation.Portrait in value)) { + return value[ + unistyles.runtime.orientation === ScreenOrientation.Portrait + ? Orientation.Portrait + : Orientation.Landscape + ] + } + + // if user defined breakpoints, then we look for the valid one const unifiedKey = breakpoint?.toLowerCase() as keyof typeof value const directBreakpoint = value[unifiedKey] @@ -127,7 +141,7 @@ export const getValueForBreakpoint = ( return directBreakpoint } - // there is no direct hit for breakpoint nor media-query, so let's simulate CSS cascading + // there is no direct hit for breakpoint nor media-query, let's simulate CSS cascading const breakpointPairs = unistyles.runtime.sortedBreakpoints const currentBreakpoint = breakpointPairs .findIndex(([key]) => key === unifiedKey) diff --git a/src/utils/common.ts b/src/utils/common.ts index f908a549..2167bded 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -8,5 +8,11 @@ export const warn = (message: string) => { console.warn(`🦄 [react-native-unistyles]: ${message}`) } +export const isMobile = Platform.OS === 'android' || Platform.OS === 'ios' export const isWeb = Platform.OS === 'web' export const isServer = typeof window === 'undefined' + +export const Orientation = { + Landscape: 'landscape', + Portrait: 'portrait' +} as const diff --git a/src/utils/index.ts b/src/utils/index.ts index abd69664..e034474c 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,7 +2,7 @@ export { normalizeStyles } from './normalizeStyles' export * from './normalizer' export { getBreakpointFromScreenWidth, sortAndValidateBreakpoints, getValueForBreakpoint } from './breakpoints' export { proxifyFunction, parseStyle } from './styles' -export { isServer } from './common' +export { isServer, Orientation } from './common' export { extractValues, getKeyForCustomMediaQuery,