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,195 @@
import { FC, HTMLAttributes, ReactNode } from "react";
import { useDispatch, useSelector } from "react-redux";
import { ActionName } from "@dndbeyond/character-components/es";
import {
ActionUtils,
characterActions,
InfusionUtils,
HelperUtils,
ItemUtils,
EntityUtils,
ItemManager,
} from "@dndbeyond/character-rules-engine/es";
import { ItemName } from "~/components/ItemName";
import { DataOriginTypeEnum } from "~/constants";
import { useSidebar } from "~/contexts/Sidebar";
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
import { Header } from "~/subApps/sheet/components/Sidebar/components/Header";
import { BaseInventoryContract } from "~/types";
import { ActionDetail } from "../../../../../../tools/js/Shared/components/ActionDetail";
import { appEnvSelectors } from "../../../../../../tools/js/Shared/selectors";
import { PaneInitFailureContent } from "../../components/PaneInitFailureContent";
import { getDataOriginComponentInfo } from "../../helpers/paneUtils";
import { PaneComponentEnum, PaneIdentifiersAction } from "../../types";
/*
ActionPane is the Sidebar content that displays the details and usages of actions. If the Action is directly represented as an Item in the Actions section - it will display the ItemPane in the Sidebar. Some Items contain actions (reactions or bonus actions) when attuned - These will display seperately from the Item and when clicked they use the ActionPane with special data depending on the DataOrigin.
*/
interface ActionPaneProps extends HTMLAttributes<HTMLDivElement> {
identifiers: PaneIdentifiersAction | null;
}
export const ActionPane: FC<ActionPaneProps> = ({ identifiers, ...props }) => {
const {
actions,
abilityLookup,
ruleData,
entityValueLookup,
proficiencyBonus,
inventoryLookup,
characterTheme,
} = useCharacterEngine();
const isReadonly = useSelector(appEnvSelectors.getIsReadonly);
const dispatch = useDispatch();
const {
pane: { paneHistoryPush },
} = useSidebar();
const action = actions.find(
(action) =>
identifiers?.id === ActionUtils.getMappingId(action) &&
identifiers?.entityTypeId === ActionUtils.getMappingEntityTypeId(action)
);
const handleCustomDataUpdate = (
key: number,
value: string,
source: string
): void => {
if (action) {
dispatch(
characterActions.valueSet(
key,
value,
source,
ActionUtils.getMappingId(action),
ActionUtils.getMappingEntityTypeId(action)
)
);
}
};
const handleRemoveCustomizations = (): void => {
if (action) {
const mappingId = ActionUtils.getMappingId(action);
const mappingEntityTypeId = ActionUtils.getMappingEntityTypeId(action);
if (mappingId !== null && mappingEntityTypeId !== null) {
dispatch(
characterActions.actionCustomizationsDelete(
mappingId,
mappingEntityTypeId
)
);
}
}
};
const handleLimitedUseSet = (uses: number): void => {
if (action) {
const mappingId = ActionUtils.getMappingId(action);
const mappingEntityTypeId = ActionUtils.getMappingEntityTypeId(action);
if (mappingId === null || mappingEntityTypeId === null) {
return;
}
let dataOriginType = ActionUtils.getDataOriginType(action);
if (dataOriginType === DataOriginTypeEnum.ITEM) {
const dataOrigin = ActionUtils.getDataOrigin(action);
const itemData = dataOrigin.primary as BaseInventoryContract;
const item = ItemManager.getItem(ItemUtils.getMappingId(itemData));
item.handleItemLimitedUseSet(uses);
} else {
dispatch(
characterActions.actionUseSet(
mappingId,
mappingEntityTypeId,
uses,
dataOriginType
)
);
}
}
};
const handleParentClick = (): void => {
if (action) {
let dataOrigin = ActionUtils.getDataOrigin(action);
let component = getDataOriginComponentInfo(dataOrigin);
if (component.type !== PaneComponentEnum.ERROR_404) {
paneHistoryPush(component.type, component.identifiers);
}
}
};
if (!action) {
return <PaneInitFailureContent />;
}
//We could do the dataOrigin stuff better, this could be refactored
//Check ItemPane and InfusionPanes for similar usages of DataOrigin
const dataOrigin = ActionUtils.getDataOrigin(action);
const dataOriginType = ActionUtils.getDataOriginType(action);
let name: ReactNode = null;
if (ActionUtils.getName(action) !== "") {
name = <ActionName theme={characterTheme} action={action} />;
}
let parentName: string | null = null;
let parentClick: (() => void) | undefined = undefined;
if (dataOriginType === DataOriginTypeEnum.ITEM) {
const itemContract = dataOrigin.primary as BaseInventoryContract;
const itemMappingId = ItemUtils.getMappingId(itemContract);
const item = HelperUtils.lookupDataOrFallback(
inventoryLookup,
itemMappingId
);
if (item !== null) {
let infusion = ItemUtils.getInfusion(item);
if (infusion) {
parentName = `Infusion: ${InfusionUtils.getName(infusion)}`;
parentClick = handleParentClick;
}
if (name === null) {
name = <ItemName item={item} onClick={handleParentClick} />;
}
}
} else {
if (dataOrigin.primary) {
parentName = EntityUtils.getDataOriginName(dataOrigin);
parentClick = handleParentClick;
}
}
return (
<div key={ActionUtils.getUniqueKey(action)} {...props}>
<Header parent={parentName} onClick={parentClick}>
{name}
</Header>
<ActionDetail
theme={characterTheme}
action={action}
abilityLookup={abilityLookup}
showCustomize={dataOriginType !== DataOriginTypeEnum.ITEM}
onCustomDataUpdate={handleCustomDataUpdate}
onCustomizationsRemove={handleRemoveCustomizations}
ruleData={ruleData}
entityValueLookup={entityValueLookup}
inventoryLookup={inventoryLookup}
isReadonly={isReadonly}
onLimitedUseSet={handleLimitedUseSet}
proficiencyBonus={proficiencyBonus}
/>
</div>
);
};