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,186 @@
import React from "react";
import {
AbilityLookup,
DataOriginBaseAction,
DataOriginSpell,
Constants,
EntityLimitedUseContract,
LimitedUseUtils,
RuleData,
RuleDataUtils,
CharacterTheme,
} from "@dndbeyond/character-rules-engine/es";
import SlotManager from "../../../../Shared/components/SlotManager";
import SlotManagerLarge from "../../../../Shared/components/SlotManagerLarge";
interface Props {
component: DataOriginBaseAction | DataOriginSpell;
limitedUse: EntityLimitedUseContract | null;
onUseSet?: (
component: DataOriginBaseAction | DataOriginSpell,
uses: number
) => void;
ruleData: RuleData;
abilityLookup: AbilityLookup;
isInteractive: boolean;
largeLimitedUseAmount: number;
proficiencyBonus: number;
theme: CharacterTheme;
}
export default class FeatureSnippetLimitedUse extends React.PureComponent<Props> {
static defaultProps = {
largeLimitedUseAmount: 8,
};
handleUseSet = (uses: number): void => {
const { onUseSet, component } = this.props;
if (onUseSet) {
onUseSet(component, uses);
}
};
renderSmallAmountSlotPool = (): React.ReactNode => {
const {
limitedUse,
ruleData,
abilityLookup,
isInteractive,
proficiencyBonus,
} = this.props;
if (!limitedUse) {
return null;
}
const numberUsed = LimitedUseUtils.getNumberUsed(limitedUse);
const maxUses = LimitedUseUtils.deriveMaxUses(
limitedUse,
abilityLookup,
ruleData,
proficiencyBonus
);
if (!maxUses) {
return null;
}
return (
<SlotManager
used={numberUsed}
available={maxUses}
size={"small"}
onSet={this.handleUseSet}
isInteractive={isInteractive}
/>
);
};
renderLargeAmountSlotPool = (): React.ReactNode => {
const {
limitedUse,
ruleData,
abilityLookup,
isInteractive,
proficiencyBonus,
} = this.props;
if (!limitedUse) {
return null;
}
const numberUsed = LimitedUseUtils.getNumberUsed(limitedUse);
const maxUses = LimitedUseUtils.deriveMaxUses(
limitedUse,
abilityLookup,
ruleData,
proficiencyBonus
);
if (!maxUses) {
return null;
}
return (
<SlotManagerLarge
label="Current:"
available={maxUses}
used={numberUsed}
onSet={this.handleUseSet}
isInteractive={isInteractive}
/>
);
};
render() {
const {
limitedUse,
ruleData,
abilityLookup,
largeLimitedUseAmount,
proficiencyBonus,
theme,
} = this.props;
if (!limitedUse) {
return null;
}
let resetType = LimitedUseUtils.getResetType(limitedUse);
let maxUses = LimitedUseUtils.deriveMaxUses(
limitedUse,
abilityLookup,
ruleData,
proficiencyBonus
);
let numberUsed = LimitedUseUtils.getNumberUsed(limitedUse);
let totalSlots = Math.max(maxUses, numberUsed);
let usagesNode: React.ReactNode;
let extraNode: React.ReactNode;
if (totalSlots >= largeLimitedUseAmount) {
usagesNode = maxUses;
extraNode = this.renderLargeAmountSlotPool();
} else if (maxUses === -1) {
usagesNode = "Unlimited";
} else {
usagesNode = this.renderSmallAmountSlotPool();
}
let resetNode: React.ReactNode;
if (
resetType !== Constants.LimitedUseResetTypeEnum.SHORT_REST &&
resetType !== Constants.LimitedUseResetTypeEnum.LONG_REST
) {
resetNode = "Special";
} else {
resetNode = RuleDataUtils.getLimitedUseResetTypeName(resetType, ruleData);
}
return (
<React.Fragment>
<div
className={`ct-feature-snippet__limited-use ${
theme.isDarkMode ? "ct-feature-snippet__limited-use--dark-mode" : ""
}`}
>
<div className="ct-feature-snippet__limited-use-usages">
{usagesNode}
</div>
<div className="ct-feature-snippet__limited-use-sep">/</div>
<div className="ct-feature-snippet__limited-use-reset">
{resetNode}
</div>
</div>
{extraNode && (
<div className="ct-feature-snippet__limited-use-extra">
{extraNode}
</div>
)}
</React.Fragment>
);
}
}
@@ -0,0 +1,4 @@
import FeatureSnippetLimitedUse from "./FeatureSnippetLimitedUse";
export default FeatureSnippetLimitedUse;
export { FeatureSnippetLimitedUse };