Convert css to a hook useCss

This commit is contained in:
Zoe Roux
2022-11-05 18:58:44 +09:00
parent 5a373c3b7a
commit 3738198ba9
3 changed files with 61 additions and 31 deletions
+1 -4
View File
@@ -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"),
+9 -3
View File
@@ -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 (
<View {...css({ backgroundColor: color }, props)}>
<Text {...css({ color: "white" })}>Text inside the custom black box.</Text>
@@ -17,14 +19,18 @@ const CustomBox = ({ color, ...props }: { color: string }) => {
};
const BoxWithoutProps = (props: object) => {
const css = useCss();
return (
<View {...css({ backgroundColor: { xs: "00ff00", md: "#ff0000"} }, props)}>
<Text>Text inside the box without props</Text>
<View {...css({ backgroundColor: { xs: "#00ff00", md: "#ff0000"} }, props)}>
<Text>Text inside the box without props (green on small screens, red on bigs)</Text>
</View>
);
};
function App() {
const css = useCss();
return (
<View
{...css({
+51 -24
View File
@@ -4,7 +4,7 @@
//
import { ViewStyle, TextStyle, ImageStyle, useWindowDimensions } from "react-native";
import { breakpoints, Breakpoints, YoushikiStyle } from "@yoshiki/core";
import { breakpoints, Breakpoints, Theme, YoushikiStyle } from "@yoshiki/core";
// TODO: shorhands
type EnhancedStyle<Properties> = {
@@ -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 = <T,>(value: unknown): value is Breakpoints<T> => {
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<Property> | ((theme: Theme) => Property),
{ breakpoint, theme }: { breakpoint: number; theme: Theme },
): Property | undefined => {
if (isBreakpoints<Property>(value)) {
const bpKeys = Object.keys(breakpoints) as Array<keyof Breakpoints<Property>>;
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,
};
};
};