mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-16 20:49:30 +02:00
refactor: tool options components
This commit is contained in:
25
.idea/workspace.xml
generated
25
.idea/workspace.xml
generated
@@ -4,10 +4,15 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="chore: tools by category">
|
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="feat: copy and import file">
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/components/options/CheckboxWithDesc.tsx" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/components/options/RadioWithTextField.tsx" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/components/options/TextFieldWithDesc.tsx" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/ToolOptions.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/options/ToolOptions.tsx" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/components/input/ToolTextInput.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/input/ToolTextInput.tsx" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/components/input/ToolTextInput.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/input/ToolTextInput.tsx" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/pages/string/split/meta.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/string/split/meta.ts" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/pages/string/join/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/string/join/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/string/split/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/string/split/index.tsx" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -80,6 +85,7 @@
|
|||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src" />
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src" />
|
||||||
</key>
|
</key>
|
||||||
<key name="MoveFile.RECENT_KEYS">
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\components\options" />
|
||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\pages\images\png\change-colors-in-png" />
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\pages\images\png\change-colors-in-png" />
|
||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\tools" />
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\tools" />
|
||||||
</key>
|
</key>
|
||||||
@@ -129,7 +135,7 @@
|
|||||||
<workItem from="1719006951159" duration="2377000" />
|
<workItem from="1719006951159" duration="2377000" />
|
||||||
<workItem from="1719021128819" duration="3239000" />
|
<workItem from="1719021128819" duration="3239000" />
|
||||||
<workItem from="1719083989394" duration="7971000" />
|
<workItem from="1719083989394" duration="7971000" />
|
||||||
<workItem from="1719092003308" duration="9218000" />
|
<workItem from="1719092003308" duration="11298000" />
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00001" summary="feat: use vite and ts">
|
<task id="LOCAL-00001" summary="feat: use vite and ts">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
@@ -347,7 +353,15 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1719102365836</updated>
|
<updated>1719102365836</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="28" />
|
<task id="LOCAL-00028" summary="feat: copy and import file">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1719103372481</created>
|
||||||
|
<option name="number" value="00028" />
|
||||||
|
<option name="presentableId" value="LOCAL-00028" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1719103372481</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="29" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
@@ -391,7 +405,8 @@
|
|||||||
<MESSAGE value="feat: search tools" />
|
<MESSAGE value="feat: search tools" />
|
||||||
<MESSAGE value="fix: deploy message" />
|
<MESSAGE value="fix: deploy message" />
|
||||||
<MESSAGE value="chore: tools by category" />
|
<MESSAGE value="chore: tools by category" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="chore: tools by category" />
|
<MESSAGE value="feat: copy and import file" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="feat: copy and import file" />
|
||||||
</component>
|
</component>
|
||||||
<component name="XSLT-Support.FileAssociations.UIState">
|
<component name="XSLT-Support.FileAssociations.UIState">
|
||||||
<expand />
|
<expand />
|
||||||
|
@@ -23,7 +23,7 @@ export default function ToolTextInput({
|
|||||||
.writeText(value)
|
.writeText(value)
|
||||||
.then(() => showSnackBar('Text copied', 'success'))
|
.then(() => showSnackBar('Text copied', 'success'))
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
showSnackBar('Failed to copy: ', err);
|
showSnackBar('Failed to copy: ' + err, 'error');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
34
src/components/options/CheckboxWithDesc.tsx
Normal file
34
src/components/options/CheckboxWithDesc.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Box, Checkbox, FormControlLabel, Typography } from '@mui/material';
|
||||||
|
|
||||||
|
const CheckboxWithDesc = ({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
checked,
|
||||||
|
onChange
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
checked: boolean;
|
||||||
|
onChange: (value: boolean) => void;
|
||||||
|
}) => {
|
||||||
|
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
onChange(event.target.checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox defaultChecked checked={checked} onChange={handleChange} />
|
||||||
|
}
|
||||||
|
label={title}
|
||||||
|
/>
|
||||||
|
<Typography fontSize={12} mt={1}>
|
||||||
|
{description}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CheckboxWithDesc;
|
46
src/components/options/RadioWithTextField.tsx
Normal file
46
src/components/options/RadioWithTextField.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { SplitOperatorType } from '../../pages/string/split/service';
|
||||||
|
import { Box, Stack } from '@mui/material';
|
||||||
|
import { Field } from 'formik';
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
import React from 'react';
|
||||||
|
import TextFieldWithDesc from './TextFieldWithDesc';
|
||||||
|
|
||||||
|
const RadioWithTextField = <T,>({
|
||||||
|
fieldName,
|
||||||
|
type,
|
||||||
|
title,
|
||||||
|
onTypeChange,
|
||||||
|
value,
|
||||||
|
description,
|
||||||
|
onTextChange
|
||||||
|
}: {
|
||||||
|
fieldName: string;
|
||||||
|
title: string;
|
||||||
|
type: T;
|
||||||
|
onTypeChange: (val: T) => void;
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
onTextChange: (value: string) => void;
|
||||||
|
}) => {
|
||||||
|
const onChange = () => onTypeChange(type);
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Stack
|
||||||
|
direction={'row'}
|
||||||
|
sx={{ mt: 2, mb: 1, cursor: 'pointer' }}
|
||||||
|
onClick={onChange}
|
||||||
|
alignItems={'center'}
|
||||||
|
spacing={1}
|
||||||
|
>
|
||||||
|
<Field type="radio" name={fieldName} value={type} onChange={onChange} />
|
||||||
|
<Typography>{title}</Typography>
|
||||||
|
</Stack>
|
||||||
|
<TextFieldWithDesc
|
||||||
|
value={value}
|
||||||
|
onChange={onTextChange}
|
||||||
|
description={description}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default RadioWithTextField;
|
31
src/components/options/TextFieldWithDesc.tsx
Normal file
31
src/components/options/TextFieldWithDesc.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { Box, TextField } from '@mui/material';
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const TextFieldWithDesc = ({
|
||||||
|
description,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
placeholder
|
||||||
|
}: {
|
||||||
|
description: string;
|
||||||
|
value: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
placeholder?: string;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<TextField
|
||||||
|
placeholder={placeholder}
|
||||||
|
sx={{ backgroundColor: 'white' }}
|
||||||
|
value={value}
|
||||||
|
onChange={(event) => onChange(event.target.value)}
|
||||||
|
/>
|
||||||
|
<Typography fontSize={12} mt={1}>
|
||||||
|
{description}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TextFieldWithDesc;
|
@@ -12,9 +12,11 @@ import { Formik, FormikProps, useFormikContext } from 'formik';
|
|||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import ToolTextInput from '../../../components/input/ToolTextInput';
|
import ToolTextInput from '../../../components/input/ToolTextInput';
|
||||||
import ToolTextResult from '../../../components/result/ToolTextResult';
|
import ToolTextResult from '../../../components/result/ToolTextResult';
|
||||||
import ToolOptions from '../../../components/ToolOptions';
|
import ToolOptions from '../../../components/options/ToolOptions';
|
||||||
import { mergeText } from './service';
|
import { mergeText } from './service';
|
||||||
import { CustomSnackBarContext } from '../../../contexts/CustomSnackBarContext';
|
import { CustomSnackBarContext } from '../../../contexts/CustomSnackBarContext';
|
||||||
|
import TextFieldWithDesc from '../../../components/options/TextFieldWithDesc';
|
||||||
|
import CheckboxWithDesc from '../../../components/options/CheckboxWithDesc';
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
joinCharacter: '',
|
joinCharacter: '',
|
||||||
@@ -52,66 +54,8 @@ const blankTrailingOptions: {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const InputWithDesc = ({
|
|
||||||
placeholder,
|
|
||||||
description,
|
|
||||||
value,
|
|
||||||
onChange
|
|
||||||
}: {
|
|
||||||
placeholder: string;
|
|
||||||
description: string;
|
|
||||||
value: string;
|
|
||||||
onChange: (value: string) => void;
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Box width={240}>
|
|
||||||
<TextField
|
|
||||||
sx={{ backgroundColor: 'white', padding: 0 }}
|
|
||||||
size="small"
|
|
||||||
placeholder={placeholder}
|
|
||||||
value={value}
|
|
||||||
onChange={(event) => onChange(event.target.value)}
|
|
||||||
/>
|
|
||||||
<Typography fontSize={12} mt={1}>
|
|
||||||
{description}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const CheckboxWithDesc = ({
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
checked,
|
|
||||||
onChange
|
|
||||||
}: {
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
checked: boolean;
|
|
||||||
onChange: (value: boolean) => void;
|
|
||||||
}) => {
|
|
||||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
onChange(event.target.checked);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox defaultChecked checked={checked} onChange={handleChange} />
|
|
||||||
}
|
|
||||||
label={title}
|
|
||||||
/>
|
|
||||||
<Typography fontSize={12} mt={1}>
|
|
||||||
{description}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function JoinText() {
|
export default function JoinText() {
|
||||||
const [input, setInput] = useState<string>('');
|
const [input, setInput] = useState<string>('');
|
||||||
const formRef = useRef<FormikProps<typeof initialValues>>(null);
|
|
||||||
const { showSnackBar } = useContext(CustomSnackBarContext);
|
const { showSnackBar } = useContext(CustomSnackBarContext);
|
||||||
const [result, setResult] = useState<string>('');
|
const [result, setResult] = useState<string>('');
|
||||||
|
|
||||||
@@ -121,7 +65,6 @@ export default function JoinText() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
console.log('Form values:', values['joinCharacter']);
|
|
||||||
setResult(mergeText(input, deleteBlank, deleteTrailing, joinCharacter));
|
setResult(mergeText(input, deleteBlank, deleteTrailing, joinCharacter));
|
||||||
} catch (exception: unknown) {
|
} catch (exception: unknown) {
|
||||||
if (exception instanceof Error)
|
if (exception instanceof Error)
|
||||||
@@ -129,7 +72,6 @@ export default function JoinText() {
|
|||||||
}
|
}
|
||||||
}, [values, input]);
|
}, [values, input]);
|
||||||
|
|
||||||
console.log('deleteBlank', deleteBlank);
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -151,7 +93,6 @@ export default function JoinText() {
|
|||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
innerRef={formRef}
|
|
||||||
onSubmit={() => {}}
|
onSubmit={() => {}}
|
||||||
>
|
>
|
||||||
{({ setFieldValue, values }) => (
|
{({ setFieldValue, values }) => (
|
||||||
@@ -159,7 +100,7 @@ export default function JoinText() {
|
|||||||
<FormikListenerComponent input={input} />
|
<FormikListenerComponent input={input} />
|
||||||
<Box>
|
<Box>
|
||||||
<Typography fontSize={22}>Text Merged Options</Typography>
|
<Typography fontSize={22}>Text Merged Options</Typography>
|
||||||
<InputWithDesc
|
<TextFieldWithDesc
|
||||||
placeholder={mergeOptions.placeholder}
|
placeholder={mergeOptions.placeholder}
|
||||||
value={values['joinCharacter']}
|
value={values['joinCharacter']}
|
||||||
onChange={(value) =>
|
onChange={(value) =>
|
||||||
|
@@ -6,9 +6,11 @@ import ToolTextInput from '../../../components/input/ToolTextInput';
|
|||||||
import ToolTextResult from '../../../components/result/ToolTextResult';
|
import ToolTextResult from '../../../components/result/ToolTextResult';
|
||||||
import { Field, Formik, FormikProps, useFormikContext } from 'formik';
|
import { Field, Formik, FormikProps, useFormikContext } from 'formik';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import ToolOptions from '../../../components/ToolOptions';
|
import ToolOptions from '../../../components/options/ToolOptions';
|
||||||
import { compute, SplitOperatorType } from './service';
|
import { compute, SplitOperatorType } from './service';
|
||||||
import { CustomSnackBarContext } from '../../../contexts/CustomSnackBarContext';
|
import { CustomSnackBarContext } from '../../../contexts/CustomSnackBarContext';
|
||||||
|
import RadioWithTextField from '../../../components/options/RadioWithTextField';
|
||||||
|
import TextFieldWithDesc from '../../../components/options/TextFieldWithDesc';
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
splitSeparatorType: 'symbol' as SplitOperatorType,
|
splitSeparatorType: 'symbol' as SplitOperatorType,
|
||||||
@@ -74,72 +76,11 @@ const outputOptions: {
|
|||||||
accessor: 'charAfterChunk'
|
accessor: 'charAfterChunk'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const CustomRadioButton = ({
|
|
||||||
fieldName,
|
|
||||||
type,
|
|
||||||
title,
|
|
||||||
onTypeChange,
|
|
||||||
value,
|
|
||||||
description,
|
|
||||||
onTextChange
|
|
||||||
}: {
|
|
||||||
fieldName: string;
|
|
||||||
title: string;
|
|
||||||
type: SplitOperatorType;
|
|
||||||
onTypeChange: (val: string) => void;
|
|
||||||
value: string;
|
|
||||||
description: string;
|
|
||||||
onTextChange: (value: string) => void;
|
|
||||||
}) => {
|
|
||||||
const onChange = () => onTypeChange(type);
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<Stack
|
|
||||||
direction={'row'}
|
|
||||||
sx={{ mt: 2, mb: 1, cursor: 'pointer' }}
|
|
||||||
onClick={onChange}
|
|
||||||
alignItems={'center'}
|
|
||||||
spacing={1}
|
|
||||||
>
|
|
||||||
<Field type="radio" name={fieldName} value={type} onChange={onChange} />
|
|
||||||
<Typography>{title}</Typography>
|
|
||||||
</Stack>
|
|
||||||
<InputWithDesc
|
|
||||||
value={value}
|
|
||||||
onChange={onTextChange}
|
|
||||||
description={description}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const InputWithDesc = ({
|
|
||||||
description,
|
|
||||||
value,
|
|
||||||
onChange
|
|
||||||
}: {
|
|
||||||
description: string;
|
|
||||||
value: string;
|
|
||||||
onChange: (value: string) => void;
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<TextField
|
|
||||||
sx={{ backgroundColor: 'white' }}
|
|
||||||
value={value}
|
|
||||||
onChange={(event) => onChange(event.target.value)}
|
|
||||||
/>
|
|
||||||
<Typography fontSize={12} mt={1}>
|
|
||||||
{description}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function SplitText() {
|
export default function SplitText() {
|
||||||
const [input, setInput] = useState<string>('');
|
const [input, setInput] = useState<string>('');
|
||||||
const [result, setResult] = useState<string>('');
|
const [result, setResult] = useState<string>('');
|
||||||
const formRef = useRef<FormikProps<typeof initialValues>>(null);
|
// const formRef = useRef<FormikProps<typeof initialValues>>(null);
|
||||||
const { showSnackBar } = useContext(CustomSnackBarContext);
|
const { showSnackBar } = useContext(CustomSnackBarContext);
|
||||||
|
|
||||||
const FormikListenerComponent = () => {
|
const FormikListenerComponent = () => {
|
||||||
@@ -197,7 +138,6 @@ export default function SplitText() {
|
|||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
innerRef={formRef}
|
|
||||||
onSubmit={() => {}}
|
onSubmit={() => {}}
|
||||||
>
|
>
|
||||||
{({ setFieldValue, values }) => (
|
{({ setFieldValue, values }) => (
|
||||||
@@ -206,7 +146,7 @@ export default function SplitText() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Typography fontSize={22}>Split separator options</Typography>
|
<Typography fontSize={22}>Split separator options</Typography>
|
||||||
{splitOperators.map(({ title, description, type }) => (
|
{splitOperators.map(({ title, description, type }) => (
|
||||||
<CustomRadioButton
|
<RadioWithTextField
|
||||||
key={type}
|
key={type}
|
||||||
type={type}
|
type={type}
|
||||||
title={title}
|
title={title}
|
||||||
@@ -223,7 +163,7 @@ export default function SplitText() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Typography fontSize={22}>Output separator options</Typography>
|
<Typography fontSize={22}>Output separator options</Typography>
|
||||||
{outputOptions.map((option) => (
|
{outputOptions.map((option) => (
|
||||||
<InputWithDesc
|
<TextFieldWithDesc
|
||||||
key={option.accessor}
|
key={option.accessor}
|
||||||
value={values[option.accessor]}
|
value={values[option.accessor]}
|
||||||
onChange={(value) => setFieldValue(option.accessor, value)}
|
onChange={(value) => setFieldValue(option.accessor, value)}
|
||||||
|
Reference in New Issue
Block a user