import clsx from "clsx";
import { FC, HTMLAttributes, ReactNode } from "react";
import { Constants } from "@dndbeyond/character-rules-engine/es";
import { NumberDisplayType } from "~/types";
import styles from "./styles.module.css";
const { FEET_IN_MILES } = Constants;
export interface NumberDisplayProps extends HTMLAttributes {
number: number | null;
type: NumberDisplayType;
isModified?: boolean;
size?: "large";
numberFallback?: ReactNode;
}
export const NumberDisplay: FC = ({
number,
type,
isModified = false,
size,
numberFallback = "--",
className,
...props
}) => {
let label = "";
let sign = "";
switch (type) {
case "weightInLb":
label = "lb.";
number = number && Math.round((number + Number.EPSILON) * 100) / 100;
break;
case "distanceInFt":
if (number && number % FEET_IN_MILES === 0) {
number = number / FEET_IN_MILES;
label = `mile${Math.abs(number) === 1 ? "" : "s"}`;
} else {
label = "ft.";
}
break;
case "signed":
if (number != null) {
sign = number >= 0 ? "+" : "-";
number = Math.abs(number);
}
break;
default:
break;
}
return (
{type === "signed" && (
/* NOTE: aria-label needs to go on an interactable element, not a span.
This will need to be refactored onto the containing button.
*/
{sign}
)}
{number === null ? numberFallback : number}
{type !== "signed" && (
{label}
)}
);
};