mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
feat: dropdown modules
This commit is contained in:
1 parent
cc6de50de6
commit
54e012f736
4 files changed
+189
-89
No files matched your search
@@ -118,6 +118,7 @@ interface VehicleDefinitions {
|
|||||||
weight: number;
|
weight: number;
|
||||||
terrainResistance: string;
|
terrainResistance: string;
|
||||||
rotationSpeed: number;
|
rotationSpeed: number;
|
||||||
|
userString: string;
|
||||||
shotDispersionFactors: {
|
shotDispersionFactors: {
|
||||||
vehicleMovement: number;
|
vehicleMovement: number;
|
||||||
vehicleRotation: number;
|
vehicleRotation: number;
|
||||||
@@ -566,6 +567,7 @@ export async function definitions(production: boolean) {
|
|||||||
tankDefinitions[tankId].tracks.push({
|
tankDefinitions[tankId].tracks.push({
|
||||||
id: trackId,
|
id: trackId,
|
||||||
weight: track.weight,
|
weight: track.weight,
|
||||||
|
name: strings[track.userString],
|
||||||
traverseSpeed: track.rotationSpeed,
|
traverseSpeed: track.rotationSpeed,
|
||||||
dispersion: {
|
dispersion: {
|
||||||
move: track.shotDispersionFactors.vehicleMovement,
|
move: track.shotDispersionFactors.vehicleMovement,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Button, Flex, Heading } from '@radix-ui/themes';
|
import { Button, DropdownMenu, Flex, Heading } from '@radix-ui/themes';
|
||||||
|
import { useState } from 'react';
|
||||||
import { ModuleButton } from '../../../../../../../components/ModuleButtons/ModuleButton';
|
import { ModuleButton } from '../../../../../../../components/ModuleButtons/ModuleButton';
|
||||||
import { TIER_ROMAN_NUMERALS } from '../../../../../../../core/blitzkrieg/tankDefinitions/constants';
|
import { TIER_ROMAN_NUMERALS } from '../../../../../../../core/blitzkrieg/tankDefinitions/constants';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
||||||
@@ -12,6 +13,10 @@ export function Modules() {
|
|||||||
protagonist.tank.turrets[0].guns.length > 1 ||
|
protagonist.tank.turrets[0].guns.length > 1 ||
|
||||||
protagonist.tank.engines.length > 1 ||
|
protagonist.tank.engines.length > 1 ||
|
||||||
protagonist.tank.tracks.length > 1;
|
protagonist.tank.tracks.length > 1;
|
||||||
|
const [turretMenuOpen, setTurretMenuOpen] = useState(false);
|
||||||
|
const [gunMenuOpen, setGunMenuOpen] = useState(false);
|
||||||
|
const [engineMenuOpen, setEngineMenuOpen] = useState(false);
|
||||||
|
const [trackMenuOpen, setTrackMenuOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigurationChildWrapper>
|
<ConfigurationChildWrapper>
|
||||||
@@ -59,96 +64,180 @@ export function Modules() {
|
|||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex gap="2" wrap="wrap">
|
<Flex gap="1" wrap="wrap">
|
||||||
<Flex>
|
<ModuleButton
|
||||||
{protagonist.tank.turrets.map((turret, index) => {
|
module="turret"
|
||||||
return (
|
discriminator={TIER_ROMAN_NUMERALS[protagonist.turret.tier]}
|
||||||
<ModuleButton
|
first
|
||||||
key={turret.id}
|
last
|
||||||
selected={protagonist.turret.id === turret.id}
|
rowChild
|
||||||
module="turret"
|
onClick={() => setTurretMenuOpen(true)}
|
||||||
discriminator={TIER_ROMAN_NUMERALS[turret.tier]}
|
/>
|
||||||
first={index === 0}
|
|
||||||
last={index === protagonist.tank.turrets.length - 1}
|
|
||||||
rowChild
|
|
||||||
onClick={() => {
|
|
||||||
mutateDuel((draft) => {
|
|
||||||
draft.protagonist!.turret = turret;
|
|
||||||
draft.protagonist!.gun = turret.guns.at(-1)!;
|
|
||||||
draft.protagonist!.shell = turret.guns.at(-1)!.shells[0];
|
|
||||||
});
|
|
||||||
mutateTankopediaTemporary((draft) => {
|
|
||||||
draft.shot = undefined;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<Flex>
|
<DropdownMenu.Root
|
||||||
{protagonist.turret.guns.map((gun, index) => {
|
open={turretMenuOpen}
|
||||||
return (
|
onOpenChange={setTurretMenuOpen}
|
||||||
<ModuleButton
|
>
|
||||||
key={gun.id}
|
<DropdownMenu.Trigger>
|
||||||
module="gun"
|
<div />
|
||||||
discriminator={TIER_ROMAN_NUMERALS[gun.tier]}
|
</DropdownMenu.Trigger>
|
||||||
selected={protagonist.gun.id === gun.id}
|
|
||||||
first={index === 0}
|
|
||||||
last={index === protagonist.turret.guns.length - 1}
|
|
||||||
rowChild
|
|
||||||
onClick={() => {
|
|
||||||
mutateDuel((draft) => {
|
|
||||||
draft.protagonist!.gun = gun;
|
|
||||||
draft.protagonist!.shell = gun.shells[0];
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<Flex>
|
<DropdownMenu.Content>
|
||||||
{protagonist.tank.engines.map((engine, index) => {
|
<DropdownMenu.RadioGroup value={`${protagonist.turret.id}`}>
|
||||||
return (
|
{[...protagonist.tank.turrets].reverse().map((turret) => {
|
||||||
<ModuleButton
|
return (
|
||||||
key={engine.id}
|
<DropdownMenu.RadioItem
|
||||||
module="engine"
|
key={turret.id}
|
||||||
discriminator={TIER_ROMAN_NUMERALS[engine.tier]}
|
value={`${turret.id}`}
|
||||||
selected={protagonist.engine.id === engine.id}
|
onClick={() => {
|
||||||
first={index === 0}
|
mutateDuel((draft) => {
|
||||||
last={index === protagonist.tank.engines.length - 1}
|
draft.protagonist!.turret = turret;
|
||||||
rowChild
|
draft.protagonist!.gun = turret.guns.at(-1)!;
|
||||||
onClick={() => {
|
draft.protagonist!.shell =
|
||||||
mutateDuel((draft) => {
|
turret.guns.at(-1)!.shells[0];
|
||||||
draft.protagonist!.engine = engine;
|
});
|
||||||
});
|
mutateTankopediaTemporary((draft) => {
|
||||||
}}
|
draft.shot = undefined;
|
||||||
/>
|
});
|
||||||
);
|
setTurretMenuOpen(false);
|
||||||
})}
|
}}
|
||||||
</Flex>
|
>
|
||||||
|
<ModuleButton
|
||||||
|
variant="ghost"
|
||||||
|
module="turret"
|
||||||
|
discriminator={TIER_ROMAN_NUMERALS[turret.tier]}
|
||||||
|
/>{' '}
|
||||||
|
{turret.name}
|
||||||
|
</DropdownMenu.RadioItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</DropdownMenu.RadioGroup>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
|
||||||
<Flex>
|
<ModuleButton
|
||||||
{protagonist.tank.tracks.map((track, index) => {
|
module="gun"
|
||||||
return (
|
discriminator={TIER_ROMAN_NUMERALS[protagonist.gun.tier]}
|
||||||
<ModuleButton
|
first
|
||||||
key={track.id}
|
last
|
||||||
module="chassis"
|
rowChild
|
||||||
discriminator={TIER_ROMAN_NUMERALS[track.tier]}
|
onClick={() => setGunMenuOpen(true)}
|
||||||
selected={protagonist.track.id === track.id}
|
/>
|
||||||
first={index === 0}
|
|
||||||
last={index === protagonist.tank.tracks.length - 1}
|
<DropdownMenu.Root open={gunMenuOpen} onOpenChange={setGunMenuOpen}>
|
||||||
rowChild
|
<DropdownMenu.Trigger>
|
||||||
onClick={() => {
|
<div />
|
||||||
mutateDuel((draft) => {
|
</DropdownMenu.Trigger>
|
||||||
draft.protagonist!.track = track;
|
|
||||||
});
|
<DropdownMenu.Content>
|
||||||
}}
|
<DropdownMenu.RadioGroup value={`${protagonist.gun.id}`}>
|
||||||
/>
|
{[...protagonist.turret.guns].reverse().map((gun) => {
|
||||||
);
|
return (
|
||||||
})}
|
<DropdownMenu.RadioItem
|
||||||
</Flex>
|
key={gun.id}
|
||||||
|
value={`${gun.id}`}
|
||||||
|
onClick={() => {
|
||||||
|
mutateDuel((draft) => {
|
||||||
|
draft.protagonist!.gun = gun;
|
||||||
|
draft.protagonist!.shell = gun.shells[0];
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ModuleButton
|
||||||
|
variant="ghost"
|
||||||
|
module="gun"
|
||||||
|
discriminator={TIER_ROMAN_NUMERALS[gun.tier]}
|
||||||
|
/>{' '}
|
||||||
|
{gun.name}
|
||||||
|
</DropdownMenu.RadioItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</DropdownMenu.RadioGroup>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
|
||||||
|
<ModuleButton
|
||||||
|
module="engine"
|
||||||
|
discriminator={TIER_ROMAN_NUMERALS[protagonist.engine.tier]}
|
||||||
|
first
|
||||||
|
last
|
||||||
|
rowChild
|
||||||
|
onClick={() => setEngineMenuOpen(true)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DropdownMenu.Root
|
||||||
|
open={engineMenuOpen}
|
||||||
|
onOpenChange={setEngineMenuOpen}
|
||||||
|
>
|
||||||
|
<DropdownMenu.Trigger>
|
||||||
|
<div />
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
|
||||||
|
<DropdownMenu.Content>
|
||||||
|
<DropdownMenu.RadioGroup value={`${protagonist.engine.id}`}>
|
||||||
|
{[...protagonist.tank.engines].reverse().map((engine) => {
|
||||||
|
return (
|
||||||
|
<DropdownMenu.RadioItem
|
||||||
|
key={engine.id}
|
||||||
|
value={`${engine.id}`}
|
||||||
|
onClick={() => {
|
||||||
|
mutateDuel((draft) => {
|
||||||
|
draft.protagonist!.engine = engine;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ModuleButton
|
||||||
|
variant="ghost"
|
||||||
|
module="engine"
|
||||||
|
discriminator={TIER_ROMAN_NUMERALS[engine.tier]}
|
||||||
|
/>{' '}
|
||||||
|
{engine.name}
|
||||||
|
</DropdownMenu.RadioItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</DropdownMenu.RadioGroup>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
|
||||||
|
<ModuleButton
|
||||||
|
module="chassis"
|
||||||
|
discriminator={TIER_ROMAN_NUMERALS[protagonist.track.tier]}
|
||||||
|
first
|
||||||
|
last
|
||||||
|
rowChild
|
||||||
|
onClick={() => setTrackMenuOpen(true)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DropdownMenu.Root open={trackMenuOpen} onOpenChange={setTrackMenuOpen}>
|
||||||
|
<DropdownMenu.Trigger>
|
||||||
|
<div />
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
|
||||||
|
<DropdownMenu.Content>
|
||||||
|
<DropdownMenu.RadioGroup value={`${protagonist.track.id}`}>
|
||||||
|
{[...protagonist.tank.tracks].reverse().map((track) => {
|
||||||
|
return (
|
||||||
|
<DropdownMenu.RadioItem
|
||||||
|
key={track.id}
|
||||||
|
value={`${track.id}`}
|
||||||
|
onClick={() => {
|
||||||
|
mutateDuel((draft) => {
|
||||||
|
draft.protagonist!.track = track;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ModuleButton
|
||||||
|
variant="ghost"
|
||||||
|
module="chassis"
|
||||||
|
discriminator={TIER_ROMAN_NUMERALS[track.tier]}
|
||||||
|
/>{' '}
|
||||||
|
{track.name}
|
||||||
|
</DropdownMenu.RadioItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</DropdownMenu.RadioGroup>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
</Flex>
|
</Flex>
|
||||||
</ConfigurationChildWrapper>
|
</ConfigurationChildWrapper>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export interface TankComponentButtonProps
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function TankComponentButton({
|
export function TankComponentButton({
|
||||||
|
variant,
|
||||||
selected,
|
selected,
|
||||||
first = false,
|
first = false,
|
||||||
last = false,
|
last = false,
|
||||||
@@ -23,13 +24,15 @@ export function TankComponentButton({
|
|||||||
special,
|
special,
|
||||||
children,
|
children,
|
||||||
banner,
|
banner,
|
||||||
|
disabled,
|
||||||
|
style,
|
||||||
...props
|
...props
|
||||||
}: TankComponentButtonProps) {
|
}: TankComponentButtonProps) {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
radius="medium"
|
radius="medium"
|
||||||
color={selected ? (special ? 'amber' : undefined) : 'gray'}
|
color={selected ? (special ? 'amber' : undefined) : 'gray'}
|
||||||
variant={selected ? 'surface' : 'soft'}
|
variant={variant ?? (selected ? 'surface' : 'soft')}
|
||||||
style={{
|
style={{
|
||||||
padding: 0,
|
padding: 0,
|
||||||
minWidth: 48,
|
minWidth: 48,
|
||||||
@@ -41,7 +44,11 @@ export function TankComponentButton({
|
|||||||
borderBottomRightRadius: last ? undefined : 0,
|
borderBottomRightRadius: last ? undefined : 0,
|
||||||
margin: rowChild ? -0.5 : 'unset',
|
margin: rowChild ? -0.5 : 'unset',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
|
cursor: 'unset',
|
||||||
|
pointerEvents: variant === 'ghost' ? 'none' : undefined,
|
||||||
|
...style,
|
||||||
}}
|
}}
|
||||||
|
disabled={variant === 'ghost' || disabled}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{banner !== undefined && (
|
{banner !== undefined && (
|
||||||
@@ -69,6 +76,7 @@ export function TankComponentButton({
|
|||||||
right: 8,
|
right: 8,
|
||||||
textAlign: 'right',
|
textAlign: 'right',
|
||||||
}}
|
}}
|
||||||
|
color={variant === 'ghost' ? 'gray' : undefined}
|
||||||
>
|
>
|
||||||
{discriminator}
|
{discriminator}
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export interface TankDefinition {
|
|||||||
export interface TrackDefinition {
|
export interface TrackDefinition {
|
||||||
id: number;
|
id: number;
|
||||||
tier: Tier;
|
tier: Tier;
|
||||||
|
name: string;
|
||||||
weight: number;
|
weight: number;
|
||||||
traverseSpeed: number;
|
traverseSpeed: number;
|
||||||
xp?: number;
|
xp?: number;
|
||||||
|
|||||||
Reference in new issue
Block a user