LogoPixi’VN

Esempi di schermate dell'UI

Tutti gli esempi sono stati creati utilizzando elementi HTML di base; per migliorare la grafica, sarà necessario sostituirli con componenti UI dalla propria libreria preferita.

Schermata dell'UI del dialogo narrativo

Ad esempio:

import { useQueryDialogue } from "../hooks/useQueryInterface";
import ChoiceMenu from "./ChoiceMenu";

export default function NarrationScreen() {
    const { data: { text, character } = {} } = useQueryDialogue();

    return (
        <div
            style={{
                position: "absolute",
                display: "flex",
                flexDirection: "column",
                height: "100%",
                width: "100%",
            }}
        >
            <div style={{ flex: 1, minHeight: 0 }}>
                {/* READ THIS: https://pixi-vn.web.app/start/choices.html#how-to-create-the-choice-menu-ui-screen */}
                <ChoiceMenu />
            </div>
            {text && (
                <div
                    style={{
                        flex: "0 0 auto",
                        height: "30%",
                        minHeight: 0,
                        pointerEvents: "auto",
                        backgroundColor: "white",
                        display: "flex",
                        flexDirection: "column",
                        overflow: "hidden",
                    }}
                >
                    {character && character.name && <b>{`${character?.name || ""} ${character?.surname || ""}`}</b>}
                    <div
                        style={{
                            display: "flex",
                            flexDirection: "row",
                            height: "100%",
                            minHeight: 0,
                            overflow: "hidden",
                        }}
                    >
                        {character?.icon && (
                            <img
                                src={character?.icon}
                                loading='lazy'
                                alt=''
                                style={{
                                    maxWidth: "30%",
                                    height: "auto",
                                    objectFit: "contain",
                                    display: "block",
                                }}
                            />
                        )}
                        <div style={{ flex: 1, minHeight: 0, overflow: "auto", height: "100%" }}>{text}</div>
                    </div>
                </div>
            )}
        </div>
    );
}

Schermata dell'UI del menu di scelta

Ad esempio:

import useNarrationFunctions from "../hooks/useNarrationFunctions";
import { useQueryChoiceMenuOptions } from "../hooks/useQueryInterface";

export default function ChoiceMenu() {
    const { data: menu = [] } = useQueryChoiceMenuOptions();
    const { selectChoice } = useNarrationFunctions();

    return (
        <div
            style={{
                display: "flex",
                flexDirection: "column",
                justifyContent: "center",
                alignItems: "center",
                width: "100%",
                height: "100%",
                overflow: "auto",
                gap: "8px",
                maxHeight: "100%",
                margin: 0,
                pointerEvents: menu?.length > 0 ? "auto" : "none",
            }}
        >
            {menu?.map((item, index) => (
                <button
                    key={"choice-" + index}
                    style={{
                        justifyContent: "center",
                        alignItems: "center",
                    }}
                    onClick={() => selectChoice(item)}
                >
                    {item.text}
                </button>
            ))}
        </div>
    );
}

Go next button

Ad esempio:

import { useState } from "react";
import useNarrationFunctions from "../hooks/useNarrationFunctions";
import { useQueryCanGoNext } from "../hooks/useQueryInterface";

export default function NextButton() {
    const { data: canGoNext = false } = useQueryCanGoNext();
    const [loading, setLoading] = useState(false);
    const { goNext } = useNarrationFunctions();

    if (!canGoNext) {
        return null;
    }

    return (
        <button
            onClick={() => {
                setLoading(true);
                goNext()
                    .then(() => setLoading(false))
                    .catch(() => setLoading(false));
            }}
            disabled={loading}
            style={{
                width: 40,
                height: 20,
                pointerEvents: "auto",
            }}
        >
            Next
        </button>
    );
}

Go back button

Ad esempio:

import { useState } from "react";
import useNarrationFunctions from "../hooks/useNarrationFunctions";
import { useQueryCanGoBack } from "../hooks/useQueryInterface";

export default function BackButton() {
    const { data: canGoBack = false } = useQueryCanGoBack();
    const [loading, setLoading] = useState(false);
    const { goBack } = useNarrationFunctions();

    if (!canGoBack) {
        return null;
    }

    return (
        <button
            onClick={() => {
                setLoading(true);
                goBack()
                    .then(() => setLoading(false))
                    .catch(() => setLoading(false));
            }}
            disabled={loading}
            style={{
                width: 40,
                height: 20,
                pointerEvents: "auto",
            }}
        >
            Back
        </button>
    );
}

Input prompt dialog UI

Ad esempio:

import { narration } from "@drincs/pixi-vn";
import { useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { INTERFACE_DATA_USE_QUEY_KEY, useQueryDialogue, useQueryInputValue } from "../../hooks/useQueryInterface";

export default function TextInput() {
    const { data: { text } = {} } = useQueryDialogue();
    const {
        data: { isRequired: open, currentValue } = {
            currentValue: undefined,
            isRequired: false,
        },
    } = useQueryInputValue<string | number>();
    const [tempValue, setTempValue] = useState<string | number>();
    const queryClient = useQueryClient();

    return (
        <dialog
            open={open}
            style={{
                pointerEvents: "auto",
            }}
        >
            <p>{text}</p>
            {open && (
                <input
                    defaultValue={currentValue || ""}
                    onChange={(e) => {
                        if (e && e.target && "value" in e.target) {
                            let value: any = e.target.value;
                            if ("type" in e.target && e.target.type === "number" && "valueAsNumber" in e.target) {
                                value = e.target.valueAsNumber;
                            }
                            setTempValue(value);
                        }
                    }}
                />
            )}
            <button
                onClick={() => {
                    narration.inputValue = tempValue || currentValue;
                    setTempValue(undefined);
                    queryClient.invalidateQueries({
                        queryKey: [INTERFACE_DATA_USE_QUEY_KEY],
                    });
                }}
            >
                Confirm
            </button>
        </dialog>
    );
}

History UI screen

Ad esempio:

import { Box, Stack } from "@mui/system";
import React from "react";
import { useQueryNarrativeHistory } from "../use_query/useQueryInterface";

export default function HistoryScreen() {
    const { data = [] } = useQueryNarrativeHistory();

    return (
        <dialog
            open={true}
            style={{
                height: "80%",
            }}
        >
            <Box
                sx={{
                    display: "flex",
                    flex: 1,
                    minHeight: 0,
                    px: 2,
                    py: 3,
                    overflowY: "scroll",
                    flexDirection: "column-reverse",
                    pointerEvents: "auto",
                    overflow: "auto",
                    height: "80%",
                }}
            >
                <Stack spacing={2} justifyContent="flex-end">
                {data.map((data, index) => {
                    return (
                    <React.Fragment key={"history" + index}>
                        <Stack direction="row" spacing={1.5}>
                            <img
                                src={data.icon}
                                loading="lazy"
                                alt=""
                                style={{
                                    verticalAlign: "middle",
                                    maxWidth: "50px",
                                    maxHeight: "50px",
                                    borderRadius: "50%",
                                }}
                            />
                            <Box sx={{ flex: 1 }}>
                                {data.character && data.character}
                                <div />
                                {data.text}
                            </Box>
                        </Stack>
                        <Stack direction="row" spacing={0.5}>
                            <Box sx={{ flex: 1 }}>
                                {data.choices &&
                                data.choices.map((choice, index) => {
                                    if (choice.hidden) {
                                        return null;
                                    }
                                    if (choice.isResponse) {
                                        return (
                                            <div
                                                key={"choices-success" + index}
                                                style={{
                                                    display: "inline-block",
                                                    padding: "5px 5px",
                                                    fontSize: "12px",
                                                    borderRadius: "25px",
                                                    backgroundColor: "#21ff3e",
                                                }}
                                            >
                                                {choice.text}
                                            </div>
                                        );
                                    }
                                    return (
                                        <div
                                            key={"choices" + index}
                                            style={{
                                                display: "inline-block",
                                                padding: "5px 5px",
                                                fontSize: "12px",
                                                borderRadius: "25px",
                                                backgroundColor: "#bcfdff",
                                            }}
                                        >
                                            {choice.text}
                                        </div>
                                    );
                                })}
                                {data.inputValue && (
                                    <div
                                        key={"choices-success" + index}
                                        style={{
                                            display: "inline-block",
                                            padding: "5px 5px",
                                            fontSize: "12px",
                                            borderRadius: "25px",
                                            backgroundColor: "#b0c2b2",
                                        }}
                                    >
                                        {data.inputValue.toString()}
                                    </div>
                                )}
                            </Box>
                        </Stack>
                    </React.Fragment>
                    );
                })}
                </Stack>
            </Box>
        </dialog>
    );
}