mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Start to remove workspace & move theme to root package
This commit is contained in:
parent
274e4b75dc
commit
6548fde324
@ -1,57 +1,55 @@
|
|||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
import { Slot } from "one";
|
import { Slot } from "one";
|
||||||
// import { WebTooltip } from "@kyoo/primitives/src/tooltip.web";
|
|
||||||
// import { HiddenIfNoJs, SkeletonCss, TouchOnlyCss } from "@kyoo/primitives";
|
|
||||||
import { useServerHeadInsertion } from "one";
|
import { useServerHeadInsertion } from "one";
|
||||||
import { StyleRegistryProvider, createStyleRegistry, useTheme } from "yoshiki/web";
|
import { StyleRegistryProvider, createStyleRegistry, useTheme } from "yoshiki/web";
|
||||||
import { Providers } from "~/providers";
|
import { Providers } from "~/providers";
|
||||||
|
|
||||||
const GlobalCssTheme = () => {
|
const GlobalCssTheme = () => {
|
||||||
const theme = useTheme();
|
// const theme = useTheme();
|
||||||
// TODO: add fonts here
|
// TODO: add fonts here
|
||||||
// body {font-family: ${font.style.fontFamily};}
|
// body {font-family: ${font.style.fontFamily};}
|
||||||
|
// background-color: ${theme.background};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <style jsx global>{` */}
|
<style>{`
|
||||||
{/* body { */}
|
body {
|
||||||
{/* margin: 0px; */}
|
margin: 0px;
|
||||||
{/* padding: 0px; */}
|
padding: 0px;
|
||||||
{/* overflow: "hidden"; */}
|
overflow: "hidden";
|
||||||
{/* background-color: ${theme.background}; */}
|
}
|
||||||
{/* } */}
|
|
||||||
{/**/}
|
*::-webkit-scrollbar {
|
||||||
{/* *::-webkit-scrollbar { */}
|
height: 6px;
|
||||||
{/* height: 6px; */}
|
width: 6px;
|
||||||
{/* width: 6px; */}
|
background: transparent;
|
||||||
{/* background: transparent; */}
|
}
|
||||||
{/* } */}
|
|
||||||
{/**/}
|
*::-webkit-scrollbar-thumb {
|
||||||
{/* *::-webkit-scrollbar-thumb { */}
|
background-color: #999;
|
||||||
{/* background-color: #999; */}
|
border-radius: 90px;
|
||||||
{/* border-radius: 90px; */}
|
}
|
||||||
{/* } */}
|
*:hover::-webkit-scrollbar-thumb {
|
||||||
{/* *:hover::-webkit-scrollbar-thumb { */}
|
background-color: rgb(134, 127, 127);
|
||||||
{/* background-color: rgb(134, 127, 127); */}
|
}
|
||||||
{/* } */}
|
|
||||||
{/**/}
|
#__next {
|
||||||
{/* #__next { */}
|
height: 100vh;
|
||||||
{/* height: 100vh; */}
|
}
|
||||||
{/* } */}
|
|
||||||
{/**/}
|
.infinite-scroll-component__outerdiv {
|
||||||
{/* .infinite-scroll-component__outerdiv { */}
|
width: 100%;
|
||||||
{/* width: 100%; */}
|
height: 100%;
|
||||||
{/* height: 100%; */}
|
}
|
||||||
{/* } */}
|
|
||||||
{/**/}
|
::cue {
|
||||||
{/* ::cue { */}
|
background-color: transparent;
|
||||||
{/* background-color: transparent; */}
|
text-shadow:
|
||||||
{/* text-shadow: */}
|
-1px -1px 0 #000,
|
||||||
{/* -1px -1px 0 #000, */}
|
1px -1px 0 #000,
|
||||||
{/* 1px -1px 0 #000, */}
|
-1px 1px 0 #000,
|
||||||
{/* -1px 1px 0 #000, */}
|
1px 1px 0 #000;
|
||||||
{/* 1px 1px 0 #000; */}
|
}
|
||||||
{/* } */}
|
`}</style>
|
||||||
{/* `}</style> */}
|
|
||||||
{/* <WebTooltip theme={theme} /> */}
|
{/* <WebTooltip theme={theme} /> */}
|
||||||
{/* <SkeletonCss /> */}
|
{/* <SkeletonCss /> */}
|
||||||
{/* <TouchOnlyCss /> */}
|
{/* <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="64x64" href="/icon-64x64.png" />
|
||||||
<link rel="icon" type="image/png" sizes="128x128" href="/icon-128x128.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" />
|
<link rel="icon" type="image/png" sizes="256x256" href="/icon-256x256.png" />
|
||||||
{/* <GlobalCssTheme /> */}
|
<GlobalCssTheme />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body className="hoverEnabled">
|
<body className="hoverEnabled">
|
||||||
|
@ -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() {
|
export default function MyApp() {
|
||||||
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
{...css({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
minHeight: "100%",
|
minHeight: "100%",
|
||||||
}}
|
})}
|
||||||
>
|
>
|
||||||
<Text>Hello from One</Text>
|
<Text>Hello from One</Text>
|
||||||
</View>
|
</View>
|
||||||
|
@ -12,10 +12,7 @@
|
|||||||
"format": "biome format .",
|
"format": "biome format .",
|
||||||
"format:fix": "biome format . --write"
|
"format:fix": "biome format . --write"
|
||||||
},
|
},
|
||||||
"workspaces": ["packages/*"],
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kyoo/models": "workspace:*",
|
|
||||||
"@kyoo/primitives": "workspace:*",
|
|
||||||
"@tanstack/react-query": "^5.66.0",
|
"@tanstack/react-query": "^5.66.0",
|
||||||
"caniuse-api": "^3.0.0",
|
"caniuse-api": "^3.0.0",
|
||||||
"expo": "~52.0.28",
|
"expo": "~52.0.28",
|
||||||
|
@ -17,73 +17,3 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* 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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
@ -18,195 +18,3 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* 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);
|
|
||||||
};
|
|
||||||
|
69
front/src/primitives/theme/catppuccin.tsx
Normal file
69
front/src/primitives/theme/catppuccin.tsx
Normal file
@ -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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
1
front/src/primitives/theme/index.ts
Normal file
1
front/src/primitives/theme/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./theme";
|
193
front/src/primitives/theme/theme.tsx
Normal file
193
front/src/primitives/theme/theme.tsx
Normal file
@ -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);
|
||||||
|
};
|
||||||
|
|
@ -1,7 +1,8 @@
|
|||||||
// import { useUserTheme } from "@kyoo/models";
|
|
||||||
import { ThemeSelector } from "@kyoo/primitives";
|
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { ComponentType, type ReactNode, useState } from "react";
|
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 QueryProvider = ({ children }: { children: ReactNode }) => {
|
||||||
// const [queryClient] = useState(() => createQueryClient());
|
// const [queryClient] = useState(() => createQueryClient());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user