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,243 @@
import axios, { Canceler } from "axios";
import React from "react";
import { connect, DispatchProp } from "react-redux";
import { Checkbox } from "@dndbeyond/character-components/es";
import {
ApiAdapterUtils,
ApiRequests,
rulesEngineSelectors,
characterActions,
Condition,
RuleData,
ShortModelInfoContract,
CharacterTheme,
} from "@dndbeyond/character-rules-engine/es";
import { Header } from "~/subApps/sheet/components/Sidebar/components/Header";
import { RestoreLifeManager } from "~/subApps/sheet/components/Sidebar/panes/HitPointsManagePane/RestoreLifeManager/RestoreLifeManager";
import { toastMessageActions } from "../../../actions/toastMessage";
import { ThemeButton } from "../../../components/common/Button";
import { SharedAppState } from "../../../stores/typings";
import { AppLoggerUtils } from "../../../utils";
interface Props extends DispatchProp {
activeConditions: Array<Condition>;
ruleData: RuleData;
isDead: boolean;
theme: CharacterTheme;
}
interface State {
resetMaxHpModifier: boolean;
adjustConditionLevel: boolean;
restMessage: string | null;
}
class LongRestPane extends React.PureComponent<Props, State> {
loadMessageCanceler: null | Canceler = null;
constructor(props) {
super(props);
this.state = {
resetMaxHpModifier: true,
adjustConditionLevel: false,
restMessage: null,
};
}
componentDidMount() {
this.loadMessage();
}
componentWillUnmount(): void {
if (this.loadMessageCanceler !== null) {
this.loadMessageCanceler();
}
}
loadMessage = (): void => {
if (this.loadMessageCanceler !== null) {
this.loadMessageCanceler();
}
ApiRequests.getCharacterRestLong({
cancelToken: new axios.CancelToken((c) => {
this.loadMessageCanceler = c;
}),
})
.then((response) => {
let message = ApiAdapterUtils.getResponseData(response);
if (message !== null) {
this.setState({
restMessage: message,
});
}
this.loadMessageCanceler = null;
})
.catch(AppLoggerUtils.handleAdhocApiError);
};
reset = (): void => {
this.setState({
resetMaxHpModifier: true,
});
};
handleReset = (): void => {
this.setState({
resetMaxHpModifier: true,
adjustConditionLevel: false,
});
};
handleSave = (): void => {
const { resetMaxHpModifier, adjustConditionLevel } = this.state;
const { dispatch } = this.props;
dispatch(
characterActions.longRest(resetMaxHpModifier, adjustConditionLevel)
);
dispatch(
toastMessageActions.toastSuccess(
"Long Rest Taken",
"You have completed a long rest. Relevant abilities have been reset."
)
);
};
handleResetMaxHpChange = (enabled: boolean): void => {
this.setState({
resetMaxHpModifier: enabled,
});
};
handleAdjustExhaustionLevel = (enabled: boolean): void => {
this.setState({
adjustConditionLevel: enabled,
});
};
handleRestoreToLife = (restoreType: ShortModelInfoContract): void => {
const { dispatch } = this.props;
const restoreChoice = restoreType.name === "Full" ? "full" : "1";
dispatch(characterActions.restoreLife(restoreType.id));
dispatch(
toastMessageActions.toastSuccess(
"Character Restored to Life",
`You have been restored to life with ${restoreChoice} HP.`
)
);
};
renderRecover = (): React.ReactNode => {
const { resetMaxHpModifier, adjustConditionLevel, restMessage } =
this.state;
const { isDead, activeConditions } = this.props;
if (isDead) {
return (
<div className="ct-reset-pane__recover-sources">
Your character is dead
</div>
);
}
const exhaustionIsActive = activeConditions.find(
(condition) => condition.level !== null
);
return (
<React.Fragment>
<div className="ct-reset-pane__recover-sources">
{restMessage === null
? "Asking the server what will be reset..."
: restMessage}
</div>
<div className="ct-reset-pane__recover-max-hp">
<Checkbox
label="Reset Maximum HP changes during this rest"
initiallyEnabled={resetMaxHpModifier}
onChange={this.handleResetMaxHpChange}
/>
</div>
{exhaustionIsActive && (
<div className="ct-reset-pane__reset-exhaustion-level">
<Checkbox
label="Recover 1 Level of Exhaustion during this rest (requires food and drink)"
initiallyEnabled={adjustConditionLevel}
onChange={this.handleAdjustExhaustionLevel}
/>
</div>
)}
</React.Fragment>
);
};
renderActions = (): React.ReactNode => {
const { isDead, ruleData, theme } = this.props;
if (isDead) {
return (
<React.Fragment>
<RestoreLifeManager onSave={this.handleRestoreToLife} />
</React.Fragment>
);
}
return (
<div className="ct-reset-pane__actions">
<div className="ct-reset-pane__action">
<ThemeButton onClick={this.handleSave} enableConfirm={true}>
Take Long Rest
</ThemeButton>
</div>
<div className="ct-reset-pane__action">
<ThemeButton onClick={this.handleReset} style="outline">
Reset
</ThemeButton>
</div>
</div>
);
};
render() {
return (
<div className="ct-reset-pane">
<Header>Long Rest</Header>
<div className="ct-reset-pane__intro">
<p>
A long rest is a period of extended downtime, at least 8 hours long,
during which a character sleeps for at least 6 hours and performs no
more than 2 hours of light activity, such as reading, talking,
eating, or standing watch.
</p>
<p>
If the rest is interrupted by a period of strenuous activity at
least 1 hour of walking, fighting, casting spells, or similar
adventuring activity the characters must begin the rest again to
gain any benefit from it.
</p>
</div>
<div className="ct-reset-pane__recover">
<div className="ct-reset-pane__recover-heading">Recover</div>
{this.renderRecover()}
</div>
{this.renderActions()}
</div>
);
}
}
function mapStateToProps(state: SharedAppState) {
return {
activeConditions: rulesEngineSelectors.getActiveConditions(state),
isDead: rulesEngineSelectors.isDead(state),
ruleData: rulesEngineSelectors.getRuleData(state),
theme: rulesEngineSelectors.getCharacterTheme(state),
};
}
export default connect(mapStateToProps)(LongRestPane);
@@ -0,0 +1,4 @@
import LongRestPane from "./LongRestPane";
export default LongRestPane;
export { LongRestPane };