feat: missing tools

This commit is contained in:
Ibrahima G. Coulibaly
2025-03-09 17:45:13 +00:00
parent 2859b1ddc2
commit 04832bd104
11 changed files with 1210 additions and 133 deletions

View File

@@ -1,12 +1,215 @@
import React, { useState } from 'react';
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { duplicateList, SplitOperatorType } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { GetGroupsType } from '@components/options/ToolOptions';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import * as Yup from 'yup';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Duplicate() {
return <Box>Lorem ipsum</Box>;
interface InitialValuesType {
splitOperatorType: SplitOperatorType;
splitSeparator: string;
joinSeparator: string;
concatenate: boolean;
reverse: boolean;
copy: string;
}
const initialValues: InitialValuesType = {
splitOperatorType: 'symbol',
splitSeparator: ' ',
joinSeparator: ' ',
concatenate: true,
reverse: false,
copy: '2'
};
const validationSchema = Yup.object({
splitSeparator: Yup.string().required('The separator is required'),
joinSeparator: Yup.string().required('The join separator is required'),
copy: Yup.number()
.typeError('Number of copies must be a number')
.min(0.1, 'Number of copies must be positive')
.required('Number of copies is required')
});
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Simple duplication',
description: 'This example shows how to duplicate a list of words.',
sampleText: 'Hello World',
sampleResult: 'Hello World Hello World',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ' ',
joinSeparator: ' ',
concatenate: true,
reverse: false,
copy: '2'
}
},
{
title: 'Reverse duplication',
description: 'This example shows how to duplicate a list in reverse order.',
sampleText: 'Hello World',
sampleResult: 'Hello World World Hello',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ' ',
joinSeparator: ' ',
concatenate: true,
reverse: true,
copy: '2'
}
},
{
title: 'Interweaving items',
description:
'This example shows how to interweave items instead of concatenating them.',
sampleText: 'Hello World',
sampleResult: 'Hello Hello World World',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ' ',
joinSeparator: ' ',
concatenate: false,
reverse: false,
copy: '2'
}
},
{
title: 'Fractional duplication',
description:
'This example shows how to duplicate a list with a fractional number of copies.',
sampleText: 'apple banana cherry',
sampleResult: 'apple banana cherry apple banana',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ' ',
joinSeparator: ' ',
concatenate: true,
reverse: false,
copy: '1.7'
}
}
];
export default function Duplicate({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: InitialValuesType, input: string) => {
if (input) {
try {
const copy = parseFloat(optionsValues.copy);
setResult(
duplicateList(
optionsValues.splitOperatorType,
optionsValues.splitSeparator,
optionsValues.joinSeparator,
input,
optionsValues.concatenate,
optionsValues.reverse,
copy
)
);
} catch (error) {
if (error instanceof Error) {
setResult(`Error: ${error.message}`);
} else {
setResult('An unknown error occurred');
}
}
}
};
const getGroups: GetGroupsType<InitialValuesType> = ({
values,
updateField
}) => [
{
title: 'Split Options',
component: (
<Box>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'symbol')}
checked={values.splitOperatorType === 'symbol'}
title={'Split by Symbol'}
/>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'regex')}
checked={values.splitOperatorType === 'regex'}
title={'Split by Regular Expression'}
/>
<TextFieldWithDesc
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
description={'Separator to split the list'}
/>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
description={'Separator to join the duplicated list'}
/>
</Box>
)
},
{
title: 'Duplication Options',
component: (
<Box>
<TextFieldWithDesc
value={values.copy}
onOwnChange={(val) => updateField('copy', val)}
description={'Number of copies (can be fractional)'}
type="number"
/>
<CheckboxWithDesc
title={'Concatenate'}
checked={values.concatenate}
onChange={(checked) => updateField('concatenate', checked)}
description={
'Concatenate copies (if unchecked, items will be interweaved)'
}
/>
<CheckboxWithDesc
title={'Reverse'}
checked={values.reverse}
onChange={(checked) => updateField('reverse', checked)}
description={'Reverse the duplicated items'}
/>
</Box>
)
}
];
return (
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input List" value={input} onChange={setInput} />
}
resultComponent={
<ToolTextResult title="Duplicated List" value={result} />
}
initialValues={initialValues}
getGroups={getGroups}
validationSchema={validationSchema}
toolInfo={{
title: 'List Duplication',
description:
"This tool allows you to duplicate items in a list. You can specify the number of copies (including fractional values), control whether items are concatenated or interweaved, and even reverse the duplicated items. It's useful for creating repeated patterns, generating test data, or expanding lists with predictable content."
}}
exampleCards={exampleCards}
input={input}
setInput={setInput}
compute={compute}
/>
);
}

View File

@@ -12,14 +12,14 @@ import { tool as listSort } from './sort/meta';
export const listTools = [
listSort,
// listUnwrap,
listUnwrap,
listReverse,
listFindUnique,
listFindMostPopular,
listGroup,
// listWrap,
listWrap,
listRotate,
listShuffle
// listTruncate,
// listDuplicate
listShuffle,
listTruncate,
listDuplicate
];

View File

@@ -1,11 +1,189 @@
import React, { useState } from 'react';
import { Box } from '@mui/material';
import React from 'react';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { SplitOperatorType, truncateList } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { GetGroupsType } from '@components/options/ToolOptions';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SimpleRadio from '@components/options/SimpleRadio';
import * as Yup from 'yup';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Truncate() {
return <Box>Lorem ipsum</Box>;
interface InitialValuesType {
splitOperatorType: SplitOperatorType;
splitSeparator: string;
joinSeparator: string;
end: boolean;
length: string;
}
const initialValues: InitialValuesType = {
splitOperatorType: 'symbol',
splitSeparator: ',',
joinSeparator: ',',
end: true,
length: '3'
};
const validationSchema = Yup.object({
splitSeparator: Yup.string().required('The separator is required'),
joinSeparator: Yup.string().required('The join separator is required'),
length: Yup.number()
.typeError('Length must be a number')
.min(0, 'Length must be a positive number')
.required('Length is required')
});
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Keep first 3 items in a list',
description:
'This example shows how to keep only the first 3 items in a comma-separated list.',
sampleText: 'apple, pineapple, lemon, orange, mango',
sampleResult: 'apple,pineapple,lemon',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ', ',
joinSeparator: ',',
end: true,
length: '3'
}
},
{
title: 'Keep last 2 items in a list',
description:
'This example shows how to keep only the last 2 items in a comma-separated list.',
sampleText: 'apple, pineapple, lemon, orange, mango',
sampleResult: 'orange,mango',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ', ',
joinSeparator: ',',
end: false,
length: '2'
}
},
{
title: 'Truncate a list with custom separators',
description:
'This example shows how to truncate a list with custom separators.',
sampleText: 'apple | pineapple | lemon | orange | mango',
sampleResult: 'apple - pineapple - lemon',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ' | ',
joinSeparator: ' - ',
end: true,
length: '3'
}
}
];
export default function Truncate({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: InitialValuesType, input: string) => {
if (input) {
try {
const length = parseInt(optionsValues.length, 10);
setResult(
truncateList(
optionsValues.splitOperatorType,
input,
optionsValues.splitSeparator,
optionsValues.joinSeparator,
optionsValues.end,
length
)
);
} catch (error) {
if (error instanceof Error) {
setResult(`Error: ${error.message}`);
} else {
setResult('An unknown error occurred');
}
}
}
};
const getGroups: GetGroupsType<InitialValuesType> = ({
values,
updateField
}) => [
{
title: 'Split Options',
component: (
<Box>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'symbol')}
checked={values.splitOperatorType === 'symbol'}
title={'Split by Symbol'}
/>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'regex')}
checked={values.splitOperatorType === 'regex'}
title={'Split by Regular Expression'}
/>
<TextFieldWithDesc
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
description={'Separator to split the list'}
/>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
description={'Separator to join the truncated list'}
/>
</Box>
)
},
{
title: 'Truncation Options',
component: (
<Box>
<TextFieldWithDesc
value={values.length}
onOwnChange={(val) => updateField('length', val)}
description={'Number of items to keep'}
type="number"
/>
<SimpleRadio
onClick={() => updateField('end', true)}
checked={values.end}
title={'Keep items from the beginning'}
/>
<SimpleRadio
onClick={() => updateField('end', false)}
checked={!values.end}
title={'Keep items from the end'}
/>
</Box>
)
}
];
return (
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input List" value={input} onChange={setInput} />
}
resultComponent={<ToolTextResult title="Truncated List" value={result} />}
initialValues={initialValues}
getGroups={getGroups}
validationSchema={validationSchema}
toolInfo={{
title: 'List Truncation',
description:
"This tool allows you to truncate a list to a specific number of items. You can choose to keep items from the beginning or the end of the list, and specify custom separators for splitting and joining. It's useful for limiting the size of lists, creating previews, or extracting specific portions of data."
}}
exampleCards={exampleCards}
input={input}
setInput={setInput}
compute={compute}
/>
);
}

View File

@@ -1,11 +1,212 @@
import React, { useState } from 'react';
import { Box } from '@mui/material';
import React from 'react';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { SplitOperatorType, unwrapList } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { GetGroupsType } from '@components/options/ToolOptions';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import * as Yup from 'yup';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Unwrap() {
return <Box>Lorem ipsum</Box>;
interface InitialValuesType {
splitOperatorType: SplitOperatorType;
splitSeparator: string;
joinSeparator: string;
deleteEmptyItems: boolean;
multiLevel: boolean;
trimItems: boolean;
left: string;
right: string;
}
const initialValues: InitialValuesType = {
splitOperatorType: 'symbol',
splitSeparator: '\n',
joinSeparator: '\n',
deleteEmptyItems: true,
multiLevel: true,
trimItems: true,
left: '',
right: ''
};
const validationSchema = Yup.object({
splitSeparator: Yup.string().required('The separator is required'),
joinSeparator: Yup.string().required('The join separator is required')
});
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Unwrap quotes from list items',
description:
'This example shows how to remove quotes from each item in a list.',
sampleText: '"apple"\n"banana"\n"orange"',
sampleResult: 'apple\nbanana\norange',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: '\n',
joinSeparator: '\n',
deleteEmptyItems: true,
multiLevel: true,
trimItems: true,
left: '"',
right: '"'
}
},
{
title: 'Unwrap multiple levels of characters',
description:
'This example shows how to remove multiple levels of the same character from each item.',
sampleText: '###Hello###\n##World##\n#Test#',
sampleResult: 'Hello\nWorld\nTest',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: '\n',
joinSeparator: '\n',
deleteEmptyItems: true,
multiLevel: true,
trimItems: true,
left: '#',
right: '#'
}
},
{
title: 'Unwrap and join with custom separator',
description:
'This example shows how to unwrap items and join them with a custom separator.',
sampleText: '[item1]\n[item2]\n[item3]',
sampleResult: 'item1, item2, item3',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: '\n',
joinSeparator: ', ',
deleteEmptyItems: true,
multiLevel: false,
trimItems: true,
left: '[',
right: ']'
}
}
];
export default function Unwrap({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: InitialValuesType, input: string) => {
if (input) {
try {
setResult(
unwrapList(
optionsValues.splitOperatorType,
input,
optionsValues.splitSeparator,
optionsValues.joinSeparator,
optionsValues.deleteEmptyItems,
optionsValues.multiLevel,
optionsValues.trimItems,
optionsValues.left,
optionsValues.right
)
);
} catch (error) {
if (error instanceof Error) {
setResult(`Error: ${error.message}`);
} else {
setResult('An unknown error occurred');
}
}
}
};
const getGroups: GetGroupsType<InitialValuesType> = ({
values,
updateField
}) => [
{
title: 'Split Options',
component: (
<Box>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'symbol')}
checked={values.splitOperatorType === 'symbol'}
title={'Split by Symbol'}
/>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'regex')}
checked={values.splitOperatorType === 'regex'}
title={'Split by Regular Expression'}
/>
<TextFieldWithDesc
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
description={'Separator to split the list'}
/>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
description={'Separator to join the unwrapped list'}
/>
</Box>
)
},
{
title: 'Unwrap Options',
component: (
<Box>
<TextFieldWithDesc
value={values.left}
onOwnChange={(val) => updateField('left', val)}
description={'Characters to remove from the left side'}
/>
<TextFieldWithDesc
value={values.right}
onOwnChange={(val) => updateField('right', val)}
description={'Characters to remove from the right side'}
/>
<CheckboxWithDesc
checked={values.multiLevel}
onChange={(checked) => updateField('multiLevel', checked)}
title={'Remove multiple levels of wrapping'}
/>
<CheckboxWithDesc
checked={values.trimItems}
onChange={(checked) => updateField('trimItems', checked)}
title={'Trim whitespace from items'}
/>
<CheckboxWithDesc
checked={values.deleteEmptyItems}
onChange={(checked) => updateField('deleteEmptyItems', checked)}
title={'Remove empty items'}
/>
</Box>
)
}
];
return (
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input List" value={input} onChange={setInput} />
}
resultComponent={<ToolTextResult title="Unwrapped List" value={result} />}
initialValues={initialValues}
getGroups={getGroups}
validationSchema={validationSchema}
toolInfo={{
title: 'List Unwrapping',
description:
"This tool allows you to remove wrapping characters from each item in a list. You can specify characters to remove from the left and right sides, handle multiple levels of wrapping, and control how the list is processed. It's useful for cleaning up data, removing quotes or brackets, and formatting lists."
}}
exampleCards={exampleCards}
input={input}
setInput={setInput}
compute={compute}
/>
);
}

View File

@@ -1,11 +1,191 @@
import React, { useState } from 'react';
import { Box } from '@mui/material';
import React from 'react';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { SplitOperatorType, wrapList } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { GetGroupsType } from '@components/options/ToolOptions';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import * as Yup from 'yup';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Wrap() {
return <Box>Lorem ipsum</Box>;
interface InitialValuesType {
splitOperatorType: SplitOperatorType;
splitSeparator: string;
joinSeparator: string;
deleteEmptyItems: boolean;
left: string;
right: string;
}
const initialValues: InitialValuesType = {
splitOperatorType: 'symbol',
splitSeparator: ',',
joinSeparator: ',',
deleteEmptyItems: true,
left: '"',
right: '"'
};
const validationSchema = Yup.object({
splitSeparator: Yup.string().required('The separator is required'),
joinSeparator: Yup.string().required('The join separator is required')
});
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Wrap list items with quotes',
description:
'This example shows how to wrap each item in a list with quotes.',
sampleText: 'apple,banana,orange',
sampleResult: '"apple","banana","orange"',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ',',
joinSeparator: ',',
deleteEmptyItems: true,
left: '"',
right: '"'
}
},
{
title: 'Wrap list items with brackets',
description:
'This example shows how to wrap each item in a list with brackets.',
sampleText: 'item1,item2,item3',
sampleResult: '[item1],[item2],[item3]',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ',',
joinSeparator: ',',
deleteEmptyItems: true,
left: '[',
right: ']'
}
},
{
title: 'Wrap list items with custom text',
description:
'This example shows how to wrap each item with different text on each side.',
sampleText: 'apple,banana,orange',
sampleResult:
'prefix-apple-suffix,prefix-banana-suffix,prefix-orange-suffix',
sampleOptions: {
splitOperatorType: 'symbol',
splitSeparator: ',',
joinSeparator: ',',
deleteEmptyItems: true,
left: 'prefix-',
right: '-suffix'
}
}
];
export default function Wrap({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: InitialValuesType, input: string) => {
if (input) {
try {
setResult(
wrapList(
optionsValues.splitOperatorType,
input,
optionsValues.splitSeparator,
optionsValues.joinSeparator,
optionsValues.deleteEmptyItems,
optionsValues.left,
optionsValues.right
)
);
} catch (error) {
if (error instanceof Error) {
setResult(`Error: ${error.message}`);
} else {
setResult('An unknown error occurred');
}
}
}
};
const getGroups: GetGroupsType<InitialValuesType> = ({
values,
updateField
}) => [
{
title: 'Split Options',
component: (
<Box>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'symbol')}
checked={values.splitOperatorType === 'symbol'}
title={'Split by Symbol'}
/>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'regex')}
checked={values.splitOperatorType === 'regex'}
title={'Split by Regular Expression'}
/>
<TextFieldWithDesc
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
description={'Separator to split the list'}
/>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
description={'Separator to join the wrapped list'}
/>
<CheckboxWithDesc
checked={values.deleteEmptyItems}
onChange={(checked) => updateField('deleteEmptyItems', checked)}
title={'Remove empty items'}
/>
</Box>
)
},
{
title: 'Wrap Options',
component: (
<Box>
<TextFieldWithDesc
value={values.left}
onOwnChange={(val) => updateField('left', val)}
description={'Text to add before each item'}
/>
<TextFieldWithDesc
value={values.right}
onOwnChange={(val) => updateField('right', val)}
description={'Text to add after each item'}
/>
</Box>
)
}
];
return (
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input List" value={input} onChange={setInput} />
}
resultComponent={<ToolTextResult title="Wrapped List" value={result} />}
initialValues={initialValues}
getGroups={getGroups}
validationSchema={validationSchema}
toolInfo={{
title: 'List Wrapping',
description:
"This tool allows you to add text before and after each item in a list. You can specify different text for the left and right sides, and control how the list is processed. It's useful for adding quotes, brackets, or other formatting to list items, preparing data for different formats, or creating structured text."
}}
exampleCards={exampleCards}
input={input}
setInput={setInput}
compute={compute}
/>
);
}