mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
1 parent
3a60535564
commit
44e7cd7505
16 files changed
+206
-14
No files matched your search
@@ -193,6 +193,10 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"tanks": {
|
"tanks": {
|
||||||
|
"loadout": {
|
||||||
|
"modules": "Modules"
|
||||||
|
},
|
||||||
|
|
||||||
"search": {
|
"search": {
|
||||||
"placeholder": "Search tanks..."
|
"placeholder": "Search tanks..."
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
@@ -90,3 +90,23 @@ import "@fontsource-variable/roboto-flex";
|
|||||||
--tank-card-min-width: 8rem;
|
--tank-card-min-width: 8rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
.composable-radius {
|
||||||
|
&[data-radius="1"] {
|
||||||
|
border-radius: var(--space-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-radius="2"] {
|
||||||
|
border-radius: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-radius="3"] {
|
||||||
|
border-radius: var(--space-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-radius="max"] {
|
||||||
|
border-radius: var(--max-size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
border-radius: var(--max-size);
|
border-radius: var(--max-size);
|
||||||
padding: var(--space-3) var(--space-4);
|
padding: var(--space-3) var(--space-4);
|
||||||
|
|
||||||
background-color: var(--accent-9);
|
|
||||||
border: none;
|
border: none;
|
||||||
|
|
||||||
font-family: var(--font-family-regular);
|
font-family: var(--font-family-regular);
|
||||||
@@ -23,4 +22,14 @@
|
|||||||
&[data-light-text="true"] {
|
&[data-light-text="true"] {
|
||||||
color: var(--white-a12);
|
color: var(--white-a12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&[data-variant="solid"] {
|
||||||
|
background-color: var(--accent-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-variant="surface"] {
|
||||||
|
background-color: var(--accent-3);
|
||||||
|
|
||||||
|
outline: var(--space-1) solid var(--accent-4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,8 @@ import styles from "./index.module.css";
|
|||||||
|
|
||||||
export interface ButtonProps extends ComponentProps<"button"> {
|
export interface ButtonProps extends ComponentProps<"button"> {
|
||||||
color?: Color;
|
color?: Color;
|
||||||
variant?: "solid";
|
radius?: `${1 | 2 | 3}` | "max";
|
||||||
|
variant?: "solid" | "surface";
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LIGHT_TEXT_COLORS = new Set<Color>([
|
export const LIGHT_TEXT_COLORS = new Set<Color>([
|
||||||
@@ -28,14 +29,16 @@ export function Button({
|
|||||||
color,
|
color,
|
||||||
variant = "solid",
|
variant = "solid",
|
||||||
style,
|
style,
|
||||||
|
radius = "max",
|
||||||
...props
|
...props
|
||||||
}: ButtonProps) {
|
}: ButtonProps) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={classNames(styles.button, className)}
|
className={classNames("composable-radius", styles.button, className)}
|
||||||
data-color={color}
|
data-color={color}
|
||||||
data-variant={variant}
|
data-variant={variant}
|
||||||
data-light-text={variant === "solid"}
|
data-light-text={variant === "solid"}
|
||||||
|
data-radius={radius}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: color ? `var(--${color}-9)` : undefined,
|
backgroundColor: color ? `var(--${color}-9)` : undefined,
|
||||||
...style,
|
...style,
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.icon-button {
|
||||||
|
padding: var(--space-3);
|
||||||
|
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { classNames } from "../../core/ui/classNames";
|
||||||
|
import type { Color } from "../../core/ui/color";
|
||||||
|
import { Button, type ButtonProps } from "../Button";
|
||||||
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
|
export interface IconButtonProps extends ButtonProps {
|
||||||
|
color?: Color;
|
||||||
|
variant?: "solid";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IconButton({ className, ...props }: ButtonProps) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
className={classNames(className, styles["icon-button"])}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
.lines {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
gap: var(--space-3);
|
||||||
|
|
||||||
|
.line {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
gap: var(--space-2);
|
||||||
|
|
||||||
|
.stage {
|
||||||
|
img {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
import type { UpgradeLine } from "@blitzkit/closed/protos/game/proto/legacy/blitz_static_tank_upgrade_line";
|
||||||
|
import { CaretDownIcon } from "@radix-ui/react-icons";
|
||||||
|
import { api } from "../../core/api/dynamic";
|
||||||
|
import { useAwait } from "../../hooks/useAwait";
|
||||||
|
import { useStrings } from "../../hooks/useStrings";
|
||||||
|
import { Tankopedia } from "../../stores/tankopedia";
|
||||||
|
import { Heading } from "../Heading";
|
||||||
|
import { IconButton } from "../IconButton";
|
||||||
|
import { Section } from "../Section";
|
||||||
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
|
export function TankopediaLoadout() {
|
||||||
|
const strings = useStrings();
|
||||||
|
|
||||||
|
const id = Tankopedia.use((state) => state.protagonist.id);
|
||||||
|
const tank = useAwait(() => api.tank(id), `tank-${id}`);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section>
|
||||||
|
<Heading size="3">{strings.tanks.loadout.modules}</Heading>
|
||||||
|
|
||||||
|
<div className={styles.lines}>
|
||||||
|
{tank.tank!.upgrade_lines.map((line) => (
|
||||||
|
<Line line={line} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LineProps {
|
||||||
|
line: UpgradeLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Line({ line }: LineProps) {
|
||||||
|
const upgrades = Tankopedia.use((state) => state.protagonist.upgrades);
|
||||||
|
const id = Tankopedia.use((state) => state.protagonist.id);
|
||||||
|
const tank = useAwait(() => api.tank(id), `tank-${id}`);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.line}>
|
||||||
|
{line.stages.map((stage, index) => {
|
||||||
|
const isSelected = upgrades[line.name] === index;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{index !== 0 && <CaretDownIcon width="1em" height="1em" />}
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
variant={isSelected ? "solid" : "surface"}
|
||||||
|
radius="1"
|
||||||
|
className={styles.stage}
|
||||||
|
onClick={() => {
|
||||||
|
Tankopedia.mutate((draft) => {
|
||||||
|
draft.protagonist.upgrades[line.name] = index;
|
||||||
|
|
||||||
|
for (const required of stage.required_upgrades) {
|
||||||
|
for (const line of tank.tank!.upgrade_lines) {
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
for (const stage of line.stages) {
|
||||||
|
if (stage.tech_name === required) {
|
||||||
|
draft.protagonist.upgrades[line.name] = Math.max(
|
||||||
|
draft.protagonist.upgrades[line.name],
|
||||||
|
i,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const line of tank.tank!.upgrade_lines) {
|
||||||
|
let i = draft.protagonist.upgrades[line.name];
|
||||||
|
|
||||||
|
while (i > 0) {
|
||||||
|
const currentStage = line.stages[i];
|
||||||
|
const valid = currentStage.required_upgrades.every(
|
||||||
|
(required) => {
|
||||||
|
for (const line of tank.tank!.upgrade_lines) {
|
||||||
|
const idx = draft.protagonist.upgrades[line.name];
|
||||||
|
|
||||||
|
if (line.stages[idx]?.tech_name === required) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (valid) break;
|
||||||
|
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
draft.protagonist.upgrades[line.name] = i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img src={`/api/tanks/modules/${stage.stage_type}.webp`} />
|
||||||
|
</IconButton>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -46,7 +46,7 @@ export abstract class AbstractAPI {
|
|||||||
return supported;
|
return supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Cache<[string, string, boolean]>((...args) => args.join("-"))
|
@Cache()
|
||||||
async groupedGameStrings(locale: string, group: string, prefix: boolean) {
|
async groupedGameStrings(locale: string, group: string, prefix: boolean) {
|
||||||
this.assertLocale(locale);
|
this.assertLocale(locale);
|
||||||
|
|
||||||
@@ -64,9 +64,7 @@ export abstract class AbstractAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Cache<Arguments extends unknown[]>(
|
export function Cache<Arguments extends unknown[]>(disableInDev = false) {
|
||||||
discriminator: (...args: Arguments) => string = (...args) => args.join("-"),
|
|
||||||
) {
|
|
||||||
const cache = new WeakMap<object, Map<string, Promise<unknown>>>();
|
const cache = new WeakMap<object, Map<string, Promise<unknown>>>();
|
||||||
|
|
||||||
return function (
|
return function (
|
||||||
@@ -77,7 +75,7 @@ export function Cache<Arguments extends unknown[]>(
|
|||||||
const original = descriptor.value;
|
const original = descriptor.value;
|
||||||
|
|
||||||
descriptor.value = function (...args: Arguments) {
|
descriptor.value = function (...args: Arguments) {
|
||||||
const key = discriminator(...args);
|
const key = args.join("-");
|
||||||
|
|
||||||
let thisCache = cache.get(this);
|
let thisCache = cache.get(this);
|
||||||
|
|
||||||
@@ -86,7 +84,9 @@ export function Cache<Arguments extends unknown[]>(
|
|||||||
cache.set(this, thisCache);
|
cache.set(this, thisCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thisCache.has(key)) {
|
const disabled = disableInDev && import.meta.env.DEV;
|
||||||
|
|
||||||
|
if (thisCache.has(key) && !disabled) {
|
||||||
return thisCache.get(key);
|
return thisCache.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ export class ServerAPI extends AbstractAPI {
|
|||||||
return tiers;
|
return tiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Cache()
|
@Cache(true)
|
||||||
async strings(locale: string) {
|
async strings(locale: string) {
|
||||||
const localized = (await globbedStrings[
|
const localized = (await globbedStrings[
|
||||||
`../../../../i18n/strings/${locale}.json`
|
`../../../../i18n/strings/${locale}.json`
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Grade } from "@blitzkit/closed/protos/game/proto/legacy/blitz_static_standard_grades_enum";
|
|
||||||
import { StageParameters_StageType } from "@blitzkit/closed/protos/game/proto/legacy/blitz_static_tank_upgrade_single_stage";
|
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
import { TankopediaLoadout } from "../../../../components/TankopediaLoadout";
|
||||||
import { api } from "../../../../core/api/dynamic";
|
import { api } from "../../../../core/api/dynamic";
|
||||||
import { characteristicsOrder } from "../../../../core/tankopedia/characteristicsOrder";
|
import { characteristicsOrder } from "../../../../core/tankopedia/characteristicsOrder";
|
||||||
import { computeCharacteristics } from "../../../../core/tankopedia/computeCharacteristics";
|
import { computeCharacteristics } from "../../../../core/tankopedia/computeCharacteristics";
|
||||||
@@ -48,7 +47,9 @@ function Content() {
|
|||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<h2>upgrades</h2>
|
<TankopediaLoadout />
|
||||||
|
|
||||||
|
{/* <h2>upgrades</h2>
|
||||||
|
|
||||||
{protagonistTank.tank!.upgrade_lines.map((line) => {
|
{protagonistTank.tank!.upgrade_lines.map((line) => {
|
||||||
return (
|
return (
|
||||||
@@ -145,7 +146,7 @@ function Content() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
})}
|
})} */}
|
||||||
|
|
||||||
<h2>characteristics</h2>
|
<h2>characteristics</h2>
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user