mirror of
https://github.com/zoriya/yoshiki.git
synced 2026-06-06 03:45:29 +00:00
Add a merged style to check types of react and native at the same time
This commit is contained in:
@@ -12,7 +12,7 @@ const CustomBox = ({ color, ...props }: { color: string } & Stylable) => {
|
||||
const { css } = useYoshiki();
|
||||
|
||||
return (
|
||||
<View {...css({ bg: color, p: "13px", alignItems: "center" }, props)}>
|
||||
<View {...css({ bg: color, alignItems: "center" }, props)}>
|
||||
<Text {...css({ color: "white" })}>Text inside the custom black box.</Text>
|
||||
</View>
|
||||
);
|
||||
@@ -26,7 +26,7 @@ const BoxWithoutProps = (props: Stylable) => {
|
||||
{...css(
|
||||
{
|
||||
backgroundColor: { xs: "#00ff00", md: "#ff0000" },
|
||||
hover: { alignContent: "center" },
|
||||
hover: { alignContent: "center", alignItems: "center" },
|
||||
press: { alignContent: "center" },
|
||||
focus: { alignContent: "center" },
|
||||
},
|
||||
@@ -34,13 +34,9 @@ const BoxWithoutProps = (props: Stylable) => {
|
||||
)}
|
||||
>
|
||||
<Text
|
||||
{...css(
|
||||
{
|
||||
backgroundColor: { xs: "#00ff00", md: "#ff0000" },
|
||||
hover: { alignContent: "center" },
|
||||
},
|
||||
props,
|
||||
)}
|
||||
{...css({
|
||||
backgroundColor: { xs: "#00ff00", md: "#ff0000" },
|
||||
})}
|
||||
>
|
||||
Text inside the box without props (green on small screens, red on bigs)
|
||||
</Text>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for details.
|
||||
//
|
||||
|
||||
import { Theme, ThemeProvider, useYoshiki } from "yoshiki";
|
||||
import { Theme, ThemeProvider } from "yoshiki";
|
||||
import { useYoshiki, useMobileHover } from "yoshiki/web";
|
||||
import { AppProps } from "next/app";
|
||||
import { useMobileHover } from "yoshiki";
|
||||
|
||||
declare module "yoshiki" {
|
||||
export interface Theme {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for details.
|
||||
//
|
||||
|
||||
import { StyleRegistryProvider, createStyleRegistry } from "yoshiki";
|
||||
import { StyleRegistryProvider, createStyleRegistry } from "yoshiki/web";
|
||||
import Document, { DocumentContext } from "next/document";
|
||||
|
||||
Document.getInitialProps = async (ctx: DocumentContext) => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import Head from "next/head";
|
||||
import Image from "next/image";
|
||||
import { useYoshiki, Stylable } from "yoshiki";
|
||||
import { useYoshiki, Stylable } from "yoshiki/web";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
const Box = ({ children, ...props }: { children?: ReactNode } & Stylable) => {
|
||||
|
||||
@@ -3,14 +3,38 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for details.
|
||||
//
|
||||
|
||||
export { type Theme, breakpoints, useTheme, ThemeProvider } from "./theme";
|
||||
import {
|
||||
useYoshiki as useWebYoshiki,
|
||||
type Stylable as WebStylable,
|
||||
type StylableHoverable as WebStylableHoverable,
|
||||
} from "./web";
|
||||
import type {
|
||||
Stylable as NativeStylable,
|
||||
StylableHoverable as NativeStylableHoverable,
|
||||
} from "./native";
|
||||
|
||||
export {
|
||||
useYoshiki,
|
||||
useStyleRegistry,
|
||||
StyleRegistryProvider,
|
||||
createStyleRegistry,
|
||||
type Stylable,
|
||||
useMobileHover,
|
||||
Pressable
|
||||
} from "./react";
|
||||
import { YsStyleProps } from "./native/generator";
|
||||
import { Theme } from "./theme";
|
||||
import { WithState, EnhancedStyle } from "./type";
|
||||
import type { ViewStyle, ImageStyle, TextStyle } from "react-native";
|
||||
|
||||
export const useYoshiki = (): {
|
||||
css: <
|
||||
Style extends ViewStyle | TextStyle | ImageStyle,
|
||||
State extends Partial<WithState<EnhancedStyle<Style>>> | Record<string, never>,
|
||||
>(
|
||||
style: EnhancedStyle<Style> & State,
|
||||
leftOvers?: { style?: Style } | WebStylable,
|
||||
) => YsStyleProps<Style, State> | WebStylable;
|
||||
theme: Theme;
|
||||
} => {
|
||||
// This index.ts will be used on the web wherase react-native will use the ./native import.
|
||||
// We need to unsure that this functions works on the web but have types that merge the two here.
|
||||
// @ts-ignore See comment above.
|
||||
return useWebYoshiki();
|
||||
};
|
||||
|
||||
export type Stylable = WebStylable | NativeStylable;
|
||||
export type StylableHoverable = WebStylableHoverable | NativeStylableHoverable;
|
||||
|
||||
export { breakpoints, type Theme, ThemeProvider, useTheme } from "./theme";
|
||||
|
||||
@@ -7,14 +7,14 @@ import { ViewStyle, TextStyle, ImageStyle, useWindowDimensions } from "react-nat
|
||||
import { breakpoints, Theme, useTheme } from "../theme";
|
||||
import { AtLeastOne, Breakpoints, WithState, YoshikiStyle, hasState } from "../type";
|
||||
import { isBreakpoints } from "../utils";
|
||||
import { shorthandsFn } from "./shorthands";
|
||||
import { shorthandsFn } from "../shorthands";
|
||||
|
||||
type EnhancedStyle<Properties> = {
|
||||
export type EnhancedStyle<Properties> = {
|
||||
[key in keyof Properties]: YoshikiStyle<Properties[key]>;
|
||||
} & {
|
||||
[key in keyof typeof shorthandsFn]?: Parameters<typeof shorthandsFn[key]>[0];
|
||||
};
|
||||
type Properties = ViewStyle | TextStyle | ImageStyle;
|
||||
export type Properties = ViewStyle | TextStyle | ImageStyle;
|
||||
|
||||
const useBreakpoint = (): number => {
|
||||
const { width } = useWindowDimensions();
|
||||
@@ -54,6 +54,10 @@ const propertyMapper = <
|
||||
return [[key, value]];
|
||||
};
|
||||
|
||||
export type YsStyleProps<Style, State> = State extends AtLeastOne<WithState<Style>>
|
||||
? { style: (state: { pressed: boolean; focused: boolean; hovered: boolean }) => Style }
|
||||
: { style: Style };
|
||||
|
||||
export const useYoshiki = () => {
|
||||
const breakpoint = useBreakpoint();
|
||||
const theme = useTheme();
|
||||
@@ -65,9 +69,7 @@ export const useYoshiki = () => {
|
||||
>(
|
||||
css: EnhancedStyle<Style> & State,
|
||||
leftOvers?: { style?: Style },
|
||||
): State extends AtLeastOne<WithState<unknown>>
|
||||
? { style: (state: { pressed: boolean; focused: boolean; hovered: boolean }) => Style }
|
||||
: { style: Style } => {
|
||||
): YsStyleProps<Style, State> => {
|
||||
const { style, ...leftOverProps } = leftOvers ?? {};
|
||||
|
||||
const processStyle = (styleList: EnhancedStyle<Style>): Style => {
|
||||
@@ -112,9 +114,11 @@ export const useYoshiki = () => {
|
||||
};
|
||||
|
||||
export type Stylable = {
|
||||
style: Properties;
|
||||
style?: Properties;
|
||||
};
|
||||
|
||||
export type StylableHoverable = {
|
||||
style: ((state: { hovered: boolean, focused: boolean, pressed: boolean}) => Properties) | Properties;
|
||||
}
|
||||
style:
|
||||
| ((state: { hovered: boolean; focused: boolean; pressed: boolean }) => Properties)
|
||||
| Properties;
|
||||
};
|
||||
|
||||
@@ -14,11 +14,11 @@ export const Pressable = ({
|
||||
onBlur,
|
||||
style,
|
||||
...props
|
||||
}: {
|
||||
}: Omit<PressableProps, "style"> & {
|
||||
style:
|
||||
| PressableProps["style"]
|
||||
| StyleProp<ViewStyle>
|
||||
| ((state: { pressed: boolean; hovered: boolean; focused: boolean }) => StyleProp<ViewStyle>);
|
||||
} & PressableProps) => {
|
||||
}) => {
|
||||
const [hovered, setHover] = useState(false);
|
||||
const [focused, setFocus] = useState(false);
|
||||
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
|
||||
export { type Theme, breakpoints, useTheme, ThemeProvider } from "../theme";
|
||||
|
||||
export { useYoshiki, type Stylable } from "./generator";
|
||||
export { useYoshiki, type Stylable, type StylableHoverable } from "./generator";
|
||||
|
||||
export { Pressable } from "./hover";
|
||||
|
||||
@@ -9,7 +9,7 @@ import { isBreakpoints } from "../utils";
|
||||
import { CSSProperties, useInsertionEffect } from "react";
|
||||
import { useStyleRegistry } from "./registry";
|
||||
import { Properties } from "csstype";
|
||||
import { shorthandsFn } from "./shorthands";
|
||||
import { shorthandsFn } from "../shorthands";
|
||||
|
||||
type _CssObject = {
|
||||
[key in keyof Properties]: YoshikiStyle<Properties[key]>;
|
||||
@@ -17,7 +17,7 @@ type _CssObject = {
|
||||
[key in keyof typeof shorthandsFn]?: Parameters<typeof shorthandsFn[key]>[0];
|
||||
};
|
||||
|
||||
type CssObject = Partial<WithState<_CssObject>> & _CssObject;
|
||||
export type CssObject = Partial<WithState<_CssObject>> & _CssObject;
|
||||
|
||||
const stateMapper: { [key in keyof (WithState<undefined> & { normal: undefined })]: (cn: string) => string } = {
|
||||
normal: (cn) => `.${cn}`,
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Zoe Roux and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for details.
|
||||
//
|
||||
|
||||
import { YoshikiStyle } from "../type";
|
||||
import { Properties } from "csstype";
|
||||
|
||||
type YSPs = { [key in keyof Properties]: YoshikiStyle<Properties[key]> };
|
||||
|
||||
export const shorthandsFn = {
|
||||
p: (v: YSPs["padding"]): YSPs => ({
|
||||
padding: v,
|
||||
}),
|
||||
pX: (v: YSPs["paddingLeft"]): YSPs => ({
|
||||
paddingLeft: v,
|
||||
paddingRight: v,
|
||||
}),
|
||||
paddingX: (v: YSPs["paddingLeft"]): YSPs => ({
|
||||
paddingLeft: v,
|
||||
paddingRight: v,
|
||||
}),
|
||||
pY: (v: YSPs["paddingTop"]): YSPs => ({
|
||||
paddingTop: v,
|
||||
paddingBottom: v,
|
||||
}),
|
||||
paddingY: (v: YSPs["paddingTop"]): YSPs => ({
|
||||
paddingTop: v,
|
||||
paddingBottom: v,
|
||||
}),
|
||||
m: (v: YSPs["margin"]): YSPs => ({
|
||||
margin: v,
|
||||
}),
|
||||
mX: (v: YSPs["marginLeft"]): YSPs => ({
|
||||
marginLeft: v,
|
||||
marginRight: v,
|
||||
}),
|
||||
marginX: (v: YSPs["marginLeft"]): YSPs => ({
|
||||
marginLeft: v,
|
||||
marginRight: v,
|
||||
}),
|
||||
mY: (v: YSPs["marginTop"]): YSPs => ({
|
||||
marginTop: v,
|
||||
marginBottom: v,
|
||||
}),
|
||||
marginY: (v: YSPs["marginTop"]): YSPs => ({
|
||||
marginTop: v,
|
||||
marginBottom: v,
|
||||
}),
|
||||
// This can't be background because react native does not support it.
|
||||
bg: (v: YSPs["backgroundColor"]): YSPs => ({
|
||||
// We still remove the background in case it was set before.
|
||||
background: "unset",
|
||||
backgroundColor: v,
|
||||
}),
|
||||
};
|
||||
@@ -3,11 +3,10 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for details.
|
||||
//
|
||||
|
||||
import { YoshikiStyle } from "../type";
|
||||
import { ImageStyle, TextStyle, ViewStyle } from "react-native";
|
||||
import type { EnhancedStyle } from "./type";
|
||||
import type { ViewStyle } from "react-native";
|
||||
|
||||
type Properties = ViewStyle | TextStyle | ImageStyle;
|
||||
type YSPs = { [key in keyof Properties]: YoshikiStyle<Properties[key]> };
|
||||
type YSPs = EnhancedStyle<ViewStyle>
|
||||
|
||||
export const shorthandsFn = {
|
||||
p: (v: YSPs["padding"]): YSPs => ({
|
||||
@@ -4,6 +4,8 @@
|
||||
//
|
||||
|
||||
import { breakpoints, Theme } from "./theme";
|
||||
import { Properties as CssProperties } from "csstype";
|
||||
import type { ViewStyle, ImageStyle, TextStyle } from "react-native";
|
||||
|
||||
export type YoshikiStyle<Property> =
|
||||
| Property
|
||||
@@ -25,3 +27,17 @@ export const hasState = <Style>(obj: unknown): obj is WithState<Style> => {
|
||||
if (!obj || typeof obj !== "object") return false;
|
||||
return "hover" in obj || "focus" in obj || "press" in obj;
|
||||
};
|
||||
|
||||
export type OmitNever<T> = {
|
||||
[key in keyof T as T[key] extends never ? never : key]: T[key];
|
||||
};
|
||||
export type Combine<A, B> = OmitNever<Pick<A & B, keyof A & keyof B>>;
|
||||
|
||||
export type CommonCss<Style extends ViewStyle | ImageStyle | TextStyle> = Combine<
|
||||
CssProperties,
|
||||
Style
|
||||
>;
|
||||
|
||||
export type EnhancedStyle<Style extends ViewStyle | ImageStyle | TextStyle> = {
|
||||
[key in keyof CommonCss<Style>]: YoshikiStyle<CommonCss<Style>[key]>;
|
||||
};
|
||||
|
||||
@@ -3,4 +3,15 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for details.
|
||||
//
|
||||
|
||||
export * from "./index";
|
||||
export { type Theme, breakpoints, useTheme, ThemeProvider } from "./theme";
|
||||
|
||||
export {
|
||||
useYoshiki,
|
||||
useStyleRegistry,
|
||||
StyleRegistryProvider,
|
||||
createStyleRegistry,
|
||||
type Stylable,
|
||||
type StylableHoverable,
|
||||
useMobileHover,
|
||||
Pressable
|
||||
} from "./react";
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for details.
|
||||
//
|
||||
|
||||
export * from "./src";
|
||||
export * from "./src/web";
|
||||
|
||||
Reference in New Issue
Block a user