From 8b566c4f345910ea5ac8c5e1018b09ea05e42139 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 1 Dec 2022 14:21:23 +0900 Subject: [PATCH] Add support of RN shadow props --- examples/expo-example/src/app.tsx | 3 ++ packages/yoshiki/package.json | 2 +- packages/yoshiki/src/native/generator.web.ts | 2 + packages/yoshiki/src/native/rnw-internal.d.ts | 7 ++++ packages/yoshiki/src/web/generator.ts | 37 ++++++++----------- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/examples/expo-example/src/app.tsx b/examples/expo-example/src/app.tsx index bc6ae91..db0fdaa 100644 --- a/examples/expo-example/src/app.tsx +++ b/examples/expo-example/src/app.tsx @@ -32,6 +32,9 @@ const BoxWithoutProps = (props: Stylable) => { hover: { alignContent: "center", alignItems: "center" }, press: { alignContent: "center" }, focus: { alignContent: "center" }, + shadowOpacity: 0.5, + shadowRadius: 2, + shadowOffset: { width: 3, height: 3 }, }, props, )} diff --git a/packages/yoshiki/package.json b/packages/yoshiki/package.json index 0878477..f3e341a 100644 --- a/packages/yoshiki/package.json +++ b/packages/yoshiki/package.json @@ -1,6 +1,6 @@ { "name": "yoshiki", - "version": "0.2.6", + "version": "0.2.7", "author": "Zoe Roux (https://github.com/AnonymusRaccoon)", "license": "MIT", "keywords": [ diff --git a/packages/yoshiki/src/native/generator.web.ts b/packages/yoshiki/src/native/generator.web.ts index dd8d874..4cfc54b 100644 --- a/packages/yoshiki/src/native/generator.web.ts +++ b/packages/yoshiki/src/native/generator.web.ts @@ -8,6 +8,7 @@ import { useTheme } from "../theme"; import { processStyleList, StyleList } from "../type"; import { NativeCssFunc } from "./type"; import createReactDOMStyle from "react-native-web/dist/exports/StyleSheet/compiler/createReactDOMStyle"; +import preprocess from "react-native-web/dist/exports/StyleSheet/preprocess"; import { yoshikiCssToClassNames } from "../web/generator"; import { useStyleRegistry } from "../web"; @@ -35,6 +36,7 @@ export const useYoshiki = () => { registry, theme, preprocessBlock: rnwPreprocess, + preprocess }); return [inline, { $$css: true, yoshiki: classNames }]; }; diff --git a/packages/yoshiki/src/native/rnw-internal.d.ts b/packages/yoshiki/src/native/rnw-internal.d.ts index ab23492..8bd74da 100644 --- a/packages/yoshiki/src/native/rnw-internal.d.ts +++ b/packages/yoshiki/src/native/rnw-internal.d.ts @@ -10,3 +10,10 @@ declare module "react-native-web/dist/exports/StyleSheet/compiler/createReactDOM ) => Record; export default createReactDOMStyle; } + +declare module "react-native-web/dist/exports/StyleSheet/preprocess" { + const preprocess: ( + style: Record, + ) => Record; + export default createReactDOMStyle; +} diff --git a/packages/yoshiki/src/web/generator.ts b/packages/yoshiki/src/web/generator.ts index 61034eb..774f41f 100644 --- a/packages/yoshiki/src/web/generator.ts +++ b/packages/yoshiki/src/web/generator.ts @@ -37,7 +37,6 @@ const sanitize = (className: unknown) => { return name.replaceAll(/[^\w-_]/g, ""); }; -type PreprocessFunction = (key: string, value: unknown) => [key: string, value: unknown][]; type PreprocessBlockFunction = (block: { [key: string]: unknown }) => { [key: string]: unknown }; const generateClass = ( @@ -45,17 +44,8 @@ const generateClass = ( value: unknown, context: string, addCssContext: (className: string, block: string) => string, - { - preprocess, - preprocessBlock, - }: { preprocess?: PreprocessFunction; preprocessBlock?: PreprocessBlockFunction }, + preprocessBlock?: PreprocessBlockFunction, ): [string, string][] => { - if (preprocess) { - return preprocess(key, value).flatMap(([nKey, nValue]) => - generateClass(nKey, nValue, context, addCssContext, { preprocessBlock }), - ); - } - if (value === undefined) return []; preprocessBlock ??= (id) => id; @@ -77,20 +67,16 @@ const generateAtomicCss = ( state: keyof WithState | "normal", { theme, - preprocess, preprocessBlock, }: { theme: Theme; - preprocess?: PreprocessFunction; preprocessBlock?: PreprocessBlockFunction; }, ): [string, string][] => { if (key in shorthandsFn) { const expanded = shorthandsFn[key as keyof typeof shorthandsFn](value as any); return Object.entries(expanded) - .map(([eKey, eValue]) => - generateAtomicCss(eKey, eValue, state, { theme, preprocess, preprocessBlock }), - ) + .map(([eKey, eValue]) => generateAtomicCss(eKey, eValue, state, { theme, preprocessBlock })) .flat(); } if (typeof value === "function") { @@ -108,7 +94,7 @@ const generateAtomicCss = ( const bpWidth = breakpoints[bp as keyof typeof breakpoints]; return `@media (min-width: ${bpWidth}px) { ${stateMapper[state](className)} ${block} }`; }, - { preprocess, preprocessBlock }, + preprocessBlock, ); }); } @@ -118,7 +104,7 @@ const generateAtomicCss = ( value, statePrefix, (className, block) => `${stateMapper[state](className)} ${block}`, - { preprocess, preprocessBlock }, + preprocessBlock, ); }; @@ -138,7 +124,11 @@ const dedupProperties = (...classList: (string[] | undefined)[]) => { }; export const yoshikiCssToClassNames = ( - css: Record, + css: Record & { + hover?: Record; + focus?: Record; + press?: Record; + }, classNames: string[] | undefined, { registry, @@ -148,21 +138,24 @@ export const yoshikiCssToClassNames = ( }: { registry: StyleRegistry; theme: Theme; - preprocess?: PreprocessFunction; + preprocess?: (style: Record) => Record; preprocessBlock?: PreprocessBlockFunction; }, ) => { const { hover, focus, press, ...inline } = css; - const processStyles = (inlineStyle?: unknown, state?: keyof WithState): string[] => { + const processStyles = ( + inlineStyle?: Record, + state?: keyof WithState, + ): string[] => { if (!inlineStyle) return []; + if (preprocess) inlineStyle = preprocess(inlineStyle); // I'm sad that traverse is not a thing in JS. const [localClassNames, localStyle] = Object.entries(inlineStyle).reduce<[string[], string[]]>( (acc, [key, value]) => { const n = generateAtomicCss(key, value, state ?? "normal", { theme, - preprocess, preprocessBlock, }); acc[0].push(...n.map((x) => x[0]));