Handling strings keys to css

This commit is contained in:
Zoe Roux
2023-01-09 18:10:49 +09:00
parent c67d964d74
commit 0fcc2cbfe3
4 changed files with 66 additions and 22 deletions

View File

@@ -16,7 +16,7 @@ const Box = ({ children, ...props }: { children?: ReactNode } & Stylable) => {
);
};
export default function Home(props: object) {
export default function Home(props: Stylable) {
const { css } = useYoshiki();
return (
@@ -27,6 +27,7 @@ export default function Home(props: object) {
display: "flex",
paddingLeft: "2rem",
paddingRight: "2rem",
paddingTop: (theme) => theme.background,
bg: (theme) => theme.background,
},
md({
@@ -58,19 +59,31 @@ export default function Home(props: object) {
<div
{...css({
backgroundColor: "green",
hover: {
backgroundColor: "blue",
},
press: {
backgroundColor: "red",
self: {
bg: "red",
},
text: {
color: "white",
},
},
hover: {
text: {
color: "blue",
},
},
focus: {
backgroundColor: "yellow",
self: {
bg: "yellow",
},
text: {
color: "green",
},
},
})}
tabIndex={0}
>
<a href="https://nextjs.org/docs">
<a href="https://nextjs.org/docs" {...css([{ color: "red" }, "text"])}>
<h2>Documentation &rarr;</h2>
<p>Find in-depth information about Next.js features and API.</p>
</a>
@@ -89,7 +102,7 @@ export default function Home(props: object) {
<div
{...css({
hover: {
background: { xs: "red", sm: "blue", md: "green" },
self: { background: { xs: "red", sm: "blue", md: "green" } },
},
})}
>

View File

@@ -5,11 +5,11 @@
import { useInsertionEffect } from "react";
import { RegisteredStyle } from "react-native";
import { useTheme } from "../theme";
import { processStyleList, StyleList } from "../type";
import { processStyleList, processStyleListWithoutChild, 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 { useClassId, yoshikiCssToClassNames } from "../web/generator";
import { useStyleRegistry } from "../web";
const rnwPreprocess = (block: Record<string, unknown>) => {
@@ -19,25 +19,30 @@ const rnwPreprocess = (block: Record<string, unknown>) => {
export const useYoshiki = () => {
const registry = useStyleRegistry();
const theme = useTheme();
const childPrefix = useClassId();
useInsertionEffect(() => {
registry.flushToBrowser();
}, [registry]);
const css: NativeCssFunc = (cssList, leftOvers) => {
const css = processStyleList(cssList);
const [css, parentKeys] = processStyleListWithoutChild(cssList);
const getStyle = (
inlineList: StyleList<{ $$css?: true; yoshiki?: string } | RegisteredStyle<unknown>>,
) => {
const inline = processStyleList(inlineList);
const overrides = "$$css" in inline && inline.$$css ? inline.yoshiki : undefined;
const classNames = yoshikiCssToClassNames(css, overrides?.split(" "), {
registry,
theme,
preprocessBlock: rnwPreprocess,
preprocess
});
const classNames = yoshikiCssToClassNames(
css,
[...parentKeys.map((x) => `${childPrefix}${x}`), ...(overrides?.split(" ") ?? [])],
{
registry,
theme,
preprocessBlock: rnwPreprocess,
preprocess,
},
);
// We use the inlineList and not the inline we have locally since $$css and inlines are not mergable.
return [inlineList, { $$css: true, yoshiki: classNames }];
};

View File

@@ -33,6 +33,23 @@ export const processStyleList = <Style>(los: StyleList<Style>): Partial<Style> =
if (isReadonlyArray(los)) return los.reduce((acc, x) => ({ ...acc, ...processStyleList(x) }), {});
return los ? los : {};
};
export const processStyleListWithoutChild = <Style>(
los: StyleList<Style | string>,
): [Partial<Style>, string[]] => {
if (isReadonlyArray(los))
return los.reduce(
(acc, x) => {
if (typeof x === "string") return [acc[0], [...acc[1], x]];
const rest = processStyleListWithoutChild(x);
return [{ ...acc[0], ...rest[0] }, [...acc[1], ...rest[1]]];
},
[{}, []] as [Partial<Style>, string[]],
);
if (!los) return [{}, []];
return typeof los === "string" ? [{}, [los]] : [los, []];
};
export const processStyleListWithChild = <Style>(
los: StyleList<Style | string>,
parent: Record<string, Style>,

View File

@@ -3,11 +3,11 @@
// Licensed under the MIT license. See LICENSE file in the project root for details.
//
import { useInsertionEffect } from "react";
import { useId, useInsertionEffect } from "react";
import { prefix } from "inline-style-prefixer";
import { Properties as CssProperties } from "csstype";
import { Theme, breakpoints, useTheme } from "../theme";
import { WithState, YoshikiStyle, StyleList, processStyleList } from "../type";
import { WithState, YoshikiStyle, StyleList, processStyleListWithoutChild } from "../type";
import { forceBreakpoint, isBreakpoints } from "../utils";
import { StyleRegistry, useStyleRegistry } from "./registry";
import { shorthandsFn } from "../shorthands";
@@ -189,9 +189,14 @@ export const yoshikiCssToClassNames = (
);
};
export const useClassId = () => {
return "ysc" + useId().replaceAll(":", "-");
};
export const useYoshiki = () => {
const theme = useTheme();
const registry = useStyleRegistry();
const childPrefix = useClassId();
useInsertionEffect(() => {
registry.flushToBrowser();
@@ -199,13 +204,17 @@ export const useYoshiki = () => {
return {
css: <Leftover>(
cssList: StyleList<CssObject>,
cssList: StyleList<CssObject | string>,
leftOverProps?: Leftover & { className?: string },
): { className: string } & Omit<Leftover, "className"> => {
const css = processStyleList(cssList);
const [css, parentKeys] = processStyleListWithoutChild(cssList);
const { className, ...leftOver } = leftOverProps ?? {};
return {
className: yoshikiCssToClassNames(css, className?.split(" "), { registry, theme }),
className: yoshikiCssToClassNames(
css,
[...parentKeys.map((x) => `${childPrefix}${x}`), ...(className?.split(" ") ?? [])],
{ registry, theme },
),
...leftOver,
} as any;
},