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,70 @@
import clsx from "clsx";
import { FC, HTMLAttributes, type MouseEvent } from "react";
import { createPortal } from "react-dom";
import GridIcon from "@dndbeyond/fontawesome-cache/svgs/solid/grid.svg";
import { useIsVisible } from "@dndbeyond/ttui/hooks/useIsVisible";
import { useSidebar } from "~/contexts/Sidebar";
import { useUnpropagatedClick } from "~/hooks/useUnpropagatedClick";
import { sidebarId } from "../../constants";
import { ArrowsLeftIcon } from "../Sidebar/svgs/ArrowsLeftIcon";
import { ArrowsRightIcon } from "../Sidebar/svgs/ArrowsRightIcon";
import { SectionMenu } from "./SectionMenu";
import styles from "./styles.module.css";
export interface MobileNavProps extends HTMLAttributes<HTMLDivElement> {}
export const MobileNav: FC<MobileNavProps> = ({ className, ...props }) => {
const {
ref,
isVisible: isMenuVisible,
setIsVisible: setIsMenuVisible,
} = useIsVisible(false);
const { sidebar } = useSidebar();
const handleToggleSidebar = useUnpropagatedClick(() => {
setIsMenuVisible(false);
sidebar.setIsVisible(!sidebar.isVisible);
});
const handleToggleMenu = () => {
setIsMenuVisible(!isMenuVisible);
};
const handleCloseMenu = (e?: MouseEvent) => {
e?.stopPropagation();
setIsMenuVisible(false);
};
return createPortal(
<div className={clsx([styles.mobileNav, className])} ref={ref} {...props}>
{!sidebar.isVisible && (
<div>
<button
className={styles.navToggle}
onClick={handleToggleMenu}
aria-label="Show navigation"
>
<GridIcon className={styles.icon} />
</button>
<SectionMenu open={isMenuVisible} onClose={handleCloseMenu} />
</div>
)}
<button
className={styles.sidebarToggle}
onClick={handleToggleSidebar}
aria-controls={sidebarId}
aria-label={`${sidebar.isVisible ? "Hide" : "Show"} sidebar`}
>
{sidebar.isVisible ? (
<ArrowsRightIcon className={styles.icon} />
) : (
<ArrowsLeftIcon className={styles.icon} />
)}
</button>
</div>,
document.body
);
};
@@ -0,0 +1,24 @@
import clsx from "clsx";
import { FC } from "react";
import { ButtonProps } from "@dndbeyond/ttui/components/Button";
import { Button } from "~/components/Button";
import styles from "./styles.module.css";
export interface SectionButtonProps extends ButtonProps {}
export const SectionButton: FC<SectionButtonProps> = ({
className,
onClick,
...props
}) => {
return (
<Button
className={clsx([styles.sectionButton, className])}
onClick={onClick}
{...props}
/>
);
};
@@ -0,0 +1,116 @@
import clsx from "clsx";
import { FC } from "react";
import { createPortal } from "react-dom";
import { useSelector } from "react-redux";
import { rulesEngineSelectors } from "@dndbeyond/character-rules-engine";
import { Dialog, DialogProps } from "@dndbeyond/ttui/components/Dialog";
import { useSheetContext } from "~/subApps/sheet/contexts/Sheet";
import {
ActionsIcon,
AttributesIcon,
DescriptionIcon,
EquipmentIcon,
ExtrasIcon,
FeatureTraitsIcon,
NotesIcon,
ProficienciesSvg,
SkillsIcon,
SpellsIcon,
} from "~/svgs";
import { appEnvSelectors } from "~/tools/js/Shared/selectors";
import { SectionButton } from "../SectionButton";
import styles from "./styles.module.css";
export interface SectionMenuProps extends DialogProps {
open: boolean;
}
export const SectionMenu: FC<SectionMenuProps> = ({
className,
open,
...props
}) => {
const { setMobileActiveSectionId: setId } = useSheetContext();
const isReadonly = useSelector(appEnvSelectors.getIsReadonly);
const hasSpells = useSelector(rulesEngineSelectors.hasSpells);
return createPortal(
<>
<Dialog
className={clsx([styles.sectionNav, className])}
open={open}
modal
{...props}
>
<SectionButton
className={styles.fullWidth}
onClick={() => setId("main")}
>
<AttributesIcon />
<span>
Abilities, Saves, Senses
<span className={styles.mobile}>
, Proficiencies, Training, Skills
</span>
</span>
</SectionButton>
<SectionButton
className={styles.mobile}
onClick={() => setId("skills")}
>
<SkillsIcon />
Skills
</SectionButton>
<SectionButton onClick={() => setId("actions")}>
<ActionsIcon />
Actions
</SectionButton>
<SectionButton onClick={() => setId("equipment")}>
<EquipmentIcon />
Inventory
</SectionButton>
{hasSpells && (
<SectionButton onClick={() => setId("spells")}>
<SpellsIcon />
Spells
</SectionButton>
)}
<SectionButton onClick={() => setId("features_traits")}>
<FeatureTraitsIcon />
Features & Traits
</SectionButton>
<SectionButton
className={styles.mobile}
onClick={() => setId("proficiencies")}
>
<ProficienciesSvg />
<span>Proficiencies & Training</span>
</SectionButton>
{!isReadonly && (
<SectionButton onClick={() => setId("description")}>
<DescriptionIcon />
Background
</SectionButton>
)}
{!isReadonly && (
<SectionButton onClick={() => setId("notes")}>
<NotesIcon />
Notes
</SectionButton>
)}
<SectionButton
className={hasSpells ? styles.fullWidth : ""}
onClick={() => setId("extras")}
>
<ExtrasIcon />
Extras
</SectionButton>
</Dialog>
{open && <div className={styles.backdrop} />}
</>,
document.body
);
};