feat: start of embeds

This commit is contained in:
TrèsAbhi committed 2024-08-05 12:52:40 -05:00
1 parent f666023bef
commit 6984794be1
23 files changed
+313 -30

No files matched your search

+25 -21
View File
@@ -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
View File
@@ -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>
);
}
+5
View File
@@ -0,0 +1,5 @@
import PageWrapper from '../../../components/PageWrapper';
export default function Page() {
return <PageWrapper></PageWrapper>;
}
+31
View File
@@ -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'];
};
+9
View File
@@ -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.
+115
View File
@@ -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>
);
}
+2 -2
View File
@@ -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"
/>
/> */}
</>
);
}
+46
View File
@@ -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
View File
@@ -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,