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:
2025-05-28 11:50:03 -07:00
commit 8df9031d27
3592 changed files with 319051 additions and 0 deletions
@@ -0,0 +1,44 @@
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 { appEnvSelectors } from "../../../../Shared/selectors";
import SubsectionTablet from "../../../components/SubsectionTablet";
import TabletBox from "../../../components/TabletBox";
import { SheetAppState } from "../../../typings";
import Actions from "../../Actions";
interface Props extends DispatchProp {
isReadonly: boolean;
theme: CharacterTheme;
}
class ActionsTablet extends React.PureComponent<Props> {
render() {
const { theme } = this.props;
return (
<SubsectionTablet>
<TabletBox theme={theme} header="Actions" className="ct-actions-tablet">
<section>
<h2 style={visuallyHidden}>Actions</h2>
<Actions />
</section>
</TabletBox>
</SubsectionTablet>
);
}
}
function mapStateToProps(state: SheetAppState) {
return {
isReadonly: appEnvSelectors.getIsReadonly(state),
theme: rulesEngineSelectors.getCharacterTheme(state),
};
}
export default connect(mapStateToProps)(ActionsTablet);
@@ -0,0 +1,4 @@
import ActionsTablet from "./ActionsTablet";
export default ActionsTablet;
export { ActionsTablet };
@@ -0,0 +1,160 @@
import React from "react";
import { connect } from "react-redux";
import { ArmorClassBox } from "@dndbeyond/character-components/es";
import {
CharacterPreferences,
SpeedInfo,
RuleData,
rulesEngineSelectors,
CharacterTheme,
} from "@dndbeyond/character-rules-engine/es";
import { PaneInfo, useSidebar } 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 ProficiencyBonusBox from "../../../components/ProficiencyBonusBox";
import SpeedBox from "../../../components/SpeedBox";
import { SheetAppState } from "../../../typings";
interface Props {
armorClass: number;
speeds: SpeedInfo;
proficiencyBonus: number;
preferences: CharacterPreferences;
theme: CharacterTheme;
ruleData: RuleData;
isReadonly: boolean;
diceEnabled: boolean;
paneHistoryStart: PaneInfo["paneHistoryStart"];
}
class CombatTablet extends React.PureComponent<Props> {
static defaultProps = {
diceEnabled: false,
};
handleProficiencyBonusClick = (): void => {
const { paneHistoryStart } = this.props;
paneHistoryStart(PaneComponentEnum.PROFICIENCY_BONUS);
};
handleSpeedsClick = (): void => {
const { paneHistoryStart } = this.props;
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 = (): void => {
const { paneHistoryStart } = this.props;
paneHistoryStart(PaneComponentEnum.ARMOR_MANAGE);
};
render() {
const {
preferences,
proficiencyBonus,
speeds,
armorClass,
theme,
ruleData,
} = this.props;
return (
<div className="ct-combat-tablet">
<div className="ct-combat-tablet__extras">
<div className="ct-combat-tablet__extra ct-combat-tablet__extra--proficiency">
<ProficiencyBonusBox
theme={theme}
proficiencyBonus={proficiencyBonus}
onClick={this.handleProficiencyBonusClick}
/>
</div>
<div className="ct-combat-tablet__extra ct-combat-tablet__extra--speed">
<SpeedBox
speeds={speeds}
preferences={preferences}
theme={theme}
ruleData={ruleData}
onClick={this.handleSpeedsClick}
/>
</div>
<div className="ct-combat-tablet__extra ct-combat-tablet__extra--initiative">
<InitiativeBox isTablet />
</div>
<div className="ct-combat-tablet__extra ct-combat-tablet__extra--ac">
<ArmorClassBox
theme={theme}
armorClass={armorClass}
onClick={this.handleArmorClassClick}
/>
</div>
<div className="ct-combat-tablet__extra ct-combat-tablet__extra--statuses">
<div className="ct-combat-tablet__ctas">
<div className="ct-combat-tablet__cta">
<div
role="button"
className={`ct-combat-tablet__cta-button ${
theme.isDarkMode
? "ct-combat-tablet__cta-button--dark-mode"
: ""
}`}
onClick={this.handleDefensesSummaryClick}
>
Defenses
</div>
</div>
<div className="ct-combat-tablet__cta">
<div
role="button"
className={`ct-combat-tablet__cta-button ${
theme.isDarkMode
? "ct-combat-tablet__cta-button--dark-mode"
: ""
}`}
onClick={this.handleConditionSummaryClick}
>
Conditions
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
function mapStateToProps(state: SheetAppState) {
return {
armorClass: rulesEngineSelectors.getAcTotal(state),
proficiencyBonus: rulesEngineSelectors.getProficiencyBonus(state),
speeds: rulesEngineSelectors.getCurrentCarriedWeightSpeed(state),
preferences: rulesEngineSelectors.getCharacterPreferences(state),
theme: rulesEngineSelectors.getCharacterTheme(state),
ruleData: rulesEngineSelectors.getRuleData(state),
isReadonly: appEnvSelectors.getIsReadonly(state),
diceEnabled: appEnvSelectors.getDiceEnabled(state),
};
}
const CombatTabletContainer = (props) => {
const {
pane: { paneHistoryStart },
} = useSidebar();
return <CombatTablet {...props} paneHistoryStart={paneHistoryStart} />;
};
export default connect(mapStateToProps)(CombatTabletContainer);
@@ -0,0 +1,4 @@
import CombatTablet from "./CombatTablet";
export default CombatTablet;
export { CombatTablet };
@@ -0,0 +1,27 @@
import { visuallyHidden } from "@mui/utils";
import { FC } from "react";
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
import SubsectionTablet from "../../../components/SubsectionTablet";
import TabletBox from "../../../components/TabletBox";
import Description from "../../Description";
export const DescriptionTablet: FC = () => {
const { characterTheme } = useCharacterEngine();
return (
<SubsectionTablet>
<TabletBox
header={"Background"}
className="ct-description-tablet"
theme={characterTheme}
>
<section>
<h2 style={visuallyHidden}>Background</h2>
<Description theme={characterTheme} />
</section>
</TabletBox>
</SubsectionTablet>
);
};
@@ -0,0 +1,70 @@
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 SubsectionTablet from "../../../components/SubsectionTablet";
import TabletBox from "../../../components/TabletBox";
import { SheetAppState } from "../../../typings";
import Equipment from "../../Equipment";
interface Props {
isReadonly: boolean;
theme: CharacterTheme;
paneHistoryStart: PaneInfo["paneHistoryStart"];
}
class EquipmentTablet extends React.PureComponent<Props> {
handleManageClick = (): void => {
const { paneHistoryStart, isReadonly } = this.props;
if (!isReadonly) {
paneHistoryStart(PaneComponentEnum.EQUIPMENT_MANAGE);
}
};
render() {
const { isReadonly, theme } = this.props;
return (
<SubsectionTablet>
<TabletBox
header="Inventory"
className="ct-equipment-tablet"
onHeaderClick={this.handleManageClick}
isReadonly={isReadonly}
theme={theme}
>
<section>
<h2 style={visuallyHidden}>Inventory</h2>
<Equipment />
</section>
</TabletBox>
</SubsectionTablet>
);
}
}
function mapStateToProps(state: SheetAppState) {
return {
isReadonly: appEnvSelectors.getIsReadonly(state),
theme: rulesEngineSelectors.getCharacterTheme(state),
};
}
const EquipmentTabletContainer = (props) => {
const {
pane: { paneHistoryStart },
} = useSidebar();
return <EquipmentTablet {...props} paneHistoryStart={paneHistoryStart} />;
};
export default connect(mapStateToProps)(EquipmentTabletContainer);
@@ -0,0 +1,4 @@
import EquipmentTablet from "./EquipmentTablet";
export default EquipmentTablet;
export { EquipmentTablet };
@@ -0,0 +1,69 @@
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 SubsectionTablet from "../../../components/SubsectionTablet";
import TabletBox from "../../../components/TabletBox";
import { SheetAppState } from "../../../typings";
import Extras from "../../Extras";
interface Props {
isReadonly: boolean;
theme: CharacterTheme;
paneHistoryStart: PaneInfo["paneHistoryStart"];
}
class ExtrasTablet extends React.PureComponent<Props> {
handleManageOpen = (): void => {
const { paneHistoryStart, isReadonly } = this.props;
if (!isReadonly) {
paneHistoryStart(PaneComponentEnum.EXTRA_MANAGE);
}
};
render() {
const { isReadonly, theme } = this.props;
return (
<SubsectionTablet>
<TabletBox
header="Extras"
onHeaderClick={this.handleManageOpen}
className="ct-extras-tablet"
isReadonly={isReadonly}
theme={theme}
>
<section>
<h2 style={visuallyHidden}>Extras</h2>
<Extras />
</section>
</TabletBox>
</SubsectionTablet>
);
}
}
function mapStateToProps(state: SheetAppState) {
return {
isReadonly: appEnvSelectors.getIsReadonly(state),
theme: rulesEngineSelectors.getCharacterTheme(state),
};
}
const ExtrasTabletContainer = (props) => {
const {
pane: { paneHistoryStart },
} = useSidebar();
return <ExtrasTablet {...props} paneHistoryStart={paneHistoryStart} />;
};
export default connect(mapStateToProps)(ExtrasTabletContainer);
@@ -0,0 +1,4 @@
import ExtrasTablet from "./ExtrasTablet";
export default ExtrasTablet;
export { ExtrasTablet };
@@ -0,0 +1,45 @@
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 SubsectionTablet from "../../../components/SubsectionTablet";
import TabletBox from "../../../components/TabletBox";
import { SheetAppState } from "../../../typings";
import Features from "../../Features";
interface Props extends DispatchProp {
theme: CharacterTheme;
}
class FeaturesTablet extends React.PureComponent<Props> {
render() {
const { theme } = this.props;
return (
<SubsectionTablet className="ct-features-tablet">
<TabletBox
header="Features & Traits"
className="ct-actions-tablet"
theme={theme}
>
<section>
<h2 style={visuallyHidden}>Features and Traits</h2>
<Features />
</section>
</TabletBox>
</SubsectionTablet>
);
}
}
function mapStateToProps(state: SheetAppState) {
return {
theme: rulesEngineSelectors.getCharacterTheme(state),
};
}
export default connect(mapStateToProps)(FeaturesTablet);
@@ -0,0 +1,4 @@
import FeaturesTablet from "./FeaturesTablet";
export default FeaturesTablet;
export { FeaturesTablet };
@@ -0,0 +1,248 @@
import { visuallyHidden } from "@mui/utils";
import { useSelector } from "react-redux";
import {
AbilitySummary,
CampaignSummary,
ManageIcon,
} from "@dndbeyond/character-components/es";
import {
AbilityManager,
rulesEngineSelectors,
Skill,
SkillUtils,
} from "@dndbeyond/character-rules-engine/es";
import { useSidebar } from "~/contexts/Sidebar";
import { useAbilities } from "~/hooks/useAbilities";
import { PaneComponentEnum } from "../../../../../../subApps/sheet/components/Sidebar/types";
import {
appEnvSelectors,
characterRollContextSelectors,
} from "../../../../Shared/selectors";
import { PaneIdentifierUtils } from "../../../../Shared/utils";
import ProficiencyGroupsBox from "../../../components/ProficiencyGroupsBox";
import SavingThrowsBox from "../../../components/SavingThrowsBox";
import SensesBox from "../../../components/SensesBox";
import SkillsBox from "../../../components/SkillsBox";
import SubsectionTablet from "../../../components/SubsectionTablet";
export default function MainTablet() {
const abilities = useAbilities();
const {
pane: { paneHistoryStart },
} = useSidebar();
const preferences = useSelector(rulesEngineSelectors.getCharacterPreferences);
const savingThrowDiceAdjustments = useSelector(
rulesEngineSelectors.getSavingThrowDiceAdjustments
);
const situationalBonusSavingThrowsLookup = useSelector(
rulesEngineSelectors.getSituationalBonusSavingThrowsLookup
);
const deathSaveInfo = useSelector(rulesEngineSelectors.getDeathSaveInfo);
const passivePerception = useSelector(
rulesEngineSelectors.getPassivePerception
);
const passiveInvestigation = useSelector(
rulesEngineSelectors.getPassiveInvestigation
);
const passiveInsight = useSelector(rulesEngineSelectors.getPassiveInsight);
const senses = useSelector(rulesEngineSelectors.getSenseInfo);
const campaign = useSelector(rulesEngineSelectors.getCampaign);
const skills = useSelector(rulesEngineSelectors.getSkills);
const valueLookup = useSelector(rulesEngineSelectors.getCharacterValueLookup);
const customSkills = useSelector(rulesEngineSelectors.getCustomSkills);
const proficiencyGroups = useSelector(
rulesEngineSelectors.getProficiencyGroups
);
const dimensions = useSelector(appEnvSelectors.getDimensions);
const theme = useSelector(rulesEngineSelectors.getCharacterTheme);
const isReadonly = useSelector(appEnvSelectors.getIsReadonly);
const diceEnabled = useSelector(appEnvSelectors.getDiceEnabled);
const ruleData = useSelector(rulesEngineSelectors.getRuleData);
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 handleProficienciesManageShow = (): void => {
if (!isReadonly) {
paneHistoryStart(PaneComponentEnum.PROFICIENCIES);
}
};
const handleCampaignShow = (): void => {
paneHistoryStart(PaneComponentEnum.CAMPAIGN);
};
const handleCustomSkillClick = (skill: Skill): void => {
paneHistoryStart(
PaneComponentEnum.CUSTOM_SKILL,
PaneIdentifierUtils.generateCustomSkill(SkillUtils.getId(skill))
);
};
const handleSkillsShow = (): void => {
paneHistoryStart(PaneComponentEnum.SKILLS);
};
const handleSkillClick = (skill: Skill): void => {
paneHistoryStart(
PaneComponentEnum.SKILL,
PaneIdentifierUtils.generateSkill(SkillUtils.getId(skill))
);
};
return (
<SubsectionTablet name="Main">
<div className="ct-main-tablet">
{campaign && (
<CampaignSummary
campaign={campaign}
onCampaignShow={handleCampaignShow}
className={
theme.isDarkMode
? "ct-main-tablet__campaign-button--dark-mode"
: ""
}
theme={theme}
gameLog={gameLog}
/>
)}
<section className="ct-main-tablet__abilities">
<h2 style={visuallyHidden}>Abilities</h2>
{abilities.map((ability) => (
<div className="ct-main-tablet__ability" key={ability.getStatKey()}>
<AbilitySummary
theme={theme}
ability={ability}
preferences={preferences}
onClick={handleAbilitySummaryClick}
diceEnabled={diceEnabled}
rollContext={characterRollContext}
/>
</div>
))}
</section>
<div className="ct-main-tablet__large-boxes">
<div className="ct-main-tablet__large-boxes-bucket">
<div className="ct-main-tablet__large-box">
<SavingThrowsBox
abilities={abilities}
ruleData={ruleData}
savingThrowDiceAdjustments={savingThrowDiceAdjustments}
situationalBonusSavingThrowsLookup={
situationalBonusSavingThrowsLookup
}
deathSaveInfo={deathSaveInfo}
onAbilityClick={handleAbilityClick}
onClick={handleSavingThrowsClick}
dimensions={dimensions}
theme={theme}
diceEnabled={diceEnabled}
rollContext={characterRollContext}
/>
<div className="ct-main-tablet__large-box-footer">
<ManageIcon
onClick={handleSavingThrowsClick}
enableTooltip={false}
theme={theme}
>
Saving Throws
</ManageIcon>
</div>
</div>
<div className="ct-main-tablet__large-box">
<SensesBox
senses={senses}
passiveInsight={Number(passiveInsight)}
passiveInvestigation={Number(passiveInvestigation)}
passivePerception={Number(passivePerception)}
onClick={handleSensesManageShow}
dimensions={dimensions}
theme={theme}
/>
<div className="ct-main-tablet__large-box-footer">
<ManageIcon
onClick={handleSensesManageShow}
enableTooltip={false}
theme={theme}
>
Senses
</ManageIcon>
</div>
</div>
<div className="ct-main-tablet__large-box">
<ProficiencyGroupsBox
dimensions={dimensions}
theme={theme}
proficiencyGroups={proficiencyGroups}
onClick={handleProficienciesManageShow}
/>
<div className="ct-main-tablet__large-box-footer">
<ManageIcon
onClick={handleProficienciesManageShow}
enableTooltip={false}
showIcon={!isReadonly}
theme={theme}
>
Proficiencies & Training
</ManageIcon>
</div>
</div>
</div>
<div className="ct-main-tablet__large-boxes-bucket">
<div className="ct-main-tablet__large-box">
<SkillsBox
skills={skills}
customSkills={customSkills}
valueLookup={valueLookup}
onCustomSkillClick={handleCustomSkillClick}
onSkillClick={handleSkillClick}
onEmptyClick={handleSkillsShow}
dimensions={dimensions}
theme={theme}
diceEnabled={diceEnabled}
ruleData={ruleData}
rollContext={characterRollContext}
/>
<div className="ct-main-tablet__large-box-footer">
<ManageIcon
onClick={handleSkillsShow}
enableTooltip={false}
theme={theme}
>
Skills
</ManageIcon>
</div>
</div>
</div>
</div>
</div>
</SubsectionTablet>
);
}
@@ -0,0 +1,4 @@
import MainTablet from "./MainTablet";
export default MainTablet;
export { MainTablet };
@@ -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 SubsectionTablet from "../../../components/SubsectionTablet";
import TabletBox from "../../../components/TabletBox";
import { SheetAppState } from "../../../typings";
import Notes from "../../Notes";
interface Props extends DispatchProp {
theme: CharacterTheme;
}
class NotesTablet extends React.PureComponent<Props> {
render() {
const { theme } = this.props;
return (
<SubsectionTablet>
<TabletBox header="Notes" className="ct-notes-tablet" theme={theme}>
<section>
<h2 style={visuallyHidden}>Notes</h2>
<Notes />
</section>
</TabletBox>
</SubsectionTablet>
);
}
}
function mapStateToProps(state: SheetAppState) {
return {
theme: rulesEngineSelectors.getCharacterTheme(state),
};
}
export default connect(mapStateToProps)(NotesTablet);
@@ -0,0 +1,4 @@
import NotesTablet from "./NotesTablet";
export default NotesTablet;
export { NotesTablet };
@@ -0,0 +1,69 @@
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 SubsectionTablet from "../../../components/SubsectionTablet";
import TabletBox from "../../../components/TabletBox";
import { SheetAppState } from "../../../typings";
import Spells from "../../Spells";
interface Props {
isReadonly: boolean;
theme: CharacterTheme;
paneHistoryStart: PaneInfo["paneHistoryStart"];
}
class SpellsTablet extends React.PureComponent<Props> {
handleManageSpellsOpen = (): void => {
const { paneHistoryStart, isReadonly } = this.props;
if (!isReadonly) {
paneHistoryStart(PaneComponentEnum.SPELL_MANAGE);
}
};
render() {
const { isReadonly, theme } = this.props;
return (
<SubsectionTablet>
<TabletBox
header="Spells"
onHeaderClick={this.handleManageSpellsOpen}
className="ct-spells-tablet"
isReadonly={isReadonly}
theme={theme}
>
<section>
<h2 style={visuallyHidden}>Spells</h2>
<Spells />
</section>
</TabletBox>
</SubsectionTablet>
);
}
}
function mapStateToProps(state: SheetAppState) {
return {
isReadonly: appEnvSelectors.getIsReadonly(state),
theme: rulesEngineSelectors.getCharacterTheme(state),
};
}
const SpellsTabletContainer = (props) => {
const {
pane: { paneHistoryStart },
} = useSidebar();
return <SpellsTablet {...props} paneHistoryStart={paneHistoryStart} />;
};
export default connect(mapStateToProps)(SpellsTabletContainer);
@@ -0,0 +1,4 @@
import SpellsTablet from "./SpellsTablet";
export default SpellsTablet;
export { SpellsTablet };