diff --git a/examples/expo-example/app.json b/examples/expo-example/app.json index 2be12af..fdcf381 100644 --- a/examples/expo-example/app.json +++ b/examples/expo-example/app.json @@ -3,7 +3,7 @@ "name": "expo-example", "slug": "expo-example", "version": "1.0.0", - "orientation": "portrait", + "orientation": "default", "icon": "./assets/icon.png", "entryPoint": "./src/app.tsx", "userInterfaceStyle": "light", diff --git a/examples/expo-example/src/app.tsx b/examples/expo-example/src/app.tsx index 2317e7d..c7a8d9f 100644 --- a/examples/expo-example/src/app.tsx +++ b/examples/expo-example/src/app.tsx @@ -31,9 +31,28 @@ const BoxWithoutProps = (props: Stylable) => { { backgroundColor: { xs: "#00ff00", md: "#ff0000" }, transform: [{ scaleY: 0.7 }], - hover: { alignContent: "center", alignItems: "center" }, - press: { alignContent: "center" }, - focus: { alignContent: "center" }, + press: { + self: { + bg: "red", + }, + text: { + color: "white", + }, + }, + hover: { + text: { + color: "blue", + }, + }, + focus: { + self: { + bg: "yellow" + }, + text: { + transform: [{ scale: 2 }], + color: "green" + }, + }, }, md({ shadowOpacity: 0.5, @@ -45,9 +64,12 @@ const BoxWithoutProps = (props: Stylable) => { )} >

Text inside the box without props (green on small screens, red on bigs)

@@ -85,12 +107,14 @@ function App() { Open up App.tsx to start working on your app! -

- Test -

+ +

+ Test +

+
); diff --git a/packages/yoshiki/src/native/generator.tsx b/packages/yoshiki/src/native/generator.tsx index 99c6763..4177f9a 100644 --- a/packages/yoshiki/src/native/generator.tsx +++ b/packages/yoshiki/src/native/generator.tsx @@ -3,12 +3,20 @@ // Licensed under the MIT license. See LICENSE file in the project root for details. // -import { useWindowDimensions } from "react-native"; +import { PressableProps, useWindowDimensions, ViewStyle } from "react-native"; import { breakpoints, Theme, useTheme } from "../theme"; -import { Breakpoints, YoshikiStyle, hasState, processStyleList } from "../type"; +import { + Breakpoints, + YoshikiStyle, + hasState, + processStyleList, + processStyleListWithChild, + assignChilds, +} from "../type"; import { isBreakpoints } from "../utils"; import { shorthandsFn } from "../shorthands"; -import { StyleFunc, NativeCssFunc } from "./type"; +import { StyleFunc, NativeCssFunc, NativeStyle } from "./type"; +import { useReducer, useRef, useState } from "react"; const useBreakpoint = (): number => { const { width } = useWindowDimensions(); @@ -46,12 +54,19 @@ const propertyMapper = ( return [[key, value]]; }; +const useForceRerender = () => { + return useReducer((x) => x + 1, 0)[1]; +}; + export const useYoshiki = () => { const breakpoint = useBreakpoint(); const theme = useTheme(); + const rerender = useForceRerender(); + const childStyles = useRef>({}); const css: NativeCssFunc = (cssList, leftOvers) => { - const css = processStyleList(cssList); + // The as any is because we can't be sure the style type is right one. + const css = processStyleListWithChild(cssList, childStyles.current as any); const processStyle = (styleList: Record>) => { const ret = Object.fromEntries( @@ -62,35 +77,63 @@ export const useYoshiki = () => { return ret; }; - if (hasState>(css)) { + if (hasState>(css)) { const { hover, focus, press, ...inline } = css; - const ret: StyleFunc = ({ hovered, focused, pressed }) => ({ - ...processStyle(inline), - ...(hovered ? processStyle(hover ?? {}) : {}), - ...(focused ? processStyle(focus ?? {}) : {}), - ...(pressed ? processStyle(press ?? {}) : {}), - ...(leftOvers?.style - ? typeof leftOvers?.style === "function" - ? processStyleList(leftOvers?.style({ hovered, focused, pressed })) - : processStyleList(leftOvers?.style) - : {}), - }); + const { onPressIn, onPressOut, onHoverIn, onHoverOut, onFocus, onBlur } = + leftOvers as PressableProps; + const ret: StyleFunc = ({ hovered, focused, pressed }) => { + childStyles.current = {}; + if (hovered) assignChilds(childStyles.current, hover); + if (focused) assignChilds(childStyles.current, focus); + if (pressed) assignChilds(childStyles.current, press); + + return [ + processStyle(inline), + hovered && processStyle(hover?.self ?? {}), + focused && processStyle(focus?.self ?? {}), + pressed && processStyle(press?.self ?? {}), + leftOvers?.style && + (typeof leftOvers?.style === "function" + ? processStyleList(leftOvers?.style({ hovered, focused, pressed })) + : leftOvers?.style), + ]; + }; return { ...leftOvers, - style: ret, - }; + style: ret as StyleFunc, + // We must use a setTimeout since the child styles are computed inside the style function (called after onIn/onOut) + // NOTE: The props onIn/onOut are overriden here and the user can't use them. Might want to find a way arround that. + onPressIn: (e) => { + onPressIn?.call(null, e); + setTimeout(rerender); + }, + onPressOut: (e) => { + onPressOut?.call(null, e); + setTimeout(rerender); + }, + onHoverIn: (e) => { + onHoverIn?.call(null, e); + setTimeout(rerender); + }, + onHoverOut: (e) => { + onHoverOut?.call(null, e); + setTimeout(rerender); + }, + onFocus: (e) => { + onFocus?.call(null, e); + setTimeout(rerender); + }, + onBlur: (e) => { + onBlur?.call(null, e); + setTimeout(rerender); + }, + } satisfies PressableProps; } else { - const loStyles = - leftOvers?.style && typeof leftOvers?.style !== "function" - ? processStyleList(leftOvers.style) - : {}; - const ret = { + return { ...leftOvers, - style: { ...processStyle(css), ...loStyles }, - }; - - return ret as any; + style: [processStyle(css), leftOvers?.style], + } as any; } }; diff --git a/packages/yoshiki/src/native/type.ts b/packages/yoshiki/src/native/type.ts index 514ef9f..5493e90 100644 --- a/packages/yoshiki/src/native/type.ts +++ b/packages/yoshiki/src/native/type.ts @@ -5,7 +5,7 @@ import { WithState, YoshikiStyle, StyleList } from "../type"; import { shorthandsFn } from "../shorthands"; -import { ImageStyle, StyleProp, TextStyle, ViewStyle } from "react-native"; +import { ImageStyle, PressableProps, StyleProp, TextStyle, ViewStyle } from "react-native"; import { Theme } from "../theme"; import { forceBreakpoint } from "../utils"; @@ -42,33 +42,18 @@ export type StyleFunc