From 3738198ba97250f7e48a3830aae9e71dafe08b6a Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 5 Nov 2022 18:58:44 +0900 Subject: [PATCH] Convert css to a hook useCss --- examples/expo-example/metro.config.js | 5 +- examples/expo-example/src/app.tsx | 12 +++-- packages/native/src/index.tsx | 75 ++++++++++++++++++--------- 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/examples/expo-example/metro.config.js b/examples/expo-example/metro.config.js index ad0672d..f79958b 100644 --- a/examples/expo-example/metro.config.js +++ b/examples/expo-example/metro.config.js @@ -14,10 +14,7 @@ const workspaceRoot = path.resolve(projectRoot, "../.."); const config = getDefaultConfig(projectRoot); // 1. Watch all files within the monorepo -config.watchFolders = [ - path.resolve(workspaceRoot, "examples/expo-example"), - path.resolve(workspaceRoot, "packages"), -]; +config.watchFolders = [workspaceRoot]; // 2. Let Metro know where to resolve packages and in what order config.resolver.nodeModulesPaths = [ path.resolve(projectRoot, "node_modules"), diff --git a/examples/expo-example/src/app.tsx b/examples/expo-example/src/app.tsx index 511a73d..08253d6 100644 --- a/examples/expo-example/src/app.tsx +++ b/examples/expo-example/src/app.tsx @@ -6,9 +6,11 @@ import { StatusBar } from "expo-status-bar"; import { Text, View } from "react-native"; import { registerRootComponent } from "expo"; -import { css } from "@yoshiki/native"; +import { useCss } from "@yoshiki/native"; const CustomBox = ({ color, ...props }: { color: string }) => { + const css = useCss(); + return ( Text inside the custom black box. @@ -17,14 +19,18 @@ const CustomBox = ({ color, ...props }: { color: string }) => { }; const BoxWithoutProps = (props: object) => { + const css = useCss(); + return ( - - Text inside the box without props + + Text inside the box without props (green on small screens, red on bigs) ); }; function App() { + const css = useCss(); + return ( = { @@ -23,31 +23,58 @@ const useBreakpoint = (): number => { return idx - 1; }; -export const css = (css: CssObject, leftOvers?: { style?: Properties }) => { - const { style, ...leftOverProps } = leftOvers ?? {}; +export const useTheme = () => { + return {} as Theme; +}; - let breakpoint: number | undefined = undefined; - const ret: Properties = Object.fromEntries( - Object.entries(css) - .map(([key, value]) => { - if (typeof value === "object") { - if (!breakpoint) breakpoint = useBreakpoint(); +const isBreakpoints = (value: unknown): value is Breakpoints => { + if (typeof value !== "object" || !value) return false; + for (const v of Object.keys(value)) { + if (!(v in breakpoints)) { + return false; + } + } + return true; +}; - const bpKeys = Object.keys(breakpoints); - for (let i = breakpoint; i >= 0; i--) { - if (bpKeys[i] in value) { - return [key, value[bpKeys[i]]]; - } - } - return undefined; - } - return [key, value]; - }) - .filter((x) => x !== undefined), - ); +const propertyMapper = < + Property extends number | string | boolean | undefined | Property[] | object, +>( + value: Property | Breakpoints | ((theme: Theme) => Property), + { breakpoint, theme }: { breakpoint: number; theme: Theme }, +): Property | undefined => { + if (isBreakpoints(value)) { + const bpKeys = Object.keys(breakpoints) as Array>; + for (let i = breakpoint; i >= 0; i--) { + if (bpKeys[i] in value) { + return value[bpKeys[i]]; + } + } + return undefined; + } + if (typeof value === "function") { + return value(theme); + } + return value; +}; - return { - style: { ...ret, ...style }, - ...leftOverProps, +// TODO: do not use a hook and use a global window width. +export const useCss = () => { + const breakpoint = useBreakpoint(); + const theme = useTheme(); + + return (css: CssObject, leftOvers?: { style?: Properties }) => { + const { style, ...leftOverProps } = leftOvers ?? {}; + + const ret: Properties = Object.fromEntries( + Object.entries(css) + .map(([key, value]) => [key, propertyMapper(value, { breakpoint, theme })]) + .filter(([, value]) => value !== undefined), + ); + + return { + style: { ...ret, ...style }, + ...leftOverProps, + }; }; };