132 lines
3.8 KiB
TypeScript
132 lines
3.8 KiB
TypeScript
import {
|
|
AbilityManager,
|
|
CharacterPreferences,
|
|
CharacterTheme,
|
|
Constants,
|
|
} from "@dndbeyond/character-rules-engine/es";
|
|
import { RollTypes } from "@dndbeyond/pocket-dimension-dice/constants";
|
|
import { RollContext } from "@dndbeyond/pocket-dimension-dice/types";
|
|
|
|
import { NumberDisplay } from "~/components/NumberDisplay";
|
|
|
|
import BoxBackground from "../BoxBackground";
|
|
import { DigitalDiceWrapper } from "../Dice";
|
|
import { DigitalDiceWrapperProps } from "../Dice/DigitalDiceWrapper/DigitalDiceWrapper";
|
|
import AbilityScoreBoxSvg from "../Svg/boxes/AbilityScoreBoxSvg";
|
|
|
|
interface Props {
|
|
className?: string;
|
|
ability: AbilityManager | { name: string; score: number; modifier: number };
|
|
preferences: CharacterPreferences;
|
|
theme: CharacterTheme;
|
|
onClick?: (ability: AbilityManager) => void;
|
|
diceEnabled?: boolean;
|
|
rollContext: RollContext;
|
|
}
|
|
export default function AbilitySummary({
|
|
className = "",
|
|
ability,
|
|
preferences,
|
|
theme,
|
|
onClick,
|
|
diceEnabled = false,
|
|
rollContext,
|
|
}: Props) {
|
|
const isManager = "getStatKey" in ability;
|
|
|
|
const handleClick = (evt: React.MouseEvent): void => {
|
|
if (onClick && isManager) {
|
|
evt.stopPropagation();
|
|
evt.nativeEvent.stopImmediatePropagation();
|
|
onClick(ability);
|
|
}
|
|
};
|
|
|
|
let classNames: Array<string> = [className, "ddbc-ability-summary"];
|
|
|
|
let primaryNode: React.ReactNode;
|
|
let secondaryNode: React.ReactNode;
|
|
if (!ability) return null;
|
|
const abilityStatKey = isManager ? ability.getStatKey() : 0;
|
|
const abilityLabel = isManager ? ability.getLabel() : ability.name;
|
|
const abilityName = isManager ? ability.getName() : ability.name;
|
|
const abilityModifier = Number(
|
|
isManager ? ability.getModifier() ?? 0 : ability.modifier
|
|
);
|
|
const abilityTotalScore = isManager ? ability.getTotalScore() : ability.score;
|
|
|
|
const diceWrapperProps: DigitalDiceWrapperProps = {
|
|
rollType: RollTypes.Check,
|
|
action: abilityName,
|
|
isDiceEnabled: diceEnabled,
|
|
diceNotation: `1d20${
|
|
abilityModifier > 0
|
|
? `+${abilityModifier}`
|
|
: abilityModifier !== 0
|
|
? abilityModifier
|
|
: ""
|
|
}`,
|
|
entityId: String(rollContext.entityId),
|
|
entityType: String(rollContext.entityType),
|
|
name: String(rollContext.name),
|
|
};
|
|
|
|
if (
|
|
preferences.abilityScoreDisplayType ===
|
|
Constants.PreferenceAbilityScoreDisplayTypeEnum.SCORES_TOP
|
|
) {
|
|
primaryNode = (
|
|
<DigitalDiceWrapper {...diceWrapperProps}>
|
|
{abilityTotalScore}
|
|
</DigitalDiceWrapper>
|
|
);
|
|
|
|
if (abilityModifier === null) {
|
|
secondaryNode = "--";
|
|
} else {
|
|
secondaryNode = <NumberDisplay type="signed" number={abilityModifier} />;
|
|
}
|
|
} else {
|
|
if (abilityModifier === null) {
|
|
primaryNode = "--";
|
|
} else {
|
|
primaryNode = (
|
|
<DigitalDiceWrapper {...diceWrapperProps}>
|
|
<NumberDisplay number={abilityModifier} type="signed" size="large" />
|
|
</DigitalDiceWrapper>
|
|
);
|
|
}
|
|
secondaryNode = abilityTotalScore;
|
|
}
|
|
|
|
return (
|
|
<div className={classNames.join(" ")} onClick={handleClick}>
|
|
<BoxBackground StyleComponent={AbilityScoreBoxSvg} theme={theme} />
|
|
<div className="ddbc-ability-summary__heading">
|
|
<span
|
|
className={`ddbc-ability-summary__label ${
|
|
theme.isDarkMode ? "ddbc-ability-summary__label--dark-mode" : ""
|
|
}`}
|
|
>
|
|
{abilityLabel}
|
|
</span>
|
|
<span className="ddbc-ability-summary__abbr">{abilityStatKey}</span>
|
|
</div>
|
|
<div
|
|
className={`ddbc-ability-summary__primary ${
|
|
theme.isDarkMode ? "ddbc-ability-summary__primary--dark-mode" : ""
|
|
}`}
|
|
>
|
|
{primaryNode}
|
|
</div>
|
|
<div
|
|
className={`ddbc-ability-summary__secondary ${
|
|
theme.isDarkMode ? "ddbc-ability-summary__secondary--dark-mode" : ""
|
|
}`}
|
|
>
|
|
{secondaryNode}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|