mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: float
This commit is contained in:
1 parent
6984794be1
commit
6a18abf17f
6 files changed
+550
-135
No files matched your search
+24
-26
@@ -28,7 +28,9 @@ const robotoFlex = Roboto_Flex({
|
||||
|
||||
export default function RootLayout({ children }: RootLayoutProps) {
|
||||
const pathname = usePathname();
|
||||
const isEmbed = pathname.startsWith('/tools/embed/host');
|
||||
const hideNav =
|
||||
pathname.startsWith('/tools/embed/host') ||
|
||||
pathname.startsWith('/tools/embed/customize');
|
||||
const isRoot = pathname === '/';
|
||||
|
||||
return (
|
||||
@@ -53,37 +55,33 @@ export default function RootLayout({ children }: RootLayoutProps) {
|
||||
<body
|
||||
style={{
|
||||
margin: 0,
|
||||
backgroundColor: isEmbed ? 'transparent' : undefined,
|
||||
backgroundColor: hideNav ? 'transparent' : undefined,
|
||||
}}
|
||||
>
|
||||
{!isEmbed && (
|
||||
<Theme
|
||||
appearance="dark"
|
||||
panelBackground="solid"
|
||||
radius="full"
|
||||
accentColor="amber"
|
||||
suppressHydrationWarning
|
||||
suppressContentEditableWarning
|
||||
<Theme
|
||||
appearance="dark"
|
||||
panelBackground="solid"
|
||||
radius="full"
|
||||
accentColor="amber"
|
||||
suppressHydrationWarning
|
||||
suppressContentEditableWarning
|
||||
>
|
||||
<Flex
|
||||
direction="column"
|
||||
style={{
|
||||
minHeight: '100vh',
|
||||
paddingTop: hideNav ? undefined : NAVBAR_HEIGHT,
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
direction="column"
|
||||
style={{
|
||||
minHeight: '100vh',
|
||||
paddingTop: isEmbed ? undefined : NAVBAR_HEIGHT,
|
||||
}}
|
||||
>
|
||||
{!isEmbed && <Navbar />}
|
||||
{!hideNav && <Navbar />}
|
||||
|
||||
<Checks />
|
||||
<Checks />
|
||||
|
||||
<Suspense fallback={<PageLoader />}>{children}</Suspense>
|
||||
<Suspense fallback={<PageLoader />}>{children}</Suspense>
|
||||
|
||||
{!isEmbed && <Footer />}
|
||||
</Flex>
|
||||
</Theme>
|
||||
)}
|
||||
|
||||
{isEmbed && children}
|
||||
{!hideNav && <Footer />}
|
||||
</Flex>
|
||||
</Theme>
|
||||
</body>
|
||||
</html>
|
||||
</App.Provider>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
'use client';
|
||||
|
||||
import { Flex } from '@radix-ui/themes';
|
||||
import { Box } 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 { imgur } from '../../../../../core/blitzkit/imgur';
|
||||
import { tanksDefinitionsArray } from '../../../../../core/blitzkit/tankDefinitions';
|
||||
import {
|
||||
EmbedConfig,
|
||||
@@ -19,10 +19,38 @@ 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 },
|
||||
listMaxTanks: { type: EmbedConfigType.Number, default: 8, pad: true },
|
||||
|
||||
cardRadius: { type: EmbedConfigType.Radius, default: '2' },
|
||||
cardHeaderPadding: { type: EmbedConfigType.Size, default: '2' },
|
||||
cardHeaderBackgroundColor: {
|
||||
type: EmbedConfigType.Color,
|
||||
default: { base: 'gray', variant: '3' },
|
||||
},
|
||||
cardHeaderPadding: { type: EmbedConfigType.Size, default: '1' },
|
||||
cardBodyBackgroundColor: {
|
||||
type: EmbedConfigType.Color,
|
||||
default: { base: 'gray', variant: '2' },
|
||||
},
|
||||
cardBodyPadding: { type: EmbedConfigType.Size, default: '2', pad: true },
|
||||
|
||||
columnGap: { type: EmbedConfigType.Size, default: '0' },
|
||||
columnValueSize: { type: EmbedConfigType.SizeNo0, default: '3' },
|
||||
columnValueColor: { type: EmbedConfigType.TextColor, default: undefined },
|
||||
columnLabelSize: { type: EmbedConfigType.SizeNo0, default: '2' },
|
||||
columnLabelColor: {
|
||||
type: EmbedConfigType.TextColor,
|
||||
default: 'gray',
|
||||
pad: true,
|
||||
},
|
||||
|
||||
column1Unit: { type: EmbedConfigType.String, default: '' },
|
||||
column2Unit: { type: EmbedConfigType.String, default: '%' },
|
||||
column3Unit: { type: EmbedConfigType.String, default: '' },
|
||||
column4Unit: { type: EmbedConfigType.String, default: '' },
|
||||
column1Label: { type: EmbedConfigType.String, default: 'Battles' },
|
||||
column2Label: { type: EmbedConfigType.String, default: 'Winrate' },
|
||||
column3Label: { type: EmbedConfigType.String, default: 'WN8' },
|
||||
column4Label: { type: EmbedConfigType.String, default: 'Damage' },
|
||||
} satisfies EmbedConfig;
|
||||
|
||||
export type TanksEmbedState = ExtractEmbedConfigType<typeof tankEmbedConfig>;
|
||||
@@ -34,24 +62,29 @@ export default function Page() {
|
||||
);
|
||||
|
||||
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>
|
||||
<Box
|
||||
width="100vw"
|
||||
height="100vh"
|
||||
style={{
|
||||
background: `url(${imgur('pAidayf')})`,
|
||||
backgroundSize: 'cover',
|
||||
}}
|
||||
>
|
||||
<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>
|
||||
<EmbedConfigInputs
|
||||
config={tankEmbedConfig}
|
||||
state={state}
|
||||
setState={
|
||||
setState as Dispatch<
|
||||
SetStateAction<ExtractEmbedConfigType<EmbedConfig>>
|
||||
>
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -1,17 +1,36 @@
|
||||
import * as radixColors from '@radix-ui/colors';
|
||||
|
||||
export enum EmbedConfigType {
|
||||
Number,
|
||||
Radius,
|
||||
Size,
|
||||
Color,
|
||||
SizeNo0,
|
||||
TextColor,
|
||||
String,
|
||||
}
|
||||
|
||||
export const radixGrays = [
|
||||
'gray',
|
||||
'mauve',
|
||||
'slate',
|
||||
'sage',
|
||||
'olive',
|
||||
'sand',
|
||||
] as const;
|
||||
|
||||
export type EmbedConfig = Record<string, EmbedConfigItem>;
|
||||
|
||||
export type EmbedConfigItem =
|
||||
export type EmbedConfigItem = (
|
||||
| {
|
||||
type: EmbedConfigType.Number;
|
||||
default: number;
|
||||
unit?: string;
|
||||
}
|
||||
| {
|
||||
type: EmbedConfigType.String;
|
||||
default: string;
|
||||
}
|
||||
| {
|
||||
type: EmbedConfigType.Radius;
|
||||
default: RadixRadius;
|
||||
@@ -19,10 +38,39 @@ export type EmbedConfigItem =
|
||||
| {
|
||||
type: EmbedConfigType.Size;
|
||||
default: RadixSize;
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: EmbedConfigType.SizeNo0;
|
||||
default: RadixSizeNo0;
|
||||
}
|
||||
| {
|
||||
type: EmbedConfigType.Color;
|
||||
default: RadixColor;
|
||||
}
|
||||
| {
|
||||
type: EmbedConfigType.TextColor;
|
||||
default: RadixTextColor;
|
||||
}
|
||||
) & {
|
||||
pad?: boolean;
|
||||
};
|
||||
|
||||
export type RadixRadius = `${1 | 2 | 3 | 4}` | 'full';
|
||||
export type RadixSize = `${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`;
|
||||
export type RadixSizeNo0 = Exclude<RadixSize, '0'>;
|
||||
export type RadixColor = { base: RadixColorBase; variant: RadixColorVariant };
|
||||
export type RadixColorBase = Exclude<
|
||||
keyof typeof radixColors,
|
||||
`${string}${'A' | 'P3' | 'Dark'}`
|
||||
>;
|
||||
type RadixColorGrays = (typeof radixGrays)[number];
|
||||
export type RadixTextColor =
|
||||
| Exclude<RadixColorBase, RadixColorGrays>
|
||||
| 'gray'
|
||||
| undefined;
|
||||
export type RadixColorVariantRaw =
|
||||
`${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12}`;
|
||||
export type RadixColorVariant = `${'' | 'a'}${RadixColorVariantRaw}`;
|
||||
|
||||
export type ExtractEmbedConfigType<Config extends EmbedConfig> = {
|
||||
[Key in keyof Config]: ({
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { EmbedConfig, ExtractEmbedConfigType } from './types';
|
||||
import {
|
||||
EmbedConfig,
|
||||
ExtractEmbedConfigType,
|
||||
RadixColor,
|
||||
RadixRadius,
|
||||
} from './types';
|
||||
|
||||
export function extractEmbedConfigDefaults<Config extends EmbedConfig>(
|
||||
config: Config,
|
||||
@@ -7,3 +12,15 @@ export function extractEmbedConfigDefaults<Config extends EmbedConfig>(
|
||||
Object.entries(config).map(([key, value]) => [key, value.default]),
|
||||
) as ExtractEmbedConfigType<Config>;
|
||||
}
|
||||
|
||||
export function toWidthVar(state: number) {
|
||||
return `${state}px`;
|
||||
}
|
||||
|
||||
export function toRadiusVar(state: RadixRadius) {
|
||||
return `var(--radius-${state})`;
|
||||
}
|
||||
|
||||
export function toColorVar(state: RadixColor) {
|
||||
return `var(--${state.base}-${state.variant})`;
|
||||
}
|
||||
@@ -1,14 +1,37 @@
|
||||
import { Flex, Select, Text, TextField } from '@radix-ui/themes';
|
||||
import * as radixColors from '@radix-ui/colors';
|
||||
import { DragHandleDots2Icon } from '@radix-ui/react-icons';
|
||||
import {
|
||||
Box,
|
||||
Card,
|
||||
Flex,
|
||||
ScrollArea,
|
||||
Select,
|
||||
Text,
|
||||
TextField,
|
||||
} from '@radix-ui/themes';
|
||||
import { produce } from 'immer';
|
||||
import { capitalize, startCase, times } from 'lodash';
|
||||
import { Dispatch, SetStateAction, useCallback } from 'react';
|
||||
import {
|
||||
Dispatch,
|
||||
ReactNode,
|
||||
SetStateAction,
|
||||
useCallback,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import {
|
||||
EmbedConfig,
|
||||
EmbedConfigType,
|
||||
ExtractEmbedConfigType,
|
||||
RadixColor,
|
||||
RadixColorBase,
|
||||
RadixColorVariant,
|
||||
RadixColorVariantRaw,
|
||||
radixGrays,
|
||||
RadixRadius,
|
||||
RadixSize,
|
||||
RadixTextColor,
|
||||
} from '../app/tools/embed/types';
|
||||
import { toColorVar, toRadiusVar } from '../app/tools/embed/utilities';
|
||||
|
||||
interface EmbedConfigInputsProps {
|
||||
config: EmbedConfig;
|
||||
@@ -27,89 +50,354 @@ export function EmbedConfigInputs({
|
||||
},
|
||||
[],
|
||||
);
|
||||
const wrapper = useRef<HTMLDivElement>(null);
|
||||
const handlePointerMove = useCallback((event: PointerEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (!wrapper.current) return;
|
||||
|
||||
wrapper.current.style.top = `${parseFloat(wrapper.current.style.top) + event.movementY}px`;
|
||||
wrapper.current.style.right = `${parseFloat(wrapper.current.style.right) - event.movementX}px`;
|
||||
}, []);
|
||||
|
||||
const handlePointerUp = useCallback((event: PointerEvent) => {
|
||||
window.removeEventListener('pointermove', handlePointerMove);
|
||||
window.removeEventListener('pointerup', handlePointerUp);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="2" align="end">
|
||||
{Object.entries(config).map(([key, setting]) => {
|
||||
const name = capitalize(startCase(key));
|
||||
<Card
|
||||
style={{ position: 'fixed', top: 0, right: 0, minWidth: 320 }}
|
||||
ref={wrapper}
|
||||
>
|
||||
<Flex
|
||||
align="center"
|
||||
justify="center"
|
||||
p="2"
|
||||
mb="2"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-panel-translucent)',
|
||||
borderRadius: 'var(--radius-2)',
|
||||
cursor: 'grab',
|
||||
}}
|
||||
onPointerDown={(event) => {
|
||||
window.addEventListener('pointermove', handlePointerMove);
|
||||
window.addEventListener('pointerup', handlePointerUp);
|
||||
}}
|
||||
>
|
||||
<DragHandleDots2Icon style={{ transform: 'rotate(90deg)' }} />
|
||||
</Flex>
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
<ScrollArea
|
||||
scrollbars="vertical"
|
||||
style={{ height: '100%', maxHeight: 640 }}
|
||||
>
|
||||
<Flex direction="column" gap="2">
|
||||
{Object.entries(config).map(([key, setting]) => {
|
||||
let control: ReactNode;
|
||||
|
||||
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}
|
||||
switch (setting.type) {
|
||||
case EmbedConfigType.Number: {
|
||||
control = (
|
||||
<TextField.Root
|
||||
size="1"
|
||||
style={{ width: 64 }}
|
||||
type="number"
|
||||
value={state[key] as number}
|
||||
onChange={(event) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = (
|
||||
event.target as HTMLInputElement
|
||||
).valueAsNumber;
|
||||
});
|
||||
}}
|
||||
>
|
||||
{setting.unit && (
|
||||
<TextField.Slot side="right">px</TextField.Slot>
|
||||
)}
|
||||
</TextField.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.String: {
|
||||
control = (
|
||||
<TextField.Root
|
||||
placeholder="Empty"
|
||||
size="1"
|
||||
style={{ width: 64 }}
|
||||
value={state[key] as string}
|
||||
onChange={(event) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = (event.target as HTMLInputElement).value;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.SizeNo0:
|
||||
case EmbedConfigType.Size: {
|
||||
control = (
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={state[key] as RadixSize}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixSize;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(10, (index) =>
|
||||
setting.type === EmbedConfigType.SizeNo0 &&
|
||||
index === 0 ? null : (
|
||||
<Select.Item key={index} value={`${index}`}>
|
||||
{index}
|
||||
</Select.Item>
|
||||
),
|
||||
)}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.Radius: {
|
||||
control = (
|
||||
<Select.Root
|
||||
size="1"
|
||||
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>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.Color: {
|
||||
control = (
|
||||
<>
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={(state[key] as RadixColor).base}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(draft[key] as RadixColor).base =
|
||||
value as RadixColorBase;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{Object.entries(radixColors)
|
||||
.filter(
|
||||
([key]) =>
|
||||
!key.endsWith('A') &&
|
||||
!key.endsWith('P3') &&
|
||||
!key.endsWith('Dark'),
|
||||
)
|
||||
.map(([key]) => (
|
||||
<Select.Item key={key} value={key}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: key as RadixColorBase,
|
||||
variant: '9',
|
||||
}),
|
||||
}}
|
||||
/>{' '}
|
||||
{capitalize(key)}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={(state[key] as RadixColor).variant}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(draft[key] as RadixColor).variant =
|
||||
value as RadixColorVariant;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(12, (index) => {
|
||||
const variant =
|
||||
`${index + 1}` as RadixColorVariantRaw;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Select.Item key={key} value={variant}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: (state[key] as RadixColor).base,
|
||||
variant,
|
||||
}),
|
||||
}}
|
||||
/>{' '}
|
||||
{variant}
|
||||
</Select.Item>
|
||||
<Select.Item key={key} value={`a${variant}`}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
overflow: 'hidden',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: (state[key] as RadixColor).base,
|
||||
variant: `a${variant}`,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
width: '50%',
|
||||
height: '100%',
|
||||
backgroundColor: toColorVar({
|
||||
base: (state[key] as RadixColor).base,
|
||||
variant,
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</Box>{' '}
|
||||
{variant} translucent
|
||||
</Select.Item>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.TextColor: {
|
||||
control = (
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={`${state[key]}`}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixTextColor;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
<Select.Item value="undefined">
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: 'white',
|
||||
}}
|
||||
/>{' '}
|
||||
White
|
||||
</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 value="gray">
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: 'gray',
|
||||
}}
|
||||
/>{' '}
|
||||
Gray
|
||||
</Select.Item>
|
||||
))}
|
||||
<Select.Item value="full">Full</Select.Item>
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
{Object.entries(radixColors)
|
||||
.filter(
|
||||
([key]) =>
|
||||
!key.endsWith('A') &&
|
||||
!key.endsWith('P3') &&
|
||||
!key.endsWith('Dark') &&
|
||||
!radixGrays.includes(key),
|
||||
)
|
||||
.map(([key]) => (
|
||||
<Select.Item key={key} value={key}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: key as RadixColorBase,
|
||||
variant: '9',
|
||||
}),
|
||||
}}
|
||||
/>{' '}
|
||||
{capitalize(key)}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex
|
||||
direction="column"
|
||||
gap="1"
|
||||
mb="1"
|
||||
pb={setting.pad ? '6' : undefined}
|
||||
>
|
||||
<Text color="gray" size="2">
|
||||
{capitalize(startCase(key))}
|
||||
</Text>
|
||||
{control && <Flex gap="1">{control}</Flex>}
|
||||
{!control && (
|
||||
<Text color="red" size="1">
|
||||
Immutable
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
}
|
||||
})}
|
||||
</Flex>
|
||||
})}
|
||||
</Flex>
|
||||
</ScrollArea>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
import { Flex } from '@radix-ui/themes';
|
||||
import { Flex, Text } from '@radix-ui/themes';
|
||||
import { times } from 'lodash';
|
||||
import { ReactNode } from 'react';
|
||||
import { TanksEmbedState } from '../app/tools/embed/customize/tanks/page';
|
||||
import {
|
||||
toColorVar,
|
||||
toRadiusVar,
|
||||
toWidthVar,
|
||||
} from '../app/tools/embed/utilities';
|
||||
import { TankDefinition } from '../core/blitzkit/tankDefinitions';
|
||||
|
||||
interface TanksEmbedWrapperProps {
|
||||
@@ -10,7 +16,11 @@ interface TanksEmbedWrapperProps {
|
||||
|
||||
export function TanksEmbedWrapper({ children, state }: TanksEmbedWrapperProps) {
|
||||
return (
|
||||
<Flex direction="column" gap={state.listGap} width={`${state.listWidth}px`}>
|
||||
<Flex
|
||||
direction="column"
|
||||
gap={state.listGap}
|
||||
width={toWidthVar(state.listWidth)}
|
||||
>
|
||||
{children}
|
||||
</Flex>
|
||||
);
|
||||
@@ -26,21 +36,42 @@ export function TanksEmbedCard({ tank, state }: TanksEmbedCardProps) {
|
||||
<Flex
|
||||
direction="column"
|
||||
style={{
|
||||
borderRadius: `var(--radius-${state.cardRadius})`,
|
||||
borderRadius: toRadiusVar(state.cardRadius),
|
||||
overflow: 'hidden',
|
||||
backgroundColor: 'var(--color-panel-solid)',
|
||||
backgroundColor: toColorVar(state.cardBodyBackgroundColor),
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
justify="center"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-panel-translucent)',
|
||||
backgroundColor: toColorVar(state.cardHeaderBackgroundColor),
|
||||
}}
|
||||
p={state.cardHeaderPadding}
|
||||
>
|
||||
{tank.name}
|
||||
</Flex>
|
||||
<Flex>asd</Flex>
|
||||
|
||||
<Flex p={state.cardBodyPadding}>
|
||||
{times(4, (index) => {
|
||||
const column = (index + 1) as 1 | 2 | 3 | 4;
|
||||
|
||||
return (
|
||||
<Flex
|
||||
direction="column"
|
||||
align="center"
|
||||
gap={state.columnGap}
|
||||
flexGrow="1"
|
||||
>
|
||||
<Text size={state.columnValueSize} color={state.columnValueColor}>
|
||||
70{state[`column${column}Unit`]}
|
||||
</Text>
|
||||
<Text size={state.columnLabelSize} color={state.columnLabelColor}>
|
||||
{state[`column${column}Label`]}
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user