mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
feat: modules button
This commit is contained in:
1 parent
02129feb25
commit
526b5785b7
1 file changed
+264
-238
+264
-238
@@ -488,274 +488,300 @@ export default function Page() {
|
|||||||
<Flex
|
<Flex
|
||||||
align="center"
|
align="center"
|
||||||
justify="center"
|
justify="center"
|
||||||
|
direction="column"
|
||||||
gap="3"
|
gap="3"
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Popover.Root>
|
<Flex align="center" justify="center" gap="3">
|
||||||
<Popover.Trigger>
|
<Popover.Root>
|
||||||
<Button
|
<Popover.Trigger>
|
||||||
variant="ghost"
|
|
||||||
radius="large"
|
|
||||||
style={{
|
|
||||||
height: '100%',
|
|
||||||
width: 12,
|
|
||||||
position: 'relative',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Flex direction="column" justify="center">
|
|
||||||
{provisions.map((provision, index) => (
|
|
||||||
<img
|
|
||||||
key={provision}
|
|
||||||
src={asset(
|
|
||||||
`/icons/provisions/${provision}.webp`,
|
|
||||||
)}
|
|
||||||
style={{
|
|
||||||
left: '50%',
|
|
||||||
/**
|
|
||||||
* max = 100% - 16px - 4px
|
|
||||||
* min = 4px
|
|
||||||
* diff = max - min
|
|
||||||
* = 100% - 16px - 4px - 4px
|
|
||||||
* = 100% - 24px
|
|
||||||
* coefficient = index / length - 1
|
|
||||||
* position = min + coefficient * diff
|
|
||||||
*/
|
|
||||||
top: `calc(4px + ${
|
|
||||||
provisions.length === 1
|
|
||||||
? 0.5
|
|
||||||
: index / (provisions.length - 1)
|
|
||||||
} * (100% - 24px))`,
|
|
||||||
transform: 'translateX(-50%)',
|
|
||||||
position: 'absolute',
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
objectFit: 'contain',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{provisions.length === 0 && (
|
|
||||||
<ComponentPlaceholderIcon />
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
</Button>
|
|
||||||
</Popover.Trigger>
|
|
||||||
|
|
||||||
<Popover.Content>
|
|
||||||
<ProvisionsManager
|
|
||||||
provisions={provisionsList.map(
|
|
||||||
(provision) => provision.id,
|
|
||||||
)}
|
|
||||||
selected={provisions}
|
|
||||||
disabled={tank.provisions === provisions.length}
|
|
||||||
onChange={(provisions) => {
|
|
||||||
mutateCompareTemporary((draft) => {
|
|
||||||
draft.members[index].provisions =
|
|
||||||
provisions;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Flex justify="end" mt="4">
|
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => {
|
radius="large"
|
||||||
mutateCompareTemporary((draft) => {
|
style={{
|
||||||
draft.members[index].provisions = [];
|
height: '100%',
|
||||||
});
|
width: 12,
|
||||||
|
position: 'relative',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Clear
|
<Flex direction="column" justify="center">
|
||||||
|
{provisions.map((provision, index) => (
|
||||||
|
<img
|
||||||
|
key={provision}
|
||||||
|
src={asset(
|
||||||
|
`/icons/provisions/${provision}.webp`,
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
left: '50%',
|
||||||
|
/**
|
||||||
|
* max = 100% - 16px - 4px
|
||||||
|
* min = 4px
|
||||||
|
* diff = max - min
|
||||||
|
* = 100% - 16px - 4px - 4px
|
||||||
|
* = 100% - 24px
|
||||||
|
* coefficient = index / length - 1
|
||||||
|
* position = min + coefficient * diff
|
||||||
|
*/
|
||||||
|
top: `calc(4px + ${
|
||||||
|
provisions.length === 1
|
||||||
|
? 0.5
|
||||||
|
: index / (provisions.length - 1)
|
||||||
|
} * (100% - 24px))`,
|
||||||
|
transform: 'translateX(-50%)',
|
||||||
|
position: 'absolute',
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
objectFit: 'contain',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{provisions.length === 0 && (
|
||||||
|
<ComponentPlaceholderIcon />
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Popover.Trigger>
|
||||||
</Popover.Content>
|
|
||||||
</Popover.Root>
|
|
||||||
|
|
||||||
<Popover.Root>
|
<Popover.Content>
|
||||||
<Popover.Trigger>
|
<ProvisionsManager
|
||||||
<Button variant="ghost" radius="large">
|
provisions={provisionsList.map(
|
||||||
<Flex gap="1" direction="column">
|
(provision) => provision.id,
|
||||||
{times(3, (y) => (
|
)}
|
||||||
<Flex
|
selected={provisions}
|
||||||
key={y}
|
disabled={
|
||||||
style={{
|
tank.provisions === provisions.length
|
||||||
gap: 6,
|
}
|
||||||
}}
|
onChange={(provisions) => {
|
||||||
>
|
mutateCompareTemporary((draft) => {
|
||||||
{times(3, (x) => {
|
draft.members[index].provisions =
|
||||||
const equipment = equipmentMatrix[y][x];
|
provisions;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
return (
|
<Flex justify="end" mt="4">
|
||||||
<Flex
|
<Button
|
||||||
key={x}
|
variant="ghost"
|
||||||
style={{
|
onClick={() => {
|
||||||
gap: 2,
|
mutateCompareTemporary((draft) => {
|
||||||
}}
|
draft.members[index].provisions = [];
|
||||||
>
|
});
|
||||||
<div
|
}}
|
||||||
style={{
|
>
|
||||||
width: 4,
|
Clear
|
||||||
height: 8,
|
</Button>
|
||||||
backgroundColor:
|
|
||||||
equipment === -1
|
|
||||||
? theme.colors
|
|
||||||
.textLowContrast_crimson
|
|
||||||
: theme.colors
|
|
||||||
.textLowContrast,
|
|
||||||
borderRadius: 2,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: 4,
|
|
||||||
height: 8,
|
|
||||||
backgroundColor:
|
|
||||||
equipment === 1
|
|
||||||
? theme.colors
|
|
||||||
.textLowContrast_crimson
|
|
||||||
: theme.colors
|
|
||||||
.textLowContrast,
|
|
||||||
borderRadius: 2,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Flex>
|
|
||||||
))}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Button>
|
</Popover.Content>
|
||||||
</Popover.Trigger>
|
</Popover.Root>
|
||||||
|
|
||||||
<Popover.Content>
|
<Popover.Root>
|
||||||
<EquipmentManager
|
<Popover.Trigger>
|
||||||
matrix={equipmentMatrix}
|
<Button variant="ghost" radius="large">
|
||||||
preset={equipmentPreset}
|
<Flex gap="1" direction="column">
|
||||||
onChange={(matrix) => {
|
{times(3, (y) => (
|
||||||
mutateCompareTemporary((draft) => {
|
<Flex
|
||||||
draft.members[index].equipmentMatrix =
|
key={y}
|
||||||
matrix;
|
style={{
|
||||||
draft.sorting = undefined;
|
gap: 6,
|
||||||
});
|
}}
|
||||||
}}
|
>
|
||||||
/>
|
{times(3, (x) => {
|
||||||
|
const equipment =
|
||||||
|
equipmentMatrix[y][x];
|
||||||
|
|
||||||
<Flex justify="end" gap="4" mt="4">
|
return (
|
||||||
<Button
|
<Flex
|
||||||
variant="ghost"
|
key={x}
|
||||||
color="red"
|
style={{
|
||||||
onClick={() => {
|
gap: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 4,
|
||||||
|
height: 8,
|
||||||
|
backgroundColor:
|
||||||
|
equipment === -1
|
||||||
|
? theme.colors
|
||||||
|
.textLowContrast_crimson
|
||||||
|
: theme.colors
|
||||||
|
.textLowContrast,
|
||||||
|
borderRadius: 2,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 4,
|
||||||
|
height: 8,
|
||||||
|
backgroundColor:
|
||||||
|
equipment === 1
|
||||||
|
? theme.colors
|
||||||
|
.textLowContrast_crimson
|
||||||
|
: theme.colors
|
||||||
|
.textLowContrast,
|
||||||
|
borderRadius: 2,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Flex>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
</Button>
|
||||||
|
</Popover.Trigger>
|
||||||
|
|
||||||
|
<Popover.Content>
|
||||||
|
<EquipmentManager
|
||||||
|
matrix={equipmentMatrix}
|
||||||
|
preset={equipmentPreset}
|
||||||
|
onChange={(matrix) => {
|
||||||
mutateCompareTemporary((draft) => {
|
mutateCompareTemporary((draft) => {
|
||||||
draft.members[index].equipmentMatrix =
|
draft.members[index].equipmentMatrix =
|
||||||
times(3, () =>
|
matrix;
|
||||||
times(3, () => 0),
|
|
||||||
) as EquipmentMatrix;
|
|
||||||
draft.sorting = undefined;
|
draft.sorting = undefined;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
Clear
|
|
||||||
</Button>
|
<Flex justify="end" gap="4" mt="4">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => {
|
color="red"
|
||||||
mutateCompareTemporary((draft) => {
|
onClick={() => {
|
||||||
draft.members.forEach((member) => {
|
mutateCompareTemporary((draft) => {
|
||||||
member.equipmentMatrix =
|
draft.members[index].equipmentMatrix =
|
||||||
draft.members[index].equipmentMatrix;
|
times(3, () =>
|
||||||
|
times(3, () => 0),
|
||||||
|
) as EquipmentMatrix;
|
||||||
draft.sorting = undefined;
|
draft.sorting = undefined;
|
||||||
});
|
});
|
||||||
});
|
}}
|
||||||
}}
|
>
|
||||||
>
|
Clear
|
||||||
Apply to all
|
</Button>
|
||||||
</Button>
|
<Button
|
||||||
</Flex>
|
variant="ghost"
|
||||||
</Popover.Content>
|
onClick={() => {
|
||||||
</Popover.Root>
|
mutateCompareTemporary((draft) => {
|
||||||
|
draft.members.forEach((member) => {
|
||||||
<Popover.Root>
|
member.equipmentMatrix =
|
||||||
<Popover.Trigger>
|
draft.members[
|
||||||
<Button
|
index
|
||||||
variant="ghost"
|
].equipmentMatrix;
|
||||||
radius="large"
|
draft.sorting = undefined;
|
||||||
style={{
|
});
|
||||||
height: '100%',
|
});
|
||||||
width: 12,
|
}}
|
||||||
position: 'relative',
|
>
|
||||||
}}
|
Apply to all
|
||||||
>
|
</Button>
|
||||||
<Flex direction="column" justify="center">
|
|
||||||
{consumables.map((consumable, index) => (
|
|
||||||
<img
|
|
||||||
key={consumable}
|
|
||||||
src={asset(
|
|
||||||
`/icons/consumables/${consumable}.webp`,
|
|
||||||
)}
|
|
||||||
style={{
|
|
||||||
left: '50%',
|
|
||||||
/**
|
|
||||||
* max = 100% - 16px - 4px
|
|
||||||
* min = 4px
|
|
||||||
* diff = max - min
|
|
||||||
* = 100% - 16px - 4px - 4px
|
|
||||||
* = 100% - 24px
|
|
||||||
* coefficient = index / length - 1
|
|
||||||
* position = min + coefficient * diff
|
|
||||||
*/
|
|
||||||
top: `calc(4px + ${
|
|
||||||
consumables.length === 1
|
|
||||||
? 0.5
|
|
||||||
: index / (consumables.length - 1)
|
|
||||||
} * (100% - 24px))`,
|
|
||||||
transform: 'translateX(-50%)',
|
|
||||||
position: 'absolute',
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
objectFit: 'contain',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{consumables.length === 0 && (
|
|
||||||
<ComponentPlaceholderIcon />
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Button>
|
</Popover.Content>
|
||||||
</Popover.Trigger>
|
</Popover.Root>
|
||||||
|
|
||||||
<Popover.Content>
|
<Popover.Root>
|
||||||
<ConsumablesManager
|
<Popover.Trigger>
|
||||||
consumables={consumablesList}
|
|
||||||
selected={consumables}
|
|
||||||
onChange={(consumables) => {
|
|
||||||
mutateCompareTemporary((draft) => {
|
|
||||||
draft.members[index].consumables =
|
|
||||||
consumables;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
disabled={
|
|
||||||
tank.consumables === consumables.length
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Flex justify="end" mt="4">
|
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => {
|
radius="large"
|
||||||
mutateCompareTemporary((draft) => {
|
style={{
|
||||||
draft.members[index].consumables = [];
|
height: '100%',
|
||||||
});
|
width: 12,
|
||||||
|
position: 'relative',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Clear
|
<Flex direction="column" justify="center">
|
||||||
|
{consumables.map((consumable, index) => (
|
||||||
|
<img
|
||||||
|
key={consumable}
|
||||||
|
src={asset(
|
||||||
|
`/icons/consumables/${consumable}.webp`,
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
left: '50%',
|
||||||
|
/**
|
||||||
|
* max = 100% - 16px - 4px
|
||||||
|
* min = 4px
|
||||||
|
* diff = max - min
|
||||||
|
* = 100% - 16px - 4px - 4px
|
||||||
|
* = 100% - 24px
|
||||||
|
* coefficient = index / length - 1
|
||||||
|
* position = min + coefficient * diff
|
||||||
|
*/
|
||||||
|
top: `calc(4px + ${
|
||||||
|
consumables.length === 1
|
||||||
|
? 0.5
|
||||||
|
: index / (consumables.length - 1)
|
||||||
|
} * (100% - 24px))`,
|
||||||
|
transform: 'translateX(-50%)',
|
||||||
|
position: 'absolute',
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
objectFit: 'contain',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{consumables.length === 0 && (
|
||||||
|
<ComponentPlaceholderIcon />
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Popover.Trigger>
|
||||||
</Popover.Content>
|
|
||||||
</Popover.Root>
|
<Popover.Content>
|
||||||
|
<ConsumablesManager
|
||||||
|
consumables={consumablesList}
|
||||||
|
selected={consumables}
|
||||||
|
onChange={(consumables) => {
|
||||||
|
mutateCompareTemporary((draft) => {
|
||||||
|
draft.members[index].consumables =
|
||||||
|
consumables;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
disabled={
|
||||||
|
tank.consumables === consumables.length
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Flex justify="end" mt="4">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
mutateCompareTemporary((draft) => {
|
||||||
|
draft.members[index].consumables = [];
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Popover.Content>
|
||||||
|
</Popover.Root>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Button variant="ghost">
|
||||||
|
<Flex align="center">
|
||||||
|
{['turret', 'gun', 'engine', 'chassis'].map(
|
||||||
|
(module, index) => (
|
||||||
|
<img
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
src={asset(`icons/modules/${module}.webp`)}
|
||||||
|
style={{
|
||||||
|
objectFit: 'contain',
|
||||||
|
marginLeft: index > 0 ? -4 : 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in new issue
Block a user