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
@@ -14,15 +14,14 @@ import {
rulesEngineSelectors,
BaseItemDefinitionContract,
RuleData,
CampaignUtils,
CharacterTheme,
Container,
ContainerUtils,
InventoryManager,
Constants,
serviceDataSelectors,
PartyInfo,
ItemManager,
ContainerManager,
} from "@dndbeyond/character-rules-engine/es";
import { Button } from "~/components/Button";
@@ -33,23 +32,24 @@ import { Popover } from "~/components/Popover";
import { PopoverContent } from "~/components/PopoverContent";
import { useSidebar } from "~/contexts/Sidebar";
import { PaneInfo } from "~/contexts/Sidebar/Sidebar";
import { ButtonWithMenu } from "~/subApps/sheet/components/Sidebar/components/ButtonWithMenu";
import { Header } from "~/subApps/sheet/components/Sidebar/components/Header";
import { Heading } from "~/subApps/sheet/components/Sidebar/components/Heading";
import { PaneComponentEnum } from "~/subApps/sheet/components/Sidebar/types";
import { CustomItemCreator } from "../../../components/CustomItemCreator";
import EquipmentShop from "../../../components/EquipmentShop";
import ItemDetail from "../../../components/ItemDetail";
import { ItemSlotManager } from "../../../components/ItemSlotManager";
import { ThemeButtonWithMenu } from "../../../components/common/Button";
import { InventoryManagerContext } from "../../../managers/InventoryManagerContext";
import { SharedAppState } from "../../../stores/typings";
import styles from "./styles.module.css";
interface Props {
loadAvailableItems: (
additionalConfig?: Partial<ApiAdapterRequestConfig>
) => ApiAdapterPromise<ApiResponse<Array<BaseItemDefinitionContract>>>;
ruleData: RuleData;
proficiencyBonus: number;
containers: Array<Container>;
theme: CharacterTheme;
partyInfo: PartyInfo | null;
@@ -59,79 +59,82 @@ interface Props {
class EquipmentManagePane extends React.PureComponent<Props> {
renderInventory = (inventory: Array<ItemManager>): React.ReactNode => {
const {
theme,
ruleData,
proficiencyBonus,
inventoryManager,
partyInfo,
containers,
} = this.props;
const { theme, ruleData, inventoryManager, partyInfo, containers } =
this.props;
return inventory.map((item) => {
return inventory.map((item, i) => {
const isContainer = item.isContainer();
const container = inventoryManager.getContainer(
item.generateContainerDefinitionKey()
);
// to ensure key is unique even if two items are the same, append index
// the index helps in re-renders when items are added/removed/moved around
const itemKey = item.getUniqueKey() + i;
const canMove = inventoryManager.canMoveItem(item.item);
const canDelete = inventoryManager.canRemoveItem(item.item);
const calloutButton: React.ReactNode = isContainer ? (
<Popover
trigger={
<Button size="xx-small" variant="outline" themed>
Delete
</Button>
}
position="bottomRight"
data-testid="remove-container-button"
maxWidth={250}
>
<PopoverContent
title={`Remove ${item.getName()}?`}
content={`Removing the ${item.getName()} will also remove all of its ${
container && container.hasInfusions() ? "infusions and " : " "
} contents.`}
confirmText="Delete"
onConfirm={() => item.handleRemove()}
withCancel
/>
</Popover>
) : canMove ? (
<ThemeButtonWithMenu
showSingleOption={true}
containerEl={
document.querySelector(".ct-sidebar__portal") as HTMLElement
}
groupedOptions={ContainerUtils.getGroupedOptions(
item.getContainerDefinitionKey(),
containers,
"Move To:",
partyInfo
? CampaignUtils.getSharingState(partyInfo)
: Constants.PartyInventorySharingStateEnum.OFF
)}
buttonStyle="outline"
onSelect={(containerDefinitionKey) =>
item.handleMove({ containerDefinitionKey })
}
>
Move
</ThemeButtonWithMenu>
) : (
<Button
onClick={() => item.handleRemove()}
size="xx-small"
variant="outline"
themed
>
Delete
</Button>
);
//if the item is a container - render the delete button withPopover only if it "canDelete"
//if the item is not a container - render the move button if it "canMove" otherwise render the delete button if it "canDelete"
//if neither - render null;
let calloutButton: React.ReactNode = null;
if (isContainer && canDelete) {
calloutButton = (
<Popover
trigger={
<Button size="xx-small" variant="outline" themed>
Delete
</Button>
}
position="bottomRight"
data-testid="remove-container-button"
maxWidth={250}
>
<PopoverContent
title={`Remove ${item.getName()}?`}
content={`Removing the ${item.getName()} will also remove all of its ${
container && container.hasInfusions() ? "infusions and " : " "
} contents.`}
confirmText="Delete"
onConfirm={() => item.handleRemove()}
withCancel
/>
</Popover>
);
} else if (!isContainer && canMove) {
calloutButton = (
<ButtonWithMenu
showSingleOption={true}
placement="bottom-end"
variant="outline"
groupedOptions={ContainerUtils.getGroupedOptions(
item.getContainerDefinitionKey(),
containers,
"Move To:"
)}
onSelect={(containerDefinitionKey) =>
item.handleMove({ containerDefinitionKey })
}
>
Move
</ButtonWithMenu>
);
} else if (!isContainer && canDelete) {
calloutButton = (
<Button
onClick={() => item.handleRemove()}
size="xx-small"
variant="outline"
themed
>
Delete
</Button>
);
}
return (
<Collapsible
key={item.getUniqueKey()}
key={itemKey}
className={`ct-equipment-manage-pane__item${
item.isContainer()
? " ct-equipment-manage-pane__item--is-container"
@@ -158,7 +161,6 @@ class EquipmentManagePane extends React.PureComponent<Props> {
}
}}
useTooltip={false}
showEmptySlot={!isContainer}
/>
</div>
<div
@@ -186,22 +188,24 @@ class EquipmentManagePane extends React.PureComponent<Props> {
ruleData={ruleData}
showCustomize={false}
showImage={false}
proficiencyBonus={proficiencyBonus}
partyInfo={partyInfo}
/>
</Collapsible>
);
});
};
renderContainers = (): React.ReactNode => {
const { theme, inventoryManager } = this.props;
renderContainers = (containers: ContainerManager[]): React.ReactNode => {
return containers.map((container) => {
const isEquipmentContainer =
container.isCharacterContainer() || container.isPartyContainer();
return inventoryManager.getAllContainers().map((container) => {
const containerInventory = container.getInventoryItems({
includeContainer: true,
}).items;
const inventoryLength = containerInventory.length;
const inventoryLength =
containerInventory.length - (isEquipmentContainer ? 0 : 1); //don't count the container item itself if its an item and not the character/party container
let isEmpty: boolean = inventoryLength === 0;
let headerNode: React.ReactNode = (
@@ -239,11 +243,11 @@ class EquipmentManagePane extends React.PureComponent<Props> {
render() {
const {
ruleData,
proficiencyBonus,
containers,
theme,
partyInfo,
paneHistoryPush,
inventoryManager,
} = this.props;
return (
@@ -255,13 +259,18 @@ class EquipmentManagePane extends React.PureComponent<Props> {
containers={containers}
theme={theme}
ruleData={ruleData}
proficiencyBonus={proficiencyBonus}
/>
<CustomItemCreator containers={containers} />
</Collapsible>
{/*container collapsibles*/}
{this.renderContainers()}
<Heading className={styles.containerHeading}>My Inventory</Heading>
{this.renderContainers(inventoryManager.getCharacterContainers())}
{inventoryManager.getPartyContainers().length > 0 && (
<Heading className={styles.containerHeading}>Party Inventory</Heading>
)}
{this.renderContainers(inventoryManager.getPartyContainers())}
<div className="ct-equipment-manage-pane__links">
<div className="ct-equipment-manage-pane__link">
@@ -299,7 +308,6 @@ class EquipmentManagePane extends React.PureComponent<Props> {
function mapStateToProps(state: SharedAppState) {
return {
ruleData: rulesEngineSelectors.getRuleData(state),
proficiencyBonus: rulesEngineSelectors.getProficiencyBonus(state),
containers: rulesEngineSelectors.getInventoryContainers(state),
theme: rulesEngineSelectors.getCharacterTheme(state),
partyInfo: serviceDataSelectors.getPartyInfo(state),