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
@@ -1,12 +1,10 @@
import { ComponentType, FC, HTMLAttributes, ReactNode } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { useSelector } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom";
import {
LightLinkOutSvg,
ThemedBackdropSvg,
ThemedBuilderSvg,
ThemedExportSvg,
ThemedFrameSvg,
ThemedLongRestSvg,
ThemedManageLevelSvg,
@@ -16,9 +14,10 @@ import {
ThemedShareSvg,
ThemedShortRestSvg,
ThemedThemeIconSvg,
ThemedChatBubbleSvg,
} from "@dndbeyond/character-components/es";
import D6 from "@dndbeyond/fontawesome-cache/svgs/regular/dice-d6.svg";
import PdfSvg from "@dndbeyond/fontawesome-cache/svgs/light/file-pdf.svg";
import ListTimeline from "@dndbeyond/fontawesome-cache/svgs/light/list-timeline.svg";
import LinkIcon from "@dndbeyond/fontawesome-cache/svgs/solid/arrow-up-right-from-square.svg";
import { Button } from "~/components/Button";
import config from "~/config";
@@ -49,6 +48,8 @@ export const CharacterManagePane: FC<CharacterManagePaneProps> = ({
...props
}) => {
const navigate = useNavigate();
const { search } = useLocation();
const isVttView = new URLSearchParams(search).get("view") === "vtt";
const isReadonly = useSelector(appEnvSelectors.getIsReadonly);
const builderUrl = useSelector(sheetAppSelectors.getBuilderUrl);
@@ -107,15 +108,23 @@ export const CharacterManagePane: FC<CharacterManagePaneProps> = ({
share: ThemedShareSvg,
managelevel: ThemedManageLevelSvg,
managexp: ThemedManageXpSvg,
gamelog: ThemedChatBubbleSvg,
frame: ThemedFrameSvg,
backdrop: ThemedBackdropSvg,
theme: ThemedThemeIconSvg,
portrait: ThemedPortraitSvg,
preferences: ThemedPreferencesSvg,
downloadpdf: ThemedExportSvg,
downloadpdf: PdfSvg,
};
if (menuKey === "gamelog") {
return (
<ListTimeline
className="ddbc-svg ddbc-svg--themed"
style={{ fill: characterTheme.themeColor }}
/>
);
}
const IconNode: ComponentType<any> | null =
menuIconLookup[menuKey] &&
helperUtils.lookupDataOrFallback(menuIconLookup, menuKey);
@@ -124,17 +133,12 @@ export const CharacterManagePane: FC<CharacterManagePaneProps> = ({
return null;
}
if (menuKey === "gamelog") {
return (
<D6
className="ddbc-svg ddbc-svg--themed"
style={{ fill: characterTheme.themeColor }}
/>
);
}
return (
<IconNode theme={decorationUtils.getCharacterTheme(decorationInfo)} />
<IconNode
className="ddbc-svg ddbc-svg--themed"
style={{ fill: characterTheme.themeColor }}
theme={decorationUtils.getCharacterTheme(decorationInfo)}
/>
);
};
@@ -144,7 +148,7 @@ export const CharacterManagePane: FC<CharacterManagePaneProps> = ({
data-testid="character-manage-pane"
{...props}
>
<Overview />
<Overview isVttView={isVttView} />
{/* Display Readonly CTA or MENU */}
{isReadonly ? (
<div className={styles.readonlyBackground}>
@@ -162,25 +166,27 @@ export const CharacterManagePane: FC<CharacterManagePaneProps> = ({
variant="solid"
target="_blank"
themed
href={`${BASE_PATHNAME}/builder`}
href={`${BASE_PATHNAME}/builder${search}`}
forceThemeMode="dark"
>
<span>Create a Character</span>
<LightLinkOutSvg />
<LinkIcon className={styles.linkIcon} />
</Button>
</div>
</div>
) : (
<PaneMenu>
<PaneMenuGroup label="My Character">
<PaneMenuItem
menukey="builder"
prefixIcon={getMenuIconNode("builder")}
suffixIcon={<LightLinkOutSvg />}
onClick={handleBuilderClick}
>
Manage Character & Levels
</PaneMenuItem>
{!isVttView && (
<PaneMenuItem
menukey="builder"
prefixIcon={getMenuIconNode("builder")}
suffixIcon={<LinkIcon className={styles.linkIcon} />}
onClick={handleBuilderClick}
>
Manage Character & Levels
</PaneMenuItem>
)}
{preferences.progressionType ===
PreferenceProgressionTypeEnum.XP && (
<PaneMenuItem
@@ -199,47 +205,52 @@ export const CharacterManagePane: FC<CharacterManagePaneProps> = ({
Character Settings
</PaneMenuItem>
</PaneMenuGroup>
<PaneMenuGroup label="Play">
<PaneMenuItem
menukey="gamelog"
prefixIcon={getMenuIconNode("gamelog")}
onClick={handleGameLogMenuClick}
>
Game Log
</PaneMenuItem>
<PaneMenuItem
menukey="shortrest"
prefixIcon={getMenuIconNode("shortrest")}
onClick={handleShortRestMenuClick}
>
Short Rest
</PaneMenuItem>
<PaneMenuItem
menukey="longrest"
prefixIcon={getMenuIconNode("longrest")}
onClick={handleLongRestMenuClick}
>
Long Rest
</PaneMenuItem>
</PaneMenuGroup>
<PaneMenuGroup label="Share">
{preferences.privacyType === PreferencePrivacyTypeEnum.PUBLIC && (
<PaneMenuItem
menukey="share"
prefixIcon={getMenuIconNode("share")}
onClick={handleShareMenuClick}
>
Shareable Link
</PaneMenuItem>
)}
<PaneMenuItem
menukey="downloadpdf"
prefixIcon={getMenuIconNode("downloadpdf")}
onClick={handlePdfClick}
>
Export to PDF
</PaneMenuItem>
</PaneMenuGroup>
{!isVttView && (
<>
<PaneMenuGroup label="Play">
<PaneMenuItem
menukey="gamelog"
prefixIcon={getMenuIconNode("gamelog")}
onClick={handleGameLogMenuClick}
>
Game Log
</PaneMenuItem>
<PaneMenuItem
menukey="shortrest"
prefixIcon={getMenuIconNode("shortrest")}
onClick={handleShortRestMenuClick}
>
Short Rest
</PaneMenuItem>
<PaneMenuItem
menukey="longrest"
prefixIcon={getMenuIconNode("longrest")}
onClick={handleLongRestMenuClick}
>
Long Rest
</PaneMenuItem>
</PaneMenuGroup>
<PaneMenuGroup label="Share">
{preferences.privacyType ===
PreferencePrivacyTypeEnum.PUBLIC && (
<PaneMenuItem
menukey="share"
prefixIcon={getMenuIconNode("share")}
onClick={handleShareMenuClick}
>
Shareable Link
</PaneMenuItem>
)}
<PaneMenuItem
menukey="downloadpdf"
prefixIcon={getMenuIconNode("downloadpdf")}
onClick={handlePdfClick}
>
Export to PDF
</PaneMenuItem>
</PaneMenuGroup>
</>
)}
</PaneMenu>
)}
</div>
@@ -8,11 +8,10 @@ import {
useRef,
useState,
} from "react";
import { useDispatch, useSelector } from "react-redux";
import { useSelector } from "react-redux";
import {
CharacterAvatarPortrait,
CharacterName,
CharacterProgressionSummary,
CharacterSummary,
LightPencilSvg,
@@ -20,16 +19,14 @@ import {
} from "@dndbeyond/character-components/es";
import { Button } from "~/components/Button/Button";
import {
CharacterNameLimitMsg,
DeathCauseEnum,
InputLimits,
} from "~/constants";
import { CharacterNameLimitMsg, InputLimits } from "~/constants";
import { useCharacterTheme } from "~/contexts/CharacterTheme";
import { useSidebar } from "~/contexts/Sidebar";
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
import { useDispatch } from "~/hooks/useDispatch";
import { useMaxLengthErrorHandling } from "~/hooks/useErrorHandling/useMaxLengthErrorHandling";
import useUserId from "~/hooks/useUserId";
import { CharacterName } from "~/subApps/sheet/components/CharacterName";
import { appEnvActions } from "~/tools/js/Shared/actions";
import { appEnvSelectors } from "~/tools/js/Shared/selectors";
import { CharacterStatusSlug } from "~/types";
@@ -39,16 +36,21 @@ import { PopoverContent } from "../../../../../../../components/PopoverContent";
import { PaneComponentEnum } from "../../../types";
import styles from "./styles.module.css";
export interface OverviewProps extends HTMLAttributes<HTMLDivElement> {}
export interface OverviewProps extends HTMLAttributes<HTMLDivElement> {
isVttView?: boolean;
}
export const Overview: FC<OverviewProps> = ({ className, ...props }) => {
export const Overview: FC<OverviewProps> = ({
isVttView = false,
className,
...props
}) => {
const {
ruleData,
characterName,
characterGender: gender,
race: species,
experienceInfo: xpInfo,
deathCause,
preferences,
decorationInfo,
playerName,
@@ -138,14 +140,16 @@ export const Overview: FC<OverviewProps> = ({ className, ...props }) => {
{
<div
className={clsx([
styles.characterName,
styles.characterNameContainer,
!isReadonly && !isVttView && styles.editableName,
isEditingCharacterName && styles.editName,
])}
onClick={isReadonly ? undefined : handleNameClick}
onClick={isReadonly || isVttView ? undefined : handleNameClick}
>
{isEditingCharacterName ? (
<>
<input
className={styles.nameInput}
ref={inputRef}
type="text"
defaultValue={characterName ?? ""}
@@ -158,12 +162,8 @@ export const Overview: FC<OverviewProps> = ({ className, ...props }) => {
</>
) : (
<>
<CharacterName
name={characterName ?? ""}
isDead={deathCause !== DeathCauseEnum.NONE}
isFaceMenu={true}
/>
{!isReadonly && <LightPencilSvg />}
<CharacterName />
{!isReadonly && !isVttView && <LightPencilSvg />}
</>
)}
</div>