New source found from dndbeyond.com

This commit is contained in:
2026-07-08 01:00:09 -07:00
parent 9a983a6d7b
commit dcefa0d2f2
2865 changed files with 222467 additions and 49053 deletions
@@ -0,0 +1,212 @@
import { FC, HTMLAttributes, useContext, useState } from "react";
import { useSelector } from "react-redux";
import {
Action,
ActionUtils,
Constants,
DataOrigin,
EntityUtils,
HelperUtils,
Infusion,
InfusionUtils,
ItemPlanUtils,
ItemUtils,
Spell,
} from "@dndbeyond/character-rules-engine/es";
import { EditableName } from "~/components/EditableName";
import { ItemName } from "~/components/ItemName";
import { useSidebar } from "~/contexts/Sidebar";
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
import { Header } from "~/subApps/sheet/components/Sidebar/components/Header";
import { Preview } from "~/subApps/sheet/components/Sidebar/components/Preview";
import {
getDataOriginComponentInfo,
getSpellComponentInfo,
} from "~/subApps/sheet/components/Sidebar/helpers/paneUtils";
import {
PaneComponentEnum,
PaneIdentifiersItem,
} from "~/subApps/sheet/components/Sidebar/types";
import ItemDetail from "~/tools/js/Shared/components/ItemDetail";
import ItemListInformationCollapsible from "~/tools/js/Shared/components/ItemListInformationCollapsible";
import { InventoryManagerContext } from "~/tools/js/Shared/managers/InventoryManagerContext";
import { appEnvSelectors } from "~/tools/js/Shared/selectors";
import { PaneIdentifierUtils } from "~/tools/js/Shared/utils";
import { PaneInitFailureContent } from "../../components/PaneInitFailureContent";
interface Props extends HTMLAttributes<HTMLDivElement> {
identifiers: PaneIdentifiersItem | null;
}
export const ItemPane: FC<Props> = ({ identifiers, ...props }) => {
const { inventoryManager } = useContext(InventoryManagerContext);
const {
pane: { paneHistoryPush },
} = useSidebar();
const {
ruleData,
allInventoryItems: items,
weaponSpellDamageGroups,
entityValueLookup,
snippetData,
infusionChoiceLookup,
characterTheme: theme,
containerLookup,
partyInfo,
itemPlans,
} = useCharacterEngine();
const isReadonly = useSelector(appEnvSelectors.getIsReadonly);
const [isCustomizeClosed, setIsCustomizeClosed] = useState(true);
const [shouldShowPaneInitFailure, setShouldShowPaneInitFailure] =
useState(true);
const item =
items.find((item) => identifiers?.id === ItemUtils.getMappingId(item)) ??
null;
const handleToggleCustomize = () => {
setIsCustomizeClosed(!isCustomizeClosed);
};
const handleCustomItemEdit = (adjustments: Record<string, any>): void => {
if (item === null) {
return;
}
if (adjustments.notes === "") {
adjustments.notes = null;
}
inventoryManager.handleCustomEdit({
item,
adjustments,
});
};
const handleCustomDataUpdate = (
adjustmentType: Constants.AdjustmentTypeEnum,
value: any
): void => {
if (item) {
inventoryManager.handleCustomizationSet({
item,
adjustmentType,
value,
});
}
};
const handleRemoveCustomizations = (): void => {
if (item) {
inventoryManager.handleCustomizationsRemove({ item });
}
};
const handleDataOriginClick = (dataOrigin: DataOrigin) => {
let component = getDataOriginComponentInfo(dataOrigin);
if (component.type !== PaneComponentEnum.ERROR_404) {
paneHistoryPush(component.type, component.identifiers);
}
};
const handleSpellClick = (spell: Spell): void => {
let component = getSpellComponentInfo(spell);
if (component.type) {
paneHistoryPush(component.type, component.identifiers);
}
};
const handleInfusionClick = (infusion: Infusion): void => {
const choiceKey = InfusionUtils.getChoiceKey(infusion);
if (choiceKey !== null) {
paneHistoryPush(
PaneComponentEnum.INFUSION_CHOICE,
PaneIdentifierUtils.generateInfusionChoice(choiceKey)
);
}
};
const handleActionClick = (action: Action): void => {
const dataOrigin = ActionUtils.getDataOrigin(action);
let component = getDataOriginComponentInfo(dataOrigin);
if (component.type !== PaneComponentEnum.ERROR_404) {
paneHistoryPush(component.type, component.identifiers);
}
};
const handleParentClick = (): void => {
if (item) {
const itemPlan = ItemUtils.getItemPlan(item, itemPlans);
if (itemPlan) {
const dataOrigin = ItemPlanUtils.getDataOrigin(itemPlan);
let component = getDataOriginComponentInfo(dataOrigin);
if (component.type !== PaneComponentEnum.ERROR_404) {
paneHistoryPush(component.type, component.identifiers);
}
}
}
};
if (item === null) {
return shouldShowPaneInitFailure ? (
<PaneInitFailureContent
errorTitle="Item Not Found"
errorMessage="That item is no longer in your inventory! Please try again."
toastMeta={{ level: "info" }}
/>
) : null;
}
let parentName: string | null = null;
const itemPlan = ItemUtils.getItemPlan(item, itemPlans);
if (itemPlan) {
const dataOrigin = ItemPlanUtils.getDataOrigin(itemPlan);
parentName = EntityUtils.getDataOriginName(dataOrigin);
}
return (
<div {...props}>
<Header
parent={parentName}
onClick={handleParentClick}
preview={<Preview imageUrl={ItemUtils.getAvatarUrl(item)} />}
>
<EditableName onClick={handleToggleCustomize}>
<ItemName item={item} />
</EditableName>
</Header>
<ItemListInformationCollapsible item={item} ruleData={ruleData} />
<ItemDetail
theme={theme}
key={ItemUtils.getUniqueKey(item)}
item={item}
weaponSpellDamageGroups={weaponSpellDamageGroups}
ruleData={ruleData}
snippetData={snippetData}
onCustomDataUpdate={handleCustomDataUpdate}
onCustomizationsRemove={handleRemoveCustomizations}
onDataOriginClick={handleDataOriginClick}
onSpellClick={handleSpellClick}
onInfusionClick={handleInfusionClick}
onMasteryActionClick={handleActionClick}
entityValueLookup={entityValueLookup}
infusionChoiceLookup={infusionChoiceLookup}
isReadonly={isReadonly}
container={HelperUtils.lookupDataOrFallback(
containerLookup,
ItemUtils.getContainerDefinitionKey(item)
)}
showCustomize={!isReadonly}
onPostRemoveNavigation={PaneComponentEnum.EQUIPMENT_MANAGE}
partyInfo={partyInfo}
onCustomItemEdit={handleCustomItemEdit}
isCustomizeClosed={isCustomizeClosed}
onCustomizeClick={handleToggleCustomize}
onRemoveItem={() => setShouldShowPaneInitFailure(false)}
/>
</div>
);
};