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,148 @@
|
||||
import clsx from "clsx";
|
||||
import {
|
||||
FC,
|
||||
HTMLAttributes,
|
||||
MouseEvent,
|
||||
ReactNode,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import ChevronDown from "@dndbeyond/fontawesome-cache/svgs/solid/chevron-down.svg";
|
||||
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
export interface AccordionProps extends HTMLAttributes<HTMLElement> {
|
||||
variant?: "default" | "text" | "paper";
|
||||
summary: ReactNode;
|
||||
description?: ReactNode;
|
||||
size?: "small" | "medium";
|
||||
forceShow?: boolean;
|
||||
useTheme?: boolean;
|
||||
resetOpen?: boolean;
|
||||
override?: boolean | null;
|
||||
handleIsOpen?: (id: string, isOpen: boolean) => void;
|
||||
summaryAction?: ReactNode;
|
||||
summaryImage?: string;
|
||||
summaryImageAlt?: string;
|
||||
summaryImageSize?: number;
|
||||
summaryMetaItems?: Array<ReactNode>;
|
||||
showAlert?: boolean;
|
||||
}
|
||||
|
||||
export const Accordion: FC<AccordionProps> = ({
|
||||
className,
|
||||
summary,
|
||||
description,
|
||||
size = "medium",
|
||||
variant = "default",
|
||||
children,
|
||||
forceShow = false,
|
||||
// style,
|
||||
useTheme,
|
||||
resetOpen,
|
||||
handleIsOpen,
|
||||
override = null,
|
||||
id = "",
|
||||
summaryAction,
|
||||
summaryImage,
|
||||
summaryImageAlt,
|
||||
summaryImageSize = 32,
|
||||
summaryMetaItems,
|
||||
showAlert,
|
||||
...props
|
||||
}) => {
|
||||
const summaryRef = useRef<HTMLElement>(null);
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const loaded = useRef(false);
|
||||
const [isOpen, setIsOpen] = useState<boolean>(forceShow);
|
||||
const [height, setHeight] = useState<number | string>();
|
||||
|
||||
const handleToggle = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
setIsOpen((current) => {
|
||||
if (handleIsOpen && id) handleIsOpen(id, !current);
|
||||
return !current;
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const summaryHeight = summaryRef.current?.clientHeight;
|
||||
const contentHeight = contentRef.current?.getBoundingClientRect().height;
|
||||
|
||||
if (isOpen) {
|
||||
// If the dialog is open and it's not the first load, set the height to the summary + content
|
||||
if (summaryHeight && contentHeight && loaded.current === true)
|
||||
setHeight(summaryHeight + contentHeight);
|
||||
} else {
|
||||
// If the dialog is closed, set the height to the summary
|
||||
if (summaryHeight) setHeight(summaryHeight);
|
||||
}
|
||||
loaded.current = true;
|
||||
}, [isOpen, resetOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (resetOpen && !isOpen) {
|
||||
setIsOpen(true);
|
||||
}
|
||||
}, [resetOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (override !== null) {
|
||||
setIsOpen(override);
|
||||
}
|
||||
}, [override]);
|
||||
|
||||
return (
|
||||
<details
|
||||
className={clsx([
|
||||
styles.details,
|
||||
styles[size],
|
||||
styles[variant],
|
||||
useTheme && styles.theme,
|
||||
showAlert && styles.alert,
|
||||
className,
|
||||
])}
|
||||
open={isOpen}
|
||||
// style={{ height, ...style }} INVESTIGATE THIS LATER
|
||||
{...props}
|
||||
>
|
||||
<summary
|
||||
className={styles.summary}
|
||||
onClick={handleToggle}
|
||||
ref={summaryRef}
|
||||
>
|
||||
{summaryImage && (
|
||||
<img
|
||||
className={styles.image}
|
||||
src={summaryImage}
|
||||
alt={summaryImageAlt}
|
||||
width={summaryImageSize}
|
||||
/>
|
||||
)}
|
||||
<div className={styles.heading}>
|
||||
<div>
|
||||
{summary}
|
||||
{summaryMetaItems && (
|
||||
<div className={styles.metaItems}>
|
||||
{summaryMetaItems.map((metaItem, idx) => (
|
||||
<div key={uuidv4()} className={styles.metaItem}>
|
||||
{metaItem}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.actions}>{summaryAction}</div>
|
||||
<ChevronDown className={styles.icon} />
|
||||
</div>
|
||||
{description && <div className={styles.description}>{description}</div>}
|
||||
</summary>
|
||||
<div className={styles.content} ref={contentRef}>
|
||||
{children}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user