refactor(forms): port game form to Chakra v3 with v4-style selects
- New FixedSelect wrapper over chakra-react-select v6 restoring the v4 look everywhere: single gray.500 control border, flush addon chevron zone with rounded inner corners, hidden indicator separator, v4 option padding/type scale, gray subtle pills, brighter unselected hover - GameForm: FormControl/InputGroup -> Field/Flex, Button colorScheme/isLoading -> colorPalette/loading, Stack spacing -> gap, Container container.md -> 768px, Steam Scrape row rebuilt as nowrap Flex, select wrappers de-bordered (control owns the border) - formFields: Field/Checkbox/Switch shims in, required asterisk dropped to match legacy labels, Select/Creatable wrappers de-bordered, TS-typed select callbacks
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
import React from 'react'
|
||||
import { Select as V6Select, CreatableSelect as V6Creatable } from 'chakra-react-select'
|
||||
import { useColorModeValue } from './ui/color-mode'
|
||||
|
||||
// Shared styling that restores how these selects looked with Chakra v2 /
|
||||
// chakra-react-select v4 (verified against the v4.9.1 source + old screenshots):
|
||||
//
|
||||
// - v4's control border resolved to the outer wrapper's gray.500 edge via
|
||||
// `borderColor: inherit` (outer Box sets gray.500). v6 paints its own light
|
||||
// edge (gray.100 in dark mode) on top, producing a double white+gray border.
|
||||
// Fix universally: single gray.500 border on the control itself, transparent
|
||||
// bg so wrapper bg shows through, no shadow, no padding so the chevron zone
|
||||
// sits flush (v4 had padding:0 + overflow:hidden).
|
||||
// - v4's chevron sat on a grey input-addon zone (gray.100 / whiteAlpha.300),
|
||||
// flush right with rounded right corners matching the control.
|
||||
// - v4's indicator separator was a subtle Divider, effectively invisible in
|
||||
// the old screenshots; v6 hides it by default, so keep it hidden instead of
|
||||
// rendering a prominent white line.
|
||||
// - v4 multi-value pills defaulted to gray subtle tags (dark gray pill in dark
|
||||
// mode), not bright blue. Defaults restored here; ActiveFilters tags pass
|
||||
// blue explicitly and are unaffected.
|
||||
function V6IndicatorSeparator() {
|
||||
return null
|
||||
}
|
||||
|
||||
function useSharedChakraStyles(extra: any) {
|
||||
const zoneBg = useColorModeValue('gray.100', 'whiteAlpha.300')
|
||||
const pillBg = useColorModeValue('gray.100', 'whiteAlpha.300')
|
||||
const pillColor = useColorModeValue('gray.800', 'gray.100')
|
||||
const optionHoverBg = useColorModeValue('gray.200', 'whiteAlpha.300')
|
||||
return {
|
||||
control: (provided: any) => ({
|
||||
...provided,
|
||||
borderColor: 'gray.500',
|
||||
borderWidth: '1px',
|
||||
borderStyle: 'solid',
|
||||
background: 'transparent',
|
||||
boxShadow: 'none',
|
||||
padding: 0,
|
||||
overflow: 'hidden',
|
||||
}),
|
||||
valueContainer: (provided: any, state: any) => ({
|
||||
...provided,
|
||||
paddingTop: '2px',
|
||||
paddingBottom: '2px',
|
||||
paddingLeft: state?.selectProps?.size === 'sm' ? '12px' : '16px',
|
||||
paddingRight: '8px',
|
||||
}),
|
||||
indicatorsContainer: (provided: any) => ({
|
||||
...provided,
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
}),
|
||||
dropdownIndicator: (provided: any) => ({
|
||||
...provided,
|
||||
background: zoneBg,
|
||||
alignSelf: 'stretch',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
margin: 0,
|
||||
paddingLeft: '8px',
|
||||
paddingRight: '8px',
|
||||
borderWidth: 0,
|
||||
borderRadius: 0,
|
||||
borderTopRightRadius: 'md',
|
||||
borderBottomRightRadius: 'md',
|
||||
}),
|
||||
option: (provided: any, state: any) => {
|
||||
const size = state?.selectProps?.size === 'sm' ? 'sm' : state?.selectProps?.size === 'lg' ? 'lg' : 'md'
|
||||
const v4 = {
|
||||
sm: { fontSize: '14px', paddingLeft: '12.8px', paddingRight: '12.8px', paddingTop: '4.8px', paddingBottom: '4.8px' },
|
||||
md: { fontSize: '16px', paddingLeft: '12.8px', paddingRight: '12.8px', paddingTop: '6.4px', paddingBottom: '6.4px' },
|
||||
lg: { fontSize: '18px', paddingLeft: '16px', paddingRight: '16px', paddingTop: '8px', paddingBottom: '8px' },
|
||||
}[size]
|
||||
return {
|
||||
...provided,
|
||||
fontSize: v4.fontSize,
|
||||
paddingLeft: v4.paddingLeft,
|
||||
paddingRight: v4.paddingRight,
|
||||
paddingTop: v4.paddingTop,
|
||||
paddingBottom: v4.paddingBottom,
|
||||
// v3 hover uses bg.emphasized/60 — near-invisible on dark surfaces.
|
||||
// Brighten unselected hover in both modes; keep selected blue.
|
||||
_highlighted: state?.isSelected
|
||||
? provided._highlighted
|
||||
: { bg: optionHoverBg },
|
||||
}
|
||||
},
|
||||
multiValue: (provided: any) => ({
|
||||
...provided,
|
||||
background: pillBg,
|
||||
color: pillColor,
|
||||
borderRadius: 'md',
|
||||
margin: '2px',
|
||||
}),
|
||||
multiValueLabel: (provided: any) => ({
|
||||
...provided,
|
||||
color: pillColor,
|
||||
}),
|
||||
multiValueRemove: (provided: any) => ({
|
||||
...provided,
|
||||
color: pillColor,
|
||||
}),
|
||||
...extra,
|
||||
}
|
||||
}
|
||||
|
||||
function mergeComponents(extra: any) {
|
||||
return { IndicatorSeparator: V6IndicatorSeparator, ...extra }
|
||||
}
|
||||
|
||||
export function Select(props: any) {
|
||||
const { chakraStyles, components, tagColorPalette = 'gray', tagVariant = 'subtle', ...rest } = props
|
||||
const mergedStyles = useSharedChakraStyles(chakraStyles)
|
||||
return (
|
||||
<V6Select
|
||||
{...rest}
|
||||
tagColorPalette={tagColorPalette}
|
||||
tagVariant={tagVariant}
|
||||
components={mergeComponents(components)}
|
||||
chakraStyles={mergedStyles}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function CreatableSelect(props: any) {
|
||||
const { chakraStyles, components, tagColorPalette = 'gray', tagVariant = 'subtle', ...rest } = props
|
||||
const mergedStyles = useSharedChakraStyles(chakraStyles)
|
||||
return (
|
||||
<V6Creatable
|
||||
{...rest}
|
||||
tagColorPalette={tagColorPalette}
|
||||
tagVariant={tagVariant}
|
||||
components={mergeComponents(components)}
|
||||
chakraStyles={mergedStyles}
|
||||
/>
|
||||
)
|
||||
}
|
||||
+43
-45
@@ -21,17 +21,16 @@ import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Flex,
|
||||
Heading,
|
||||
InputGroup,
|
||||
Spacer,
|
||||
Stack,
|
||||
Switch,
|
||||
Text,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react'
|
||||
import {CreatableSelect,} from 'chakra-react-select'
|
||||
import {Field} from './ui/field'
|
||||
import {Switch} from './ui/switch'
|
||||
import {useColorModeValue} from './ui/color-mode'
|
||||
import {CreatableSelect} from './FixedSelect'
|
||||
import {adminMode} from '../stateManagement/userState'
|
||||
import {encode} from 'js-base64'
|
||||
import SingleFieldInput from './formFields/SingleFieldInput'
|
||||
@@ -314,63 +313,64 @@ const GameForm = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container maxW="container.md" mt="10">
|
||||
<Container maxW="768px" mt="10">
|
||||
{id ? <Heading as="h1" size="xl">Editing {game.title}</Heading> :
|
||||
<Heading as="h1" size="xl">Add a Game to the Database</Heading>}
|
||||
<form onSubmit={handleSubmit} style={{marginTop: '2rem'}}>
|
||||
<Stack spacing={[1, 5]} direction={{base: 'column', sm: 'row'}} justify={'flex-end'}>
|
||||
<Stack gap={[1, 5]} direction={{base: 'column', sm: 'row'}} justify={'flex-end'}>
|
||||
<Button
|
||||
isLoading={submitLoading}
|
||||
colorScheme="blue"
|
||||
loading={submitLoading}
|
||||
colorPalette="blue"
|
||||
type="submit"
|
||||
data-name={"save"}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
isLoading={moveOn}
|
||||
colorScheme="green"
|
||||
loading={moveOn}
|
||||
colorPalette="green"
|
||||
type="submit"
|
||||
data-name={"save-and-view"}
|
||||
>
|
||||
Save and View
|
||||
</Button>
|
||||
</Stack>
|
||||
<InputGroup>
|
||||
<Flex gap={3} alignItems="center">
|
||||
{!id || admin ? (
|
||||
<Box flex="1">
|
||||
<SingleFieldNumericInput label={'Steam ID'} textField={'steamId'} field={game.steamId} bg={bg}
|
||||
handleInputChange={handleInputChange} required={game.scrape}/>
|
||||
</Box>
|
||||
) : ''}
|
||||
{!id && (
|
||||
<FormControl display="flex" ml={'3'} alignItems="center">
|
||||
<FormLabel htmlFor="scrape" mb="0">Steam Scrape</FormLabel>
|
||||
<Flex alignItems="center" ml={'3'} flexShrink={0} gap={2}>
|
||||
<Text whiteSpace="nowrap">Steam Scrape</Text>
|
||||
<Switch
|
||||
isChecked={game.scrape}
|
||||
onChange={() => {
|
||||
colorPalette="blue"
|
||||
checked={game.scrape}
|
||||
onCheckedChange={() => {
|
||||
handleToggle('scrape')
|
||||
}}
|
||||
name="scrape"
|
||||
id="scrape"
|
||||
/>
|
||||
</FormControl>
|
||||
</Flex>
|
||||
)}
|
||||
</InputGroup>
|
||||
</Flex>
|
||||
{(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? (
|
||||
<SingleFieldInput label={'Title'} textField={'title'} field={game.title} bg={bg}
|
||||
handleInputChange={handleInputChange} required={false}/>
|
||||
) : ''}
|
||||
<>
|
||||
<FormControl mb="3">
|
||||
<FormLabel>Series</FormLabel>
|
||||
<Field mb="3" label="Series">
|
||||
<Box
|
||||
bg={bg}
|
||||
border="1px"
|
||||
borderColor="gray.500"
|
||||
rounded="md">
|
||||
rounded="md"
|
||||
w="full">
|
||||
<CreatableSelect
|
||||
name="series"
|
||||
isClearable
|
||||
onChange={(values) => {
|
||||
onChange={(values: any) => {
|
||||
if (values === null) values = {value: '', label: ''}
|
||||
if (values) {
|
||||
handleInputChange('series', values.value)
|
||||
@@ -380,20 +380,18 @@ const GameForm = () => {
|
||||
value={{value: game.series, label: game.series}}
|
||||
/>
|
||||
</Box>
|
||||
</FormControl>
|
||||
</Field>
|
||||
</>
|
||||
{(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? (
|
||||
<>
|
||||
<SingleFieldInput label={'Front Image'} textField={'frontImage'} field={game.frontImage}
|
||||
bg={bg}
|
||||
handleInputChange={handleInputChange} required={false}/>
|
||||
<FormControl mb="3">
|
||||
<FormLabel>Screenshots</FormLabel>
|
||||
<Field mb="3" label="Screenshots">
|
||||
<Box
|
||||
bg={bg}
|
||||
border="1px"
|
||||
borderColor="gray.500"
|
||||
rounded="md">
|
||||
rounded="md"
|
||||
w="full">
|
||||
<CreatableSelect
|
||||
name="screenshots"
|
||||
isClearable
|
||||
@@ -433,7 +431,7 @@ const GameForm = () => {
|
||||
value={screenshots[0]?.value === '' ? [] : screenshots}
|
||||
/>
|
||||
</Box>
|
||||
</FormControl>
|
||||
</Field>
|
||||
</>
|
||||
) : ''}
|
||||
{(gameId === '' && !game.scrape) || (gameId.length >= 1) ?
|
||||
@@ -453,14 +451,14 @@ const GameForm = () => {
|
||||
</>
|
||||
{(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? (
|
||||
<Box mt="5" mb="5">
|
||||
<FormLabel>Operating Systems</FormLabel>
|
||||
<Text fontWeight="medium" mb="2">Operating Systems</Text>
|
||||
<Box
|
||||
bg={bg}
|
||||
border="1px"
|
||||
borderWidth="1px" borderStyle="solid"
|
||||
borderColor="gray.500"
|
||||
rounded="md"
|
||||
p="2">
|
||||
<Stack spacing={[1, 5]} direction={['column', 'row']}>
|
||||
<Stack gap={[1, 5]} direction={['column', 'row']}>
|
||||
<CheckboxInput label={'Windows'} textField={'windows'} checked={game.os.windows}
|
||||
defaultIsChecked={true} handleOSChange={handleOSChange}/>
|
||||
<CheckboxInput label={'Mac OSX'} textField={'mac'} checked={game.os.mac}
|
||||
@@ -518,9 +516,9 @@ const GameForm = () => {
|
||||
</>
|
||||
{(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? (
|
||||
<>
|
||||
<Text align="center" fontSize="xl" mt="10">System Requirements</Text>
|
||||
<Text textAlign="center" fontSize="xl" mt="10">System Requirements</Text>
|
||||
<Box>
|
||||
<Text fontSize="lg" align="center">Windows</Text>
|
||||
<Text fontSize="lg" textAlign="center">Windows</Text>
|
||||
<SystemRequirementsTextareaInput label={'Windows Minimum'}
|
||||
textField={'systemRequirements.windows.minimum'}
|
||||
field={game.systemRequirements.windows.minimum} bg={bg}
|
||||
@@ -532,7 +530,7 @@ const GameForm = () => {
|
||||
bg={bg}
|
||||
handleSystemRequirements={handleSystemRequirements}
|
||||
rows={3}/>
|
||||
<Text fontSize="lg" align="center">Mac OSX</Text>
|
||||
<Text fontSize="lg" textAlign="center">Mac OSX</Text>
|
||||
<SystemRequirementsTextareaInput label={'Mac OSX Minimum'}
|
||||
textField={'systemRequirements.mac.minimum'}
|
||||
field={game.systemRequirements.mac.minimum} bg={bg}
|
||||
@@ -543,7 +541,7 @@ const GameForm = () => {
|
||||
field={game.systemRequirements.mac.recommended} bg={bg}
|
||||
handleSystemRequirements={handleSystemRequirements}
|
||||
rows={3}/>
|
||||
<Text fontSize="lg" align="center">Linux</Text>
|
||||
<Text fontSize="lg" textAlign="center">Linux</Text>
|
||||
<SystemRequirementsTextareaInput label={'Linux Minimum'}
|
||||
textField={'systemRequirements.linux.minimum'}
|
||||
field={game.systemRequirements.linux.minimum} bg={bg}
|
||||
@@ -558,18 +556,18 @@ const GameForm = () => {
|
||||
</Box>
|
||||
</>
|
||||
) : ''}
|
||||
<Stack spacing={[1, 5]} direction={{base: 'column', sm: 'row'}} align={{base: 'start'}}>
|
||||
<Stack gap={[1, 5]} direction={{base: 'column', sm: 'row'}} align={{base: 'start'}}>
|
||||
<Button
|
||||
isLoading={submitLoading}
|
||||
colorScheme="blue"
|
||||
loading={submitLoading}
|
||||
colorPalette="blue"
|
||||
type="submit"
|
||||
data-name={"save"}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
isLoading={moveOn}
|
||||
colorScheme="green"
|
||||
loading={moveOn}
|
||||
colorPalette="green"
|
||||
type="submit"
|
||||
data-name={"save-and-view"}
|
||||
>
|
||||
@@ -579,7 +577,7 @@ const GameForm = () => {
|
||||
<>
|
||||
<Spacer/>
|
||||
<Button
|
||||
colorScheme="red"
|
||||
colorPalette="red"
|
||||
onMouseDown={() => {
|
||||
openState.set(true)
|
||||
}}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react'
|
||||
import { Checkbox, Text } from '@chakra-ui/react'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import {Checkbox} from '../ui/checkbox'
|
||||
|
||||
interface Props {
|
||||
label: string
|
||||
@@ -12,15 +13,16 @@ interface Props {
|
||||
const CheckboxInput = ({ label, textField, checked, defaultIsChecked, handleOSChange }: Props) => {
|
||||
return (
|
||||
<Checkbox
|
||||
colorPalette="blue"
|
||||
defaultChecked={defaultIsChecked}
|
||||
isChecked={checked}
|
||||
onChange={() => {
|
||||
checked={checked}
|
||||
onCheckedChange={() => {
|
||||
handleOSChange(textField)
|
||||
}}
|
||||
name={textField}
|
||||
spacing="1rem"
|
||||
gap="1rem"
|
||||
><Text mt="1">{label}</Text></Checkbox>
|
||||
)
|
||||
}
|
||||
|
||||
export default CheckboxInput
|
||||
export default CheckboxInput
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react'
|
||||
import { Box, FormControl, FormLabel } from '@chakra-ui/react'
|
||||
import { CreatableSelect } from 'chakra-react-select'
|
||||
import { Box } from '@chakra-ui/react'
|
||||
import { Field } from '../ui/field'
|
||||
import { CreatableSelect } from '../FixedSelect'
|
||||
|
||||
interface Props {
|
||||
label: string
|
||||
@@ -13,13 +14,12 @@ interface Props {
|
||||
|
||||
const CreatableSelectInput = ({ label, textField, value, bg, handleInputChange, options}: Props) => {
|
||||
return (
|
||||
<FormControl mb="3">
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<Field mb="3" label={label}>
|
||||
<Box
|
||||
bg={bg}
|
||||
border="1px"
|
||||
borderColor="gray.500"
|
||||
rounded="md">
|
||||
rounded="md"
|
||||
w="full"
|
||||
>
|
||||
<CreatableSelect
|
||||
name={textField}
|
||||
isClearable
|
||||
@@ -39,8 +39,8 @@ const CreatableSelectInput = ({ label, textField, value, bg, handleInputChange,
|
||||
options={options}
|
||||
/>
|
||||
</Box>
|
||||
</FormControl>
|
||||
</Field>
|
||||
)
|
||||
}
|
||||
|
||||
export default CreatableSelectInput
|
||||
export default CreatableSelectInput
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react'
|
||||
import {Box, FormControl, FormLabel} from '@chakra-ui/react'
|
||||
import {Select} from 'chakra-react-select'
|
||||
import {Box} from '@chakra-ui/react'
|
||||
import { Field } from '../ui/field'
|
||||
import {Select} from '../FixedSelect'
|
||||
|
||||
interface Props {
|
||||
label: string
|
||||
@@ -14,18 +15,15 @@ interface Props {
|
||||
|
||||
const SelectInput = ({label, textField, field, bg, handleAccessedBy, options, width = ''}: Props) => {
|
||||
return (
|
||||
<FormControl mb="3">
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<Field mb="3" label={label}>
|
||||
<Box
|
||||
bg={bg}
|
||||
w={width}
|
||||
border="1px"
|
||||
borderColor="gray.500"
|
||||
w={width || 'full'}
|
||||
rounded="md">
|
||||
<Select
|
||||
id={textField}
|
||||
name={textField}
|
||||
onChange={(values) => {
|
||||
onChange={(values: any) => {
|
||||
if (values) handleAccessedBy(textField, values.value)
|
||||
}}
|
||||
options={options}
|
||||
@@ -35,8 +33,8 @@ const SelectInput = ({label, textField, field, bg, handleAccessedBy, options, wi
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</FormControl>
|
||||
</Field>
|
||||
)
|
||||
}
|
||||
|
||||
export default SelectInput
|
||||
export default SelectInput
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react'
|
||||
import { FormControl, FormLabel, Input } from '@chakra-ui/react'
|
||||
import { Input } from '@chakra-ui/react'
|
||||
import { Field } from '../ui/field'
|
||||
import { Data } from '../../models/game'
|
||||
|
||||
interface Props {
|
||||
@@ -14,15 +15,14 @@ interface Props {
|
||||
const SingleFieldInput = ({ label, textField, field, bg, handleInputChange, required }: Props) => {
|
||||
|
||||
return (
|
||||
<FormControl mb="3">
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<Field mb="3" label={label}>
|
||||
<Input
|
||||
id={textField}
|
||||
name={textField}
|
||||
bg={bg}
|
||||
type="text"
|
||||
border="1px"
|
||||
borderColor="gray.500"
|
||||
borderWidth="1px" borderStyle="solid"
|
||||
borderColor={{ base: "gray.500", _invalid: "red.500" }}
|
||||
rounded="md"
|
||||
value={field}
|
||||
required={required}
|
||||
@@ -30,8 +30,8 @@ const SingleFieldInput = ({ label, textField, field, bg, handleInputChange, requ
|
||||
handleInputChange(textField, e.target.value)
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
</Field>
|
||||
)
|
||||
}
|
||||
|
||||
export default SingleFieldInput
|
||||
export default SingleFieldInput
|
||||
|
||||
@@ -1,39 +1,63 @@
|
||||
import React from 'react'
|
||||
import { FormControl, FormLabel, Input } from '@chakra-ui/react'
|
||||
import { Data } from '../../models/game'
|
||||
import React from "react";
|
||||
import { Input } from "@chakra-ui/react";
|
||||
import { Field } from "../ui/field";
|
||||
import { Data } from "../../models/game";
|
||||
|
||||
interface Props {
|
||||
label: string
|
||||
textField: string
|
||||
field: string
|
||||
bg: string
|
||||
handleInputChange: <G extends keyof Data>(name: string, value: Data[G]) => void
|
||||
required: boolean
|
||||
label: string;
|
||||
textField: string;
|
||||
field: string;
|
||||
bg: string;
|
||||
handleInputChange: <G extends keyof Data>(
|
||||
name: string,
|
||||
value: Data[G],
|
||||
) => void;
|
||||
required: boolean;
|
||||
}
|
||||
|
||||
const SingleFieldNumericInput = ({ label, textField, field, bg, handleInputChange, required }: Props) => {
|
||||
const SingleFieldNumericInput = ({
|
||||
label,
|
||||
textField,
|
||||
field,
|
||||
bg,
|
||||
handleInputChange,
|
||||
required,
|
||||
}: Props) => {
|
||||
const isValidSteamValue = (v: string) => {
|
||||
const s = v.trim();
|
||||
if (!s) return false;
|
||||
if (/^\d+$/.test(s)) return true;
|
||||
return s.includes("store.steampowered.com");
|
||||
};
|
||||
|
||||
const showError = field.trim() !== "" && !isValidSteamValue(field);
|
||||
|
||||
return (
|
||||
<FormControl mb="3">
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<Field
|
||||
mb="3"
|
||||
label={label}
|
||||
errorText="Enter a Steam App Id or a Steam App URL"
|
||||
>
|
||||
<Input
|
||||
id={textField}
|
||||
name={textField}
|
||||
bg={bg}
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
pattern="[0-9]*"
|
||||
border="1px"
|
||||
borderColor="gray.500"
|
||||
inputMode="text"
|
||||
aria-invalid={showError}
|
||||
placeholder="Steam Id or Steam URL"
|
||||
borderWidth="1px"
|
||||
borderStyle="solid"
|
||||
borderColor={{ base: "gray.500", _invalid: "red.500" }}
|
||||
rounded="md"
|
||||
value={field}
|
||||
required={required}
|
||||
onChange={(e) => {
|
||||
handleInputChange(textField, e.target.value)
|
||||
handleInputChange(textField, e.target.value);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
)
|
||||
}
|
||||
</Field>
|
||||
);
|
||||
};
|
||||
|
||||
export default SingleFieldNumericInput
|
||||
export default SingleFieldNumericInput;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, {useMemo, useRef} from 'react'
|
||||
import {FormControl, FormLabel} from '@chakra-ui/react'
|
||||
import {Field} from '../ui/field'
|
||||
import JoditEditor from "jodit-react";
|
||||
|
||||
interface Props {
|
||||
@@ -24,18 +24,17 @@ const SystemRequirementsTextareaInput = ({label, textField, field, handleSystemR
|
||||
);
|
||||
|
||||
return (
|
||||
<FormControl mb="3">
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<Field mb="3" label={label}>
|
||||
<JoditEditor
|
||||
ref={editor}
|
||||
value={field}
|
||||
config={config}
|
||||
onChange={(value) => {
|
||||
onChange={(value: string) => {
|
||||
handleSystemRequirements(arrText[1], arrText[2], value)
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
</Field>
|
||||
)
|
||||
}
|
||||
|
||||
export default SystemRequirementsTextareaInput
|
||||
export default SystemRequirementsTextareaInput
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, {useMemo, useRef} from 'react'
|
||||
import { FormControl, FormLabel } from '@chakra-ui/react'
|
||||
import { Field } from '../ui/field'
|
||||
import { Data } from '../../models/game'
|
||||
import JoditEditor from "jodit-react";
|
||||
|
||||
@@ -25,18 +25,17 @@ const TextareaInput = ({ label, textField, field, handleInputChange }: Props) =>
|
||||
|
||||
|
||||
return (
|
||||
<FormControl mb="3">
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<Field mb="3" label={label}>
|
||||
<JoditEditor
|
||||
ref={editor}
|
||||
value={field}
|
||||
config={config}
|
||||
onChange={(value) => {
|
||||
onChange={(value: string) => {
|
||||
handleInputChange(textField, value)
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
</Field>
|
||||
)
|
||||
}
|
||||
|
||||
export default TextareaInput
|
||||
export default TextareaInput
|
||||
|
||||
Reference in New Issue
Block a user