w-funnel/src/components/ui/Typography/Typography.tsx
dev.daminik00 b57e99e472 merge
2025-09-28 04:41:13 +02:00

113 lines
2.9 KiB
TypeScript

import { createElement, JSX, ReactNode } from "react";
import { cva, VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
import { MarkupText } from "@/components/ui/MarkupText/MarkupText";
const typographyVariants = cva(cn("text-center text-foreground block"), {
variants: {
size: {
xs: "text-xs",
sm: "text-sm",
md: "text-base",
lg: "text-lg",
xl: "text-xl",
"2xl": "text-2xl",
"3xl": "text-3xl",
"4xl": "text-4xl",
},
weight: {
regular: "font-normal",
medium: "font-medium",
semiBold: "font-semibold",
bold: "font-bold",
extraBold: "font-extrabold",
black: "font-black",
},
color: {
default: "text-foreground",
primary: "text-primary-foreground",
secondary: "text-secondary-foreground",
destructive: "text-destructive",
success: "text-success",
card: "text-card-foreground",
accent: "text-accent-foreground",
muted: "text-muted-foreground",
},
align: {
center: "text-center",
left: "text-left",
right: "text-right",
},
font: {
manrope: "font-manrope",
inter: "font-inter",
geistSans: "font-geist-sans",
geistMono: "font-geist-mono",
},
},
defaultVariants: {
size: "md",
weight: "regular",
color: "default",
align: "left",
font: "manrope",
},
});
type TypographyElements = Pick<
JSX.IntrinsicElements,
"span" | "p" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "div"
>;
export type TypographyProps<T extends keyof TypographyElements = "span"> =
VariantProps<typeof typographyVariants> &
Omit<TypographyElements[T], "color"> & {
as?: T;
children: ReactNode;
enableMarkup?: boolean; // 🎨 Новый параметр для включения разметки
};
export default function Typography<
T extends keyof TypographyElements = "span"
>({
as: Component = "span" as T,
children,
className,
weight,
size,
color,
align,
font,
enableMarkup = false, // 🎨 По умолчанию выключена для обратной совместимости
...props
}: TypographyProps<T>) {
const classes = cn(
typographyVariants({ size, weight, color, align, font }),
className
);
// 🎨 Если включена разметка и это строка, используем MarkupText
if (enableMarkup && typeof children === 'string') {
return (
<MarkupText
as={Component}
className={classes}
boldClassName={weight === 'bold' ? undefined : 'font-bold'} // Наследуем стиль жирного текста
{...props}
>
{children}
</MarkupText>
);
}
// 🎨 Обычный рендеринг без разметки
return createElement(
Component,
{
className: classes,
...props,
},
children
);
}