mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
rename
This commit is contained in:
1 parent
ed92440b94
commit
f85d097c16
44 files changed
+5
-5
No files matched your search
@@ -0,0 +1,288 @@
|
||||
import {
|
||||
CodeIcon,
|
||||
HeightIcon,
|
||||
ImageIcon,
|
||||
ResetIcon,
|
||||
TimerIcon,
|
||||
WidthIcon,
|
||||
} from "@radix-ui/react-icons";
|
||||
import { Box, Button, Flex, Heading, ScrollArea, Text } from "@radix-ui/themes";
|
||||
import { useEffect, useRef, useState, type ReactNode } from "react";
|
||||
import { CopyButton } from "../../../../components/CopyButton";
|
||||
import { Boolean } from "../../../../components/Embeds/Boolean";
|
||||
import { Color } from "../../../../components/Embeds/Color";
|
||||
import { Enum } from "../../../../components/Embeds/Enum";
|
||||
import { GenerateURL } from "../../../../components/Embeds/GenerateURL";
|
||||
import { Import } from "../../../../components/Embeds/Import";
|
||||
import { PreviewWrapper } from "../../../../components/Embeds/PreviewWrapper";
|
||||
import { Radius } from "../../../../components/Embeds/Radius";
|
||||
import { RichText } from "../../../../components/Embeds/RichText";
|
||||
import { Size } from "../../../../components/Embeds/Size";
|
||||
import { SizeWithout0 } from "../../../../components/Embeds/SizeWithout0";
|
||||
import { Slider } from "../../../../components/Embeds/Slider";
|
||||
import { TextController } from "../../../../components/Embeds/TextController";
|
||||
import { PageWrapper } from "../../../../components/PageWrapper";
|
||||
import {
|
||||
embedConfigurations,
|
||||
extractEmbedConfigDefaults,
|
||||
} from "../../../../constants/embeds";
|
||||
import { NAVBAR_HEIGHT } from "../../../../constants/navbar";
|
||||
import {
|
||||
LocaleProvider,
|
||||
useLocale,
|
||||
type LocaleAcceptorProps,
|
||||
} from "../../../../hooks/useLocale";
|
||||
import { EmbedState, type EmbedConfig } from "../../../../stores/embedState";
|
||||
import { EmbedItemType } from "../../../../stores/embedState/constants";
|
||||
|
||||
export interface EmbedPreviewControllerProps {
|
||||
configKey: string;
|
||||
}
|
||||
|
||||
interface PageProps {
|
||||
embed: keyof typeof embedConfigurations;
|
||||
}
|
||||
|
||||
export function Page({ embed, locale }: PageProps & LocaleAcceptorProps) {
|
||||
const config = embedConfigurations[embed];
|
||||
|
||||
EmbedState.useInitialization(extractEmbedConfigDefaults(config));
|
||||
|
||||
return (
|
||||
<LocaleProvider locale={locale}>
|
||||
<Content embed={embed} />
|
||||
</LocaleProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function Content({ embed }: PageProps) {
|
||||
const config = embedConfigurations[embed] as EmbedConfig;
|
||||
const [backgroundImage, setBackgroundImage] = useState(
|
||||
"/assets/images/backgrounds/embed-default.webp"
|
||||
);
|
||||
const fileInput = useRef<HTMLInputElement>(null!);
|
||||
const { strings } = useLocale();
|
||||
|
||||
useEffect(() => {
|
||||
fileInput.current = document.createElement("input");
|
||||
fileInput.current.type = "file";
|
||||
fileInput.current.style.display = "none";
|
||||
fileInput.current.accept = "image/*";
|
||||
fileInput.current.onchange = (event) => {
|
||||
const file = (event.target as HTMLInputElement).files?.[0];
|
||||
if (!file) return;
|
||||
setBackgroundImage(URL.createObjectURL(file));
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PageWrapper padding="0" maxWidth="104rem" color="red">
|
||||
<Flex>
|
||||
<ScrollArea
|
||||
scrollbars="vertical"
|
||||
style={{ height: "100%", maxWidth: 320 }}
|
||||
>
|
||||
<Flex direction="column" gap="2" p="4">
|
||||
<Import />
|
||||
|
||||
<Heading>
|
||||
{strings.website.tools.embed.configuration.export.title}
|
||||
</Heading>
|
||||
<Text size="2" color="gray" mb="2">
|
||||
{strings.website.tools.embed.configuration.export.description}
|
||||
</Text>
|
||||
|
||||
<Flex mb="6" gap="2" wrap="wrap">
|
||||
<GenerateURL embed={embed} />
|
||||
|
||||
<CopyButton
|
||||
variant="outline"
|
||||
copy={() =>
|
||||
"body { margin: 0; background-color: transparent; overflow: hidden; }"
|
||||
}
|
||||
>
|
||||
<CodeIcon />
|
||||
{strings.website.tools.embed.configuration.export.css}
|
||||
</CopyButton>
|
||||
<CopyButton
|
||||
variant="outline"
|
||||
copy={() => `${EmbedState.state.width}`}
|
||||
>
|
||||
<WidthIcon />
|
||||
{strings.website.tools.embed.configuration.export.width}
|
||||
</CopyButton>
|
||||
<CopyButton
|
||||
variant="outline"
|
||||
copy={() => `${EmbedState.state.height}`}
|
||||
>
|
||||
<HeightIcon />
|
||||
{strings.website.tools.embed.configuration.export.height}
|
||||
</CopyButton>
|
||||
<CopyButton variant="outline" copy={() => "1"}>
|
||||
<TimerIcon />
|
||||
{strings.website.tools.embed.configuration.export.framerate}
|
||||
</CopyButton>
|
||||
</Flex>
|
||||
|
||||
<Flex justify="between" align="center">
|
||||
<Heading>
|
||||
{strings.website.tools.embed.configuration.customize.title}
|
||||
</Heading>
|
||||
<Button
|
||||
color="red"
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
EmbedState.set(EmbedState.initial);
|
||||
}}
|
||||
>
|
||||
<ResetIcon />{" "}
|
||||
{strings.website.tools.embed.configuration.customize.reset}
|
||||
</Button>
|
||||
</Flex>
|
||||
<Text size="2" color="gray" mb="2">
|
||||
{strings.website.tools.embed.configuration.customize.description}
|
||||
</Text>
|
||||
|
||||
{Object.keys(config).map((configKey) => {
|
||||
const item = config[configKey];
|
||||
let control: ReactNode;
|
||||
let oneLiner = false;
|
||||
|
||||
switch (item.type) {
|
||||
case EmbedItemType.Boolean: {
|
||||
control = <Boolean configKey={configKey} />;
|
||||
oneLiner = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedItemType.Color: {
|
||||
control = <Color configKey={configKey} />;
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedItemType.Radius: {
|
||||
control = <Radius configKey={configKey} />;
|
||||
oneLiner = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedItemType.Size: {
|
||||
control = <Size configKey={configKey} />;
|
||||
oneLiner = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedItemType.SizeWithout0: {
|
||||
control = <SizeWithout0 configKey={configKey} />;
|
||||
oneLiner = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedItemType.Slider: {
|
||||
control = <Slider configKey={configKey} config={item} />;
|
||||
oneLiner = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedItemType.String: {
|
||||
control = <TextController configKey={configKey} />;
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedItemType.RichText: {
|
||||
control = <RichText configKey={configKey} />;
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedItemType.Enum: {
|
||||
control = <Enum configKey={configKey} config={item} />;
|
||||
oneLiner = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex
|
||||
key={configKey}
|
||||
direction={oneLiner ? undefined : "column"}
|
||||
gap={oneLiner ? "2" : "1"}
|
||||
justify={oneLiner ? "between" : undefined}
|
||||
mb={oneLiner ? "2" : "4"}
|
||||
pb={item.pad ? "6" : undefined}
|
||||
>
|
||||
<Text>
|
||||
{
|
||||
(
|
||||
strings.website.tools.embed.types[embed]
|
||||
.options as Record<string, string>
|
||||
)[configKey]
|
||||
}
|
||||
</Text>
|
||||
<Flex
|
||||
gap="2"
|
||||
align="center"
|
||||
flexGrow="1"
|
||||
justify={oneLiner ? "end" : undefined}
|
||||
>
|
||||
{control}
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
</ScrollArea>
|
||||
|
||||
<Box
|
||||
p="4"
|
||||
flexGrow="1"
|
||||
position="sticky"
|
||||
top={`${NAVBAR_HEIGHT}px`}
|
||||
height={`calc(100vh - ${NAVBAR_HEIGHT}px)`}
|
||||
>
|
||||
<Flex
|
||||
direction="column"
|
||||
height="100%"
|
||||
style={{
|
||||
borderRadius: "var(--radius-3)",
|
||||
overflow: "hidden",
|
||||
boxShadow: "var(--shadow-3)",
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
justify="between"
|
||||
align="center"
|
||||
p="2"
|
||||
pl="3"
|
||||
style={{
|
||||
backgroundColor: "var(--color-panel-solid)",
|
||||
}}
|
||||
>
|
||||
<Text color="gray">
|
||||
{strings.website.tools.embed.preview.title}
|
||||
</Text>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
color="gray"
|
||||
onClick={() => fileInput.current?.click()}
|
||||
>
|
||||
<ImageIcon /> {strings.website.tools.embed.preview.upload}
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
<Box
|
||||
flexGrow="1"
|
||||
style={{
|
||||
background: `url(${backgroundImage}) center / cover no-repeat`,
|
||||
}}
|
||||
position="relative"
|
||||
overflow="hidden"
|
||||
>
|
||||
<PreviewWrapper name={embed} />
|
||||
</Box>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Flex>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import { Box } from "@radix-ui/themes";
|
||||
import { useMemo } from "react";
|
||||
import { parse } from "urlon";
|
||||
import { BlitzKitTheme } from "../../../../../components/BlitzKitTheme";
|
||||
import {
|
||||
embedConfigurations,
|
||||
embedRenderers,
|
||||
extractEmbedConfigDefaults,
|
||||
} from "../../../../../constants/embeds";
|
||||
import {
|
||||
LocaleProvider,
|
||||
type LocaleAcceptorProps,
|
||||
} from "../../../../../hooks/useLocale";
|
||||
import {
|
||||
EmbedState,
|
||||
type EmbedConfig,
|
||||
type ExtractEmbedConfigTypes,
|
||||
} from "../../../../../stores/embedState";
|
||||
import { useEmbedStateCurry } from "../../../../../stores/embedState/utilities";
|
||||
|
||||
interface PageProps {
|
||||
embed: keyof typeof embedConfigurations;
|
||||
}
|
||||
|
||||
export function Page({ embed, locale }: PageProps & LocaleAcceptorProps) {
|
||||
const state = useMemo(() => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const stateRaw = params.get("state");
|
||||
const partialState = stateRaw === null ? {} : parse(stateRaw);
|
||||
const state = {
|
||||
...extractEmbedConfigDefaults(embedConfigurations[embed]),
|
||||
...partialState,
|
||||
} as ExtractEmbedConfigTypes<EmbedConfig>;
|
||||
|
||||
return state;
|
||||
}, [embed]);
|
||||
|
||||
EmbedState.useInitialization(state);
|
||||
|
||||
return (
|
||||
<LocaleProvider locale={locale}>
|
||||
<Content embed={embed} />
|
||||
</LocaleProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function Content({ embed }: PageProps) {
|
||||
const Renderer = embedRenderers[embed];
|
||||
const { useEmbedState } = useEmbedStateCurry();
|
||||
const width = useEmbedState("width");
|
||||
const height = useEmbedState("height");
|
||||
|
||||
return (
|
||||
<BlitzKitTheme style={{ background: "transparent" }}>
|
||||
<Box width={`${width}px`} height={`${height}px`} overflow="hidden">
|
||||
<Renderer />
|
||||
</Box>
|
||||
</BlitzKitTheme>
|
||||
);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
---
|
||||
import EmbedLayout from "../../../../../layouts/EmbedLayout.astro";
|
||||
import type { getStaticPaths } from "../index.astro";
|
||||
import { Page } from "./_index";
|
||||
|
||||
export { getStaticPaths } from "../index.astro";
|
||||
|
||||
const { locale } = Astro.props;
|
||||
---
|
||||
|
||||
<EmbedLayout>
|
||||
<Page {locale} client:only="react" embed={Astro.params.embed} />
|
||||
</EmbedLayout>
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
import { AstroSeo } from "@astrolib/seo";
|
||||
import type { GetStaticPaths } from "astro";
|
||||
import { capitalize } from "lodash-es";
|
||||
import { embedConfigurations } from "../../../../constants/embeds";
|
||||
import BaseLayout from "../../../../layouts/BaseLayout.astro";
|
||||
import { getStaticPaths as parentGetStaticPaths } from "../index.astro";
|
||||
import { Page } from "./_index";
|
||||
|
||||
export const getStaticPaths = (() => {
|
||||
const parentPaths = parentGetStaticPaths();
|
||||
|
||||
return Object.keys(embedConfigurations)
|
||||
.map((embed) =>
|
||||
parentPaths.map((parent) => ({
|
||||
params: {
|
||||
...parent.params,
|
||||
embed: embed as keyof typeof embedConfigurations,
|
||||
},
|
||||
}))
|
||||
)
|
||||
.flat();
|
||||
}) satisfies GetStaticPaths;
|
||||
|
||||
const name = capitalize(Astro.params.embed);
|
||||
const title = `BlitzKit - ${name} embed`;
|
||||
const description = `BlitzKit ${name} embeds for streaming World of Tanks Blitz with extreme customization`;
|
||||
const { locale } = Astro.props;
|
||||
---
|
||||
|
||||
<AstroSeo
|
||||
title={title}
|
||||
description={description}
|
||||
canonical={Astro.url.href}
|
||||
openGraph={{
|
||||
url: Astro.url.href,
|
||||
title,
|
||||
description,
|
||||
site_name: "BlitzKit",
|
||||
}}
|
||||
twitter={{ cardType: "summary_large_image" }}
|
||||
/>
|
||||
|
||||
<style is:global>
|
||||
@keyframes fade-out-border {
|
||||
from {
|
||||
outline: 1rem solid #ff0000ff;
|
||||
}
|
||||
to {
|
||||
outline: 0.75rem solid #ff000000;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-container-animated {
|
||||
animation: fade-out-border 0.5s linear;
|
||||
}
|
||||
|
||||
.preview-container-animated:hover {
|
||||
outline: 1rem solid #ff000080;
|
||||
}
|
||||
</style>
|
||||
|
||||
<BaseLayout {locale}>
|
||||
<Page {locale} client:load embed={Astro.params.embed} />
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,92 @@
|
||||
import { Box, Flex, Link, Text } from "@radix-ui/themes";
|
||||
import { PreviewWrapper } from "../../../components/Embeds/PreviewWrapper";
|
||||
import { LinkI18n } from "../../../components/LinkI18n";
|
||||
import { PageWrapper } from "../../../components/PageWrapper";
|
||||
import { embedConfigurations } from "../../../constants/embeds";
|
||||
import { Var } from "../../../core/radix/var";
|
||||
import {
|
||||
type LocaleAcceptorProps,
|
||||
LocaleProvider,
|
||||
useLocale,
|
||||
} from "../../../hooks/useLocale";
|
||||
|
||||
export function Page({ locale }: LocaleAcceptorProps) {
|
||||
return (
|
||||
<LocaleProvider locale={locale}>
|
||||
<Content />
|
||||
</LocaleProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function Content() {
|
||||
const { locale, strings } = useLocale();
|
||||
|
||||
return (
|
||||
<PageWrapper color="red">
|
||||
<Text align="center" mt="3">
|
||||
{strings.website.tools.embed.coming_soon}{" "}
|
||||
<Link
|
||||
underline="always"
|
||||
href="https://discord.gg/nDt7AjGJQH"
|
||||
target="_blank"
|
||||
>
|
||||
{strings.website.tools.embed.suggest}
|
||||
</Link>
|
||||
</Text>
|
||||
|
||||
<Flex justify="center">
|
||||
{Object.keys(embedConfigurations).map((embed) => (
|
||||
<LinkI18n
|
||||
locale={locale}
|
||||
href={`/embed/${embed}`}
|
||||
color="gray"
|
||||
highContrast
|
||||
style={{
|
||||
width: "fit-content",
|
||||
height: "fit-content",
|
||||
}}
|
||||
underline="hover"
|
||||
>
|
||||
<Flex
|
||||
direction="column"
|
||||
overflow="hidden"
|
||||
style={{
|
||||
borderRadius: Var("radius-4"),
|
||||
backgroundColor: Var("color-panel-solid"),
|
||||
boxShadow: Var("shadow-3"),
|
||||
}}
|
||||
>
|
||||
<Flex justify="center" p="2">
|
||||
<Text>
|
||||
{
|
||||
strings.website.tools.embed.types[
|
||||
embed as keyof typeof strings.website.tools.embed.types
|
||||
].name
|
||||
}
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
<Box
|
||||
width="20rem"
|
||||
height="20rem"
|
||||
overflow="hidden"
|
||||
position="relative"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(/assets/images/backgrounds/embed-default.webp)",
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
}}
|
||||
>
|
||||
<PreviewWrapper
|
||||
naked
|
||||
name={embed as keyof typeof embedConfigurations}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
</LinkI18n>
|
||||
))}
|
||||
</Flex>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
import { tools } from "../../../constants/tools";
|
||||
import ToolLayout from "../../../layouts/ToolLayout.astro";
|
||||
import { Page } from "./_index";
|
||||
|
||||
export { getStaticPaths } from "../index.astro";
|
||||
|
||||
const { locale } = Astro.props;
|
||||
---
|
||||
|
||||
<ToolLayout {locale} tool={tools.embed}>
|
||||
<Page {locale} />
|
||||
</ToolLayout>
|
||||
Reference in new issue
Block a user