mirror of
https://github.com/k1tbyte/Wand-Enhancer.git
synced 2026-08-29 01:08:51 +00:00
a0b3968d33
Reorganize the panel around product capabilities and integrate the remote i18n feature from origin/master into the new structure. - Restructure src into capability features (app, trainer, library, remote-session, appearance, shared); move the bridge to bridge/src. - Add lingui-based UI localization and wrap remaining user-facing strings (Trans / msg macros); fix the 'END В·' mojibake. - Port WeMod cheat-metadata i18n: capture the access token from the snapshot's renderer in the bridge and fetch localized trainer_meta in remote-session.i18n; guarantee snapshot sync on token failure. - Wire vitest to the app's lingui/preact pipeline (mergeConfig).
50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
import { type FormEvent } from 'react';
|
|
|
|
import type { CheatSchema } from '../../../protocol/messages';
|
|
import { resolveOption } from '../model/values';
|
|
import { formatNumber, numericValue } from './format-number';
|
|
import { SliderTrack, type ControlInternalProps } from './shared';
|
|
|
|
export const ScalarControl = ({ cheat, value, disabled, onChange }: ControlInternalProps) => {
|
|
const numericOptions = getNumericOptions(cheat.args.options ?? []);
|
|
const min = cheat.args.min ?? numericOptions[0] ?? 0;
|
|
const max = cheat.args.max ?? numericOptions[numericOptions.length - 1] ?? 100;
|
|
const step = cheat.args.step ?? inferStep(numericOptions) ?? 1;
|
|
const currentValue = numericValue(value, min);
|
|
const handleInput = (event: FormEvent<HTMLInputElement>) => onChange(Number(event.currentTarget.value));
|
|
|
|
return (
|
|
<div className="w-full">
|
|
<div className="mb-1 flex justify-end font-mono text-[12.5px] tabular-nums text-(--deck-accent)">
|
|
{formatNumber(currentValue, step)}{cheat.args.postfix ?? ''}
|
|
</div>
|
|
<SliderTrack disabled={disabled} max={max} min={min} step={step} value={currentValue} onInput={handleInput} />
|
|
<div className="mt-1 flex justify-between font-mono text-[10px] text-(--deck-fg-4)">
|
|
<span>{min}{cheat.args.postfix ?? ''}</span>
|
|
<span>{max}{cheat.args.postfix ?? ''}</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
function getNumericOptions(options: NonNullable<CheatSchema['args']['options']>): number[] {
|
|
return options
|
|
.map(resolveOption)
|
|
.map((option) => numericValue(option.value, Number.NaN))
|
|
.filter((option) => Number.isFinite(option))
|
|
.sort((left, right) => left - right);
|
|
}
|
|
|
|
function inferStep(options: number[]): number | null {
|
|
if (options.length < 2) {
|
|
return null;
|
|
}
|
|
|
|
const steps = options
|
|
.slice(1)
|
|
.map((option, index) => Math.abs(option - options[index]))
|
|
.filter((option) => option > 0);
|
|
|
|
return steps.length > 0 ? Math.min(...steps) : null;
|
|
}
|