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,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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user