This commit is contained in:
Daniil
2026-04-04 14:51:40 +03:00
parent 10a1d28f77
commit 0523ef3d72
191 changed files with 12065 additions and 2658 deletions
@@ -0,0 +1,123 @@
"use client"
import type { components } from "@shared/api/__generated__/openapi.types"
import type { JSX } from "react"
import { FunctionComponent } from "react"
import cs from "classnames"
import styles from "./StylePreview.module.scss"
type CaptionStyleConfig = components["schemas"]["CaptionStyleConfig"]
interface IStylePreviewProps {
config?: CaptionStyleConfig | null
size?: "small" | "large"
className?: string
}
const SMALL_SCALE = 0.65
const buildContainerStyles = (
config: CaptionStyleConfig,
scale: number,
): React.CSSProperties => {
const bg = config.background
return {
backgroundColor: bg?.bg_color ?? "rgba(0,0,0,0.6)",
borderRadius: (bg?.bg_border_radius_px ?? 8) * scale,
padding: (bg?.bg_padding_px ?? 12) * scale,
...(bg?.bg_blur_px
? { backdropFilter: `blur(${bg.bg_blur_px * scale}px)` }
: {}),
...(bg?.bg_glow_color
? { boxShadow: `0 0 ${20 * scale}px ${bg.bg_glow_color}` }
: {}),
}
}
const buildTextStyles = (
config: CaptionStyleConfig,
scale: number,
): React.CSSProperties => {
const text = config.text
return {
fontFamily: text?.font_family ?? "Lobster",
fontSize: (text?.font_size ?? 40) * scale,
fontWeight: text?.font_weight ?? 400,
color: text?.text_color ?? "#FFFFFF",
textAlign:
(config.layout?.horizontal_alignment as "left" | "center" | "right") ??
"center",
...(text?.text_shadow ? { textShadow: text.text_shadow } : {}),
...(text?.text_stroke_width
? {
WebkitTextStroke: `${(text.text_stroke_width ?? 0) * scale}px ${text.text_stroke_color ?? "#000000"}`,
}
: {}),
}
}
const VERTICAL_MAP: Record<string, string> = {
top: "flex-start",
center: "center",
bottom: "flex-end",
}
const HORIZONTAL_MAP: Record<string, string> = {
left: "flex-start",
center: "center",
right: "flex-end",
}
const buildPositionStyles = (
config: CaptionStyleConfig,
scale: number,
): React.CSSProperties => {
const layout = config.layout
const vPos = layout?.vertical_position ?? "bottom"
const hAlign = layout?.horizontal_alignment ?? "center"
const padding = (layout?.padding_px ?? 20) * scale
return {
justifyContent: VERTICAL_MAP[vPos] ?? "flex-end",
alignItems: HORIZONTAL_MAP[hAlign] ?? "center",
padding,
}
}
export const StylePreview: FunctionComponent<IStylePreviewProps> = ({
config,
size = "small",
className,
}): JSX.Element => {
const safeConfig = config ?? {}
const highlightColor = safeConfig.text?.highlight_color ?? "#FFFF00"
const scale = size === "small" ? SMALL_SCALE : 1
return (
<div
className={cs(styles.root, styles[size], className)}
style={buildPositionStyles(safeConfig, scale)}
data-testid="StylePreview"
>
<div
style={{
...buildContainerStyles(safeConfig, scale),
maxWidth: "100%",
boxSizing: "border-box",
}}
>
<span
style={{
...buildTextStyles(safeConfig, scale),
wordBreak: "break-word",
}}
>
Пример <span style={{ color: highlightColor }}>субтитров</span>
</span>
</div>
</div>
)
}