Files
dndbeyond_src/ddb_main/subApps/sheet/components/InitiativeBox/InitiativeBox.tsx
T

122 lines
3.5 KiB
TypeScript

import clsx from "clsx";
import { FC, HTMLAttributes } from "react";
import { useSelector } from "react-redux";
import {
AdvantageIcon,
BoxBackground,
DigitalDiceWrapper,
InitiativeBoxSvg,
} from "@dndbeyond/character-components/es";
import {
RollKinds,
RollTypes,
} from "@dndbeyond/pocket-dimension-dice/constants";
import { NumberDisplay } from "~/components/NumberDisplay";
import { useCharacterTheme } from "~/contexts/CharacterTheme";
import { useSidebar } from "~/contexts/Sidebar";
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
import a11yStyles from "~/styles/accessibility.module.css";
import {
appEnvSelectors,
characterRollContextSelectors,
} from "~/tools/js/Shared/selectors";
import { PaneComponentEnum } from "../Sidebar/types";
import styles from "./styles.module.css";
interface Props extends HTMLAttributes<HTMLDivElement> {
isMobile?: boolean;
isTablet?: boolean;
}
export const InitiativeBox: FC<Props> = ({ isMobile, isTablet, ...props }) => {
const {
pane: { paneHistoryStart },
} = useSidebar();
const handleClick = (evt: React.MouseEvent): void => {
evt.stopPropagation();
evt.nativeEvent.stopImmediatePropagation();
paneHistoryStart(PaneComponentEnum.INITIATIVE);
};
const {
hasInitiativeAdvantage,
processedInitiative,
characterTheme: theme,
} = useCharacterEngine();
const initiative = Number(processedInitiative);
const { isDarkMode } = useCharacterTheme();
const diceEnabled = useSelector(appEnvSelectors.getDiceEnabled);
const rollContext = useSelector(
characterRollContextSelectors.getCharacterRollContext
);
return (
<section
className={clsx([isMobile ? styles.boxMobile : styles.box])}
onClick={handleClick}
{...props}
>
{!isMobile && (
<div
className={clsx([
styles.label,
isDarkMode && !isTablet && styles.dark,
])}
data-testid="combat-initiative-label"
>
Initiative
</div>
)}
<div className={isMobile ? styles.valueMobile : styles.value}>
{!isMobile && (
<>
<BoxBackground StyleComponent={InitiativeBoxSvg} theme={theme} />
<h2 className={a11yStyles.screenreaderOnly}>Initiative</h2>
</>
)}
<DigitalDiceWrapper
diceNotation={`1d20${
initiative > 0
? `+${initiative}`
: initiative !== 0
? initiative
: ""
}`}
rollType={RollTypes.Roll}
action="Initiative"
rollKind={hasInitiativeAdvantage ? RollKinds.Advantage : undefined}
isDiceEnabled={diceEnabled}
entityId={String(rollContext.entityId)}
entityType={String(rollContext.entityType)}
name={String(rollContext.name)}
>
<NumberDisplay
number={initiative}
type="signed"
size="large"
className={clsx([
isMobile && !theme.isDarkMode && styles.numberColorOverride,
])}
/>
</DigitalDiceWrapper>
</div>
{hasInitiativeAdvantage && (
<div
className={clsx([styles.advantage, isMobile && styles.mobile])}
aria-label="Has advantage on initiative"
>
<AdvantageIcon
theme={theme}
className={styles.advantageIcon}
title={"Advantage on Initiative"}
/>
</div>
)}
{isMobile && <div className={styles.labelMobile}>Initiative</div>}
</section>
);
};