Grabbed dndbeyond's source code
``` ~/go/bin/sourcemapper -output ddb -jsurl https://media.dndbeyond.com/character-app/static/js/main.90aa78c5.js ```
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import React from "react";
|
||||
import { connect, DispatchProp } from "react-redux";
|
||||
|
||||
import {
|
||||
CharacterTheme,
|
||||
rulesEngineSelectors,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
import { SheetAppState } from "../../../typings";
|
||||
import Actions from "../../Actions";
|
||||
|
||||
interface Props extends DispatchProp {
|
||||
theme: CharacterTheme;
|
||||
}
|
||||
class ActionsMobile extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
|
||||
return (
|
||||
<SubsectionMobile>
|
||||
<section className="ct-actions-mobile">
|
||||
<h2 style={visuallyHidden}>Actions</h2>
|
||||
<MobileDivider label="Actions" theme={theme} />
|
||||
<Actions showNotes={false} />
|
||||
<MobileDivider isEnd={true} theme={theme} />
|
||||
</section>
|
||||
</SubsectionMobile>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: SheetAppState) {
|
||||
return {
|
||||
theme: rulesEngineSelectors.getCharacterTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(ActionsMobile);
|
||||
@@ -0,0 +1,4 @@
|
||||
import ActionsMobile from "./ActionsMobile";
|
||||
|
||||
export default ActionsMobile;
|
||||
export { ActionsMobile };
|
||||
@@ -0,0 +1,244 @@
|
||||
import clsx from "clsx";
|
||||
import React from "react";
|
||||
import { connect, DispatchProp } from "react-redux";
|
||||
|
||||
import {
|
||||
CharacterPreferences,
|
||||
SpeedInfo,
|
||||
RuleData,
|
||||
RuleDataUtils,
|
||||
rulesEngineSelectors,
|
||||
CharacterTheme,
|
||||
characterSelectors,
|
||||
CharacterStatusSlug,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
import { GameLogContext } from "@dndbeyond/game-log-components";
|
||||
|
||||
import { NumberDisplay } from "~/components/NumberDisplay";
|
||||
import { PremadeCharacterEditStatus } from "~/components/PremadeCharacterEditStatus";
|
||||
import { useSidebar } from "~/contexts/Sidebar";
|
||||
import { PaneInfo } from "~/contexts/Sidebar/Sidebar";
|
||||
import { InitiativeBox } from "~/subApps/sheet/components/InitiativeBox";
|
||||
import { PaneComponentEnum } from "~/subApps/sheet/components/Sidebar/types";
|
||||
|
||||
import { appEnvSelectors } from "../../../../Shared/selectors";
|
||||
import { SheetAppState } from "../../../typings";
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
interface Props extends DispatchProp {
|
||||
armorClass: number;
|
||||
speeds: SpeedInfo;
|
||||
proficiencyBonus: number;
|
||||
preferences: CharacterPreferences;
|
||||
ruleData: RuleData;
|
||||
diceEnabled: boolean;
|
||||
theme: CharacterTheme;
|
||||
paneHistoryStart: PaneInfo["paneHistoryStart"];
|
||||
isReadonly: boolean;
|
||||
characterStatus: CharacterStatusSlug | null;
|
||||
}
|
||||
class CombatMobile extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
diceEnabled: false,
|
||||
};
|
||||
|
||||
handleProficiencyBonusClick = (evt: React.MouseEvent): void => {
|
||||
const { paneHistoryStart } = this.props;
|
||||
evt.stopPropagation();
|
||||
evt.nativeEvent.stopImmediatePropagation();
|
||||
paneHistoryStart(PaneComponentEnum.PROFICIENCY_BONUS);
|
||||
};
|
||||
|
||||
handleSpeedsClick = (evt: React.MouseEvent): void => {
|
||||
const { paneHistoryStart } = this.props;
|
||||
evt.stopPropagation();
|
||||
evt.nativeEvent.stopImmediatePropagation();
|
||||
paneHistoryStart(PaneComponentEnum.SPEED_MANAGE);
|
||||
};
|
||||
|
||||
handleDefensesSummaryClick = (evt: React.MouseEvent): void => {
|
||||
const { paneHistoryStart } = this.props;
|
||||
evt.stopPropagation();
|
||||
evt.nativeEvent.stopImmediatePropagation();
|
||||
paneHistoryStart(PaneComponentEnum.DEFENSE_MANAGE);
|
||||
};
|
||||
|
||||
handleConditionSummaryClick = (evt: React.MouseEvent): void => {
|
||||
const { paneHistoryStart } = this.props;
|
||||
evt.stopPropagation();
|
||||
evt.nativeEvent.stopImmediatePropagation();
|
||||
paneHistoryStart(PaneComponentEnum.CONDITION_MANAGE);
|
||||
};
|
||||
|
||||
handleArmorClassClick = (evt: React.MouseEvent): void => {
|
||||
const { paneHistoryStart } = this.props;
|
||||
evt.stopPropagation();
|
||||
evt.nativeEvent.stopImmediatePropagation();
|
||||
paneHistoryStart(PaneComponentEnum.ARMOR_MANAGE);
|
||||
};
|
||||
|
||||
handleInitiativeClick = (evt: React.MouseEvent): void => {
|
||||
const { paneHistoryStart } = this.props;
|
||||
evt.stopPropagation();
|
||||
evt.nativeEvent.stopImmediatePropagation();
|
||||
paneHistoryStart(PaneComponentEnum.INITIATIVE);
|
||||
};
|
||||
|
||||
renderProficiency = (): React.ReactNode => {
|
||||
const { proficiencyBonus } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="ct-combat-mobile__extra ct-combat-mobile__extra--proficiency"
|
||||
onClick={this.handleProficiencyBonusClick}
|
||||
>
|
||||
<div className="ct-combat-mobile__extra-heading">
|
||||
<div className="ct-combat-mobile__extra-label">Proficiency</div>
|
||||
</div>
|
||||
<div className="ct-combat-mobile__extra-value">
|
||||
<NumberDisplay
|
||||
type="signed"
|
||||
number={proficiencyBonus}
|
||||
size={"large"}
|
||||
className={clsx([
|
||||
!this.props.theme.isDarkMode && styles.numberColorOverride,
|
||||
])}
|
||||
/>
|
||||
</div>
|
||||
<div className="ct-combat-mobile__extra-footer">
|
||||
<div className="ct-combat-mobile__extra-label">Bonus</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
renderSpeed = (): React.ReactNode => {
|
||||
const { preferences, speeds, ruleData, theme } = this.props;
|
||||
|
||||
const displaySpeedValue: number =
|
||||
speeds[
|
||||
RuleDataUtils.getSpeedMovementKeyById(preferences.primaryMovement)
|
||||
];
|
||||
const displaySpeedLabel = RuleDataUtils.getMovementDescription(
|
||||
preferences.primaryMovement,
|
||||
ruleData
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="ct-combat-mobile__extra ct-combat-mobile__extra--speed"
|
||||
onClick={this.handleSpeedsClick}
|
||||
>
|
||||
<div className="ct-combat-mobile__extra-heading">
|
||||
<div className="ct-combat-mobile__extra-subheading">
|
||||
{displaySpeedLabel}
|
||||
</div>
|
||||
</div>
|
||||
<div className="ct-combat-mobile__extra-value">
|
||||
<NumberDisplay
|
||||
type="distanceInFt"
|
||||
number={displaySpeedValue}
|
||||
size={"large"}
|
||||
className={clsx([
|
||||
!this.props.theme.isDarkMode && styles.numberColorOverride,
|
||||
])}
|
||||
/>
|
||||
</div>
|
||||
<div className="ct-combat-mobile__extra-footer">
|
||||
<div className="ct-combat-mobile__extra-label">Speed</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
renderArmorClass = (): React.ReactNode => {
|
||||
const { armorClass } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="ct-combat-mobile__extra ct-combat-mobile__extra--ac"
|
||||
onClick={this.handleArmorClassClick}
|
||||
>
|
||||
<div className="ct-combat-mobile__extra-heading">
|
||||
<div className="ct-combat-mobile__extra-label">Armor</div>
|
||||
</div>
|
||||
<div
|
||||
className="ct-combat-mobile__extra-value"
|
||||
data-testid="armor-class-value"
|
||||
>
|
||||
{armorClass}
|
||||
</div>
|
||||
<div className="ct-combat-mobile__extra-footer">
|
||||
<div className="ct-combat-mobile__extra-label">Class</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { theme, isReadonly, characterStatus } = this.props;
|
||||
return (
|
||||
<div
|
||||
className={`ct-combat-mobile ${
|
||||
theme.isDarkMode ? "ct-combat-mobile--dark-mode" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="ct-combat-mobile__extras">
|
||||
{this.renderProficiency()}
|
||||
{this.renderSpeed()}
|
||||
<InitiativeBox isMobile={true} />
|
||||
{this.renderArmorClass()}
|
||||
<div className="ct-combat-mobile__extra ct-combat-mobile__extra--statuses">
|
||||
<div className="ct-combat-mobile__ctas">
|
||||
<div className="ct-combat-mobile__cta">
|
||||
<div
|
||||
className="ct-combat-mobile__cta-button"
|
||||
onClick={this.handleDefensesSummaryClick}
|
||||
>
|
||||
Defenses
|
||||
</div>
|
||||
</div>
|
||||
<div className="ct-combat-mobile__cta">
|
||||
<div
|
||||
className="ct-combat-mobile__cta-button"
|
||||
onClick={this.handleConditionSummaryClick}
|
||||
>
|
||||
Conditions
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<PremadeCharacterEditStatus
|
||||
characterStatus={characterStatus}
|
||||
isReadonly={isReadonly}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: SheetAppState) {
|
||||
return {
|
||||
armorClass: rulesEngineSelectors.getAcTotal(state),
|
||||
proficiencyBonus: rulesEngineSelectors.getProficiencyBonus(state),
|
||||
speeds: rulesEngineSelectors.getCurrentCarriedWeightSpeed(state),
|
||||
preferences: rulesEngineSelectors.getCharacterPreferences(state),
|
||||
ruleData: rulesEngineSelectors.getRuleData(state),
|
||||
diceEnabled: appEnvSelectors.getDiceEnabled(state),
|
||||
theme: rulesEngineSelectors.getCharacterTheme(state),
|
||||
characterStatus: characterSelectors.getStatusSlug(state),
|
||||
isReadonly: appEnvSelectors.getIsReadonly(state),
|
||||
};
|
||||
}
|
||||
|
||||
const CombatMobileContainer = (props) => {
|
||||
const {
|
||||
pane: { paneHistoryStart },
|
||||
} = useSidebar();
|
||||
return <CombatMobile {...props} paneHistoryStart={paneHistoryStart} />;
|
||||
};
|
||||
|
||||
CombatMobileContainer.contextType = GameLogContext;
|
||||
|
||||
export default connect(mapStateToProps)(CombatMobileContainer);
|
||||
@@ -0,0 +1,4 @@
|
||||
import CombatMobile from "./CombatMobile";
|
||||
|
||||
export default CombatMobile;
|
||||
export { CombatMobile };
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import { FC } from "react";
|
||||
|
||||
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
|
||||
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
import Description from "../../Description";
|
||||
|
||||
export const DescriptionMobile: FC = () => {
|
||||
const { characterTheme } = useCharacterEngine();
|
||||
return (
|
||||
<SubsectionMobile className="ct-description-mobile">
|
||||
<MobileDivider label={"Background"} theme={characterTheme} />
|
||||
<section>
|
||||
<h2 style={visuallyHidden}>Background</h2>
|
||||
<Description theme={characterTheme} isVertical={true} />
|
||||
</section>
|
||||
<MobileDivider isEnd={true} theme={characterTheme} />
|
||||
</SubsectionMobile>
|
||||
);
|
||||
};
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import {
|
||||
CharacterTheme,
|
||||
rulesEngineSelectors,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import { PaneInfo, useSidebar } from "~/contexts/Sidebar/Sidebar";
|
||||
import { PaneComponentEnum } from "~/subApps/sheet/components/Sidebar/types";
|
||||
|
||||
import { appEnvSelectors } from "../../../../Shared/selectors";
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
import { SheetAppState } from "../../../typings";
|
||||
import { Equipment } from "../../Equipment";
|
||||
|
||||
interface Props {
|
||||
isReadonly: boolean;
|
||||
theme: CharacterTheme;
|
||||
paneHistoryStart: PaneInfo["paneHistoryStart"];
|
||||
}
|
||||
class EquipmentMobile extends React.PureComponent<Props> {
|
||||
handleManageClick = (): void => {
|
||||
const { paneHistoryStart, isReadonly } = this.props;
|
||||
|
||||
if (!isReadonly) {
|
||||
paneHistoryStart(PaneComponentEnum.EQUIPMENT_MANAGE);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isReadonly, theme } = this.props;
|
||||
|
||||
return (
|
||||
<SubsectionMobile>
|
||||
<MobileDivider
|
||||
label="Inventory"
|
||||
onClick={this.handleManageClick}
|
||||
isReadonly={isReadonly}
|
||||
theme={theme}
|
||||
/>
|
||||
<section className="ct-equipment-mobile">
|
||||
<h2 style={visuallyHidden}>Inventory</h2>
|
||||
<Equipment showNotes={false} />
|
||||
</section>
|
||||
<MobileDivider isEnd={true} theme={theme} />
|
||||
</SubsectionMobile>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: SheetAppState) {
|
||||
return {
|
||||
isReadonly: appEnvSelectors.getIsReadonly(state),
|
||||
theme: rulesEngineSelectors.getCharacterTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
const EquipmentMobileContainer = (props) => {
|
||||
const {
|
||||
pane: { paneHistoryStart },
|
||||
} = useSidebar();
|
||||
return <EquipmentMobile paneHistoryStart={paneHistoryStart} {...props} />;
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(EquipmentMobileContainer);
|
||||
@@ -0,0 +1,4 @@
|
||||
import EquipmentMobile from "./EquipmentMobile";
|
||||
|
||||
export default EquipmentMobile;
|
||||
export { EquipmentMobile };
|
||||
@@ -0,0 +1,68 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import {
|
||||
CharacterTheme,
|
||||
rulesEngineSelectors,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import { PaneInfo, useSidebar } from "~/contexts/Sidebar/Sidebar";
|
||||
import { PaneComponentEnum } from "~/subApps/sheet/components/Sidebar/types";
|
||||
|
||||
import { appEnvSelectors } from "../../../../Shared/selectors";
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
import { SheetAppState } from "../../../typings";
|
||||
import Extras from "../../Extras";
|
||||
|
||||
interface Props {
|
||||
isReadonly: boolean;
|
||||
theme: CharacterTheme;
|
||||
paneHistoryStart: PaneInfo["paneHistoryStart"];
|
||||
}
|
||||
class ExtrasMobile extends React.PureComponent<Props> {
|
||||
handleManageOpen = (): void => {
|
||||
const { paneHistoryStart, isReadonly } = this.props;
|
||||
|
||||
if (!isReadonly) {
|
||||
paneHistoryStart(PaneComponentEnum.EXTRA_MANAGE);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isReadonly, theme } = this.props;
|
||||
|
||||
return (
|
||||
<SubsectionMobile>
|
||||
<MobileDivider
|
||||
label="Extras"
|
||||
onClick={this.handleManageOpen}
|
||||
isReadonly={isReadonly}
|
||||
theme={theme}
|
||||
/>
|
||||
<section className="ct-extras-mobile">
|
||||
<h2 style={visuallyHidden}>Extras</h2>
|
||||
<Extras showNotes={false} />
|
||||
</section>
|
||||
<MobileDivider isEnd={true} theme={theme} />
|
||||
</SubsectionMobile>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: SheetAppState) {
|
||||
return {
|
||||
isReadonly: appEnvSelectors.getIsReadonly(state),
|
||||
theme: rulesEngineSelectors.getCharacterTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
const ExtrasMobileContainer = (props) => {
|
||||
const {
|
||||
pane: { paneHistoryStart },
|
||||
} = useSidebar();
|
||||
return <ExtrasMobile paneHistoryStart={paneHistoryStart} {...props} />;
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(ExtrasMobileContainer);
|
||||
@@ -0,0 +1,4 @@
|
||||
import ExtrasMobile from "./ExtrasMobile";
|
||||
|
||||
export default ExtrasMobile;
|
||||
export { ExtrasMobile };
|
||||
@@ -0,0 +1,41 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import React from "react";
|
||||
import { connect, DispatchProp } from "react-redux";
|
||||
|
||||
import {
|
||||
CharacterTheme,
|
||||
rulesEngineSelectors,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
import { SheetAppState } from "../../../typings";
|
||||
import Features from "../../Features";
|
||||
|
||||
interface Props extends DispatchProp {
|
||||
theme: CharacterTheme;
|
||||
}
|
||||
class FeaturesMobile extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
|
||||
return (
|
||||
<SubsectionMobile>
|
||||
<MobileDivider label="Features & Traits" theme={theme} />
|
||||
<section className="ct-features-mobile">
|
||||
<h2 style={visuallyHidden}>Features and Traits</h2>
|
||||
<Features />
|
||||
</section>
|
||||
<MobileDivider isEnd={true} theme={theme} />
|
||||
</SubsectionMobile>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: SheetAppState) {
|
||||
return {
|
||||
theme: rulesEngineSelectors.getCharacterTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(FeaturesMobile);
|
||||
@@ -0,0 +1,4 @@
|
||||
import FeaturesMobile from "./FeaturesMobile";
|
||||
|
||||
export default FeaturesMobile;
|
||||
export { FeaturesMobile };
|
||||
@@ -0,0 +1,176 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
import {
|
||||
AbilitySummary,
|
||||
CampaignSummary,
|
||||
SavingThrowsSummary,
|
||||
} from "@dndbeyond/character-components/es";
|
||||
import {
|
||||
AbilityManager,
|
||||
DataOrigin,
|
||||
rulesEngineSelectors,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import { useSidebar } from "~/contexts/Sidebar";
|
||||
import { useAbilities } from "~/hooks/useAbilities";
|
||||
|
||||
import { getDataOriginComponentInfo } from "../../../../../../subApps/sheet/components/Sidebar/helpers/paneUtils";
|
||||
import { PaneComponentEnum } from "../../../../../../subApps/sheet/components/Sidebar/types";
|
||||
import {
|
||||
appEnvSelectors,
|
||||
characterRollContextSelectors,
|
||||
} from "../../../../Shared/selectors";
|
||||
import { PaneIdentifierUtils } from "../../../../Shared/utils";
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import SavingThrowsDetails from "../../../components/SavingThrowsDetails";
|
||||
import Senses from "../../../components/Senses";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
|
||||
export default function MainMobile() {
|
||||
const abilities = useAbilities();
|
||||
const {
|
||||
pane: { paneHistoryStart, paneHistoryPush },
|
||||
} = useSidebar();
|
||||
const preferences = useSelector(rulesEngineSelectors.getCharacterPreferences);
|
||||
const savingThrowDiceAdjustments = useSelector(
|
||||
rulesEngineSelectors.getSavingThrowDiceAdjustments
|
||||
); // TODO: GFS move to mangers
|
||||
const situationalBonusSavingThrowsLookup = useSelector(
|
||||
rulesEngineSelectors.getSituationalBonusSavingThrowsLookup
|
||||
); // TODO: GFS move to mangers
|
||||
const passivePerception = useSelector(
|
||||
rulesEngineSelectors.getPassivePerception
|
||||
); // TODO: GFS move to mangers
|
||||
const passiveInvestigation = useSelector(
|
||||
rulesEngineSelectors.getPassiveInvestigation
|
||||
); // TODO: GFS move to mangers
|
||||
const passiveInsight = useSelector(rulesEngineSelectors.getPassiveInsight); // TODO: GFS move to mangers
|
||||
const senses = useSelector(rulesEngineSelectors.getSenseInfo); // TODO: GFS move to mangers
|
||||
const ruleData = useSelector(rulesEngineSelectors.getRuleData);
|
||||
const campaign = useSelector(rulesEngineSelectors.getCampaign);
|
||||
const theme = useSelector(rulesEngineSelectors.getCharacterTheme);
|
||||
const deathSaveInfo = useSelector(rulesEngineSelectors.getDeathSaveInfo);
|
||||
const diceEnabled = useSelector(appEnvSelectors.getDiceEnabled);
|
||||
const characterRollContext = useSelector(
|
||||
characterRollContextSelectors.getCharacterRollContext
|
||||
);
|
||||
const gameLog = useSelector(appEnvSelectors.getGameLog);
|
||||
|
||||
const handleSensesManageShow = (): void => {
|
||||
paneHistoryStart(PaneComponentEnum.SENSE_MANAGE);
|
||||
};
|
||||
|
||||
const handleSavingThrowsClick = (): void => {
|
||||
paneHistoryStart(PaneComponentEnum.SAVING_THROWS);
|
||||
};
|
||||
|
||||
const handleAbilitySummaryClick = (ability: AbilityManager): void => {
|
||||
paneHistoryStart(
|
||||
PaneComponentEnum.ABILITY,
|
||||
PaneIdentifierUtils.generateAbility(ability)
|
||||
);
|
||||
};
|
||||
|
||||
const handleAbilityClick = (ability: AbilityManager): void => {
|
||||
paneHistoryStart(
|
||||
PaneComponentEnum.ABILITY_SAVING_THROW,
|
||||
PaneIdentifierUtils.generateAbilitySavingThrows(ability.getId())
|
||||
);
|
||||
};
|
||||
|
||||
const handleDataOriginClick = (dataOrigin: DataOrigin): void => {
|
||||
let component = getDataOriginComponentInfo(dataOrigin);
|
||||
if (component.type !== PaneComponentEnum.ERROR_404) {
|
||||
paneHistoryPush(component.type, component.identifiers);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCampaignShow = (): void => {
|
||||
paneHistoryStart(PaneComponentEnum.CAMPAIGN);
|
||||
};
|
||||
|
||||
return (
|
||||
<SubsectionMobile name="Main">
|
||||
<div
|
||||
className={`ct-main-mobile ${
|
||||
theme.isDarkMode ? "ct-main-mobile--dark-mode" : ""
|
||||
}`}
|
||||
>
|
||||
{campaign && (
|
||||
<CampaignSummary
|
||||
campaign={campaign}
|
||||
onCampaignShow={handleCampaignShow}
|
||||
className={
|
||||
theme.isDarkMode
|
||||
? "ct-main-mobile__campaign-button--dark-mode"
|
||||
: ""
|
||||
}
|
||||
theme={theme}
|
||||
gameLog={gameLog}
|
||||
/>
|
||||
)}
|
||||
<section className="ct-main-mobile__abilities">
|
||||
<h2 style={visuallyHidden}>Ability Scores</h2>
|
||||
{abilities.map((ability) => (
|
||||
<div className="ct-main-mobile__ability" key={ability.getStatKey()}>
|
||||
<AbilitySummary
|
||||
ability={ability}
|
||||
preferences={preferences}
|
||||
theme={theme}
|
||||
onClick={handleAbilitySummaryClick}
|
||||
diceEnabled={diceEnabled}
|
||||
rollContext={characterRollContext}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</section>
|
||||
<MobileDivider
|
||||
label="Saving Throws"
|
||||
onClick={handleSavingThrowsClick}
|
||||
theme={theme}
|
||||
/>
|
||||
<section
|
||||
className={`ct-main-mobile__saving-throws ${
|
||||
theme.isDarkMode ? "ct-main-mobile__saving-throws--dark-mode" : ""
|
||||
}`}
|
||||
>
|
||||
<h2 style={visuallyHidden}>Saving Throws</h2>
|
||||
<SavingThrowsSummary
|
||||
abilities={abilities}
|
||||
situationalBonusSavingThrowsLookup={
|
||||
situationalBonusSavingThrowsLookup
|
||||
}
|
||||
onClick={handleAbilityClick}
|
||||
diceEnabled={diceEnabled}
|
||||
theme={theme}
|
||||
rollContext={characterRollContext}
|
||||
/>
|
||||
<SavingThrowsDetails
|
||||
theme={theme}
|
||||
ruleData={ruleData}
|
||||
savingThrowDiceAdjustments={savingThrowDiceAdjustments}
|
||||
onDataOriginClick={handleDataOriginClick}
|
||||
deathSaveInfo={deathSaveInfo}
|
||||
/>
|
||||
</section>
|
||||
<MobileDivider isEnd={true} theme={theme} />
|
||||
<MobileDivider
|
||||
label="Senses"
|
||||
onClick={handleSensesManageShow}
|
||||
theme={theme}
|
||||
/>
|
||||
<h2 style={visuallyHidden}>Senses</h2>
|
||||
<Senses
|
||||
senses={senses}
|
||||
theme={theme}
|
||||
passiveInsight={Number(passiveInsight)}
|
||||
passiveInvestigation={Number(passiveInvestigation)}
|
||||
passivePerception={Number(passivePerception)}
|
||||
onClick={handleSensesManageShow}
|
||||
/>
|
||||
<MobileDivider isEnd={true} theme={theme} />
|
||||
</div>
|
||||
</SubsectionMobile>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import MainMobile from "./MainMobile";
|
||||
|
||||
export default MainMobile;
|
||||
export { MainMobile };
|
||||
@@ -0,0 +1,41 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import React from "react";
|
||||
import { connect, DispatchProp } from "react-redux";
|
||||
|
||||
import {
|
||||
CharacterTheme,
|
||||
rulesEngineSelectors,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
import { SheetAppState } from "../../../typings";
|
||||
import Notes from "../../Notes";
|
||||
|
||||
interface Props extends DispatchProp {
|
||||
theme: CharacterTheme;
|
||||
}
|
||||
class NotesMobile extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
|
||||
return (
|
||||
<SubsectionMobile className="ct-notes-mobile">
|
||||
<MobileDivider label="Notes" theme={theme} />
|
||||
<section>
|
||||
<h2 style={visuallyHidden}>Notes</h2>
|
||||
<Notes />
|
||||
</section>
|
||||
<MobileDivider isEnd={true} theme={theme} />
|
||||
</SubsectionMobile>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: SheetAppState) {
|
||||
return {
|
||||
theme: rulesEngineSelectors.getCharacterTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(NotesMobile);
|
||||
@@ -0,0 +1,4 @@
|
||||
import NotesMobile from "./NotesMobile";
|
||||
|
||||
export default NotesMobile;
|
||||
export { NotesMobile };
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import { FC } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
import { useSidebar } from "~/contexts/Sidebar";
|
||||
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
|
||||
import { PaneComponentEnum } from "~/subApps/sheet/components/Sidebar/types";
|
||||
|
||||
import { appEnvSelectors } from "../../../../Shared/selectors";
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import ProficiencyGroups from "../../../components/ProficiencyGroups";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
|
||||
interface Props {}
|
||||
export const ProficiencyGroupsMobile: FC<Props> = () => {
|
||||
const {
|
||||
pane: { paneHistoryStart },
|
||||
} = useSidebar();
|
||||
|
||||
const { proficiencyGroups, characterTheme } = useCharacterEngine();
|
||||
const isReadonly = useSelector(appEnvSelectors.getIsReadonly);
|
||||
|
||||
const handleManageShow = (): void => {
|
||||
if (!isReadonly) {
|
||||
paneHistoryStart(PaneComponentEnum.PROFICIENCIES);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SubsectionMobile name="Proficiency Groups">
|
||||
<MobileDivider
|
||||
label={"Proficiencies & Training"}
|
||||
onClick={handleManageShow}
|
||||
isReadonly={isReadonly}
|
||||
theme={characterTheme}
|
||||
/>
|
||||
<section className="ct-proficiency-groups-mobile">
|
||||
<h2 style={visuallyHidden}>Proficiencies and Training</h2>
|
||||
<ProficiencyGroups
|
||||
proficiencyGroups={proficiencyGroups}
|
||||
onClick={handleManageShow}
|
||||
/>
|
||||
</section>
|
||||
<MobileDivider isEnd={true} theme={characterTheme} />
|
||||
</SubsectionMobile>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,131 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import {
|
||||
rulesEngineSelectors,
|
||||
Skill,
|
||||
SkillUtils,
|
||||
ValueLookup,
|
||||
CharacterTheme,
|
||||
RuleData,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
import { IRollContext } from "@dndbeyond/dice";
|
||||
|
||||
import { useSidebar } from "~/contexts/Sidebar";
|
||||
import { PaneInfo } from "~/contexts/Sidebar/Sidebar";
|
||||
import { PaneComponentEnum } from "~/subApps/sheet/components/Sidebar/types";
|
||||
|
||||
import {
|
||||
appEnvSelectors,
|
||||
characterRollContextSelectors,
|
||||
} from "../../../../Shared/selectors";
|
||||
import { PaneIdentifierUtils } from "../../../../Shared/utils";
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import Skills from "../../../components/Skills";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
import { SheetAppState } from "../../../typings";
|
||||
|
||||
interface Props {
|
||||
skills: Array<Skill>;
|
||||
customSkills: Array<Skill>;
|
||||
valueLookup: ValueLookup;
|
||||
theme: CharacterTheme;
|
||||
diceEnabled: boolean;
|
||||
ruleData: RuleData;
|
||||
characterRollContext: IRollContext;
|
||||
paneHistoryStart: PaneInfo["paneHistoryStart"];
|
||||
}
|
||||
class SkillsBox extends React.PureComponent<Props> {
|
||||
handleManageShow = (): void => {
|
||||
const { paneHistoryStart } = this.props;
|
||||
|
||||
paneHistoryStart(PaneComponentEnum.SKILLS);
|
||||
};
|
||||
|
||||
handleCustomSkillClick = (skill: Skill): void => {
|
||||
const { paneHistoryStart } = this.props;
|
||||
|
||||
paneHistoryStart(
|
||||
PaneComponentEnum.CUSTOM_SKILL,
|
||||
PaneIdentifierUtils.generateCustomSkill(SkillUtils.getId(skill))
|
||||
);
|
||||
};
|
||||
|
||||
handleEmptyClick = (): void => {
|
||||
this.handleManageShow();
|
||||
};
|
||||
|
||||
handleSkillClick = (skill: Skill): void => {
|
||||
const { paneHistoryStart } = this.props;
|
||||
|
||||
paneHistoryStart(
|
||||
PaneComponentEnum.SKILL,
|
||||
PaneIdentifierUtils.generateSkill(SkillUtils.getId(skill))
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
skills,
|
||||
valueLookup,
|
||||
customSkills,
|
||||
theme,
|
||||
diceEnabled,
|
||||
ruleData,
|
||||
characterRollContext,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<SubsectionMobile name="Skills">
|
||||
<section
|
||||
className={`ct-skills-mobile ${
|
||||
theme.isDarkMode ? "ct-skills-mobile--dark-mode" : ""
|
||||
}`}
|
||||
>
|
||||
<MobileDivider
|
||||
label="Skills"
|
||||
onClick={this.handleManageShow}
|
||||
theme={theme}
|
||||
/>
|
||||
<h2 style={visuallyHidden}>Skills</h2>
|
||||
<Skills
|
||||
skills={skills}
|
||||
customSkills={customSkills}
|
||||
valueLookup={valueLookup}
|
||||
onCustomSkillClick={this.handleCustomSkillClick}
|
||||
onSkillClick={this.handleSkillClick}
|
||||
onEmptyClick={this.handleEmptyClick}
|
||||
diceEnabled={diceEnabled}
|
||||
ruleData={ruleData}
|
||||
theme={theme}
|
||||
rollContext={characterRollContext}
|
||||
/>
|
||||
<MobileDivider isEnd={true} theme={theme} />
|
||||
</section>
|
||||
</SubsectionMobile>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: SheetAppState) {
|
||||
return {
|
||||
skills: rulesEngineSelectors.getSkills(state),
|
||||
valueLookup: rulesEngineSelectors.getCharacterValueLookup(state),
|
||||
customSkills: rulesEngineSelectors.getCustomSkills(state),
|
||||
theme: rulesEngineSelectors.getCharacterTheme(state),
|
||||
diceEnabled: appEnvSelectors.getDiceEnabled(state),
|
||||
ruleData: rulesEngineSelectors.getRuleData(state),
|
||||
characterRollContext:
|
||||
characterRollContextSelectors.getCharacterRollContext(state),
|
||||
};
|
||||
}
|
||||
|
||||
const SkillsBoxContainer = (props) => {
|
||||
const {
|
||||
pane: { paneHistoryStart },
|
||||
} = useSidebar();
|
||||
return <SkillsBox {...props} paneHistoryStart={paneHistoryStart} />;
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(SkillsBoxContainer);
|
||||
@@ -0,0 +1,4 @@
|
||||
import SkillsMobile from "./SkillsMobile";
|
||||
|
||||
export default SkillsMobile;
|
||||
export { SkillsMobile };
|
||||
@@ -0,0 +1,68 @@
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import {
|
||||
CharacterTheme,
|
||||
rulesEngineSelectors,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import { PaneInfo, useSidebar } from "~/contexts/Sidebar/Sidebar";
|
||||
import { PaneComponentEnum } from "~/subApps/sheet/components/Sidebar/types";
|
||||
|
||||
import { appEnvSelectors } from "../../../../Shared/selectors";
|
||||
import MobileDivider from "../../../components/MobileDivider";
|
||||
import SubsectionMobile from "../../../components/SubsectionMobile";
|
||||
import { SheetAppState } from "../../../typings";
|
||||
import Spells from "../../Spells";
|
||||
|
||||
interface Props {
|
||||
isReadonly: boolean;
|
||||
theme: CharacterTheme;
|
||||
paneHistoryStart: PaneInfo["paneHistoryStart"];
|
||||
}
|
||||
class SpellsMobile extends React.PureComponent<Props> {
|
||||
handleManageSpellsOpen = (): void => {
|
||||
const { paneHistoryStart, isReadonly } = this.props;
|
||||
|
||||
if (!isReadonly) {
|
||||
paneHistoryStart(PaneComponentEnum.SPELL_MANAGE);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isReadonly, theme } = this.props;
|
||||
|
||||
return (
|
||||
<SubsectionMobile>
|
||||
<MobileDivider
|
||||
label="Spells"
|
||||
onClick={this.handleManageSpellsOpen}
|
||||
isReadonly={isReadonly}
|
||||
theme={theme}
|
||||
/>
|
||||
<section className="ct-spells-mobile">
|
||||
<h2 style={visuallyHidden}>Spells</h2>
|
||||
<Spells showNotes={false} />
|
||||
</section>
|
||||
<MobileDivider isEnd={true} theme={theme} />
|
||||
</SubsectionMobile>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: SheetAppState) {
|
||||
return {
|
||||
isReadonly: appEnvSelectors.getIsReadonly(state),
|
||||
theme: rulesEngineSelectors.getCharacterTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
const SpellsMobileContainer = (props) => {
|
||||
const {
|
||||
pane: { paneHistoryStart },
|
||||
} = useSidebar();
|
||||
return <SpellsMobile {...props} paneHistoryStart={paneHistoryStart} />;
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(SpellsMobileContainer);
|
||||
@@ -0,0 +1,4 @@
|
||||
import SpellsMobile from "./SpellsMobile";
|
||||
|
||||
export default SpellsMobile;
|
||||
export { SpellsMobile };
|
||||
Reference in New Issue
Block a user