5180 fichiers 38.5 Mo 0 téléchargements 378 vues mis à jour il y a 7 heures ui
nitro-v36-with-renderer-v36 / src / components / wired / views / selectors / WiredSelectorFurniAltitudeView.tsx
WiredSelectorFurniAltitudeView.tsx 4.4 Ko Télécharger le fichier
import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText, WiredFurniType } from '../../../../api';
import { Slider, Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { WiredSelectorBaseView } from './WiredSelectorBaseView';
import { Radio } from '../../../../common/Radio';
import { NativeTextTree } from '../../../../common/native-text/NativeTextTree';

const MIN_ALTITUDE = 0;
const MAX_ALTITUDE = 80;
const ALTITUDE_STEP = 0.01;
const ALTITUDE_PATTERN = /^\d*(\.\d{0,2})?$/;

const clampAltitude = (value: number) => {
    if (isNaN(value)) return MIN_ALTITUDE;

    const clamped = Math.min(MAX_ALTITUDE, Math.max(MIN_ALTITUDE, value));

    return parseFloat(clamped.toFixed(2));
};

const formatAltitude = (value: number) => {
    const normalized = clampAltitude(value);
    const text = normalized.toFixed(2);

    return text.replace(/\.00$/, '').replace(/(\.\d)0$/, '$1');
};

export const WiredSelectorFurniAltitudeView: FC<{}> = () => {
    const { trigger = null, setIntParams = null, setStringParam = null } = useWired();
    const [comparison, setComparison] = useState(1);
    const [altitude, setAltitude] = useState(0);
    const [altitudeInput, setAltitudeInput] = useState('0');

    useEffect(() => {
        if (!trigger) return;

        // Official layout: [altitude in hundredths, comparison].
        const nextAltitude = clampAltitude((trigger.intData[0] ?? 0) / 100);

        setComparison(trigger.intData.length > 1 ? trigger.intData[1] : 1);
        setAltitude(nextAltitude);
        setAltitudeInput(formatAltitude(nextAltitude));
    }, [trigger]);

    const updateAltitude = (value: number) => {
        const nextValue = clampAltitude(value);

        setAltitude(nextValue);
        setAltitudeInput(formatAltitude(nextValue));
    };

    const updateAltitudeInput = (value: string) => {
        if (!ALTITUDE_PATTERN.test(value)) return;

        setAltitudeInput(value);

        if (!value.length) {
            setAltitude(0);
            return;
        }

        const parsedValue = parseFloat(value);

        if (isNaN(parsedValue)) return;

        if (parsedValue > MAX_ALTITUDE) {
            updateAltitude(MAX_ALTITUDE);
            return;
        }

        setAltitude(clampAltitude(parsedValue));
    };

    const save = useCallback(() => {
        setIntParams([Math.round(altitude * 100), comparison]);
        setStringParam('');
    }, [altitude, comparison, setIntParams, setStringParam]);

    return (
        <NativeTextTree>
            <WiredSelectorBaseView
                hasSpecialInput={true}
                requiresFurni={WiredFurniType.STUFF_SELECTION_OPTION_NONE}
                save={save}
                hideDelay={true}
                cardStyle={{ width: 400 }}
            >
                <div className="flex flex-col gap-2">
                    <div className="flex flex-col gap-1">
                        {[0, 1, 2].map((value) => {
                            return (
                                <label key={value} className="flex items-center gap-1">
                                    <Radio checked={comparison === value} name="furniAltitudeComparison" onCheckedChange={() => setComparison(value)} />
                                    <Text>{LocalizeText(`wiredfurni.params.comparison.${value}`)}</Text>
                                </label>
                            );
                        })}
                    </div>

                    <div className="flex flex-col gap-1">
                        <Text bold>{LocalizeText('wiredfurni.params.setaltitude')}</Text>
                        <input
                            className="form-control form-control-sm"
                            inputMode="decimal"
                            type="text"
                            value={altitudeInput}
                            onBlur={() => setAltitudeInput(formatAltitude(altitude))}
                            onChange={(event) => updateAltitudeInput(event.target.value)}
                        />
                    </div>

                    <div className="flex flex-col gap-1">
                        <Slider max={MAX_ALTITUDE} min={MIN_ALTITUDE} step={ALTITUDE_STEP} value={altitude} onChange={(event) => updateAltitude(event as number)} />
                        <Text small>{formatAltitude(altitude)}</Text>
                    </div>

                </div>
            </WiredSelectorBaseView>
        </NativeTextTree>
    );
};
15Sujets
1Dépôts
20Membres
3En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser