New source found from dndbeyond.com
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { orderBy } from "lodash";
|
||||
import { FC, Fragment, useMemo } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import ArrowRightIcon from "@dndbeyond/fontawesome-cache/svgs/solid/arrow-right.svg";
|
||||
import LinkIcon from "@dndbeyond/fontawesome-cache/svgs/solid/arrow-up-right-from-square.svg";
|
||||
|
||||
import { Accordion } from "~/components/Accordion";
|
||||
import { Button } from "~/components/Button";
|
||||
@@ -13,6 +13,7 @@ import { HtmlContent } from "~/components/HtmlContent";
|
||||
import { Reference } from "~/components/Reference";
|
||||
import { isNotNullOrUndefined } from "~/helpers/validation";
|
||||
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
|
||||
import { useDispatch } from "~/hooks/useDispatch";
|
||||
import { builderSelectors } from "~/tools/js/CharacterBuilder/selectors";
|
||||
|
||||
import styles from "./styles.module.css";
|
||||
@@ -97,7 +98,7 @@ export const ConfirmClassModal: FC<ConfirmClassModalProps> = ({
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{confirmClass.name} Details Page <ArrowRightIcon />
|
||||
{confirmClass.name} Details Page <LinkIcon />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import React, { FC } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
import ArrowRightIcon from "@dndbeyond/fontawesome-cache/svgs/solid/arrow-right.svg";
|
||||
|
||||
@@ -11,6 +10,7 @@ import { SummaryList } from "~/components/SummaryList";
|
||||
import { AppContextTypeEnum, DisplayConfigurationTypeEnum } from "~/constants";
|
||||
import { isNotNullOrUndefined } from "~/helpers/validation";
|
||||
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
|
||||
import { useDispatch } from "~/hooks/useDispatch";
|
||||
import { Feat, RacialTraitContract as RacialTrait } from "~/types";
|
||||
|
||||
import { useSpeciesContext } from "../../contexts/Species";
|
||||
|
||||
@@ -41,7 +41,9 @@ export const EditorWithDialog: FC<EditorWithDialogProps> = ({
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const textareaInput = useRef<HTMLDivElement>(null);
|
||||
const id = uuidv4();
|
||||
const headingNode = cloneElement(heading, { className: styles.heading });
|
||||
const headingNode = cloneElement(heading, { className: styles.heading } as {
|
||||
className: string;
|
||||
});
|
||||
|
||||
const handleInputBlur = (content: string): void => {
|
||||
if (saveOnBlur) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import { FC, FocusEvent, useMemo, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
import {
|
||||
characterActions,
|
||||
@@ -14,6 +13,7 @@ import {
|
||||
|
||||
import { ConfirmModal, ConfirmModalProps } from "~/components/ConfirmModal";
|
||||
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
|
||||
import { useDispatch } from "~/hooks/useDispatch";
|
||||
import {
|
||||
HP_BASE_MAX_VALUE,
|
||||
HP_BONUS_VALUE,
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
ChangeEvent,
|
||||
FC,
|
||||
FocusEvent,
|
||||
FormEvent,
|
||||
HTMLAttributes,
|
||||
HTMLInputTypeAttribute,
|
||||
useEffect,
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
} from "react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import formStyles from "../../styles/form.module.css";
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
interface InputProps extends HTMLAttributes<HTMLInputElement> {
|
||||
@@ -18,14 +20,23 @@ interface InputProps extends HTMLAttributes<HTMLInputElement> {
|
||||
autoComplete?: string;
|
||||
}
|
||||
|
||||
export interface InputFieldProps extends HTMLAttributes<HTMLInputElement> {
|
||||
export type InputElements = HTMLInputElement | HTMLTextAreaElement;
|
||||
|
||||
export interface InputFieldProps
|
||||
extends Omit<
|
||||
HTMLAttributes<HTMLInputElement>,
|
||||
"onBlur" | "onChange" | "onFocus"
|
||||
> {
|
||||
errorMessage?: string;
|
||||
initialValue?: string | number | null;
|
||||
label: string;
|
||||
maxLength?: number;
|
||||
placeholder?: string;
|
||||
type?: HTMLInputTypeAttribute;
|
||||
type?: HTMLInputTypeAttribute | "textarea";
|
||||
inputProps?: InputProps;
|
||||
onBlur?: (event: FocusEvent<InputElements, Element>) => void;
|
||||
onChange?: (event: FormEvent<InputElements>) => void;
|
||||
onFocus?: (event: FocusEvent<InputElements, Element>) => void;
|
||||
}
|
||||
|
||||
export const InputField: FC<InputFieldProps> = ({
|
||||
@@ -49,7 +60,7 @@ export const InputField: FC<InputFieldProps> = ({
|
||||
const [showError, setShowError] = useState(false);
|
||||
const id = props.id ?? `input-field-${uuidv4()}`;
|
||||
|
||||
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
const handleChange = (e: ChangeEvent<InputElements>) => {
|
||||
const valueLength = e.target.value.length;
|
||||
if (maxLength) {
|
||||
// If the value length exceeds maxLength, show error
|
||||
@@ -75,7 +86,7 @@ export const InputField: FC<InputFieldProps> = ({
|
||||
return;
|
||||
};
|
||||
|
||||
const handleBlur = (e: FocusEvent<HTMLInputElement>) => {
|
||||
const handleBlur = (e: FocusEvent<InputElements>) => {
|
||||
const intValue = parseInt(e.target.value);
|
||||
|
||||
// If entered value is below the minimum, reset to minimum
|
||||
@@ -103,7 +114,7 @@ export const InputField: FC<InputFieldProps> = ({
|
||||
setShowError(false);
|
||||
};
|
||||
|
||||
const handleFocus = (e: FocusEvent<HTMLInputElement>) => {
|
||||
const handleFocus = (e: FocusEvent<InputElements>) => {
|
||||
// Call the provided onFocus handler if it exists
|
||||
if (onFocus) onFocus(e);
|
||||
// Check for maxLength error
|
||||
@@ -122,18 +133,29 @@ export const InputField: FC<InputFieldProps> = ({
|
||||
|
||||
return (
|
||||
<div className={clsx([styles.inputField, className])} {...props}>
|
||||
<label className={styles.label} htmlFor={id}>
|
||||
<label className={formStyles.label} htmlFor={id}>
|
||||
{label}
|
||||
</label>
|
||||
<input
|
||||
className={styles.input}
|
||||
value={value ?? ""}
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
{...inputAttrs}
|
||||
{...inputProps}
|
||||
/>
|
||||
{type !== "textarea" ? (
|
||||
<input
|
||||
className={formStyles.input}
|
||||
value={value ?? ""}
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
{...inputAttrs}
|
||||
{...inputProps}
|
||||
/>
|
||||
) : (
|
||||
<textarea
|
||||
className={styles.input}
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
>
|
||||
{value}
|
||||
</textarea>
|
||||
)}
|
||||
{showError && <span className={styles.error}>{errorMessage}</span>}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import clsx from "clsx";
|
||||
import { FC, HTMLAttributes } from "react";
|
||||
|
||||
import { NoResultsFound } from "~/components/NoResultsFound";
|
||||
|
||||
import { GroupedListingItem, ListingItem } from "../../types";
|
||||
import { ListingGroup } from "./ListingGroup";
|
||||
import { ListingItemButton } from "./ListingItemButton/ListingItemButton";
|
||||
@@ -50,7 +52,7 @@ export const Listing: FC<ListingProps> = ({
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<p className={styles.notFound}>No Listings Found</p>
|
||||
<NoResultsFound message="No listings found." />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -82,6 +82,7 @@ export const ListingGroup: FC<ListingGroupProps> = ({
|
||||
isDisabled={disabledIds && disabledIds.includes(item.id)}
|
||||
key={item.id}
|
||||
onQuickSelect={onQuickSelect}
|
||||
data-testid="optionButton"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import clsx from "clsx";
|
||||
import { FC, HTMLAttributes, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
import { CharacterPortraitContract } from "@dndbeyond/character-rules-engine";
|
||||
import ShuffleIcon from "@dndbeyond/fontawesome-cache/svgs/solid/shuffle.svg";
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
DefaultCharacterName,
|
||||
} from "~/constants";
|
||||
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
|
||||
import { useDispatch } from "~/hooks/useDispatch";
|
||||
import { builderActions } from "~/tools/js/CharacterBuilder/actions";
|
||||
import { builderSelectors } from "~/tools/js/CharacterBuilder/selectors";
|
||||
import { PortraitManager } from "~/tools/js/Shared/containers/panes/DecoratePane";
|
||||
@@ -188,18 +189,6 @@ export const PortraitName: FC<Props> = ({
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.credit}>
|
||||
Names by
|
||||
<Button
|
||||
className={styles.creditLink}
|
||||
href="http://www.fantasynamegenerators.com/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
variant="text"
|
||||
>
|
||||
<span className={styles.creditText}>Fantasy Name Generators</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import clsx from "clsx";
|
||||
import { ChangeEvent, FC, HTMLAttributes } from "react";
|
||||
import { v4 as uuid4 } from "uuid";
|
||||
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
@@ -17,6 +18,7 @@ export const Search: FC<SearchProps> = ({
|
||||
...props
|
||||
}) => (
|
||||
<input
|
||||
id={`search-input-${uuid4()}`}
|
||||
type="search"
|
||||
className={clsx([styles.search, className])}
|
||||
value={value}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import clsx from "clsx";
|
||||
import { FC } from "react";
|
||||
|
||||
import { Select } from "~/components/Select";
|
||||
import { SelectProps } from "~/components/Select/Select";
|
||||
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
interface Props extends SelectProps {
|
||||
label: string;
|
||||
description?: string;
|
||||
}
|
||||
export const SelectField: FC<Props> = ({
|
||||
value,
|
||||
className,
|
||||
description,
|
||||
label,
|
||||
options,
|
||||
onChange,
|
||||
onChangeConfirm,
|
||||
hidePlaceholderOption,
|
||||
placeholder,
|
||||
name,
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx([styles.selectField, className])}
|
||||
data-testid="select-field-container"
|
||||
>
|
||||
<div>
|
||||
<label className={styles.label} htmlFor={name}>
|
||||
{label}
|
||||
</label>
|
||||
{description && <div className={styles.description}>{description}</div>}
|
||||
</div>
|
||||
<Select
|
||||
className={styles.field}
|
||||
options={options}
|
||||
onChange={onChange}
|
||||
onChangeConfirm={onChangeConfirm}
|
||||
value={value}
|
||||
hidePlaceholderOption={hidePlaceholderOption}
|
||||
placeholder={placeholder}
|
||||
name={name}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -30,11 +30,11 @@ export const SpeciesDisplay: FC<SpeciesDisplayProps> = ({
|
||||
portraitAvatarUrl || ruleDataUtils.getDefaultRaceImageUrl(ruleData);
|
||||
|
||||
// Navigate back to the class manage page
|
||||
const handleNavigate = (): void =>
|
||||
const handleNavigate = () =>
|
||||
navigate(
|
||||
navigationConfig
|
||||
.getRouteDefPath(RouteKey.RACE_MANAGE)
|
||||
.replace(":characterId", characterId)
|
||||
.replace(":characterId", characterId.toString())
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user