From f15ac3a566d65fb43c1fa1a531d57910ebff2286 Mon Sep 17 00:00:00 2001 From: Zoe Roux <zoe.roux@zoriya.dev> Date: Sun, 2 Feb 2025 00:24:34 +0100 Subject: [PATCH] Start to remove workspace & move theme to root package --- front/app/_layout.tsx | 86 ++++---- front/app/index.tsx | 9 +- front/package.json | 3 - .../primitives/src/themes/catppuccin.ts | 70 ------- .../packages/primitives/src/themes/theme.tsx | 192 ----------------- front/src/primitives/theme/catppuccin.tsx | 69 +++++++ front/src/primitives/theme/index.ts | 1 + front/src/primitives/theme/theme.tsx | 193 ++++++++++++++++++ front/src/providers.tsx | 5 +- 9 files changed, 314 insertions(+), 314 deletions(-) create mode 100644 front/src/primitives/theme/catppuccin.tsx create mode 100644 front/src/primitives/theme/index.ts create mode 100644 front/src/primitives/theme/theme.tsx diff --git a/front/app/_layout.tsx b/front/app/_layout.tsx index 5248e0027..2eab9e0e8 100644 --- a/front/app/_layout.tsx +++ b/front/app/_layout.tsx @@ -1,57 +1,55 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import { Slot } from "one"; -// import { WebTooltip } from "@kyoo/primitives/src/tooltip.web"; -// import { HiddenIfNoJs, SkeletonCss, TouchOnlyCss } from "@kyoo/primitives"; import { useServerHeadInsertion } from "one"; import { StyleRegistryProvider, createStyleRegistry, useTheme } from "yoshiki/web"; import { Providers } from "~/providers"; const GlobalCssTheme = () => { - const theme = useTheme(); + // const theme = useTheme(); // TODO: add fonts here // body {font-family: ${font.style.fontFamily};} + // background-color: ${theme.background}; return ( <> - {/* <style jsx global>{` */} - {/* body { */} - {/* margin: 0px; */} - {/* padding: 0px; */} - {/* overflow: "hidden"; */} - {/* background-color: ${theme.background}; */} - {/* } */} - {/**/} - {/* *::-webkit-scrollbar { */} - {/* height: 6px; */} - {/* width: 6px; */} - {/* background: transparent; */} - {/* } */} - {/**/} - {/* *::-webkit-scrollbar-thumb { */} - {/* background-color: #999; */} - {/* border-radius: 90px; */} - {/* } */} - {/* *:hover::-webkit-scrollbar-thumb { */} - {/* background-color: rgb(134, 127, 127); */} - {/* } */} - {/**/} - {/* #__next { */} - {/* height: 100vh; */} - {/* } */} - {/**/} - {/* .infinite-scroll-component__outerdiv { */} - {/* width: 100%; */} - {/* height: 100%; */} - {/* } */} - {/**/} - {/* ::cue { */} - {/* background-color: transparent; */} - {/* text-shadow: */} - {/* -1px -1px 0 #000, */} - {/* 1px -1px 0 #000, */} - {/* -1px 1px 0 #000, */} - {/* 1px 1px 0 #000; */} - {/* } */} - {/* `}</style> */} + <style>{` + body { + margin: 0px; + padding: 0px; + overflow: "hidden"; + } + + *::-webkit-scrollbar { + height: 6px; + width: 6px; + background: transparent; + } + + *::-webkit-scrollbar-thumb { + background-color: #999; + border-radius: 90px; + } + *:hover::-webkit-scrollbar-thumb { + background-color: rgb(134, 127, 127); + } + + #__next { + height: 100vh; + } + + .infinite-scroll-component__outerdiv { + width: 100%; + height: 100%; + } + + ::cue { + background-color: transparent; + text-shadow: + -1px -1px 0 #000, + 1px -1px 0 #000, + -1px 1px 0 #000, + 1px 1px 0 #000; + } + `}</style> {/* <WebTooltip theme={theme} /> */} {/* <SkeletonCss /> */} {/* <TouchOnlyCss /> */} @@ -76,7 +74,7 @@ export default function Layout() { <link rel="icon" type="image/png" sizes="64x64" href="/icon-64x64.png" /> <link rel="icon" type="image/png" sizes="128x128" href="/icon-128x128.png" /> <link rel="icon" type="image/png" sizes="256x256" href="/icon-256x256.png" /> - {/* <GlobalCssTheme /> */} + <GlobalCssTheme /> </head> <body className="hoverEnabled"> diff --git a/front/app/index.tsx b/front/app/index.tsx index 99584d210..a58e035d8 100644 --- a/front/app/index.tsx +++ b/front/app/index.tsx @@ -1,14 +1,17 @@ -import { View, Text } from "react-native"; +import { Text, View } from "react-native"; +import { useYoshiki } from "yoshiki/native"; export default function MyApp() { + const { css } = useYoshiki(); + return ( <View - style={{ + {...css({ flex: 1, justifyContent: "center", alignItems: "center", minHeight: "100%", - }} + })} > <Text>Hello from One</Text> </View> diff --git a/front/package.json b/front/package.json index fd63bc785..83d88bcea 100644 --- a/front/package.json +++ b/front/package.json @@ -12,10 +12,7 @@ "format": "biome format .", "format:fix": "biome format . --write" }, - "workspaces": ["packages/*"], "dependencies": { - "@kyoo/models": "workspace:*", - "@kyoo/primitives": "workspace:*", "@tanstack/react-query": "^5.66.0", "caniuse-api": "^3.0.0", "expo": "~52.0.28", diff --git a/front/packages/primitives/src/themes/catppuccin.ts b/front/packages/primitives/src/themes/catppuccin.ts index 869883632..609d690d9 100644 --- a/front/packages/primitives/src/themes/catppuccin.ts +++ b/front/packages/primitives/src/themes/catppuccin.ts @@ -17,73 +17,3 @@ * You should have received a copy of the GNU General Public License * along with Kyoo. If not, see <https://www.gnu.org/licenses/>. */ - -import type { ThemeBuilder } from "./theme"; - -// Ref: https://github.com/catppuccin/catppuccin -export const catppuccin: ThemeBuilder = { - light: { - // Catppuccin latte - overlay0: "#9ca0b0", - overlay1: "#7c7f93", - lightOverlay: "#eff1f599", - darkOverlay: "#4c4f6999", - link: "#1e66f5", - default: { - background: "#eff1f5", - accent: "#e64553", - divider: "#8c8fa1", - heading: "#4c4f69", - paragraph: "#5c5f77", - subtext: "#6c6f85", - }, - variant: { - background: "#e6e9ef", - accent: "#d20f39", - divider: "#dd7878", - heading: "#4c4f69", - paragraph: "#5c5f77", - subtext: "#6c6f85", - }, - colors: { - red: "#d20f39", - green: "#40a02b", - blue: "#1e66f5", - yellow: "#df8e1d", - black: "#4c4f69", - white: "#eff1f5", - }, - }, - dark: { - // Catppuccin mocha - overlay0: "#6c7086", - overlay1: "#9399b2", - lightOverlay: "#f5f0f899", - darkOverlay: "#11111b99", - link: "#89b4fa", - default: { - background: "#1e1e2e", - accent: "#89b4fa", - divider: "#7f849c", - heading: "#cdd6f4", - paragraph: "#bac2de", - subtext: "#a6adc8", - }, - variant: { - background: "#181825", - accent: "#74c7ec", - divider: "#1e1e2e", - heading: "#cdd6f4", - paragraph: "#bac2de", - subtext: "#a6adc8", - }, - colors: { - red: "#f38ba8", - green: "#a6e3a1", - blue: "#89b4fa", - yellow: "#f9e2af", - black: "#11111b", - white: "#f5f0f8", - }, - }, -}; diff --git a/front/packages/primitives/src/themes/theme.tsx b/front/packages/primitives/src/themes/theme.tsx index ffc764ce7..b4d49ce95 100644 --- a/front/packages/primitives/src/themes/theme.tsx +++ b/front/packages/primitives/src/themes/theme.tsx @@ -18,195 +18,3 @@ * along with Kyoo. If not, see <https://www.gnu.org/licenses/>. */ -import type { Property } from "csstype"; -import type { ReactNode } from "react"; -import { Platform, type TextStyle } from "react-native"; -import { type Theme, ThemeProvider, useAutomaticTheme } from "yoshiki"; -import "yoshiki"; -import { useTheme, useYoshiki } from "yoshiki/native"; -import "yoshiki/native"; -import { catppuccin } from "./catppuccin"; - -type FontList = Partial< - Record<Exclude<TextStyle["fontWeight"], null | undefined | number>, string> ->; - -type Mode = { - mode: "light" | "dark" | "auto"; - overlay0: Property.Color; - overlay1: Property.Color; - lightOverlay: Property.Color; - darkOverlay: Property.Color; - themeOverlay: Property.Color; - link: Property.Color; - contrast: Property.Color; - variant: Variant; - colors: { - red: Property.Color; - green: Property.Color; - blue: Property.Color; - yellow: Property.Color; - white: Property.Color; - black: Property.Color; - }; -}; - -type Variant = { - background: Property.Color; - accent: Property.Color; - divider: Property.Color; - heading: Property.Color; - paragraph: Property.Color; - subtext: Property.Color; -}; - -declare module "yoshiki" { - export interface Theme extends Mode, Variant { - light: Mode & Variant; - dark: Mode & Variant; - user: Mode & Variant; - alternate: Mode & Variant; - font: FontList; - } -} - -export type { Theme } from "yoshiki"; -export type ThemeBuilder = { - light: Omit<Mode, "contrast" | "mode" | "themeOverlay"> & { default: Variant }; - dark: Omit<Mode, "contrast" | "mode" | "themeOverlay"> & { default: Variant }; -}; - -const selectMode = ( - theme: ThemeBuilder & { font: FontList }, - mode: "light" | "dark" | "auto", -): Theme => { - const { light: lightBuilder, dark: darkBuilder, ...options } = theme; - const light: Mode & Variant = { - ...lightBuilder, - ...lightBuilder.default, - contrast: lightBuilder.colors.black, - themeOverlay: lightBuilder.lightOverlay, - mode: "light", - }; - const dark: Mode & Variant = { - ...darkBuilder, - ...darkBuilder.default, - contrast: darkBuilder.colors.white, - themeOverlay: darkBuilder.darkOverlay, - mode: "dark", - }; - if (Platform.OS !== "web" || mode !== "auto") { - const value = mode === "light" ? light : dark; - const alternate = mode === "light" ? dark : light; - return { - ...options, - ...value, - light, - dark, - user: value, - alternate, - }; - } - - const auto = useAutomaticTheme("theme", { light, dark }); - const alternate = useAutomaticTheme("alternate", { dark: light, light: dark }); - return { - ...options, - ...auto, - mode: "auto", - light, - dark, - user: { ...auto, mode: "auto" }, - alternate: { ...alternate, mode: "auto" }, - }; -}; - -const switchVariant = (theme: Theme) => { - return { - ...theme, - ...theme.variant, - variant: { - background: theme.background, - accent: theme.accent, - divider: theme.divider, - heading: theme.heading, - paragraph: theme.paragraph, - subtext: theme.subtext, - }, - }; -}; - -export const ThemeSelector = ({ - children, - theme, - font, -}: { - children: ReactNode; - theme: "light" | "dark" | "auto"; - font: FontList; -}) => { - const newTheme = selectMode({ ...catppuccin, font }, theme); - - return <ThemeProvider theme={newTheme}>{children as any}</ThemeProvider>; -}; - -export type YoshikiFunc<T> = (props: ReturnType<typeof useYoshiki>) => T; - -const YoshikiProvider = ({ children }: { children: YoshikiFunc<ReactNode> }) => { - const yoshiki = useYoshiki(); - return <>{children(yoshiki)}</>; -}; - -export const SwitchVariant = ({ children }: { children: ReactNode | YoshikiFunc<ReactNode> }) => { - const theme = useTheme(); - - return ( - <ThemeProvider theme={switchVariant(theme)}> - {typeof children === "function" ? ( - <YoshikiProvider>{children}</YoshikiProvider> - ) : ( - (children as any) - )} - </ThemeProvider> - ); -}; - -export const ContrastArea = ({ - children, - mode = "dark", - contrastText, -}: { - children: ReactNode | YoshikiFunc<ReactNode>; - mode?: "light" | "dark" | "user" | "alternate"; - contrastText?: boolean; -}) => { - const oldTheme = useTheme(); - const theme: Theme = { ...oldTheme, ...oldTheme[mode] }; - - return ( - <ThemeProvider - theme={ - contrastText - ? { - ...theme, - // Keep the same skeletons, it looks weird otherwise. - overlay0: theme.user.overlay0, - overlay1: theme.user.overlay1, - heading: theme.contrast, - paragraph: theme.heading, - } - : theme - } - > - {typeof children === "function" ? ( - <YoshikiProvider>{children}</YoshikiProvider> - ) : ( - (children as any) - )} - </ThemeProvider> - ); -}; - -export const alpha = (color: Property.Color, alpha: number) => { - return color + Math.round(alpha * 255).toString(16); -}; diff --git a/front/src/primitives/theme/catppuccin.tsx b/front/src/primitives/theme/catppuccin.tsx new file mode 100644 index 000000000..1c3af6c8b --- /dev/null +++ b/front/src/primitives/theme/catppuccin.tsx @@ -0,0 +1,69 @@ +import type { ThemeBuilder } from "./theme"; + +// Ref: https://github.com/catppuccin/catppuccin +export const catppuccin: ThemeBuilder = { + light: { + // Catppuccin latte + overlay0: "#9ca0b0", + overlay1: "#7c7f93", + lightOverlay: "#eff1f599", + darkOverlay: "#4c4f6999", + link: "#1e66f5", + default: { + background: "#eff1f5", + accent: "#e64553", + divider: "#8c8fa1", + heading: "#4c4f69", + paragraph: "#5c5f77", + subtext: "#6c6f85", + }, + variant: { + background: "#e6e9ef", + accent: "#d20f39", + divider: "#dd7878", + heading: "#4c4f69", + paragraph: "#5c5f77", + subtext: "#6c6f85", + }, + colors: { + red: "#d20f39", + green: "#40a02b", + blue: "#1e66f5", + yellow: "#df8e1d", + black: "#4c4f69", + white: "#eff1f5", + }, + }, + dark: { + // Catppuccin mocha + overlay0: "#6c7086", + overlay1: "#9399b2", + lightOverlay: "#f5f0f899", + darkOverlay: "#11111b99", + link: "#89b4fa", + default: { + background: "#1e1e2e", + accent: "#89b4fa", + divider: "#7f849c", + heading: "#cdd6f4", + paragraph: "#bac2de", + subtext: "#a6adc8", + }, + variant: { + background: "#181825", + accent: "#74c7ec", + divider: "#1e1e2e", + heading: "#cdd6f4", + paragraph: "#bac2de", + subtext: "#a6adc8", + }, + colors: { + red: "#f38ba8", + green: "#a6e3a1", + blue: "#89b4fa", + yellow: "#f9e2af", + black: "#11111b", + white: "#f5f0f8", + }, + }, +}; diff --git a/front/src/primitives/theme/index.ts b/front/src/primitives/theme/index.ts new file mode 100644 index 000000000..3797aeae0 --- /dev/null +++ b/front/src/primitives/theme/index.ts @@ -0,0 +1 @@ +export * from "./theme"; diff --git a/front/src/primitives/theme/theme.tsx b/front/src/primitives/theme/theme.tsx new file mode 100644 index 000000000..fbd134bb2 --- /dev/null +++ b/front/src/primitives/theme/theme.tsx @@ -0,0 +1,193 @@ +import type { Property } from "csstype"; +import type { ReactNode } from "react"; +import { Platform, type TextStyle } from "react-native"; +import { type Theme, ThemeProvider, useAutomaticTheme } from "yoshiki"; +import "yoshiki"; +import { useTheme, useYoshiki } from "yoshiki/native"; +import "yoshiki/native"; +import { catppuccin } from "./catppuccin"; + +type FontList = Partial< + Record<Exclude<TextStyle["fontWeight"], null | undefined | number>, string> +>; + +type Mode = { + mode: "light" | "dark" | "auto"; + overlay0: Property.Color; + overlay1: Property.Color; + lightOverlay: Property.Color; + darkOverlay: Property.Color; + themeOverlay: Property.Color; + link: Property.Color; + contrast: Property.Color; + variant: Variant; + colors: { + red: Property.Color; + green: Property.Color; + blue: Property.Color; + yellow: Property.Color; + white: Property.Color; + black: Property.Color; + }; +}; + +type Variant = { + background: Property.Color; + accent: Property.Color; + divider: Property.Color; + heading: Property.Color; + paragraph: Property.Color; + subtext: Property.Color; +}; + +declare module "yoshiki" { + export interface Theme extends Mode, Variant { + light: Mode & Variant; + dark: Mode & Variant; + user: Mode & Variant; + alternate: Mode & Variant; + font: FontList; + } +} + +export type { Theme } from "yoshiki"; +export type ThemeBuilder = { + light: Omit<Mode, "contrast" | "mode" | "themeOverlay"> & { default: Variant }; + dark: Omit<Mode, "contrast" | "mode" | "themeOverlay"> & { default: Variant }; +}; + +const selectMode = ( + theme: ThemeBuilder & { font: FontList }, + mode: "light" | "dark" | "auto", +): Theme => { + const { light: lightBuilder, dark: darkBuilder, ...options } = theme; + const light: Mode & Variant = { + ...lightBuilder, + ...lightBuilder.default, + contrast: lightBuilder.colors.black, + themeOverlay: lightBuilder.lightOverlay, + mode: "light", + }; + const dark: Mode & Variant = { + ...darkBuilder, + ...darkBuilder.default, + contrast: darkBuilder.colors.white, + themeOverlay: darkBuilder.darkOverlay, + mode: "dark", + }; + if (Platform.OS !== "web" || mode !== "auto") { + const value = mode === "light" ? light : dark; + const alternate = mode === "light" ? dark : light; + return { + ...options, + ...value, + light, + dark, + user: value, + alternate, + }; + } + + const auto = useAutomaticTheme("theme", { light, dark }); + const alternate = useAutomaticTheme("alternate", { dark: light, light: dark }); + return { + ...options, + ...auto, + mode: "auto", + light, + dark, + user: { ...auto, mode: "auto" }, + alternate: { ...alternate, mode: "auto" }, + }; +}; + +const switchVariant = (theme: Theme) => { + return { + ...theme, + ...theme.variant, + variant: { + background: theme.background, + accent: theme.accent, + divider: theme.divider, + heading: theme.heading, + paragraph: theme.paragraph, + subtext: theme.subtext, + }, + }; +}; + +export const ThemeSelector = ({ + children, + theme, + font, +}: { + children: ReactNode; + theme: "light" | "dark" | "auto"; + font: FontList; +}) => { + const newTheme = selectMode({ ...catppuccin, font }, theme); + + return <ThemeProvider theme={newTheme}>{children as any}</ThemeProvider>; +}; + +export type YoshikiFunc<T> = (props: ReturnType<typeof useYoshiki>) => T; + +const YoshikiProvider = ({ children }: { children: YoshikiFunc<ReactNode> }) => { + const yoshiki = useYoshiki(); + return <>{children(yoshiki)}</>; +}; + +export const SwitchVariant = ({ children }: { children: ReactNode | YoshikiFunc<ReactNode> }) => { + const theme = useTheme(); + + return ( + <ThemeProvider theme={switchVariant(theme)}> + {typeof children === "function" ? ( + <YoshikiProvider>{children}</YoshikiProvider> + ) : ( + (children as any) + )} + </ThemeProvider> + ); +}; + +export const ContrastArea = ({ + children, + mode = "dark", + contrastText, +}: { + children: ReactNode | YoshikiFunc<ReactNode>; + mode?: "light" | "dark" | "user" | "alternate"; + contrastText?: boolean; +}) => { + const oldTheme = useTheme(); + const theme: Theme = { ...oldTheme, ...oldTheme[mode] }; + + return ( + <ThemeProvider + theme={ + contrastText + ? { + ...theme, + // Keep the same skeletons, it looks weird otherwise. + overlay0: theme.user.overlay0, + overlay1: theme.user.overlay1, + heading: theme.contrast, + paragraph: theme.heading, + } + : theme + } + > + {typeof children === "function" ? ( + <YoshikiProvider>{children}</YoshikiProvider> + ) : ( + (children as any) + )} + </ThemeProvider> + ); +}; + +export const alpha = (color: Property.Color, alpha: number) => { + return color + Math.round(alpha * 255).toString(16); +}; + diff --git a/front/src/providers.tsx b/front/src/providers.tsx index 313c33ebe..7e9a46941 100644 --- a/front/src/providers.tsx +++ b/front/src/providers.tsx @@ -1,7 +1,8 @@ -// import { useUserTheme } from "@kyoo/models"; -import { ThemeSelector } from "@kyoo/primitives"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ComponentType, type ReactNode, useState } from "react"; +// import { useUserTheme } from "@kyoo/models"; +// import { createQueryClient } from "@kyoo/models"; +import { ThemeSelector } from "~/primitives/theme"; const QueryProvider = ({ children }: { children: ReactNode }) => { // const [queryClient] = useState(() => createQueryClient());