mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-30 03:19:31 +02:00
Merge pull request #41 from TheLukasHenry/createUIsForTools
Create UI for already created tools (#35)
This commit is contained in:
2
.idea/workspace.xml
generated
2
.idea/workspace.xml
generated
@@ -820,4 +820,4 @@
|
||||
<expand />
|
||||
<select />
|
||||
</component>
|
||||
</project>
|
||||
</project>
|
||||
|
@@ -25,7 +25,7 @@ interface ToolContentProps<T, I> extends ToolComponentProps {
|
||||
// Tool info (optional)
|
||||
toolInfo?: {
|
||||
title: string;
|
||||
description: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
// Input value to pass to the compute function
|
||||
@@ -66,7 +66,7 @@ export default function ToolContent<T extends FormikValues, I>({
|
||||
validationSchema={validationSchema}
|
||||
/>
|
||||
|
||||
{toolInfo && (
|
||||
{toolInfo && toolInfo.title && toolInfo.description && (
|
||||
<ToolInfo title={toolInfo.title} description={toolInfo.description} />
|
||||
)}
|
||||
|
||||
|
@@ -60,33 +60,36 @@ export default function ExampleCard<T>({
|
||||
{description}
|
||||
</Typography>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
zIndex: '2',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
bgcolor: 'transparent',
|
||||
padding: '5px 10px',
|
||||
borderRadius: '5px',
|
||||
boxShadow: 'inset 2px 2px 5px #b8b9be, inset -3px -3px 7px #fff;'
|
||||
}}
|
||||
>
|
||||
<TextField
|
||||
value={sampleText}
|
||||
disabled
|
||||
fullWidth
|
||||
multiline
|
||||
{sampleText && (
|
||||
<Box
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
zIndex: '-1',
|
||||
'& fieldset': {
|
||||
border: 'none'
|
||||
}
|
||||
}
|
||||
display: 'flex',
|
||||
zIndex: '2',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
bgcolor: 'transparent',
|
||||
padding: '5px 10px',
|
||||
borderRadius: '5px',
|
||||
boxShadow:
|
||||
'inset 2px 2px 5px #b8b9be, inset -3px -3px 7px #fff;'
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
>
|
||||
<TextField
|
||||
value={sampleText}
|
||||
disabled
|
||||
fullWidth
|
||||
multiline
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
zIndex: '-1',
|
||||
'& fieldset': {
|
||||
border: 'none'
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<ArrowDownwardIcon />
|
||||
<Box
|
||||
|
@@ -36,9 +36,11 @@ interface FormikHelperProps<T> {
|
||||
compute: (optionsValues: T, input: any) => void;
|
||||
input: any;
|
||||
children?: ReactNode;
|
||||
getGroups: (
|
||||
formikProps: FormikProps<T> & { updateField: UpdateField<T> }
|
||||
) => ToolOptionGroup[];
|
||||
getGroups:
|
||||
| null
|
||||
| ((
|
||||
formikProps: FormikProps<T> & { updateField: UpdateField<T> }
|
||||
) => ToolOptionGroup[]);
|
||||
formikProps: FormikProps<T>;
|
||||
}
|
||||
|
||||
@@ -63,7 +65,9 @@ const ToolBody = <T,>({
|
||||
input={input}
|
||||
initialValues={values}
|
||||
/>
|
||||
<ToolOptionGroups groups={getGroups({ ...formikProps, updateField })} />
|
||||
<ToolOptionGroups
|
||||
groups={getGroups?.({ ...formikProps, updateField }) ?? []}
|
||||
/>
|
||||
{children}
|
||||
</Stack>
|
||||
);
|
||||
@@ -90,41 +94,41 @@ export default function ToolOptions<T extends FormikValues>({
|
||||
formRef?: RefObject<FormikProps<T>>;
|
||||
}) {
|
||||
const theme = useTheme();
|
||||
if (getGroups)
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
mb: 2,
|
||||
borderRadius: 2,
|
||||
padding: 2,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
boxShadow: '2'
|
||||
}}
|
||||
mt={2}
|
||||
>
|
||||
<Stack direction={'row'} spacing={1} alignItems={'center'}>
|
||||
<SettingsIcon />
|
||||
<Typography fontSize={22}>Tool options</Typography>
|
||||
</Stack>
|
||||
<Box mt={2}>
|
||||
<Formik
|
||||
innerRef={formRef}
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={() => {}}
|
||||
>
|
||||
{(formikProps) => (
|
||||
<ToolBody
|
||||
compute={compute}
|
||||
input={input}
|
||||
getGroups={getGroups}
|
||||
formikProps={formikProps}
|
||||
>
|
||||
{children}
|
||||
</ToolBody>
|
||||
)}
|
||||
</Formik>
|
||||
</Box>
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
mb: 2,
|
||||
borderRadius: 2,
|
||||
padding: 2,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
boxShadow: '2',
|
||||
display: getGroups ? 'block' : 'none'
|
||||
}}
|
||||
mt={2}
|
||||
>
|
||||
<Stack direction={'row'} spacing={1} alignItems={'center'}>
|
||||
<SettingsIcon />
|
||||
<Typography fontSize={22}>Tool options</Typography>
|
||||
</Stack>
|
||||
<Box mt={2}>
|
||||
<Formik
|
||||
innerRef={formRef}
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={() => {}}
|
||||
>
|
||||
{(formikProps) => (
|
||||
<ToolBody
|
||||
compute={compute}
|
||||
input={input}
|
||||
getGroups={getGroups}
|
||||
formikProps={formikProps}
|
||||
>
|
||||
{children}
|
||||
</ToolBody>
|
||||
)}
|
||||
</Formik>
|
||||
</Box>
|
||||
);
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
|
||||
import { generateArithmeticSequence } from './service';
|
||||
import * as Yup from 'yup';
|
||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
|
||||
type InitialValuesType = {
|
||||
firstTerm: string;
|
||||
@@ -68,11 +69,12 @@ const exampleCards: CardExampleType<InitialValuesType>[] = [
|
||||
}
|
||||
];
|
||||
|
||||
export default function ArithmeticSequence() {
|
||||
export default function ArithmeticSequence({ title }: ToolComponentProps) {
|
||||
const [result, setResult] = useState<string>('');
|
||||
|
||||
return (
|
||||
<ToolContent
|
||||
title={title}
|
||||
inputComponent={null}
|
||||
resultComponent={
|
||||
<ToolTextResult title="Generated Sequence" value={result} />
|
||||
|
@@ -1,11 +1,113 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React from 'react';
|
||||
import * as Yup from 'yup';
|
||||
import React, { useState } from 'react';
|
||||
import ToolTextInput from '@components/input/ToolTextInput';
|
||||
import ToolTextResult from '@components/result/ToolTextResult';
|
||||
import { GetGroupsType } from '@components/options/ToolOptions';
|
||||
import { createPalindromeList } from './service';
|
||||
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
|
||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
|
||||
const initialValues = {};
|
||||
const validationSchema = Yup.object({
|
||||
// splitSeparator: Yup.string().required('The separator is required')
|
||||
});
|
||||
export default function CreatePalindrome() {
|
||||
return <Box>Lorem ipsum</Box>;
|
||||
const initialValues = {
|
||||
lastChar: true,
|
||||
multiLine: false
|
||||
};
|
||||
|
||||
const exampleCards: CardExampleType<typeof initialValues>[] = [
|
||||
{
|
||||
title: 'Create Simple Palindrome',
|
||||
description:
|
||||
'Creates a palindrome by repeating the text in reverse order, including the last character.',
|
||||
sampleText: 'level',
|
||||
sampleResult: 'levellevel',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
lastChar: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Create Palindrome Without Last Character Duplication',
|
||||
description:
|
||||
'Creates a palindrome without repeating the last character in the reverse part.',
|
||||
sampleText: 'radar',
|
||||
sampleResult: 'radarada',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
lastChar: false
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Multi-line Palindrome Creation',
|
||||
description: 'Creates palindromes for each line independently.',
|
||||
sampleText: 'mom\ndad\nwow',
|
||||
sampleResult: 'mommom\ndaddad\nwowwow',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
lastChar: true,
|
||||
multiLine: true
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export default function CreatePalindrome({
|
||||
title,
|
||||
longDescription
|
||||
}: ToolComponentProps) {
|
||||
const [input, setInput] = useState<string>('');
|
||||
const [result, setResult] = useState<string>('');
|
||||
|
||||
const computeExternal = (
|
||||
optionsValues: typeof initialValues,
|
||||
input: string
|
||||
) => {
|
||||
const { lastChar, multiLine } = optionsValues;
|
||||
setResult(createPalindromeList(input, lastChar, multiLine));
|
||||
};
|
||||
|
||||
const getGroups: GetGroupsType<typeof initialValues> = ({
|
||||
values,
|
||||
updateField
|
||||
}) => [
|
||||
{
|
||||
title: 'Palindrome options',
|
||||
component: [
|
||||
<CheckboxWithDesc
|
||||
key="lastChar"
|
||||
checked={values.lastChar}
|
||||
title="Include last character"
|
||||
description="Repeat the last character in the reversed part"
|
||||
onChange={(val) => updateField('lastChar', val)}
|
||||
/>,
|
||||
<CheckboxWithDesc
|
||||
key="multiLine"
|
||||
checked={values.multiLine}
|
||||
title="Process multi-line text"
|
||||
description="Create palindromes for each line independently"
|
||||
onChange={(val) => updateField('multiLine', val)}
|
||||
/>
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<ToolContent
|
||||
title={title}
|
||||
initialValues={initialValues}
|
||||
getGroups={getGroups}
|
||||
compute={computeExternal}
|
||||
input={input}
|
||||
setInput={setInput}
|
||||
inputComponent={
|
||||
<ToolTextInput title={'Input text'} value={input} onChange={setInput} />
|
||||
}
|
||||
resultComponent={
|
||||
<ToolTextResult title={'Palindrome text'} value={result} />
|
||||
}
|
||||
toolInfo={{
|
||||
title: 'What Is a String Palindrome Creator?',
|
||||
description: longDescription
|
||||
}}
|
||||
exampleCards={exampleCards}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -5,9 +5,12 @@ import { lazy } from 'react';
|
||||
export const tool = defineTool('string', {
|
||||
name: 'Create palindrome',
|
||||
path: 'create-palindrome',
|
||||
icon: '',
|
||||
description: '',
|
||||
shortDescription: '',
|
||||
icon: 'material-symbols-light:repeat',
|
||||
description:
|
||||
"World's simplest browser-based utility for creating palindromes from any text. Input text and instantly transform it into a palindrome that reads the same forward and backward. Perfect for word games, creating symmetrical text patterns, or exploring linguistic curiosities.",
|
||||
shortDescription: 'Create text that reads the same forward and backward',
|
||||
longDescription:
|
||||
'This tool creates a palindrome from the given string. It does it by generating a copy of the string, reversing it, and appending it at the end of the original string. This method creates a palindrome with the last character duplicated twice. There is also another way to do it, which deletes the first letter of the reversed copy. In this case, when the string and the copy are joined together, you also get a palindrome but without the repeating last character. You can compare the two types of palindromes by switching between them in the options. You can also enable the multi-line mode that will create palindromes of every string on every line. Stringabulous!',
|
||||
keywords: ['create', 'palindrome'],
|
||||
component: lazy(() => import('./index'))
|
||||
});
|
||||
|
@@ -1,11 +1,142 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React from 'react';
|
||||
import * as Yup from 'yup';
|
||||
import React, { useState } from 'react';
|
||||
import ToolTextInput from '@components/input/ToolTextInput';
|
||||
import ToolTextResult from '@components/result/ToolTextResult';
|
||||
import { GetGroupsType } from '@components/options/ToolOptions';
|
||||
import { extractSubstring } from './service';
|
||||
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
|
||||
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
|
||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
|
||||
const initialValues = {};
|
||||
const validationSchema = Yup.object({
|
||||
// splitSeparator: Yup.string().required('The separator is required')
|
||||
});
|
||||
export default function ExtractSubstring() {
|
||||
return <Box>Lorem ipsum</Box>;
|
||||
const initialValues = {
|
||||
start: '1',
|
||||
length: '5',
|
||||
multiLine: false,
|
||||
reverse: false
|
||||
};
|
||||
|
||||
const exampleCards: CardExampleType<typeof initialValues>[] = [
|
||||
{
|
||||
title: 'Extract First 5 Characters',
|
||||
description: 'This example extracts the first 5 characters from the text.',
|
||||
sampleText: 'The quick brown fox jumps over the lazy dog.',
|
||||
sampleResult: 'The q',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
start: '1',
|
||||
length: '5'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Extract Words from the Middle',
|
||||
description:
|
||||
'Extract a substring starting from position 11 with a length of 10 characters.',
|
||||
sampleText: 'The quick brown fox jumps over the lazy dog.',
|
||||
sampleResult: 'brown fox',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
start: '11',
|
||||
length: '10'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Multi-line Extraction with Reversal',
|
||||
description: 'Extract characters 1-3 from each line and reverse them.',
|
||||
sampleText: 'First line\nSecond line\nThird line',
|
||||
sampleResult: 'riF\nceS\nihT',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
start: '1',
|
||||
length: '3',
|
||||
multiLine: true,
|
||||
reverse: true
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export default function ExtractSubstring({ title }: ToolComponentProps) {
|
||||
const [input, setInput] = useState<string>('');
|
||||
const [result, setResult] = useState<string>('');
|
||||
|
||||
const computeExternal = (
|
||||
optionsValues: typeof initialValues,
|
||||
input: string
|
||||
) => {
|
||||
const { start, length, multiLine, reverse } = optionsValues;
|
||||
try {
|
||||
setResult(
|
||||
extractSubstring(
|
||||
input,
|
||||
parseInt(start, 10),
|
||||
parseInt(length, 10),
|
||||
multiLine,
|
||||
reverse
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
setResult(`Error: ${error.message}`);
|
||||
} else {
|
||||
setResult('An unknown error occurred');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getGroups: GetGroupsType<typeof initialValues> = ({
|
||||
values,
|
||||
updateField
|
||||
}) => [
|
||||
{
|
||||
title: 'Extraction options',
|
||||
component: [
|
||||
<TextFieldWithDesc
|
||||
key="start"
|
||||
value={values.start}
|
||||
onOwnChange={(value) => updateField('start', value)}
|
||||
description="Start position (1-based index)"
|
||||
type="number"
|
||||
/>,
|
||||
<TextFieldWithDesc
|
||||
key="length"
|
||||
value={values.length}
|
||||
onOwnChange={(value) => updateField('length', value)}
|
||||
description="Number of characters to extract"
|
||||
type="number"
|
||||
/>,
|
||||
<CheckboxWithDesc
|
||||
key="multiLine"
|
||||
checked={values.multiLine}
|
||||
title="Process multi-line text"
|
||||
description="Extract from each line independently"
|
||||
onChange={(val) => updateField('multiLine', val)}
|
||||
/>,
|
||||
<CheckboxWithDesc
|
||||
key="reverse"
|
||||
checked={values.reverse}
|
||||
title="Reverse output"
|
||||
description="Reverse the extracted substring"
|
||||
onChange={(val) => updateField('reverse', val)}
|
||||
/>
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<ToolContent
|
||||
title={title}
|
||||
initialValues={initialValues}
|
||||
getGroups={getGroups}
|
||||
compute={computeExternal}
|
||||
input={input}
|
||||
setInput={setInput}
|
||||
inputComponent={
|
||||
<ToolTextInput title={'Input text'} value={input} onChange={setInput} />
|
||||
}
|
||||
resultComponent={
|
||||
<ToolTextResult title={'Extracted text'} value={result} />
|
||||
}
|
||||
exampleCards={exampleCards}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -5,9 +5,10 @@ import { lazy } from 'react';
|
||||
export const tool = defineTool('string', {
|
||||
name: 'Extract substring',
|
||||
path: 'extract-substring',
|
||||
icon: '',
|
||||
description: '',
|
||||
shortDescription: '',
|
||||
icon: 'material-symbols-light:content-cut',
|
||||
description:
|
||||
"World's simplest browser-based utility for extracting substrings from text. Easily extract specific portions of text by specifying start position and length. Perfect for parsing data, isolating specific parts of text, or data extraction tasks. Supports multi-line text processing and character-level precision.",
|
||||
shortDescription: 'Extract specific portions of text by position and length',
|
||||
keywords: ['extract', 'substring'],
|
||||
component: lazy(() => import('./index'))
|
||||
});
|
||||
|
@@ -20,11 +20,11 @@ export const stringTools = [
|
||||
stringRemoveDuplicateLines,
|
||||
stringToMorse,
|
||||
stringReplace,
|
||||
stringRepeat
|
||||
// stringReverse,
|
||||
// stringRandomizeCase,
|
||||
// stringUppercase,
|
||||
// stringExtractSubstring,
|
||||
// stringCreatePalindrome,
|
||||
// stringPalindrome
|
||||
stringRepeat,
|
||||
stringReverse,
|
||||
stringRandomizeCase,
|
||||
stringUppercase,
|
||||
stringExtractSubstring,
|
||||
stringCreatePalindrome,
|
||||
stringPalindrome
|
||||
];
|
||||
|
@@ -1,11 +1,126 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React from 'react';
|
||||
import * as Yup from 'yup';
|
||||
import React, { useState, useRef } from 'react';
|
||||
import ToolTextInput from '@components/input/ToolTextInput';
|
||||
import ToolTextResult from '@components/result/ToolTextResult';
|
||||
import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions';
|
||||
import { palindromeList, SplitOperatorType } from './service';
|
||||
import RadioWithTextField from '@components/options/RadioWithTextField';
|
||||
import ToolInputAndResult from '@components/ToolInputAndResult';
|
||||
import ToolExamples, {
|
||||
CardExampleType
|
||||
} from '@components/examples/ToolExamples';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import { FormikProps } from 'formik';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
|
||||
const initialValues = {};
|
||||
const validationSchema = Yup.object({
|
||||
// splitSeparator: Yup.string().required('The separator is required')
|
||||
});
|
||||
export default function Palindrome() {
|
||||
return <Box>Lorem ipsum</Box>;
|
||||
const initialValues = {
|
||||
splitOperatorType: 'symbol' as SplitOperatorType,
|
||||
symbolValue: ' ',
|
||||
regexValue: '\\s+'
|
||||
};
|
||||
|
||||
const splitOperators: {
|
||||
title: string;
|
||||
description: string;
|
||||
type: SplitOperatorType;
|
||||
}[] = [
|
||||
{
|
||||
title: 'Use a Symbol for Splitting',
|
||||
description:
|
||||
'Character that will be used to split text into parts for palindrome checking.',
|
||||
type: 'symbol'
|
||||
},
|
||||
{
|
||||
title: 'Use a Regex for Splitting',
|
||||
type: 'regex',
|
||||
description:
|
||||
'Regular expression that will be used to split text into parts for palindrome checking.'
|
||||
}
|
||||
];
|
||||
|
||||
const exampleCards: CardExampleType<typeof initialValues>[] = [
|
||||
{
|
||||
title: 'Check for Word Palindromes',
|
||||
description:
|
||||
'Checks if each word in the text is a palindrome. Returns "true" for palindromes and "false" for non-palindromes.',
|
||||
sampleText: 'radar level hello anna',
|
||||
sampleResult: 'true true false true',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
symbolValue: ' '
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Check CSV Words',
|
||||
description: 'Checks palindrome status for comma-separated words.',
|
||||
sampleText: 'mom,dad,wow,test',
|
||||
sampleResult: 'true true true false',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
symbolValue: ','
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Check with Regular Expression',
|
||||
description:
|
||||
'Use a regular expression to split text and check for palindromes.',
|
||||
sampleText: 'level:madam;noon|test',
|
||||
sampleResult: 'true true true false',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
splitOperatorType: 'regex',
|
||||
regexValue: '[:|;]|\\|'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export default function Palindrome({ title }: ToolComponentProps) {
|
||||
const [input, setInput] = useState<string>('');
|
||||
const [result, setResult] = useState<string>('');
|
||||
|
||||
const computeExternal = (
|
||||
optionsValues: typeof initialValues,
|
||||
input: string
|
||||
) => {
|
||||
const { splitOperatorType, symbolValue, regexValue } = optionsValues;
|
||||
const separator = splitOperatorType === 'symbol' ? symbolValue : regexValue;
|
||||
setResult(palindromeList(splitOperatorType, input, separator));
|
||||
};
|
||||
|
||||
const getGroups: GetGroupsType<typeof initialValues> = ({
|
||||
values,
|
||||
updateField
|
||||
}) => [
|
||||
{
|
||||
title: 'Splitting options',
|
||||
component: splitOperators.map(({ title, description, type }) => (
|
||||
<RadioWithTextField
|
||||
key={type}
|
||||
checked={type === values.splitOperatorType}
|
||||
title={title}
|
||||
fieldName={'splitOperatorType'}
|
||||
description={description}
|
||||
value={values[`${type}Value`]}
|
||||
onRadioClick={() => updateField('splitOperatorType', type)}
|
||||
onTextChange={(val) => updateField(`${type}Value`, val)}
|
||||
/>
|
||||
))
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<ToolContent
|
||||
title={title}
|
||||
initialValues={initialValues}
|
||||
getGroups={getGroups}
|
||||
compute={computeExternal}
|
||||
input={input}
|
||||
setInput={setInput}
|
||||
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
|
||||
resultComponent={
|
||||
<ToolTextResult title={'Palindrome results'} value={result} />
|
||||
}
|
||||
exampleCards={exampleCards}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -5,9 +5,10 @@ import { lazy } from 'react';
|
||||
export const tool = defineTool('string', {
|
||||
name: 'Palindrome',
|
||||
path: 'palindrome',
|
||||
icon: '',
|
||||
description: '',
|
||||
shortDescription: '',
|
||||
icon: 'material-symbols-light:search',
|
||||
description:
|
||||
"World's simplest browser-based utility for checking if text is a palindrome. Instantly verify if your text reads the same forward and backward. Perfect for word puzzles, linguistic analysis, or validating symmetrical text patterns. Supports various delimiters and multi-word palindrome detection.",
|
||||
shortDescription: 'Check if text reads the same forward and backward',
|
||||
keywords: ['palindrome'],
|
||||
component: lazy(() => import('./index'))
|
||||
});
|
||||
|
@@ -1,11 +1,66 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React from 'react';
|
||||
import * as Yup from 'yup';
|
||||
import React, { useState } from 'react';
|
||||
import ToolTextInput from '@components/input/ToolTextInput';
|
||||
import ToolTextResult from '@components/result/ToolTextResult';
|
||||
import { randomizeCase } from './service';
|
||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
|
||||
const initialValues = {};
|
||||
const validationSchema = Yup.object({
|
||||
// splitSeparator: Yup.string().required('The separator is required')
|
||||
});
|
||||
export default function RandomizeCase() {
|
||||
return <Box>Lorem ipsum</Box>;
|
||||
|
||||
const exampleCards: CardExampleType<typeof initialValues>[] = [
|
||||
{
|
||||
title: 'Randomize Text Case',
|
||||
description:
|
||||
'This example turns normal text into a random mix of uppercase and lowercase letters.',
|
||||
sampleText: 'The quick brown fox jumps over the lazy dog.',
|
||||
sampleResult: 'tHe qUIcK BrOWn fOx JuMPs ovEr ThE LaZy Dog.',
|
||||
sampleOptions: {}
|
||||
},
|
||||
{
|
||||
title: 'Randomize Code Case',
|
||||
description:
|
||||
'Transform code identifiers with randomized case for a chaotic look.',
|
||||
sampleText:
|
||||
'function calculateTotal(price, quantity) { return price * quantity; }',
|
||||
sampleResult:
|
||||
'FuNcTIon cAlCuLAtEtOtaL(pRicE, qUaNTiTy) { rETuRn PrICe * QuAnTiTY; }',
|
||||
sampleOptions: {}
|
||||
},
|
||||
{
|
||||
title: 'Randomize a Famous Quote',
|
||||
description:
|
||||
'Give a unique randomized case treatment to a well-known quote.',
|
||||
sampleText: 'To be or not to be, that is the question.',
|
||||
sampleResult: 'tO Be oR NoT To bE, ThAt iS ThE QueStIoN.',
|
||||
sampleOptions: {}
|
||||
}
|
||||
];
|
||||
|
||||
export default function RandomizeCase({ title }: ToolComponentProps) {
|
||||
const [input, setInput] = useState<string>('');
|
||||
const [result, setResult] = useState<string>('');
|
||||
|
||||
const computeExternal = (
|
||||
_optionsValues: typeof initialValues,
|
||||
input: string
|
||||
) => {
|
||||
setResult(randomizeCase(input));
|
||||
};
|
||||
|
||||
return (
|
||||
<ToolContent
|
||||
title={title}
|
||||
initialValues={initialValues}
|
||||
getGroups={null}
|
||||
compute={computeExternal}
|
||||
input={input}
|
||||
setInput={setInput}
|
||||
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
|
||||
resultComponent={
|
||||
<ToolTextResult title={'Randomized text'} value={result} />
|
||||
}
|
||||
exampleCards={exampleCards}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -5,9 +5,10 @@ import { lazy } from 'react';
|
||||
export const tool = defineTool('string', {
|
||||
name: 'Randomize case',
|
||||
path: 'randomize-case',
|
||||
icon: '',
|
||||
description: '',
|
||||
shortDescription: '',
|
||||
icon: 'material-symbols-light:format-textdirection-l-to-r',
|
||||
description:
|
||||
"World's simplest browser-based utility for randomizing the case of text. Just paste your text and get it instantly transformed with random uppercase and lowercase letters. Perfect for creating playful text styles, meme text, or simulating chaotic writing.",
|
||||
shortDescription: 'Convert text to random uppercase and lowercase letters',
|
||||
keywords: ['randomize', 'case'],
|
||||
component: lazy(() => import('./index'))
|
||||
});
|
||||
|
@@ -1,11 +1,119 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React from 'react';
|
||||
import * as Yup from 'yup';
|
||||
import React, { useState, useRef } from 'react';
|
||||
import ToolTextInput from '@components/input/ToolTextInput';
|
||||
import ToolTextResult from '@components/result/ToolTextResult';
|
||||
import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions';
|
||||
import { stringReverser } from './service';
|
||||
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
|
||||
import ToolInputAndResult from '@components/ToolInputAndResult';
|
||||
import ToolExamples, {
|
||||
CardExampleType
|
||||
} from '@components/examples/ToolExamples';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import { FormikProps } from 'formik';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
|
||||
const initialValues = {};
|
||||
const validationSchema = Yup.object({
|
||||
// splitSeparator: Yup.string().required('The separator is required')
|
||||
});
|
||||
export default function Reverse() {
|
||||
return <Box>Lorem ipsum</Box>;
|
||||
const initialValues = {
|
||||
multiLine: true,
|
||||
emptyItems: false,
|
||||
trim: false
|
||||
};
|
||||
|
||||
const exampleCards: CardExampleType<typeof initialValues>[] = [
|
||||
{
|
||||
title: 'Simple Text Reversal',
|
||||
description:
|
||||
'Reverses each character in the text. Perfect for creating mirror text.',
|
||||
sampleText: 'Hello World',
|
||||
sampleResult: 'dlroW olleH',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
multiLine: false
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Multi-line Reversal',
|
||||
description:
|
||||
'Reverses each line independently while preserving the line breaks.',
|
||||
sampleText: 'First line\nSecond line\nThird line',
|
||||
sampleResult: 'enil tsriF\nenil dnoceS\nenil drihT',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
multiLine: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Clean Reversed Text',
|
||||
description:
|
||||
'Trims whitespace and skips empty lines before reversing the text.',
|
||||
sampleText: ' Spaces removed \n\nEmpty line skipped',
|
||||
sampleResult: 'devomer secapS\ndeppiks enil ytpmE',
|
||||
sampleOptions: {
|
||||
...initialValues,
|
||||
multiLine: true,
|
||||
emptyItems: true,
|
||||
trim: true
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export default function Reverse({ title }: ToolComponentProps) {
|
||||
const [input, setInput] = useState<string>('');
|
||||
const [result, setResult] = useState<string>('');
|
||||
|
||||
const computeExternal = (
|
||||
optionsValues: typeof initialValues,
|
||||
input: string
|
||||
) => {
|
||||
const { multiLine, emptyItems, trim } = optionsValues;
|
||||
setResult(stringReverser(input, multiLine, emptyItems, trim));
|
||||
};
|
||||
|
||||
const getGroups: GetGroupsType<typeof initialValues> = ({
|
||||
values,
|
||||
updateField
|
||||
}) => [
|
||||
{
|
||||
title: 'Reversal options',
|
||||
component: [
|
||||
<CheckboxWithDesc
|
||||
key="multiLine"
|
||||
checked={values.multiLine}
|
||||
title="Process multi-line text"
|
||||
description="Each line will be reversed independently"
|
||||
onChange={(val) => updateField('multiLine', val)}
|
||||
/>,
|
||||
<CheckboxWithDesc
|
||||
key="emptyItems"
|
||||
checked={values.emptyItems}
|
||||
title="Skip empty lines"
|
||||
description="Empty lines will be removed from the output"
|
||||
onChange={(val) => updateField('emptyItems', val)}
|
||||
/>,
|
||||
<CheckboxWithDesc
|
||||
key="trim"
|
||||
checked={values.trim}
|
||||
title="Trim whitespace"
|
||||
description="Remove leading and trailing whitespace from each line"
|
||||
onChange={(val) => updateField('trim', val)}
|
||||
/>
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<ToolContent
|
||||
title={title}
|
||||
initialValues={initialValues}
|
||||
getGroups={getGroups}
|
||||
compute={computeExternal}
|
||||
input={input}
|
||||
setInput={setInput}
|
||||
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
|
||||
resultComponent={
|
||||
<ToolTextResult title={'Reversed text'} value={result} />
|
||||
}
|
||||
exampleCards={exampleCards}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import { lazy } from 'react';
|
||||
export const tool = defineTool('string', {
|
||||
name: 'Reverse',
|
||||
path: 'reverse',
|
||||
icon: '',
|
||||
icon: 'material-symbols-light:swap-horiz',
|
||||
description:
|
||||
"World's simplest browser-based utility for reversing text. Input any text and get it instantly reversed, character by character. Perfect for creating mirror text, analyzing palindromes, or playing with text patterns. Preserves spaces and special characters while reversing.",
|
||||
shortDescription: 'Reverse any text character by character',
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
import image from '@assets/text.png';
|
||||
|
||||
export const tool = defineTool('string', {
|
||||
path: 'split',
|
||||
@@ -9,6 +8,7 @@ export const tool = defineTool('string', {
|
||||
description:
|
||||
"World's simplest browser-based utility for splitting text. Load your text in the input form on the left and you'll automatically get pieces of this text on the right. Powerful, free, and fast. Load text – get chunks.",
|
||||
shortDescription: 'Quickly split a text',
|
||||
longDescription: 'Quickly split a text',
|
||||
keywords: ['text', 'split'],
|
||||
component: lazy(() => import('./index'))
|
||||
});
|
||||
|
@@ -1,11 +1,63 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React from 'react';
|
||||
import * as Yup from 'yup';
|
||||
import React, { useState } from 'react';
|
||||
import ToolTextInput from '@components/input/ToolTextInput';
|
||||
import ToolTextResult from '@components/result/ToolTextResult';
|
||||
import { UppercaseInput } from './service';
|
||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
|
||||
const initialValues = {};
|
||||
const validationSchema = Yup.object({
|
||||
// splitSeparator: Yup.string().required('The separator is required')
|
||||
});
|
||||
export default function Uppercase() {
|
||||
return <Box>Lorem ipsum</Box>;
|
||||
|
||||
const exampleCards: CardExampleType<typeof initialValues>[] = [
|
||||
{
|
||||
title: 'Convert Text to Uppercase',
|
||||
description: 'This example transforms any text to ALL UPPERCASE format.',
|
||||
sampleText: 'The quick brown fox jumps over the lazy dog.',
|
||||
sampleResult: 'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.',
|
||||
sampleOptions: {}
|
||||
},
|
||||
{
|
||||
title: 'Uppercase Code',
|
||||
description:
|
||||
'Convert code to uppercase format. Note that this is for display only and would not maintain code functionality.',
|
||||
sampleText: 'function example() { return "hello world"; }',
|
||||
sampleResult: 'FUNCTION EXAMPLE() { RETURN "HELLO WORLD"; }',
|
||||
sampleOptions: {}
|
||||
},
|
||||
{
|
||||
title: 'Mixed Case to Uppercase',
|
||||
description:
|
||||
'Transform text with mixed casing to consistent all uppercase format.',
|
||||
sampleText: 'ThIs Is MiXeD CaSe TeXt!',
|
||||
sampleResult: 'THIS IS MIXED CASE TEXT!',
|
||||
sampleOptions: {}
|
||||
}
|
||||
];
|
||||
|
||||
export default function Uppercase({ title }: ToolComponentProps) {
|
||||
const [input, setInput] = useState<string>('');
|
||||
const [result, setResult] = useState<string>('');
|
||||
|
||||
const computeExternal = (
|
||||
_optionsValues: typeof initialValues,
|
||||
input: string
|
||||
) => {
|
||||
setResult(UppercaseInput(input));
|
||||
};
|
||||
|
||||
return (
|
||||
<ToolContent
|
||||
title={title}
|
||||
initialValues={initialValues}
|
||||
getGroups={null}
|
||||
compute={computeExternal}
|
||||
input={input}
|
||||
setInput={setInput}
|
||||
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
|
||||
resultComponent={
|
||||
<ToolTextResult title={'Uppercase text'} value={result} />
|
||||
}
|
||||
exampleCards={exampleCards}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -4,8 +4,9 @@ import { lazy } from 'react';
|
||||
export const tool = defineTool('string', {
|
||||
name: 'Uppercase',
|
||||
path: 'uppercase',
|
||||
icon: '',
|
||||
description: "World's simplest browser-based utility for converting text to uppercase. Just input your text and it will be automatically converted to all capital letters. Perfect for creating headlines, emphasizing text, or standardizing text format. Supports various text formats and preserves special characters.",
|
||||
icon: 'material-symbols-light:text-fields',
|
||||
description:
|
||||
"World's simplest browser-based utility for converting text to uppercase. Just input your text and it will be automatically converted to all capital letters. Perfect for creating headlines, emphasizing text, or standardizing text format. Supports various text formats and preserves special characters.",
|
||||
shortDescription: 'Convert text to uppercase letters',
|
||||
keywords: ['uppercase'],
|
||||
component: lazy(() => import('./index'))
|
||||
|
@@ -10,6 +10,7 @@ interface ToolOptions {
|
||||
name: string;
|
||||
description: string;
|
||||
shortDescription: string;
|
||||
longDescription?: string;
|
||||
}
|
||||
|
||||
export type ToolCategory =
|
||||
@@ -33,7 +34,8 @@ export interface DefinedTool {
|
||||
}
|
||||
|
||||
export interface ToolComponentProps {
|
||||
title?: any;
|
||||
title: string;
|
||||
longDescription?: string;
|
||||
}
|
||||
|
||||
export const defineTool = (
|
||||
@@ -47,7 +49,8 @@ export const defineTool = (
|
||||
description,
|
||||
keywords,
|
||||
component,
|
||||
shortDescription
|
||||
shortDescription,
|
||||
longDescription
|
||||
} = options;
|
||||
const Component = component;
|
||||
return {
|
||||
@@ -66,7 +69,7 @@ export const defineTool = (
|
||||
icon={icon}
|
||||
type={basePath}
|
||||
>
|
||||
<Component title={name} />
|
||||
<Component title={name} longDescription={longDescription} />
|
||||
</ToolLayout>
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user