diff --git a/examples/expo-example/package.json b/examples/expo-example/package.json index 951329c..c164e35 100644 --- a/examples/expo-example/package.json +++ b/examples/expo-example/package.json @@ -11,7 +11,7 @@ "dependencies": { "@expo/html-elements": "^0.2.0", "@expo/webpack-config": "^0.17.0", - "@yoshiki/native": "*", + "yoshiki": "*", "expo": "~46.0.16", "expo-status-bar": "~1.4.0", "react": "18.0.0", diff --git a/examples/expo-example/src/app.tsx b/examples/expo-example/src/app.tsx index 674d154..b293975 100644 --- a/examples/expo-example/src/app.tsx +++ b/examples/expo-example/src/app.tsx @@ -4,12 +4,12 @@ // import { StatusBar } from "expo-status-bar"; -import { Pressable, Text, View } from "react-native"; +import { Text, View } from "react-native"; import { registerRootComponent } from "expo"; -import { useCss } from "@yoshiki/native"; +import { Stylable, useYoshiki } from "yoshiki/native"; -const CustomBox = ({ color, ...props }: { color: string }) => { - const css = useCss(); +const CustomBox = ({ color, ...props }: { color: string } & Stylable) => { + const { css } = useYoshiki(); return ( @@ -18,18 +18,18 @@ const CustomBox = ({ color, ...props }: { color: string }) => { ); }; -const BoxWithoutProps = (props: object) => { - const css = useCss(); +const BoxWithoutProps = (props: Stylable) => { + const { css } = useYoshiki(); return ( - + Text inside the box without props (green on small screens, red on bigs) ); }; function App() { - const css = useCss(); + const { css } = useYoshiki(); return ( { diff --git a/examples/next-example/src/pages/_document.tsx b/examples/next-example/src/pages/_document.tsx index d8f41fb..12566e7 100644 --- a/examples/next-example/src/pages/_document.tsx +++ b/examples/next-example/src/pages/_document.tsx @@ -3,11 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for details. // -import { - StyleRegistryProvider, - createStyleRegistry, - useStyleRegistry, -} from "@yoshiki/react/src/registry"; +import { StyleRegistryProvider, createStyleRegistry, useStyleRegistry } from "yoshiki"; import Document, { DocumentContext } from "next/document"; Document.getInitialProps = async (ctx: DocumentContext) => { diff --git a/examples/next-example/src/pages/index.tsx b/examples/next-example/src/pages/index.tsx index 32d325c..f77ac75 100644 --- a/examples/next-example/src/pages/index.tsx +++ b/examples/next-example/src/pages/index.tsx @@ -5,7 +5,7 @@ import Head from "next/head"; import Image from "next/image"; -import { useYoshiki, Stylable } from "@yoshiki/react"; +import { useYoshiki, Stylable } from "yoshiki"; import { ReactNode } from "react"; const Box = ({ children, ...props }: { children?: ReactNode } & Stylable) => { diff --git a/packages/core/package.json b/packages/core/package.json deleted file mode 100644 index dd25faa..0000000 --- a/packages/core/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@yoshiki/core", - "version": "1.0.0", - "main": "src/index.ts", - "types": "src/index.ts", - "peerDependencies": { - "react": "*" - }, - "devDependencies": { - "@types/react": "^18.0.24", - "react": "^18.2.0", - "typescript": "^4.8.4" - } -} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts deleted file mode 100644 index bb2028f..0000000 --- a/packages/core/src/index.ts +++ /dev/null @@ -1,9 +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. -// - -export * from "./type"; -export * from "./theme"; - -export * from "./utils"; diff --git a/packages/native/package.json b/packages/native/package.json deleted file mode 100644 index f44348f..0000000 --- a/packages/native/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "@yoshiki/native", - "version": "1.0.0", - "main": "src/index.tsx", - "types": "src/index.tsx", - "dependencies": { - "@yoshiki/core": "*" - }, - "devDependencies": { - "@types/react": "^18.0.24", - "@types/react-native": "~0.69.1", - "typescript": "^4.8.4" - }, - "peerDependencies": { - "react": "*", - "react-native": "*" - } -} diff --git a/packages/native/tsconfig.json b/packages/native/tsconfig.json deleted file mode 100755 index b65f7f9..0000000 --- a/packages/native/tsconfig.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - "noErrorTruncation": true, - "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], - "declaration": true, - "sourceMap": true, - "noEmit": true, - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "react-native", - "incremental": true, - "baseUrl": ".", - "paths": { - "~/*": ["src/*"] - } - }, - "include": ["**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] -} diff --git a/packages/react/package.json b/packages/react/package.json deleted file mode 100644 index 5c27c24..0000000 --- a/packages/react/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "@yoshiki/react", - "version": "1.0.0", - "main": "src/index.ts", - "types": "src/index.ts", - "dependencies": { - "@yoshiki/core": "*" - }, - "devDependencies": { - "@types/react": "^18.0.24", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "typescript": "^4.8.4" - }, - "peerDependencies": { - "react": "*" - } -} diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json deleted file mode 100755 index aedf3ae..0000000 --- a/packages/react/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "lib": ["dom", "dom.iterable", "esnext"], - "declaration": true, - "sourceMap": true, - "noEmit": true, - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "react", - "incremental": true, - "baseUrl": ".", - "paths": { - "~/*": ["src/*"] - } - }, - "include": ["**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] -} diff --git a/packages/yoshiki/package.json b/packages/yoshiki/package.json new file mode 100644 index 0000000..1c22978 --- /dev/null +++ b/packages/yoshiki/package.json @@ -0,0 +1,25 @@ +{ + "name": "yoshiki", + "version": "1.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "exports": { + ".": "./src/index.ts", + "./native": "./src/native/index.ts" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "react-native": { + "optional": true + } + }, + "devDependencies": { + "@types/react": "^18.0.24", + "@types/react-native": "~0.69.1", + "react": "^18.2.0", + "typescript": "^4.8.4" + } +} diff --git a/packages/yoshiki/src/index.ts b/packages/yoshiki/src/index.ts new file mode 100644 index 0000000..7f65d46 --- /dev/null +++ b/packages/yoshiki/src/index.ts @@ -0,0 +1,16 @@ +// +// Copyright (c) Zoe Roux and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. +// + +export { type Theme, breakpoints, useTheme } from "./theme"; +export { type YoshikiRegistry } from "./type"; + +export { + useYoshiki, + useStyleRegistry, + StyleRegistryProvider, + createStyleRegistry, + type Stylable, + type CssObject, +} from "./react"; diff --git a/packages/native/src/index.tsx b/packages/yoshiki/src/native/generator.tsx similarity index 67% rename from packages/native/src/index.tsx rename to packages/yoshiki/src/native/generator.tsx index 65c6251..8b7c5bd 100644 --- a/packages/native/src/index.tsx +++ b/packages/yoshiki/src/native/generator.tsx @@ -4,14 +4,9 @@ // import { ViewStyle, TextStyle, ImageStyle, useWindowDimensions } from "react-native"; -import { - breakpoints, - Breakpoints, - Theme, - YoshikiStyle, - useTheme, - isBreakpoints, -} from "@yoshiki/core"; +import { breakpoints, Theme, useTheme } from "~/theme"; +import { Breakpoints, YoshikiStyle } from "~/type"; +import { isBreakpoints } from "~/utils"; // TODO: shorhands type EnhancedStyle = { @@ -51,23 +46,29 @@ const propertyMapper = < return value; }; -// TODO: do not use a hook and use a global window width. -export const useCss = () => { +export const useYoshiki = () => { const breakpoint = useBreakpoint(); const theme = useTheme(); - return (css: CssObject, leftOvers?: { style?: Properties }) => { - const { style, ...leftOverProps } = leftOvers ?? {}; + return { + css: (css: CssObject, leftOvers?: { style?: Properties }) => { + const { style, ...leftOverProps } = leftOvers ?? {}; - const inline: Properties = Object.fromEntries( - Object.entries(css) - .map(([key, value]) => [key, propertyMapper(value, { breakpoint, theme })]) - .filter(([, value]) => value !== undefined), - ); + const inline: Properties = Object.fromEntries( + Object.entries(css) + .map(([key, value]) => [key, propertyMapper(value, { breakpoint, theme })]) + .filter(([, value]) => value !== undefined), + ); - return { - style: { ...inline, ...style }, - ...leftOverProps, - }; + return { + style: { ...inline, ...style }, + ...leftOverProps, + }; + }, + theme: theme, }; }; + +export type Stylable = { + style: Properties +} diff --git a/packages/yoshiki/src/native/index.ts b/packages/yoshiki/src/native/index.ts new file mode 100644 index 0000000..5f7e1cd --- /dev/null +++ b/packages/yoshiki/src/native/index.ts @@ -0,0 +1,11 @@ +// +// Copyright (c) Zoe Roux and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. +// + +export { type Theme, breakpoints, useTheme } from "../theme"; +export { type YoshikiRegistry } from "../type"; + +export { useYoshiki, type Stylable, type CssObject } from "./generator"; + +export { useStyleRegistry, StyleRegistryProvider, createStyleRegistry } from "./noop-registry"; diff --git a/packages/yoshiki/src/native/noop-registry.tsx b/packages/yoshiki/src/native/noop-registry.tsx new file mode 100644 index 0000000..2f3ace2 --- /dev/null +++ b/packages/yoshiki/src/native/noop-registry.tsx @@ -0,0 +1,27 @@ +// +// Copyright (c) Zoe Roux and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. +// + +import { ReactNode } from "react"; +import { YoshikiRegistry } from "~/type"; + +class NoopRegistry implements YoshikiRegistry { + flush(): string[] { + return []; + } +} + +export const StyleRegistryProvider = ({ + registry, + children, +}: { + registry?: YoshikiRegistry; + children: ReactNode; +}) => { + return children; +}; + +export const createStyleRegistry = () => new NoopRegistry(); +export const useStyleRegistry = createStyleRegistry; + diff --git a/packages/react/src/index.ts b/packages/yoshiki/src/react/generator.ts similarity index 81% rename from packages/react/src/index.ts rename to packages/yoshiki/src/react/generator.ts index 4f2a0a9..db0a867 100644 --- a/packages/react/src/index.ts +++ b/packages/yoshiki/src/react/generator.ts @@ -3,15 +3,12 @@ // Licensed under the MIT license. See LICENSE file in the project root for details. // -import { Properties } from "csstype"; -import { Theme, YoshikiStyle, useTheme, breakpoints, isBreakpoints } from "@yoshiki/core"; +import { useTheme } from "~/theme"; +import { Theme, YoshikiStyle, breakpoints } from "~/type"; +import { isBreakpoints } from "~/utils"; import { CSSProperties, useInsertionEffect } from "react"; import { useStyleRegistry } from "./registry"; - -// TODO: shorthands -export type CssObject = { - [key in keyof Properties]: YoshikiStyle; -}; +import type { CssObject } from "."; const generateAtomicCss = ( key: string, @@ -43,7 +40,7 @@ const dedupProperties = (...classes: (string | undefined)[]) => { for (const name of classes) { if (!name) continue; // example ys-background-blue or ys-sm_background-red - const key = name.substring(3, name.lastIndexOf('-')) + const key = name.substring(3, name.lastIndexOf("-")); propMap.set(key, name); } return Array.from(propMap.values()).join(" "); @@ -58,10 +55,7 @@ export const useYoshiki = () => { }, [registry]); return { - css: ( - css: CssObject /* | CssObject[] */, - leftOverProps?: { className?: string; style?: CSSProperties }, - ) => { + css: (css: CssObject, leftOverProps?: { className?: string; style?: CSSProperties }) => { const { className, style, ...leftOver } = leftOverProps ?? {}; // I'm sad that traverse is not a thing in JS. @@ -84,8 +78,3 @@ export const useYoshiki = () => { theme, }; }; - -export type Stylable = { - className?: string, - style?: CSSProperties, -} diff --git a/packages/yoshiki/src/react/index.tsx b/packages/yoshiki/src/react/index.tsx new file mode 100644 index 0000000..328d2bb --- /dev/null +++ b/packages/yoshiki/src/react/index.tsx @@ -0,0 +1,20 @@ +// +// Copyright (c) Zoe Roux and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. +// + +import { Properties } from "csstype"; +import { CSSProperties } from "react"; +import { YoshikiStyle } from "~/type"; + +export type CssObject = { + [key in keyof Properties]: YoshikiStyle; +}; + +export type Stylable = { + className?: string; + style?: CSSProperties; +}; + +export { useYoshiki } from "./generator"; +export { StyleRegistryProvider, useStyleRegistry, createStyleRegistry } from "./registry"; diff --git a/packages/react/src/registry.tsx b/packages/yoshiki/src/react/registry.tsx similarity index 96% rename from packages/react/src/registry.tsx rename to packages/yoshiki/src/react/registry.tsx index 1375091..d4f74da 100644 --- a/packages/react/src/registry.tsx +++ b/packages/yoshiki/src/react/registry.tsx @@ -4,8 +4,9 @@ // import React, { createContext, ReactNode, useContext } from "react"; +import { YoshikiRegistry } from "~/type"; -class StyleRegistry { +class StyleRegistry implements YoshikiRegistry { private completed: string[] = []; private rules: [string, string][] = []; private styleElement: HTMLStyleElement | null = null; diff --git a/packages/core/src/theme.tsx b/packages/yoshiki/src/theme.tsx similarity index 55% rename from packages/core/src/theme.tsx rename to packages/yoshiki/src/theme.tsx index ec6f87e..cc05ca0 100644 --- a/packages/core/src/theme.tsx +++ b/packages/yoshiki/src/theme.tsx @@ -3,7 +3,16 @@ // Licensed under the MIT license. See LICENSE file in the project root for details. // -import { Theme } from "./type"; +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface Theme {}; + +export const breakpoints = { + xs: 0, + sm: 600, + md: 900, + lg: 1200, + xl: 1600, +} export const useTheme = () => { return {} as Theme; diff --git a/packages/core/src/type.ts b/packages/yoshiki/src/type.ts similarity index 62% rename from packages/core/src/type.ts rename to packages/yoshiki/src/type.ts index b850d38..fda320c 100644 --- a/packages/core/src/type.ts +++ b/packages/yoshiki/src/type.ts @@ -3,18 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for details. // -export type Theme = { - // TODO: remove this, just for test purpose - spacing: string; -}; - -export const breakpoints = { - xs: 0, - sm: 600, - md: 900, - lg: 1200, - xl: 1600, -} +import { breakpoints, Theme } from "./theme"; export type YoshikiStyle = | Property @@ -25,3 +14,11 @@ export type YoshikiStyle = export type Breakpoints = { [key in keyof (typeof breakpoints)]?: Property; }; + +export interface YoshikiRegistry { + /** + * Retrieve all newly created styles not yet flushed. + * @returns An array of css classes declarations. + */ + flush(): string[]; +} diff --git a/packages/core/src/utils.ts b/packages/yoshiki/src/utils.ts similarity index 100% rename from packages/core/src/utils.ts rename to packages/yoshiki/src/utils.ts diff --git a/packages/core/tsconfig.json b/packages/yoshiki/tsconfig.json similarity index 96% rename from packages/core/tsconfig.json rename to packages/yoshiki/tsconfig.json index 32ca157..fbe09c6 100755 --- a/packages/core/tsconfig.json +++ b/packages/yoshiki/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "es6", "lib": ["dom", "dom.iterable", "esnext"], "declaration": true, "sourceMap": true, diff --git a/yarn.lock b/yarn.lock index 57f8ff1..18f3893 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9509,7 +9509,7 @@ react-dom@18.0.0: loose-envify "^1.1.0" scheduler "^0.21.0" -react-dom@18.2.0, react-dom@^18.2.0: +react-dom@18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==