mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: start of embeds
This commit is contained in:
1 parent
f666023bef
commit
6984794be1
23 files changed
+313
-30
No files matched your search
+25
-21
@@ -28,7 +28,7 @@ const robotoFlex = Roboto_Flex({
|
||||
|
||||
export default function RootLayout({ children }: RootLayoutProps) {
|
||||
const pathname = usePathname();
|
||||
const isEmbed = pathname.split('/')[1] === 'embeds';
|
||||
const isEmbed = pathname.startsWith('/tools/embed/host');
|
||||
const isRoot = pathname === '/';
|
||||
|
||||
return (
|
||||
@@ -56,30 +56,34 @@ export default function RootLayout({ children }: RootLayoutProps) {
|
||||
backgroundColor: isEmbed ? 'transparent' : undefined,
|
||||
}}
|
||||
>
|
||||
<Theme
|
||||
appearance="dark"
|
||||
panelBackground="solid"
|
||||
radius="full"
|
||||
accentColor="amber"
|
||||
suppressHydrationWarning
|
||||
suppressContentEditableWarning
|
||||
>
|
||||
<Flex
|
||||
direction="column"
|
||||
style={{
|
||||
minHeight: '100vh',
|
||||
paddingTop: isEmbed ? undefined : NAVBAR_HEIGHT,
|
||||
}}
|
||||
{!isEmbed && (
|
||||
<Theme
|
||||
appearance="dark"
|
||||
panelBackground="solid"
|
||||
radius="full"
|
||||
accentColor="amber"
|
||||
suppressHydrationWarning
|
||||
suppressContentEditableWarning
|
||||
>
|
||||
{!isEmbed && <Navbar />}
|
||||
<Flex
|
||||
direction="column"
|
||||
style={{
|
||||
minHeight: '100vh',
|
||||
paddingTop: isEmbed ? undefined : NAVBAR_HEIGHT,
|
||||
}}
|
||||
>
|
||||
{!isEmbed && <Navbar />}
|
||||
|
||||
<Checks />
|
||||
<Checks />
|
||||
|
||||
<Suspense fallback={<PageLoader />}>{children}</Suspense>
|
||||
<Suspense fallback={<PageLoader />}>{children}</Suspense>
|
||||
|
||||
{!isEmbed && <Footer />}
|
||||
</Flex>
|
||||
</Theme>
|
||||
{!isEmbed && <Footer />}
|
||||
</Flex>
|
||||
</Theme>
|
||||
)}
|
||||
|
||||
{isEmbed && children}
|
||||
</body>
|
||||
</html>
|
||||
</App.Provider>
|
||||
|
||||
+7
-5
@@ -1,10 +1,11 @@
|
||||
'use client';
|
||||
|
||||
import { Flex } from '@radix-ui/themes';
|
||||
import { Box, Flex } from '@radix-ui/themes';
|
||||
import { AdMidSectionResponsive } from '../components/AdMidSectionResponsive';
|
||||
import {
|
||||
compareTool,
|
||||
discordTool,
|
||||
embedTool,
|
||||
moreTool,
|
||||
ratingTool,
|
||||
sessionTool,
|
||||
@@ -43,7 +44,7 @@ export default function Page() {
|
||||
|
||||
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
|
||||
<ToolCard tool={sessionTool} />
|
||||
<ToolCard tool={ratingTool} />
|
||||
<ToolCard tool={embedTool} />
|
||||
</Flex>
|
||||
|
||||
{!exempt && (
|
||||
@@ -59,13 +60,14 @@ export default function Page() {
|
||||
)}
|
||||
|
||||
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
|
||||
<ToolCard tool={ratingTool} />
|
||||
<ToolCard tool={discordTool} />
|
||||
<ToolCard tool={moreTool} />
|
||||
</Flex>
|
||||
|
||||
{/* <Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
|
||||
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
|
||||
<ToolCard tool={moreTool} />
|
||||
<Box flexGrow="1" />
|
||||
</Flex> */}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
'use client';
|
||||
|
||||
import { Flex } from '@radix-ui/themes';
|
||||
import { Dispatch, SetStateAction, use, useState } from 'react';
|
||||
import { EmbedConfigInputs } from '../../../../../components/EmbedConfigInputs';
|
||||
import PageWrapper from '../../../../../components/PageWrapper';
|
||||
import {
|
||||
TanksEmbedCard,
|
||||
TanksEmbedWrapper,
|
||||
} from '../../../../../components/TanksEmbed';
|
||||
import { tanksDefinitionsArray } from '../../../../../core/blitzkit/tankDefinitions';
|
||||
import {
|
||||
EmbedConfig,
|
||||
EmbedConfigType,
|
||||
ExtractEmbedConfigType,
|
||||
} from '../../types';
|
||||
import { extractEmbedConfigDefaults } from '../../utilities';
|
||||
|
||||
const tankEmbedConfig = {
|
||||
listWidth: { type: EmbedConfigType.Number, default: 320, unit: 'px' },
|
||||
listGap: { type: EmbedConfigType.Size, default: '2' },
|
||||
listMaxTanks: { type: EmbedConfigType.Number, default: 8 },
|
||||
|
||||
cardRadius: { type: EmbedConfigType.Radius, default: '2' },
|
||||
cardHeaderPadding: { type: EmbedConfigType.Size, default: '2' },
|
||||
} satisfies EmbedConfig;
|
||||
|
||||
export type TanksEmbedState = ExtractEmbedConfigType<typeof tankEmbedConfig>;
|
||||
|
||||
export default function Page() {
|
||||
const tanks = use(tanksDefinitionsArray);
|
||||
const [state, setState] = useState(
|
||||
extractEmbedConfigDefaults(tankEmbedConfig),
|
||||
);
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
<Flex align="start" justify="between" gap="4">
|
||||
<TanksEmbedWrapper state={state}>
|
||||
{tanks.slice(0, state.listMaxTanks).map((tank) => (
|
||||
<TanksEmbedCard key={tank.id} tank={tank} state={state} />
|
||||
))}
|
||||
</TanksEmbedWrapper>
|
||||
|
||||
<EmbedConfigInputs
|
||||
config={tankEmbedConfig}
|
||||
state={state}
|
||||
setState={
|
||||
setState as Dispatch<
|
||||
SetStateAction<ExtractEmbedConfigType<EmbedConfig>>
|
||||
>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import PageWrapper from '../../../components/PageWrapper';
|
||||
|
||||
export default function Page() {
|
||||
return <PageWrapper></PageWrapper>;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
export enum EmbedConfigType {
|
||||
Number,
|
||||
Radius,
|
||||
Size,
|
||||
}
|
||||
|
||||
export type EmbedConfig = Record<string, EmbedConfigItem>;
|
||||
|
||||
export type EmbedConfigItem =
|
||||
| {
|
||||
type: EmbedConfigType.Number;
|
||||
default: number;
|
||||
unit?: string;
|
||||
}
|
||||
| {
|
||||
type: EmbedConfigType.Radius;
|
||||
default: RadixRadius;
|
||||
}
|
||||
| {
|
||||
type: EmbedConfigType.Size;
|
||||
default: RadixSize;
|
||||
};
|
||||
|
||||
export type RadixRadius = `${1 | 2 | 3 | 4}` | 'full';
|
||||
export type RadixSize = `${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`;
|
||||
|
||||
export type ExtractEmbedConfigType<Config extends EmbedConfig> = {
|
||||
[Key in keyof Config]: ({
|
||||
type: Config[Key]['type'];
|
||||
} & EmbedConfigItem)['default'];
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { EmbedConfig, ExtractEmbedConfigType } from './types';
|
||||
|
||||
export function extractEmbedConfigDefaults<Config extends EmbedConfig>(
|
||||
config: Config,
|
||||
) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(config).map(([key, value]) => [key, value.default]),
|
||||
) as ExtractEmbedConfigType<Config>;
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,115 @@
|
||||
import { Flex, Select, Text, TextField } from '@radix-ui/themes';
|
||||
import { produce } from 'immer';
|
||||
import { capitalize, startCase, times } from 'lodash';
|
||||
import { Dispatch, SetStateAction, useCallback } from 'react';
|
||||
import {
|
||||
EmbedConfig,
|
||||
EmbedConfigType,
|
||||
ExtractEmbedConfigType,
|
||||
RadixRadius,
|
||||
RadixSize,
|
||||
} from '../app/tools/embed/types';
|
||||
|
||||
interface EmbedConfigInputsProps {
|
||||
config: EmbedConfig;
|
||||
state: ExtractEmbedConfigType<EmbedConfig>;
|
||||
setState: Dispatch<SetStateAction<ExtractEmbedConfigType<EmbedConfig>>>;
|
||||
}
|
||||
|
||||
export function EmbedConfigInputs({
|
||||
config,
|
||||
state,
|
||||
setState,
|
||||
}: EmbedConfigInputsProps) {
|
||||
const mutateState = useCallback(
|
||||
(recipe: (draft: ExtractEmbedConfigType<EmbedConfig>) => void) => {
|
||||
setState(produce(recipe));
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="2" align="end">
|
||||
{Object.entries(config).map(([key, setting]) => {
|
||||
const name = capitalize(startCase(key));
|
||||
|
||||
switch (setting.type) {
|
||||
case EmbedConfigType.Number: {
|
||||
return (
|
||||
<Flex align="center" gap="2">
|
||||
<Text>{name}</Text>
|
||||
<TextField.Root
|
||||
style={{ width: 96 }}
|
||||
type="number"
|
||||
value={state[key]}
|
||||
onChange={(event) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = (
|
||||
event.target as HTMLInputElement
|
||||
).valueAsNumber;
|
||||
});
|
||||
}}
|
||||
>
|
||||
{setting.unit && (
|
||||
<TextField.Slot side="right">px</TextField.Slot>
|
||||
)}
|
||||
</TextField.Root>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
case EmbedConfigType.Size: {
|
||||
return (
|
||||
<Flex align="center" gap="2">
|
||||
<Text>{name}</Text>
|
||||
<Select.Root
|
||||
value={state[key] as RadixSize}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixSize;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(10, (index) => (
|
||||
<Select.Item key={index} value={`${index}`}>
|
||||
{index}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
case EmbedConfigType.Radius: {
|
||||
return (
|
||||
<Flex align="center" gap="2">
|
||||
<Text>Card radius</Text>
|
||||
<Select.Root
|
||||
value={state[key] as RadixRadius}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixRadius;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(5, (index) => (
|
||||
<Select.Item key={index} value={`${index}`}>
|
||||
{index}
|
||||
</Select.Item>
|
||||
))}
|
||||
<Select.Item value="full">Full</Select.Item>
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
}
|
||||
})}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -34,11 +34,11 @@ export function Party3() {
|
||||
/> */}
|
||||
|
||||
{/* pub center */}
|
||||
<script
|
||||
{/* <script
|
||||
async
|
||||
src="https://adsdk.microsoft.com/mmnow/sdk.js?siteId=364645&publisherId=253617120"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
/> */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { Flex } from '@radix-ui/themes';
|
||||
import { ReactNode } from 'react';
|
||||
import { TanksEmbedState } from '../app/tools/embed/customize/tanks/page';
|
||||
import { TankDefinition } from '../core/blitzkit/tankDefinitions';
|
||||
|
||||
interface TanksEmbedWrapperProps {
|
||||
children: ReactNode;
|
||||
state: TanksEmbedState;
|
||||
}
|
||||
|
||||
export function TanksEmbedWrapper({ children, state }: TanksEmbedWrapperProps) {
|
||||
return (
|
||||
<Flex direction="column" gap={state.listGap} width={`${state.listWidth}px`}>
|
||||
{children}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
interface TanksEmbedCardProps {
|
||||
tank: TankDefinition;
|
||||
state: TanksEmbedState;
|
||||
}
|
||||
|
||||
export function TanksEmbedCard({ tank, state }: TanksEmbedCardProps) {
|
||||
return (
|
||||
<Flex
|
||||
direction="column"
|
||||
style={{
|
||||
borderRadius: `var(--radius-${state.cardRadius})`,
|
||||
overflow: 'hidden',
|
||||
backgroundColor: 'var(--color-panel-solid)',
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
justify="center"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-panel-translucent)',
|
||||
}}
|
||||
p={state.cardHeaderPadding}
|
||||
>
|
||||
{tank.name}
|
||||
</Flex>
|
||||
<Flex>asd</Flex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
+16
-2
@@ -108,8 +108,8 @@ export const playerStatsTool: Tool = {
|
||||
};
|
||||
|
||||
export const tankPerformanceTool: Tool = {
|
||||
id: 'tank-performance',
|
||||
title: 'Tank performance',
|
||||
id: 'performance',
|
||||
title: 'Performance',
|
||||
description: 'Tank performance statistics',
|
||||
pageDescription: 'Best tanks and their performances in World of Tanks Blitz',
|
||||
button: {
|
||||
@@ -119,12 +119,26 @@ export const tankPerformanceTool: Tool = {
|
||||
image: 'vOKFB03',
|
||||
};
|
||||
|
||||
export const embedTool: Tool = {
|
||||
id: 'embed',
|
||||
title: 'Embed',
|
||||
description: 'Embeds for streaming',
|
||||
pageDescription:
|
||||
'Create embeds for streaming World of Tanks Blitz with extreme customization',
|
||||
button: {
|
||||
text: 'Create',
|
||||
color: 'red',
|
||||
},
|
||||
image: 'Q0faRYg',
|
||||
};
|
||||
|
||||
export const TOOLS: Tool[] = [
|
||||
tankopediaTool,
|
||||
compareTool,
|
||||
tankPerformanceTool,
|
||||
playerStatsTool,
|
||||
sessionTool,
|
||||
embedTool,
|
||||
ratingTool,
|
||||
discordTool,
|
||||
moreTool,
|
||||
|
||||
Reference in new issue
Block a user