diff --git a/front/packages/models/src/utils.ts b/front/packages/models/src/utils.ts index 6d3557de..51678098 100644 --- a/front/packages/models/src/utils.ts +++ b/front/packages/models/src/utils.ts @@ -42,6 +42,7 @@ export const getDisplayDate = (data: Show | Movie) => { if (airDate) { return airDate.getFullYear().toString(); } + return null; }; export const useLocalSetting = (setting: string, def: string) => { diff --git a/front/packages/primitives/src/avatar.tsx b/front/packages/primitives/src/avatar.tsx index a2bcea47..f4ac1721 100644 --- a/front/packages/primitives/src/avatar.tsx +++ b/front/packages/primitives/src/avatar.tsx @@ -23,6 +23,7 @@ import { type ComponentType, type RefAttributes, forwardRef } from "react"; import { Image, type ImageProps, View, type ViewStyle } from "react-native"; import { type Stylable, px, useYoshiki } from "yoshiki/native"; import { Icon } from "./icons"; +import { Skeleton } from "./skeleton"; import { P } from "./text"; const stringToColor = (string: string) => { @@ -40,7 +41,7 @@ const stringToColor = (string: string) => { return color; }; -export const Avatar = forwardRef< +const AvatarC = forwardRef< View, { src?: string; @@ -48,12 +49,11 @@ export const Avatar = forwardRef< size?: number; placeholder?: string; color?: string; - isLoading?: boolean; fill?: boolean; as?: ComponentType<{ style?: ViewStyle } & RefAttributes>; } & Stylable ->(function Avatar( - { src, alt, size = px(24), color, placeholder, isLoading = false, fill = false, as, ...props }, +>(function AvatarI( + { src, alt, size = px(24), color, placeholder, fill = false, as, ...props }, ref, ) { const { css, theme } = useYoshiki(); @@ -106,3 +106,22 @@ export const Avatar = forwardRef< ); }); + +const AvatarLoader = ({ size = px(24), ...props }: { size?: number }) => { + const { css } = useYoshiki(); + + return ( + + ); +}; + +export const Avatar = Object.assign(AvatarC, { Loader: AvatarLoader }); diff --git a/front/packages/primitives/src/chip.tsx b/front/packages/primitives/src/chip.tsx index a4930fb7..78d2d2c5 100644 --- a/front/packages/primitives/src/chip.tsx +++ b/front/packages/primitives/src/chip.tsx @@ -18,7 +18,7 @@ * along with Kyoo. If not, see . */ -import type { TextProps } from "react-native"; +import { type TextProps, View } from "react-native"; import { type Theme, px, rem, useYoshiki } from "yoshiki/native"; import { Link } from "./links"; import { Skeleton } from "./skeleton"; @@ -63,6 +63,7 @@ export const Chip = ({ pX: ts(2.5 * sizeMult), borderRadius: ts(3), overflow: "hidden", + justifyContent: "center", }, outline && { borderColor: color ?? ((theme: Theme) => theme.accent), @@ -102,3 +103,40 @@ export const Chip = ({ ); }; + +Chip.Loader = ({ + color, + size = "medium", + outline = false, + ...props +}: { color?: string; size?: "small" | "medium" | "large"; outline?: boolean }) => { + const { css } = useYoshiki(); + const sizeMult = size === "medium" ? 1 : size === "small" ? 0.5 : 1.5; + + return ( + theme.accent), + borderStyle: "solid", + borderWidth: px(1), + }, + !outline && { + bg: color ?? ((theme: Theme) => theme.accent), + }, + ], + props, + )} + > + + + ); +}; diff --git a/front/packages/primitives/src/icons.tsx b/front/packages/primitives/src/icons.tsx index 3c504c33..9421624a 100644 --- a/front/packages/primitives/src/icons.tsx +++ b/front/packages/primitives/src/icons.tsx @@ -45,7 +45,7 @@ type IconProps = { export const Icon = ({ icon: Icon, color, size = 24, ...props }: IconProps) => { const { css, theme } = useYoshiki(); const computed = css( - { width: size, height: size, fill: color ?? theme.contrast } as any, + { width: size, height: size, fill: color ?? theme.contrast, flexShrink: 0 } as any, props, ) as any; diff --git a/front/packages/primitives/src/image/image.tsx b/front/packages/primitives/src/image/image.tsx index a117d76d..cfa14c69 100644 --- a/front/packages/primitives/src/image/image.tsx +++ b/front/packages/primitives/src/image/image.tsx @@ -19,7 +19,7 @@ */ import { getCurrentToken } from "@kyoo/models"; -import { useState } from "react"; +import { type ReactElement, useState } from "react"; import { type FlexStyle, type ImageStyle, View, type ViewStyle } from "react-native"; import { Blurhash } from "react-native-blurhash"; import FastImage from "react-native-fast-image"; @@ -93,3 +93,10 @@ export const Image = ({ ); }; + +Image.Loader = ({ layout, ...props }: { layout: ImageLayout; children?: ReactElement }) => { + const { css } = useYoshiki(); + const border = { borderRadius: 6, overflow: "hidden" } satisfies ViewStyle; + + return ; +}; diff --git a/front/packages/primitives/src/image/image.web.tsx b/front/packages/primitives/src/image/image.web.tsx index 3c5f6514..77fb650b 100644 --- a/front/packages/primitives/src/image/image.web.tsx +++ b/front/packages/primitives/src/image/image.web.tsx @@ -19,7 +19,7 @@ */ import NextImage from "next/image"; -import { useState } from "react"; +import { type ReactElement, useState } from "react"; import { type ImageStyle, View, type ViewStyle } from "react-native"; import { useYoshiki } from "yoshiki/native"; import { imageBorderRadius } from "../constants"; @@ -73,3 +73,10 @@ export const Image = ({ ); }; + +Image.Loader = ({ layout, ...props }: { layout: ImageLayout; children?: ReactElement }) => { + const { css } = useYoshiki(); + const border = { borderRadius: 6, overflow: "hidden" } satisfies ViewStyle; + + return ; +}; diff --git a/front/packages/primitives/src/image/index.tsx b/front/packages/primitives/src/image/index.tsx index daffe995..9eea507f 100644 --- a/front/packages/primitives/src/image/index.tsx +++ b/front/packages/primitives/src/image/index.tsx @@ -19,7 +19,7 @@ */ import { LinearGradient, type LinearGradientProps } from "expo-linear-gradient"; -import type { ComponentProps, ComponentType, ReactNode } from "react"; +import type { ComponentProps, ComponentType, ReactElement, ReactNode } from "react"; import { type ImageStyle, View, type ViewProps, type ViewStyle } from "react-native"; import { percent } from "yoshiki/native"; import { imageBorderRadius } from "../constants"; @@ -39,6 +39,14 @@ export const Poster = ({ layout: YoshikiEnhanced<{ width: ImageStyle["width"] } | { height: ImageStyle["height"] }>; }) => {alt!}; +Poster.Loader = ({ + layout, + ...props +}: { + children?: ReactElement; + layout: YoshikiEnhanced<{ width: ImageStyle["width"] } | { height: ImageStyle["height"] }>; +}) => ; + export const PosterBackground = ({ alt, layout, @@ -86,7 +94,7 @@ export const ImageBackground = ({ {({ css, theme }) => ( diff --git a/front/packages/primitives/src/skeleton.tsx b/front/packages/primitives/src/skeleton.tsx index d6336b75..3470a75d 100644 --- a/front/packages/primitives/src/skeleton.tsx +++ b/front/packages/primitives/src/skeleton.tsx @@ -19,11 +19,10 @@ */ import { LinearGradient as LG } from "expo-linear-gradient"; -import { AnimatePresence, MotiView, motify } from "moti"; +import { MotiView, motify } from "moti"; import { useState } from "react"; import { Platform, View, type ViewProps } from "react-native"; import { em, percent, px, rem, useYoshiki } from "yoshiki/native"; -import { hiddenIfNoJs } from "./utils/nojs"; const LinearGradient = motify(LG)(); @@ -99,71 +98,59 @@ export const Skeleton = ({ props, )} > - - {children} - {(forcedShow || !children || children === true) && - [...Array(lines)].map((_, i) => ( - setWidth(e.nativeEvent.layout.width)} - {...css( - [ - { - bg: (theme) => theme.overlay0, - }, - lines === 1 && { - position: "absolute", - top: 0, - bottom: 0, - left: 0, - right: 0, - }, - lines !== 1 && { - width: i === lines - 1 ? percent(40) : percent(100), - height: rem(1.2), - marginBottom: rem(0.5), - overflow: "hidden", - borderRadius: px(6), - }, - ], - hiddenIfNoJs, - )} - > - - - ))} - + {(forcedShow || !children || children === true) && + [...Array(lines)].map((_, i) => ( + setWidth(e.nativeEvent.layout.width)} + {...css([ + { + bg: (theme) => theme.overlay0, + }, + lines === 1 && { + position: "absolute", + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + lines !== 1 && { + width: i === lines - 1 ? percent(40) : percent(100), + height: rem(1.2), + marginBottom: rem(0.5), + overflow: "hidden", + borderRadius: px(6), + }, + ])} + > + + + ))} + {children} ); }; diff --git a/front/packages/primitives/src/skeleton.web.tsx b/front/packages/primitives/src/skeleton.web.tsx index f322cac0..318e9aa7 100644 --- a/front/packages/primitives/src/skeleton.web.tsx +++ b/front/packages/primitives/src/skeleton.web.tsx @@ -21,7 +21,6 @@ import { LinearGradient } from "expo-linear-gradient"; import { View, type ViewProps } from "react-native"; import { em, percent, px, rem, useYoshiki } from "yoshiki/native"; -import { hiddenIfNoJs } from "./utils/nojs"; export const SkeletonCss = () => (